annotate plugin/LADSPAPluginInstance.cpp @ 6:44bbf5793d84

* Rework handling of layer properties in file I/O -- we now get the individual layers to load and save them rather than doing it via generic property lists in the base class, so as to ensure we read and write meaningful values rather than generic int values requiring conversion.
author Chris Cannam
date Thu, 19 Jan 2006 12:54:38 +0000
parents d86891498eef
children 2fb933f88604
rev   line source
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@2 5 Chris Cannam, Queen Mary University of London, 2005-2006
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