comparison vamp-hostsdk/PluginInputDomainAdapter.cpp @ 56:4ab6224110ef host-factory-stuff

* implement plugin loader and plugin input-domain adapter (to do basic ffts)
author cannam
date Fri, 04 May 2007 15:21:12 +0000
parents
children 09a1aac6c362
comparison
equal deleted inserted replaced
55:0dad357a3406 56:4ab6224110ef
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2
3 /*
4 Vamp
5
6 An API for audio analysis and feature extraction plugins.
7
8 Centre for Digital Music, Queen Mary, University of London.
9 Copyright 2006 Chris Cannam.
10
11 Permission is hereby granted, free of charge, to any person
12 obtaining a copy of this software and associated documentation
13 files (the "Software"), to deal in the Software without
14 restriction, including without limitation the rights to use, copy,
15 modify, merge, publish, distribute, sublicense, and/or sell copies
16 of the Software, and to permit persons to whom the Software is
17 furnished to do so, subject to the following conditions:
18
19 The above copyright notice and this permission notice shall be
20 included in all copies or substantial portions of the Software.
21
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
26 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
27 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
29
30 Except as contained in this notice, the names of the Centre for
31 Digital Music; Queen Mary, University of London; and Chris Cannam
32 shall not be used in advertising or otherwise to promote the sale,
33 use or other dealings in this Software without prior written
34 authorization.
35 */
36
37 #include "PluginInputDomainAdapter.h"
38
39 #include <cmath>
40
41 namespace Vamp {
42
43 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
44 Plugin(0),
45 m_plugin(plugin),
46 m_channels(0),
47 m_blockSize(0),
48 m_freqbuf(0)
49 {
50 }
51
52 PluginInputDomainAdapter::~PluginInputDomainAdapter()
53 {
54 delete m_plugin;
55 }
56
57 bool
58 PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
59 {
60 //!!! complain and die if blocksize is not a power of 2
61
62 if (m_plugin->getInputDomain() == FrequencyDomain) {
63 if (m_channels > 0) {
64 for (size_t c = 0; c < m_channels; ++c) {
65 delete[] m_freqbuf[c];
66 }
67 delete[] m_freqbuf;
68 delete[] m_ri;
69 delete[] m_ro;
70 delete[] m_io;
71 }
72 }
73
74 m_channels = channels;
75 m_blockSize = blockSize;
76
77 if (m_plugin->getInputDomain() == FrequencyDomain) {
78 m_freqbuf = new float *[m_channels];
79 for (size_t c = 0; c < m_channels; ++c) {
80 m_freqbuf[c] = new float[m_blockSize + 2];
81 }
82 m_ri = new double[m_blockSize];
83 m_ro = new double[m_blockSize];
84 m_io = new double[m_blockSize];
85 }
86
87 return m_plugin->initialise(channels, stepSize, blockSize);
88 }
89
90 void
91 PluginInputDomainAdapter::reset()
92 {
93 m_plugin->reset();
94 }
95
96 unsigned int
97 PluginInputDomainAdapter::getVampApiVersion() const
98 {
99 return m_plugin->getVampApiVersion();
100 }
101
102 std::string
103 PluginInputDomainAdapter::getIdentifier() const
104 {
105 return m_plugin->getIdentifier();
106 }
107
108 std::string
109 PluginInputDomainAdapter::getName() const
110 {
111 return m_plugin->getName();
112 }
113
114 std::string
115 PluginInputDomainAdapter::getDescription() const
116 {
117 return m_plugin->getDescription();
118 }
119
120 std::string
121 PluginInputDomainAdapter::getMaker() const
122 {
123 return m_plugin->getMaker();
124 }
125
126 int
127 PluginInputDomainAdapter::getPluginVersion() const
128 {
129 return m_plugin->getPluginVersion();
130 }
131
132 std::string
133 PluginInputDomainAdapter::getCopyright() const
134 {
135 return m_plugin->getCopyright();
136 }
137
138 PluginBase::ParameterList
139 PluginInputDomainAdapter::getParameterDescriptors() const
140 {
141 return m_plugin->getParameterDescriptors();
142 }
143
144 float
145 PluginInputDomainAdapter::getParameter(std::string parameter) const
146 {
147 return m_plugin->getParameter(parameter);
148 }
149
150 void
151 PluginInputDomainAdapter::setParameter(std::string parameter, float value)
152 {
153 m_plugin->setParameter(parameter, value);
154 }
155
156 PluginBase::ProgramList
157 PluginInputDomainAdapter::getPrograms() const
158 {
159 return m_plugin->getPrograms();
160 }
161
162 std::string
163 PluginInputDomainAdapter::getCurrentProgram() const
164 {
165 return m_plugin->getCurrentProgram();
166 }
167
168 void
169 PluginInputDomainAdapter::selectProgram(std::string program)
170 {
171 m_plugin->selectProgram(program);
172 }
173
174 size_t
175 PluginInputDomainAdapter::getPreferredStepSize() const
176 {
177 size_t step = m_plugin->getPreferredStepSize();
178
179 if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
180 step = getPreferredBlockSize() / 2;
181 }
182
183 return step;
184 }
185
186 size_t
187 PluginInputDomainAdapter::getPreferredBlockSize() const
188 {
189 size_t block = m_plugin->getPreferredBlockSize();
190
191 if (block == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
192 block = 1024;
193 }
194
195 return block;
196 }
197
198 size_t
199 PluginInputDomainAdapter::getMinChannelCount() const
200 {
201 return m_plugin->getMinChannelCount();
202 }
203
204 size_t PluginInputDomainAdapter::getMaxChannelCount() const
205 {
206 return m_plugin->getMaxChannelCount();
207 }
208
209 Plugin::OutputList
210 PluginInputDomainAdapter::getOutputDescriptors() const
211 {
212 return m_plugin->getOutputDescriptors();
213 }
214
215 Plugin::FeatureSet
216 PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
217 {
218 if (m_plugin->getInputDomain() == TimeDomain) {
219 return m_plugin->process(inputBuffers, timestamp);
220 }
221
222 for (size_t c = 0; c < m_channels; ++c) {
223
224 for (size_t i = 0; i < m_blockSize; ++i) {
225 // Hanning window
226 m_ri[i] = double(inputBuffers[c][i])
227 * (0.50 - 0.50 * cos((2 * M_PI * i)
228 / m_blockSize));
229 }
230
231 for (size_t i = 0; i < m_blockSize/2; ++i) {
232 // FFT shift
233 double value = m_ri[i];
234 m_ri[i] = m_ri[i + m_blockSize/2];
235 m_ri[i + m_blockSize/2] = value;
236 }
237
238 fft(m_blockSize, false, m_ri, 0, m_ro, m_io);
239
240 for (size_t i = 0; i < m_blockSize/2; ++i) {
241 m_freqbuf[c][i * 2] = m_ro[i];
242 m_freqbuf[c][i * 2 + 1] = m_io[i];
243 }
244 }
245
246 //!!! do we want to adjust the timestamp or anything so as to
247 // effectively centre the frame?
248
249 return m_plugin->process(m_freqbuf, timestamp);
250 }
251
252 Plugin::FeatureSet
253 PluginInputDomainAdapter::getRemainingFeatures()
254 {
255 return m_plugin->getRemainingFeatures();
256 }
257
258 void
259 PluginInputDomainAdapter::fft(unsigned int n, bool inverse,
260 double *ri, double *ii, double *ro, double *io)
261 {
262 if (!ri || !ro || !io) return;
263
264 unsigned int bits;
265 unsigned int i, j, k, m;
266 unsigned int blockSize, blockEnd;
267
268 double tr, ti;
269
270 if (n < 2) return;
271 if (n & (n-1)) return;
272
273 double angle = 2.0 * M_PI;
274 if (inverse) angle = -angle;
275
276 for (i = 0; ; ++i) {
277 if (n & (1 << i)) {
278 bits = i;
279 break;
280 }
281 }
282
283 static unsigned int tableSize = 0;
284 static int *table = 0;
285
286 if (tableSize != n) {
287
288 delete[] table;
289
290 table = new int[n];
291
292 for (i = 0; i < n; ++i) {
293
294 m = i;
295
296 for (j = k = 0; j < bits; ++j) {
297 k = (k << 1) | (m & 1);
298 m >>= 1;
299 }
300
301 table[i] = k;
302 }
303
304 tableSize = n;
305 }
306
307 if (ii) {
308 for (i = 0; i < n; ++i) {
309 ro[table[i]] = ri[i];
310 io[table[i]] = ii[i];
311 }
312 } else {
313 for (i = 0; i < n; ++i) {
314 ro[table[i]] = ri[i];
315 io[table[i]] = 0.0;
316 }
317 }
318
319 blockEnd = 1;
320
321 for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
322
323 double delta = angle / (double)blockSize;
324 double sm2 = -sin(-2 * delta);
325 double sm1 = -sin(-delta);
326 double cm2 = cos(-2 * delta);
327 double cm1 = cos(-delta);
328 double w = 2 * cm1;
329 double ar[3], ai[3];
330
331 for (i = 0; i < n; i += blockSize) {
332
333 ar[2] = cm2;
334 ar[1] = cm1;
335
336 ai[2] = sm2;
337 ai[1] = sm1;
338
339 for (j = i, m = 0; m < blockEnd; j++, m++) {
340
341 ar[0] = w * ar[1] - ar[2];
342 ar[2] = ar[1];
343 ar[1] = ar[0];
344
345 ai[0] = w * ai[1] - ai[2];
346 ai[2] = ai[1];
347 ai[1] = ai[0];
348
349 k = j + blockEnd;
350 tr = ar[0] * ro[k] - ai[0] * io[k];
351 ti = ar[0] * io[k] + ai[0] * ro[k];
352
353 ro[k] = ro[j] - tr;
354 io[k] = io[j] - ti;
355
356 ro[j] += tr;
357 io[j] += ti;
358 }
359 }
360
361 blockEnd = blockSize;
362 }
363
364 if (inverse) {
365
366 double denom = (double)n;
367
368 for (i = 0; i < n; i++) {
369 ro[i] /= denom;
370 io[i] /= denom;
371 }
372 }
373 }
374
375
376 }
377