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 }