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 *****************************************************************************/
30 #include "lv2-miditype.h"
31 #include "lv2-midifunctions.h"
34 #include "lv2dynparam/lv2dynparam.h"
35 #include "lv2dynparam/lv2_rtmempool.h"
36 #include "lv2dynparam/plugin.h"
38 #include "zynadd_internal.h"
39 //#define LOG_LEVEL LOG_LEVEL_DEBUG
43 * The number of voices of additive synth for a single note
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
54 const LV2_Descriptor
* descriptor
,
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
);
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
;
82 if (rtmempool_ptr
== NULL
)
84 LOG_ERROR(LV2_RTSAFE_MEMORY_POOL_URI
" extension is required");
88 zynadd_ptr
= malloc(sizeof(struct zynadd
));
89 if (zynadd_ptr
== NULL
)
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
;
126 zyn_addsynth_destroy(zynadd_ptr
->synth
);
129 free(zynadd_ptr
->ports
);
131 fail_free_bundle_path
:
132 free(zynadd_ptr
->bundle_path
);
138 /* printf("zynadd_instantiate() failed.\n"); */
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. */
150 uint32_t samples_count
)
155 unsigned char* event
;
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
;
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) */
194 /* event_time = 0; */
195 /* fake_event[0] = 0x90; */
196 /* fake_event[1] = 69; */
201 if (event_time
>= 0 && event_time
< now
+ fill
)
203 /* printf("%02X\n", (unsigned int)event[0]); */
206 switch (event
[0] & 0xF0)
208 case 0x90: /* note on */
209 zyn_addsynth_note_on(zynadd_ptr
->synth
, event
[1], event
[2]);
211 case 0x80: /* note off */
212 zyn_addsynth_note_off(zynadd_ptr
->synth
, event
[1]);
217 case 0x78: /* all sound off */
218 zyn_addsynth_all_sound_off(zynadd_ptr
->synth
);
220 case 0x7B: /* all notes off */
221 zyn_addsynth_all_notes_off(zynadd_ptr
->synth
);
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
);
246 assert(now
<= samples_count
);
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
);
266 void * data_location
)
268 if (port
>= LV2_PORTS_COUNT
)
274 zynadd_ptr
->ports
[port
] = data_location
;
278 zynadd_extension_data(
281 if (strcmp(URI
, LV2DYNPARAM_URI
) == 0)
283 return get_lv2dynparam_plugin_extension_data();