annotate 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
rev   line source
Chris@739 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
Chris@739 2
Chris@739 3 /*
Chris@739 4 Sonic Visualiser
Chris@739 5 An audio file viewer and annotation editor.
Chris@739 6 Centre for Digital Music, Queen Mary, University of London.
Chris@739 7
Chris@739 8 This program is free software; you can redistribute it and/or
Chris@739 9 modify it under the terms of the GNU General Public License as
Chris@739 10 published by the Free Software Foundation; either version 2 of the
Chris@739 11 License, or (at your option) any later version. See the file
Chris@739 12 COPYING included with this distribution for more information.
Chris@739 13 */
Chris@739 14
Chris@739 15 #include "EffectWrapper.h"
Chris@739 16
Chris@739 17 #include <rubberband/RubberBandStretcher.h>
Chris@739 18
Chris@739 19 #include "base/Debug.h"
Chris@739 20
Chris@739 21 using namespace std;
Chris@739 22
Chris@739 23 static const int DEFAULT_RING_BUFFER_SIZE = 131071;
Chris@739 24
Chris@739 25 EffectWrapper::EffectWrapper(ApplicationPlaybackSource *source) :
Chris@739 26 m_source(source),
Chris@739 27 m_bypassed(false),
Chris@739 28 m_failed(false),
Chris@739 29 m_channelCount(0)
Chris@739 30 {
Chris@739 31 }
Chris@739 32
Chris@739 33 EffectWrapper::~EffectWrapper()
Chris@739 34 {
Chris@739 35 }
Chris@739 36
Chris@739 37 void
Chris@739 38 EffectWrapper::setEffect(weak_ptr<RealTimePluginInstance> effect)
Chris@739 39 {
Chris@739 40 lock_guard<mutex> guard(m_mutex);
Chris@739 41
Chris@739 42 m_effect = effect;
Chris@739 43 m_failed = false;
Chris@739 44 }
Chris@739 45
Chris@739 46 void
Chris@739 47 EffectWrapper::setBypassed(bool bypassed)
Chris@739 48 {
Chris@739 49 lock_guard<mutex> guard(m_mutex);
Chris@739 50
Chris@739 51 m_bypassed = bypassed;
Chris@739 52 }
Chris@739 53
Chris@739 54 bool
Chris@739 55 EffectWrapper::isBypassed() const
Chris@739 56 {
Chris@739 57 lock_guard<mutex> guard(m_mutex);
Chris@739 58
Chris@739 59 return m_bypassed;
Chris@739 60 }
Chris@739 61
Chris@739 62 void
Chris@739 63 EffectWrapper::reset()
Chris@739 64 {
Chris@739 65 lock_guard<mutex> guard(m_mutex);
Chris@739 66
Chris@739 67 for (auto &rb: m_effectOutputBuffers) {
Chris@739 68 rb.reset();
Chris@739 69 }
Chris@739 70 }
Chris@739 71
Chris@739 72 int
Chris@739 73 EffectWrapper::getSourceSamples(float *const *samples,
Chris@739 74 int nchannels, int nframes)
Chris@739 75 {
Chris@739 76 lock_guard<mutex> guard(m_mutex);
Chris@739 77
Chris@739 78 auto effect(m_effect.lock());
Chris@739 79
Chris@739 80 if (!effect || m_bypassed || m_failed) {
Chris@739 81 return m_source->getSourceSamples(samples, nchannels, nframes);
Chris@739 82 }
Chris@739 83
Chris@739 84 static int warnings = 0;
Chris@739 85 if (nchannels != m_channelCount) {
Chris@739 86 if (warnings >= 0) {
Chris@739 87 SVCERR << "WARNING: getSourceSamples called for a number of channels different from that set with setSystemPlaybackChannelCount ("
Chris@739 88 << nchannels << " vs " << m_channelCount << ")" << endl;
Chris@739 89 if (++warnings == 6) {
Chris@739 90 SVCERR << "(further warnings will be suppressed)" << endl;
Chris@739 91 warnings = -1;
Chris@739 92 }
Chris@739 93 }
Chris@739 94 return 0;
Chris@739 95 }
Chris@739 96
Chris@739 97 if ((int)effect->getAudioInputCount() != m_channelCount) {
Chris@739 98 if (!m_failed) {
Chris@739 99 SVCERR << "EffectWrapper::getSourceSamples: "
Chris@739 100 << "Can't run plugin: plugin input count "
Chris@739 101 << effect->getAudioInputCount()
Chris@739 102 << " != our channel count " << m_channelCount
Chris@739 103 << " (future errors for this plugin will be suppressed)"
Chris@739 104 << endl;
Chris@739 105 m_failed = true;
Chris@739 106 }
Chris@739 107 }
Chris@739 108 if ((int)effect->getAudioOutputCount() != m_channelCount) {
Chris@739 109 if (!m_failed) {
Chris@739 110 SVCERR << "EffectWrapper::getSourceSamples: "
Chris@739 111 << "Can't run plugin: plugin output count "
Chris@739 112 << effect->getAudioOutputCount()
Chris@739 113 << " != our channel count " << m_channelCount
Chris@739 114 << " (future errors for this plugin will be suppressed)"
Chris@739 115 << endl;
Chris@739 116 m_failed = true;
Chris@739 117 }
Chris@739 118 }
Chris@739 119
Chris@739 120 if (m_failed) {
Chris@739 121 return m_source->getSourceSamples(samples, nchannels, nframes);
Chris@739 122 }
Chris@739 123
Chris@739 124 float **ib = effect->getAudioInputBuffers();
Chris@739 125 float **ob = effect->getAudioOutputBuffers();
Chris@739 126 int blockSize = effect->getBufferSize();
Chris@739 127
Chris@739 128 int got = 0;
Chris@739 129 int offset = 0;
Chris@739 130
Chris@739 131 while (got < nframes) {
Chris@739 132
Chris@739 133 int read = 0;
Chris@739 134 for (int c = 0; c < nchannels; ++c) {
Chris@739 135 read = m_effectOutputBuffers[c].read(samples[c], nframes - got);
Chris@739 136 }
Chris@739 137
Chris@739 138 got += read;
Chris@739 139
Chris@739 140 if (got < nframes) {
Chris@739 141
Chris@739 142 int toRun = m_source->getSourceSamples(ib, nchannels, blockSize);
Chris@739 143 if (toRun <= 0) break;
Chris@739 144
Chris@739 145 effect->run(Vamp::RealTime::zeroTime, toRun);
Chris@739 146
Chris@739 147 for (int c = 0; c < nchannels; ++c) {
Chris@739 148 m_effectOutputBuffers[c].write(ob[c], toRun);
Chris@739 149 }
Chris@739 150 }
Chris@739 151 }
Chris@739 152
Chris@739 153 return got;
Chris@739 154 }
Chris@739 155
Chris@739 156 void
Chris@739 157 EffectWrapper::setSystemPlaybackChannelCount(int count)
Chris@739 158 {
Chris@739 159 {
Chris@739 160 lock_guard<mutex> guard(m_mutex);
Chris@739 161 m_effectOutputBuffers.resize
Chris@739 162 (count, RingBuffer<float>(DEFAULT_RING_BUFFER_SIZE));
Chris@739 163 m_channelCount = count;
Chris@739 164 }
Chris@739 165 m_source->setSystemPlaybackChannelCount(count);
Chris@739 166 }
Chris@739 167
Chris@739 168 void
Chris@739 169 EffectWrapper::setSystemPlaybackSampleRate(int rate)
Chris@739 170 {
Chris@739 171 m_source->setSystemPlaybackSampleRate(rate);
Chris@739 172 }
Chris@739 173
Chris@739 174 std::string
Chris@739 175 EffectWrapper::getClientName() const
Chris@739 176 {
Chris@739 177 return m_source->getClientName();
Chris@739 178 }
Chris@739 179
Chris@739 180 int
Chris@739 181 EffectWrapper::getApplicationSampleRate() const
Chris@739 182 {
Chris@739 183 return m_source->getApplicationSampleRate();
Chris@739 184 }
Chris@739 185
Chris@739 186 int
Chris@739 187 EffectWrapper::getApplicationChannelCount() const
Chris@739 188 {
Chris@739 189 return m_source->getApplicationChannelCount();
Chris@739 190 }
Chris@739 191
Chris@739 192 void
Chris@739 193 EffectWrapper::setSystemPlaybackBlockSize(int sz)
Chris@739 194 {
Chris@739 195 SVDEBUG << "NOTE: EffectWrapper::setSystemPlaybackBlockSize called "
Chris@739 196 << "with size = " << sz << "; not passing to wrapped source, as "
Chris@739 197 << "actual block size will vary" << endl;
Chris@739 198 }
Chris@739 199
Chris@739 200 void
Chris@739 201 EffectWrapper::setSystemPlaybackLatency(int latency)
Chris@739 202 {
Chris@739 203 m_source->setSystemPlaybackLatency(latency);
Chris@739 204 }
Chris@739 205
Chris@739 206 void
Chris@739 207 EffectWrapper::setOutputLevels(float left, float right)
Chris@739 208 {
Chris@739 209 m_source->setOutputLevels(left, right);
Chris@739 210 }
Chris@739 211
Chris@739 212 void
Chris@739 213 EffectWrapper::audioProcessingOverload()
Chris@739 214 {
Chris@739 215 m_source->audioProcessingOverload();
Chris@739 216 }