Mercurial > hg > vamp-tempogram
comparison Tempogram.cpp @ 3:5125d34fda67
* Implemented normalisation
* Implemented threshold
* Strated implementing bandpass processing
author | Carl Bussey <c.bussey@se10.qmul.ac.uk> |
---|---|
date | Wed, 09 Jul 2014 20:14:20 +0100 |
parents | 1d0b7dcea27f |
children | 597f033fa7a2 |
comparison
equal
deleted
inserted
replaced
2:1d0b7dcea27f | 3:5125d34fda67 |
---|---|
17 Tempogram::Tempogram(float inputSampleRate) : | 17 Tempogram::Tempogram(float inputSampleRate) : |
18 Plugin(inputSampleRate), | 18 Plugin(inputSampleRate), |
19 m_blockSize(0), | 19 m_blockSize(0), |
20 m_stepSize(0), | 20 m_stepSize(0), |
21 compressionConstant(1000), //make param | 21 compressionConstant(1000), //make param |
22 specMax(0), | |
22 previousY(NULL), | 23 previousY(NULL), |
23 currentY(NULL), | 24 currentY(NULL), |
25 minDB(0), | |
24 tN(1024), //make param | 26 tN(1024), //make param |
25 thopSize(512), //make param | 27 thopSize(512), //make param |
26 fftInput(NULL), | 28 fftInput(NULL), |
27 fftOutputReal(NULL), | 29 fftOutputReal(NULL), |
28 fftOutputImag(NULL), | 30 fftOutputImag(NULL), |
29 ncLength(0) | 31 numberOfBlocks(0), |
32 hannN(0) | |
30 | 33 |
31 // Also be sure to set your plugin parameters (presumably stored | 34 // Also be sure to set your plugin parameters (presumably stored |
32 // in member variables) to their default values here -- the host | 35 // in member variables) to their default values here -- the host |
33 // will not do that for you | 36 // will not do that for you |
34 { | 37 { |
264 // Real initialisation work goes here! | 267 // Real initialisation work goes here! |
265 m_blockSize = blockSize; | 268 m_blockSize = blockSize; |
266 m_stepSize = stepSize; | 269 m_stepSize = stepSize; |
267 currentY = new float[m_blockSize]; | 270 currentY = new float[m_blockSize]; |
268 previousY = new float[m_blockSize]; | 271 previousY = new float[m_blockSize]; |
272 minDB = pow((float)10,(float)-74/20); | |
269 | 273 |
270 return true; | 274 return true; |
271 } | 275 } |
272 | 276 |
273 void | 277 void |
283 | 287 |
284 FeatureSet featureSet; | 288 FeatureSet featureSet; |
285 Feature feature; | 289 Feature feature; |
286 | 290 |
287 const float *in = inputBuffers[0]; | 291 const float *in = inputBuffers[0]; |
288 | 292 |
289 float sum = 0; | |
290 for (int i = 0; i < n; i++){ | 293 for (int i = 0; i < n; i++){ |
291 float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]); | 294 float magnitude = sqrt(in[2*i] * in[2*i] + in[2*i + 1] * in[2*i + 1]); |
295 magnitude = magnitude > minDB ? magnitude : minDB; | |
296 specData.push_back(magnitude); | |
292 feature.values.push_back(magnitude); | 297 feature.values.push_back(magnitude); |
293 currentY[i] = log(1+compressionConstant*magnitude); | 298 |
294 if(currentY[i] >= previousY[i]){ | 299 specMax = specMax > magnitude ? specMax : magnitude; |
295 sum += (currentY[i] - previousY[i]); | 300 } |
296 } | 301 |
297 } | 302 numberOfBlocks++; |
298 | |
299 noveltyCurve.push_back(sum); | |
300 | |
301 float *tmpY = currentY; | |
302 currentY = previousY; | |
303 previousY = tmpY; | |
304 tmpY = NULL; | |
305 | |
306 ncTimestamps.push_back(timestamp); | 303 ncTimestamps.push_back(timestamp); |
307 featureSet[2].push_back(feature); | 304 featureSet[2].push_back(feature); |
308 | 305 |
309 return featureSet; | 306 return featureSet; |
310 } | 307 } |
315 hannWindow = new float[hannN]; | 312 hannWindow = new float[hannN]; |
316 hannWindowtN = new float[tN]; | 313 hannWindowtN = new float[tN]; |
317 fftInput = new double[tN]; | 314 fftInput = new double[tN]; |
318 fftOutputReal = new double[tN]; | 315 fftOutputReal = new double[tN]; |
319 fftOutputImag = new double[tN]; | 316 fftOutputImag = new double[tN]; |
320 ncLength = noveltyCurve.size(); | |
321 | 317 |
322 WindowFunction::hanning(hannWindow, hannN, true); | 318 WindowFunction::hanning(hannWindow, hannN, true); |
323 } | 319 } |
324 | 320 |
325 void | 321 void |
334 fftOutputReal = NULL; | 330 fftOutputReal = NULL; |
335 delete []fftOutputImag; | 331 delete []fftOutputImag; |
336 fftOutputImag = NULL; | 332 fftOutputImag = NULL; |
337 } | 333 } |
338 | 334 |
335 vector<float> | |
336 Tempogram::spectrogramToNoveltyCurve(vector<float> spectrogram, int numberOfBlocks, int blockSize, float samplingFrequency, FeatureSet * featureSet){ | |
337 int numberOfBands = 5; | |
338 | |
339 for (int block = 0; block < numberOfBlocks; block++){ | |
340 vector<float> sum = vector<float>(numberOfBands); | |
341 | |
342 int band = 0; | |
343 for (int k = 0; k < blockSize; k++){ | |
344 int index = block*blockSize + k; | |
345 | |
346 if(index > 500*pow(2.5, band)) | |
347 if(band < numberOfBands) | |
348 band++; | |
349 | |
350 specData[index] = log(1+compressionConstant*(specData[index]/specMax)); | |
351 | |
352 float currentY = specData[index]; | |
353 float prevI = index - m_blockSize; | |
354 float previousY = prevI >= 0 ? specData[prevI] : 0; | |
355 | |
356 if(currentY >= previousY){ | |
357 sum[band] += (currentY - previousY); | |
358 } | |
359 } | |
360 | |
361 float total = 0; | |
362 for(int band = 0; band < numberOfBands; band++){ | |
363 total += sum[band]; | |
364 } | |
365 float average = total/numberOfBands; | |
366 | |
367 noveltyCurve.push_back(average); | |
368 } | |
369 | |
370 vector<float> noveltyCurveLocalAverage(numberOfBlocks); | |
371 | |
372 FIRFilter *filter = new FIRFilter(numberOfBlocks, hannN); | |
373 filter->process(&noveltyCurve[0], hannWindow, &noveltyCurveLocalAverage[0]); | |
374 delete filter; | |
375 | |
376 for (int i = 0; i < numberOfBlocks; i++){ | |
377 | |
378 noveltyCurve[i] -= noveltyCurveLocalAverage[i]; | |
379 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0; | |
380 | |
381 if(featureSet != NULL){ | |
382 Feature ncFeature; | |
383 ncFeature.hasTimestamp = true; | |
384 ncFeature.timestamp = ncTimestamps[i]; | |
385 ncFeature.values.push_back(noveltyCurve[i]); | |
386 (*featureSet)[1].push_back(ncFeature); | |
387 } | |
388 } | |
389 | |
390 return noveltyCurve; | |
391 } | |
392 | |
339 Tempogram::FeatureSet | 393 Tempogram::FeatureSet |
340 Tempogram::getRemainingFeatures() | 394 Tempogram::getRemainingFeatures() |
341 { | 395 { |
342 //Make sure this is called at the beginning of the function | 396 //Make sure this is called at the beginning of the function |
343 initialiseForGRF(); | 397 initialiseForGRF(); |
344 FeatureSet featureSet; | 398 FeatureSet featureSet; |
345 | 399 |
346 vector<float> noveltyCurveLocalAverage(ncLength); | 400 noveltyCurve = spectrogramToNoveltyCurve(specData, numberOfBlocks, m_blockSize, m_inputSampleRate, &featureSet); |
347 | |
348 FIRFilter *filter = new FIRFilter(ncLength, hannN); | |
349 filter->process(&noveltyCurve[0], hannWindow, &noveltyCurveLocalAverage[0]); | |
350 delete filter; | |
351 | |
352 for(int i = 0; i < ncLength; i++){ | |
353 noveltyCurve[i] -= noveltyCurveLocalAverage[i]; | |
354 noveltyCurve[i] = noveltyCurve[i] >= 0 ? noveltyCurve[i] : 0; | |
355 Feature ncFeature; | |
356 ncFeature.hasTimestamp = true; | |
357 ncFeature.timestamp = ncTimestamps[i]; | |
358 ncFeature.values.push_back(noveltyCurve[i]); | |
359 featureSet[1].push_back(ncFeature); | |
360 } | |
361 | |
362 WindowFunction::hanning(hannWindowtN, tN); | 401 WindowFunction::hanning(hannWindowtN, tN); |
363 | 402 |
364 int timestampInc = floor((((float)ncTimestamps[1].nsec - ncTimestamps[0].nsec)/1e9)*(thopSize) + 0.5); | 403 int timestampInc = floor((((float)ncTimestamps[1].nsec - ncTimestamps[0].nsec)/1e9)*(thopSize) + 0.5); |
365 int i=0; | 404 int i = 0; |
366 int index; | 405 int index; |
367 int frameBeginOffset = floor(tN/2 + 0.5); | 406 int frameBeginOffset = floor(tN/2 + 0.5); |
368 | 407 |
369 while(i < ncLength){ | 408 while(i < numberOfBlocks){ |
370 Feature feature; | 409 Feature feature; |
371 | 410 |
372 for (int n = frameBeginOffset; n < tN; n++){ | 411 for (int n = frameBeginOffset; n < tN; n++){ |
373 index = i + n - tN/2; | 412 index = i + n - tN/2; |
374 assert (index >= 0); | 413 assert (index >= 0); |
375 | 414 |
376 if(index < ncLength){ | 415 if(index < numberOfBlocks){ |
377 fftInput[n] = noveltyCurve[i + n] * hannWindowtN[n]; | 416 fftInput[n] = noveltyCurve[i + n] * hannWindowtN[n]; |
378 } | 417 } |
379 else if(index >= ncLength){ | 418 else if(index >= numberOfBlocks){ |
380 fftInput[n] = 0.0; //pad the end with zeros | 419 fftInput[n] = 0.0; //pad the end with zeros |
381 } | 420 } |
382 //cout << fftInput[n] << endl; | 421 //cout << fftInput[n] << endl; |
383 } | 422 } |
384 if (i+tN/2 > ncLength){ | 423 if (i+tN/2 > numberOfBlocks){ |
385 feature.timestamp = Vamp::RealTime::fromSeconds(ncTimestamps[i].sec + timestampInc); | 424 feature.timestamp = Vamp::RealTime::fromSeconds(ncTimestamps[i].sec + timestampInc); |
386 } | 425 } |
387 else{ | 426 else{ |
388 feature.timestamp = ncTimestamps[i + tN/2]; | 427 feature.timestamp = ncTimestamps[i + tN/2]; |
389 } | 428 } |