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