Mercurial > hg > midi-score-follower
changeset 1:1a32ce016bb9
Changed bestEstimate timing to work via time sent from Max not the elapsed time. This had caused some problems, but this version now working surprisingly well on MIDI files with variable timing.
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Thu, 18 Aug 2011 23:27:42 +0100 |
parents | b299a65a3ad0 |
children | 5581023e0de4 |
files | src/BayesianArrayStructure.cpp src/DynamicVector.cpp src/DynamicVector.h src/midiEventHolder.cpp src/midiEventHolder.h src/testApp.cpp workingNotes.rtf |
diffstat | 7 files changed, 85 insertions(+), 18 deletions(-) [+] |
line wrap: on
line diff
--- a/src/BayesianArrayStructure.cpp Tue Aug 16 11:29:59 2011 +0100 +++ b/src/BayesianArrayStructure.cpp Thu Aug 18 23:27:42 2011 +0100 @@ -246,7 +246,7 @@ //set new likelihood relativeSpeedLikelihood.zero(); - relativeSpeedLikelihood.addConstant(0.02); + relativeSpeedLikelihood.addConstant(0.05); relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5*matchFactor); @@ -368,7 +368,7 @@ relativeString += " mapped to screen "+ofToString(startScreenPosition)+" , "+ofToString(endScreenPosition); ofDrawBitmapString(relativeString, 100, 180); - ofSetColor(0, 200, 0); + ofSetColor(255, 255, 0); likelihood.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); ofSetColor(0,0,200); @@ -377,6 +377,7 @@ ofSetColor(200, 0, 0); posterior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition); + // ofSetColor(0, 200, 255); // acceleration.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
--- a/src/DynamicVector.cpp Tue Aug 16 11:29:59 2011 +0100 +++ b/src/DynamicVector.cpp Thu Aug 18 23:27:42 2011 +0100 @@ -132,6 +132,15 @@ } +double DynamicVector::getValueAtMillis(const double& millis){ + + int index = round(getRealTermsAsIndex(millis)); + if (index >= 0 && index < length) + return array[index]; + else + return 0; +} + void DynamicVector::drawVector(const int& minIndex, const int& maxIndex){
--- a/src/DynamicVector.h Tue Aug 16 11:29:59 2011 +0100 +++ b/src/DynamicVector.h Thu Aug 18 23:27:42 2011 +0100 @@ -36,6 +36,7 @@ double getIndexInRealTerms(const int& index); double getRealTermsAsIndex(double value); + double getValueAtMillis(const double& millis); void printArray(); void zero();
--- a/src/midiEventHolder.cpp Tue Aug 16 11:29:59 2011 +0100 +++ b/src/midiEventHolder.cpp Thu Aug 18 23:27:42 2011 +0100 @@ -25,14 +25,14 @@ noteMinimum = 30; noteMaximum = 96; - minimumMatchSpeed = 0.5; - maximumMatchSpeed = 2.0; + minimumMatchSpeed = 0.7; + maximumMatchSpeed = 1.3; likelihoodWidth = 100; likelihoodToNoiseRatio = 50; - matchWindowWidth = 6000;//window size for matching in ms + matchWindowWidth = 4000;//window size for matching in ms - bayesStruct.resetSize(4000); + bayesStruct.resetSize(matchWindowWidth); bayesStruct.resetSpeedSize(200); bayesStruct.setRelativeSpeedScalar(0.01); bayesStruct.relativeSpeedPrior.getMaximum(); @@ -61,6 +61,18 @@ } +void midiEventHolder::clearAllEvents(){ + recordedNoteOnMatrix.clear(); + matchesFound.clear(); + noteOnMatches.clear(); + recordedEventTimes.clear(); + + //played events: + playedEventTimes.clear(); + playedNoteOnMatrix.clear(); + matchMatrix.clear(); +} + void midiEventHolder::printNotes(){ printf("RECORDED MATRIX"); for (int i = 0;i < recordedNoteOnMatrix.size();i++){ @@ -151,6 +163,7 @@ bayesStruct.lastEventTime = ofGetElapsedTimeMillis(); //do the cross update to find current posterior for location +// totalConfidence= 0; int numberOfMatchesFound = findLocalMatches(pitch); setMatchLikelihoods(numberOfMatchesFound); bayesStruct.calculatePosterior(); @@ -166,11 +179,13 @@ //here we find the matches to the new note within appropriate range - matchString += ", "+ofToString(notePitch); + matchString = ""; windowStartTime = max(0.0,(bayesStruct.bestEstimate - matchWindowWidth/2));//was playPositionInMillis int numberOfMatches = findMatch(notePitch, windowStartTime, windowStartTime + matchWindowWidth); + matchString += " pitch: "+ofToString(notePitch)+" matches "+ofToString(numberOfMatches)+" win start "+ofToString(windowStartTime); + return numberOfMatches; @@ -188,7 +203,11 @@ // printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset); //this is the vent time since start of file if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){ - bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, 0.5 * likelihoodToNoiseRatio); + // double confidenceMeasure = 0; + // if (totalConfidence > 0) + // confidenceMeasure = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence; + + bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth, 0.5 * likelihoodToNoiseRatio );//* confidenceMeasure }//end if } bayesStruct.likelihood.addConstant(0.01); @@ -211,6 +230,9 @@ while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < endTime){ if (recordedNoteOnMatrix[startIndex][1] == notePitch){ matchesFound.push_back(startIndex); + double confidence = bayesStruct.posterior.getValueAtMillis(mouseX); + // recordedEventTimes[startIndex]); + matchString += "["+ofToString(startIndex)+"] = "+ofToString(confidence, 3)+" ."; } startIndex++; } @@ -259,18 +281,20 @@ for (int k = 0;k < matchMatrix[previousIndex][0];k++){ int recordedPreviousIndex = matchMatrix[previousIndex][k+1]; - // printf("(%i)", matchMatrix[currentPlayedIndex][i+1]); - // printf("[%i] :: ", recordedPreviousIndex); + double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex]; - /// printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); + //we want the speed of the recording relative to that of the playing live double speedRatio = recordedTimeDifference / playedTimeDifference; if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){ - - // printf("update on speed ratio %f", speedRatio); + printf("(%i)", matchMatrix[currentPlayedIndex][i+1]); + printf("[%i] :: ", recordedPreviousIndex); + printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); + printf("update on speed ratio %f\n", speedRatio); + // matchString += " speed: "+ofToString(speedRatio, 3); // commented for debug bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match @@ -370,6 +394,8 @@ } + + ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20); ofDrawBitmapString(timeString, 20, 60); @@ -382,10 +408,16 @@ //need to draw arrays within correct timescope bayesStruct.drawArraysRelativeToTimeframe(timeOffsetForScreen, timeOffsetForScreen + getEventTimeMillis(ticksPerScreen)); - //bayesStruct.drawTempoArrays(); + if (drawTempoMode) + bayesStruct.drawTempoArrays(); + + ofSetColor(0, 0, 0); ofDrawBitmapString(matchString, 20, ofGetHeight() - 20); + double confidence = bayesStruct.posterior.getValueAtMillis(mouseX); + string mouseString = "mouseX "+ofToString(confidence, 3)+" ."; + ofDrawBitmapString(mouseString, 20 , ofGetHeight() - 40); } int midiEventHolder::getLocationFromTicks(double tickPosition){
--- a/src/midiEventHolder.h Tue Aug 16 11:29:59 2011 +0100 +++ b/src/midiEventHolder.h Thu Aug 18 23:27:42 2011 +0100 @@ -28,6 +28,7 @@ IntMatrix recordedNoteOnMatrix;//note, velocity, duration IntVector matchesFound; BoolVector noteOnMatches; + // int recordedNoteOnIndex; DoubleVector recordedEventTimes; @@ -35,7 +36,13 @@ DoubleVector playedEventTimes; int playedNoteIndex; IntMatrix matchMatrix; + DoubleMatrix matchConfidence; + double totalConfidence; + double mouseX; + + void clearAllEvents(); + bool drawTempoMode; double minimumMatchSpeed , maximumMatchSpeed;
--- a/src/testApp.cpp Tue Aug 16 11:29:59 2011 +0100 +++ b/src/testApp.cpp Thu Aug 18 23:27:42 2011 +0100 @@ -114,6 +114,9 @@ if (key == 'l') midiEvents.bayesStruct.decaySpeedDistribution(100); + if (key == 't') + midiEvents.drawTempoMode = !midiEvents.drawTempoMode; + if (key == 'o'){ //open audio file string *filePtr; @@ -134,7 +137,7 @@ //-------------------------------------------------------------- void testApp::mouseMoved(int x, int y ){ - + midiEvents.mouseX = midiEvents.getEventTimeMillis((x * midiEvents.ticksPerScreen)/ screenWidth); } //-------------------------------------------------------------- @@ -203,7 +206,7 @@ int testApp::cannamMainFunction(){ - midiEvents.recordedNoteOnMatrix.clear();//where we store the note ons + midiEvents.clearAllEvents(); //int main(int argc, char **argv) //{
--- a/workingNotes.rtf Tue Aug 16 11:29:59 2011 +0100 +++ b/workingNotes.rtf Thu Aug 18 23:27:42 2011 +0100 @@ -1,7 +1,7 @@ {\rtf1\ansi\ansicpg1252\cocoartf1038\cocoasubrtf350 {\fonttbl\f0\fswiss\fcharset0 Helvetica;} {\colortbl;\red255\green255\blue255;} -\paperw11900\paperh16840\margl1440\margr1440\vieww9000\viewh8400\viewkind0 +\paperw11900\paperh16840\margl1440\margr1440\vieww20940\viewh15820\viewkind0 \pard\tx566\tx1133\tx1700\tx2267\tx2834\tx3401\tx3968\tx4535\tx5102\tx5669\tx6236\tx6803\ql\qnatural\pardirnatural \f0\fs24 \cf0 BUGS:\ @@ -16,4 +16,18 @@ \ need to do relative tempo estimates\ \ -} \ No newline at end of file +\ +\ +works\ +bartok.mid counterexample:\ +problem is that the tempo needs to estimate the likelihood confidence that the match is valid\ +at the moment all are equally weighted.\ +but if we know that the match is (n, k) then prob(loc_n) the phase at note n - gives us probability that the note is correctly identified.\ +\ +\ +//new note\ +in comes note\ +\ +decay speed distribution - so we have uncertainty about tempo\ +\ +cross update - so we have new prior for position} \ No newline at end of file