comparison audio/EffectWrapper.cpp @ 746:771ec060c1d2

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