cannam@233
|
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
|
cannam@233
|
2
|
cannam@233
|
3 /*
|
cannam@233
|
4 Vamp
|
cannam@233
|
5
|
cannam@233
|
6 An API for audio analysis and feature extraction plugins.
|
cannam@233
|
7
|
cannam@233
|
8 Centre for Digital Music, Queen Mary, University of London.
|
cannam@290
|
9 Copyright 2006-2009 Chris Cannam and QMUL.
|
cannam@233
|
10
|
cannam@233
|
11 This file is based in part on Don Cross's public domain FFT
|
cannam@233
|
12 implementation.
|
cannam@233
|
13
|
cannam@233
|
14 Permission is hereby granted, free of charge, to any person
|
cannam@233
|
15 obtaining a copy of this software and associated documentation
|
cannam@233
|
16 files (the "Software"), to deal in the Software without
|
cannam@233
|
17 restriction, including without limitation the rights to use, copy,
|
cannam@233
|
18 modify, merge, publish, distribute, sublicense, and/or sell copies
|
cannam@233
|
19 of the Software, and to permit persons to whom the Software is
|
cannam@233
|
20 furnished to do so, subject to the following conditions:
|
cannam@233
|
21
|
cannam@233
|
22 The above copyright notice and this permission notice shall be
|
cannam@233
|
23 included in all copies or substantial portions of the Software.
|
cannam@233
|
24
|
cannam@233
|
25 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
cannam@233
|
26 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
cannam@233
|
27 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
cannam@233
|
28 NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
|
cannam@233
|
29 ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
|
cannam@233
|
30 CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
cannam@233
|
31 WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
cannam@233
|
32
|
cannam@233
|
33 Except as contained in this notice, the names of the Centre for
|
cannam@233
|
34 Digital Music; Queen Mary, University of London; and Chris Cannam
|
cannam@233
|
35 shall not be used in advertising or otherwise to promote the sale,
|
cannam@233
|
36 use or other dealings in this Software without prior written
|
cannam@233
|
37 authorization.
|
cannam@233
|
38 */
|
cannam@233
|
39
|
cannam@233
|
40 #include <vamp-hostsdk/PluginInputDomainAdapter.h>
|
cannam@233
|
41
|
cannam@233
|
42 #include <cmath>
|
cannam@233
|
43
|
Chris@317
|
44 #include "Window.h"
|
Chris@317
|
45
|
Chris@434
|
46 #include <stdlib.h>
|
Chris@434
|
47 #include <stdio.h>
|
Chris@434
|
48 #include <math.h>
|
Chris@434
|
49 #include <string.h>
|
Chris@434
|
50 #include <limits.h>
|
cannam@233
|
51
|
Chris@445
|
52 _VAMP_SDK_HOSTSPACE_BEGIN(PluginInputDomainAdapter.cpp)
|
Chris@444
|
53
|
Chris@445
|
54 #include "../vamp-sdk/FFTimpl.cpp"
|
cannam@263
|
55
|
cannam@233
|
56 namespace Vamp {
|
cannam@233
|
57
|
cannam@233
|
58 namespace HostExt {
|
cannam@233
|
59
|
cannam@233
|
60 class PluginInputDomainAdapter::Impl
|
cannam@233
|
61 {
|
cannam@233
|
62 public:
|
cannam@233
|
63 Impl(Plugin *plugin, float inputSampleRate);
|
cannam@233
|
64 ~Impl();
|
cannam@233
|
65
|
cannam@233
|
66 bool initialise(size_t channels, size_t stepSize, size_t blockSize);
|
cannam@288
|
67 void reset();
|
cannam@233
|
68
|
cannam@233
|
69 size_t getPreferredStepSize() const;
|
cannam@233
|
70 size_t getPreferredBlockSize() const;
|
cannam@233
|
71
|
cannam@233
|
72 FeatureSet process(const float *const *inputBuffers, RealTime timestamp);
|
cannam@288
|
73
|
cannam@288
|
74 void setProcessTimestampMethod(ProcessTimestampMethod m);
|
cannam@288
|
75 ProcessTimestampMethod getProcessTimestampMethod() const;
|
cannam@233
|
76
|
cannam@233
|
77 RealTime getTimestampAdjustment() const;
|
cannam@233
|
78
|
Chris@317
|
79 WindowType getWindowType() const;
|
Chris@317
|
80 void setWindowType(WindowType type);
|
Chris@317
|
81
|
cannam@233
|
82 protected:
|
cannam@233
|
83 Plugin *m_plugin;
|
cannam@233
|
84 float m_inputSampleRate;
|
cannam@233
|
85 int m_channels;
|
cannam@288
|
86 int m_stepSize;
|
cannam@233
|
87 int m_blockSize;
|
cannam@233
|
88 float **m_freqbuf;
|
Chris@444
|
89 Kiss::kiss_fft_scalar *m_ri;
|
Chris@317
|
90
|
Chris@317
|
91 WindowType m_windowType;
|
Chris@444
|
92 typedef Window<Kiss::kiss_fft_scalar> W;
|
Chris@444
|
93 W *m_window;
|
cannam@233
|
94
|
cannam@288
|
95 ProcessTimestampMethod m_method;
|
cannam@288
|
96 int m_processCount;
|
cannam@289
|
97 float **m_shiftBuffers;
|
cannam@288
|
98
|
Chris@444
|
99 Kiss::kiss_fftr_cfg m_cfg;
|
Chris@444
|
100 Kiss::kiss_fft_cpx *m_cbuf;
|
cannam@233
|
101
|
cannam@289
|
102 FeatureSet processShiftingTimestamp(const float *const *inputBuffers, RealTime timestamp);
|
cannam@289
|
103 FeatureSet processShiftingData(const float *const *inputBuffers, RealTime timestamp);
|
cannam@289
|
104
|
cannam@233
|
105 size_t makeBlockSizeAcceptable(size_t) const;
|
Chris@317
|
106
|
Chris@444
|
107 W::WindowType convertType(WindowType t) const;
|
cannam@233
|
108 };
|
cannam@233
|
109
|
cannam@233
|
110 PluginInputDomainAdapter::PluginInputDomainAdapter(Plugin *plugin) :
|
cannam@233
|
111 PluginWrapper(plugin)
|
cannam@233
|
112 {
|
cannam@233
|
113 m_impl = new Impl(plugin, m_inputSampleRate);
|
cannam@233
|
114 }
|
cannam@233
|
115
|
cannam@233
|
116 PluginInputDomainAdapter::~PluginInputDomainAdapter()
|
cannam@233
|
117 {
|
cannam@233
|
118 delete m_impl;
|
cannam@233
|
119 }
|
cannam@233
|
120
|
cannam@233
|
121 bool
|
cannam@233
|
122 PluginInputDomainAdapter::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
cannam@233
|
123 {
|
cannam@233
|
124 return m_impl->initialise(channels, stepSize, blockSize);
|
cannam@233
|
125 }
|
cannam@233
|
126
|
cannam@288
|
127 void
|
cannam@288
|
128 PluginInputDomainAdapter::reset()
|
cannam@288
|
129 {
|
cannam@288
|
130 m_impl->reset();
|
cannam@288
|
131 }
|
cannam@288
|
132
|
cannam@233
|
133 Plugin::InputDomain
|
cannam@233
|
134 PluginInputDomainAdapter::getInputDomain() const
|
cannam@233
|
135 {
|
cannam@233
|
136 return TimeDomain;
|
cannam@233
|
137 }
|
cannam@233
|
138
|
cannam@233
|
139 size_t
|
cannam@233
|
140 PluginInputDomainAdapter::getPreferredStepSize() const
|
cannam@233
|
141 {
|
cannam@233
|
142 return m_impl->getPreferredStepSize();
|
cannam@233
|
143 }
|
cannam@233
|
144
|
cannam@233
|
145 size_t
|
cannam@233
|
146 PluginInputDomainAdapter::getPreferredBlockSize() const
|
cannam@233
|
147 {
|
cannam@233
|
148 return m_impl->getPreferredBlockSize();
|
cannam@233
|
149 }
|
cannam@233
|
150
|
cannam@233
|
151 Plugin::FeatureSet
|
cannam@233
|
152 PluginInputDomainAdapter::process(const float *const *inputBuffers, RealTime timestamp)
|
cannam@233
|
153 {
|
cannam@233
|
154 return m_impl->process(inputBuffers, timestamp);
|
cannam@233
|
155 }
|
cannam@233
|
156
|
cannam@288
|
157 void
|
cannam@288
|
158 PluginInputDomainAdapter::setProcessTimestampMethod(ProcessTimestampMethod m)
|
cannam@288
|
159 {
|
cannam@288
|
160 m_impl->setProcessTimestampMethod(m);
|
cannam@288
|
161 }
|
cannam@288
|
162
|
cannam@288
|
163 PluginInputDomainAdapter::ProcessTimestampMethod
|
cannam@288
|
164 PluginInputDomainAdapter::getProcessTimestampMethod() const
|
cannam@288
|
165 {
|
cannam@288
|
166 return m_impl->getProcessTimestampMethod();
|
cannam@288
|
167 }
|
cannam@288
|
168
|
cannam@233
|
169 RealTime
|
cannam@233
|
170 PluginInputDomainAdapter::getTimestampAdjustment() const
|
cannam@233
|
171 {
|
cannam@233
|
172 return m_impl->getTimestampAdjustment();
|
cannam@233
|
173 }
|
cannam@233
|
174
|
Chris@317
|
175 PluginInputDomainAdapter::WindowType
|
Chris@317
|
176 PluginInputDomainAdapter::getWindowType() const
|
Chris@317
|
177 {
|
Chris@317
|
178 return m_impl->getWindowType();
|
Chris@317
|
179 }
|
Chris@317
|
180
|
Chris@317
|
181 void
|
Chris@317
|
182 PluginInputDomainAdapter::setWindowType(WindowType w)
|
Chris@317
|
183 {
|
Chris@317
|
184 m_impl->setWindowType(w);
|
Chris@317
|
185 }
|
Chris@317
|
186
|
cannam@233
|
187
|
cannam@233
|
188 PluginInputDomainAdapter::Impl::Impl(Plugin *plugin, float inputSampleRate) :
|
cannam@233
|
189 m_plugin(plugin),
|
cannam@233
|
190 m_inputSampleRate(inputSampleRate),
|
cannam@233
|
191 m_channels(0),
|
cannam@288
|
192 m_stepSize(0),
|
cannam@233
|
193 m_blockSize(0),
|
cannam@233
|
194 m_freqbuf(0),
|
cannam@233
|
195 m_ri(0),
|
Chris@317
|
196 m_windowType(HanningWindow),
|
cannam@233
|
197 m_window(0),
|
cannam@288
|
198 m_method(ShiftTimestamp),
|
cannam@288
|
199 m_processCount(0),
|
cannam@289
|
200 m_shiftBuffers(0),
|
Chris@434
|
201 m_cfg(0),
|
cannam@233
|
202 m_cbuf(0)
|
cannam@233
|
203 {
|
cannam@233
|
204 }
|
cannam@233
|
205
|
cannam@233
|
206 PluginInputDomainAdapter::Impl::~Impl()
|
cannam@233
|
207 {
|
cannam@233
|
208 // the adapter will delete the plugin
|
cannam@233
|
209
|
cannam@289
|
210 if (m_shiftBuffers) {
|
cannam@289
|
211 for (int c = 0; c < m_channels; ++c) {
|
cannam@289
|
212 delete[] m_shiftBuffers[c];
|
cannam@289
|
213 }
|
cannam@289
|
214 delete[] m_shiftBuffers;
|
cannam@289
|
215 }
|
cannam@289
|
216
|
cannam@233
|
217 if (m_channels > 0) {
|
cannam@233
|
218 for (int c = 0; c < m_channels; ++c) {
|
cannam@233
|
219 delete[] m_freqbuf[c];
|
cannam@233
|
220 }
|
cannam@233
|
221 delete[] m_freqbuf;
|
Chris@435
|
222 delete[] m_ri;
|
Chris@434
|
223 if (m_cfg) {
|
Chris@444
|
224 Kiss::kiss_fftr_free(m_cfg);
|
Chris@435
|
225 m_cfg = 0;
|
Chris@434
|
226 delete[] m_cbuf;
|
Chris@435
|
227 m_cbuf = 0;
|
cannam@233
|
228 }
|
Chris@317
|
229 delete m_window;
|
cannam@233
|
230 }
|
cannam@233
|
231 }
|
cannam@233
|
232
|
cannam@233
|
233 // for some visual studii apparently
|
cannam@233
|
234 #ifndef M_PI
|
cannam@233
|
235 #define M_PI 3.14159265358979232846
|
cannam@233
|
236 #endif
|
cannam@233
|
237
|
cannam@233
|
238 bool
|
cannam@233
|
239 PluginInputDomainAdapter::Impl::initialise(size_t channels, size_t stepSize, size_t blockSize)
|
cannam@233
|
240 {
|
cannam@233
|
241 if (m_plugin->getInputDomain() == TimeDomain) {
|
cannam@233
|
242
|
cannam@288
|
243 m_stepSize = int(stepSize);
|
cannam@233
|
244 m_blockSize = int(blockSize);
|
cannam@233
|
245 m_channels = int(channels);
|
cannam@233
|
246
|
cannam@233
|
247 return m_plugin->initialise(channels, stepSize, blockSize);
|
cannam@233
|
248 }
|
cannam@233
|
249
|
cannam@233
|
250 if (blockSize < 2) {
|
cannam@283
|
251 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: blocksize < 2 not supported" << std::endl;
|
cannam@233
|
252 return false;
|
cannam@233
|
253 }
|
cannam@233
|
254
|
Chris@434
|
255 if (blockSize % 2) {
|
Chris@434
|
256 std::cerr << "ERROR: PluginInputDomainAdapter::initialise: odd blocksize " << blockSize << " not supported" << std::endl;
|
cannam@233
|
257 return false;
|
cannam@233
|
258 }
|
cannam@233
|
259
|
cannam@233
|
260 if (m_channels > 0) {
|
cannam@233
|
261 for (int c = 0; c < m_channels; ++c) {
|
cannam@233
|
262 delete[] m_freqbuf[c];
|
cannam@233
|
263 }
|
cannam@233
|
264 delete[] m_freqbuf;
|
Chris@435
|
265 delete[] m_ri;
|
Chris@434
|
266 if (m_cfg) {
|
Chris@444
|
267 Kiss::kiss_fftr_free(m_cfg);
|
Chris@435
|
268 m_cfg = 0;
|
Chris@434
|
269 delete[] m_cbuf;
|
Chris@435
|
270 m_cbuf = 0;
|
cannam@233
|
271 }
|
Chris@317
|
272 delete m_window;
|
cannam@233
|
273 }
|
cannam@233
|
274
|
cannam@288
|
275 m_stepSize = int(stepSize);
|
cannam@233
|
276 m_blockSize = int(blockSize);
|
cannam@233
|
277 m_channels = int(channels);
|
cannam@233
|
278
|
cannam@233
|
279 m_freqbuf = new float *[m_channels];
|
cannam@233
|
280 for (int c = 0; c < m_channels; ++c) {
|
cannam@233
|
281 m_freqbuf[c] = new float[m_blockSize + 2];
|
cannam@233
|
282 }
|
Chris@444
|
283 m_ri = new Kiss::kiss_fft_scalar[m_blockSize];
|
cannam@233
|
284
|
Chris@444
|
285 m_window = new W(convertType(m_windowType), m_blockSize);
|
cannam@233
|
286
|
Chris@444
|
287 m_cfg = Kiss::kiss_fftr_alloc(m_blockSize, false, 0, 0);
|
Chris@444
|
288 m_cbuf = new Kiss::kiss_fft_cpx[m_blockSize/2+1];
|
cannam@233
|
289
|
cannam@288
|
290 m_processCount = 0;
|
cannam@288
|
291
|
Chris@435
|
292 return m_plugin->initialise(channels, stepSize, m_blockSize);
|
cannam@233
|
293 }
|
cannam@233
|
294
|
cannam@288
|
295 void
|
cannam@288
|
296 PluginInputDomainAdapter::Impl::reset()
|
cannam@288
|
297 {
|
cannam@288
|
298 m_processCount = 0;
|
cannam@288
|
299 m_plugin->reset();
|
cannam@288
|
300 }
|
cannam@288
|
301
|
cannam@233
|
302 size_t
|
cannam@233
|
303 PluginInputDomainAdapter::Impl::getPreferredStepSize() const
|
cannam@233
|
304 {
|
cannam@233
|
305 size_t step = m_plugin->getPreferredStepSize();
|
cannam@233
|
306
|
cannam@233
|
307 if (step == 0 && (m_plugin->getInputDomain() == FrequencyDomain)) {
|
cannam@233
|
308 step = getPreferredBlockSize() / 2;
|
cannam@233
|
309 }
|
cannam@233
|
310
|
cannam@233
|
311 return step;
|
cannam@233
|
312 }
|
cannam@233
|
313
|
cannam@233
|
314 size_t
|
cannam@233
|
315 PluginInputDomainAdapter::Impl::getPreferredBlockSize() const
|
cannam@233
|
316 {
|
cannam@233
|
317 size_t block = m_plugin->getPreferredBlockSize();
|
cannam@233
|
318
|
cannam@233
|
319 if (m_plugin->getInputDomain() == FrequencyDomain) {
|
cannam@233
|
320 if (block == 0) {
|
cannam@233
|
321 block = 1024;
|
cannam@233
|
322 } else {
|
cannam@233
|
323 block = makeBlockSizeAcceptable(block);
|
cannam@233
|
324 }
|
cannam@233
|
325 }
|
cannam@233
|
326
|
cannam@233
|
327 return block;
|
cannam@233
|
328 }
|
cannam@233
|
329
|
cannam@233
|
330 size_t
|
cannam@233
|
331 PluginInputDomainAdapter::Impl::makeBlockSizeAcceptable(size_t blockSize) const
|
cannam@233
|
332 {
|
cannam@233
|
333 if (blockSize < 2) {
|
cannam@233
|
334
|
cannam@283
|
335 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: blocksize < 2 not" << std::endl
|
cannam@233
|
336 << "supported, increasing from " << blockSize << " to 2" << std::endl;
|
cannam@233
|
337 blockSize = 2;
|
Chris@434
|
338
|
Chris@434
|
339 } else if (blockSize % 2) {
|
cannam@233
|
340
|
Chris@434
|
341 std::cerr << "WARNING: PluginInputDomainAdapter::initialise: odd blocksize not" << std::endl
|
Chris@434
|
342 << "supported, increasing from " << blockSize << " to " << (blockSize+1) << std::endl;
|
Chris@434
|
343 blockSize = blockSize+1;
|
cannam@233
|
344 }
|
cannam@233
|
345
|
cannam@233
|
346 return blockSize;
|
cannam@233
|
347 }
|
cannam@233
|
348
|
cannam@233
|
349 RealTime
|
cannam@233
|
350 PluginInputDomainAdapter::Impl::getTimestampAdjustment() const
|
cannam@233
|
351 {
|
cannam@233
|
352 if (m_plugin->getInputDomain() == TimeDomain) {
|
cannam@233
|
353 return RealTime::zeroTime;
|
cannam@298
|
354 } else if (m_method == ShiftData || m_method == NoShift) {
|
cannam@289
|
355 return RealTime::zeroTime;
|
cannam@233
|
356 } else {
|
cannam@233
|
357 return RealTime::frame2RealTime
|
cannam@233
|
358 (m_blockSize/2, int(m_inputSampleRate + 0.5));
|
cannam@233
|
359 }
|
cannam@233
|
360 }
|
cannam@233
|
361
|
cannam@288
|
362 void
|
cannam@288
|
363 PluginInputDomainAdapter::Impl::setProcessTimestampMethod(ProcessTimestampMethod m)
|
cannam@288
|
364 {
|
cannam@288
|
365 m_method = m;
|
cannam@288
|
366 }
|
cannam@288
|
367
|
cannam@288
|
368 PluginInputDomainAdapter::ProcessTimestampMethod
|
cannam@288
|
369 PluginInputDomainAdapter::Impl::getProcessTimestampMethod() const
|
cannam@288
|
370 {
|
cannam@288
|
371 return m_method;
|
cannam@288
|
372 }
|
cannam@288
|
373
|
Chris@317
|
374 void
|
Chris@317
|
375 PluginInputDomainAdapter::Impl::setWindowType(WindowType t)
|
Chris@317
|
376 {
|
Chris@317
|
377 if (m_windowType == t) return;
|
Chris@317
|
378 m_windowType = t;
|
Chris@317
|
379 if (m_window) {
|
Chris@317
|
380 delete m_window;
|
Chris@444
|
381 m_window = new W(convertType(m_windowType), m_blockSize);
|
Chris@317
|
382 }
|
Chris@317
|
383 }
|
Chris@317
|
384
|
Chris@317
|
385 PluginInputDomainAdapter::WindowType
|
Chris@317
|
386 PluginInputDomainAdapter::Impl::getWindowType() const
|
Chris@317
|
387 {
|
Chris@317
|
388 return m_windowType;
|
Chris@317
|
389 }
|
Chris@317
|
390
|
Chris@444
|
391 PluginInputDomainAdapter::Impl::W::WindowType
|
Chris@317
|
392 PluginInputDomainAdapter::Impl::convertType(WindowType t) const
|
Chris@317
|
393 {
|
Chris@317
|
394 switch (t) {
|
Chris@317
|
395 case RectangularWindow:
|
Chris@444
|
396 return W::RectangularWindow;
|
Chris@317
|
397 case BartlettWindow:
|
Chris@444
|
398 return W::BartlettWindow;
|
Chris@317
|
399 case HammingWindow:
|
Chris@444
|
400 return W::HammingWindow;
|
Chris@317
|
401 case HanningWindow:
|
Chris@444
|
402 return W::HanningWindow;
|
Chris@317
|
403 case BlackmanWindow:
|
Chris@444
|
404 return W::BlackmanWindow;
|
Chris@317
|
405 case NuttallWindow:
|
Chris@444
|
406 return W::NuttallWindow;
|
Chris@317
|
407 case BlackmanHarrisWindow:
|
Chris@444
|
408 return W::BlackmanHarrisWindow;
|
Chris@319
|
409 default:
|
Chris@444
|
410 return W::HanningWindow;
|
Chris@317
|
411 }
|
Chris@317
|
412 }
|
Chris@317
|
413
|
cannam@233
|
414 Plugin::FeatureSet
|
cannam@233
|
415 PluginInputDomainAdapter::Impl::process(const float *const *inputBuffers,
|
cannam@233
|
416 RealTime timestamp)
|
cannam@233
|
417 {
|
cannam@233
|
418 if (m_plugin->getInputDomain() == TimeDomain) {
|
cannam@233
|
419 return m_plugin->process(inputBuffers, timestamp);
|
cannam@233
|
420 }
|
cannam@233
|
421
|
cannam@298
|
422 if (m_method == ShiftTimestamp || m_method == NoShift) {
|
cannam@289
|
423 return processShiftingTimestamp(inputBuffers, timestamp);
|
cannam@289
|
424 } else {
|
cannam@289
|
425 return processShiftingData(inputBuffers, timestamp);
|
cannam@289
|
426 }
|
cannam@289
|
427 }
|
cannam@233
|
428
|
cannam@289
|
429 Plugin::FeatureSet
|
cannam@289
|
430 PluginInputDomainAdapter::Impl::processShiftingTimestamp(const float *const *inputBuffers,
|
cannam@289
|
431 RealTime timestamp)
|
cannam@289
|
432 {
|
Chris@421
|
433 unsigned int roundedRate = 1;
|
Chris@421
|
434 if (m_inputSampleRate > 0.f) {
|
Chris@421
|
435 roundedRate = (unsigned int)round(m_inputSampleRate);
|
Chris@421
|
436 }
|
Chris@421
|
437
|
cannam@298
|
438 if (m_method == ShiftTimestamp) {
|
Chris@386
|
439 // we may need to add one nsec if timestamp +
|
Chris@386
|
440 // getTimestampAdjustment() rounds down
|
cannam@298
|
441 timestamp = timestamp + getTimestampAdjustment();
|
Chris@386
|
442 RealTime nsec(0, 1);
|
Chris@421
|
443 if (RealTime::realTime2Frame(timestamp, roundedRate) <
|
Chris@421
|
444 RealTime::realTime2Frame(timestamp + nsec, roundedRate)) {
|
Chris@386
|
445 timestamp = timestamp + nsec;
|
Chris@386
|
446 }
|
cannam@298
|
447 }
|
cannam@233
|
448
|
cannam@233
|
449 for (int c = 0; c < m_channels; ++c) {
|
cannam@233
|
450
|
Chris@317
|
451 m_window->cut(inputBuffers[c], m_ri);
|
cannam@233
|
452
|
cannam@233
|
453 for (int i = 0; i < m_blockSize/2; ++i) {
|
cannam@233
|
454 // FFT shift
|
Chris@444
|
455 Kiss::kiss_fft_scalar value = m_ri[i];
|
cannam@233
|
456 m_ri[i] = m_ri[i + m_blockSize/2];
|
cannam@233
|
457 m_ri[i + m_blockSize/2] = value;
|
cannam@233
|
458 }
|
cannam@233
|
459
|
Chris@444
|
460 Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf);
|
Chris@434
|
461
|
cannam@233
|
462 for (int i = 0; i <= m_blockSize/2; ++i) {
|
Chris@434
|
463 m_freqbuf[c][i * 2] = m_cbuf[i].r;
|
Chris@434
|
464 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i;
|
cannam@233
|
465 }
|
cannam@233
|
466 }
|
cannam@233
|
467
|
cannam@289
|
468 return m_plugin->process(m_freqbuf, timestamp);
|
cannam@288
|
469 }
|
cannam@288
|
470
|
cannam@288
|
471 Plugin::FeatureSet
|
cannam@289
|
472 PluginInputDomainAdapter::Impl::processShiftingData(const float *const *inputBuffers,
|
cannam@289
|
473 RealTime timestamp)
|
cannam@288
|
474 {
|
cannam@289
|
475 if (m_processCount == 0) {
|
cannam@289
|
476 if (!m_shiftBuffers) {
|
cannam@289
|
477 m_shiftBuffers = new float *[m_channels];
|
cannam@289
|
478 for (int c = 0; c < m_channels; ++c) {
|
cannam@289
|
479 m_shiftBuffers[c] = new float[m_blockSize + m_blockSize/2];
|
cannam@289
|
480 }
|
cannam@289
|
481 }
|
cannam@289
|
482 for (int c = 0; c < m_channels; ++c) {
|
cannam@289
|
483 for (int i = 0; i < m_blockSize + m_blockSize/2; ++i) {
|
cannam@289
|
484 m_shiftBuffers[c][i] = 0.f;
|
cannam@289
|
485 }
|
cannam@289
|
486 }
|
cannam@289
|
487 }
|
cannam@289
|
488
|
cannam@289
|
489 for (int c = 0; c < m_channels; ++c) {
|
cannam@289
|
490 for (int i = m_stepSize; i < m_blockSize + m_blockSize/2; ++i) {
|
cannam@289
|
491 m_shiftBuffers[c][i - m_stepSize] = m_shiftBuffers[c][i];
|
cannam@289
|
492 }
|
cannam@289
|
493 for (int i = 0; i < m_blockSize; ++i) {
|
cannam@289
|
494 m_shiftBuffers[c][i + m_blockSize/2] = inputBuffers[c][i];
|
cannam@289
|
495 }
|
cannam@289
|
496 }
|
cannam@289
|
497
|
cannam@289
|
498 for (int c = 0; c < m_channels; ++c) {
|
cannam@289
|
499
|
Chris@317
|
500 m_window->cut(m_shiftBuffers[c], m_ri);
|
cannam@289
|
501
|
cannam@289
|
502 for (int i = 0; i < m_blockSize/2; ++i) {
|
cannam@289
|
503 // FFT shift
|
Chris@444
|
504 Kiss::kiss_fft_scalar value = m_ri[i];
|
cannam@289
|
505 m_ri[i] = m_ri[i + m_blockSize/2];
|
cannam@289
|
506 m_ri[i + m_blockSize/2] = value;
|
cannam@289
|
507 }
|
cannam@289
|
508
|
Chris@444
|
509 Kiss::kiss_fftr(m_cfg, m_ri, m_cbuf);
|
Chris@434
|
510
|
cannam@289
|
511 for (int i = 0; i <= m_blockSize/2; ++i) {
|
Chris@434
|
512 m_freqbuf[c][i * 2] = m_cbuf[i].r;
|
Chris@434
|
513 m_freqbuf[c][i * 2 + 1] = m_cbuf[i].i;
|
cannam@289
|
514 }
|
cannam@289
|
515 }
|
cannam@289
|
516
|
cannam@289
|
517 ++m_processCount;
|
cannam@289
|
518
|
cannam@289
|
519 return m_plugin->process(m_freqbuf, timestamp);
|
cannam@233
|
520 }
|
cannam@233
|
521
|
cannam@233
|
522 }
|
cannam@233
|
523
|
cannam@233
|
524 }
|
cannam@233
|
525
|
cannam@263
|
526 _VAMP_SDK_HOSTSPACE_END(PluginInputDomainAdapter.cpp)
|
cannam@263
|
527
|