LADSPAPluginInstance.cpp
Go to the documentation of this file.
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 
37  int clientId,
38  QString identifier,
39  int position,
40  sv_samplerate_t sampleRate,
41  int 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(nullptr),
52  m_run(false),
53  m_bypassed(false)
54 {
55  init(idealChannelCount);
56 
57  if (m_audioPortsIn.size() == 0) {
58  m_inputBuffers = nullptr;
59  } else {
61  }
62 
63  if (m_audioPortsOut.size() == 0) {
64  m_outputBuffers = nullptr;
65  } else {
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
87 {
88  return m_descriptor->Label;
89 }
90 
91 std::string
93 {
94  return m_descriptor->Name;
95 }
96 
97 std::string
99 {
100  return "";
101 }
102 
103 std::string
105 {
106  return m_descriptor->Maker;
107 }
108 
109 int
111 {
112  return -1;
113 }
114 
115 std::string
117 {
118  return m_descriptor->Copyright;
119 }
120 
121 LADSPAPluginInstance::ParameterList
123 {
124  ParameterList list;
125  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
126  if (!f) return list;
127 
128  for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
129 
130  ParameterDescriptor pd;
131  unsigned int pn = m_controlPortsIn[i].first;
132 
133  pd.identifier = m_descriptor->PortNames[pn];
134  pd.name = pd.identifier;
135  pd.description = "";
136  pd.minValue = f->getPortMinimum(m_descriptor, pn);
137  pd.maxValue = f->getPortMaximum(m_descriptor, pn);
138  pd.defaultValue = f->getPortDefault(m_descriptor, pn);
139 
140  float q = f->getPortQuantization(m_descriptor, pn);
141  if (q == 0.0) {
142  pd.isQuantized = false;
143  } else {
144  pd.isQuantized = true;
145  pd.quantizeStep = q;
146  }
147 
148  bool haveLabels = false;
149 
150 #ifdef HAVE_LRDF
151  if (pd.isQuantized && pd.quantizeStep == 1.0) {
152 
153  lrdf_defaults *defaults =
154  lrdf_get_scale_values(m_descriptor->UniqueID, pn);
155 
156  if (defaults) {
157  if (defaults->count > 0) {
158  std::map<int, std::string> values;
159  int v = 0;
160  for (size_t i = 0; i < defaults->count; ++i) {
161  v = int(lrintf(fabsf(defaults->items[i].value)));
162  values[v] = defaults->items[i].label;
163  }
164  for (int i = 0; i <= v; ++i) {
165  pd.valueNames.push_back(values[i]);
166  }
167  haveLabels = true;
168  }
169  lrdf_free_setting_values(defaults);
170  }
171  }
172 #endif
173 
174  if (haveLabels) {
175  pd.name = QString(pd.name.c_str())
176  .replace(QRegExp("\\([^\\(\\)]+=[^\\(\\)]+\\)$"), "")
177  .toStdString();
178  } else {
179  static QRegExp unitRE("[\\[\\(]([A-Za-z0-9/]+)[\\)\\]]$");
180  if (unitRE.indexIn(pd.name.c_str()) >= 0) {
181  pd.unit = unitRE.cap(1).toStdString();
182  pd.name = QString(pd.name.c_str())
183  .replace(unitRE, "").toStdString();
184  }
185  }
186 
187  list.push_back(pd);
188  }
189 
190  return list;
191 }
192 
193 float
195 {
196  for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
197  if (id == m_descriptor->PortNames[m_controlPortsIn[i].first]) {
198  return getParameterValue(i);
199  }
200  }
201 
202  return 0.0;
203 }
204 
205 void
206 LADSPAPluginInstance::setParameter(std::string id, float value)
207 {
208  for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
209  if (id == m_descriptor->PortNames[m_controlPortsIn[i].first]) {
210 #ifdef DEBUG_LADSPA
211  SVDEBUG << "LADSPAPluginInstance::setParameter: Found id "
212  << id << " at control port " << i << endl;
213 #endif
214  setParameterValue(i, value);
215  break;
216  }
217  }
218 }
219 
220 void
221 LADSPAPluginInstance::init(int idealChannelCount)
222 {
223 #ifdef DEBUG_LADSPA
224  SVDEBUG << "LADSPAPluginInstance::init(" << idealChannelCount << "): plugin has "
225  << m_descriptor->PortCount << " ports" << endl;
226 #endif
227 
228  // Discover ports numbers and identities
229  //
230  for (int i = 0; i < (int)m_descriptor->PortCount; ++i) {
231 
232  if (LADSPA_IS_PORT_AUDIO(m_descriptor->PortDescriptors[i])) {
233 
234  if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
235 #ifdef DEBUG_LADSPA
236  SVDEBUG << "LADSPAPluginInstance::init: port " << i << " is audio in" << endl;
237 #endif
238  m_audioPortsIn.push_back(i);
239  } else {
240 #ifdef DEBUG_LADSPA
241  SVDEBUG << "LADSPAPluginInstance::init: port " << i << " is audio out" << endl;
242 #endif
243  m_audioPortsOut.push_back(i);
244  }
245 
246  } else if (LADSPA_IS_PORT_CONTROL(m_descriptor->PortDescriptors[i])) {
247 
248  if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
249 
250 #ifdef DEBUG_LADSPA
251  SVDEBUG << "LADSPAPluginInstance::init: port " << i << " is control in" << endl;
252 #endif
253  LADSPA_Data *data = new LADSPA_Data(0.0);
254  m_controlPortsIn.push_back(
255  std::pair<unsigned long, LADSPA_Data*>(i, data));
256 
257  } else {
258 
259 #ifdef DEBUG_LADSPA
260  SVDEBUG << "LADSPAPluginInstance::init: port " << i << " is control out" << endl;
261 #endif
262  LADSPA_Data *data = new LADSPA_Data(0.0);
263  m_controlPortsOut.push_back(
264  std::pair<unsigned long, LADSPA_Data*>(i, data));
265  if (!strcmp(m_descriptor->PortNames[i], "latency") ||
266  !strcmp(m_descriptor->PortNames[i], "_latency")) {
267 #ifdef DEBUG_LADSPA
268  cerr << "Wooo! We have a latency port!" << endl;
269 #endif
270  m_latencyPort = data;
271  }
272 
273  }
274  }
275 #ifdef DEBUG_LADSPA
276  else
277  SVDEBUG << "LADSPAPluginInstance::init - "
278  << "unrecognised port type" << endl;
279 #endif
280  }
281 
282  m_instanceCount = 1;
283 
284  if (idealChannelCount > 0) {
285  if (m_audioPortsIn.size() == 1) {
286  // mono plugin: duplicate it if need be
287  m_instanceCount = idealChannelCount;
288  }
289  }
290 }
291 
294 {
295  if (m_latencyPort) {
296  if (!m_run) {
297  for (int i = 0; i < getAudioInputCount(); ++i) {
298  for (int j = 0; j < m_blockSize; ++j) {
299  m_inputBuffers[i][j] = 0.f;
300  }
301  }
302  run(Vamp::RealTime::zeroTime);
303  }
304  if (*m_latencyPort > 0) return (sv_frame_t)*m_latencyPort;
305  }
306  return 0;
307 }
308 
309 void
311 {
312  if (isOK()) {
313  deactivate();
314  activate();
315  }
316 }
317 
318 void
320 {
321  if (m_audioPortsIn.size() != 1 || channels == m_instanceCount) {
322  silence();
323  return;
324  }
325 
326  if (isOK()) {
327  deactivate();
328  }
329 
331 
332  cleanup();
333  m_instanceCount = channels;
335  if (isOK()) {
336  connectPorts();
337  activate();
338  }
339 }
340 
341 
343 {
344 #ifdef DEBUG_LADSPA
345  SVDEBUG << "LADSPAPluginInstance::~LADSPAPluginInstance" << endl;
346 #endif
347 
348  if (m_instanceHandles.size() != 0) { // "isOK()"
349  deactivate();
350  }
351 
352  cleanup();
353 
354  for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i)
355  delete m_controlPortsIn[i].second;
356 
357  for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i)
358  delete m_controlPortsOut[i].second;
359 
360  m_controlPortsIn.clear();
361  m_controlPortsOut.clear();
362 
363  if (m_ownBuffers) {
364  for (size_t i = 0; i < m_instanceCount * m_audioPortsIn.size(); ++i) {
365  delete[] m_inputBuffers[i];
366  }
367  for (size_t i = 0; i < m_instanceCount * m_audioPortsOut.size(); ++i) {
368  delete[] m_outputBuffers[i];
369  }
370 
371  delete[] m_inputBuffers;
372  delete[] m_outputBuffers;
373  }
374 
375  m_audioPortsIn.clear();
376  m_audioPortsOut.clear();
377 }
378 
379 
380 void
382 {
383  if (!m_descriptor) return;
384 
385 #ifdef DEBUG_LADSPA
386  cout << "LADSPAPluginInstance::instantiate - plugin unique id = "
387  << m_descriptor->UniqueID << endl;
388 #endif
389 
390  if (!m_descriptor->instantiate) {
391  cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
392  << ":" << m_descriptor->Label
393  << " has no instantiate method!" << endl;
394  return;
395  }
396 
397  unsigned long pluginRate = (unsigned long)(sampleRate);
398  if (sampleRate != sv_samplerate_t(pluginRate)) {
399  cerr << "LADSPAPluginInstance: WARNING: Non-integer sample rate "
400  << sampleRate << " presented, rounding to " << pluginRate
401  << endl;
402  }
403 
404  for (int i = 0; i < m_instanceCount; ++i) {
405  m_instanceHandles.push_back
406  (m_descriptor->instantiate(m_descriptor, pluginRate));
407  }
408 }
409 
410 void
412 {
413  if (!m_descriptor || !m_descriptor->activate) return;
414 
415  for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
416  hi != m_instanceHandles.end(); ++hi) {
417  m_descriptor->activate(*hi);
418  }
419 }
420 
421 void
423 {
424  if (!m_descriptor || !m_descriptor->connect_port) return;
425 
426  assert(sizeof(LADSPA_Data) == sizeof(float));
427  assert(sizeof(sample_t) == sizeof(float));
428 
429  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
430  int inbuf = 0, outbuf = 0;
431 
432  for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
433  hi != m_instanceHandles.end(); ++hi) {
434 
435  for (unsigned int i = 0; i < m_audioPortsIn.size(); ++i) {
436  m_descriptor->connect_port(*hi,
437  m_audioPortsIn[i],
438  (LADSPA_Data *)m_inputBuffers[inbuf]);
439  ++inbuf;
440  }
441 
442  for (unsigned int i = 0; i < m_audioPortsOut.size(); ++i) {
443  m_descriptor->connect_port(*hi,
444  m_audioPortsOut[i],
445  (LADSPA_Data *)m_outputBuffers[outbuf]);
446  ++outbuf;
447  }
448 
449  // If there is more than one instance, they all share the same
450  // control port ins (and outs, for the moment, because we
451  // don't actually do anything with the outs anyway -- but they
452  // do have to be connected as the plugin can't know if they're
453  // not and will write to them anyway).
454 
455  for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
456  m_descriptor->connect_port(*hi,
457  m_controlPortsIn[i].first,
458  m_controlPortsIn[i].second);
459  if (f) {
460  float defaultValue = f->getPortDefault
461  (m_descriptor, m_controlPortsIn[i].first);
462  *m_controlPortsIn[i].second = defaultValue;
463  }
464  }
465 
466  for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) {
467  m_descriptor->connect_port(*hi,
468  m_controlPortsOut[i].first,
469  m_controlPortsOut[i].second);
470  }
471  }
472 }
473 
474 int
476 {
477  return (int)m_controlPortsIn.size();
478 }
479 
480 void
481 LADSPAPluginInstance::setParameterValue(int parameter, float value)
482 {
483  if (!in_range_for(m_controlPortsIn, parameter)) return;
484 
485  unsigned int portNumber = m_controlPortsIn[parameter].first;
486 
487  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
488  if (f) {
489  if (value < f->getPortMinimum(m_descriptor, portNumber)) {
490  value = f->getPortMinimum(m_descriptor, portNumber);
491  }
492  if (value > f->getPortMaximum(m_descriptor, portNumber)) {
493  value = f->getPortMaximum(m_descriptor, portNumber);
494  }
495  }
496 
497  (*m_controlPortsIn[parameter].second) = value;
498 }
499 
500 float
502 {
503  if (!in_range_for(m_controlPortsOut, output)) return 0.0;
504  return (*m_controlPortsOut[output].second);
505 }
506 
507 float
509 {
510  if (!in_range_for(m_controlPortsIn, parameter)) return 0.0;
511  return (*m_controlPortsIn[parameter].second);
512 }
513 
514 float
516 {
517  if (!in_range_for(m_controlPortsIn, parameter)) return 0.0;
518 
519  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
520  if (f) {
521  return f->getPortDefault(m_descriptor, m_controlPortsIn[parameter].first);
522  } else {
523  return 0.0f;
524  }
525 }
526 
527 int
529 {
530  if (!in_range_for(m_controlPortsIn, parameter)) return 0.0;
531 
532  LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
533  if (f) {
534  return f->getPortDisplayHint(m_descriptor, m_controlPortsIn[parameter].first);
535  } else {
536  return PortHint::NoHint;
537  }
538 }
539 
540 void
542 {
543  if (!m_descriptor || !m_descriptor->run) return;
544 
545  if (count == 0) count = m_blockSize;
546 
547  for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
548  hi != m_instanceHandles.end(); ++hi) {
549 
550  m_descriptor->run(*hi, count);
551  }
552 
553  m_run = true;
554 }
555 
556 void
558 {
559  if (!m_descriptor || !m_descriptor->deactivate) return;
560 
561  for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
562  hi != m_instanceHandles.end(); ++hi) {
563  m_descriptor->deactivate(*hi);
564  }
565 }
566 
567 void
569 {
570  if (!m_descriptor) return;
571 
572  if (!m_descriptor->cleanup) {
573  cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
574  << ":" << m_descriptor->Label
575  << " has no cleanup method!" << endl;
576  return;
577  }
578 
579  for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
580  hi != m_instanceHandles.end(); ++hi) {
581  m_descriptor->cleanup(*hi);
582  }
583 
584  m_instanceHandles.clear();
585 }
586 
587 
float getControlOutputValue(int n) const override
double sv_samplerate_t
Sample rate.
Definition: BaseTypes.h:51
float getParameterValue(int parameter) const override
int getPluginVersion() const override
std::vector< std::pair< int, LADSPA_Data * > > m_controlPortsOut
std::string getDescription() const override
bool isOK() const override
int getParameterCount() const override
int getPortDisplayHint(const LADSPA_Descriptor *, int port)
int64_t sv_frame_t
Frame index, the unit of our time axis.
Definition: BaseTypes.h:31
std::vector< LADSPA_Handle > m_instanceHandles
sv_samplerate_t m_sampleRate
static const int NoHint
LADSPAPluginInstance(RealTimePluginFactory *factory, int client, QString identifier, int position, sv_samplerate_t sampleRate, int blockSize, int idealChannelCount, const LADSPA_Descriptor *descriptor)
std::string getIdentifier() const override
void setParameterValue(int parameter, float value) override
float getPortDefault(const LADSPA_Descriptor *, int port)
int getAudioInputCount() const override
int getParameterDisplayHint(int parameter) const override
static sv_samplerate_t m_sampleRate
float getPortMaximum(const LADSPA_Descriptor *, int port)
sv_frame_t getLatency() override
float getPortQuantization(const LADSPA_Descriptor *, int port)
void instantiate(sv_samplerate_t sampleRate)
float getParameterDefault(int parameter) const override
ParameterList getParameterDescriptors() const override
std::string getCopyright() const override
bool in_range_for(const C &container, T i)
Check whether an integer index is in range for a container, avoiding overflows and signed/unsigned co...
Definition: BaseTypes.h:37
#define SVDEBUG
Definition: Debug.h:106
void setIdealChannelCount(int channels) override
void init(int idealChannelCount=0)
std::vector< int > m_audioPortsOut
RealTimePluginFactory * m_factory
std::vector< int > m_audioPortsIn
std::string getName() const override
void run(const RealTime &rt, int count=0) override
Run for one block, starting at the given time.
std::string getMaker() const override
float getParameter(std::string) const override
const LADSPA_Descriptor * m_descriptor
std::vector< std::pair< int, LADSPA_Data * > > m_controlPortsIn
float getPortMinimum(const LADSPA_Descriptor *, int port)
RealTime represents time values to nanosecond precision with accurate arithmetic and frame-rate conve...
Definition: RealTime.h:42
void setParameter(std::string, float) override