Chris@0
|
1 /* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */
|
Chris@0
|
2
|
Chris@0
|
3 /*
|
Chris@0
|
4 A waveform viewer and audio annotation editor.
|
Chris@0
|
5 Chris Cannam, Queen Mary University of London, 2005
|
Chris@0
|
6
|
Chris@0
|
7 This is experimental software. Not for distribution.
|
Chris@0
|
8 */
|
Chris@0
|
9
|
Chris@0
|
10 /*
|
Chris@0
|
11 This is a modified version of a source file from the
|
Chris@0
|
12 Rosegarden MIDI and audio sequencer and notation editor.
|
Chris@0
|
13 This file copyright 2000-2005 Chris Cannam and Richard Bown.
|
Chris@0
|
14 */
|
Chris@0
|
15
|
Chris@0
|
16 #include <iostream>
|
Chris@0
|
17 #include <cassert>
|
Chris@0
|
18
|
Chris@0
|
19 #include "LADSPAPluginInstance.h"
|
Chris@0
|
20 #include "LADSPAPluginFactory.h"
|
Chris@0
|
21
|
Chris@0
|
22 //#define DEBUG_LADSPA 1
|
Chris@0
|
23
|
Chris@0
|
24
|
Chris@0
|
25 LADSPAPluginInstance::LADSPAPluginInstance(RealTimePluginFactory *factory,
|
Chris@0
|
26 int clientId,
|
Chris@0
|
27 QString identifier,
|
Chris@0
|
28 int position,
|
Chris@0
|
29 unsigned long sampleRate,
|
Chris@0
|
30 size_t blockSize,
|
Chris@0
|
31 int idealChannelCount,
|
Chris@0
|
32 const LADSPA_Descriptor* descriptor) :
|
Chris@0
|
33 RealTimePluginInstance(factory, identifier),
|
Chris@0
|
34 m_client(clientId),
|
Chris@0
|
35 m_position(position),
|
Chris@0
|
36 m_instanceCount(0),
|
Chris@0
|
37 m_descriptor(descriptor),
|
Chris@0
|
38 m_blockSize(blockSize),
|
Chris@0
|
39 m_sampleRate(sampleRate),
|
Chris@0
|
40 m_latencyPort(0),
|
Chris@0
|
41 m_run(false),
|
Chris@0
|
42 m_bypassed(false)
|
Chris@0
|
43 {
|
Chris@0
|
44 init(idealChannelCount);
|
Chris@0
|
45
|
Chris@0
|
46 m_inputBuffers = new sample_t*[m_instanceCount * m_audioPortsIn.size()];
|
Chris@0
|
47 m_outputBuffers = new sample_t*[m_instanceCount * m_audioPortsOut.size()];
|
Chris@0
|
48
|
Chris@0
|
49 for (size_t i = 0; i < m_instanceCount * m_audioPortsIn.size(); ++i) {
|
Chris@0
|
50 m_inputBuffers[i] = new sample_t[blockSize];
|
Chris@0
|
51 }
|
Chris@0
|
52 for (size_t i = 0; i < m_instanceCount * m_audioPortsOut.size(); ++i) {
|
Chris@0
|
53 m_outputBuffers[i] = new sample_t[blockSize];
|
Chris@0
|
54 }
|
Chris@0
|
55
|
Chris@0
|
56 m_ownBuffers = true;
|
Chris@0
|
57
|
Chris@0
|
58 instantiate(sampleRate);
|
Chris@0
|
59 if (isOK()) {
|
Chris@0
|
60 connectPorts();
|
Chris@0
|
61 activate();
|
Chris@0
|
62 }
|
Chris@0
|
63 }
|
Chris@0
|
64
|
Chris@0
|
65 LADSPAPluginInstance::LADSPAPluginInstance(RealTimePluginFactory *factory,
|
Chris@0
|
66 int clientId,
|
Chris@0
|
67 QString identifier,
|
Chris@0
|
68 int position,
|
Chris@0
|
69 unsigned long sampleRate,
|
Chris@0
|
70 size_t blockSize,
|
Chris@0
|
71 sample_t **inputBuffers,
|
Chris@0
|
72 sample_t **outputBuffers,
|
Chris@0
|
73 const LADSPA_Descriptor* descriptor) :
|
Chris@0
|
74 RealTimePluginInstance(factory, identifier),
|
Chris@0
|
75 m_client(clientId),
|
Chris@0
|
76 m_position(position),
|
Chris@0
|
77 m_instanceCount(0),
|
Chris@0
|
78 m_descriptor(descriptor),
|
Chris@0
|
79 m_blockSize(blockSize),
|
Chris@0
|
80 m_inputBuffers(inputBuffers),
|
Chris@0
|
81 m_outputBuffers(outputBuffers),
|
Chris@0
|
82 m_ownBuffers(false),
|
Chris@0
|
83 m_sampleRate(sampleRate),
|
Chris@0
|
84 m_latencyPort(0),
|
Chris@0
|
85 m_run(false),
|
Chris@0
|
86 m_bypassed(false)
|
Chris@0
|
87 {
|
Chris@0
|
88 init();
|
Chris@0
|
89
|
Chris@0
|
90 instantiate(sampleRate);
|
Chris@0
|
91 if (isOK()) {
|
Chris@0
|
92 connectPorts();
|
Chris@0
|
93 activate();
|
Chris@0
|
94 }
|
Chris@0
|
95 }
|
Chris@0
|
96
|
Chris@0
|
97
|
Chris@0
|
98 void
|
Chris@0
|
99 LADSPAPluginInstance::init(int idealChannelCount)
|
Chris@0
|
100 {
|
Chris@0
|
101 #ifdef DEBUG_LADSPA
|
Chris@0
|
102 std::cerr << "LADSPAPluginInstance::init(" << idealChannelCount << "): plugin has "
|
Chris@0
|
103 << m_descriptor->PortCount << " ports" << std::endl;
|
Chris@0
|
104 #endif
|
Chris@0
|
105
|
Chris@0
|
106 // Discover ports numbers and identities
|
Chris@0
|
107 //
|
Chris@0
|
108 for (unsigned long i = 0; i < m_descriptor->PortCount; ++i)
|
Chris@0
|
109 {
|
Chris@0
|
110 if (LADSPA_IS_PORT_AUDIO(m_descriptor->PortDescriptors[i]))
|
Chris@0
|
111 {
|
Chris@0
|
112 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
|
Chris@0
|
113 #ifdef DEBUG_LADSPA
|
Chris@0
|
114 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio in" << std::endl;
|
Chris@0
|
115 #endif
|
Chris@0
|
116 m_audioPortsIn.push_back(i);
|
Chris@0
|
117 } else {
|
Chris@0
|
118 #ifdef DEBUG_LADSPA
|
Chris@0
|
119 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio out" << std::endl;
|
Chris@0
|
120 #endif
|
Chris@0
|
121 m_audioPortsOut.push_back(i);
|
Chris@0
|
122 }
|
Chris@0
|
123 }
|
Chris@0
|
124 else
|
Chris@0
|
125 if (LADSPA_IS_PORT_CONTROL(m_descriptor->PortDescriptors[i]))
|
Chris@0
|
126 {
|
Chris@0
|
127 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
|
Chris@0
|
128 #ifdef DEBUG_LADSPA
|
Chris@0
|
129 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control in" << std::endl;
|
Chris@0
|
130 #endif
|
Chris@0
|
131 LADSPA_Data *data = new LADSPA_Data(0.0);
|
Chris@0
|
132 m_controlPortsIn.push_back(
|
Chris@0
|
133 std::pair<unsigned long, LADSPA_Data*>(i, data));
|
Chris@0
|
134 } else {
|
Chris@0
|
135 #ifdef DEBUG_LADSPA
|
Chris@0
|
136 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control out" << std::endl;
|
Chris@0
|
137 #endif
|
Chris@0
|
138 LADSPA_Data *data = new LADSPA_Data(0.0);
|
Chris@0
|
139 m_controlPortsOut.push_back(
|
Chris@0
|
140 std::pair<unsigned long, LADSPA_Data*>(i, data));
|
Chris@0
|
141 if (!strcmp(m_descriptor->PortNames[i], "latency") ||
|
Chris@0
|
142 !strcmp(m_descriptor->PortNames[i], "_latency")) {
|
Chris@0
|
143 #ifdef DEBUG_LADSPA
|
Chris@0
|
144 std::cerr << "Wooo! We have a latency port!" << std::endl;
|
Chris@0
|
145 #endif
|
Chris@0
|
146 m_latencyPort = data;
|
Chris@0
|
147 }
|
Chris@0
|
148 }
|
Chris@0
|
149 }
|
Chris@0
|
150 #ifdef DEBUG_LADSPA
|
Chris@0
|
151 else
|
Chris@0
|
152 std::cerr << "LADSPAPluginInstance::init - "
|
Chris@0
|
153 << "unrecognised port type" << std::endl;
|
Chris@0
|
154 #endif
|
Chris@0
|
155 }
|
Chris@0
|
156
|
Chris@0
|
157 m_instanceCount = 1;
|
Chris@0
|
158
|
Chris@0
|
159 if (idealChannelCount > 0) {
|
Chris@0
|
160 if (m_audioPortsIn.size() == 1) {
|
Chris@0
|
161 // mono plugin: duplicate it if need be
|
Chris@0
|
162 m_instanceCount = idealChannelCount;
|
Chris@0
|
163 }
|
Chris@0
|
164 }
|
Chris@0
|
165 }
|
Chris@0
|
166
|
Chris@0
|
167 size_t
|
Chris@0
|
168 LADSPAPluginInstance::getLatency()
|
Chris@0
|
169 {
|
Chris@0
|
170 if (m_latencyPort) {
|
Chris@0
|
171 if (!m_run) run(RealTime::zeroTime);
|
Chris@0
|
172 if (*m_latencyPort > 0) return (size_t)*m_latencyPort;
|
Chris@0
|
173 }
|
Chris@0
|
174 return 0;
|
Chris@0
|
175 }
|
Chris@0
|
176
|
Chris@0
|
177 void
|
Chris@0
|
178 LADSPAPluginInstance::silence()
|
Chris@0
|
179 {
|
Chris@0
|
180 if (isOK()) {
|
Chris@0
|
181 deactivate();
|
Chris@0
|
182 activate();
|
Chris@0
|
183 }
|
Chris@0
|
184 }
|
Chris@0
|
185
|
Chris@0
|
186 void
|
Chris@0
|
187 LADSPAPluginInstance::setIdealChannelCount(size_t channels)
|
Chris@0
|
188 {
|
Chris@0
|
189 if (m_audioPortsIn.size() != 1 || channels == m_instanceCount) {
|
Chris@0
|
190 silence();
|
Chris@0
|
191 return;
|
Chris@0
|
192 }
|
Chris@0
|
193
|
Chris@0
|
194 if (isOK()) {
|
Chris@0
|
195 deactivate();
|
Chris@0
|
196 }
|
Chris@0
|
197
|
Chris@0
|
198 //!!! don't we need to reallocate inputBuffers and outputBuffers?
|
Chris@0
|
199
|
Chris@0
|
200 cleanup();
|
Chris@0
|
201 m_instanceCount = channels;
|
Chris@0
|
202 instantiate(m_sampleRate);
|
Chris@0
|
203 if (isOK()) {
|
Chris@0
|
204 connectPorts();
|
Chris@0
|
205 activate();
|
Chris@0
|
206 }
|
Chris@0
|
207 }
|
Chris@0
|
208
|
Chris@0
|
209
|
Chris@0
|
210 LADSPAPluginInstance::~LADSPAPluginInstance()
|
Chris@0
|
211 {
|
Chris@0
|
212 #ifdef DEBUG_LADSPA
|
Chris@0
|
213 std::cerr << "LADSPAPluginInstance::~LADSPAPluginInstance" << std::endl;
|
Chris@0
|
214 #endif
|
Chris@0
|
215
|
Chris@0
|
216 if (m_instanceHandles.size() != 0) { // "isOK()"
|
Chris@0
|
217 deactivate();
|
Chris@0
|
218 }
|
Chris@0
|
219
|
Chris@0
|
220 cleanup();
|
Chris@0
|
221
|
Chris@0
|
222 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i)
|
Chris@0
|
223 delete m_controlPortsIn[i].second;
|
Chris@0
|
224
|
Chris@0
|
225 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i)
|
Chris@0
|
226 delete m_controlPortsOut[i].second;
|
Chris@0
|
227
|
Chris@0
|
228 m_controlPortsIn.clear();
|
Chris@0
|
229 m_controlPortsOut.clear();
|
Chris@0
|
230
|
Chris@0
|
231 if (m_ownBuffers) {
|
Chris@0
|
232 for (size_t i = 0; i < m_audioPortsIn.size(); ++i) {
|
Chris@0
|
233 delete[] m_inputBuffers[i];
|
Chris@0
|
234 }
|
Chris@0
|
235 for (size_t i = 0; i < m_audioPortsOut.size(); ++i) {
|
Chris@0
|
236 delete[] m_outputBuffers[i];
|
Chris@0
|
237 }
|
Chris@0
|
238
|
Chris@0
|
239 delete[] m_inputBuffers;
|
Chris@0
|
240 delete[] m_outputBuffers;
|
Chris@0
|
241 }
|
Chris@0
|
242
|
Chris@0
|
243 m_audioPortsIn.clear();
|
Chris@0
|
244 m_audioPortsOut.clear();
|
Chris@0
|
245 }
|
Chris@0
|
246
|
Chris@0
|
247
|
Chris@0
|
248 void
|
Chris@0
|
249 LADSPAPluginInstance::instantiate(unsigned long sampleRate)
|
Chris@0
|
250 {
|
Chris@0
|
251 #ifdef DEBUG_LADSPA
|
Chris@0
|
252 std::cout << "LADSPAPluginInstance::instantiate - plugin unique id = "
|
Chris@0
|
253 << m_descriptor->UniqueID << std::endl;
|
Chris@0
|
254 #endif
|
Chris@0
|
255 if (!m_descriptor) return;
|
Chris@0
|
256
|
Chris@0
|
257 if (!m_descriptor->instantiate) {
|
Chris@0
|
258 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
|
Chris@0
|
259 << ":" << m_descriptor->Label
|
Chris@0
|
260 << " has no instantiate method!" << std::endl;
|
Chris@0
|
261 return;
|
Chris@0
|
262 }
|
Chris@0
|
263
|
Chris@0
|
264 for (size_t i = 0; i < m_instanceCount; ++i) {
|
Chris@0
|
265 m_instanceHandles.push_back
|
Chris@0
|
266 (m_descriptor->instantiate(m_descriptor, sampleRate));
|
Chris@0
|
267 }
|
Chris@0
|
268 }
|
Chris@0
|
269
|
Chris@0
|
270 void
|
Chris@0
|
271 LADSPAPluginInstance::activate()
|
Chris@0
|
272 {
|
Chris@0
|
273 if (!m_descriptor || !m_descriptor->activate) return;
|
Chris@0
|
274
|
Chris@0
|
275 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
|
Chris@0
|
276 hi != m_instanceHandles.end(); ++hi) {
|
Chris@0
|
277 m_descriptor->activate(*hi);
|
Chris@0
|
278 }
|
Chris@0
|
279 }
|
Chris@0
|
280
|
Chris@0
|
281 void
|
Chris@0
|
282 LADSPAPluginInstance::connectPorts()
|
Chris@0
|
283 {
|
Chris@0
|
284 if (!m_descriptor || !m_descriptor->connect_port) return;
|
Chris@0
|
285
|
Chris@0
|
286 assert(sizeof(LADSPA_Data) == sizeof(float));
|
Chris@0
|
287 assert(sizeof(sample_t) == sizeof(float));
|
Chris@0
|
288
|
Chris@0
|
289 int inbuf = 0, outbuf = 0;
|
Chris@0
|
290
|
Chris@0
|
291 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
|
Chris@0
|
292 hi != m_instanceHandles.end(); ++hi) {
|
Chris@0
|
293
|
Chris@0
|
294 for (unsigned int i = 0; i < m_audioPortsIn.size(); ++i) {
|
Chris@0
|
295 m_descriptor->connect_port(*hi,
|
Chris@0
|
296 m_audioPortsIn[i],
|
Chris@0
|
297 (LADSPA_Data *)m_inputBuffers[inbuf]);
|
Chris@0
|
298 ++inbuf;
|
Chris@0
|
299 }
|
Chris@0
|
300
|
Chris@0
|
301 for (unsigned int i = 0; i < m_audioPortsOut.size(); ++i) {
|
Chris@0
|
302 m_descriptor->connect_port(*hi,
|
Chris@0
|
303 m_audioPortsOut[i],
|
Chris@0
|
304 (LADSPA_Data *)m_outputBuffers[outbuf]);
|
Chris@0
|
305 ++outbuf;
|
Chris@0
|
306 }
|
Chris@0
|
307
|
Chris@0
|
308 // If there is more than one instance, they all share the same
|
Chris@0
|
309 // control port ins (and outs, for the moment, because we
|
Chris@0
|
310 // don't actually do anything with the outs anyway -- but they
|
Chris@0
|
311 // do have to be connected as the plugin can't know if they're
|
Chris@0
|
312 // not and will write to them anyway).
|
Chris@0
|
313
|
Chris@0
|
314 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
|
Chris@0
|
315 m_descriptor->connect_port(*hi,
|
Chris@0
|
316 m_controlPortsIn[i].first,
|
Chris@0
|
317 m_controlPortsIn[i].second);
|
Chris@0
|
318 }
|
Chris@0
|
319
|
Chris@0
|
320 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) {
|
Chris@0
|
321 m_descriptor->connect_port(*hi,
|
Chris@0
|
322 m_controlPortsOut[i].first,
|
Chris@0
|
323 m_controlPortsOut[i].second);
|
Chris@0
|
324 }
|
Chris@0
|
325 }
|
Chris@0
|
326 }
|
Chris@0
|
327
|
Chris@0
|
328 unsigned int
|
Chris@0
|
329 LADSPAPluginInstance::getParameterCount() const
|
Chris@0
|
330 {
|
Chris@0
|
331 return m_controlPortsIn.size();
|
Chris@0
|
332 }
|
Chris@0
|
333
|
Chris@0
|
334 void
|
Chris@0
|
335 LADSPAPluginInstance::setParameterValue(unsigned int parameter, float value)
|
Chris@0
|
336 {
|
Chris@0
|
337 if (parameter >= m_controlPortsIn.size()) return;
|
Chris@0
|
338
|
Chris@0
|
339 unsigned int portNumber = m_controlPortsIn[parameter].first;
|
Chris@0
|
340
|
Chris@0
|
341 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
|
Chris@0
|
342 if (f) {
|
Chris@0
|
343 if (value < f->getPortMinimum(m_descriptor, portNumber)) {
|
Chris@0
|
344 value = f->getPortMinimum(m_descriptor, portNumber);
|
Chris@0
|
345 }
|
Chris@0
|
346 if (value > f->getPortMaximum(m_descriptor, portNumber)) {
|
Chris@0
|
347 value = f->getPortMaximum(m_descriptor, portNumber);
|
Chris@0
|
348 }
|
Chris@0
|
349 }
|
Chris@0
|
350
|
Chris@0
|
351 (*m_controlPortsIn[parameter].second) = value;
|
Chris@0
|
352 }
|
Chris@0
|
353
|
Chris@0
|
354 float
|
Chris@0
|
355 LADSPAPluginInstance::getParameterValue(unsigned int parameter) const
|
Chris@0
|
356 {
|
Chris@0
|
357 if (parameter >= m_controlPortsIn.size()) return 0.0;
|
Chris@0
|
358 return (*m_controlPortsIn[parameter].second);
|
Chris@0
|
359 }
|
Chris@0
|
360
|
Chris@0
|
361 float
|
Chris@0
|
362 LADSPAPluginInstance::getParameterDefault(unsigned int parameter) const
|
Chris@0
|
363 {
|
Chris@0
|
364 if (parameter >= m_controlPortsIn.size()) return 0.0;
|
Chris@0
|
365
|
Chris@0
|
366 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
|
Chris@0
|
367 if (f) {
|
Chris@0
|
368 return f->getPortDefault(m_descriptor, m_controlPortsIn[parameter].first);
|
Chris@0
|
369 } else {
|
Chris@0
|
370 return 0.0f;
|
Chris@0
|
371 }
|
Chris@0
|
372 }
|
Chris@0
|
373
|
Chris@0
|
374 void
|
Chris@0
|
375 LADSPAPluginInstance::run(const RealTime &)
|
Chris@0
|
376 {
|
Chris@0
|
377 if (!m_descriptor || !m_descriptor->run) return;
|
Chris@0
|
378
|
Chris@0
|
379 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
|
Chris@0
|
380 hi != m_instanceHandles.end(); ++hi) {
|
Chris@0
|
381 m_descriptor->run(*hi, m_blockSize);
|
Chris@0
|
382 }
|
Chris@0
|
383
|
Chris@0
|
384 m_run = true;
|
Chris@0
|
385 }
|
Chris@0
|
386
|
Chris@0
|
387 void
|
Chris@0
|
388 LADSPAPluginInstance::deactivate()
|
Chris@0
|
389 {
|
Chris@0
|
390 if (!m_descriptor || !m_descriptor->deactivate) return;
|
Chris@0
|
391
|
Chris@0
|
392 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
|
Chris@0
|
393 hi != m_instanceHandles.end(); ++hi) {
|
Chris@0
|
394 m_descriptor->deactivate(*hi);
|
Chris@0
|
395 }
|
Chris@0
|
396 }
|
Chris@0
|
397
|
Chris@0
|
398 void
|
Chris@0
|
399 LADSPAPluginInstance::cleanup()
|
Chris@0
|
400 {
|
Chris@0
|
401 if (!m_descriptor) return;
|
Chris@0
|
402
|
Chris@0
|
403 if (!m_descriptor->cleanup) {
|
Chris@0
|
404 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
|
Chris@0
|
405 << ":" << m_descriptor->Label
|
Chris@0
|
406 << " has no cleanup method!" << std::endl;
|
Chris@0
|
407 return;
|
Chris@0
|
408 }
|
Chris@0
|
409
|
Chris@0
|
410 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
|
Chris@0
|
411 hi != m_instanceHandles.end(); ++hi) {
|
Chris@0
|
412 m_descriptor->cleanup(*hi);
|
Chris@0
|
413 }
|
Chris@0
|
414
|
Chris@0
|
415 m_instanceHandles.clear();
|
Chris@0
|
416 }
|
Chris@0
|
417
|
Chris@0
|
418
|