Mercurial > hg > midi-score-follower
changeset 29:69083ce48b83
alternative tempo strategy when matching.
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Mon, 05 Dec 2011 21:47:19 +0000 |
parents | 49a5b023df1e |
children | be2e779d76b5 |
files | .DS_Store hackday/BayesianArrayStructure.cpp hackday/midiEventHolder.cpp hackday/midiEventHolder.h hackday/musescore info.txt hackday/testApp.cpp |
diffstat | 6 files changed, 160 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/hackday/BayesianArrayStructure.cpp Mon Dec 05 07:00:47 2011 +0000 +++ b/hackday/BayesianArrayStructure.cpp Mon Dec 05 21:47:19 2011 +0000 @@ -14,7 +14,7 @@ BayesianArrayStructure::BayesianArrayStructure(){ printf("Bayesian structure: DeFault constructor called"); - usingIntegratedTempoEstimate = true;//false: use max index + usingIntegratedTempoEstimate = false;// use max index relativeSpeedLikelihoodStdDev = 5.0;
--- a/hackday/midiEventHolder.cpp Mon Dec 05 07:00:47 2011 +0000 +++ b/hackday/midiEventHolder.cpp Mon Dec 05 21:47:19 2011 +0000 @@ -7,6 +7,9 @@ * */ + +//Main file to look at here is newNoteEvent() - this calls everything else to update the Bayesian array + #include "midiEventHolder.h" midiEventHolder::midiEventHolder(){ @@ -60,7 +63,7 @@ //bayesStruct.simpleExample(); - speedWindowWidthMillis = 4000; + speedWindowWidthMillis = matchWindowWidth;// 4000; speedPriorValue = 1.0; noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum); @@ -234,14 +237,23 @@ setMatchLikelihoods(numberOfMatchesFound); bayesStruct.calculatePosterior(); + updateTempo(); + + + +} + +void midiEventHolder::updateTempo(){ //having found matches we have matches for new note and matches for previous notes +/* if (!confidenceWeightingUsed) - findLocalTempoPairs(); + findLocalTempoPairs(); else - findLocalTempoPairsWeightedForConfidence(); + findLocalTempoPairsWeightedForConfidence(); +*/ + findOptimumTempoPairsToCurrentBestMatch(); //bayesStruct.addGaussianNoiseToSpeedPosterior(10); - } double midiEventHolder::getTimeNow(double eventTime){ @@ -533,6 +545,134 @@ //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); } +double midiEventHolder::getBestSpeedEstimate(const int& currentPlayedIndex, const int& equivalentRecordedIndex){ + double estimate = 1.0; + if (bestMatchIndex > 0){ + double accordingToFileLengthEstimate = recordedEventTimes[equivalentRecordedIndex] - recordedEventTimes[0]; + double playedEquivalent = (playedEventTimes[currentPlayedIndex] - playedEventTimes[0]); + if (accordingToFileLengthEstimate > 0 && playedEquivalent > 0) + accordingToFileLengthEstimate /= playedEquivalent; + estimate = accordingToFileLengthEstimate; + } + return estimate; +} + +void midiEventHolder::findOptimumTempoPairsToCurrentBestMatch(){ + bool needToUpdate = false; + + DoubleVector speedIntervalsFound; + + + int currentPlayedIndex = playedNoteOnMatrix.size()-1; + + bayesStruct.setLikelihoodToConstant(); + + int recordedCurrentIndex = bestMatchFound[currentPlayedIndex]; + //we only look at intervals between the current best match and other recent best matched notes + + //printf("BEST MATCH FOUND for index %i is %i ", currentPlayedIndex, bestMatchFound[currentPlayedIndex]); + + int previousIndex = currentPlayedIndex-1; + + //withing speedwindow i.e. 4 seconds + while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) { + + double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex]; + + int recordedPreviousIndex = bestMatchFound[previousIndex]; + + double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex]; + + //we want the speed of the recording relative to that of the playing live + double speedRatio = recordedTimeDifference / playedTimeDifference; + + //now check if this can be closer the observed value + int checkRecordedCurrentIndex = recordedCurrentIndex; + int checkRecordedPreviousIndex ;//= recordedCurrentIndex; + int currentPlayedPitch = playedNoteOnMatrix[currentPlayedIndex][1]; + int previousPlayedPitch = playedNoteOnMatrix[previousIndex][1]; + + double recordedTimeOfBestMatch = recordedEventTimes[recordedCurrentIndex]; + + //change this so we start first in window and go to end + + while (checkRecordedCurrentIndex >= 0 && recordedEventTimes[checkRecordedCurrentIndex] > recordedTimeOfBestMatch - speedWindowWidthMillis ){ + + checkRecordedCurrentIndex--; + } + + double bestSpeedEstimate = getBestSpeedEstimate(currentPlayedIndex, bestMatchIndex); + + while (checkRecordedCurrentIndex < recordedEventTimes.size() && recordedEventTimes[checkRecordedCurrentIndex] < recordedTimeOfBestMatch + speedWindowWidthMillis ){ + if (recordedNoteOnMatrix[checkRecordedCurrentIndex][1] == currentPlayedPitch ){ + checkRecordedPreviousIndex = checkRecordedCurrentIndex; + double recordedTimeCurrent = recordedEventTimes[checkRecordedCurrentIndex] ; + while (checkRecordedPreviousIndex >= 0 && recordedEventTimes[checkRecordedPreviousIndex] + maximumMatchSpeed*playedTimeDifference > recordedTimeCurrent ) { + if (recordedNoteOnMatrix[checkRecordedPreviousIndex][1] == previousPlayedPitch){ + //we have a candidate + double speedToTest = recordedEventTimes[checkRecordedCurrentIndex] - recordedEventTimes[checkRecordedPreviousIndex]; + speedToTest /= playedTimeDifference; + if (abs(speedToTest-1) < abs(speedRatio - 1) ){ + speedRatio = speedToTest; + } + } + checkRecordedPreviousIndex--; + } + } + checkRecordedCurrentIndex++; + } + + + if (recordedTimeDifference > minimumTimeIntervalForTempoUpdate + && speedRatio < maximumMatchSpeed && speedRatio > minimumMatchSpeed){ + + /* printf("(%i)", previousIndex); + printf("[%i] :: ", recordedPreviousIndex); + // printf(" conf %f & %f ", currentMatchConfidence, previousMatchConfidence); + printf(" rec{%f} vs play(%f) ", recordedTimeDifference, playedTimeDifference); + printf("update on speed ratio %f\n", speedRatio); + */ + // matchString += " speed: "+ofToString(speedRatio, 3); + // commented for debug + + + double priorWeighting = 1; + + if (useTempoPrior) + priorWeighting = sin(speedRatio * PI/2);//adding in a prior that prefers 1.0 speed + + + // double weighting = previousMatchConfidence * currentMatchConfidence ; + double amount = (1-bayesStruct.speedLikelihoodNoise)*priorWeighting/16;//was 9 + + speedIntervalsFound.push_back(speedRatio); + // bayesStruct.updateTempoLikelihood(speedRatio, amount);//second paramter is confidence in the match + + // tempoSpeedString += ofToString(recordedCurrentIndex) + " :: " + ofToString(recordedPreviousIndex); + // tempoSpeedString += " " + ofToString(recordedTimeDifference)+ " " + ofToString(speedRatio, 2) + " "+ofToString(amount, 2) += " \n"; + + needToUpdate = true; + } + // printf("\n"); + + + previousIndex--; + }//end while previousindex countdown + + if (speedIntervalsFound.size() > 0){ + double amount = (1 - bayesStruct.speedLikelihoodNoise) / speedIntervalsFound.size(); + for (int i = 0;i < speedIntervalsFound.size();i++) + bayesStruct.updateTempoLikelihood(speedIntervalsFound[i], amount); + } + + + if (needToUpdate) + bayesStruct.updateTempoDistribution(); + //printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate)); +} + + + /* void midiEventHolder::findLocalTempoPairsWeightedForConfidence(){ bool needToUpdate = false;
--- a/hackday/midiEventHolder.h Mon Dec 05 07:00:47 2011 +0000 +++ b/hackday/midiEventHolder.h Mon Dec 05 21:47:19 2011 +0000 @@ -77,9 +77,11 @@ bool checkIfMatchedNote(const int& tmpIndex); int findMatch(const int& notePitch, const int& startTime, const int& endTime); - + void updateTempo(); void findLocalTempoPairs(); void findLocalTempoPairsWeightedForConfidence(); + void findOptimumTempoPairsToCurrentBestMatch(); + double getBestSpeedEstimate(const int& currentPlayedIndex, const int& equivalentRecordedIndex); double likelihoodWidth; double likelihoodToNoiseRatio; @@ -150,5 +152,8 @@ int minimumTimeIntervalForTempoUpdate; double ticksFactor; + + + }; #endif \ No newline at end of file
--- a/hackday/musescore info.txt Mon Dec 05 07:00:47 2011 +0000 +++ b/hackday/musescore info.txt Mon Dec 05 21:47:19 2011 +0000 @@ -8,3 +8,11 @@ restart mus sc + + +switch receive osc (prefs) on in musescore + +plugin tick box + +restart musescore +
--- a/hackday/testApp.cpp Mon Dec 05 07:00:47 2011 +0000 +++ b/hackday/testApp.cpp Mon Dec 05 21:47:19 2011 +0000 @@ -30,7 +30,7 @@ midiPortName = ""; //midiPortName = midiIn.portNames(midiPort); - transpose = 12; + transpose = 0; noteInStream.transposeVal = &transpose; noteInStream.startTime = &midiEvents.startTime;//point start time of note in stream to the same time in MIDI events