Mercurial > hg > easaier-soundaccess
comparison plugin/LADSPAPluginInstance.cpp @ 0:fc9323a41f5a
start base : Sonic Visualiser sv1-1.0rc1
author | lbajardsilogic |
---|---|
date | Fri, 11 May 2007 09:08:14 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:fc9323a41f5a |
---|---|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ | |
2 | |
3 /* | |
4 Sonic Visualiser | |
5 An audio file viewer and annotation editor. | |
6 Centre for Digital Music, Queen Mary, University of London. | |
7 | |
8 This program is free software; you can redistribute it and/or | |
9 modify it under the terms of the GNU General Public License as | |
10 published by the Free Software Foundation; either version 2 of the | |
11 License, or (at your option) any later version. See the file | |
12 COPYING included with this distribution for more information. | |
13 */ | |
14 | |
15 /* | |
16 This is a modified version of a source file from the | |
17 Rosegarden MIDI and audio sequencer and notation editor. | |
18 This file copyright 2000-2006 Chris Cannam, Richard Bown, and QMUL. | |
19 */ | |
20 | |
21 #include <iostream> | |
22 #include <cassert> | |
23 | |
24 #include "LADSPAPluginInstance.h" | |
25 #include "LADSPAPluginFactory.h" | |
26 | |
27 #ifdef HAVE_LRDF | |
28 #include "lrdf.h" | |
29 #endif // HAVE_LRDF | |
30 | |
31 //#define DEBUG_LADSPA 1 | |
32 | |
33 #include <cmath> | |
34 | |
35 | |
36 LADSPAPluginInstance::LADSPAPluginInstance(RealTimePluginFactory *factory, | |
37 int clientId, | |
38 QString identifier, | |
39 int position, | |
40 unsigned long sampleRate, | |
41 size_t blockSize, | |
42 int idealChannelCount, | |
43 const LADSPA_Descriptor* descriptor) : | |
44 RealTimePluginInstance(factory, identifier), | |
45 m_client(clientId), | |
46 m_position(position), | |
47 m_instanceCount(0), | |
48 m_descriptor(descriptor), | |
49 m_blockSize(blockSize), | |
50 m_sampleRate(sampleRate), | |
51 m_latencyPort(0), | |
52 m_run(false), | |
53 m_bypassed(false) | |
54 { | |
55 init(idealChannelCount); | |
56 | |
57 if (m_audioPortsIn.size() == 0) { | |
58 m_inputBuffers = 0; | |
59 } else { | |
60 m_inputBuffers = new sample_t*[m_instanceCount * m_audioPortsIn.size()]; | |
61 } | |
62 | |
63 if (m_audioPortsOut.size() == 0) { | |
64 m_outputBuffers = 0; | |
65 } else { | |
66 m_outputBuffers = new sample_t*[m_instanceCount * m_audioPortsOut.size()]; | |
67 } | |
68 | |
69 for (size_t i = 0; i < m_instanceCount * m_audioPortsIn.size(); ++i) { | |
70 m_inputBuffers[i] = new sample_t[blockSize]; | |
71 } | |
72 for (size_t i = 0; i < m_instanceCount * m_audioPortsOut.size(); ++i) { | |
73 m_outputBuffers[i] = new sample_t[blockSize]; | |
74 } | |
75 | |
76 m_ownBuffers = true; | |
77 | |
78 instantiate(sampleRate); | |
79 if (isOK()) { | |
80 connectPorts(); | |
81 activate(); | |
82 } | |
83 } | |
84 | |
85 std::string | |
86 LADSPAPluginInstance::getIdentifier() const | |
87 { | |
88 return m_descriptor->Label; | |
89 } | |
90 | |
91 std::string | |
92 LADSPAPluginInstance::getName() const | |
93 { | |
94 return m_descriptor->Name; | |
95 } | |
96 | |
97 std::string | |
98 LADSPAPluginInstance::getDescription() const | |
99 { | |
100 return ""; | |
101 } | |
102 | |
103 std::string | |
104 LADSPAPluginInstance::getMaker() const | |
105 { | |
106 return m_descriptor->Maker; | |
107 } | |
108 | |
109 int | |
110 LADSPAPluginInstance::getPluginVersion() const | |
111 { | |
112 return 1; | |
113 } | |
114 | |
115 std::string | |
116 LADSPAPluginInstance::getCopyright() const | |
117 { | |
118 return m_descriptor->Copyright; | |
119 } | |
120 | |
121 LADSPAPluginInstance::ParameterList | |
122 LADSPAPluginInstance::getParameterDescriptors() const | |
123 { | |
124 ParameterList list; | |
125 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory); | |
126 | |
127 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) { | |
128 | |
129 ParameterDescriptor pd; | |
130 unsigned int pn = m_controlPortsIn[i].first; | |
131 | |
132 pd.identifier = m_descriptor->PortNames[pn]; | |
133 pd.name = pd.identifier; | |
134 pd.description = ""; | |
135 pd.minValue = f->getPortMinimum(m_descriptor, pn); | |
136 pd.maxValue = f->getPortMaximum(m_descriptor, pn); | |
137 pd.defaultValue = f->getPortDefault(m_descriptor, pn); | |
138 | |
139 float q = f->getPortQuantization(m_descriptor, pn); | |
140 if (q == 0.0) { | |
141 pd.isQuantized = false; | |
142 } else { | |
143 pd.isQuantized = true; | |
144 pd.quantizeStep = q; | |
145 } | |
146 | |
147 bool haveLabels = false; | |
148 | |
149 #ifdef HAVE_LRDF | |
150 if (pd.isQuantized && pd.quantizeStep == 1.0) { | |
151 | |
152 lrdf_defaults *defaults = | |
153 lrdf_get_scale_values(m_descriptor->UniqueID, pn); | |
154 | |
155 if (defaults) { | |
156 if (defaults->count > 0) { | |
157 std::map<int, std::string> values; | |
158 size_t v = 0; | |
159 for (size_t i = 0; i < defaults->count; ++i) { | |
160 v = size_t(lrintf(fabsf(defaults->items[i].value))); | |
161 values[v] = defaults->items[i].label; | |
162 } | |
163 for (size_t i = 0; i <= v; ++i) { | |
164 pd.valueNames.push_back(values[i]); | |
165 } | |
166 haveLabels = true; | |
167 } | |
168 lrdf_free_setting_values(defaults); | |
169 } | |
170 } | |
171 #endif | |
172 | |
173 if (haveLabels) { | |
174 pd.name = QString(pd.name.c_str()) | |
175 .replace(QRegExp("\\([^\\(\\)]+=[^\\(\\)]+\\)$"), "") | |
176 .toStdString(); | |
177 } else { | |
178 static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$"); | |
179 if (unitRE.indexIn(pd.name.c_str()) >= 0) { | |
180 pd.unit = unitRE.cap(1).toStdString(); | |
181 pd.name = QString(pd.name.c_str()) | |
182 .replace(unitRE, "").toStdString(); | |
183 } | |
184 } | |
185 | |
186 list.push_back(pd); | |
187 } | |
188 | |
189 return list; | |
190 } | |
191 | |
192 float | |
193 LADSPAPluginInstance::getParameter(std::string id) const | |
194 { | |
195 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) { | |
196 if (id == m_descriptor->PortNames[m_controlPortsIn[i].first]) { | |
197 return getParameterValue(i); | |
198 } | |
199 } | |
200 | |
201 return 0.0; | |
202 } | |
203 | |
204 void | |
205 LADSPAPluginInstance::setParameter(std::string id, float value) | |
206 { | |
207 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) { | |
208 if (id == m_descriptor->PortNames[m_controlPortsIn[i].first]) { | |
209 #ifdef DEBUG_LADSPA | |
210 std::cerr << "LADSPAPluginInstance::setParameter: Found id " | |
211 << id << " at control port " << i << std::endl; | |
212 #endif | |
213 setParameterValue(i, value); | |
214 break; | |
215 } | |
216 } | |
217 } | |
218 | |
219 void | |
220 LADSPAPluginInstance::init(int idealChannelCount) | |
221 { | |
222 #ifdef DEBUG_LADSPA | |
223 std::cerr << "LADSPAPluginInstance::init(" << idealChannelCount << "): plugin has " | |
224 << m_descriptor->PortCount << " ports" << std::endl; | |
225 #endif | |
226 | |
227 // Discover ports numbers and identities | |
228 // | |
229 for (unsigned long i = 0; i < m_descriptor->PortCount; ++i) { | |
230 | |
231 if (LADSPA_IS_PORT_AUDIO(m_descriptor->PortDescriptors[i])) { | |
232 | |
233 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) { | |
234 #ifdef DEBUG_LADSPA | |
235 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio in" << std::endl; | |
236 #endif | |
237 m_audioPortsIn.push_back(i); | |
238 } else { | |
239 #ifdef DEBUG_LADSPA | |
240 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio out" << std::endl; | |
241 #endif | |
242 m_audioPortsOut.push_back(i); | |
243 } | |
244 | |
245 } else if (LADSPA_IS_PORT_CONTROL(m_descriptor->PortDescriptors[i])) { | |
246 | |
247 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) { | |
248 | |
249 #ifdef DEBUG_LADSPA | |
250 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control in" << std::endl; | |
251 #endif | |
252 LADSPA_Data *data = new LADSPA_Data(0.0); | |
253 m_controlPortsIn.push_back( | |
254 std::pair<unsigned long, LADSPA_Data*>(i, data)); | |
255 | |
256 } else { | |
257 | |
258 #ifdef DEBUG_LADSPA | |
259 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control out" << std::endl; | |
260 #endif | |
261 LADSPA_Data *data = new LADSPA_Data(0.0); | |
262 m_controlPortsOut.push_back( | |
263 std::pair<unsigned long, LADSPA_Data*>(i, data)); | |
264 if (!strcmp(m_descriptor->PortNames[i], "latency") || | |
265 !strcmp(m_descriptor->PortNames[i], "_latency")) { | |
266 #ifdef DEBUG_LADSPA | |
267 std::cerr << "Wooo! We have a latency port!" << std::endl; | |
268 #endif | |
269 m_latencyPort = data; | |
270 } | |
271 | |
272 } | |
273 } | |
274 #ifdef DEBUG_LADSPA | |
275 else | |
276 std::cerr << "LADSPAPluginInstance::init - " | |
277 << "unrecognised port type" << std::endl; | |
278 #endif | |
279 } | |
280 | |
281 m_instanceCount = 1; | |
282 | |
283 if (idealChannelCount > 0) { | |
284 if (m_audioPortsIn.size() == 1) { | |
285 // mono plugin: duplicate it if need be | |
286 m_instanceCount = idealChannelCount; | |
287 } | |
288 } | |
289 } | |
290 | |
291 size_t | |
292 LADSPAPluginInstance::getLatency() | |
293 { | |
294 if (m_latencyPort) { | |
295 if (!m_run) { | |
296 for (size_t i = 0; i < getAudioInputCount(); ++i) { | |
297 for (size_t j = 0; j < m_blockSize; ++j) { | |
298 m_inputBuffers[i][j] = 0.f; | |
299 } | |
300 } | |
301 run(Vamp::RealTime::zeroTime); | |
302 } | |
303 if (*m_latencyPort > 0) return (size_t)*m_latencyPort; | |
304 } | |
305 return 0; | |
306 } | |
307 | |
308 void | |
309 LADSPAPluginInstance::silence() | |
310 { | |
311 if (isOK()) { | |
312 deactivate(); | |
313 activate(); | |
314 } | |
315 } | |
316 | |
317 void | |
318 LADSPAPluginInstance::setIdealChannelCount(size_t channels) | |
319 { | |
320 if (m_audioPortsIn.size() != 1 || channels == m_instanceCount) { | |
321 silence(); | |
322 return; | |
323 } | |
324 | |
325 if (isOK()) { | |
326 deactivate(); | |
327 } | |
328 | |
329 //!!! don't we need to reallocate inputBuffers and outputBuffers? | |
330 | |
331 cleanup(); | |
332 m_instanceCount = channels; | |
333 instantiate(m_sampleRate); | |
334 if (isOK()) { | |
335 connectPorts(); | |
336 activate(); | |
337 } | |
338 } | |
339 | |
340 | |
341 LADSPAPluginInstance::~LADSPAPluginInstance() | |
342 { | |
343 #ifdef DEBUG_LADSPA | |
344 std::cerr << "LADSPAPluginInstance::~LADSPAPluginInstance" << std::endl; | |
345 #endif | |
346 | |
347 if (m_instanceHandles.size() != 0) { // "isOK()" | |
348 deactivate(); | |
349 } | |
350 | |
351 cleanup(); | |
352 | |
353 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) | |
354 delete m_controlPortsIn[i].second; | |
355 | |
356 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) | |
357 delete m_controlPortsOut[i].second; | |
358 | |
359 m_controlPortsIn.clear(); | |
360 m_controlPortsOut.clear(); | |
361 | |
362 if (m_ownBuffers) { | |
363 for (size_t i = 0; i < m_instanceCount * m_audioPortsIn.size(); ++i) { | |
364 delete[] m_inputBuffers[i]; | |
365 } | |
366 for (size_t i = 0; i < m_instanceCount * m_audioPortsOut.size(); ++i) { | |
367 delete[] m_outputBuffers[i]; | |
368 } | |
369 | |
370 delete[] m_inputBuffers; | |
371 delete[] m_outputBuffers; | |
372 } | |
373 | |
374 m_audioPortsIn.clear(); | |
375 m_audioPortsOut.clear(); | |
376 } | |
377 | |
378 | |
379 void | |
380 LADSPAPluginInstance::instantiate(unsigned long sampleRate) | |
381 { | |
382 #ifdef DEBUG_LADSPA | |
383 std::cout << "LADSPAPluginInstance::instantiate - plugin unique id = " | |
384 << m_descriptor->UniqueID << std::endl; | |
385 #endif | |
386 if (!m_descriptor) return; | |
387 | |
388 if (!m_descriptor->instantiate) { | |
389 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID | |
390 << ":" << m_descriptor->Label | |
391 << " has no instantiate method!" << std::endl; | |
392 return; | |
393 } | |
394 | |
395 for (size_t i = 0; i < m_instanceCount; ++i) { | |
396 m_instanceHandles.push_back | |
397 (m_descriptor->instantiate(m_descriptor, sampleRate)); | |
398 } | |
399 } | |
400 | |
401 void | |
402 LADSPAPluginInstance::activate() | |
403 { | |
404 if (!m_descriptor || !m_descriptor->activate) return; | |
405 | |
406 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); | |
407 hi != m_instanceHandles.end(); ++hi) { | |
408 m_descriptor->activate(*hi); | |
409 } | |
410 } | |
411 | |
412 void | |
413 LADSPAPluginInstance::connectPorts() | |
414 { | |
415 if (!m_descriptor || !m_descriptor->connect_port) return; | |
416 | |
417 assert(sizeof(LADSPA_Data) == sizeof(float)); | |
418 assert(sizeof(sample_t) == sizeof(float)); | |
419 | |
420 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory); | |
421 int inbuf = 0, outbuf = 0; | |
422 | |
423 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); | |
424 hi != m_instanceHandles.end(); ++hi) { | |
425 | |
426 for (unsigned int i = 0; i < m_audioPortsIn.size(); ++i) { | |
427 m_descriptor->connect_port(*hi, | |
428 m_audioPortsIn[i], | |
429 (LADSPA_Data *)m_inputBuffers[inbuf]); | |
430 ++inbuf; | |
431 } | |
432 | |
433 for (unsigned int i = 0; i < m_audioPortsOut.size(); ++i) { | |
434 m_descriptor->connect_port(*hi, | |
435 m_audioPortsOut[i], | |
436 (LADSPA_Data *)m_outputBuffers[outbuf]); | |
437 ++outbuf; | |
438 } | |
439 | |
440 // If there is more than one instance, they all share the same | |
441 // control port ins (and outs, for the moment, because we | |
442 // don't actually do anything with the outs anyway -- but they | |
443 // do have to be connected as the plugin can't know if they're | |
444 // not and will write to them anyway). | |
445 | |
446 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) { | |
447 m_descriptor->connect_port(*hi, | |
448 m_controlPortsIn[i].first, | |
449 m_controlPortsIn[i].second); | |
450 if (f) { | |
451 float defaultValue = f->getPortDefault | |
452 (m_descriptor, m_controlPortsIn[i].first); | |
453 *m_controlPortsIn[i].second = defaultValue; | |
454 } | |
455 } | |
456 | |
457 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) { | |
458 m_descriptor->connect_port(*hi, | |
459 m_controlPortsOut[i].first, | |
460 m_controlPortsOut[i].second); | |
461 } | |
462 } | |
463 } | |
464 | |
465 unsigned int | |
466 LADSPAPluginInstance::getParameterCount() const | |
467 { | |
468 return m_controlPortsIn.size(); | |
469 } | |
470 | |
471 void | |
472 LADSPAPluginInstance::setParameterValue(unsigned int parameter, float value) | |
473 { | |
474 if (parameter >= m_controlPortsIn.size()) return; | |
475 | |
476 unsigned int portNumber = m_controlPortsIn[parameter].first; | |
477 | |
478 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory); | |
479 if (f) { | |
480 if (value < f->getPortMinimum(m_descriptor, portNumber)) { | |
481 value = f->getPortMinimum(m_descriptor, portNumber); | |
482 } | |
483 if (value > f->getPortMaximum(m_descriptor, portNumber)) { | |
484 value = f->getPortMaximum(m_descriptor, portNumber); | |
485 } | |
486 } | |
487 | |
488 (*m_controlPortsIn[parameter].second) = value; | |
489 } | |
490 | |
491 float | |
492 LADSPAPluginInstance::getControlOutputValue(size_t output) const | |
493 { | |
494 if (output > m_controlPortsOut.size()) return 0.0; | |
495 return (*m_controlPortsOut[output].second); | |
496 } | |
497 | |
498 float | |
499 LADSPAPluginInstance::getParameterValue(unsigned int parameter) const | |
500 { | |
501 if (parameter >= m_controlPortsIn.size()) return 0.0; | |
502 return (*m_controlPortsIn[parameter].second); | |
503 } | |
504 | |
505 float | |
506 LADSPAPluginInstance::getParameterDefault(unsigned int parameter) const | |
507 { | |
508 if (parameter >= m_controlPortsIn.size()) return 0.0; | |
509 | |
510 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory); | |
511 if (f) { | |
512 return f->getPortDefault(m_descriptor, m_controlPortsIn[parameter].first); | |
513 } else { | |
514 return 0.0f; | |
515 } | |
516 } | |
517 | |
518 void | |
519 LADSPAPluginInstance::run(const Vamp::RealTime &) | |
520 { | |
521 if (!m_descriptor || !m_descriptor->run) return; | |
522 | |
523 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); | |
524 hi != m_instanceHandles.end(); ++hi) { | |
525 | |
526 m_descriptor->run(*hi, m_blockSize); | |
527 } | |
528 | |
529 m_run = true; | |
530 } | |
531 | |
532 void | |
533 LADSPAPluginInstance::deactivate() | |
534 { | |
535 if (!m_descriptor || !m_descriptor->deactivate) return; | |
536 | |
537 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); | |
538 hi != m_instanceHandles.end(); ++hi) { | |
539 m_descriptor->deactivate(*hi); | |
540 } | |
541 } | |
542 | |
543 void | |
544 LADSPAPluginInstance::cleanup() | |
545 { | |
546 if (!m_descriptor) return; | |
547 | |
548 if (!m_descriptor->cleanup) { | |
549 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID | |
550 << ":" << m_descriptor->Label | |
551 << " has no cleanup method!" << std::endl; | |
552 return; | |
553 } | |
554 | |
555 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); | |
556 hi != m_instanceHandles.end(); ++hi) { | |
557 m_descriptor->cleanup(*hi); | |
558 } | |
559 | |
560 m_instanceHandles.clear(); | |
561 } | |
562 | |
563 |