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
Binary file .DS_Store has changed
--- 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