annotate plugin/LADSPAPluginInstance.cpp @ 117:c30728d5625c sv1-v0.9rc1

* Make vertical scale alignment modes work in note layer as well as time-value layer, and several significant fixes to it * Make it possible to draw notes properly on the note layer * Show units (and frequencies etc in note layer's case) in the time-value and note layer description boxes * Minor fix to item edit dialog layout * Some minor menu rearrangement * Comment out a lot of debug output * Add SV website and reference URLs to Help menu, and add code to (attempt to) open them in the user's preferred browser
author Chris Cannam
date Fri, 12 May 2006 14:40:43 +0000
parents c983dda79f72
children 702fc936e6a6
rev   line source
Chris@49 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@0 2
Chris@0 3 /*
Chris@52 4 Sonic Visualiser
Chris@52 5 An audio file viewer and annotation editor.
Chris@52 6 Centre for Digital Music, Queen Mary, University of London.
Chris@0 7
Chris@52 8 This program is free software; you can redistribute it and/or
Chris@52 9 modify it under the terms of the GNU General Public License as
Chris@52 10 published by the Free Software Foundation; either version 2 of the
Chris@52 11 License, or (at your option) any later version. See the file
Chris@52 12 COPYING included with this distribution for more information.
Chris@0 13 */
Chris@0 14
Chris@0 15 /*
Chris@0 16 This is a modified version of a source file from the
Chris@0 17 Rosegarden MIDI and audio sequencer and notation editor.
Chris@17 18 This file copyright 2000-2006 Chris Cannam and Richard Bown.
Chris@0 19 */
Chris@0 20
Chris@0 21 #include <iostream>
Chris@0 22 #include <cassert>
Chris@0 23
Chris@0 24 #include "LADSPAPluginInstance.h"
Chris@0 25 #include "LADSPAPluginFactory.h"
Chris@0 26
Chris@117 27 //#define DEBUG_LADSPA 1
Chris@0 28
Chris@0 29
Chris@0 30 LADSPAPluginInstance::LADSPAPluginInstance(RealTimePluginFactory *factory,
Chris@0 31 int clientId,
Chris@0 32 QString identifier,
Chris@0 33 int position,
Chris@0 34 unsigned long sampleRate,
Chris@0 35 size_t blockSize,
Chris@0 36 int idealChannelCount,
Chris@0 37 const LADSPA_Descriptor* descriptor) :
Chris@0 38 RealTimePluginInstance(factory, identifier),
Chris@0 39 m_client(clientId),
Chris@0 40 m_position(position),
Chris@0 41 m_instanceCount(0),
Chris@0 42 m_descriptor(descriptor),
Chris@0 43 m_blockSize(blockSize),
Chris@0 44 m_sampleRate(sampleRate),
Chris@0 45 m_latencyPort(0),
Chris@0 46 m_run(false),
Chris@0 47 m_bypassed(false)
Chris@0 48 {
Chris@0 49 init(idealChannelCount);
Chris@0 50
Chris@0 51 m_inputBuffers = new sample_t*[m_instanceCount * m_audioPortsIn.size()];
Chris@0 52 m_outputBuffers = new sample_t*[m_instanceCount * m_audioPortsOut.size()];
Chris@0 53
Chris@0 54 for (size_t i = 0; i < m_instanceCount * m_audioPortsIn.size(); ++i) {
Chris@0 55 m_inputBuffers[i] = new sample_t[blockSize];
Chris@0 56 }
Chris@0 57 for (size_t i = 0; i < m_instanceCount * m_audioPortsOut.size(); ++i) {
Chris@0 58 m_outputBuffers[i] = new sample_t[blockSize];
Chris@0 59 }
Chris@0 60
Chris@0 61 m_ownBuffers = true;
Chris@0 62
Chris@0 63 instantiate(sampleRate);
Chris@0 64 if (isOK()) {
Chris@0 65 connectPorts();
Chris@0 66 activate();
Chris@0 67 }
Chris@0 68 }
Chris@0 69
Chris@51 70 std::string
Chris@51 71 LADSPAPluginInstance::getName() const
Chris@0 72 {
Chris@51 73 return m_descriptor->Label;
Chris@0 74 }
Chris@0 75
Chris@51 76 std::string
Chris@51 77 LADSPAPluginInstance::getDescription() const
Chris@51 78 {
Chris@51 79 return m_descriptor->Name;
Chris@51 80 }
Chris@51 81
Chris@51 82 std::string
Chris@51 83 LADSPAPluginInstance::getMaker() const
Chris@51 84 {
Chris@51 85 return m_descriptor->Maker;
Chris@51 86 }
Chris@51 87
Chris@51 88 int
Chris@51 89 LADSPAPluginInstance::getPluginVersion() const
Chris@51 90 {
Chris@51 91 return 1;
Chris@51 92 }
Chris@51 93
Chris@51 94 std::string
Chris@51 95 LADSPAPluginInstance::getCopyright() const
Chris@51 96 {
Chris@51 97 return m_descriptor->Copyright;
Chris@51 98 }
Chris@51 99
Chris@51 100 LADSPAPluginInstance::ParameterList
Chris@51 101 LADSPAPluginInstance::getParameterDescriptors() const
Chris@51 102 {
Chris@51 103 ParameterList list;
Chris@51 104 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@51 105
Chris@51 106 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@51 107
Chris@51 108 ParameterDescriptor pd;
Chris@51 109 unsigned int pn = m_controlPortsIn[i].first;
Chris@51 110
Chris@51 111 pd.name = m_descriptor->PortNames[pn];
Chris@51 112 pd.description = pd.name;
Chris@51 113 pd.minValue = f->getPortMinimum(m_descriptor, pn);
Chris@51 114 pd.maxValue = f->getPortMaximum(m_descriptor, pn);
Chris@51 115 pd.defaultValue = f->getPortDefault(m_descriptor, pn);
Chris@57 116
Chris@57 117 float q = f->getPortQuantization(m_descriptor, pn);
Chris@57 118 if (q == 0.0) {
Chris@57 119 pd.isQuantized = false;
Chris@57 120 } else {
Chris@57 121 pd.isQuantized = true;
Chris@57 122 pd.quantizeStep = q;
Chris@57 123 }
Chris@51 124
Chris@51 125 list.push_back(pd);
Chris@51 126 }
Chris@51 127
Chris@51 128 return list;
Chris@51 129 }
Chris@51 130
Chris@51 131 float
Chris@51 132 LADSPAPluginInstance::getParameter(std::string name) const
Chris@51 133 {
Chris@51 134 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@51 135 if (name == m_descriptor->PortNames[m_controlPortsIn[i].first]) {
Chris@51 136 return getParameterValue(i);
Chris@51 137 }
Chris@51 138 }
Chris@51 139
Chris@51 140 return 0.0;
Chris@51 141 }
Chris@51 142
Chris@51 143 void
Chris@51 144 LADSPAPluginInstance::setParameter(std::string name, float value)
Chris@51 145 {
Chris@51 146 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@51 147 if (name == m_descriptor->PortNames[m_controlPortsIn[i].first]) {
Chris@51 148 setParameterValue(i, value);
Chris@51 149 break;
Chris@51 150 }
Chris@51 151 }
Chris@51 152 }
Chris@0 153
Chris@0 154 void
Chris@0 155 LADSPAPluginInstance::init(int idealChannelCount)
Chris@0 156 {
Chris@0 157 #ifdef DEBUG_LADSPA
Chris@0 158 std::cerr << "LADSPAPluginInstance::init(" << idealChannelCount << "): plugin has "
Chris@0 159 << m_descriptor->PortCount << " ports" << std::endl;
Chris@0 160 #endif
Chris@0 161
Chris@0 162 // Discover ports numbers and identities
Chris@0 163 //
Chris@0 164 for (unsigned long i = 0; i < m_descriptor->PortCount; ++i)
Chris@0 165 {
Chris@0 166 if (LADSPA_IS_PORT_AUDIO(m_descriptor->PortDescriptors[i]))
Chris@0 167 {
Chris@0 168 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
Chris@0 169 #ifdef DEBUG_LADSPA
Chris@0 170 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio in" << std::endl;
Chris@0 171 #endif
Chris@0 172 m_audioPortsIn.push_back(i);
Chris@0 173 } else {
Chris@0 174 #ifdef DEBUG_LADSPA
Chris@0 175 std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio out" << std::endl;
Chris@0 176 #endif
Chris@0 177 m_audioPortsOut.push_back(i);
Chris@0 178 }
Chris@0 179 }
Chris@0 180 else
Chris@0 181 if (LADSPA_IS_PORT_CONTROL(m_descriptor->PortDescriptors[i]))
Chris@0 182 {
Chris@0 183 if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) {
Chris@0 184 #ifdef DEBUG_LADSPA
Chris@0 185 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control in" << std::endl;
Chris@0 186 #endif
Chris@0 187 LADSPA_Data *data = new LADSPA_Data(0.0);
Chris@0 188 m_controlPortsIn.push_back(
Chris@0 189 std::pair<unsigned long, LADSPA_Data*>(i, data));
Chris@0 190 } else {
Chris@0 191 #ifdef DEBUG_LADSPA
Chris@0 192 std::cerr << "LADSPAPluginInstance::init: port " << i << " is control out" << std::endl;
Chris@0 193 #endif
Chris@0 194 LADSPA_Data *data = new LADSPA_Data(0.0);
Chris@0 195 m_controlPortsOut.push_back(
Chris@0 196 std::pair<unsigned long, LADSPA_Data*>(i, data));
Chris@0 197 if (!strcmp(m_descriptor->PortNames[i], "latency") ||
Chris@0 198 !strcmp(m_descriptor->PortNames[i], "_latency")) {
Chris@0 199 #ifdef DEBUG_LADSPA
Chris@0 200 std::cerr << "Wooo! We have a latency port!" << std::endl;
Chris@0 201 #endif
Chris@0 202 m_latencyPort = data;
Chris@0 203 }
Chris@0 204 }
Chris@0 205 }
Chris@0 206 #ifdef DEBUG_LADSPA
Chris@0 207 else
Chris@0 208 std::cerr << "LADSPAPluginInstance::init - "
Chris@0 209 << "unrecognised port type" << std::endl;
Chris@0 210 #endif
Chris@0 211 }
Chris@0 212
Chris@0 213 m_instanceCount = 1;
Chris@0 214
Chris@0 215 if (idealChannelCount > 0) {
Chris@0 216 if (m_audioPortsIn.size() == 1) {
Chris@0 217 // mono plugin: duplicate it if need be
Chris@0 218 m_instanceCount = idealChannelCount;
Chris@0 219 }
Chris@0 220 }
Chris@0 221 }
Chris@0 222
Chris@0 223 size_t
Chris@0 224 LADSPAPluginInstance::getLatency()
Chris@0 225 {
Chris@0 226 if (m_latencyPort) {
Chris@66 227 if (!m_run) run(Vamp::RealTime::zeroTime);
Chris@0 228 if (*m_latencyPort > 0) return (size_t)*m_latencyPort;
Chris@0 229 }
Chris@0 230 return 0;
Chris@0 231 }
Chris@0 232
Chris@0 233 void
Chris@0 234 LADSPAPluginInstance::silence()
Chris@0 235 {
Chris@0 236 if (isOK()) {
Chris@0 237 deactivate();
Chris@0 238 activate();
Chris@0 239 }
Chris@0 240 }
Chris@0 241
Chris@0 242 void
Chris@0 243 LADSPAPluginInstance::setIdealChannelCount(size_t channels)
Chris@0 244 {
Chris@0 245 if (m_audioPortsIn.size() != 1 || channels == m_instanceCount) {
Chris@0 246 silence();
Chris@0 247 return;
Chris@0 248 }
Chris@0 249
Chris@0 250 if (isOK()) {
Chris@0 251 deactivate();
Chris@0 252 }
Chris@0 253
Chris@0 254 //!!! don't we need to reallocate inputBuffers and outputBuffers?
Chris@0 255
Chris@0 256 cleanup();
Chris@0 257 m_instanceCount = channels;
Chris@0 258 instantiate(m_sampleRate);
Chris@0 259 if (isOK()) {
Chris@0 260 connectPorts();
Chris@0 261 activate();
Chris@0 262 }
Chris@0 263 }
Chris@0 264
Chris@0 265
Chris@0 266 LADSPAPluginInstance::~LADSPAPluginInstance()
Chris@0 267 {
Chris@0 268 #ifdef DEBUG_LADSPA
Chris@0 269 std::cerr << "LADSPAPluginInstance::~LADSPAPluginInstance" << std::endl;
Chris@0 270 #endif
Chris@0 271
Chris@0 272 if (m_instanceHandles.size() != 0) { // "isOK()"
Chris@0 273 deactivate();
Chris@0 274 }
Chris@0 275
Chris@0 276 cleanup();
Chris@0 277
Chris@0 278 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i)
Chris@0 279 delete m_controlPortsIn[i].second;
Chris@0 280
Chris@0 281 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i)
Chris@0 282 delete m_controlPortsOut[i].second;
Chris@0 283
Chris@0 284 m_controlPortsIn.clear();
Chris@0 285 m_controlPortsOut.clear();
Chris@0 286
Chris@0 287 if (m_ownBuffers) {
Chris@0 288 for (size_t i = 0; i < m_audioPortsIn.size(); ++i) {
Chris@0 289 delete[] m_inputBuffers[i];
Chris@0 290 }
Chris@0 291 for (size_t i = 0; i < m_audioPortsOut.size(); ++i) {
Chris@0 292 delete[] m_outputBuffers[i];
Chris@0 293 }
Chris@0 294
Chris@0 295 delete[] m_inputBuffers;
Chris@0 296 delete[] m_outputBuffers;
Chris@0 297 }
Chris@0 298
Chris@0 299 m_audioPortsIn.clear();
Chris@0 300 m_audioPortsOut.clear();
Chris@0 301 }
Chris@0 302
Chris@0 303
Chris@0 304 void
Chris@0 305 LADSPAPluginInstance::instantiate(unsigned long sampleRate)
Chris@0 306 {
Chris@0 307 #ifdef DEBUG_LADSPA
Chris@0 308 std::cout << "LADSPAPluginInstance::instantiate - plugin unique id = "
Chris@0 309 << m_descriptor->UniqueID << std::endl;
Chris@0 310 #endif
Chris@0 311 if (!m_descriptor) return;
Chris@0 312
Chris@0 313 if (!m_descriptor->instantiate) {
Chris@0 314 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
Chris@0 315 << ":" << m_descriptor->Label
Chris@0 316 << " has no instantiate method!" << std::endl;
Chris@0 317 return;
Chris@0 318 }
Chris@0 319
Chris@0 320 for (size_t i = 0; i < m_instanceCount; ++i) {
Chris@0 321 m_instanceHandles.push_back
Chris@0 322 (m_descriptor->instantiate(m_descriptor, sampleRate));
Chris@0 323 }
Chris@0 324 }
Chris@0 325
Chris@0 326 void
Chris@0 327 LADSPAPluginInstance::activate()
Chris@0 328 {
Chris@0 329 if (!m_descriptor || !m_descriptor->activate) return;
Chris@0 330
Chris@0 331 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 332 hi != m_instanceHandles.end(); ++hi) {
Chris@0 333 m_descriptor->activate(*hi);
Chris@0 334 }
Chris@0 335 }
Chris@0 336
Chris@0 337 void
Chris@0 338 LADSPAPluginInstance::connectPorts()
Chris@0 339 {
Chris@0 340 if (!m_descriptor || !m_descriptor->connect_port) return;
Chris@0 341
Chris@0 342 assert(sizeof(LADSPA_Data) == sizeof(float));
Chris@0 343 assert(sizeof(sample_t) == sizeof(float));
Chris@0 344
Chris@57 345 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@0 346 int inbuf = 0, outbuf = 0;
Chris@0 347
Chris@0 348 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 349 hi != m_instanceHandles.end(); ++hi) {
Chris@0 350
Chris@0 351 for (unsigned int i = 0; i < m_audioPortsIn.size(); ++i) {
Chris@0 352 m_descriptor->connect_port(*hi,
Chris@0 353 m_audioPortsIn[i],
Chris@0 354 (LADSPA_Data *)m_inputBuffers[inbuf]);
Chris@0 355 ++inbuf;
Chris@0 356 }
Chris@0 357
Chris@0 358 for (unsigned int i = 0; i < m_audioPortsOut.size(); ++i) {
Chris@0 359 m_descriptor->connect_port(*hi,
Chris@0 360 m_audioPortsOut[i],
Chris@0 361 (LADSPA_Data *)m_outputBuffers[outbuf]);
Chris@0 362 ++outbuf;
Chris@0 363 }
Chris@0 364
Chris@0 365 // If there is more than one instance, they all share the same
Chris@0 366 // control port ins (and outs, for the moment, because we
Chris@0 367 // don't actually do anything with the outs anyway -- but they
Chris@0 368 // do have to be connected as the plugin can't know if they're
Chris@0 369 // not and will write to them anyway).
Chris@0 370
Chris@0 371 for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) {
Chris@0 372 m_descriptor->connect_port(*hi,
Chris@0 373 m_controlPortsIn[i].first,
Chris@0 374 m_controlPortsIn[i].second);
Chris@57 375 if (f) {
Chris@57 376 float defaultValue = f->getPortDefault
Chris@57 377 (m_descriptor, m_controlPortsIn[i].first);
Chris@57 378 *m_controlPortsIn[i].second = defaultValue;
Chris@57 379 }
Chris@0 380 }
Chris@0 381
Chris@0 382 for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) {
Chris@0 383 m_descriptor->connect_port(*hi,
Chris@0 384 m_controlPortsOut[i].first,
Chris@0 385 m_controlPortsOut[i].second);
Chris@0 386 }
Chris@0 387 }
Chris@0 388 }
Chris@0 389
Chris@0 390 unsigned int
Chris@0 391 LADSPAPluginInstance::getParameterCount() const
Chris@0 392 {
Chris@0 393 return m_controlPortsIn.size();
Chris@0 394 }
Chris@0 395
Chris@0 396 void
Chris@0 397 LADSPAPluginInstance::setParameterValue(unsigned int parameter, float value)
Chris@0 398 {
Chris@0 399 if (parameter >= m_controlPortsIn.size()) return;
Chris@0 400
Chris@0 401 unsigned int portNumber = m_controlPortsIn[parameter].first;
Chris@0 402
Chris@0 403 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@0 404 if (f) {
Chris@0 405 if (value < f->getPortMinimum(m_descriptor, portNumber)) {
Chris@0 406 value = f->getPortMinimum(m_descriptor, portNumber);
Chris@0 407 }
Chris@0 408 if (value > f->getPortMaximum(m_descriptor, portNumber)) {
Chris@0 409 value = f->getPortMaximum(m_descriptor, portNumber);
Chris@0 410 }
Chris@0 411 }
Chris@0 412
Chris@0 413 (*m_controlPortsIn[parameter].second) = value;
Chris@0 414 }
Chris@0 415
Chris@0 416 float
Martin@62 417 LADSPAPluginInstance::getControlOutputValue(size_t output) const
Chris@60 418 {
Chris@60 419 if (output > m_controlPortsOut.size()) return 0.0;
Chris@60 420 return (*m_controlPortsOut[output].second);
Chris@60 421 }
Chris@60 422
Chris@60 423 float
Chris@0 424 LADSPAPluginInstance::getParameterValue(unsigned int parameter) const
Chris@0 425 {
Chris@0 426 if (parameter >= m_controlPortsIn.size()) return 0.0;
Chris@0 427 return (*m_controlPortsIn[parameter].second);
Chris@0 428 }
Chris@0 429
Chris@0 430 float
Chris@0 431 LADSPAPluginInstance::getParameterDefault(unsigned int parameter) const
Chris@0 432 {
Chris@0 433 if (parameter >= m_controlPortsIn.size()) return 0.0;
Chris@0 434
Chris@0 435 LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory);
Chris@0 436 if (f) {
Chris@0 437 return f->getPortDefault(m_descriptor, m_controlPortsIn[parameter].first);
Chris@0 438 } else {
Chris@0 439 return 0.0f;
Chris@0 440 }
Chris@0 441 }
Chris@0 442
Chris@0 443 void
Chris@66 444 LADSPAPluginInstance::run(const Vamp::RealTime &)
Chris@0 445 {
Chris@0 446 if (!m_descriptor || !m_descriptor->run) return;
Chris@0 447
Chris@0 448 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 449 hi != m_instanceHandles.end(); ++hi) {
Chris@0 450 m_descriptor->run(*hi, m_blockSize);
Chris@0 451 }
Chris@0 452
Chris@0 453 m_run = true;
Chris@0 454 }
Chris@0 455
Chris@0 456 void
Chris@0 457 LADSPAPluginInstance::deactivate()
Chris@0 458 {
Chris@0 459 if (!m_descriptor || !m_descriptor->deactivate) return;
Chris@0 460
Chris@0 461 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 462 hi != m_instanceHandles.end(); ++hi) {
Chris@0 463 m_descriptor->deactivate(*hi);
Chris@0 464 }
Chris@0 465 }
Chris@0 466
Chris@0 467 void
Chris@0 468 LADSPAPluginInstance::cleanup()
Chris@0 469 {
Chris@0 470 if (!m_descriptor) return;
Chris@0 471
Chris@0 472 if (!m_descriptor->cleanup) {
Chris@0 473 std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID
Chris@0 474 << ":" << m_descriptor->Label
Chris@0 475 << " has no cleanup method!" << std::endl;
Chris@0 476 return;
Chris@0 477 }
Chris@0 478
Chris@0 479 for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin();
Chris@0 480 hi != m_instanceHandles.end(); ++hi) {
Chris@0 481 m_descriptor->cleanup(*hi);
Chris@0 482 }
Chris@0 483
Chris@0 484 m_instanceHandles.clear();
Chris@0 485 }
Chris@0 486
Chris@0 487