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