Mercurial > hg > devuvuzelator
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 |