Mercurial > hg > svcore
view 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 |
line wrap: on
line source
/* -*- c-basic-offset: 4 -*- vi:set ts=8 sts=4 sw=4: */ /* A waveform viewer and audio annotation editor. Chris Cannam, Queen Mary University of London, 2005-2006 This is experimental software. Not for distribution. */ /* This is a modified version of a source file from the Rosegarden MIDI and audio sequencer and notation editor. This file copyright 2000-2005 Chris Cannam and Richard Bown. */ #include <iostream> #include <cassert> #include "LADSPAPluginInstance.h" #include "LADSPAPluginFactory.h" //#define DEBUG_LADSPA 1 LADSPAPluginInstance::LADSPAPluginInstance(RealTimePluginFactory *factory, int clientId, QString identifier, int position, unsigned long sampleRate, size_t blockSize, int idealChannelCount, const LADSPA_Descriptor* descriptor) : RealTimePluginInstance(factory, identifier), m_client(clientId), m_position(position), m_instanceCount(0), m_descriptor(descriptor), m_blockSize(blockSize), m_sampleRate(sampleRate), m_latencyPort(0), m_run(false), m_bypassed(false) { init(idealChannelCount); m_inputBuffers = new sample_t*[m_instanceCount * m_audioPortsIn.size()]; m_outputBuffers = new sample_t*[m_instanceCount * m_audioPortsOut.size()]; for (size_t i = 0; i < m_instanceCount * m_audioPortsIn.size(); ++i) { m_inputBuffers[i] = new sample_t[blockSize]; } for (size_t i = 0; i < m_instanceCount * m_audioPortsOut.size(); ++i) { m_outputBuffers[i] = new sample_t[blockSize]; } m_ownBuffers = true; instantiate(sampleRate); if (isOK()) { connectPorts(); activate(); } } LADSPAPluginInstance::LADSPAPluginInstance(RealTimePluginFactory *factory, int clientId, QString identifier, int position, unsigned long sampleRate, size_t blockSize, sample_t **inputBuffers, sample_t **outputBuffers, const LADSPA_Descriptor* descriptor) : RealTimePluginInstance(factory, identifier), m_client(clientId), m_position(position), m_instanceCount(0), m_descriptor(descriptor), m_blockSize(blockSize), m_inputBuffers(inputBuffers), m_outputBuffers(outputBuffers), m_ownBuffers(false), m_sampleRate(sampleRate), m_latencyPort(0), m_run(false), m_bypassed(false) { init(); instantiate(sampleRate); if (isOK()) { connectPorts(); activate(); } } void LADSPAPluginInstance::init(int idealChannelCount) { #ifdef DEBUG_LADSPA std::cerr << "LADSPAPluginInstance::init(" << idealChannelCount << "): plugin has " << m_descriptor->PortCount << " ports" << std::endl; #endif // Discover ports numbers and identities // for (unsigned long i = 0; i < m_descriptor->PortCount; ++i) { if (LADSPA_IS_PORT_AUDIO(m_descriptor->PortDescriptors[i])) { if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) { #ifdef DEBUG_LADSPA std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio in" << std::endl; #endif m_audioPortsIn.push_back(i); } else { #ifdef DEBUG_LADSPA std::cerr << "LADSPAPluginInstance::init: port " << i << " is audio out" << std::endl; #endif m_audioPortsOut.push_back(i); } } else if (LADSPA_IS_PORT_CONTROL(m_descriptor->PortDescriptors[i])) { if (LADSPA_IS_PORT_INPUT(m_descriptor->PortDescriptors[i])) { #ifdef DEBUG_LADSPA std::cerr << "LADSPAPluginInstance::init: port " << i << " is control in" << std::endl; #endif LADSPA_Data *data = new LADSPA_Data(0.0); m_controlPortsIn.push_back( std::pair<unsigned long, LADSPA_Data*>(i, data)); } else { #ifdef DEBUG_LADSPA std::cerr << "LADSPAPluginInstance::init: port " << i << " is control out" << std::endl; #endif LADSPA_Data *data = new LADSPA_Data(0.0); m_controlPortsOut.push_back( std::pair<unsigned long, LADSPA_Data*>(i, data)); if (!strcmp(m_descriptor->PortNames[i], "latency") || !strcmp(m_descriptor->PortNames[i], "_latency")) { #ifdef DEBUG_LADSPA std::cerr << "Wooo! We have a latency port!" << std::endl; #endif m_latencyPort = data; } } } #ifdef DEBUG_LADSPA else std::cerr << "LADSPAPluginInstance::init - " << "unrecognised port type" << std::endl; #endif } m_instanceCount = 1; if (idealChannelCount > 0) { if (m_audioPortsIn.size() == 1) { // mono plugin: duplicate it if need be m_instanceCount = idealChannelCount; } } } size_t LADSPAPluginInstance::getLatency() { if (m_latencyPort) { if (!m_run) run(RealTime::zeroTime); if (*m_latencyPort > 0) return (size_t)*m_latencyPort; } return 0; } void LADSPAPluginInstance::silence() { if (isOK()) { deactivate(); activate(); } } void LADSPAPluginInstance::setIdealChannelCount(size_t channels) { if (m_audioPortsIn.size() != 1 || channels == m_instanceCount) { silence(); return; } if (isOK()) { deactivate(); } //!!! don't we need to reallocate inputBuffers and outputBuffers? cleanup(); m_instanceCount = channels; instantiate(m_sampleRate); if (isOK()) { connectPorts(); activate(); } } LADSPAPluginInstance::~LADSPAPluginInstance() { #ifdef DEBUG_LADSPA std::cerr << "LADSPAPluginInstance::~LADSPAPluginInstance" << std::endl; #endif if (m_instanceHandles.size() != 0) { // "isOK()" deactivate(); } cleanup(); for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) delete m_controlPortsIn[i].second; for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) delete m_controlPortsOut[i].second; m_controlPortsIn.clear(); m_controlPortsOut.clear(); if (m_ownBuffers) { for (size_t i = 0; i < m_audioPortsIn.size(); ++i) { delete[] m_inputBuffers[i]; } for (size_t i = 0; i < m_audioPortsOut.size(); ++i) { delete[] m_outputBuffers[i]; } delete[] m_inputBuffers; delete[] m_outputBuffers; } m_audioPortsIn.clear(); m_audioPortsOut.clear(); } void LADSPAPluginInstance::instantiate(unsigned long sampleRate) { #ifdef DEBUG_LADSPA std::cout << "LADSPAPluginInstance::instantiate - plugin unique id = " << m_descriptor->UniqueID << std::endl; #endif if (!m_descriptor) return; if (!m_descriptor->instantiate) { std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID << ":" << m_descriptor->Label << " has no instantiate method!" << std::endl; return; } for (size_t i = 0; i < m_instanceCount; ++i) { m_instanceHandles.push_back (m_descriptor->instantiate(m_descriptor, sampleRate)); } } void LADSPAPluginInstance::activate() { if (!m_descriptor || !m_descriptor->activate) return; for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); hi != m_instanceHandles.end(); ++hi) { m_descriptor->activate(*hi); } } void LADSPAPluginInstance::connectPorts() { if (!m_descriptor || !m_descriptor->connect_port) return; assert(sizeof(LADSPA_Data) == sizeof(float)); assert(sizeof(sample_t) == sizeof(float)); int inbuf = 0, outbuf = 0; for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); hi != m_instanceHandles.end(); ++hi) { for (unsigned int i = 0; i < m_audioPortsIn.size(); ++i) { m_descriptor->connect_port(*hi, m_audioPortsIn[i], (LADSPA_Data *)m_inputBuffers[inbuf]); ++inbuf; } for (unsigned int i = 0; i < m_audioPortsOut.size(); ++i) { m_descriptor->connect_port(*hi, m_audioPortsOut[i], (LADSPA_Data *)m_outputBuffers[outbuf]); ++outbuf; } // If there is more than one instance, they all share the same // control port ins (and outs, for the moment, because we // don't actually do anything with the outs anyway -- but they // do have to be connected as the plugin can't know if they're // not and will write to them anyway). for (unsigned int i = 0; i < m_controlPortsIn.size(); ++i) { m_descriptor->connect_port(*hi, m_controlPortsIn[i].first, m_controlPortsIn[i].second); } for (unsigned int i = 0; i < m_controlPortsOut.size(); ++i) { m_descriptor->connect_port(*hi, m_controlPortsOut[i].first, m_controlPortsOut[i].second); } } } unsigned int LADSPAPluginInstance::getParameterCount() const { return m_controlPortsIn.size(); } void LADSPAPluginInstance::setParameterValue(unsigned int parameter, float value) { if (parameter >= m_controlPortsIn.size()) return; unsigned int portNumber = m_controlPortsIn[parameter].first; LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory); if (f) { if (value < f->getPortMinimum(m_descriptor, portNumber)) { value = f->getPortMinimum(m_descriptor, portNumber); } if (value > f->getPortMaximum(m_descriptor, portNumber)) { value = f->getPortMaximum(m_descriptor, portNumber); } } (*m_controlPortsIn[parameter].second) = value; } float LADSPAPluginInstance::getParameterValue(unsigned int parameter) const { if (parameter >= m_controlPortsIn.size()) return 0.0; return (*m_controlPortsIn[parameter].second); } float LADSPAPluginInstance::getParameterDefault(unsigned int parameter) const { if (parameter >= m_controlPortsIn.size()) return 0.0; LADSPAPluginFactory *f = dynamic_cast<LADSPAPluginFactory *>(m_factory); if (f) { return f->getPortDefault(m_descriptor, m_controlPortsIn[parameter].first); } else { return 0.0f; } } void LADSPAPluginInstance::run(const RealTime &) { if (!m_descriptor || !m_descriptor->run) return; for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); hi != m_instanceHandles.end(); ++hi) { m_descriptor->run(*hi, m_blockSize); } m_run = true; } void LADSPAPluginInstance::deactivate() { if (!m_descriptor || !m_descriptor->deactivate) return; for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); hi != m_instanceHandles.end(); ++hi) { m_descriptor->deactivate(*hi); } } void LADSPAPluginInstance::cleanup() { if (!m_descriptor) return; if (!m_descriptor->cleanup) { std::cerr << "Bad plugin: plugin id " << m_descriptor->UniqueID << ":" << m_descriptor->Label << " has no cleanup method!" << std::endl; return; } for (std::vector<LADSPA_Handle>::iterator hi = m_instanceHandles.begin(); hi != m_instanceHandles.end(); ++hi) { m_descriptor->cleanup(*hi); } m_instanceHandles.clear(); }