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 *****************************************************************************/
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
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
49 const LV2_Descriptor
* descriptor
,
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
);
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
;
77 if (rtmempool_ptr
== NULL
)
79 LOG_ERROR(LV2_RTSAFE_MEMORY_POOL_URI
" extension is required");
83 zynadd_ptr
= malloc(sizeof(struct zynadd
));
84 if (zynadd_ptr
== NULL
)
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
;
121 zyn_addsynth_destroy(zynadd_ptr
->synth
);
124 free(zynadd_ptr
->ports
);
126 fail_free_bundle_path
:
127 free(zynadd_ptr
->bundle_path
);
133 /* printf("zynadd_instantiate() failed.\n"); */
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. */
145 uint32_t samples_count
)
150 unsigned char* event
;
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
;
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) */
189 /* event_time = 0; */
190 /* fake_event[0] = 0x90; */
191 /* fake_event[1] = 69; */
196 if (event_time
>= 0 && event_time
< now
+ fill
)
198 /* printf("%02X\n", (unsigned int)event[0]); */
201 switch (event
[0] & 0xF0)
203 case 0x90: /* note on */
204 zyn_addsynth_note_on(zynadd_ptr
->synth
, event
[1], event
[2]);
206 case 0x80: /* note off */
207 zyn_addsynth_note_off(zynadd_ptr
->synth
, event
[1]);
212 case 0x78: /* all sound off */
213 zyn_addsynth_all_sound_off(zynadd_ptr
->synth
);
215 case 0x7B: /* all notes off */
216 zyn_addsynth_all_notes_off(zynadd_ptr
->synth
);
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
);
241 assert(now
<= samples_count
);
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
);
261 void * data_location
)
263 if (port
>= LV2_PORTS_COUNT
)
269 zynadd_ptr
->ports
[port
] = data_location
;
273 zynadd_extension_data(
276 if (strcmp(URI
, LV2DYNPARAM_URI
) == 0)
278 return get_lv2dynparam_plugin_extension_data();