comparison SimpleCepstrum.cpp @ 3:a6f9ece68482

Add choice of cepstrum transform method
author Chris Cannam
date Fri, 22 Jun 2012 23:01:00 +0100
parents e6faf01e25d8
children 3467d995ea2b
comparison
equal deleted inserted replaced
2:e6faf01e25d8 3:a6f9ece68482
15 m_channels(0), 15 m_channels(0),
16 m_stepSize(256), 16 m_stepSize(256),
17 m_blockSize(1024), 17 m_blockSize(1024),
18 m_fmin(50), 18 m_fmin(50),
19 m_fmax(1000), 19 m_fmax(1000),
20 m_clamp(false) 20 m_clamp(false),
21 m_method(InverseSymmetric)
21 { 22 {
22 } 23 }
23 24
24 SimpleCepstrum::~SimpleCepstrum() 25 SimpleCepstrum::~SimpleCepstrum()
25 { 26 {
123 d.maxValue = m_inputSampleRate / 2; 124 d.maxValue = m_inputSampleRate / 2;
124 d.defaultValue = 1000; 125 d.defaultValue = 1000;
125 d.isQuantized = false; 126 d.isQuantized = false;
126 list.push_back(d); 127 list.push_back(d);
127 128
129 d.identifier = "method";
130 d.name = "Cepstrum transform method";
131 d.unit = "";
132 d.minValue = 0;
133 d.maxValue = 3;
134 d.defaultValue = 0;
135 d.isQuantized = true;
136 d.quantizeStep = 1;
137 d.valueNames.push_back("Inverse symmetric");
138 d.valueNames.push_back("Inverse asymmetric");
139 d.valueNames.push_back("Forward magnitude");
140 d.valueNames.push_back("Forward difference");
141 list.push_back(d);
142
128 d.identifier = "clamp"; 143 d.identifier = "clamp";
129 d.name = "Clamp negative values in cepstrum at zero"; 144 d.name = "Clamp negative values in cepstrum at zero";
130 d.unit = ""; 145 d.unit = "";
131 d.minValue = 0; 146 d.minValue = 0;
132 d.maxValue = 1; 147 d.maxValue = 1;
133 d.defaultValue = 0; 148 d.defaultValue = 0;
134 d.isQuantized = true; 149 d.isQuantized = true;
135 d.quantizeStep = 1; 150 d.quantizeStep = 1;
151 d.valueNames.clear();
136 list.push_back(d); 152 list.push_back(d);
137 153
138 return list; 154 return list;
139 } 155 }
140 156
142 SimpleCepstrum::getParameter(string identifier) const 158 SimpleCepstrum::getParameter(string identifier) const
143 { 159 {
144 if (identifier == "fmin") return m_fmin; 160 if (identifier == "fmin") return m_fmin;
145 else if (identifier == "fmax") return m_fmax; 161 else if (identifier == "fmax") return m_fmax;
146 else if (identifier == "clamp") return (m_clamp ? 1 : 0); 162 else if (identifier == "clamp") return (m_clamp ? 1 : 0);
163 else if (identifier == "method") return (int)m_method;
147 else return 0.f; 164 else return 0.f;
148 } 165 }
149 166
150 void 167 void
151 SimpleCepstrum::setParameter(string identifier, float value) 168 SimpleCepstrum::setParameter(string identifier, float value)
152 { 169 {
153 if (identifier == "fmin") m_fmin = value; 170 if (identifier == "fmin") m_fmin = value;
154 else if (identifier == "fmax") m_fmax = value; 171 else if (identifier == "fmax") m_fmax = value;
155 else if (identifier == "clamp") m_clamp = (value > 0.5); 172 else if (identifier == "clamp") m_clamp = (value > 0.5);
173 else if (identifier == "method") m_method = Method(int(value + 0.5));
156 } 174 }
157 175
158 SimpleCepstrum::ProgramList 176 SimpleCepstrum::ProgramList
159 SimpleCepstrum::getPrograms() const 177 SimpleCepstrum::getPrograms() const
160 { 178 {
307 325
308 int bs = m_blockSize; 326 int bs = m_blockSize;
309 int hs = m_blockSize/2 + 1; 327 int hs = m_blockSize/2 + 1;
310 328
311 double *logmag = new double[bs]; 329 double *logmag = new double[bs];
330
312 for (int i = 0; i < hs; ++i) { 331 for (int i = 0; i < hs; ++i) {
332
313 double mag = sqrt(inputBuffers[0][i*2 ] * inputBuffers[0][i*2 ] + 333 double mag = sqrt(inputBuffers[0][i*2 ] * inputBuffers[0][i*2 ] +
314 inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]); 334 inputBuffers[0][i*2+1] * inputBuffers[0][i*2+1]);
315 logmag[i] = log(mag + 0.00000001); 335 double lm = log(mag + 0.00000001);
316 if (i > 0) { 336
317 logmag[bs - i] = logmag[i]; 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;
318 } 353 }
319 } 354 }
320 355
321 double *cep = new double[bs]; 356 double *cep = new double[bs];
322 double *discard = new double[bs]; 357 double *io = new double[bs];
323 fft(bs, true, logmag, 0, cep, discard); 358
359 if (m_method == InverseSymmetric ||
360 m_method == InverseAsymmetric) {
361
362 fft(bs, true, logmag, 0, cep, io);
363
364 } else {
365
366 fft(bs, false, logmag, 0, cep, io);
367
368 if (m_method == ForwardDifference) {
369 for (int i = 0; i < hs; ++i) {
370 cep[i] = fabs(io[i]) - fabs(cep[i]);
371 }
372 } else {
373 for (int i = 0; i < hs; ++i) {
374 cep[i] = sqrt(cep[i]*cep[i] + io[i]*io[i]);
375 }
376 }
377 }
324 378
325 if (m_clamp) { 379 if (m_clamp) {
326 for (int i = 0; i < bs; ++i) { 380 for (int i = 0; i < bs; ++i) {
327 if (cep[i] < 0) cep[i] = 0; 381 if (cep[i] < 0) cep[i] = 0;
328 } 382 }
399 cep[i] /= bs; 453 cep[i] /= bs;
400 } 454 }
401 for (int i = from; i < bs; ++i) { 455 for (int i = from; i < bs; ++i) {
402 cep[i] = 0; 456 cep[i] = 0;
403 } 457 }
404 fft(bs, false, cep, 0, logmag, discard); 458 fft(bs, false, cep, 0, logmag, io);
405 for (int i = 0; i < hs; ++i) { 459 for (int i = 0; i < hs; ++i) {
406 logmag[i] = exp(logmag[i]); 460 logmag[i] = exp(logmag[i]);
407 } 461 }
408 Feature env; 462 Feature env;
409 for (int i = 0; i < hs; ++i) { 463 for (int i = 0; i < hs; ++i) {
418 double mag = sqrt(re*re + im*im); 472 double mag = sqrt(re*re + im*im);
419 es.values.push_back(mag); 473 es.values.push_back(mag);
420 } 474 }
421 fs[m_esOutput].push_back(es); 475 fs[m_esOutput].push_back(es);
422 476
423 delete[] discard; 477 delete[] io;
424 delete[] logmag; 478 delete[] logmag;
425 delete[] cep; 479 delete[] cep;
426 480
427 return fs; 481 return fs;
428 } 482 }