Mercurial > hg > vamp-simple-cepstrum
comparison SimpleCepstrum.cpp @ 4:3467d995ea2b
Attempt a complex inverse transform -- doesn't seem to work well?
author | Chris Cannam |
---|---|
date | Fri, 22 Jun 2012 23:56:37 +0100 |
parents | a6f9ece68482 |
children | 05c558f1a23b |
comparison
equal
deleted
inserted
replaced
3:a6f9ece68482 | 4:3467d995ea2b |
---|---|
5 #include <vector> | 5 #include <vector> |
6 #include <algorithm> | 6 #include <algorithm> |
7 | 7 |
8 #include <cstdio> | 8 #include <cstdio> |
9 #include <cmath> | 9 #include <cmath> |
10 #include <complex> | |
10 | 11 |
11 using std::string; | 12 using std::string; |
12 | 13 |
13 SimpleCepstrum::SimpleCepstrum(float inputSampleRate) : | 14 SimpleCepstrum::SimpleCepstrum(float inputSampleRate) : |
14 Plugin(inputSampleRate), | 15 Plugin(inputSampleRate), |
128 | 129 |
129 d.identifier = "method"; | 130 d.identifier = "method"; |
130 d.name = "Cepstrum transform method"; | 131 d.name = "Cepstrum transform method"; |
131 d.unit = ""; | 132 d.unit = ""; |
132 d.minValue = 0; | 133 d.minValue = 0; |
133 d.maxValue = 3; | 134 d.maxValue = 5; |
134 d.defaultValue = 0; | 135 d.defaultValue = 0; |
135 d.isQuantized = true; | 136 d.isQuantized = true; |
136 d.quantizeStep = 1; | 137 d.quantizeStep = 1; |
137 d.valueNames.push_back("Inverse symmetric"); | 138 d.valueNames.push_back("Inverse symmetric"); |
138 d.valueNames.push_back("Inverse asymmetric"); | 139 d.valueNames.push_back("Inverse asymmetric"); |
140 d.valueNames.push_back("Inverse complex"); | |
141 d.valueNames.push_back("Forward power"); | |
139 d.valueNames.push_back("Forward magnitude"); | 142 d.valueNames.push_back("Forward magnitude"); |
140 d.valueNames.push_back("Forward difference"); | 143 d.valueNames.push_back("Forward difference"); |
141 list.push_back(d); | 144 list.push_back(d); |
142 | 145 |
143 d.identifier = "clamp"; | 146 d.identifier = "clamp"; |
324 FeatureSet fs; | 327 FeatureSet fs; |
325 | 328 |
326 int bs = m_blockSize; | 329 int bs = m_blockSize; |
327 int hs = m_blockSize/2 + 1; | 330 int hs = m_blockSize/2 + 1; |
328 | 331 |
329 double *logmag = new double[bs]; | |
330 | |
331 for (int i = 0; i < hs; ++i) { | |
332 | |
333 double mag = sqrt(inputBuffers[0][i*2 ] * inputBuffers[0][i*2 ] + | |
334 inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]); | |
335 double lm = log(mag + 0.00000001); | |
336 | |
337 switch (m_method) { | |
338 case InverseSymmetric: | |
339 logmag[i] = lm; | |
340 if (i > 0) logmag[bs - i] = lm; | |
341 break; | |
342 case InverseAsymmetric: | |
343 logmag[i] = lm; | |
344 if (i > 0) logmag[bs - i] = 0; | |
345 break; | |
346 case ForwardMagnitude: | |
347 case ForwardDifference: | |
348 logmag[bs/2 + i - 1] = lm; | |
349 if (i < hs-1) { | |
350 logmag[bs/2 - i - 1] = lm; | |
351 } | |
352 break; | |
353 } | |
354 } | |
355 | |
356 double *cep = new double[bs]; | 332 double *cep = new double[bs]; |
357 double *io = new double[bs]; | 333 double *io = new double[bs]; |
358 | 334 |
359 if (m_method == InverseSymmetric || | 335 if (m_method != InverseComplex) { |
360 m_method == InverseAsymmetric) { | 336 |
361 | 337 double *logmag = new double[bs]; |
362 fft(bs, true, logmag, 0, cep, io); | 338 |
363 | 339 for (int i = 0; i < hs; ++i) { |
364 } else { | 340 |
365 | 341 double power = |
366 fft(bs, false, logmag, 0, cep, io); | 342 inputBuffers[0][i*2 ] * inputBuffers[0][i*2 ] + |
367 | 343 inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]; |
368 if (m_method == ForwardDifference) { | 344 |
369 for (int i = 0; i < hs; ++i) { | 345 double lm; |
370 cep[i] = fabs(io[i]) - fabs(cep[i]); | 346 |
347 if (m_method == ForwardPower) { | |
348 lm = log(power + 0.00000001); | |
349 } else { | |
350 double mag = sqrt(power); | |
351 lm = log(mag + 0.00000001); | |
371 } | 352 } |
372 } else { | 353 |
373 for (int i = 0; i < hs; ++i) { | 354 switch (m_method) { |
374 cep[i] = sqrt(cep[i]*cep[i] + io[i]*io[i]); | 355 case InverseSymmetric: |
356 logmag[i] = lm; | |
357 if (i > 0) logmag[bs - i] = lm; | |
358 break; | |
359 case InverseAsymmetric: | |
360 logmag[i] = lm; | |
361 if (i > 0) logmag[bs - i] = 0; | |
362 break; | |
363 default: | |
364 logmag[bs/2 + i - 1] = lm; | |
365 if (i < hs-1) { | |
366 logmag[bs/2 - i - 1] = lm; | |
367 } | |
368 break; | |
375 } | 369 } |
376 } | 370 } |
371 | |
372 if (m_method == InverseSymmetric || | |
373 m_method == InverseAsymmetric) { | |
374 | |
375 fft(bs, true, logmag, 0, cep, io); | |
376 | |
377 } else { | |
378 | |
379 fft(bs, false, logmag, 0, cep, io); | |
380 | |
381 if (m_method == ForwardDifference) { | |
382 for (int i = 0; i < hs; ++i) { | |
383 cep[i] = fabs(io[i]) - fabs(cep[i]); | |
384 } | |
385 } else { | |
386 for (int i = 0; i < hs; ++i) { | |
387 cep[i] = sqrt(cep[i]*cep[i] + io[i]*io[i]); | |
388 } | |
389 } | |
390 } | |
391 | |
392 delete[] logmag; | |
393 | |
394 } else { // InverseComplex | |
395 | |
396 double *ri = new double[bs]; | |
397 double *ii = new double[bs]; | |
398 | |
399 for (int i = 0; i < hs; ++i) { | |
400 double re = inputBuffers[0][i*2]; | |
401 double im = inputBuffers[0][i*2+1]; | |
402 std::complex<double> c(re, im); | |
403 std::complex<double> clog = std::log(c); | |
404 ri[i] = clog.real(); | |
405 ii[i] = clog.imag(); | |
406 if (i > 0) { | |
407 ri[bs - i] = ri[i]; | |
408 ii[bs - i] = -ii[i]; | |
409 } | |
410 } | |
411 | |
412 fft(bs, true, ri, ii, cep, io); | |
413 | |
414 delete[] ri; | |
415 delete[] ii; | |
377 } | 416 } |
378 | 417 |
379 if (m_clamp) { | 418 if (m_clamp) { |
380 for (int i = 0; i < bs; ++i) { | 419 for (int i = 0; i < bs; ++i) { |
381 if (cep[i] < 0) cep[i] = 0; | 420 if (cep[i] < 0) cep[i] = 0; |
445 } | 484 } |
446 fs[m_amOutput].push_back(am); | 485 fs[m_amOutput].push_back(am); |
447 | 486 |
448 // destructively wipe the higher cepstral bins in order to | 487 // destructively wipe the higher cepstral bins in order to |
449 // calculate the envelope | 488 // calculate the envelope |
489 double *env = new double[bs]; | |
450 cep[0] /= 2; | 490 cep[0] /= 2; |
451 cep[from-1] /= 2; | 491 cep[from-1] /= 2; |
452 for (int i = 0; i < from; ++i) { | 492 for (int i = 0; i < from; ++i) { |
453 cep[i] /= bs; | 493 cep[i] /= bs; |
454 } | 494 } |
455 for (int i = from; i < bs; ++i) { | 495 for (int i = from; i < bs; ++i) { |
456 cep[i] = 0; | 496 cep[i] = 0; |
457 } | 497 } |
458 fft(bs, false, cep, 0, logmag, io); | 498 fft(bs, false, cep, 0, env, io); |
459 for (int i = 0; i < hs; ++i) { | 499 for (int i = 0; i < hs; ++i) { |
460 logmag[i] = exp(logmag[i]); | 500 env[i] = exp(env[i]); |
461 } | 501 } |
462 Feature env; | 502 Feature envf; |
463 for (int i = 0; i < hs; ++i) { | 503 for (int i = 0; i < hs; ++i) { |
464 env.values.push_back(logmag[i]); | 504 envf.values.push_back(env[i]); |
465 } | 505 } |
466 fs[m_envOutput].push_back(env); | 506 fs[m_envOutput].push_back(envf); |
467 | 507 |
468 Feature es; | 508 Feature es; |
469 for (int i = 0; i < hs; ++i) { | 509 for (int i = 0; i < hs; ++i) { |
470 double re = inputBuffers[0][i*2 ] / logmag[i]; | 510 double re = inputBuffers[0][i*2 ] / env[i]; |
471 double im = inputBuffers[0][i*2+1] / logmag[i]; | 511 double im = inputBuffers[0][i*2+1] / env[i]; |
472 double mag = sqrt(re*re + im*im); | 512 double mag = sqrt(re*re + im*im); |
473 es.values.push_back(mag); | 513 es.values.push_back(mag); |
474 } | 514 } |
475 fs[m_esOutput].push_back(es); | 515 fs[m_esOutput].push_back(es); |
476 | 516 |
517 delete[] env; | |
477 delete[] io; | 518 delete[] io; |
478 delete[] logmag; | |
479 delete[] cep; | 519 delete[] cep; |
480 | 520 |
481 return fs; | 521 return fs; |
482 } | 522 } |
483 | 523 |