annotate ofxPreciseOnsetDetectorOffline/PreciseOnsetDetectorOffline.cpp @ 8:184a7c232049 tip

changed files since updating computer
author Venetian
date Thu, 14 Aug 2014 17:53:57 +0100
parents b1c13e8bec26
children
rev   line source
andrew@2 1 /*
andrew@2 2 * PreciseOnsetDetectorOffline.cpp
andrew@2 3 * ofxPreciseOnsetDetectionOffline
andrew@2 4 *
andrew@2 5 * Created by Andrew Robertson on 25/12/2013.
andrew@2 6 * Copyright 2013 QMUL. All rights reserved.
andrew@2 7 *
andrew@2 8 */
andrew@2 9
andrew@2 10
andrew@2 11 //add a retrigger threshold
andrew@2 12
andrew@2 13 #include "PreciseOnsetDetectorOffline.h"
andrew@2 14
Venetian@7 15 const bool printingOn = false;//true
Venetian@7 16
Venetian@7 17 //can work just by calling initialise, then recursive call to processAudioFrame(float* frame, in numSamples)
Venetian@7 18 //set the dfType - initialises to energy - good for bass and drums, not so good for harmonic instruments
andrew@6 19
andrew@2 20 PreciseOnsetDetectorOffline::PreciseOnsetDetectorOffline(){
andrew@2 21 frameSize = 1024;
andrew@2 22 hopSize = 512;
andrew@2 23 preciseLocator.setup(frameSize);
andrew@2 24 writeOutput = true;//write output to txt when loading file - stored at sample location as file
Venetian@7 25
Venetian@7 26 dfType = 5;//see onset detection class
Venetian@7 27 //0 energy
Venetian@7 28 //5 is csd
Venetian@7 29
Venetian@7 30 ringbuffer = new AudioRingBuffer(frameSize, hopSize);
Venetian@7 31 sampleCount = 0;
Venetian@7 32 frameCount = 0;
Venetian@7 33
Venetian@7 34 initialised = false;
Venetian@7 35
Venetian@7 36 //some params for peak processing
Venetian@7 37 peakProcess.cutoffForRepeatOnsetsFrames = 8;
Venetian@7 38 peakProcess.detectionTriggerRatio = 0.5f;//was 0.5
Venetian@7 39 peakProcess.bestSlopeMedian = 3;
Venetian@7 40 peakProcess.thresholdRelativeToMedian = 1.81;
Venetian@7 41
Venetian@7 42 isBass = false;
andrew@2 43 }
andrew@2 44
andrew@2 45 PreciseOnsetDetectorOffline::~PreciseOnsetDetectorOffline(){
Venetian@7 46
Venetian@7 47 if (initialised)
Venetian@7 48 delete detectionFunction;
Venetian@7 49
Venetian@7 50 delete ringbuffer;
Venetian@7 51
andrew@2 52 }
andrew@2 53
Venetian@7 54 void PreciseOnsetDetectorOffline::initialise(){
Venetian@7 55 clearAll();
Venetian@7 56 sampleCount = 0;
Venetian@7 57 frameCount = 0;
Venetian@7 58 // initialises with hopsize = 512, framesize = 1024, complex spectral difference DF and hanning window
Venetian@7 59 detectionFunction = new OnsetDetectionFunction(hopSize, frameSize, dfType, 1);
Venetian@7 60
Venetian@7 61 setDfType(5);//for csd
Venetian@7 62 initialised = true;
Venetian@7 63
Venetian@7 64 peakProcess.reset();
Venetian@7 65 }
Venetian@7 66
Venetian@7 67 void PreciseOnsetDetectorOffline::endProcessing(){
Venetian@7 68 delete detectionFunction;
Venetian@7 69 detectionFunction = NULL;
Venetian@7 70 initialised = false;
Venetian@7 71
Venetian@7 72 printf("frames in seconds %f\n", secondsToFrameIndex(samples/44100.));
Venetian@7 73 printf("frames %i\n", (int) dfValues.size());
Venetian@7 74
Venetian@7 75 }
Venetian@7 76
Venetian@7 77 #pragma mark AudioProcessing
Venetian@7 78 void PreciseOnsetDetectorOffline::processAudioFrame(float* frame, int n){
Venetian@7 79 //call initialise before starting here
Venetian@7 80 assert(initialised);
Venetian@7 81
Venetian@7 82 sampleCount += n;
Venetian@7 83
Venetian@7 84 if (ringbuffer->addToBuffer(frame, n)){
Venetian@7 85 //for (int i = 0; i < ringbuffer->buffersize; i++)
Venetian@7 86 // printf("ring[%i] %.6f\n", i, ringbuffer->audiobuffer[i]);
Venetian@7 87
Venetian@7 88
Venetian@7 89 //needed to make sure df fn is same framesize as our ringbuffer
Venetian@7 90 double dfval = detectionFunction->getDFsample(ringbuffer->audiobuffer); // compute detection function sample
Venetian@7 91
Venetian@7 92 dfValues.push_back(dfval);
Venetian@7 93
Venetian@7 94 if (printingOn)
Venetian@7 95 printf("det val %i: %f\n", frameCount, dfval);
Venetian@7 96
Venetian@7 97 if (peakProcess.peakProcessing(dfval)){
Venetian@7 98
Venetian@7 99 //onsetPositionFrames.push_back(frameCount);
Venetian@7 100
Venetian@7 101 int precisesample = preciseLocator.findExactOnset(ringbuffer->audiobuffer);
Venetian@7 102
Venetian@7 103 //printf("precise sample is %i\n", precisesample);
Venetian@7 104 //so exact sample is
Venetian@7 105 //int exactsample = (frameCount-1)*hopSize;//chunks in from beginning of frame
Venetian@7 106 //as we have just added hopsize samples in, the beginning of the frame is -1 from counter
Venetian@7 107 //exactsample += precisesample;
Venetian@7 108
Venetian@7 109 //above was old way, but not as neat
Venetian@7 110
Venetian@7 111 //number of samples in, but to beginning of frame, then precisesample in from there
Venetian@7 112 int alternativePreciseSample = sampleCount - frameSize + precisesample;
Venetian@7 113
Venetian@7 114 //printf("PreciseSample %i, %i == %i\n", precisesample, exactsample, alternativePrecise);
Venetian@7 115
Venetian@7 116 OnsetInfo newOnsetInfo;
Venetian@7 117 newOnsetInfo.onsetLocation = alternativePreciseSample/44100.;
Venetian@7 118 newOnsetInfo.positionSamples = alternativePreciseSample;
Venetian@7 119 newOnsetInfo.positionFrames = frameCount;
Venetian@7 120 newOnsetInfo.pitch = 0;
Venetian@7 121 newOnsetInfo.matchIndicator = 0;
Venetian@7 122 newOnsetInfo.onBeat = false;
Venetian@7 123 newOnsetInfo.expressiveTiming = 0;
Venetian@7 124 // onsetLocations.push_back(alternativePreciseSample/44100.);
Venetian@7 125 // onsetPositionSamples.push_back(alternativePreciseSample);
Venetian@7 126 onsetList.push_back(newOnsetInfo);
Venetian@7 127
Venetian@7 128
Venetian@7 129 if (printingOn)
Venetian@7 130 printf("BANG\n");
Venetian@7 131 }
Venetian@7 132
Venetian@7 133 frameCount++;
Venetian@7 134
Venetian@7 135 }
Venetian@7 136
Venetian@7 137 }
Venetian@7 138
Venetian@7 139
Venetian@7 140 void PreciseOnsetDetectorOffline::setDfType(int t){
Venetian@7 141 if (t >= 0 && t <= 9)
Venetian@7 142 dfType = t;
Venetian@7 143
Venetian@7 144 /*
Venetian@7 145 switch (df_type){
Venetian@7 146 case 0:
Venetian@7 147 df_sample = energy_envelope(); // calculate energy envelope detection function sample
Venetian@7 148 break;
Venetian@7 149 case 1:
Venetian@7 150 df_sample = energy_difference(); // calculate half-wave rectified energy difference detection function sample
Venetian@7 151 break;
Venetian@7 152 case 2:
Venetian@7 153 df_sample = spectral_difference(); // calculate spectral difference detection function sample
Venetian@7 154 break;
Venetian@7 155 case 3:
Venetian@7 156 df_sample = spectral_difference_hwr(); // calculate spectral difference detection function sample (half wave rectified)
Venetian@7 157 break;
Venetian@7 158 case 4:
Venetian@7 159 df_sample = phase_deviation(); // calculate phase deviation detection function sample (half wave rectified)
Venetian@7 160 break;
Venetian@7 161 case 5:
Venetian@7 162 df_sample = complex_spectral_difference(); // calcualte complex spectral difference detection function sample
Venetian@7 163 break;
Venetian@7 164 case 6:
Venetian@7 165 df_sample = complex_spectral_difference_hwr(); // calcualte complex spectral difference detection function sample (half-wave rectified)
Venetian@7 166 break;
Venetian@7 167 case 7:
Venetian@7 168 df_sample = high_frequency_content(); // calculate high frequency content detection function sample
Venetian@7 169 break;
Venetian@7 170 case 8:
Venetian@7 171 df_sample = high_frequency_spectral_difference(); // calculate high frequency spectral difference detection function sample
Venetian@7 172 break;
Venetian@7 173 case 9:
Venetian@7 174 df_sample = high_frequency_spectral_difference_hwr(); // calculate high frequency spectral difference detection function (half-wave rectified)
Venetian@7 175 break;
Venetian@7 176 */
Venetian@7 177 }
andrew@2 178
andrew@4 179 int PreciseOnsetDetectorOffline::load(std::string filename){
andrew@2 180
andrew@2 181 //name for output file is same dir and filename as aif/wav but with _preciseOnsets.txt added
andrew@2 182 //eg 'song.wav' is 'song.wav_preciseOnsets.txt'
andrew@2 183
Venetian@7 184 //printf("PODO: load '%s'\n", filename.c_str());
Venetian@7 185 return processAudioFileForBeatTimes(filename);
andrew@2 186 }
andrew@2 187
andrew@2 188
Venetian@7 189 void PreciseOnsetDetectorOffline::clearAll(){
Venetian@7 190
Venetian@7 191 dfValues.clear();
Venetian@7 192 onsetList.clear();
Venetian@7 193 // onsetLocations.clear();
Venetian@7 194 // onsetPositionFrames.clear();
Venetian@7 195 // onsetPositionSamples.clear();
Venetian@7 196 }
andrew@2 197
Venetian@7 198
Venetian@7 199 int PreciseOnsetDetectorOffline::processAudioFileForBeatTimes(std::string audiofile){
andrew@2 200 //originally from BeatAnnotationViewer project
Venetian@7 201 printf("PODO: ProcessFunction %s\n", audiofile.c_str());
Venetian@7 202
Venetian@7 203 initialise();// - needed but elsewhere
Venetian@7 204
andrew@3 205
andrew@2 206
andrew@2 207 // static double frame[FRAMESIZE]; // to hold a single frame
andrew@2 208 double buffer[frameSize];
andrew@2 209 double dfval;
andrew@2 210
andrew@2 211 for (int i = 0;i < frameSize;i++)
andrew@2 212 {
andrew@2 213 buffer[i] = 0;
andrew@2 214 }
andrew@2 215
andrew@2 216 //detfun = new df(1,(FRAMESIZE*2),0);
andrew@2 217
Venetian@7 218
andrew@2 219
andrew@2 220 SNDFILE *infile, *outfile ; // define input and output sound files
andrew@2 221
andrew@2 222 SF_INFO sfinfo ; // struct to hold info about sound file
andrew@2 223 int readcount ; // counts number of samples read from sound file
andrew@2 224 const char *infilename = audiofile.c_str();
andrew@2 225 //"/Users/andrew/Music/Station To Station 2/3-03 Panic In Detroit (Live Nassau Coliseum '76).wav";//"ledzep.wav" ; // input file name
andrew@2 226 // const char *outfilename = "output.wav" ; // output file name
andrew@2 227
andrew@2 228
andrew@2 229 // Open Input File
andrew@2 230 if (! (infile = sf_open (infilename, SFM_READ, &sfinfo)))
andrew@2 231 { // Open failed
andrew@2 232 printf ("Not able to open input file %s.\n", infilename) ;
andrew@2 233 // Print the error message from libsndfile.
andrew@2 234 puts (sf_strerror (NULL)) ;
andrew@2 235 return 1;
andrew@2 236 } ;
andrew@2 237
andrew@2 238 printf("opened '%s'\n", audiofile.c_str());
andrew@2 239 loadedFilename = audiofile;
andrew@2 240 //STEREO OKAY
andrew@2 241
andrew@2 242 //HERE IS THE CLASSIC LOADING FILE CODE
andrew@2 243 //DEALS WITH MORE THAN MONO
andrew@2 244 int channels = sfinfo.channels;
andrew@2 245 samples = sfinfo.frames;
andrew@2 246 printf("Number of channels %i, samples %i\n", channels, samples);
andrew@2 247
andrew@2 248
andrew@2 249 int blocksize = hopSize;//FRAMESIZE;
andrew@2 250 float buf [channels * blocksize] ;
andrew@2 251 float frame[blocksize];
andrew@2 252
andrew@2 253 int k, m;
andrew@2 254 readcount = 1;
Venetian@7 255
andrew@2 256
andrew@2 257 //DoubleVector d;
andrew@2 258 while ((readcount = sf_readf_float (infile, buf, blocksize)) > 0){
andrew@2 259 for (k = 0 ; k < readcount ; k++){
andrew@2 260 //d.clear();
andrew@2 261 frame[k] = 0;
andrew@2 262
andrew@2 263 for (m = 0 ; m < channels ; m++){
andrew@2 264 frame[k] += buf[k*channels + 0];//sum the channels together
andrew@2 265 //d.push_back(buf [k * channels + m]);
andrew@2 266 }
andrew@2 267
andrew@2 268 frame[k] /= channels;//average of the channels
andrew@2 269 }
andrew@2 270
Venetian@7 271 processAudioFrame(frame, blocksize);
Venetian@7 272
andrew@2 273 //add to our buffer for pocessing
andrew@2 274 for (int i = 0; i< frameSize-hopSize;i++)
andrew@2 275 {
andrew@2 276 buffer[i] = buffer[i+hopSize];
andrew@2 277 buffer[i+hopSize] = frame[i];
andrew@2 278 }
Venetian@7 279 /*
Venetian@7 280 for (int i = 0; i < frameSize; i++)
Venetian@7 281 printf("buffer[%i] %.6f\n", i, buffer[i]);
andrew@2 282
andrew@2 283 dfval = detectionFunction->getDFsample(buffer); // compute detection function sample
andrew@2 284
andrew@2 285 dfValues.push_back(dfval);
andrew@2 286
Venetian@7 287 // if (printingOn)
Venetian@7 288 // printf("det val %i: %f\n", counter, dfval);
andrew@2 289
andrew@2 290 if (peakProcess.peakProcessing(dfval)){
andrew@6 291
andrew@2 292 onsetPositionFrames.push_back(counter);
andrew@2 293 int precisesample = preciseLocator.findExactOnset(&buffer[0]);
Venetian@7 294 printf("precise sample is %i\n", precisesample);
andrew@2 295 //so exact sample is
Venetian@7 296 int exactsample = (counter-1)*hopSize;//chunks in from beginning of frame
andrew@2 297 //as we have just added hopsize samples in, the beginning of the frame is -1 from counter
andrew@2 298 exactsample += precisesample;
andrew@2 299 //printf("PreciseSample %i, %i\n", precisesample, exactsample);
andrew@3 300
andrew@2 301
andrew@2 302 onsetLocations.push_back(exactsample/44100.);
Venetian@7 303 onsetPositionSamples.push_back(exactsample);
Venetian@7 304
Venetian@7 305
andrew@6 306
andrew@6 307 if (printingOn)
andrew@6 308 printf("BANG\n");
andrew@2 309 }
andrew@2 310
andrew@2 311 counter++;
Venetian@7 312 */
andrew@4 313 //printf("read %i samples\n", readcount);
andrew@2 314 //was sf_write_double(outfile, frame, readcount) ;
andrew@2 315
andrew@2 316 }//end readcount
andrew@2 317 //END STEREO OKAY
andrew@2 318
andrew@2 319 // Close input file
andrew@2 320 sf_close (infile);
andrew@2 321
Venetian@7 322 endProcessing();
andrew@6 323
andrew@2 324 return 0;
andrew@2 325
andrew@2 326 }
andrew@2 327
andrew@4 328 double PreciseOnsetDetectorOffline::frameIndexToSeconds(const int& frameIndex){
andrew@4 329 return ((double)(frameIndex*hopSize) /44100.);//- (detectionFunction.framesize/2)?;
andrew@4 330 }
andrew@4 331
andrew@4 332 double PreciseOnsetDetectorOffline::secondsToFrameIndex(const double& seconds){
andrew@4 333 return (seconds*44100./(double)hopSize );//- (detectionFunction.framesize/2)?;
andrew@4 334 }
andrew@4 335
andrew@4 336
andrew@3 337 void PreciseOnsetDetectorOffline::exportOnsetTimes(){
andrew@3 338 exportOnsetTimes(0.0, samples/44100.0);//i.e. the whole file
andrew@3 339 }
andrew@2 340
andrew@2 341
andrew@3 342 void PreciseOnsetDetectorOffline::exportOnsetTimes(double startTime, double endTime){
andrew@3 343 //for writing output
andrew@3 344 BeatWriter writer;
andrew@3 345 std::string outputFilename = loadedFilename+"_preciseOnsets.txt";
andrew@3 346
andrew@3 347 if (writeOutput)
andrew@3 348 writer.openFile(outputFilename);
andrew@3 349
andrew@3 350
andrew@3 351 int index = 0;
Venetian@7 352 while (index < onsetList.size() && onsetList[index].onsetLocation < startTime)
andrew@3 353 index++;
andrew@3 354
Venetian@7 355 while (index < onsetList.size() && onsetList[index].onsetLocation <= endTime){
Venetian@7 356 writer.writeBeatTime(onsetList[index].onsetLocation);
andrew@3 357 index++;
andrew@3 358 }
andrew@3 359
andrew@3 360 if (writeOutput)
andrew@3 361 writer.closeFile();
andrew@3 362 }
andrew@2 363
andrew@2 364 void PreciseOnsetDetectorOffline::update(){
andrew@2 365
andrew@2 366 }
andrew@2 367
andrew@2 368
andrew@2 369 void PreciseOnsetDetectorOffline::draw(){
andrew@2 370 //do vizualisation in a specialised class
andrew@2 371 }
andrew@2 372
andrew@2 373 void PreciseOnsetDetectorOffline::printOnsetLocations(){
Venetian@7 374 for (int i = 0; i < (int)onsetList.size(); i++)
Venetian@7 375 printf("Onset[%i]: %.3f, samples %i\n", i, onsetList[i].onsetLocation, onsetList[i].positionSamples);
andrew@2 376 }
andrew@3 377
andrew@3 378 double PreciseOnsetDetectorOffline::closestOnset(double& targetVal){
andrew@3 379 int bestIndex = 0;
andrew@3 380 double bestDiff = 99999;
andrew@3 381 double bestVal = -1;
andrew@3 382
Venetian@7 383 for (int testIndex = 0; testIndex < (int)onsetList.size(); testIndex++){
Venetian@7 384 double testDiff = (onsetList[testIndex].onsetLocation - targetVal);
andrew@3 385 if (fabs(testDiff) < bestDiff){
andrew@3 386 bestDiff = fabs(testDiff);
Venetian@7 387 bestVal = onsetList[testIndex].onsetLocation;
andrew@3 388 bestIndex = testIndex;
andrew@3 389 }
andrew@3 390 }
andrew@3 391 return bestVal;
andrew@3 392 }
andrew@3 393
andrew@4 394 void PreciseOnsetDetectorOffline::loadOnsetLocations(DoubleVector& beats){
andrew@4 395 //replaces onset locations with new vector
Venetian@7 396 onsetList.clear();
Venetian@7 397
Venetian@7 398 //onsetLocations.clear();
andrew@4 399 for (int i = 0; i < beats.size(); i++){
Venetian@7 400 //onsetLocations.push_back(beats[i]);
Venetian@7 401 OnsetInfo newInfo;
Venetian@7 402 newInfo.onsetLocation = beats[i];
Venetian@7 403 onsetList.push_back(newInfo);
andrew@4 404 }
Venetian@7 405 }
Venetian@7 406
Venetian@7 407 double PreciseOnsetDetectorOffline::onsetAtIndex(int index){
Venetian@7 408 if (index < onsetList.size())
Venetian@7 409 return onsetList[index].onsetLocation;
Venetian@7 410 else
Venetian@7 411 return 0;
Venetian@7 412 /*
Venetian@7 413 if (index < onsetLocations.size())
Venetian@7 414 return onsetLocations[index];
Venetian@7 415 else
Venetian@7 416 return 0;
Venetian@7 417 */
Venetian@7 418 }
Venetian@7 419
Venetian@7 420 void PreciseOnsetDetectorOffline::cropStartTo(double startTime){
Venetian@7 421 int index = 0;
Venetian@7 422 while (index < onsetList.size() && onsetList[index].onsetLocation < startTime){
Venetian@7 423 onsetList.erase(onsetList.begin());
Venetian@7 424 // onsetLocations.erase(onsetLocations.begin());
Venetian@7 425 // onsetPositionSamples.erase(onsetPositionSamples.begin());
Venetian@7 426 // onsetPositionFrames.erase(onsetPositionFrames.begin());
Venetian@7 427 }
Venetian@7 428 /*
Venetian@7 429 int index = 0;
Venetian@7 430 while (index < onsetLocations.size() && onsetLocations[index] < startTime){
Venetian@7 431 onsetLocations.erase(onsetLocations.begin());
Venetian@7 432 onsetPositionSamples.erase(onsetPositionSamples.begin());
Venetian@7 433 onsetPositionFrames.erase(onsetPositionFrames.begin());
Venetian@7 434 }
Venetian@7 435 */
Venetian@7 436 }
Venetian@7 437
Venetian@7 438 void PreciseOnsetDetectorOffline::setMinimumThreshold(float fVal){
Venetian@7 439 peakProcess.minimumThreshold = fVal;
Venetian@7 440 }
Venetian@7 441
Venetian@7 442
Venetian@7 443
Venetian@7 444 double PreciseOnsetDetectorOffline::beatAtIndex(std::vector<double> beatTimes, int beatIndex){
Venetian@7 445 if (beatIndex >= 0 && beatIndex < beatTimes.size()){
Venetian@7 446 return beatTimes[beatIndex];
Venetian@7 447 } else {
Venetian@7 448 printf("OUT OF RANGE\n");
Venetian@7 449 return 0;
Venetian@7 450 }
Venetian@7 451 }
Venetian@7 452
Venetian@7 453
Venetian@7 454
Venetian@7 455 #pragma mark Quantisation
Venetian@7 456 void PreciseOnsetDetectorOffline::categoriseOnsets(std::vector<double> beatTimes){
Venetian@7 457 double onsetTime;
Venetian@7 458 double cutoff = 0.06;//seconds - is it within this range of given beat times
Venetian@7 459
Venetian@7 460 for (int i = 0; i < onsetList.size(); i++){
Venetian@7 461
Venetian@7 462 onsetTime = onsetList[i].onsetLocation;
Venetian@7 463
Venetian@7 464 int beatIndex = 0;
Venetian@7 465 while(beatIndex < beatTimes.size() && beatTimes[beatIndex] < onsetTime){
Venetian@7 466 beatIndex++;
Venetian@7 467 }
Venetian@7 468 while(beatIndex > 0 && beatTimes[beatIndex] > onsetTime){
Venetian@7 469 beatIndex--;
Venetian@7 470 }
Venetian@7 471 //beatIndex now either side of onset, or onset before first beat
Venetian@7 472
Venetian@7 473 printf("beat %.2f, beat+1 %.2f, onset %.2f\n", beatAtIndex(beatTimes, beatIndex),
Venetian@7 474 beatAtIndex(beatTimes, beatIndex+1), onsetTime);
Venetian@7 475
Venetian@7 476 double beatTime = beatAtIndex(beatTimes, beatIndex);
Venetian@7 477 double nextBeatTime = beatAtIndex(beatTimes, beatIndex+1);
Venetian@7 478
Venetian@7 479 //new cutoff part
Venetian@7 480 onsetList[i].onBeat = false;
Venetian@7 481
Venetian@7 482
Venetian@7 483
Venetian@7 484 if (fabs(onsetTime-beatTime) < cutoff || fabs(onsetTime-nextBeatTime) < cutoff){
Venetian@7 485 onsetList[i].onBeat = true;
Venetian@7 486 }
Venetian@7 487 //end cutoff part
Venetian@7 488
Venetian@7 489 double diff = onsetTime - beatTime;
Venetian@7 490
Venetian@7 491 double period;
Venetian@7 492 if (nextBeatTime){
Venetian@7 493 period = nextBeatTime - beatTime;
Venetian@7 494 } else {
Venetian@7 495 period = beatAtIndex(beatTimes, beatIndex) - beatAtIndex(beatTimes, beatIndex-1);
Venetian@7 496 }
Venetian@7 497
Venetian@7 498 while (onsetTime < beatTime){
Venetian@7 499 //bug if onset is before th first beat
Venetian@7 500 beatTime -= period;
Venetian@7 501 nextBeatTime -= period;
Venetian@7 502 beatIndex--;
Venetian@7 503 printf("FIXING: beat index %i time %f onsest %f\n", beatIndex, beatTime, onsetTime);
Venetian@7 504 }
Venetian@7 505
Venetian@7 506 if (period > 0){
Venetian@7 507 while (diff < 0){
Venetian@7 508 diff += period;
Venetian@7 509 //i.e. add the beat period to bring it in range
Venetian@7 510 }
Venetian@7 511 //now can look which point it is nearest
Venetian@7 512 double ratio = diff/period;
Venetian@7 513 ratio *= 12;
Venetian@7 514 int beattype = round(ratio);
Venetian@7 515 if (beattype == 12){
Venetian@7 516 beattype = 0;
Venetian@7 517
Venetian@7 518 beatIndex++;//added need to test
Venetian@7 519 }
Venetian@7 520
Venetian@7 521 doCorrection(beattype, beatIndex);
Venetian@7 522
Venetian@7 523
Venetian@7 524
Venetian@7 525 // Onset newOnset;
Venetian@7 526 // newOnset.time = onsetTime;
Venetian@7 527 // newOnset.onsetType = beattype;
Venetian@7 528 //int position = beatIndex%4;
Venetian@7 529
Venetian@7 530 // if (onsetTime > beatTime + (period/2.))
Venetian@7 531 // pos++;
Venetian@7 532 // newOnset.position = pos%4;
Venetian@7 533
Venetian@7 534 onsetList[i].beatPosition = beatIndex;
Venetian@7 535 onsetList[i].onsetType = beattype;
Venetian@7 536
Venetian@7 537 printf("Position %i,%i\n", onsetList[i].beatPosition, beattype);
Venetian@7 538 }
Venetian@7 539
Venetian@7 540 }
Venetian@7 541
Venetian@7 542 }
Venetian@7 543
Venetian@7 544
Venetian@7 545 void PreciseOnsetDetectorOffline::doCorrection(int& beattype, int& beatPosition){
Venetian@7 546 switch (beattype) {
Venetian@7 547 case 1:
Venetian@7 548 beattype = 0;//on beat
Venetian@7 549 break;
Venetian@7 550 case 2:
Venetian@7 551 beattype = 3;//16th
Venetian@7 552 break;
Venetian@7 553 case 5: case 7:
Venetian@7 554 beattype = 6;//8th note
Venetian@7 555 break;
Venetian@7 556 case 10:
Venetian@7 557 beattype = 9;
Venetian@7 558 break;
Venetian@7 559 case 11:
Venetian@7 560 beattype = 0;//on the beat
Venetian@7 561 beatPosition++;
Venetian@7 562 break;
Venetian@7 563 default:
Venetian@7 564 break;
Venetian@7 565 }
Venetian@7 566
Venetian@7 567 }
Venetian@7 568
Venetian@7 569
Venetian@7 570
Venetian@7 571
Venetian@7 572 int PreciseOnsetDetectorOffline::onsetAtBeat(int testPosition){
Venetian@7 573 //find onset bear at particular beat
Venetian@7 574 int index = 0;
Venetian@7 575 int foundIndex = 0;
Venetian@7 576 bool found = false;
Venetian@7 577 double tmpDiff = 10000;
Venetian@7 578 while (index < onsetList.size() && onsetList[index].beatPosition <= testPosition){
Venetian@7 579
Venetian@7 580 if (onsetList[index].beatPosition == testPosition && onsetList[index].onsetType == 0){
Venetian@7 581 found = true;
Venetian@7 582 foundIndex = index;
Venetian@7 583 //tmpDiff = fabs(onsetList[index].onsetLocation -
Venetian@7 584 //break; - could break here - would find the first onset
Venetian@7 585 //commented out finds the last one - really we'd just want the closest one to beat time
Venetian@7 586 }
Venetian@7 587 index++;
Venetian@7 588 }
Venetian@7 589 if (found)
Venetian@7 590 return foundIndex;
Venetian@7 591 else
Venetian@7 592 return -1;
Venetian@7 593 }
Venetian@7 594