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@740
|
21 //#define DEBUG_EFFECT_WRAPPER 1
|
Chris@740
|
22
|
Chris@739
|
23 using namespace std;
|
Chris@739
|
24
|
Chris@739
|
25 static const int DEFAULT_RING_BUFFER_SIZE = 131071;
|
Chris@739
|
26
|
Chris@739
|
27 EffectWrapper::EffectWrapper(ApplicationPlaybackSource *source) :
|
Chris@739
|
28 m_source(source),
|
Chris@739
|
29 m_bypassed(false),
|
Chris@739
|
30 m_failed(false),
|
Chris@739
|
31 m_channelCount(0)
|
Chris@739
|
32 {
|
Chris@739
|
33 }
|
Chris@739
|
34
|
Chris@739
|
35 EffectWrapper::~EffectWrapper()
|
Chris@739
|
36 {
|
Chris@739
|
37 }
|
Chris@739
|
38
|
Chris@739
|
39 void
|
Chris@739
|
40 EffectWrapper::setEffect(weak_ptr<RealTimePluginInstance> effect)
|
Chris@739
|
41 {
|
Chris@739
|
42 lock_guard<mutex> guard(m_mutex);
|
Chris@739
|
43
|
Chris@740
|
44 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
45 SVCERR << "EffectWrapper[" << this
|
Chris@740
|
46 << "]::setEffect(" << effect.lock() << ")" << endl;
|
Chris@740
|
47 #endif
|
Chris@740
|
48
|
Chris@739
|
49 m_effect = effect;
|
Chris@739
|
50 m_failed = false;
|
Chris@739
|
51 }
|
Chris@739
|
52
|
Chris@749
|
53 bool
|
Chris@749
|
54 EffectWrapper::haveEffect() const
|
Chris@749
|
55 {
|
Chris@749
|
56 return m_effect.lock() != nullptr;
|
Chris@749
|
57 }
|
Chris@749
|
58
|
Chris@749
|
59 void
|
Chris@749
|
60 EffectWrapper::clearEffect()
|
Chris@749
|
61 {
|
Chris@749
|
62 m_effect = {};
|
Chris@749
|
63 }
|
Chris@749
|
64
|
Chris@739
|
65 void
|
Chris@739
|
66 EffectWrapper::setBypassed(bool bypassed)
|
Chris@739
|
67 {
|
Chris@739
|
68 lock_guard<mutex> guard(m_mutex);
|
Chris@739
|
69
|
Chris@740
|
70 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
71 SVCERR << "EffectWrapper[" << this
|
Chris@740
|
72 << "]::setBypassed(" << bypassed << ")" << endl;
|
Chris@740
|
73 #endif
|
Chris@740
|
74
|
Chris@739
|
75 m_bypassed = bypassed;
|
Chris@739
|
76 }
|
Chris@739
|
77
|
Chris@739
|
78 bool
|
Chris@739
|
79 EffectWrapper::isBypassed() const
|
Chris@739
|
80 {
|
Chris@739
|
81 lock_guard<mutex> guard(m_mutex);
|
Chris@739
|
82
|
Chris@739
|
83 return m_bypassed;
|
Chris@739
|
84 }
|
Chris@739
|
85
|
Chris@739
|
86 void
|
Chris@739
|
87 EffectWrapper::reset()
|
Chris@739
|
88 {
|
Chris@739
|
89 lock_guard<mutex> guard(m_mutex);
|
Chris@739
|
90
|
Chris@740
|
91 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
92 SVCERR << "EffectWrapper[" << this << "]::reset" << endl;
|
Chris@740
|
93 #endif
|
Chris@740
|
94
|
Chris@739
|
95 for (auto &rb: m_effectOutputBuffers) {
|
Chris@739
|
96 rb.reset();
|
Chris@739
|
97 }
|
Chris@740
|
98
|
Chris@740
|
99 m_failed = false;
|
Chris@739
|
100 }
|
Chris@739
|
101
|
Chris@739
|
102 int
|
Chris@739
|
103 EffectWrapper::getSourceSamples(float *const *samples,
|
Chris@739
|
104 int nchannels, int nframes)
|
Chris@739
|
105 {
|
Chris@739
|
106 lock_guard<mutex> guard(m_mutex);
|
Chris@739
|
107
|
Chris@740
|
108 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
109 SVCERR << "EffectWrapper[" << this << "]::getSourceSamples: " << nframes
|
Chris@740
|
110 << " frames across " << nchannels << " channels" << endl;
|
Chris@740
|
111 #endif
|
Chris@740
|
112
|
Chris@739
|
113 auto effect(m_effect.lock());
|
Chris@739
|
114
|
Chris@740
|
115 if (!effect) {
|
Chris@740
|
116 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
117 SVCERR << "EffectWrapper::getSourceSamples: "
|
Chris@740
|
118 << "no effect is set" << endl;
|
Chris@740
|
119 #endif
|
Chris@739
|
120 return m_source->getSourceSamples(samples, nchannels, nframes);
|
Chris@739
|
121 }
|
Chris@739
|
122
|
Chris@740
|
123 if (m_bypassed || m_failed) {
|
Chris@740
|
124 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
125 SVCERR << "EffectWrapper::getSourceSamples: "
|
Chris@740
|
126 << "effect is bypassed or has failed" << endl;
|
Chris@740
|
127 #endif
|
Chris@740
|
128 return m_source->getSourceSamples(samples, nchannels, nframes);
|
Chris@740
|
129 }
|
Chris@740
|
130
|
Chris@739
|
131 static int warnings = 0;
|
Chris@739
|
132 if (nchannels != m_channelCount) {
|
Chris@739
|
133 if (warnings >= 0) {
|
Chris@740
|
134 SVCERR << "WARNING: EffectWrapper::getSourceSamples called for a number of channels different from that set with setSystemPlaybackChannelCount ("
|
Chris@739
|
135 << nchannels << " vs " << m_channelCount << ")" << endl;
|
Chris@739
|
136 if (++warnings == 6) {
|
Chris@739
|
137 SVCERR << "(further warnings will be suppressed)" << endl;
|
Chris@739
|
138 warnings = -1;
|
Chris@739
|
139 }
|
Chris@739
|
140 }
|
Chris@739
|
141 return 0;
|
Chris@739
|
142 }
|
Chris@739
|
143
|
Chris@739
|
144 if ((int)effect->getAudioInputCount() != m_channelCount) {
|
Chris@739
|
145 if (!m_failed) {
|
Chris@739
|
146 SVCERR << "EffectWrapper::getSourceSamples: "
|
Chris@739
|
147 << "Can't run plugin: plugin input count "
|
Chris@739
|
148 << effect->getAudioInputCount()
|
Chris@739
|
149 << " != our channel count " << m_channelCount
|
Chris@739
|
150 << " (future errors for this plugin will be suppressed)"
|
Chris@739
|
151 << endl;
|
Chris@739
|
152 m_failed = true;
|
Chris@739
|
153 }
|
Chris@739
|
154 }
|
Chris@739
|
155 if ((int)effect->getAudioOutputCount() != m_channelCount) {
|
Chris@739
|
156 if (!m_failed) {
|
Chris@739
|
157 SVCERR << "EffectWrapper::getSourceSamples: "
|
Chris@739
|
158 << "Can't run plugin: plugin output count "
|
Chris@739
|
159 << effect->getAudioOutputCount()
|
Chris@739
|
160 << " != our channel count " << m_channelCount
|
Chris@739
|
161 << " (future errors for this plugin will be suppressed)"
|
Chris@739
|
162 << endl;
|
Chris@739
|
163 m_failed = true;
|
Chris@739
|
164 }
|
Chris@739
|
165 }
|
Chris@739
|
166
|
Chris@739
|
167 if (m_failed) {
|
Chris@739
|
168 return m_source->getSourceSamples(samples, nchannels, nframes);
|
Chris@739
|
169 }
|
Chris@739
|
170
|
Chris@739
|
171 float **ib = effect->getAudioInputBuffers();
|
Chris@739
|
172 float **ob = effect->getAudioOutputBuffers();
|
Chris@739
|
173 int blockSize = effect->getBufferSize();
|
Chris@739
|
174
|
Chris@739
|
175 int got = 0;
|
Chris@739
|
176
|
Chris@739
|
177 while (got < nframes) {
|
Chris@739
|
178
|
Chris@739
|
179 int read = 0;
|
Chris@739
|
180 for (int c = 0; c < nchannels; ++c) {
|
Chris@740
|
181 read = m_effectOutputBuffers[c].read(samples[c] + got,
|
Chris@740
|
182 nframes - got);
|
Chris@739
|
183 }
|
Chris@739
|
184
|
Chris@739
|
185 got += read;
|
Chris@739
|
186
|
Chris@739
|
187 if (got < nframes) {
|
Chris@739
|
188
|
Chris@739
|
189 int toRun = m_source->getSourceSamples(ib, nchannels, blockSize);
|
Chris@739
|
190 if (toRun <= 0) break;
|
Chris@739
|
191
|
Chris@740
|
192 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
193 SVCERR << "EffectWrapper::getSourceSamples: Running effect "
|
Chris@740
|
194 << "for " << toRun << " frames" << endl;
|
Chris@740
|
195 #endif
|
Chris@739
|
196 effect->run(Vamp::RealTime::zeroTime, toRun);
|
Chris@739
|
197
|
Chris@739
|
198 for (int c = 0; c < nchannels; ++c) {
|
Chris@739
|
199 m_effectOutputBuffers[c].write(ob[c], toRun);
|
Chris@739
|
200 }
|
Chris@739
|
201 }
|
Chris@739
|
202 }
|
Chris@739
|
203
|
Chris@739
|
204 return got;
|
Chris@739
|
205 }
|
Chris@739
|
206
|
Chris@739
|
207 void
|
Chris@739
|
208 EffectWrapper::setSystemPlaybackChannelCount(int count)
|
Chris@739
|
209 {
|
Chris@739
|
210 {
|
Chris@739
|
211 lock_guard<mutex> guard(m_mutex);
|
Chris@740
|
212 #ifdef DEBUG_EFFECT_WRAPPER
|
Chris@740
|
213 SVCERR << "EffectWrapper[" << this
|
Chris@740
|
214 << "]::setSystemPlaybackChannelCount(" << count << ")" << endl;
|
Chris@740
|
215 #endif
|
Chris@739
|
216 m_effectOutputBuffers.resize
|
Chris@739
|
217 (count, RingBuffer<float>(DEFAULT_RING_BUFFER_SIZE));
|
Chris@739
|
218 m_channelCount = count;
|
Chris@739
|
219 }
|
Chris@739
|
220 m_source->setSystemPlaybackChannelCount(count);
|
Chris@739
|
221 }
|
Chris@739
|
222
|
Chris@739
|
223 void
|
Chris@739
|
224 EffectWrapper::setSystemPlaybackSampleRate(int rate)
|
Chris@739
|
225 {
|
Chris@739
|
226 m_source->setSystemPlaybackSampleRate(rate);
|
Chris@739
|
227 }
|
Chris@739
|
228
|
Chris@739
|
229 std::string
|
Chris@739
|
230 EffectWrapper::getClientName() const
|
Chris@739
|
231 {
|
Chris@739
|
232 return m_source->getClientName();
|
Chris@739
|
233 }
|
Chris@739
|
234
|
Chris@739
|
235 int
|
Chris@739
|
236 EffectWrapper::getApplicationSampleRate() const
|
Chris@739
|
237 {
|
Chris@739
|
238 return m_source->getApplicationSampleRate();
|
Chris@739
|
239 }
|
Chris@739
|
240
|
Chris@739
|
241 int
|
Chris@739
|
242 EffectWrapper::getApplicationChannelCount() const
|
Chris@739
|
243 {
|
Chris@739
|
244 return m_source->getApplicationChannelCount();
|
Chris@739
|
245 }
|
Chris@739
|
246
|
Chris@739
|
247 void
|
Chris@739
|
248 EffectWrapper::setSystemPlaybackBlockSize(int sz)
|
Chris@739
|
249 {
|
Chris@739
|
250 SVDEBUG << "NOTE: EffectWrapper::setSystemPlaybackBlockSize called "
|
Chris@739
|
251 << "with size = " << sz << "; not passing to wrapped source, as "
|
Chris@739
|
252 << "actual block size will vary" << endl;
|
Chris@739
|
253 }
|
Chris@739
|
254
|
Chris@739
|
255 void
|
Chris@739
|
256 EffectWrapper::setSystemPlaybackLatency(int latency)
|
Chris@739
|
257 {
|
Chris@739
|
258 m_source->setSystemPlaybackLatency(latency);
|
Chris@739
|
259 }
|
Chris@739
|
260
|
Chris@739
|
261 void
|
Chris@739
|
262 EffectWrapper::setOutputLevels(float left, float right)
|
Chris@739
|
263 {
|
Chris@739
|
264 m_source->setOutputLevels(left, right);
|
Chris@739
|
265 }
|
Chris@739
|
266
|
Chris@739
|
267 void
|
Chris@739
|
268 EffectWrapper::audioProcessingOverload()
|
Chris@739
|
269 {
|
Chris@739
|
270 m_source->audioProcessingOverload();
|
Chris@739
|
271 }
|