Mercurial > hg > svcore
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 |