Mercurial > hg > svapp
diff audio/EffectWrapper.cpp @ 739:ddfac001b543 audio-source-refactor
Introduce EffectWrapper for the auditioning effect
author | Chris Cannam |
---|---|
date | Thu, 19 Mar 2020 16:14:02 +0000 |
parents | |
children | 846970dbef17 |
line wrap: on
line diff
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/audio/EffectWrapper.cpp Thu Mar 19 16:14:02 2020 +0000 @@ -0,0 +1,216 @@ +/* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ + +/* + Sonic Visualiser + An audio file viewer and annotation editor. + Centre for Digital Music, Queen Mary, University of London. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License as + published by the Free Software Foundation; either version 2 of the + License, or (at your option) any later version. See the file + COPYING included with this distribution for more information. +*/ + +#include "EffectWrapper.h" + +#include <rubberband/RubberBandStretcher.h> + +#include "base/Debug.h" + +using namespace std; + +static const int DEFAULT_RING_BUFFER_SIZE = 131071; + +EffectWrapper::EffectWrapper(ApplicationPlaybackSource *source) : + m_source(source), + m_bypassed(false), + m_failed(false), + m_channelCount(0) +{ +} + +EffectWrapper::~EffectWrapper() +{ +} + +void +EffectWrapper::setEffect(weak_ptr<RealTimePluginInstance> effect) +{ + lock_guard<mutex> guard(m_mutex); + + m_effect = effect; + m_failed = false; +} + +void +EffectWrapper::setBypassed(bool bypassed) +{ + lock_guard<mutex> guard(m_mutex); + + m_bypassed = bypassed; +} + +bool +EffectWrapper::isBypassed() const +{ + lock_guard<mutex> guard(m_mutex); + + return m_bypassed; +} + +void +EffectWrapper::reset() +{ + lock_guard<mutex> guard(m_mutex); + + for (auto &rb: m_effectOutputBuffers) { + rb.reset(); + } +} + +int +EffectWrapper::getSourceSamples(float *const *samples, + int nchannels, int nframes) +{ + lock_guard<mutex> guard(m_mutex); + + auto effect(m_effect.lock()); + + if (!effect || m_bypassed || m_failed) { + return m_source->getSourceSamples(samples, nchannels, nframes); + } + + static int warnings = 0; + if (nchannels != m_channelCount) { + if (warnings >= 0) { + SVCERR << "WARNING: getSourceSamples called for a number of channels different from that set with setSystemPlaybackChannelCount (" + << nchannels << " vs " << m_channelCount << ")" << endl; + if (++warnings == 6) { + SVCERR << "(further warnings will be suppressed)" << endl; + warnings = -1; + } + } + return 0; + } + + if ((int)effect->getAudioInputCount() != m_channelCount) { + if (!m_failed) { + SVCERR << "EffectWrapper::getSourceSamples: " + << "Can't run plugin: plugin input count " + << effect->getAudioInputCount() + << " != our channel count " << m_channelCount + << " (future errors for this plugin will be suppressed)" + << endl; + m_failed = true; + } + } + if ((int)effect->getAudioOutputCount() != m_channelCount) { + if (!m_failed) { + SVCERR << "EffectWrapper::getSourceSamples: " + << "Can't run plugin: plugin output count " + << effect->getAudioOutputCount() + << " != our channel count " << m_channelCount + << " (future errors for this plugin will be suppressed)" + << endl; + m_failed = true; + } + } + + if (m_failed) { + return m_source->getSourceSamples(samples, nchannels, nframes); + } + + float **ib = effect->getAudioInputBuffers(); + float **ob = effect->getAudioOutputBuffers(); + int blockSize = effect->getBufferSize(); + + int got = 0; + int offset = 0; + + while (got < nframes) { + + int read = 0; + for (int c = 0; c < nchannels; ++c) { + read = m_effectOutputBuffers[c].read(samples[c], nframes - got); + } + + got += read; + + if (got < nframes) { + + int toRun = m_source->getSourceSamples(ib, nchannels, blockSize); + if (toRun <= 0) break; + + effect->run(Vamp::RealTime::zeroTime, toRun); + + for (int c = 0; c < nchannels; ++c) { + m_effectOutputBuffers[c].write(ob[c], toRun); + } + } + } + + return got; +} + +void +EffectWrapper::setSystemPlaybackChannelCount(int count) +{ + { + lock_guard<mutex> guard(m_mutex); + m_effectOutputBuffers.resize + (count, RingBuffer<float>(DEFAULT_RING_BUFFER_SIZE)); + m_channelCount = count; + } + m_source->setSystemPlaybackChannelCount(count); +} + +void +EffectWrapper::setSystemPlaybackSampleRate(int rate) +{ + m_source->setSystemPlaybackSampleRate(rate); +} + +std::string +EffectWrapper::getClientName() const +{ + return m_source->getClientName(); +} + +int +EffectWrapper::getApplicationSampleRate() const +{ + return m_source->getApplicationSampleRate(); +} + +int +EffectWrapper::getApplicationChannelCount() const +{ + return m_source->getApplicationChannelCount(); +} + +void +EffectWrapper::setSystemPlaybackBlockSize(int sz) +{ + SVDEBUG << "NOTE: EffectWrapper::setSystemPlaybackBlockSize called " + << "with size = " << sz << "; not passing to wrapped source, as " + << "actual block size will vary" << endl; +} + +void +EffectWrapper::setSystemPlaybackLatency(int latency) +{ + m_source->setSystemPlaybackLatency(latency); +} + +void +EffectWrapper::setOutputLevels(float left, float right) +{ + m_source->setOutputLevels(left, right); +} + +void +EffectWrapper::audioProcessingOverload() +{ + m_source->audioProcessingOverload(); +}