Expose voice detune parameter of the lv2 plugin
[zyn.git] / zynadd.c
blobbe2b6408e349b607216fb0f24604f2e7be7b440d
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * Copyright (C) 2006,2007,2008,2009 Nedko Arnaudov <nedko@arnaudov.name>
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; version 2 of the License
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
19 *****************************************************************************/
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24 #include <assert.h>
25 #include <math.h>
26 #include <stdbool.h>
27 #include <lv2.h>
29 #include "common.h"
30 #include "lv2-miditype.h"
31 #include "lv2-midifunctions.h"
32 #include "zynadd.h"
33 #include "addsynth.h"
34 #include "lv2dynparam/lv2dynparam.h"
35 #include "lv2dynparam/lv2_rtmempool.h"
36 #include "lv2dynparam/plugin.h"
37 #include "list.h"
38 #include "zynadd_internal.h"
39 //#define LOG_LEVEL LOG_LEVEL_DEBUG
40 #include "log.h"
42 #define LV2_PORT_MIDI_IN 0
43 #define LV2_PORT_OUTPUT_LEFT 1
44 #define LV2_PORT_OUTPUT_RIGHT 2
45 #define LV2_PORTS_COUNT 3
47 LV2_Handle
48 zynadd_instantiate(
49 const LV2_Descriptor * descriptor,
50 double sample_rate,
51 const char * bundle_path,
52 const LV2_Feature * const * host_features)
54 struct zynadd * zynadd_ptr;
55 struct lv2_rtsafe_memory_pool_provider * rtmempool_ptr;
56 const LV2_Feature * const * feature_ptr_ptr;
58 LOG_DEBUG("zynadd_create_plugin_instance() called.");
59 LOG_DEBUG("sample_rate = %f", sample_rate);
60 LOG_DEBUG("bundle_path = \"%s\"", bundle_path);
62 rtmempool_ptr = NULL;
64 feature_ptr_ptr = host_features;
65 while (*feature_ptr_ptr)
67 LOG_DEBUG("Host feature <%s> detected", (*feature_ptr_ptr)->URI);
69 if (strcmp((*feature_ptr_ptr)->URI, LV2_RTSAFE_MEMORY_POOL_URI) == 0)
71 rtmempool_ptr = (*feature_ptr_ptr)->data;
74 feature_ptr_ptr++;
77 if (rtmempool_ptr == NULL)
79 LOG_ERROR(LV2_RTSAFE_MEMORY_POOL_URI " extension is required");
80 goto fail;
83 zynadd_ptr = malloc(sizeof(struct zynadd));
84 if (zynadd_ptr == NULL)
86 goto fail;
89 zynadd_ptr->host_features = host_features;
91 zynadd_ptr->bundle_path = strdup(bundle_path);
92 if (zynadd_ptr->bundle_path == NULL)
94 goto fail_free_instance;
97 zynadd_ptr->ports = malloc(LV2_PORTS_COUNT * sizeof(void *));
98 if (zynadd_ptr->ports == NULL)
100 goto fail_free_bundle_path;
103 zynadd_ptr->sample_rate = sample_rate;
105 if (!zyn_addsynth_create(sample_rate, VOICES_COUNT, &zynadd_ptr->synth))
107 goto fail_free_ports;
110 zynadd_ptr->synth_output_offset = SOUND_BUFFER_SIZE;
112 if (!zynadd_dynparam_init(zynadd_ptr))
114 LOG_ERROR("zynadd_dynparam_init() failed.");
115 goto fail_destroy_synth;
118 return (LV2_Handle)zynadd_ptr;
120 fail_destroy_synth:
121 zyn_addsynth_destroy(zynadd_ptr->synth);
123 fail_free_ports:
124 free(zynadd_ptr->ports);
126 fail_free_bundle_path:
127 free(zynadd_ptr->bundle_path);
129 fail_free_instance:
130 free(zynadd_ptr);
132 fail:
133 /* printf("zynadd_instantiate() failed.\n"); */
134 return NULL;
137 #define zynadd_ptr ((struct zynadd *)instance)
139 /* The run() callback. This is the function that gets called by the host
140 when it wants to run the plugin. The parameter is the number of sample
141 frames to process. */
142 void
143 zynadd_run(
144 LV2_Handle instance,
145 uint32_t samples_count)
147 LV2_MIDIState midi;
148 double event_time;
149 uint32_t event_size;
150 unsigned char* event;
151 uint32_t now;
152 uint32_t fill;
153 uint32_t synth_output_offset_future;
154 /* char fake_event[2]; */
156 /* printf("%u\n", sample_count); fflush(stdout); */
158 midi.midi = (LV2_MIDI *)zynadd_ptr->ports[LV2_PORT_MIDI_IN];
159 midi.frame_count = samples_count;
160 midi.position = 0;
162 now = 0;
163 event_time = -1.0;
164 event = NULL;
165 event_size = 0;
167 while (now < samples_count)
169 fill = samples_count - now;
170 synth_output_offset_future = zynadd_ptr->synth_output_offset;
172 if (synth_output_offset_future == SOUND_BUFFER_SIZE)
174 synth_output_offset_future = 0;
177 if (fill > SOUND_BUFFER_SIZE - synth_output_offset_future)
179 fill = SOUND_BUFFER_SIZE - synth_output_offset_future;
182 while (event_time < now + fill)
184 if (event_time < 0) /* we need to extract next event */
186 lv2midi_get_event(&midi, &event_time, &event_size, &event);
187 /* if (event[0] == 0x90) */
188 /* { */
189 /* event_time = 0; */
190 /* fake_event[0] = 0x90; */
191 /* fake_event[1] = 69; */
192 /* } */
193 lv2midi_step(&midi);
196 if (event_time >= 0 && event_time < now + fill)
198 /* printf("%02X\n", (unsigned int)event[0]); */
199 if (event_size == 3)
201 switch (event[0] & 0xF0)
203 case 0x90: /* note on */
204 zyn_addsynth_note_on(zynadd_ptr->synth, event[1], event[2]);
205 break;
206 case 0x80: /* note off */
207 zyn_addsynth_note_off(zynadd_ptr->synth, event[1]);
208 break;
209 case 0xB0:
210 switch (event[1])
212 case 0x78: /* all sound off */
213 zyn_addsynth_all_sound_off(zynadd_ptr->synth);
214 break;
215 case 0x7B: /* all notes off */
216 zyn_addsynth_all_notes_off(zynadd_ptr->synth);
217 break;
219 break;
223 event_time = -1.0;
227 if (zynadd_ptr->synth_output_offset == SOUND_BUFFER_SIZE)
229 zyn_addsynth_get_audio_output(zynadd_ptr->synth, zynadd_ptr->synth_output_left, zynadd_ptr->synth_output_right);
230 zynadd_ptr->synth_output_offset = 0;
233 assert(zynadd_ptr->synth_output_offset == synth_output_offset_future);
235 memcpy((float *)(zynadd_ptr->ports[LV2_PORT_OUTPUT_LEFT]) + now, zynadd_ptr->synth_output_left, fill * sizeof(float));
236 memcpy((float *)(zynadd_ptr->ports[LV2_PORT_OUTPUT_RIGHT]) + now, zynadd_ptr->synth_output_right, fill * sizeof(float));
238 zynadd_ptr->synth_output_offset += fill;
239 assert(zynadd_ptr->synth_output_offset <= SOUND_BUFFER_SIZE);
240 now += fill;
241 assert(now <= samples_count);
245 void
246 zynadd_cleanup(
247 LV2_Handle instance)
249 /* printf("zynadd_cleanup\n"); */
250 zynadd_dynparam_uninit(zynadd_ptr);
251 zyn_addsynth_destroy(zynadd_ptr->synth);
252 free(zynadd_ptr->ports);
253 free(zynadd_ptr->bundle_path);
254 free(zynadd_ptr);
257 void
258 zynadd_connect_port(
259 LV2_Handle instance,
260 uint32_t port,
261 void * data_location)
263 if (port >= LV2_PORTS_COUNT)
265 assert(0);
266 return;
269 zynadd_ptr->ports[port] = data_location;
272 const void *
273 zynadd_extension_data(
274 const char * URI)
276 if (strcmp(URI, LV2DYNPARAM_URI) == 0)
278 return get_lv2dynparam_plugin_extension_data();
281 return NULL;