Mercurial > hg > pub > prymula > com
comparison DPF-Prymula-audioplugins/dpf/distrho/src/DistrhoPluginLADSPA+DSSI.cpp @ 3:84e66ea83026
DPF-Prymula-audioplugins-0.231015-2
author | prymula <prymula76@outlook.com> |
---|---|
date | Mon, 16 Oct 2023 21:53:34 +0200 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:cf2cb71d31dd | 3:84e66ea83026 |
---|---|
1 /* | |
2 * DISTRHO Plugin Framework (DPF) | |
3 * Copyright (C) 2012-2023 Filipe Coelho <falktx@falktx.com> | |
4 * | |
5 * Permission to use, copy, modify, and/or distribute this software for any purpose with | |
6 * or without fee is hereby granted, provided that the above copyright notice and this | |
7 * permission notice appear in all copies. | |
8 * | |
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD | |
10 * TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN | |
11 * NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL | |
12 * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER | |
13 * IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN | |
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. | |
15 */ | |
16 | |
17 #include "DistrhoPluginInternal.hpp" | |
18 | |
19 #if DISTRHO_PLUGIN_WANT_PARAMETER_VALUE_CHANGE_REQUEST | |
20 # error Cannot use parameter value change request with LADSPA or DSSI | |
21 #endif | |
22 #if DISTRHO_PLUGIN_WANT_MIDI_OUTPUT | |
23 # error Cannot use MIDI Output with LADSPA or DSSI | |
24 #endif | |
25 #if DISTRHO_PLUGIN_WANT_FULL_STATE && !defined(DISTRHO_PLUGIN_WANT_FULL_STATE_WITH_LADSPA) | |
26 # error Cannot use full state with LADSPA or DSSI | |
27 #endif | |
28 | |
29 #if DISTRHO_PLUGIN_WANT_TIMEPOS && !defined(DISTRHO_NO_WARNINGS) | |
30 # warning LADSPA/DSSI does not support TimePos | |
31 #endif | |
32 | |
33 #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |
34 # include "dssi/dssi.h" | |
35 #else | |
36 # include "ladspa/ladspa.h" | |
37 # if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |
38 # error Cannot use MIDI with LADSPA | |
39 # endif | |
40 # if DISTRHO_PLUGIN_WANT_STATE && !defined(DISTRHO_NO_WARNINGS) | |
41 # warning LADSPA cannot handle states | |
42 # endif | |
43 #endif | |
44 | |
45 START_NAMESPACE_DISTRHO | |
46 | |
47 // ----------------------------------------------------------------------- | |
48 | |
49 class PluginLadspaDssi | |
50 { | |
51 public: | |
52 PluginLadspaDssi() | |
53 : fPlugin(nullptr, nullptr, nullptr, nullptr), | |
54 fPortControls(nullptr), | |
55 fLastControlValues(nullptr) | |
56 { | |
57 #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |
58 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |
59 fPortAudioIns[i] = nullptr; | |
60 #else | |
61 fPortAudioIns = nullptr; | |
62 #endif | |
63 | |
64 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |
65 for (uint32_t i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |
66 fPortAudioOuts[i] = nullptr; | |
67 #else | |
68 fPortAudioOuts = nullptr; | |
69 #endif | |
70 | |
71 if (const uint32_t count = fPlugin.getParameterCount()) | |
72 { | |
73 fPortControls = new LADSPA_Data*[count]; | |
74 fLastControlValues = new LADSPA_Data[count]; | |
75 | |
76 for (uint32_t i=0; i < count; ++i) | |
77 { | |
78 fPortControls[i] = nullptr; | |
79 fLastControlValues[i] = fPlugin.getParameterValue(i); | |
80 } | |
81 } | |
82 else | |
83 { | |
84 fPortControls = nullptr; | |
85 fLastControlValues = nullptr; | |
86 } | |
87 | |
88 #if DISTRHO_PLUGIN_WANT_LATENCY | |
89 fPortLatency = nullptr; | |
90 #endif | |
91 } | |
92 | |
93 ~PluginLadspaDssi() noexcept | |
94 { | |
95 if (fPortControls != nullptr) | |
96 { | |
97 delete[] fPortControls; | |
98 fPortControls = nullptr; | |
99 } | |
100 | |
101 if (fLastControlValues != nullptr) | |
102 { | |
103 delete[] fLastControlValues; | |
104 fLastControlValues = nullptr; | |
105 } | |
106 } | |
107 | |
108 // ------------------------------------------------------------------- | |
109 | |
110 void ladspa_activate() | |
111 { | |
112 fPlugin.activate(); | |
113 } | |
114 | |
115 void ladspa_deactivate() | |
116 { | |
117 fPlugin.deactivate(); | |
118 } | |
119 | |
120 // ------------------------------------------------------------------- | |
121 | |
122 void ladspa_connect_port(const ulong port, LADSPA_Data* const dataLocation) noexcept | |
123 { | |
124 ulong index = 0; | |
125 | |
126 #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |
127 for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i) | |
128 { | |
129 if (port == index++) | |
130 { | |
131 fPortAudioIns[i] = dataLocation; | |
132 return; | |
133 } | |
134 } | |
135 #endif | |
136 | |
137 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |
138 for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i) | |
139 { | |
140 if (port == index++) | |
141 { | |
142 fPortAudioOuts[i] = dataLocation; | |
143 return; | |
144 } | |
145 } | |
146 #endif | |
147 | |
148 #if DISTRHO_PLUGIN_WANT_LATENCY | |
149 if (port == index++) | |
150 { | |
151 fPortLatency = dataLocation; | |
152 return; | |
153 } | |
154 #endif | |
155 | |
156 for (ulong i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |
157 { | |
158 if (port == index++) | |
159 { | |
160 fPortControls[i] = dataLocation; | |
161 return; | |
162 } | |
163 } | |
164 } | |
165 | |
166 // ------------------------------------------------------------------- | |
167 | |
168 #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |
169 void ladspa_run(const ulong sampleCount) | |
170 { | |
171 dssi_run_synth(sampleCount, nullptr, 0); | |
172 } | |
173 | |
174 void dssi_run_synth(const ulong sampleCount, snd_seq_event_t* const events, const ulong eventCount) | |
175 #else | |
176 void ladspa_run(const ulong sampleCount) | |
177 #endif | |
178 { | |
179 // pre-roll | |
180 if (sampleCount == 0) | |
181 return updateParameterOutputsAndTriggers(); | |
182 | |
183 // Check for updated parameters | |
184 float curValue; | |
185 | |
186 for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |
187 { | |
188 if (fPortControls[i] == nullptr) | |
189 continue; | |
190 | |
191 curValue = *fPortControls[i]; | |
192 | |
193 if (fPlugin.isParameterInput(i) && d_isNotEqual(fLastControlValues[i], curValue)) | |
194 { | |
195 fLastControlValues[i] = curValue; | |
196 fPlugin.setParameterValue(i, curValue); | |
197 } | |
198 } | |
199 | |
200 #if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |
201 // Get MIDI Events | |
202 uint32_t midiEventCount = 0; | |
203 MidiEvent midiEvents[eventCount]; | |
204 | |
205 for (uint32_t i=0, j; i < eventCount; ++i) | |
206 { | |
207 const snd_seq_event_t& seqEvent(events[i]); | |
208 | |
209 // FIXME | |
210 if (seqEvent.data.note.channel > 0xF || seqEvent.data.control.channel > 0xF) | |
211 continue; | |
212 | |
213 switch (seqEvent.type) | |
214 { | |
215 case SND_SEQ_EVENT_NOTEOFF: | |
216 j = midiEventCount++; | |
217 midiEvents[j].frame = seqEvent.time.tick; | |
218 midiEvents[j].size = 3; | |
219 midiEvents[j].data[0] = 0x80 + seqEvent.data.note.channel; | |
220 midiEvents[j].data[1] = seqEvent.data.note.note; | |
221 midiEvents[j].data[2] = 0; | |
222 midiEvents[j].data[3] = 0; | |
223 break; | |
224 case SND_SEQ_EVENT_NOTEON: | |
225 j = midiEventCount++; | |
226 midiEvents[j].frame = seqEvent.time.tick; | |
227 midiEvents[j].size = 3; | |
228 midiEvents[j].data[0] = 0x90 + seqEvent.data.note.channel; | |
229 midiEvents[j].data[1] = seqEvent.data.note.note; | |
230 midiEvents[j].data[2] = seqEvent.data.note.velocity; | |
231 midiEvents[j].data[3] = 0; | |
232 break; | |
233 case SND_SEQ_EVENT_KEYPRESS: | |
234 j = midiEventCount++; | |
235 midiEvents[j].frame = seqEvent.time.tick; | |
236 midiEvents[j].size = 3; | |
237 midiEvents[j].data[0] = 0xA0 + seqEvent.data.note.channel; | |
238 midiEvents[j].data[1] = seqEvent.data.note.note; | |
239 midiEvents[j].data[2] = seqEvent.data.note.velocity; | |
240 midiEvents[j].data[3] = 0; | |
241 break; | |
242 case SND_SEQ_EVENT_CONTROLLER: | |
243 j = midiEventCount++; | |
244 midiEvents[j].frame = seqEvent.time.tick; | |
245 midiEvents[j].size = 3; | |
246 midiEvents[j].data[0] = 0xB0 + seqEvent.data.control.channel; | |
247 midiEvents[j].data[1] = seqEvent.data.control.param; | |
248 midiEvents[j].data[2] = seqEvent.data.control.value; | |
249 midiEvents[j].data[3] = 0; | |
250 break; | |
251 case SND_SEQ_EVENT_CHANPRESS: | |
252 j = midiEventCount++; | |
253 midiEvents[j].frame = seqEvent.time.tick; | |
254 midiEvents[j].size = 2; | |
255 midiEvents[j].data[0] = 0xD0 + seqEvent.data.control.channel; | |
256 midiEvents[j].data[1] = seqEvent.data.control.value; | |
257 midiEvents[j].data[2] = 0; | |
258 midiEvents[j].data[3] = 0; | |
259 break; | |
260 case SND_SEQ_EVENT_PITCHBEND: | |
261 j = midiEventCount++; | |
262 midiEvents[j].frame = seqEvent.time.tick; | |
263 midiEvents[j].size = 3; | |
264 midiEvents[j].data[0] = 0xE0 + seqEvent.data.control.channel; | |
265 uint16_t tempvalue = seqEvent.data.control.value + 8192; | |
266 midiEvents[j].data[1] = tempvalue & 0x7F; | |
267 midiEvents[j].data[2] = tempvalue >> 7; | |
268 midiEvents[j].data[3] = 0; | |
269 break; | |
270 } | |
271 } | |
272 | |
273 fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount, midiEvents, midiEventCount); | |
274 #else | |
275 fPlugin.run(fPortAudioIns, fPortAudioOuts, sampleCount); | |
276 #endif | |
277 | |
278 updateParameterOutputsAndTriggers(); | |
279 | |
280 #if defined(DISTRHO_PLUGIN_TARGET_DSSI) && ! DISTRHO_PLUGIN_WANT_MIDI_INPUT | |
281 return; // unused | |
282 (void)events; (void)eventCount; | |
283 #endif | |
284 } | |
285 | |
286 // ------------------------------------------------------------------- | |
287 | |
288 #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |
289 # if DISTRHO_PLUGIN_WANT_STATE | |
290 char* dssi_configure(const char* const key, const char* const value) | |
291 { | |
292 if (std::strncmp(key, DSSI_RESERVED_CONFIGURE_PREFIX, std::strlen(DSSI_RESERVED_CONFIGURE_PREFIX)) == 0) | |
293 return nullptr; | |
294 if (std::strncmp(key, DSSI_GLOBAL_CONFIGURE_PREFIX, std::strlen(DSSI_GLOBAL_CONFIGURE_PREFIX)) == 0) | |
295 return nullptr; | |
296 | |
297 fPlugin.setState(key, value); | |
298 return nullptr; | |
299 } | |
300 # endif | |
301 | |
302 # if DISTRHO_PLUGIN_WANT_PROGRAMS | |
303 const DSSI_Program_Descriptor* dssi_get_program(const ulong index) | |
304 { | |
305 if (index >= fPlugin.getProgramCount()) | |
306 return nullptr; | |
307 | |
308 static DSSI_Program_Descriptor desc; | |
309 | |
310 desc.Bank = index / 128; | |
311 desc.Program = index % 128; | |
312 desc.Name = fPlugin.getProgramName(index); | |
313 | |
314 return &desc; | |
315 } | |
316 | |
317 void dssi_select_program(const ulong bank, const ulong program) | |
318 { | |
319 const ulong realProgram(bank * 128 + program); | |
320 | |
321 DISTRHO_SAFE_ASSERT_RETURN(realProgram < fPlugin.getProgramCount(),); | |
322 | |
323 fPlugin.loadProgram(realProgram); | |
324 | |
325 // Update control inputs | |
326 for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |
327 { | |
328 if (fPlugin.isParameterOutput(i)) | |
329 continue; | |
330 | |
331 fLastControlValues[i] = fPlugin.getParameterValue(i); | |
332 | |
333 if (fPortControls[i] != nullptr) | |
334 *fPortControls[i] = fLastControlValues[i]; | |
335 } | |
336 } | |
337 # endif | |
338 | |
339 int dssi_get_midi_controller_for_port(const ulong port) noexcept | |
340 { | |
341 const uint32_t parameterOffset = fPlugin.getParameterOffset(); | |
342 | |
343 if (port > parameterOffset) | |
344 return DSSI_NONE; | |
345 | |
346 const uint8_t midiCC = fPlugin.getParameterMidiCC(port-parameterOffset); | |
347 | |
348 if (midiCC == 0 || midiCC == 32 || midiCC >= 0x78) | |
349 return DSSI_NONE; | |
350 | |
351 return DSSI_CC(midiCC); | |
352 } | |
353 #endif | |
354 | |
355 // ------------------------------------------------------------------- | |
356 | |
357 private: | |
358 PluginExporter fPlugin; | |
359 | |
360 // LADSPA ports | |
361 #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |
362 const LADSPA_Data* fPortAudioIns[DISTRHO_PLUGIN_NUM_INPUTS]; | |
363 #else | |
364 const LADSPA_Data** fPortAudioIns; | |
365 #endif | |
366 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |
367 LADSPA_Data* fPortAudioOuts[DISTRHO_PLUGIN_NUM_OUTPUTS]; | |
368 #else | |
369 LADSPA_Data** fPortAudioOuts; | |
370 #endif | |
371 LADSPA_Data** fPortControls; | |
372 #if DISTRHO_PLUGIN_WANT_LATENCY | |
373 LADSPA_Data* fPortLatency; | |
374 #endif | |
375 | |
376 // Temporary data | |
377 LADSPA_Data* fLastControlValues; | |
378 | |
379 // ------------------------------------------------------------------- | |
380 | |
381 void updateParameterOutputsAndTriggers() | |
382 { | |
383 float value; | |
384 | |
385 for (uint32_t i=0, count=fPlugin.getParameterCount(); i < count; ++i) | |
386 { | |
387 if (fPlugin.isParameterOutput(i)) | |
388 { | |
389 value = fLastControlValues[i] = fPlugin.getParameterValue(i); | |
390 | |
391 if (fPortControls[i] != nullptr) | |
392 *fPortControls[i] = value; | |
393 } | |
394 else if ((fPlugin.getParameterHints(i) & kParameterIsTrigger) == kParameterIsTrigger) | |
395 { | |
396 // NOTE: no trigger support in LADSPA control ports, simulate it here | |
397 value = fPlugin.getParameterRanges(i).def; | |
398 | |
399 if (d_isEqual(value, fPlugin.getParameterValue(i))) | |
400 continue; | |
401 | |
402 fLastControlValues[i] = value; | |
403 fPlugin.setParameterValue(i, value); | |
404 | |
405 if (fPortControls[i] != nullptr) | |
406 *fPortControls[i] = value; | |
407 } | |
408 } | |
409 | |
410 #if DISTRHO_PLUGIN_WANT_LATENCY | |
411 if (fPortLatency != nullptr) | |
412 *fPortLatency = fPlugin.getLatency(); | |
413 #endif | |
414 } | |
415 }; | |
416 | |
417 // ----------------------------------------------------------------------- | |
418 | |
419 static LADSPA_Handle ladspa_instantiate(const LADSPA_Descriptor*, ulong sampleRate) | |
420 { | |
421 if (d_nextBufferSize == 0) | |
422 d_nextBufferSize = 2048; | |
423 d_nextSampleRate = sampleRate; | |
424 | |
425 return new PluginLadspaDssi(); | |
426 } | |
427 | |
428 #define instancePtr ((PluginLadspaDssi*)instance) | |
429 | |
430 static void ladspa_connect_port(LADSPA_Handle instance, ulong port, LADSPA_Data* dataLocation) | |
431 { | |
432 instancePtr->ladspa_connect_port(port, dataLocation); | |
433 } | |
434 | |
435 static void ladspa_activate(LADSPA_Handle instance) | |
436 { | |
437 instancePtr->ladspa_activate(); | |
438 } | |
439 | |
440 static void ladspa_run(LADSPA_Handle instance, ulong sampleCount) | |
441 { | |
442 instancePtr->ladspa_run(sampleCount); | |
443 } | |
444 | |
445 static void ladspa_deactivate(LADSPA_Handle instance) | |
446 { | |
447 instancePtr->ladspa_deactivate(); | |
448 } | |
449 | |
450 static void ladspa_cleanup(LADSPA_Handle instance) | |
451 { | |
452 delete instancePtr; | |
453 } | |
454 | |
455 #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |
456 # if DISTRHO_PLUGIN_WANT_STATE | |
457 static char* dssi_configure(LADSPA_Handle instance, const char* key, const char* value) | |
458 { | |
459 return instancePtr->dssi_configure(key, value); | |
460 } | |
461 # endif | |
462 | |
463 # if DISTRHO_PLUGIN_WANT_PROGRAMS | |
464 static const DSSI_Program_Descriptor* dssi_get_program(LADSPA_Handle instance, ulong index) | |
465 { | |
466 return instancePtr->dssi_get_program(index); | |
467 } | |
468 | |
469 static void dssi_select_program(LADSPA_Handle instance, ulong bank, ulong program) | |
470 { | |
471 instancePtr->dssi_select_program(bank, program); | |
472 } | |
473 # endif | |
474 | |
475 static int dssi_get_midi_controller_for_port(LADSPA_Handle instance, ulong port) | |
476 { | |
477 return instancePtr->dssi_get_midi_controller_for_port(port); | |
478 } | |
479 | |
480 # if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |
481 static void dssi_run_synth(LADSPA_Handle instance, ulong sampleCount, snd_seq_event_t* events, ulong eventCount) | |
482 { | |
483 instancePtr->dssi_run_synth(sampleCount, events, eventCount); | |
484 } | |
485 # endif | |
486 #endif | |
487 | |
488 #undef instancePtr | |
489 | |
490 // ----------------------------------------------------------------------- | |
491 | |
492 static LADSPA_Descriptor sLadspaDescriptor = { | |
493 /* UniqueID */ 0, | |
494 /* Label */ nullptr, | |
495 #if DISTRHO_PLUGIN_IS_RT_SAFE | |
496 /* Properties */ LADSPA_PROPERTY_HARD_RT_CAPABLE, | |
497 #else | |
498 /* Properties */ 0x0, | |
499 #endif | |
500 /* Name */ nullptr, | |
501 /* Maker */ nullptr, | |
502 /* Copyright */ nullptr, | |
503 /* PortCount */ 0, | |
504 /* PortDescriptors */ nullptr, | |
505 /* PortNames */ nullptr, | |
506 /* PortRangeHints */ nullptr, | |
507 /* ImplementationData */ nullptr, | |
508 ladspa_instantiate, | |
509 ladspa_connect_port, | |
510 ladspa_activate, | |
511 ladspa_run, | |
512 /* run_adding */ nullptr, | |
513 /* set_run_adding_gain */ nullptr, | |
514 ladspa_deactivate, | |
515 ladspa_cleanup | |
516 }; | |
517 | |
518 #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |
519 static DSSI_Descriptor sDssiDescriptor = { | |
520 1, | |
521 &sLadspaDescriptor, | |
522 # if DISTRHO_PLUGIN_WANT_STATE | |
523 dssi_configure, | |
524 # else | |
525 /* configure */ nullptr, | |
526 # endif | |
527 # if DISTRHO_PLUGIN_WANT_PROGRAMS | |
528 dssi_get_program, | |
529 dssi_select_program, | |
530 # else | |
531 /* get_program */ nullptr, | |
532 /* select_program */ nullptr, | |
533 # endif | |
534 dssi_get_midi_controller_for_port, | |
535 # if DISTRHO_PLUGIN_WANT_MIDI_INPUT | |
536 dssi_run_synth, | |
537 # else | |
538 /* run_synth */ nullptr, | |
539 # endif | |
540 /* run_synth_adding */ nullptr, | |
541 /* run_multiple_synths */ nullptr, | |
542 /* run_multiple_synths_adding */ nullptr, | |
543 nullptr, nullptr | |
544 }; | |
545 #endif | |
546 | |
547 // ----------------------------------------------------------------------- | |
548 | |
549 static const struct DescriptorInitializer | |
550 { | |
551 DescriptorInitializer() | |
552 { | |
553 // Create dummy plugin to get data from | |
554 d_nextBufferSize = 512; | |
555 d_nextSampleRate = 44100.0; | |
556 d_nextPluginIsDummy = true; | |
557 const PluginExporter plugin(nullptr, nullptr, nullptr, nullptr); | |
558 d_nextBufferSize = 0; | |
559 d_nextSampleRate = 0.0; | |
560 d_nextPluginIsDummy = false; | |
561 | |
562 // Get port count, init | |
563 ulong port = 0; | |
564 ulong portCount = DISTRHO_PLUGIN_NUM_INPUTS + DISTRHO_PLUGIN_NUM_OUTPUTS + plugin.getParameterCount(); | |
565 #if DISTRHO_PLUGIN_WANT_LATENCY | |
566 portCount += 1; | |
567 #endif | |
568 const char** const portNames = new const char*[portCount]; | |
569 LADSPA_PortDescriptor* portDescriptors = new LADSPA_PortDescriptor[portCount]; | |
570 LADSPA_PortRangeHint* portRangeHints = new LADSPA_PortRangeHint [portCount]; | |
571 | |
572 // Set ports | |
573 #if DISTRHO_PLUGIN_NUM_INPUTS > 0 | |
574 for (ulong i=0; i < DISTRHO_PLUGIN_NUM_INPUTS; ++i, ++port) | |
575 { | |
576 const AudioPort& aport(plugin.getAudioPort(true, i)); | |
577 | |
578 portNames[port] = strdup(aport.name); | |
579 portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_INPUT; | |
580 | |
581 portRangeHints[port].HintDescriptor = 0x0; | |
582 portRangeHints[port].LowerBound = 0.0f; | |
583 portRangeHints[port].UpperBound = 1.0f; | |
584 } | |
585 #endif | |
586 | |
587 #if DISTRHO_PLUGIN_NUM_OUTPUTS > 0 | |
588 for (ulong i=0; i < DISTRHO_PLUGIN_NUM_OUTPUTS; ++i, ++port) | |
589 { | |
590 const AudioPort& aport(plugin.getAudioPort(false, i)); | |
591 | |
592 portNames[port] = strdup(aport.name); | |
593 portDescriptors[port] = LADSPA_PORT_AUDIO | LADSPA_PORT_OUTPUT; | |
594 | |
595 portRangeHints[port].HintDescriptor = 0x0; | |
596 portRangeHints[port].LowerBound = 0.0f; | |
597 portRangeHints[port].UpperBound = 1.0f; | |
598 } | |
599 #endif | |
600 | |
601 #if DISTRHO_PLUGIN_WANT_LATENCY | |
602 // Set latency port | |
603 portNames[port] = strdup("_latency"); | |
604 portDescriptors[port] = LADSPA_PORT_CONTROL | LADSPA_PORT_OUTPUT; | |
605 portRangeHints[port].HintDescriptor = LADSPA_HINT_SAMPLE_RATE|LADSPA_HINT_INTEGER; | |
606 portRangeHints[port].LowerBound = 0.0f; | |
607 portRangeHints[port].UpperBound = 1.0f; | |
608 ++port; | |
609 #endif | |
610 | |
611 for (ulong i=0, count=plugin.getParameterCount(); i < count; ++i, ++port) | |
612 { | |
613 portNames[port] = strdup((const char*)plugin.getParameterName(i)); | |
614 portDescriptors[port] = LADSPA_PORT_CONTROL; | |
615 | |
616 if (plugin.isParameterOutput(i)) | |
617 portDescriptors[port] |= LADSPA_PORT_OUTPUT; | |
618 else | |
619 portDescriptors[port] |= LADSPA_PORT_INPUT; | |
620 | |
621 const uint32_t hints = plugin.getParameterHints(i); | |
622 | |
623 { | |
624 const ParameterRanges& ranges(plugin.getParameterRanges(i)); | |
625 const float defValue = ranges.def; | |
626 | |
627 // LADSPA doesn't allow bounded hints on toggles | |
628 portRangeHints[port].HintDescriptor = hints & kParameterIsBoolean | |
629 ? 0 | |
630 : LADSPA_HINT_BOUNDED_BELOW | LADSPA_HINT_BOUNDED_ABOVE; | |
631 | |
632 portRangeHints[port].LowerBound = ranges.min; | |
633 portRangeHints[port].UpperBound = ranges.max; | |
634 | |
635 /**/ if (d_isZero(defValue)) | |
636 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_0; | |
637 else if (d_isEqual(defValue, 1.0f)) | |
638 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_1; | |
639 else if (d_isEqual(defValue, 100.0f)) | |
640 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_100; | |
641 else if (d_isEqual(defValue, 440.0f)) | |
642 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_440; | |
643 else if (d_isEqual(ranges.min, defValue)) | |
644 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MINIMUM; | |
645 else if (d_isEqual(ranges.max, defValue)) | |
646 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MAXIMUM; | |
647 else | |
648 { | |
649 const float middleValue = ranges.min/2.0f + ranges.max/2.0f; | |
650 const float middleLow = (ranges.min/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f; | |
651 const float middleHigh = (ranges.max/2.0f + middleValue/2.0f)/2.0f + middleValue/2.0f; | |
652 | |
653 /**/ if (defValue < middleLow) | |
654 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_LOW; | |
655 else if (defValue > middleHigh) | |
656 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_HIGH; | |
657 else | |
658 portRangeHints[port].HintDescriptor |= LADSPA_HINT_DEFAULT_MIDDLE; | |
659 } | |
660 } | |
661 | |
662 { | |
663 if (hints & kParameterIsBoolean) | |
664 { | |
665 portRangeHints[port].HintDescriptor |= LADSPA_HINT_TOGGLED; | |
666 } | |
667 else | |
668 { | |
669 if (hints & kParameterIsInteger) | |
670 portRangeHints[port].HintDescriptor |= LADSPA_HINT_INTEGER; | |
671 if (hints & kParameterIsLogarithmic) | |
672 portRangeHints[port].HintDescriptor |= LADSPA_HINT_LOGARITHMIC; | |
673 } | |
674 } | |
675 } | |
676 | |
677 // Set data | |
678 sLadspaDescriptor.UniqueID = plugin.getUniqueId(); | |
679 sLadspaDescriptor.Label = strdup(plugin.getLabel()); | |
680 sLadspaDescriptor.Name = strdup(plugin.getName()); | |
681 sLadspaDescriptor.Maker = strdup(plugin.getMaker()); | |
682 sLadspaDescriptor.Copyright = strdup(plugin.getLicense()); | |
683 sLadspaDescriptor.PortCount = portCount; | |
684 sLadspaDescriptor.PortNames = portNames; | |
685 sLadspaDescriptor.PortDescriptors = portDescriptors; | |
686 sLadspaDescriptor.PortRangeHints = portRangeHints; | |
687 } | |
688 | |
689 ~DescriptorInitializer() | |
690 { | |
691 if (sLadspaDescriptor.Label != nullptr) | |
692 { | |
693 std::free((void*)sLadspaDescriptor.Label); | |
694 sLadspaDescriptor.Label = nullptr; | |
695 } | |
696 | |
697 if (sLadspaDescriptor.Name != nullptr) | |
698 { | |
699 std::free((void*)sLadspaDescriptor.Name); | |
700 sLadspaDescriptor.Name = nullptr; | |
701 } | |
702 | |
703 if (sLadspaDescriptor.Maker != nullptr) | |
704 { | |
705 std::free((void*)sLadspaDescriptor.Maker); | |
706 sLadspaDescriptor.Maker = nullptr; | |
707 } | |
708 | |
709 if (sLadspaDescriptor.Copyright != nullptr) | |
710 { | |
711 std::free((void*)sLadspaDescriptor.Copyright); | |
712 sLadspaDescriptor.Copyright = nullptr; | |
713 } | |
714 | |
715 if (sLadspaDescriptor.PortDescriptors != nullptr) | |
716 { | |
717 delete[] sLadspaDescriptor.PortDescriptors; | |
718 sLadspaDescriptor.PortDescriptors = nullptr; | |
719 } | |
720 | |
721 if (sLadspaDescriptor.PortRangeHints != nullptr) | |
722 { | |
723 delete[] sLadspaDescriptor.PortRangeHints; | |
724 sLadspaDescriptor.PortRangeHints = nullptr; | |
725 } | |
726 | |
727 if (sLadspaDescriptor.PortNames != nullptr) | |
728 { | |
729 for (ulong i=0; i < sLadspaDescriptor.PortCount; ++i) | |
730 { | |
731 if (sLadspaDescriptor.PortNames[i] != nullptr) | |
732 std::free((void*)sLadspaDescriptor.PortNames[i]); | |
733 } | |
734 | |
735 delete[] sLadspaDescriptor.PortNames; | |
736 sLadspaDescriptor.PortNames = nullptr; | |
737 } | |
738 } | |
739 } sDescInit; | |
740 | |
741 // ----------------------------------------------------------------------- | |
742 | |
743 END_NAMESPACE_DISTRHO | |
744 | |
745 DISTRHO_PLUGIN_EXPORT | |
746 const LADSPA_Descriptor* ladspa_descriptor(ulong index) | |
747 { | |
748 USE_NAMESPACE_DISTRHO | |
749 return (index == 0) ? &sLadspaDescriptor : nullptr; | |
750 } | |
751 | |
752 #ifdef DISTRHO_PLUGIN_TARGET_DSSI | |
753 DISTRHO_PLUGIN_EXPORT | |
754 const DSSI_Descriptor* dssi_descriptor(ulong index) | |
755 { | |
756 USE_NAMESPACE_DISTRHO | |
757 return (index == 0) ? &sDssiDescriptor : nullptr; | |
758 } | |
759 #endif | |
760 | |
761 // ----------------------------------------------------------------------- |