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 }
|