comparison plugin/LADSPAPluginInstance.cpp @ 0:da6937383da8

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