comparison devuvuzelator-vst.cpp @ 9:a1539d4e3b08

* Tidy code, start doc
author Chris Cannam
date Sat, 12 Jun 2010 13:08:33 +0100
parents e15ebd222c63
children 1e6360396b6c
comparison
equal deleted inserted replaced
8:e15ebd222c63 9:a1539d4e3b08
1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */ 1 /* -*- c-basic-offset: 4 indent-tabs-mode: nil -*- vi:set ts=8 sts=4 sw=4: */
2 2
3 #include "devuvuzelator-vst.h"
4
3 #define _USE_MATH_DEFINES 5 #define _USE_MATH_DEFINES
4 6 #include <cmath>
5 #include <iostream> 7 #include <iostream>
6 #include <cmath>
7 #include <cstdio> 8 #include <cstdio>
8 9
9 #include "public.sdk/source/vst2.x/audioeffect.h" 10 #include "params.h"
10 11
11 #define snprintf _snprintf 12 #define snprintf _snprintf
12 #define alloca _alloca 13 #define alloca _alloca
13
14 #define FFTSIZE 1024
15 #define WINSIZE 1024
16
17 #include "median.h"
18
19 class Devuvuzelator : public AudioEffect
20 {
21 enum {
22 FundamentalParam = 0,
23 BandwidthParam = 1,
24 HarmonicsParam = 2,
25 ReductionParam = 3,
26 NumParams = 4
27 };
28
29 public:
30 Devuvuzelator(audioMasterCallback cb);
31 ~Devuvuzelator();
32
33 virtual void getEffectName(char *n) {
34 vst_strncpy(n, "Devuvuzelator", kVstMaxEffectNameLen);
35 }
36 virtual void getProductString(char *n) {
37 vst_strncpy(n, "Devuvuzelator", kVstMaxProductStrLen);
38 }
39 virtual void getVendorString(char *n) {
40 vst_strncpy(n, "Queen Mary, University of London", kVstMaxVendorStrLen);
41 }
42
43 virtual void setParameter(VstInt32 index, float value);
44 virtual float getParameter(VstInt32 index);
45 virtual void getParameterLabel(VstInt32 index, char* label);
46 virtual void getParameterDisplay(VstInt32 index, char* text);
47 virtual void getParameterName(VstInt32 index, char* text);
48
49 virtual void setSampleRate (float sampleRate) {
50 m_sampleRate = sampleRate;
51 AudioEffect::setSampleRate(sampleRate);
52 }
53
54 virtual void processReplacing (float** inputs, float** outputs, VstInt32 sampleFrames) {
55 m_input = inputs[0];
56 m_output = outputs[0];
57 runImpl(sampleFrames);
58 }
59
60 void reset();
61 void window(float *);
62 void runImpl(unsigned long);
63 void processFrame();
64 void processSpectralFrame();
65
66 static void fft(unsigned int n, bool inverse,
67 double *ri, double *ii, double *ro, double *io);
68
69 float m_sampleRate;
70 float *m_input;
71 float *m_output;
72
73 float m_fundamental;
74 float m_bandwidth;
75 int m_harmonics;
76 float m_reduction;
77
78 const int m_fftsize;
79 const int m_winsize;
80 const int m_increment;
81 int m_fill;
82 int m_read;
83 float *m_buffer;
84 float *m_outacc;
85 double *m_frame;
86 double *m_spare;
87 double *m_real;
88 double *m_imag;
89 double *m_window;
90 MedianFilter<double> **m_medians;
91 };
92 14
93 // VST params 0->1 15 // VST params 0->1
94 16
95 void 17 void
96 Devuvuzelator::setParameter(VstInt32 index, float value) 18 Devuvuzelator::setParameter(VstInt32 index, float value)
162 m_input(0), 84 m_input(0),
163 m_output(0), 85 m_output(0),
164 m_fftsize(FFTSIZE), 86 m_fftsize(FFTSIZE),
165 m_winsize(WINSIZE), 87 m_winsize(WINSIZE),
166 m_increment(m_winsize/2), 88 m_increment(m_winsize/2),
89 m_filtersecs(FILTERSECS),
167 m_fill(0), 90 m_fill(0),
168 m_read(0) 91 m_read(0)
169 { 92 {
170 m_buffer = new float[m_winsize]; 93 m_buffer = new float[m_winsize];
171 m_outacc = new float[m_winsize * 2]; 94 m_outacc = new float[m_winsize * 2];
172 m_window = new double[m_winsize]; 95 m_window = new double[m_winsize];
173 m_frame = new double[m_fftsize]; 96 m_frame = new double[m_fftsize];
174 m_spare = new double[m_fftsize]; 97 m_spare = new double[m_fftsize];
175 m_real = new double[m_fftsize]; 98 m_real = new double[m_fftsize];
176 m_imag = new double[m_fftsize]; 99 m_imag = new double[m_fftsize];
177 m_medians = new MedianFilter<double> *[m_fftsize/2+1]; 100 m_medians = new MedianFilter<double> *[m_fftsize/2+1];
178 101
179 for (int i = 0; i < m_winsize; ++i) { 102 for (int i = 0; i < m_winsize; ++i) {
199 122
200 Devuvuzelator::~Devuvuzelator() 123 Devuvuzelator::~Devuvuzelator()
201 { 124 {
202 delete[] m_buffer; 125 delete[] m_buffer;
203 delete[] m_outacc; 126 delete[] m_outacc;
204 delete[] m_frame; 127 delete[] m_frame;
205 delete[] m_spare; 128 delete[] m_spare;
206 delete[] m_real; 129 delete[] m_real;
207 delete[] m_imag; 130 delete[] m_imag;
208 delete[] m_window; 131 delete[] m_window;
209 for (int i = 0; i < m_fftsize/2+1; ++i) { 132 for (int i = 0; i < m_fftsize/2+1; ++i) {
210 delete m_medians[i]; 133 delete m_medians[i];
232 Devuvuzelator::runImpl(unsigned long sampleCount) 155 Devuvuzelator::runImpl(unsigned long sampleCount)
233 { 156 {
234 if (!m_input || !m_output) return; 157 if (!m_input || !m_output) return;
235 158
236 const int sc = sampleCount; 159 const int sc = sampleCount;
237 /* 160
238 static FILE *blah = 0; 161 float *output = m_output;
239 if (!blah) { 162 if (m_input == m_output) {
240 blah = fopen("d:\\devuvu-counts.txt", "w"); 163 output = (float *)alloca(sampleCount * sizeof(float));
241 } 164 }
242 165
243 if (m_input == m_output) fprintf(blah, "in-place\n"); 166 int oi = 0;
244 */ 167 for (int ii = 0; ii < sc; ++ii) {
245 float *output = m_output; 168
246 if (m_input == m_output) { 169 output[oi++] = m_outacc[m_read++];
247 output = (float *)alloca(sampleCount * sizeof(float));
248 }
249 /*
250 float inmean = 0;
251 for (int i = 0; i < sc; ++i) {
252 inmean += m_input[i] * m_input[i];
253 fprintf(blah, "i:%d:%f ", i, m_input[i]);
254 }
255 inmean/=sc;
256 inmean = sqrt(inmean);
257
258 fprintf(blah, "%d\n", (int)sampleCount);
259 fflush(blah);
260 */
261 int oi = 0;
262 for (int ii = 0; ii < sc; ++ii) {
263
264 output[oi++] = m_outacc[m_read++];
265 // m_output[oi++] = inmean * float(ii%100)/100;
266 // m_read++;
267 if (m_fill == m_winsize) { 170 if (m_fill == m_winsize) {
268 171
269 processFrame(); 172 processFrame();
270 /*
271 for (int i = 0; i < m_winsize; ++i) {
272 float v = m_buffer[i];
273 fprintf(blah, "%f ", v);
274 m_outacc[m_winsize + i] = m_buffer[i];//m_input[i];//m_buffer[i] ;//* m_window[i];
275 }
276 fprintf(blah, "\n");
277
278 // for (int j = 0; j < m_winsize; ++j) {
279 // m_outacc[m_winsize+j] = inmean * float(j%100)/100;
280 // }
281 */
282 173
283 for (int j = m_increment; j < m_winsize; ++j) { 174 for (int j = m_increment; j < m_winsize; ++j) {
284 m_buffer[j - m_increment] = m_buffer[j]; 175 m_buffer[j - m_increment] = m_buffer[j];
285 } 176 }
286 177
293 } 184 }
294 185
295 m_fill = m_fill - m_increment; 186 m_fill = m_fill - m_increment;
296 m_read = m_read - m_increment; 187 m_read = m_read - m_increment;
297 } 188 }
298 /* 189 m_buffer[m_fill] = m_input[ii];
299 fprintf(blah, "%d:%f ", ii, m_input[ii]); 190 ++m_fill;
300 */ 191 }
301 m_buffer[m_fill] = m_input[ii]; 192
302 ++m_fill; 193 if (m_input == m_output) {
303 } 194 for (int i = 0; i < sc; ++i) m_output[i] = output[i];
304 195 }
305 static int block = 0;
306 for (int i = 0; i < sc; ++i) {
307 // m_output[i] = float(block % 100) / 100;
308 // m_output[i] = inmean * float(i % 100) / 100;
309 }
310 ++block;
311
312 if (m_input == m_output) {
313 for (int i = 0; i < sc; ++i) m_output[i] = output[i];
314 }
315 } 196 }
316 197
317 void 198 void
318 Devuvuzelator::processFrame() 199 Devuvuzelator::processFrame()
319 { 200 {
320 /* for (int i = 0; i < m_winsize; ++i) {
321 m_outacc[m_winsize + i] += m_buffer[i] ;//* m_window[i];
322 }
323 return;
324 */
325
326 for (int i = 0; i < m_fftsize; ++i) { 201 for (int i = 0; i < m_fftsize; ++i) {
327 m_frame[i] = 0.0; 202 m_frame[i] = 0.0;
328 } 203 }
329 204
330 int ix = m_fftsize - m_winsize/2; 205 int ix = m_fftsize - m_winsize/2;
334 if (ix == m_fftsize) ix = 0; 209 if (ix == m_fftsize) ix = 0;
335 } 210 }
336 211
337 fft(m_fftsize, false, m_frame, 0, m_real, m_imag); 212 fft(m_fftsize, false, m_frame, 0, m_real, m_imag);
338 213
339 // processSpectralFrame(); 214 processSpectralFrame();
340 215
341 for (int i = 0; i < m_fftsize/2-1; ++i) { 216 for (int i = 0; i < m_fftsize/2-1; ++i) {
342 m_real[m_fftsize-i-1] = m_real[i+1]; 217 m_real[m_fftsize-i-1] = m_real[i+1];
343 m_imag[m_fftsize-i-1] = -m_imag[i+1]; 218 m_imag[m_fftsize-i-1] = -m_imag[i+1];
344 } 219 }
351 m_outacc[m_winsize + i] += m_frame[ix++]; 226 m_outacc[m_winsize + i] += m_frame[ix++];
352 if (ix == m_fftsize) ix = 0; 227 if (ix == m_fftsize) ix = 0;
353 } 228 }
354 } 229 }
355 230
356 // FFT implementation by Don Cross, public domain.
357 // This version scales the forward transform.
358
359 void Devuvuzelator::fft(unsigned int n, bool inverse,
360 double *ri, double *ii, double *ro, double *io)
361 {
362 if (!ri || !ro || !io) return;
363
364 unsigned int bits;
365 unsigned int i, j, k, m;
366 unsigned int blockSize, blockEnd;
367
368 double tr, ti;
369
370 if (n < 2) return;
371 if (n & (n-1)) return;
372
373 double angle = 2.0 * M_PI;
374 if (inverse) angle = -angle;
375
376 for (i = 0; ; ++i) {
377 if (n & (1 << i)) {
378 bits = i;
379 break;
380 }
381 }
382
383 static unsigned int tableSize = 0;
384 static int *table = 0;
385
386 if (tableSize != n) {
387
388 delete[] table;
389
390 table = new int[n];
391
392 for (i = 0; i < n; ++i) {
393
394 m = i;
395
396 for (j = k = 0; j < bits; ++j) {
397 k = (k << 1) | (m & 1);
398 m >>= 1;
399 }
400
401 table[i] = k;
402 }
403
404 tableSize = n;
405 }
406
407 if (ii) {
408 for (i = 0; i < n; ++i) {
409 ro[table[i]] = ri[i];
410 io[table[i]] = ii[i];
411 }
412 } else {
413 for (i = 0; i < n; ++i) {
414 ro[table[i]] = ri[i];
415 io[table[i]] = 0.0;
416 }
417 }
418
419 blockEnd = 1;
420
421 for (blockSize = 2; blockSize <= n; blockSize <<= 1) {
422
423 double delta = angle / (double)blockSize;
424 double sm2 = -sin(-2 * delta);
425 double sm1 = -sin(-delta);
426 double cm2 = cos(-2 * delta);
427 double cm1 = cos(-delta);
428 double w = 2 * cm1;
429 double ar[3], ai[3];
430
431 for (i = 0; i < n; i += blockSize) {
432
433 ar[2] = cm2;
434 ar[1] = cm1;
435
436 ai[2] = sm2;
437 ai[1] = sm1;
438
439 for (j = i, m = 0; m < blockEnd; j++, m++) {
440
441 ar[0] = w * ar[1] - ar[2];
442 ar[2] = ar[1];
443 ar[1] = ar[0];
444
445 ai[0] = w * ai[1] - ai[2];
446 ai[2] = ai[1];
447 ai[1] = ai[0];
448
449 k = j + blockEnd;
450 tr = ar[0] * ro[k] - ai[0] * io[k];
451 ti = ar[0] * io[k] + ai[0] * ro[k];
452
453 ro[k] = ro[j] - tr;
454 io[k] = io[j] - ti;
455
456 ro[j] += tr;
457 io[j] += ti;
458 }
459 }
460
461 blockEnd = blockSize;
462 }
463
464 if (!inverse) {
465
466 double denom = (double)n;
467
468 for (i = 0; i < n; i++) {
469 ro[i] /= denom;
470 io[i] /= denom;
471 }
472 }
473 }
474
475 AudioEffect *createEffectInstance(audioMasterCallback audioMaster) 231 AudioEffect *createEffectInstance(audioMasterCallback audioMaster)
476 { 232 {
477 return new Devuvuzelator(audioMaster); 233 return new Devuvuzelator(audioMaster);
478 } 234 }
479 235
480 #include "devuvuzelator.cpp" 236
481