annotate ofxPreciseOnsetDetectorOffline/PreciseBassOnsetDetectorOffline.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
Venetian@7 1 /*
Venetian@7 2 * PreciseBassOnsetDetectorOffline.cpp
Venetian@7 3 * BasslinePrediction
Venetian@7 4 *
Venetian@7 5 * Created by Andrew N Robertson on 11/04/2014.
Venetian@7 6 * Copyright 2014 QMUL. All rights reserved.
Venetian@7 7 *
Venetian@7 8 */
Venetian@7 9
Venetian@7 10 #include "PreciseBassOnsetDetectorOffline.h"
Venetian@7 11
Venetian@7 12 bool printingOn = false;//true;
Venetian@7 13
Venetian@7 14 int PreciseBassOnsetDetectorOffline::processAudioFileForBeatTimes(std::string audiofile){
Venetian@7 15 printf("PBODO: Process Function BASS OFFLINE VERSION\n");
Venetian@7 16
Venetian@7 17 //originally from BeatAnnotationViewer project
Venetian@7 18
Venetian@7 19 initialise();// - needed but elsewhere
Venetian@7 20 isBass = true;
Venetian@7 21
Venetian@7 22 // static double frame[FRAMESIZE]; // to hold a single frame
Venetian@7 23 double buffer[frameSize];
Venetian@7 24 double dfval;
Venetian@7 25
Venetian@7 26 for (int i = 0;i < frameSize;i++)
Venetian@7 27 {
Venetian@7 28 buffer[i] = 0;
Venetian@7 29 }
Venetian@7 30
Venetian@7 31 //detfun = new df(1,(FRAMESIZE*2),0);
Venetian@7 32
Venetian@7 33
Venetian@7 34
Venetian@7 35 SNDFILE *infile, *outfile ; // define input and output sound files
Venetian@7 36
Venetian@7 37 SF_INFO sfinfo ; // struct to hold info about sound file
Venetian@7 38 int readcount ; // counts number of samples read from sound file
Venetian@7 39 const char *infilename = audiofile.c_str();
Venetian@7 40 //"/Users/andrew/Music/Station To Station 2/3-03 Panic In Detroit (Live Nassau Coliseum '76).wav";//"ledzep.wav" ; // input file name
Venetian@7 41 // const char *outfilename = "output.wav" ; // output file name
Venetian@7 42
Venetian@7 43
Venetian@7 44 // Open Input File
Venetian@7 45 if (! (infile = sf_open (infilename, SFM_READ, &sfinfo)))
Venetian@7 46 { // Open failed
Venetian@7 47 printf ("Not able to open input file %s.\n", infilename) ;
Venetian@7 48 // Print the error message from libsndfile.
Venetian@7 49 puts (sf_strerror (NULL)) ;
Venetian@7 50 return 1;
Venetian@7 51 } ;
Venetian@7 52
Venetian@7 53 printf("opened '%s'\n", audiofile.c_str());
Venetian@7 54 loadedFilename = audiofile;
Venetian@7 55 //STEREO OKAY
Venetian@7 56
Venetian@7 57 //HERE IS THE CLASSIC LOADING FILE CODE
Venetian@7 58 //DEALS WITH MORE THAN MONO
Venetian@7 59 int channels = sfinfo.channels;
Venetian@7 60 samples = sfinfo.frames;
Venetian@7 61 printf("Number of channels %i, samples %i\n", channels, samples);
Venetian@7 62
Venetian@7 63
Venetian@7 64 int blocksize = hopSize;//FRAMESIZE;
Venetian@7 65 float buf [channels * blocksize] ;
Venetian@7 66 float frame[blocksize];
Venetian@7 67
Venetian@7 68 int k, m;
Venetian@7 69 readcount = 1;
Venetian@7 70
Venetian@7 71
Venetian@7 72 //DoubleVector d;
Venetian@7 73 while ((readcount = sf_readf_float (infile, buf, blocksize)) > 0){
Venetian@7 74 for (k = 0 ; k < readcount ; k++){
Venetian@7 75 //d.clear();
Venetian@7 76 frame[k] = 0;
Venetian@7 77
Venetian@7 78 for (m = 0 ; m < channels ; m++){
Venetian@7 79 frame[k] += buf[k*channels + 0];//sum the channels together
Venetian@7 80 //d.push_back(buf [k * channels + m]);
Venetian@7 81 }
Venetian@7 82
Venetian@7 83 frame[k] /= channels;//average of the channels
Venetian@7 84 }
Venetian@7 85
Venetian@7 86 processAudioFrame(frame, blocksize);
Venetian@7 87 processYinAudio(frame, blocksize);
Venetian@7 88 //have now processed framecount samples
Venetian@7 89 processBassPitches();
Venetian@7 90
Venetian@7 91 //add to our buffer for pocessing
Venetian@7 92 for (int i = 0; i< frameSize-hopSize;i++)
Venetian@7 93 {
Venetian@7 94 buffer[i] = buffer[i+hopSize];
Venetian@7 95 buffer[i+hopSize] = frame[i];
Venetian@7 96 }
Venetian@7 97
Venetian@7 98 //printf("read %i samples\n", readcount);
Venetian@7 99 //was sf_write_double(outfile, frame, readcount) ;
Venetian@7 100
Venetian@7 101 }//end readcount
Venetian@7 102 //END STEREO OKAY
Venetian@7 103
Venetian@7 104 // Close input file
Venetian@7 105 sf_close (infile);
Venetian@7 106
Venetian@7 107 endProcessing();
Venetian@7 108
Venetian@7 109 return 0;
Venetian@7 110
Venetian@7 111 }
Venetian@7 112
Venetian@7 113 void PreciseBassOnsetDetectorOffline::processYinAudio(float* frame, int blocksize){
Venetian@7 114 //continually update yin
Venetian@7 115 yule.processBuffer(frame, (int)blocksize);
Venetian@7 116 }
Venetian@7 117
Venetian@7 118 void PreciseBassOnsetDetectorOffline::processBassPitches(){
Venetian@7 119 int tmpIndex = onsetList.size()-1;
Venetian@7 120 int hsize = 1024;
Venetian@7 121 while (tmpIndex >= 0 && onsetList[tmpIndex].positionSamples+8192+hsize>sampleCount){
Venetian@7 122 // printf("testing onset %i at %i, samplecount now %i diff %i\n", tmpIndex, onsetList[tmpIndex].positionSamples, sampleCount, sampleCount-onsetList[tmpIndex].positionSamples);
Venetian@7 123 if (onsetList[tmpIndex].positionSamples+8192 <= sampleCount && !onsetList[tmpIndex].pitch){
Venetian@7 124 //do yin value for this onset
Venetian@7 125 onsetList[tmpIndex].pitch = yule.yinFrequency;
Venetian@7 126
Venetian@7 127 float midiPitch = onsetList[tmpIndex].pitch/27.5;
Venetian@7 128 if (midiPitch > 0){
Venetian@7 129 midiPitch = 12.0*log(midiPitch)/log(2);
Venetian@7 130 midiPitch += 24+9;
Venetian@7 131 }
Venetian@7 132
Venetian@7 133 onsetList[tmpIndex].midiPitch = midiPitch;
Venetian@7 134 onsetList[tmpIndex].roundedPitch = round(midiPitch);
Venetian@7 135
Venetian@7 136 setMidiNoteString(tmpIndex, midiPitch);//sets string eg C#4
Venetian@7 137
Venetian@7 138 if (printingOn)
Venetian@7 139 printf("PBODO: Yin Pitch %i, %f, %f, %s\n", tmpIndex, onsetList[tmpIndex].pitch, midiPitch, onsetList[tmpIndex].midiName.c_str());
Venetian@7 140 }
Venetian@7 141
Venetian@7 142 tmpIndex--;
Venetian@7 143 }
Venetian@7 144 }
Venetian@7 145
Venetian@7 146 void PreciseBassOnsetDetectorOffline::printOnsetLocations(){
Venetian@7 147 for (int i = 0; i < (int)onsetList.size(); i++)
Venetian@7 148 printf("PBODO: Onset[%i]: %.3f, samples %i pitch %f, %i\n", i, onsetList[i].onsetLocation, onsetList[i].positionSamples, onsetList[i].pitch, onsetList[i].roundedPitch);
Venetian@7 149 }
Venetian@7 150
Venetian@7 151 void PreciseBassOnsetDetectorOffline::printPitchInfo(){
Venetian@7 152 for (int i = 0; i < (int)onsetList.size(); i++)
Venetian@7 153 printf("PBODO: Beat Position %i,%i: pitch %i\n", onsetList[i].beatPosition, onsetList[i].onsetType, onsetList[i].roundedPitch);
Venetian@7 154 }
Venetian@7 155
Venetian@7 156 void PreciseBassOnsetDetectorOffline::setMidiNoteString(int index, float midiPitch){
Venetian@7 157 std:string midiName = "";
Venetian@7 158 if (midiPitch > 0){
Venetian@7 159 midiPitch = round(midiPitch);
Venetian@7 160 int midiLetter = (int)midiPitch%12;
Venetian@7 161 int midiOctave = midiPitch - (int)midiPitch%12;
Venetian@7 162
Venetian@7 163 switch (midiLetter) {
Venetian@7 164 case 0:
Venetian@7 165 midiName = "C ";
Venetian@7 166 break;
Venetian@7 167 case 1:
Venetian@7 168 midiName = "C#";
Venetian@7 169 break;
Venetian@7 170 case 2:
Venetian@7 171 midiName = "D";
Venetian@7 172 break;
Venetian@7 173 case 3:
Venetian@7 174 midiName = "D#";
Venetian@7 175 break;
Venetian@7 176 case 4:
Venetian@7 177 midiName = "E";
Venetian@7 178 break;
Venetian@7 179 case 5:
Venetian@7 180 midiName = "F ";
Venetian@7 181 break;
Venetian@7 182 case 6:
Venetian@7 183 midiName = "F#";
Venetian@7 184 break;
Venetian@7 185 case 7:
Venetian@7 186 midiName = "G ";
Venetian@7 187 break;
Venetian@7 188 case 8:
Venetian@7 189 midiName = "G#";
Venetian@7 190 break;
Venetian@7 191 case 9:
Venetian@7 192 midiName = "A ";
Venetian@7 193 break;
Venetian@7 194 case 10:
Venetian@7 195 midiName = "A#";
Venetian@7 196 break;
Venetian@7 197 case 11:
Venetian@7 198 midiName = "B ";
Venetian@7 199 break;
Venetian@7 200 default:
Venetian@7 201 break;
Venetian@7 202 }
Venetian@7 203
Venetian@7 204 midiName += ofToString(midiOctave/12);
Venetian@7 205 }
Venetian@7 206 if (index < onsetList.size())
Venetian@7 207 onsetList[index].midiName = midiName;
Venetian@7 208
Venetian@7 209 }
Venetian@7 210
Venetian@7 211
Venetian@7 212 /*
Venetian@7 213 #pragma mark Quantisation
Venetian@7 214 void PreciseBassOnsetDetectorOffline::categoriseOnsets(std::vector<double> beatTimes){
Venetian@7 215 double onsetTime;
Venetian@7 216 for (int i = 0; i < onsetList.size(); i++){
Venetian@7 217
Venetian@7 218 onsetTime = onsetList[i].onsetLocation;
Venetian@7 219
Venetian@7 220 int beatIndex = 0;
Venetian@7 221 while(beatIndex < beatTimes.size() && beatTimes[beatIndex] < onsetTime){
Venetian@7 222 beatIndex++;
Venetian@7 223 }
Venetian@7 224 while(beatIndex > 0 && beatTimes[beatIndex] > onsetTime){
Venetian@7 225 beatIndex--;
Venetian@7 226 }
Venetian@7 227 //beatIndex now either side of onset, or onset before first beat
Venetian@7 228
Venetian@7 229 printf("beat %.2f, beat+1 %.2f, onset %.2f freq %.2f, ", beatAtIndex(beatTimes, beatIndex),
Venetian@7 230 beatAtIndex(beatTimes, beatIndex+1), onsetTime, onsetList[i].pitch);
Venetian@7 231
Venetian@7 232 double beatTime = beatAtIndex(beatTimes, beatIndex);//vampBeats.vampBeatAtIndex(beatIndex);
Venetian@7 233
Venetian@7 234
Venetian@7 235 double diff = onsetTime - beatTime;
Venetian@7 236 double nextBeat = beatAtIndex(beatTimes, beatIndex+1);
Venetian@7 237 double period;
Venetian@7 238 if (nextBeat){
Venetian@7 239 period = nextBeat - beatAtIndex(beatTimes, beatIndex);
Venetian@7 240 } else {
Venetian@7 241 period = beatAtIndex(beatTimes, beatIndex) - beatAtIndex(beatTimes, beatIndex-1);
Venetian@7 242 }
Venetian@7 243 if (period > 0){
Venetian@7 244 while (diff < 0){
Venetian@7 245 diff += period;
Venetian@7 246 //i.e. add the beat period to bring it in range
Venetian@7 247 }
Venetian@7 248 //now can look which point it is nearest
Venetian@7 249 double ratio = diff/period;
Venetian@7 250 ratio *= 12;
Venetian@7 251 int beattype = round(ratio);
Venetian@7 252 if (beattype == 12){
Venetian@7 253 beattype = 0;
Venetian@7 254 beatIndex++;//added need to test
Venetian@7 255 }
Venetian@7 256
Venetian@7 257 doCorrection(beattype, beatIndex);
Venetian@7 258
Venetian@7 259
Venetian@7 260
Venetian@7 261 // Onset newOnset;
Venetian@7 262 // newOnset.time = onsetTime;
Venetian@7 263 // newOnset.onsetType = beattype;
Venetian@7 264 int position = beatIndex%4;
Venetian@7 265
Venetian@7 266 // if (onsetTime > beatTime + (period/2.))
Venetian@7 267 // pos++;
Venetian@7 268 // newOnset.position = pos%4;
Venetian@7 269
Venetian@7 270 onsetList[i].beatPosition = beatIndex;
Venetian@7 271 onsetList[i].onsetType = beattype;
Venetian@7 272
Venetian@7 273 printf("Pitch %i, Position %i,%i\n", onsetList[i].roundedPitch, onsetList[i].beatPosition, beattype);
Venetian@7 274 }
Venetian@7 275
Venetian@7 276 }
Venetian@7 277 }
Venetian@7 278 */
Venetian@7 279
Venetian@7 280 #pragma mark PredictionProcess
Venetian@7 281 void PreciseBassOnsetDetectorOffline::predictionProcess(){
Venetian@7 282
Venetian@7 283
Venetian@7 284
Venetian@7 285 //NOW do do precition
Venetian@7 286 int optimalLag = getOptimalLag();
Venetian@7 287 checkPrediction(optimalLag);
Venetian@7 288
Venetian@7 289 checkPredictionFirstOrderMarkovCorrect(optimalLag);
Venetian@7 290
Venetian@7 291 //checkBars(); - not quite sure what the idea here was
Venetian@7 292
Venetian@7 293 /*
Venetian@7 294 beatInfo.clear();
Venetian@7 295
Venetian@7 296 int tmpIndex = 0;
Venetian@7 297 double nearestOnset = preciseDetector.pod.onsetAtIndex(0);//start with first
Venetian@7 298 for (int beatIndex = 0; beatIndex < beatTimes.size(); beatIndex++){
Venetian@7 299 double newBeatTime = beatTimes[beatIndex];
Venetian@7 300 printf("BEAT %i: %f, ", beatIndex, newBeatTime);
Venetian@7 301 double diff = pod.onsetAtIndex(tmpIndex) - newBeatTime;
Venetian@7 302 while (fabs(pod.onsetAtIndex(tmpIndex+1) - newBeatTime) < fabs(diff)){
Venetian@7 303 tmpIndex++;
Venetian@7 304 nearestOnset = pod.onsetAtIndex(tmpIndex);
Venetian@7 305 diff = pod.onsetAtIndex(tmpIndex) - newBeatTime;
Venetian@7 306 printf("testing %f, ", nearestOnset);
Venetian@7 307 }
Venetian@7 308
Venetian@7 309
Venetian@7 310 Beat newBeat(false);
Venetian@7 311 newBeat.onsetFound = false;
Venetian@7 312 if (fabs(nearestOnset - newBeatTime) < thresholdForBeat){
Venetian@7 313 newBeat.onsetFound = true;
Venetian@7 314 newBeat.onsetDifference = nearestOnset - newBeatTime;
Venetian@7 315 printf("nearest onset %f\n", nearestOnset);
Venetian@7 316 } else
Venetian@7 317 printf("no onset %f\n", nearestOnset);
Venetian@7 318 //within 80 msec we say the onset is attributable to the beat location
Venetian@7 319 newBeat.onsetTime = nearestOnset;
Venetian@7 320 newBeat.time = newBeatTime;
Venetian@7 321 newBeat.errorFound = false;
Venetian@7 322 newBeat.period = nan(0);
Venetian@7 323 //find error
Venetian@7 324 int secondBeat = beatIndex-4;
Venetian@7 325 if (beatIndex%4 != 0)
Venetian@7 326 secondBeat = beatIndex - (beatIndex%4);
Venetian@7 327 int firstBeat = secondBeat - 4;
Venetian@7 328
Venetian@7 329 //for the one use previous bar kicks
Venetian@7 330 //otherwise recent kicks on the one
Venetian@7 331
Venetian@7 332 if (firstBeat >= 0 && secondBeat < beatInfo.size()){
Venetian@7 333 if (beatInfo[firstBeat].onsetFound && beatInfo[secondBeat].onsetFound){
Venetian@7 334 //can project
Venetian@7 335 double beatPeriod = beatInfo[secondBeat].onsetTime - beatInfo[firstBeat].onsetTime;
Venetian@7 336 beatPeriod /= 4.;
Venetian@7 337 printf("%i beat period %f, ", beatIndex, beatPeriod);
Venetian@7 338 double error = nearestOnset - (beatInfo[secondBeat].onsetTime + (beatIndex - secondBeat)*beatPeriod);
Venetian@7 339 printf("error %.1f, beat period %.1f\n", error*1000., beatPeriod*1000.);
Venetian@7 340 newBeat.errorFound = true;
Venetian@7 341 newBeat.error = error;
Venetian@7 342 newBeat.period = beatPeriod;
Venetian@7 343 }
Venetian@7 344
Venetian@7 345 }//end if error
Venetian@7 346
Venetian@7 347 beatInfo.push_back(newBeat);
Venetian@7 348
Venetian@7 349
Venetian@7 350 }
Venetian@7 351 */
Venetian@7 352
Venetian@7 353 //dtwProcess();
Venetian@7 354 }
Venetian@7 355
Venetian@7 356 int PreciseBassOnsetDetectorOffline::getOptimalLag(){
Venetian@7 357 std::vector<double> correlationScores;
Venetian@7 358 int maxCorr = 35;
Venetian@7 359
Venetian@7 360 for (int i = 0; i < maxCorr; i++){
Venetian@7 361 correlationScores.push_back(quantisedCorrelation(i));
Venetian@7 362 printf("Lag[%i] %f\n", i, correlationScores[i]);
Venetian@7 363 }
Venetian@7 364
Venetian@7 365 int optimalLag = 8;
Venetian@7 366
Venetian@7 367 BeatWriter newWriter;
Venetian@7 368 newWriter.closeFile();
Venetian@7 369 newWriter.openFile("/Users/andrewrobertson/corr_scores.txt");
Venetian@7 370
Venetian@7 371
Venetian@7 372 //make rayligh
Venetian@7 373 std::vector<double> wv;
Venetian@7 374 float rayparam = 16;
Venetian@7 375 for (int n = 0; n < maxCorr;n++){
Venetian@7 376 wv.push_back(((float) n / pow(rayparam,2)) * exp((-1*pow((float)-n,2)) / (2*pow(rayparam,2))));
Venetian@7 377 //wv.push_back(1.0 - fabs(n - 12.0)/64.0);
Venetian@7 378
Venetian@7 379 }
Venetian@7 380
Venetian@7 381 double maxScore = 0;
Venetian@7 382 for (int i = 2; i < maxCorr; i++){
Venetian@7 383 printf("Lag[%i] %f, rayleigh %f, weighted vec %f\n", i, correlationScores[i], wv[i], correlationScores[i]*wv[i]);
Venetian@7 384 if (correlationScores[i]*wv[i] > maxScore){
Venetian@7 385 maxScore = correlationScores[i]*wv[i];
Venetian@7 386 optimalLag = i;
Venetian@7 387 }
Venetian@7 388
Venetian@7 389 newWriter.outputFile << i << "\t" << correlationScores[i] << std::endl;
Venetian@7 390 }
Venetian@7 391
Venetian@7 392 newWriter.closeFile();
Venetian@7 393
Venetian@7 394 printf("Optimal lag %i\n", optimalLag);
Venetian@7 395
Venetian@7 396 return optimalLag;
Venetian@7 397 }
Venetian@7 398
Venetian@7 399
Venetian@7 400 /*
Venetian@7 401 void PreciseBassOnsetDetectorOffline::doCorrection(int& beattype, int& beatPosition){
Venetian@7 402 switch (beattype) {
Venetian@7 403 case 1:
Venetian@7 404 beattype = 0;//on beat
Venetian@7 405 break;
Venetian@7 406 case 2:
Venetian@7 407 beattype = 3;//16th
Venetian@7 408 break;
Venetian@7 409 case 5: case 7:
Venetian@7 410 beattype = 6;//8th note
Venetian@7 411 break;
Venetian@7 412 case 10:
Venetian@7 413 beattype = 9;
Venetian@7 414 break;
Venetian@7 415 case 11:
Venetian@7 416 beattype = 0;//on the beat
Venetian@7 417 beatPosition++;
Venetian@7 418 break;
Venetian@7 419 default:
Venetian@7 420 break;
Venetian@7 421 }
Venetian@7 422
Venetian@7 423 }
Venetian@7 424 */
Venetian@7 425
Venetian@7 426
Venetian@7 427
Venetian@7 428 double PreciseBassOnsetDetectorOffline::quantisedCorrelation(int lag){
Venetian@7 429
Venetian@7 430 double meanCorrelation = 0;
Venetian@7 431 int count = 0;
Venetian@7 432
Venetian@7 433 bool printResult = false;
Venetian@7 434
Venetian@7 435 for (int index = 0; index < onsetList.size(); index++){
Venetian@7 436 int midiPitch = 0;
Venetian@7 437 if (printResult)
Venetian@7 438 printf("testing %i,%i (%i): ", onsetList[index].beatPosition, onsetList[index].onsetType, onsetList[index].roundedPitch);
Venetian@7 439
Venetian@7 440 getOnsetAtBeat(index, onsetList[index].beatPosition-lag, onsetList[index].onsetType, midiPitch);
Venetian@7 441
Venetian@7 442 if (midiPitch){
Venetian@7 443 count++;
Venetian@7 444 if (midiPitch == onsetList[index].roundedPitch){
Venetian@7 445 meanCorrelation++;
Venetian@7 446 }
Venetian@7 447 if (printResult){
Venetian@7 448 printf("MIDI pitch found %i at lag %i\n", midiPitch, lag);
Venetian@7 449 } else if (printResult){
Venetian@7 450 printf("none\n");
Venetian@7 451 }
Venetian@7 452 }
Venetian@7 453 }
Venetian@7 454
Venetian@7 455 if (count > 0)
Venetian@7 456 meanCorrelation /= count;
Venetian@7 457
Venetian@7 458 return meanCorrelation;
Venetian@7 459 }
Venetian@7 460
Venetian@7 461
Venetian@7 462 void PreciseBassOnsetDetectorOffline::checkPrediction(int lag){
Venetian@7 463
Venetian@7 464 //NAIVE METHOD - JUST LOOKING BACK FOR A BASS NOTE IN SAME POSITION AT SAME LAG
Venetian@7 465
Venetian@7 466 int matches = 0;
Venetian@7 467 int octaveErrors = 0;
Venetian@7 468 int mismatches = 0;
Venetian@7 469
Venetian@7 470 bool printResult = false;//true;
Venetian@7 471
Venetian@7 472 for (int index = 0; index < onsetList.size(); index++){
Venetian@7 473 onsetList[index].midiPrediction = 0;
Venetian@7 474
Venetian@7 475 int midiPitch = 0;
Venetian@7 476 if (printResult)
Venetian@7 477 printf("prediction %i,%i (%i): ", onsetList[index].beatPosition, onsetList[index].onsetType, onsetList[index].roundedPitch);
Venetian@7 478
Venetian@7 479 int k = 1;
Venetian@7 480 while (onsetList[index].beatPosition - k *lag >= 0){
Venetian@7 481
Venetian@7 482 int tmp = getOnsetAtBeat(index, onsetList[index].beatPosition-(k*lag), onsetList[index].onsetType, midiPitch);
Venetian@7 483
Venetian@7 484 // if (tmp == 0 && printResult)
Venetian@7 485 // printf("k %i, pos %i,%i : midi pred %i\n", k, onsetList[index].beatPosition-(k*lag), onsetList[index].onsetType, tmp);
Venetian@7 486
Venetian@7 487 if (midiPitch)//i.e. non zero prediction made looking back k*lag beats
Venetian@7 488 break;
Venetian@7 489
Venetian@7 490 k++;//keep looking back
Venetian@7 491 }
Venetian@7 492
Venetian@7 493 if (midiPitch){
Venetian@7 494 onsetList[index].midiPrediction = midiPitch;
Venetian@7 495
Venetian@7 496 if (printResult)
Venetian@7 497 printf(", pred %i, (lag %i) ", midiPitch, k);
Venetian@7 498
Venetian@7 499 if (midiPitch == onsetList[index].roundedPitch){
Venetian@7 500 onsetList[index].matchIndicator = 1;
Venetian@7 501 matches++;
Venetian@7 502 if (printResult)
Venetian@7 503 printf(", MATCH");
Venetian@7 504
Venetian@7 505 }
Venetian@7 506
Venetian@7 507 if (midiPitch && onsetList[index].roundedPitch && abs(midiPitch - onsetList[index].roundedPitch) == 12){
Venetian@7 508 octaveErrors++;
Venetian@7 509 if (printResult)
Venetian@7 510 printf(", OCTAVE %i", onsetList[index].roundedPitch-midiPitch);
Venetian@7 511 }
Venetian@7 512 else if (midiPitch && onsetList[index].roundedPitch && midiPitch != onsetList[index].roundedPitch){
Venetian@7 513 mismatches++;
Venetian@7 514 if (printResult)
Venetian@7 515 printf(", NOT");
Venetian@7 516 }
Venetian@7 517 }
Venetian@7 518
Venetian@7 519 if (printResult)
Venetian@7 520 printf("\n");
Venetian@7 521
Venetian@7 522 }
Venetian@7 523 double sum = matches+octaveErrors+mismatches;
Venetian@7 524 printf("\nResult: naive method\noptimal lag %i, matches %.3f, octaves %.3f, wrong %.3f\n", lag, matches/sum, octaveErrors/sum, mismatches/sum);
Venetian@7 525 }
Venetian@7 526
Venetian@7 527
Venetian@7 528 int PreciseBassOnsetDetectorOffline::getOnsetAtBeat(int tmpIndex, int beatPosition, int beatType, int& midiPitch){
Venetian@7 529 bool onsetFound = false;
Venetian@7 530 while (tmpIndex >= 0 && onsetList[tmpIndex].beatPosition >= beatPosition){
Venetian@7 531 if (onsetList[tmpIndex].beatPosition == beatPosition && onsetList[tmpIndex].onsetType == beatType){
Venetian@7 532 midiPitch = onsetList[tmpIndex].roundedPitch;
Venetian@7 533 //printf("beat pos %i,%i: pitch %i\n", beatPosition, beatType, midiPitch);
Venetian@7 534 onsetFound = true;
Venetian@7 535 break;
Venetian@7 536 }
Venetian@7 537 tmpIndex--;
Venetian@7 538 }
Venetian@7 539 return onsetFound;
Venetian@7 540
Venetian@7 541 }
Venetian@7 542
Venetian@7 543
Venetian@7 544
Venetian@7 545
Venetian@7 546 void PreciseBassOnsetDetectorOffline::checkPredictionFirstOrderMarkovCorrect(int lag){
Venetian@7 547
Venetian@7 548 //LOOKING BACK, NOW REQUIRE ANOTHER CORRECT BASS NOTE RECENT BEAT POSITION
Venetian@7 549 //hard to find
Venetian@7 550 printf("First Order check\n");
Venetian@7 551
Venetian@7 552
Venetian@7 553 int matches = 0;
Venetian@7 554 int octaveErrors = 0;
Venetian@7 555 int mismatches = 0;
Venetian@7 556
Venetian@7 557 bool printResult = false;//rue;
Venetian@7 558
Venetian@7 559 if (printResult)
Venetian@7 560 printPitchInfo();
Venetian@7 561
Venetian@7 562 for (int index = 0; index < onsetList.size(); index++){
Venetian@7 563 onsetList[index].midiPrediction = 0;
Venetian@7 564
Venetian@7 565 int midiPitch = 0;
Venetian@7 566 int previousMidiPitch = 0;
Venetian@7 567
Venetian@7 568 if (printResult)
Venetian@7 569 printf("\nBeat Position %i,%i:\n", onsetList[index].beatPosition, onsetList[index].onsetType);
Venetian@7 570
Venetian@7 571 int k = 1;
Venetian@7 572
Venetian@7 573 int previousOffset = 1;//the note before
Venetian@7 574 while (index - previousOffset >= 0 && (onsetList[index-previousOffset].onsetType != 0 || !onsetList[index-previousOffset].roundedPitch)){
Venetian@7 575 //printf("rejected: index %i offset %i onset type %i pitch %i\n", index, previousOffset, onsetList[index-previousOffset].onsetType, onsetList[index-previousOffset].roundedPitch);
Venetian@7 576 previousOffset++;
Venetian@7 577 }
Venetian@7 578
Venetian@7 579
Venetian@7 580 if (printResult){
Venetian@7 581 printf("\nBeat Position %i,%i (midi %i, prev %i,%i: %i):\n", onsetList[index].beatPosition, onsetList[index].onsetType, onsetList[index].roundedPitch, onsetList[index-previousOffset].beatPosition, onsetList[index-previousOffset].onsetType, onsetList[index-previousOffset].roundedPitch);
Venetian@7 582 printf("Previous position is %i,%i offset %i, previous pitch %i\n", onsetList[index-previousOffset].beatPosition, onsetList[index-previousOffset].onsetType, previousOffset, onsetList[index-previousOffset].roundedPitch);
Venetian@7 583 }
Venetian@7 584
Venetian@7 585 bool printit = false;
Venetian@7 586 //first try our new markov condition
Venetian@7 587 while (onsetList[index].beatPosition - k *lag >= 0){
Venetian@7 588
Venetian@7 589 if(getOnsetAtBeat(index, onsetList[index].beatPosition-(k*lag), onsetList[index].onsetType, midiPitch)
Venetian@7 590 && getOnsetAtBeat(index - previousOffset, onsetList[index - previousOffset].beatPosition - (k*lag), onsetList[index-previousOffset].onsetType, previousMidiPitch))
Venetian@7 591 {
Venetian@7 592 if (printit)
Venetian@7 593 printf("k %i Predicted pitch %i Lag previous pitch %i \n", k, midiPitch, previousMidiPitch);
Venetian@7 594 //midi picth is what we would do precition as, but require that the previous note also match our last observed note
Venetian@7 595
Venetian@7 596 //onset found at beat pos - k*lag
Venetian@7 597 //then is the same
Venetian@7 598
Venetian@7 599 bool goodPrediction = false;
Venetian@7 600 if (previousMidiPitch == onsetList[index-previousOffset].roundedPitch){
Venetian@7 601 goodPrediction = true;
Venetian@7 602 if (printit)
Venetian@7 603 printf("Previous Found! Lag %i Lag previous pitch %i\nPrediction %i", k, onsetList[index-previousOffset].roundedPitch, previousMidiPitch, midiPitch);
Venetian@7 604 }
Venetian@7 605
Venetian@7 606
Venetian@7 607
Venetian@7 608 if (midiPitch && goodPrediction)//i.e. non zero prediction made looking back k*lag beats
Venetian@7 609 {
Venetian@7 610 if (printit)
Venetian@7 611 printf("MIDI PREDICTION IS %i\n", midiPitch);
Venetian@7 612 break;
Venetian@7 613 }
Venetian@7 614 }
Venetian@7 615 k++;//keep looking back
Venetian@7 616 }
Venetian@7 617
Venetian@7 618
Venetian@7 619 if (!midiPitch){
Venetian@7 620 k = 1;
Venetian@7 621 while (onsetList[index].beatPosition - k *lag >= 0){
Venetian@7 622
Venetian@7 623 int tmp = getOnsetAtBeat(index, onsetList[index].beatPosition-(k*lag), onsetList[index].onsetType, midiPitch);
Venetian@7 624
Venetian@7 625 if (midiPitch)//i.e. non zero prediction made looking back k*lag beats
Venetian@7 626 break;
Venetian@7 627
Venetian@7 628 k++;//keep looking back
Venetian@7 629 }
Venetian@7 630 }
Venetian@7 631
Venetian@7 632 if (midiPitch){//only test non zero
Venetian@7 633 onsetList[index].midiPrediction = midiPitch;
Venetian@7 634
Venetian@7 635 if (printResult)
Venetian@7 636 printf(", pred %i, (lag %i) ", midiPitch, k);
Venetian@7 637
Venetian@7 638 if (midiPitch == onsetList[index].roundedPitch){
Venetian@7 639 onsetList[index].matchIndicator = 1;
Venetian@7 640 matches++;
Venetian@7 641 if (printResult)
Venetian@7 642 printf(", MATCH");
Venetian@7 643
Venetian@7 644 }
Venetian@7 645
Venetian@7 646 if (midiPitch && onsetList[index].roundedPitch && abs(midiPitch - onsetList[index].roundedPitch) == 12){
Venetian@7 647 octaveErrors++;
Venetian@7 648 if (printResult)
Venetian@7 649 printf(", OCTAVE %i", onsetList[index].roundedPitch-midiPitch);
Venetian@7 650 }
Venetian@7 651 else if (midiPitch && onsetList[index].roundedPitch && midiPitch != onsetList[index].roundedPitch){
Venetian@7 652 mismatches++;
Venetian@7 653 if (printResult)
Venetian@7 654 printf(", NOT");
Venetian@7 655 }
Venetian@7 656 }
Venetian@7 657
Venetian@7 658 if (printResult)
Venetian@7 659 printf("\n");
Venetian@7 660
Venetian@7 661 }
Venetian@7 662 double sum = matches+octaveErrors+mismatches;
Venetian@7 663 printf("Results : First Oreder Markov Correct\nOptimal lag %i, matches %.3f, octaves %.3f, wrong %.3f\n", lag, matches/sum, octaveErrors/sum, mismatches/sum);
Venetian@7 664 }
Venetian@7 665
Venetian@7 666
Venetian@7 667
Venetian@7 668 void PreciseBassOnsetDetectorOffline::checkBars(){
Venetian@7 669 int bar = 0;
Venetian@7 670 double barScore = 0;
Venetian@7 671 double barCount;
Venetian@7 672 std::vector<double> scorePerBar;
Venetian@7 673 for (int index = 0; index < onsetList.size(); index++){
Venetian@7 674 while (bar*4 < onsetList[index].beatPosition){
Venetian@7 675 if (barCount > 0)
Venetian@7 676 barScore /= barCount;
Venetian@7 677 scorePerBar.push_back(barScore);
Venetian@7 678 //now going to next bar so reinitialise
Venetian@7 679 bar++;
Venetian@7 680 barScore = 0;
Venetian@7 681 barCount = 0;
Venetian@7 682 }
Venetian@7 683 barScore += onsetList[index].matchIndicator;
Venetian@7 684 barCount++;
Venetian@7 685
Venetian@7 686 }
Venetian@7 687
Venetian@7 688 for (int i = 0; i < scorePerBar.size(); i++)
Venetian@7 689 printf("Score bar [%i] %f\n", i, scorePerBar[i]);
Venetian@7 690 }
Venetian@7 691
Venetian@7 692