Mercurial > hg > midi-score-follower
diff jnmr/midiEventHolder.cpp @ 50:158f5f38e9d3
outputting exact difference for annotations, comparison with match annotations is now working over all rwc files
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Thu, 29 Mar 2012 13:41:59 +0100 |
parents | 3ce6dadd8167 |
children | 13194a9dca77 |
line wrap: on
line diff
--- a/jnmr/midiEventHolder.cpp Fri Mar 23 10:53:57 2012 +0000 +++ b/jnmr/midiEventHolder.cpp Thu Mar 29 13:41:59 2012 +0100 @@ -35,7 +35,7 @@ confidenceWeightingUsed = true; newOptimalMethod = true; - matchWindowWidth = 16000;//window size for matching in ms + matchWindowWidth = 20000;//window size for matching in ms interNoteRange = 1600;//preferred duration //so max here is really four @@ -44,7 +44,7 @@ likelihoodToNoiseRatio = 0.20;//was 0.02 on 18/11/11, changing to give more weight to observations //was 0.08 on 11/12/11 but need more for tempo varn in rwc database - bayesStruct.speedLikelihoodNoise = 0.1;//was 0.05 + bayesStruct.speedLikelihoodNoise = 0.2;//changed from 0.1, was 0.05 bayesStruct.speedDecayWidth = 40; bayesStruct.speedDecayAmount = 10; @@ -131,7 +131,7 @@ interNoteIntervals.clear(); - smoothIndex = 0; + outputIndex = 0; smoothPlayPosition = 0.0; causalPlayPosition = 0; lastCausalUpdateTime = getTimeNow(0); @@ -157,6 +157,21 @@ //period = 500.0; } +void midiEventHolder::testSpeedPriorSetting(){ + if (speedPriorValue > 2){ + bayesStruct.resetSpeedSize(speedPriorValue * 200); + bayesStruct.setRelativeSpeedScalar(0.01); + bayesStruct.relativeSpeedPrior.getMaximum(); + printf("SPEED SIZE EXCEEDS MAXIMUM!!! RESETTING TO SIXE %i\n", (int)(speedPriorValue * 200)); + } + else{ + bayesStruct.resetSpeedSize(200); + bayesStruct.setRelativeSpeedScalar(0.01); + bayesStruct.relativeSpeedPrior.getMaximum(); + } + +} + void midiEventHolder::setMatchedNotesBackToFalse(){ for (int i = 0;i < noteOnMatches.size();i++) noteOnMatches[i] = false; @@ -309,14 +324,13 @@ void midiEventHolder::updateTempo(){ //having found matches we have matches for new note and matches for previous notes - if (newOptimalMethod) + if (newOptimalMethod)//now true findOptimumTempoPairsToCurrentBestMatch(); else if (!confidenceWeightingUsed) findLocalTempoPairs(); else findLocalTempoPairsWeightedForConfidence(); - //bayesStruct.addGaussianNoiseToSpeedPosterior(10); } @@ -376,6 +390,7 @@ if (recordedEventTimes.size() > 0){ //get to the right range of events to check in + //OPTIMIZE! while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < startTime) startIndex++; @@ -396,7 +411,7 @@ double eventConfidence = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[startIndex]); if (eventConfidence > minimumConfidence){ minimumConfidence = eventConfidence; - bestMatchIndex = startIndex; + bestMatchIndex = startIndex;//could change this to minimumMatchError below } d.push_back(eventConfidence); @@ -408,6 +423,7 @@ //record the error between expected and observed times tmpError = abs(recordedEventTimes[startIndex] - bayesStruct.bestEstimate); minimumMatchError = tmpError;//recordedEventTimes[startIndex] - bayesStruct.bestEstimate; + // bestMatchIndex = startIndex; } } @@ -794,15 +810,22 @@ //did just update smooth to current if it was less if (smoothPlayPosition < bayesStruct.bestEstimate){ - updateSmoothPositionTo(bayesStruct.bestEstimate); - //smoothPlayPosition = bayesStruct.bestEstimate; + // updateOutputPositionTo(bayesStruct.bestEstimate); + smoothPlayPosition = bayesStruct.bestEstimate; } + updateOutputPositionTo(causalPlayPosition); //need it outputting before the update + + updateCausalPlayPosition(getTimeNow(bayesStruct.lastBestEstimateUpdateTime)); + - updateCausalPlayPosition(getTimeNow(bayesStruct.lastBestEstimateUpdateTime)); + //can choose to output either the smooth position (i.e. forwards) + //or causal play position which aims toward our current smooth position in near future -/* + + + /* //now we try updating it to a causal path that tries to match into the future if (smoothPlayPosition < causalPlayPosition){ updateSmoothPositionTo(causalPlayPosition); @@ -822,101 +845,134 @@ } -void midiEventHolder::updateSmoothPositionTo(const double& newPosition){ +void midiEventHolder::updateOutputPositionTo(const double& newPosition){ //smooth play position was where we last outputted notes from. //checking index is there to make sense. - while (smoothIndex > 0 && recordedEventTimes[smoothIndex] > smoothPlayPosition){ - smoothIndex--; - //printf("going backewaers on smooth, "); +// double checkPosition = smoothPlayPosition; + double checkPosition = lastUpdatePosition; + + + while (outputIndex > 0 && recordedEventTimes[outputIndex] > checkPosition){ + outputIndex--; +// printf("going backewards, smooth time %f, ", recordedEventTimes[outputIndex]); } - while (smoothIndex < recordedEventTimes.size()-1 && recordedEventTimes[smoothIndex] < smoothPlayPosition){ - smoothIndex++; - //printf("outputting smooth\n "); + while (outputIndex < recordedEventTimes.size()-1 && recordedEventTimes[outputIndex] < checkPosition){ + outputIndex++; +// printf("outputting smooth forwards time %f\n ", recordedEventTimes[outputIndex], checkPosition); } +// printf("last output position %f, new position %f\n", checkPosition, newPosition); +// printf("causal pos %.0f, smooth pos %.0f, best est %.0f\n", causalPlayPosition, smoothPlayPosition, bayesStruct.bestEstimate); + + outputPosition = recordedEventTimes[outputIndex]; double playingTime = ofGetElapsedTimeMillis(); playingTime -= startPlayingTime; //now at the last one - float smoothLocation = beatPositions[smoothIndex]; - int currentNote = recordedNoteOnMatrix[smoothIndex][1]; + float smoothLocation = beatPositions[outputIndex]; + int currentNote = recordedNoteOnMatrix[outputIndex][1]; - while (smoothIndex < recordedEventTimes.size() && recordedEventTimes[smoothIndex] < newPosition){ + while (outputIndex < recordedEventTimes.size() && recordedEventTimes[outputIndex] < newPosition){ float annotationTime = 0; float annotationLocation = 0; int annotationTick = 0; int annotationNote = 0; float difference = 10000;//very big - float currentLocationDifference = 1.0; + //float currentLocationDifference = 1.0; + + double amountSinceLastUpdate = 0.0;//between 0 and 1, the exact position of this event since last update + if (newPosition > lastUpdatePosition){ + amountSinceLastUpdate = (recordedEventTimes[outputIndex] - lastUpdatePosition)/(newPosition - lastUpdatePosition); + } + float range = 1.0; - if (smoothIndex < myNotation.rwcAnnotations.size()){ + if (outputIndex < myNotation.rwcAnnotations.size()){ //add in test here to find closest matching note - annotationTime = myNotation.rwcAnnotations[smoothIndex].eventTime; - annotationNote = myNotation.rwcAnnotations[smoothIndex].midiNote; - annotationLocation = myNotation.rwcAnnotations[smoothIndex].beatLocation; + annotationTime = myNotation.rwcAnnotations[outputIndex].eventTime; + annotationNote = myNotation.rwcAnnotations[outputIndex].midiNote; + annotationLocation = myNotation.rwcAnnotations[outputIndex].beatLocation; annotationTick = round(annotationLocation*480.0); }else{ printf("No annotaion size %i\n", (int)myNotation.rwcAnnotations.size()); } + double exactPlayingTime = amountSinceLastUpdate*playingTime + ((1 - amountSinceLastUpdate)*lastUpdatePlayingTime); difference = playingTime - (annotationTime*1000.0); - - if ((*fileOutput).is_open()){ - (*fileOutput) << fixed << beatPositions[smoothIndex] <<",\t" << recordedNoteOnMatrix[smoothIndex][1] << ",\t"; + double exactDifference = exactPlayingTime - (annotationTime*1000.0); + /* + //NO LONGER NEEDED ALLO + if ((*fileOutput).is_open()){ + (*fileOutput) << fixed << beatPositions[outputIndex] <<",\t" << recordedNoteOnMatrix[outputIndex][1] << ",\t"; (*fileOutput) << playingTime ; - if ( recordedNoteOnMatrix[smoothIndex][1] == annotationNote){ + if ( recordedNoteOnMatrix[outputIndex][1] == annotationNote){ (*fileOutput) << " corresponds to " << annotationTime; } (*fileOutput) << " \n"; } - - printf("annotations: rec tick time %i vs %i midi %i beat pos %f playing time now at %f :: annotaion %i loc % f time %f diff \t%f ms\n", - recordedNoteOnMatrix[smoothIndex][0], annotationTick, recordedNoteOnMatrix[smoothIndex][1], - beatPositions[smoothIndex], playingTime, - annotationNote, annotationLocation, annotationTime, difference); + */ -// assert(annotationNote == recordedNoteOnMatrix[smoothIndex][1]); - assert(annotationTick == recordedNoteOnMatrix[smoothIndex][0]); + //useful printing stuff +// printf("playing time %.1f, annotation time %.1f, diff %.1f\n", playingTime, (annotationTime*1000.0), difference); + +// printf("last posn %.1f, amount since %.2f \n" lastUpdatePosition, amountSinceLastUpdate); + +// printf("annotations:Diff %f rec tick time %i vs %i midi %i beat pos %f playing time now at %f :: annotaion %i loc % f time %f diff \t%f ms\n", +// difference, recordedNoteOnMatrix[outputIndex][0], annotationTick, recordedNoteOnMatrix[outputIndex][1], +// beatPositions[outputIndex], playingTime, +// annotationNote, annotationLocation, annotationTime, difference); + + // we use exact difference as it more accurately predicts where we scheduled the note +// printf("diff %.1f, exact diff %.1f\n", difference, exactDifference); + + + //assert(annotationNote == recordedNoteOnMatrix[outputIndex][1]); + assert(annotationTick == recordedNoteOnMatrix[outputIndex][0]); smoothDifference = difference; if ((*differenceOutput).is_open()){ - (*differenceOutput) << beatPositions[smoothIndex] << "," << difference << "," << playingTime << "," << (annotationTime*1000.0) << "\n"; + (*differenceOutput) << beatPositions[outputIndex] << "," << exactDifference << "," << playingTime << "," << (annotationTime*1000.0) << annotationNote << difference << "\n"; // printf("midi %i beat pos %f playing time now at %f :: annotaion %i loc % f time %f diff \t%f ms\n", - // recordedNoteOnMatrix[smoothIndex][1], - // beatPositions[smoothIndex], playingTime, + // recordedNoteOnMatrix[outputIndex][1], + // beatPositions[outputIndex], playingTime, // annotationNote, annotationLocation, annotationTime, difference); }else{ printf("file not open\n"); } - smoothIndex++; + outputIndex++; } - - smoothPlayPosition = newPosition; - + lastUpdatePosition = newPosition; + lastUpdatePlayingTime = playingTime; } void midiEventHolder::updateCausalPlayPosition(const double& timeNow){ //projected position + //first update the speed + updateCausalSpeed(); + + causalPlayPosition += causalSpeed * (timeNow - lastCausalUpdateTime); + lastCausalUpdateTime = timeNow; + +} + +void midiEventHolder::updateCausalSpeed(){ double difference = bayesStruct.bestEstimate - causalPlayPosition; causalSpeed = bayesStruct.speedEstimate; causalSpeed += (difference/timeProjectionToMeet); if (causalSpeed < 0) causalSpeed = 0; - - causalPlayPosition += causalSpeed * (timeNow - lastCausalUpdateTime); - lastCausalUpdateTime = timeNow; - + } + /* void midiEventHolder::updatePeriodValue(const double& millis){ @@ -981,7 +1037,7 @@ if (checkIfMatchedNote(tmpIndex)) ofSetColor(100,100,100);//0,0,255); else if(noteOnMatches[tmpIndex]){ - ofSetColor(255,0,255);//dark grey + ofSetColor(255,0,255);//pink } else{ ofSetColor(255,255,255);//255,255,255); @@ -1011,10 +1067,14 @@ ofSetColor(250,250,20);//250,100,0); ofLine(xLocation, 0, xLocation, (*screenHeight)); + +/* + //cyan blue - smooth position xLocation = getLocationFromMillis(smoothPlayPosition);//bayesStruct.tmpBestEstimate - ofSetColor(0,250,0);//250,150, 250,100,0); - // ofLine(xLocation, 0, xLocation, (*screenHeight)); - + ofSetColor(0,250,250);//250,150, 250,100,0); + ofLine(xLocation, 0, xLocation, (*screenHeight)); +*/ + //bright green is the causal play position xLocation = getLocationFromMillis(causalPlayPosition);//bayesStruct.tmpBestEstimate ofSetColor(0,250,0);//250,150, 250,100,0); ofLine(xLocation, 0, xLocation, (*screenHeight)); @@ -1049,9 +1109,16 @@ //ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20); ofSetColor(255,255,255); ofDrawBitmapString(timeString, 20, 60); - ofDrawBitmapString("diff "+ofToString(smoothDifference), 20, 140); + string diffString = "diff "+ofToString(smoothDifference); + diffString += "\ncausal posn: "+ofToString(causalPlayPosition, 0); + diffString += "\nsmooth posn: "+ofToString(smoothPlayPosition, 0); + diffString += "\noutput posn: "+ofToString(outputPosition, 0); + diffString += "\nbest est: "+ofToString(bayesStruct.bestEstimate, 0); + diffString += "\nlast best est: "+ofToString(bayesStruct.lastBestEstimateUpdateTime, 0); -//last played piutch + ofDrawBitmapString(diffString, 20, 140); + + //last played pitch ofSetColor(0,200,0,50); int yLocation = (*screenHeight) - ((lastPlayedPitch - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum)); ofRect(0,yLocation, 100, noteHeight); @@ -1448,7 +1515,7 @@ /* JUNK SMOOTH StuffHex /* - int testIndex = smoothIndex; + int testIndex = outputIndex; while (testIndex >= 0 && abs(smoothLocation - myNotation.rwcAnnotations[testIndex].beatLocation) < range){ if (myNotation.rwcAnnotations[testIndex].midiNote == currentNote){ @@ -1463,7 +1530,7 @@ testIndex--; } - testIndex = smoothIndex; + testIndex = outputIndex; while (testIndex >= 0 && testIndex < myNotation.rwcAnnotations.size() && abs(smoothLocation - myNotation.rwcAnnotations[testIndex].beatLocation) < range){ if (myNotation.rwcAnnotations[testIndex].midiNote == currentNote){