recognize "All Sound Off" and "All Notes Off" MIDI events
[zyn.git] / zynadd.c
blob8d11319ffd8cd3955e3f9ceb5e278b2ad6da252f
1 /* -*- Mode: C ; c-basic-offset: 2 -*- */
2 /*****************************************************************************
4 * Copyright (C) 2006,2007 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"
43 * The number of voices of additive synth for a single note
45 #define NUM_VOICES 8
47 #define LV2_PORT_MIDI_IN 0
48 #define LV2_PORT_OUTPUT_LEFT 1
49 #define LV2_PORT_OUTPUT_RIGHT 2
50 #define LV2_PORTS_COUNT 3
52 LV2_Handle
53 zynadd_instantiate(
54 const LV2_Descriptor * descriptor,
55 double sample_rate,
56 const char * bundle_path,
57 const LV2_Feature * const * host_features)
59 struct zynadd * zynadd_ptr;
60 struct lv2_rtsafe_memory_pool_provider * rtmempool_ptr;
61 const LV2_Feature * const * feature_ptr_ptr;
63 LOG_DEBUG("zynadd_create_plugin_instance() called.");
64 LOG_DEBUG("sample_rate = %f", sample_rate);
65 LOG_DEBUG("bundle_path = \"%s\"", bundle_path);
67 rtmempool_ptr = NULL;
69 feature_ptr_ptr = host_features;
70 while (*feature_ptr_ptr)
72 LOG_DEBUG("Host feature <%s> detected", (*feature_ptr_ptr)->URI);
74 if (strcmp((*feature_ptr_ptr)->URI, LV2_RTSAFE_MEMORY_POOL_URI) == 0)
76 rtmempool_ptr = (*feature_ptr_ptr)->data;
79 feature_ptr_ptr++;
82 if (rtmempool_ptr == NULL)
84 LOG_ERROR(LV2_RTSAFE_MEMORY_POOL_URI " extension is required");
85 goto fail;
88 zynadd_ptr = malloc(sizeof(struct zynadd));
89 if (zynadd_ptr == NULL)
91 goto fail;
94 zynadd_ptr->host_features = host_features;
96 zynadd_ptr->bundle_path = strdup(bundle_path);
97 if (zynadd_ptr->bundle_path == NULL)
99 goto fail_free_instance;
102 zynadd_ptr->ports = malloc(LV2_PORTS_COUNT * sizeof(void *));
103 if (zynadd_ptr->ports == NULL)
105 goto fail_free_bundle_path;
108 zynadd_ptr->sample_rate = sample_rate;
110 if (!zyn_addsynth_create(sample_rate, NUM_VOICES, &zynadd_ptr->synth))
112 goto fail_free_ports;
115 zynadd_ptr->synth_output_offset = SOUND_BUFFER_SIZE;
117 if (!zynadd_dynparam_init(zynadd_ptr))
119 LOG_ERROR("zynadd_dynparam_init() failed.");
120 goto fail_destroy_synth;
123 return (LV2_Handle)zynadd_ptr;
125 fail_destroy_synth:
126 zyn_addsynth_destroy(zynadd_ptr->synth);
128 fail_free_ports:
129 free(zynadd_ptr->ports);
131 fail_free_bundle_path:
132 free(zynadd_ptr->bundle_path);
134 fail_free_instance:
135 free(zynadd_ptr);
137 fail:
138 /* printf("zynadd_instantiate() failed.\n"); */
139 return NULL;
142 #define zynadd_ptr ((struct zynadd *)instance)
144 /* The run() callback. This is the function that gets called by the host
145 when it wants to run the plugin. The parameter is the number of sample
146 frames to process. */
147 void
148 zynadd_run(
149 LV2_Handle instance,
150 uint32_t samples_count)
152 LV2_MIDIState midi;
153 double event_time;
154 uint32_t event_size;
155 unsigned char* event;
156 uint32_t now;
157 uint32_t fill;
158 uint32_t synth_output_offset_future;
159 /* char fake_event[2]; */
161 /* printf("%u\n", sample_count); fflush(stdout); */
163 midi.midi = (LV2_MIDI *)zynadd_ptr->ports[LV2_PORT_MIDI_IN];
164 midi.frame_count = samples_count;
165 midi.position = 0;
167 now = 0;
168 event_time = -1.0;
169 event = NULL;
170 event_size = 0;
172 while (now < samples_count)
174 fill = samples_count - now;
175 synth_output_offset_future = zynadd_ptr->synth_output_offset;
177 if (synth_output_offset_future == SOUND_BUFFER_SIZE)
179 synth_output_offset_future = 0;
182 if (fill > SOUND_BUFFER_SIZE - synth_output_offset_future)
184 fill = SOUND_BUFFER_SIZE - synth_output_offset_future;
187 while (event_time < now + fill)
189 if (event_time < 0) /* we need to extract next event */
191 lv2midi_get_event(&midi, &event_time, &event_size, &event);
192 /* if (event[0] == 0x90) */
193 /* { */
194 /* event_time = 0; */
195 /* fake_event[0] = 0x90; */
196 /* fake_event[1] = 69; */
197 /* } */
198 lv2midi_step(&midi);
201 if (event_time >= 0 && event_time < now + fill)
203 /* printf("%02X\n", (unsigned int)event[0]); */
204 if (event_size == 3)
206 switch (event[0] & 0xF0)
208 case 0x90: /* note on */
209 zyn_addsynth_note_on(zynadd_ptr->synth, event[1], event[2]);
210 break;
211 case 0x80: /* note off */
212 zyn_addsynth_note_off(zynadd_ptr->synth, event[1]);
213 break;
214 case 0xB0:
215 switch (event[1])
217 case 0x78: /* all sound off */
218 zyn_addsynth_all_sound_off(zynadd_ptr->synth);
219 break;
220 case 0x7B: /* all notes off */
221 zyn_addsynth_all_notes_off(zynadd_ptr->synth);
222 break;
224 break;
228 event_time = -1.0;
232 if (zynadd_ptr->synth_output_offset == SOUND_BUFFER_SIZE)
234 zyn_addsynth_get_audio_output(zynadd_ptr->synth, zynadd_ptr->synth_output_left, zynadd_ptr->synth_output_right);
235 zynadd_ptr->synth_output_offset = 0;
238 assert(zynadd_ptr->synth_output_offset == synth_output_offset_future);
240 memcpy((float *)(zynadd_ptr->ports[LV2_PORT_OUTPUT_LEFT]) + now, zynadd_ptr->synth_output_left, fill * sizeof(float));
241 memcpy((float *)(zynadd_ptr->ports[LV2_PORT_OUTPUT_RIGHT]) + now, zynadd_ptr->synth_output_right, fill * sizeof(float));
243 zynadd_ptr->synth_output_offset += fill;
244 assert(zynadd_ptr->synth_output_offset <= SOUND_BUFFER_SIZE);
245 now += fill;
246 assert(now <= samples_count);
250 void
251 zynadd_cleanup(
252 LV2_Handle instance)
254 /* printf("zynadd_cleanup\n"); */
255 zynadd_dynparam_uninit(zynadd_ptr);
256 zyn_addsynth_destroy(zynadd_ptr->synth);
257 free(zynadd_ptr->ports);
258 free(zynadd_ptr->bundle_path);
259 free(zynadd_ptr);
262 void
263 zynadd_connect_port(
264 LV2_Handle instance,
265 uint32_t port,
266 void * data_location)
268 if (port >= LV2_PORTS_COUNT)
270 assert(0);
271 return;
274 zynadd_ptr->ports[port] = data_location;
277 const void *
278 zynadd_extension_data(
279 const char * URI)
281 if (strcmp(URI, LV2DYNPARAM_URI) == 0)
283 return get_lv2dynparam_plugin_extension_data();
286 return NULL;