Mercurial > hg > midi-score-follower
comparison src/midiEventHolder.cpp @ 9:75dcd1308658
looked at tempo process, likelihood function changed and improved. Now drawing using constrained vector function. Good working version.
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Tue, 23 Aug 2011 11:20:44 +0100 |
parents | 6f5836d432ca |
children | 2ab6f4670cf5 |
comparison
equal
deleted
inserted
replaced
8:d9a3613e7264 | 9:75dcd1308658 |
---|---|
29 maximumMatchSpeed = 2.0; | 29 maximumMatchSpeed = 2.0; |
30 | 30 |
31 likelihoodWidth = 100; | 31 likelihoodWidth = 100; |
32 likelihoodToNoiseRatio = 0.02; | 32 likelihoodToNoiseRatio = 0.02; |
33 | 33 |
34 bayesStruct.speedLikelihoodNoise = 0.02;//was 0.05 | 34 bayesStruct.speedLikelihoodNoise = 0.1;//was 0.05 |
35 bayesStruct.speedDecayWidth = 20; | 35 bayesStruct.speedDecayWidth = 20; |
36 bayesStruct.speedDecayAmount = 10; | 36 bayesStruct.speedDecayAmount = 10; |
37 | 37 |
38 speedPriorValue = 1.0; | 38 speedPriorValue = 1.0; |
39 | 39 |
51 speedWindowWidthMillis = 4000; | 51 speedWindowWidthMillis = 4000; |
52 speedPriorValue = 1.0; | 52 speedPriorValue = 1.0; |
53 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum); | 53 noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum); |
54 | 54 |
55 confidenceWeightingUsed = false; | 55 confidenceWeightingUsed = false; |
56 | |
57 drawPhaseMode = true; | |
56 | 58 |
57 printf("lookup index %f value %f\n", bayesStruct.prior.getLookupIndex(100, 30., 10.0), bayesStruct.prior.gaussianLookupTable[(int)bayesStruct.prior.getLookupIndex(100, 30., 10.0)]); | 59 printf("lookup index %f value %f\n", bayesStruct.prior.getLookupIndex(100, 30., 10.0), bayesStruct.prior.gaussianLookupTable[(int)bayesStruct.prior.getLookupIndex(100, 30., 10.0)]); |
58 } | 60 } |
59 | 61 |
60 | 62 |
142 playedEventTimes.push_back(timePlayed); | 144 playedEventTimes.push_back(timePlayed); |
143 | 145 |
144 // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; | 146 // double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; |
145 double timeDifference = timePlayed - bayesStruct.lastEventTime; | 147 double timeDifference = timePlayed - bayesStruct.lastEventTime; |
146 | 148 |
147 printf("note %i played at %f and last event %f\n", pitch, timePlayed, bayesStruct.lastEventTime); | 149 // printf("note %i played at %f and last event %f\n", pitch, timePlayed, bayesStruct.lastEventTime); |
148 //addnoise to the tempo distribution | 150 //addnoise to the tempo distribution |
149 //bayesStruct.decaySpeedDistribution(timeDifference); | 151 //bayesStruct.decaySpeedDistribution(timeDifference); |
150 if (timeDifference > 50){ | 152 if (timeDifference > 50){ |
151 bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10 / 100.); | 153 bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10 / 100.); |
152 // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.); | 154 // bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.); |
163 timeString += ", time now:"+ofToString(timeNow, 1); | 165 timeString += ", time now:"+ofToString(timeNow, 1); |
164 timeString += " TD "+ofToString(timeDifference, 1); | 166 timeString += " TD "+ofToString(timeDifference, 1); |
165 timeString += " offset "+ofToString(bayesStruct.posterior.offset , 0); | 167 timeString += " offset "+ofToString(bayesStruct.posterior.offset , 0); |
166 timeString += " map Est: "+ofToString(bayesStruct.posterior.MAPestimate, 0); | 168 timeString += " map Est: "+ofToString(bayesStruct.posterior.MAPestimate, 0); |
167 // timeString += " Previous time" + ofToString(newMAPestimateTime,0); | 169 // timeString += " Previous time" + ofToString(newMAPestimateTime,0); |
168 timeString += " speedMap "+ofToString(bayesStruct.relativeSpeedPosterior.MAPestimate, 2); | 170 timeString += " speedMap "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 2); |
169 timeString += " :: "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 2); | 171 timeString += " :: "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 2); |
170 | 172 |
171 // newMAPestimateTime += (timeDifference * bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); | 173 // newMAPestimateTime += (timeDifference * bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); |
172 // timeString += " : Predicted MAP time" + ofToString(newMAPestimateTime,0); | 174 // timeString += " : Predicted MAP time" + ofToString(newMAPestimateTime,0); |
173 | 175 |
174 //then we recalculate the window start based on MAP being central | 176 //then we recalculate the window start based on MAP being central |
177 bayesStruct.setNewDistributionOffsets(max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2))); | 179 bayesStruct.setNewDistributionOffsets(max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2))); |
178 // bayesStruct.prior.offset = max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); | 180 // bayesStruct.prior.offset = max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)); |
179 | 181 |
180 timeString += " \n : new offset " + ofToString(bayesStruct.prior.offset , 0); | 182 timeString += " \n : new offset " + ofToString(bayesStruct.prior.offset , 0); |
181 timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1); | 183 timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1); |
182 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.MAPestimate, 1); | 184 timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 1); |
183 timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 1); | 185 timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 1); |
184 | 186 |
185 | 187 |
186 //be able to draw the prior in correct location relative to the midi notes | 188 //be able to draw the prior in correct location relative to the midi notes |
187 //this calculates the cross update of all possible speeds and all possible positions | 189 //this calculates the cross update of all possible speeds and all possible positions |
188 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference); | 190 bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference); |
327 int currentPlayedIndex = playedNoteOnMatrix.size()-1; | 329 int currentPlayedIndex = playedNoteOnMatrix.size()-1; |
328 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]); | 330 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]); |
329 // printMatchesFound(); | 331 // printMatchesFound(); |
330 // printMatchMatrix(); | 332 // printMatchMatrix(); |
331 // printf("possible notes \n"); | 333 // printf("possible notes \n"); |
334 bool needToUpdate = false; | |
335 bayesStruct.setLikelihoodToConstant(); | |
332 | 336 |
333 | 337 |
334 for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){ | 338 for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){ |
335 //iterate through the recently matched events - even dodgy matches included | 339 //iterate through the recently matched events - even dodgy matches included |
336 //size, index of match0, index of match1, .... | 340 //size, index of match0, index of match1, .... |
341 | |
342 | |
337 int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1]; | 343 int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1]; |
338 | 344 |
339 int previousIndex = currentPlayedIndex-1; | 345 int previousIndex = currentPlayedIndex-1; |
346 | |
340 | 347 |
341 while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) { | 348 while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) { |
342 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex]; | 349 double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex]; |
343 | 350 |
344 for (int k = 0;k < matchMatrix[previousIndex][0];k++){ | 351 for (int k = 0;k < matchMatrix[previousIndex][0];k++){ |
359 printf("update on speed ratio %f\n", speedRatio); | 366 printf("update on speed ratio %f\n", speedRatio); |
360 */ | 367 */ |
361 // matchString += " speed: "+ofToString(speedRatio, 3); | 368 // matchString += " speed: "+ofToString(speedRatio, 3); |
362 // commented for debug | 369 // commented for debug |
363 | 370 |
364 bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match | 371 //bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match |
365 | 372 double amount = (1-bayesStruct.speedLikelihoodNoise)/10; |
373 bayesStruct.updateTempoLikelihood(speedRatio, amount); | |
374 needToUpdate = true; | |
366 } | 375 } |
367 // printf("\n"); | 376 // printf("\n"); |
368 } | 377 } |
369 | 378 |
370 previousIndex--; | 379 previousIndex--; |
371 }//end while previousindex countdown | 380 }//end while previousindex countdown |
372 }//end for loop through possible current matches | 381 }//end for loop through possible current matches |
373 | 382 |
383 if (needToUpdate) | |
384 bayesStruct.updateTempoDistribution(); | |
385 | |
374 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); | 386 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); |
375 } | 387 } |
376 | 388 |
377 | 389 |
378 void midiEventHolder::findLocalTempoPairsWeightedForConfidence(){ | 390 void midiEventHolder::findLocalTempoPairsWeightedForConfidence(){ |
391 bool needToUpdate = false; | |
379 | 392 |
380 int currentPlayedIndex = playedNoteOnMatrix.size()-1; | 393 int currentPlayedIndex = playedNoteOnMatrix.size()-1; |
381 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]); | 394 // printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]); |
382 // printMatchesFound(); | 395 // printMatchesFound(); |
383 // printMatchMatrix(); | 396 // printMatchMatrix(); |
384 // printf("possible notes \n"); | 397 // printf("possible notes \n"); |
385 | 398 |
399 bayesStruct.setLikelihoodToConstant(); | |
386 | 400 |
387 for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){ | 401 for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){ |
388 //iterate through the recently matched events - even dodgy matches included | 402 //iterate through the recently matched events - even dodgy matches included |
389 //size, index of match0, index of match1, .... | 403 //size, index of match0, index of match1, .... |
390 int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1]; | 404 int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1]; |
416 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); | 430 printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); |
417 printf("update on speed ratio %f\n", speedRatio); | 431 printf("update on speed ratio %f\n", speedRatio); |
418 | 432 |
419 // matchString += " speed: "+ofToString(speedRatio, 3); | 433 // matchString += " speed: "+ofToString(speedRatio, 3); |
420 // commented for debug | 434 // commented for debug |
421 double weighting = previousMatchConfidence * currentMatchConfidence * 0.1; | 435 double weighting = previousMatchConfidence * currentMatchConfidence ; |
422 bayesStruct.updateTempoDistribution(speedRatio, weighting);//second paramter is confidence in the match | 436 double amount = (1-bayesStruct.speedLikelihoodNoise)*weighting/10; |
423 | 437 bayesStruct.updateTempoLikelihood(speedRatio, amount);//second paramter is confidence in the match |
438 needToUpdate = true; | |
424 } | 439 } |
425 // printf("\n"); | 440 // printf("\n"); |
426 } | 441 } |
427 | 442 |
428 previousIndex--; | 443 previousIndex--; |
429 }//end while previousindex countdown | 444 }//end while previousindex countdown |
430 }//end for loop through possible current matches | 445 }//end for loop through possible current matches |
431 | 446 |
447 if (needToUpdate) | |
448 bayesStruct.updateTempoDistribution(); | |
432 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); | 449 //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); |
433 } | 450 } |
434 | 451 |
435 | 452 |
436 | 453 |
451 bayesStruct.updateBestEstimate(); | 468 bayesStruct.updateBestEstimate(); |
452 | 469 |
453 } | 470 } |
454 | 471 |
455 | 472 |
456 void midiEventHolder::drawFile(){ | 473 void midiEventHolder::drawMidiFile(){ |
474 | |
457 //draws midi file on scrolling screen | 475 //draws midi file on scrolling screen |
458 int size = recordedNoteOnMatrix.size(); | 476 int size = recordedNoteOnMatrix.size(); |
459 if (size > 0){ | 477 if (size > 0){ |
460 | 478 |
461 numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in | 479 numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in |
462 | 480 |
463 // numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down | 481 // numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down |
464 timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen); | 482 timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen); |
465 | 483 |
466 while (noteArrayIndex < recordedNoteOnMatrix.size() && tickLocation > recordedNoteOnMatrix[noteArrayIndex][0] ) | 484 while (noteArrayIndex < recordedNoteOnMatrix.size() && tickLocation > recordedNoteOnMatrix[noteArrayIndex][0] ) |
467 noteArrayIndex++; | 485 noteArrayIndex++; |
468 | 486 |
483 for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)recordedNoteOnMatrix.size());tmpIndex++){ | 501 for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)recordedNoteOnMatrix.size());tmpIndex++){ |
484 | 502 |
485 if (checkIfMatchedNote(tmpIndex)) | 503 if (checkIfMatchedNote(tmpIndex)) |
486 ofSetColor(0,0,255); | 504 ofSetColor(0,0,255); |
487 else if(noteOnMatches[tmpIndex]){ | 505 else if(noteOnMatches[tmpIndex]){ |
488 ofSetColor(255,0,255); | 506 ofSetColor(255,0,255); |
489 }else{ | 507 }else{ |
490 ofSetColor(255,255,255); | 508 ofSetColor(255,255,255); |
491 } | 509 } |
492 | 510 |
493 | 511 |
494 | 512 |
495 // XXX replace ofgetwidth below | 513 // XXX replace ofgetwidth below |
496 //if (tmpIndex >= 0 && tmpIndex < size) | 514 //if (tmpIndex >= 0 && tmpIndex < size) |
497 int xLocation = (float)(recordedNoteOnMatrix[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen; | 515 int xLocation = (float)(recordedNoteOnMatrix[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen; |
498 int duration = (float)(recordedNoteOnMatrix[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen; | 516 int duration = (float)(recordedNoteOnMatrix[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen; |
499 | 517 |
500 | 518 |
503 | 521 |
504 } | 522 } |
505 | 523 |
506 | 524 |
507 int xLocation;// = getLocationFromTicks(tickLocation); | 525 int xLocation;// = getLocationFromTicks(tickLocation); |
508 // ofLine(xLocation, 0, xLocation, (*screenHeight)); | 526 // ofLine(xLocation, 0, xLocation, (*screenHeight)); |
509 | 527 |
510 //orange line at best estimate | 528 //orange line at best estimate |
511 xLocation = getLocationFromMillis(bayesStruct.bestEstimate); | 529 xLocation = getLocationFromMillis(bayesStruct.bestEstimate); |
512 ofSetColor(250,100,0); | 530 ofSetColor(250,100,0); |
513 ofLine(xLocation, 0, xLocation, (*screenHeight)); | 531 ofLine(xLocation, 0, xLocation, (*screenHeight)); |
521 ofSetColor(0,100,255); | 539 ofSetColor(0,100,255); |
522 xLocation = getLocationFromMillis(windowStartTime); | 540 xLocation = getLocationFromMillis(windowStartTime); |
523 ofLine(xLocation, 0, xLocation, (*screenHeight)); | 541 ofLine(xLocation, 0, xLocation, (*screenHeight)); |
524 xLocation = getLocationFromMillis(windowStartTime+matchWindowWidth); | 542 xLocation = getLocationFromMillis(windowStartTime+matchWindowWidth); |
525 ofLine(xLocation, 0, xLocation, (*screenHeight)); | 543 ofLine(xLocation, 0, xLocation, (*screenHeight)); |
526 | 544 |
527 | 545 |
528 } | 546 } |
529 | 547 |
530 | |
531 | |
532 ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20); | 548 ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20); |
533 | 549 |
534 ofDrawBitmapString(timeString, 20, 60); | 550 ofDrawBitmapString(timeString, 20, 60); |
551 | |
552 | |
553 } | |
554 | |
555 void midiEventHolder::drawFile(){ | |
556 drawMidiFile(); | |
557 | |
535 | 558 |
536 // bayesStruct.drawArrays(); | 559 // bayesStruct.drawArrays(); |
537 | 560 |
538 // ofSetColor(200,200,0); | 561 // ofSetColor(200,200,0); |
539 // bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800); | 562 // bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800); |
540 | 563 |
541 //need to draw arrays within correct timescope | 564 //need to draw arrays within correct timescope |
565 if (drawPhaseMode) | |
542 bayesStruct.drawArraysRelativeToTimeframe(timeOffsetForScreen, timeOffsetForScreen + getEventTimeMillis(ticksPerScreen)); | 566 bayesStruct.drawArraysRelativeToTimeframe(timeOffsetForScreen, timeOffsetForScreen + getEventTimeMillis(ticksPerScreen)); |
543 | 567 |
544 if (drawTempoMode) | 568 if (drawTempoMode) |
545 bayesStruct.drawTempoArrays(); | 569 bayesStruct.drawTempoArrays(); |
546 | 570 |