changeset 31:9a70d9abdc8b

examining the tempo speed process
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Sun, 11 Dec 2011 17:19:34 +0000
parents be2e779d76b5
children f91b7b019350
files hackday/BayesianArrayStructure.cpp hackday/CannamMidiFileLoader.cpp hackday/CannamMidiFileLoader.h hackday/DynamicVector.cpp hackday/DynamicVector.h hackday/midiEventHolder.cpp hackday/midiEventHolder.h hackday/testApp.cpp
diffstat 8 files changed, 98 insertions(+), 21 deletions(-) [+]
line wrap: on
line diff
--- a/hackday/BayesianArrayStructure.cpp	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/BayesianArrayStructure.cpp	Sun Dec 11 17:19:34 2011 +0000
@@ -158,7 +158,7 @@
 	
 	updateCounter = 0;
 	
-	posterior.offset = 0;
+	posterior.offset = -1000;
 	setNewDistributionOffsets(0);
 	
 	int zeroIndex = posterior.getRealTermsAsIndex(0);
@@ -379,7 +379,7 @@
 //	printf("decay %f around %i \n", timeDifference, relativeSpeedPosterior.MAPestimate);
 	relativeAmount *= speedDecayAmount;
 	relativeSpeedPosterior.renormalise();
-	relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.integratedEstimate, speedDecayWidth, relativeAmount);
+	relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, relativeAmount);
 	
 	relativeSpeedPosterior.renormalise();
 	double newMax = relativeSpeedPosterior.getMaximum();
@@ -434,7 +434,9 @@
 		
 	relativeSpeedPosterior.getMaximum();	
 	
-	relativeSpeedPosterior.updateIntegratedEstimate();
+//	relativeSpeedPosterior.updateIntegratedEstimate();
+	relativeSpeedPosterior.updateLimitedIntegratedEstimate();
+	
 	speedEstimate = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate);
 }
 
--- a/hackday/CannamMidiFileLoader.cpp	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/CannamMidiFileLoader.cpp	Sun Dec 11 17:19:34 2011 +0000
@@ -12,16 +12,19 @@
 
 CannamMidiFileLoader::CannamMidiFileLoader(){
 	chopBeginning = true;
+	firstTickTime = 0;
 }
 
 int CannamMidiFileLoader::loadFile(std::string& filename, midiEventHolder& myMidiEvents){
 		
 		noteOnIndex = 0;
+		firstTickTime = 0;
 		myMidiEvents.clearAllEvents();
 		
+		
 		setTempoFromMidiValue(500000, myMidiEvents);//default is 120bpm
 		myMidiEvents.pulsesPerQuarternote = 240;//default
-		myMidiEvents.measureVector.push_back(0);
+		//myMidiEvents.measureVector.push_back(0);
 		//int main(int argc, char **argv)
 		//{
 		//	if (argc != 2) {
@@ -101,11 +104,33 @@
 							int m1 = j->getMetaMessage()[1];
 							int m2 = j->getMetaMessage()[2];
 							long tempo = (((m0 << 8) + m1) << 8) + m2;
-								if (printMidiInfo)
+								//if (printMidiInfo)
 								cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
 							setTempoFromMidiValue(tempo, myMidiEvents);
-						
-							printf("period double is %f\n", myMidiEvents.period);
+							DoubleVector tmp;
+
+							
+							double lastTickInMillis = 0;
+							double millisTimeNow = lastTickInMillis;
+							int tickInterval = 0;
+							if (myMidiEvents.periodValues.size() > 0){
+								lastTickInMillis = myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][2];
+								tickInterval = (t - firstTickTime) - myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][0];
+								millisTimeNow = lastTickInMillis + (myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][1]*tickInterval);
+								
+							}
+							
+							if (!chopBeginning)
+								tmp.push_back(t);
+							else
+								tmp.push_back(t - firstTickTime);
+							
+							tmp.push_back(60000000.0 / double(tempo));	
+							tmp.push_back(millisTimeNow);
+							myMidiEvents.periodValues.push_back(tmp);
+							
+							printf("tick[%i]: TEMPO period %f : time now %f\n", t, 60000000.0 / double(tempo), millisTimeNow);
+							//printf("period double is %f\n", myMidiEvents.period);
 						
 						}
 							break;
@@ -119,7 +144,7 @@
 							
 							//if (printMidiInfo)
 							cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
-							printf(" ticks %i Time signature: %i by %i ", t,  numerator , denominator );
+							printf(" ticks %i Time signature: %i by %i \n", t,  numerator , denominator );
 						}
 							
 						case MIDI_KEY_SIGNATURE:
@@ -166,14 +191,18 @@
 						<< "event time " << myMidiEvents.getEventTimeMillis(t) << endl;
 				
 						
-						if (noteOnIndex == 0){
+						if (noteOnIndex == 0  || t < firstTickTime){
+							//easier just to pick the minimum
 							firstTickTime = t;
+							printf("FIRST TICK TIME %i\n", firstTickTime);
 						}
 						
 						noteOnIndex++;
 						
 						v.clear();
 						
+					//	printf("note on at %i\n", t);
+						
 						if (!chopBeginning)
 							v.push_back(t);
 						else
@@ -281,6 +310,11 @@
 
 	createEventTiming(myMidiEvents);
 	
+	printf("BEFORE DOING MEASURE UPDATE\n first tick pos is %i\n", firstTickTime);
+//	printMeasuresSoFar(myMidiEvents);
+	if (chopBeginning)
+		correctMeasuresTiming(myMidiEvents);
+	
 	if (printMidiInfo)
 	myMidiEvents.printRecordedEvents();	
 	
@@ -330,9 +364,12 @@
 	
 	int measureVectorSize = myMidiEvents.measureVector.size();
 	int lastMeasurePosition = 0;
+//	if (chopBeginning)
+//		lastMeasurePosition = -1*firstTickTime;
 	
 	if (measureVectorSize > 0)
 		lastMeasurePosition = myMidiEvents.measureVector[measureVectorSize-1];
+
 	
 while (lastMeasurePosition < ticks){
 	//update
@@ -344,6 +381,15 @@
 }
 
 
+void CannamMidiFileLoader::correctMeasuresTiming(midiEventHolder& myMidiEvents){
+	//correct measures
+	for (int i = 0;i <myMidiEvents.measureVector.size();i++){
+		myMidiEvents.measureVector[i] -= firstTickTime;
+	}
+	printf("AFTER DOING MEASURE UPDATE\n");
+	printMeasuresSoFar(myMidiEvents);
+}
+
 void CannamMidiFileLoader::printMeasuresSoFar(midiEventHolder& myMidiEvents){
 	for (int i = 0;i < myMidiEvents.measureVector.size();i++){
 		printf("measure [%i] at %i\n", i, myMidiEvents.measureVector[i]);
--- a/hackday/CannamMidiFileLoader.h	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/CannamMidiFileLoader.h	Sun Dec 11 17:19:34 2011 +0000
@@ -20,6 +20,8 @@
 public:
 	CannamMidiFileLoader();
 	
+	typedef std::vector<double> DoubleVector;
+	
 	int loadFile(std::string& filename, midiEventHolder& myMidiEvents);
 
 	void createEventTiming( midiEventHolder& myMidiEvents);
@@ -37,6 +39,7 @@
 	void updateMeasureToTickPosition(int ticks,  midiEventHolder& myMidiEvents);
 	bool printMidiInfo;
 	void printMeasuresSoFar(midiEventHolder& myMidiEvents);
+	void correctMeasuresTiming(midiEventHolder& myMidiEvents);
 	
 };
 #endif
\ No newline at end of file
--- a/hackday/DynamicVector.cpp	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/DynamicVector.cpp	Sun Dec 11 17:19:34 2011 +0000
@@ -90,6 +90,26 @@
 
 }
 
+void DynamicVector::updateLimitedIntegratedEstimate(){
+	//returns the index of the integrated average - where the probability distribution is centred
+	//but limited round the MAP estimate
+	double tmp = getMaximum();
+	int limit = min(MAPestimate, length - MAPestimate);
+	int start = max(0, MAPestimate - limit);
+	int end = min(MAPestimate + limit, length-1);
+	
+	integratedEstimate = 0;
+	double integratedTotal = 0;
+	for (int i = start;i <= end;i++){
+		integratedEstimate += array[i]*i;
+		integratedTotal += array[i];
+	}
+	if (integratedTotal > 0){
+		integratedEstimate /= integratedTotal;
+	}
+	
+}
+
 
 void DynamicVector::zero(){
 	for (int i = 0;i < array.size();i++)
--- a/hackday/DynamicVector.h	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/DynamicVector.h	Sun Dec 11 17:19:34 2011 +0000
@@ -33,6 +33,7 @@
 	double gaussianLookupMean, gaussianLookupStdDev;
 	double integratedEstimate;
 	void updateIntegratedEstimate();
+	void updateLimitedIntegratedEstimate();
 	
 	void drawVector(const int& minIndex, const int& maxIndex);
 	void drawConstrainedVector(const int& minIndex, const int& maxIndex, const int& minScreenIndex, const int& maxScreenIndex);
--- a/hackday/midiEventHolder.cpp	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/midiEventHolder.cpp	Sun Dec 11 17:19:34 2011 +0000
@@ -19,6 +19,7 @@
 	confidenceWeightingUsed = true;
 	newOptimalMethod = true;
 	
+	matchWindowWidth = 8000;//window size for matching in ms 
 	interNoteRange = 1600;//preferred duration
 	//so max here is really four
 	
@@ -27,7 +28,7 @@
 	runningInRealTime = true;
 	bayesStruct.realTimeMode = &runningInRealTime;
 	
-	minimumMatchSpeed = 0.5;
+	minimumMatchSpeed = 0.0;
 	maximumMatchSpeed = 2.0;
 	minimumTimeIntervalForTempoUpdate = 150;
 	
@@ -49,14 +50,13 @@
 	likelihoodToNoiseRatio = 0.08;//was 0.02 on 18/11/11, changing to give more weight to observations
 	
 	bayesStruct.speedLikelihoodNoise = 0.1;//was 0.05
-	bayesStruct.speedDecayWidth = 20;
+	bayesStruct.speedDecayWidth = 40;
 	bayesStruct.speedDecayAmount = 10;
 	
 
 	
 	speedPriorValue = 1.0;
 	
-	matchWindowWidth = 8000;//window size for matching in ms 
 	
 	bayesStruct.resetSize(matchWindowWidth);
 	bayesStruct.setPositionDistributionScalar(1);
@@ -67,7 +67,7 @@
 	//bayesStruct.simpleExample();
 	
 	
-	speedWindowWidthMillis =  4000;
+	speedWindowWidthMillis =  1600;//4000
 	speedPriorValue = 1.0;
 	noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum);
 	
@@ -133,6 +133,7 @@
 	playedNoteOnMatrix.clear();
 	matchMatrix.clear();
 	bestMatchFound.clear();
+	periodValues.clear();
 	
 	recordedTotalNoteCounterByPitch.clear();
 	recordedTotalNoteCounterByPitch.assign(127, 0);
@@ -192,8 +193,9 @@
 
 	//addnoise to the tempo distribution
 	//bayesStruct.decaySpeedDistribution(timeDifference);
+	
 	if (timeDifference > 50){
-	bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10 / 100.);
+	bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.);
 //	bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.);
 	}
 	
@@ -577,6 +579,7 @@
 	
 	DoubleVector speedIntervalsFound;
 	
+	double currentSpeedEstimate = bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate);
 	
 	int currentPlayedIndex = playedNoteOnMatrix.size()-1;
 
@@ -627,7 +630,7 @@
 					//we have a candidate
 						double speedToTest = recordedEventTimes[checkRecordedCurrentIndex]  - recordedEventTimes[checkRecordedPreviousIndex];
 						speedToTest /= playedTimeDifference;
-						if (abs(speedToTest-1) < abs(speedRatio - 1) ){
+						if (abs(speedToTest-currentSpeedEstimate) < abs(speedRatio - currentSpeedEstimate) ){
 							speedRatio = speedToTest;
 						}
 					}
@@ -1143,7 +1146,6 @@
 		}
 		
 	}	
-		
 	//printRecordedEvents();
 
 }
--- a/hackday/midiEventHolder.h	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/midiEventHolder.h	Sun Dec 11 17:19:34 2011 +0000
@@ -163,5 +163,7 @@
 	void drawInterNoteIntervals();
 	void printInterNoteIntervals();
 	int interNoteRange;
+	DoubleMatrix periodValues;
+	
 };
 #endif
\ No newline at end of file
--- a/hackday/testApp.cpp	Wed Dec 07 13:04:59 2011 +0000
+++ b/hackday/testApp.cpp	Sun Dec 11 17:19:34 2011 +0000
@@ -62,7 +62,7 @@
 	screenHeight = ofGetHeight();
 	midiEvents.screenWidth = &screenWidth;
 	midiEvents.screenHeight = &screenHeight;
-	midiEvents.drawTempoMode = false;
+	midiEvents.drawTempoMode = true;
 	ofSetFrameRate(30);
 	
 	midiEvents.ticksPerScreen += 4000;
@@ -99,7 +99,7 @@
 					startPlaying();
 					printf("starting to PLAY!!!");
 				}
-				
+				printf("MIDI NOTE %i \n", newMidiOnPitch);
 				midiEvents.newNoteOnEvent(newMidiOnPitch, velocity, time);
 				noteInStream.newNoteCounted(newMidiOnPitch);
 			}
@@ -206,7 +206,7 @@
 	if (midiEvents.recordedNoteOnMatrix.size() > 0){
 	int ticks = midiEvents.recordedNoteOnMatrix[midiEvents.bestMatchIndex][0];
 	int pitch = midiEvents.recordedNoteOnMatrix[midiEvents.bestMatchIndex][1];
-	printf("sending to muse score %i, %i \n", ticks, pitch);
+//	printf("sending to muse score %i, %i \n", ticks, pitch);
 	sendNoteDataByOsc(pitch, ticks);
 	}
 	/*
@@ -496,8 +496,9 @@
 }
 
 void testApp::stopPlaying(){
-	midiEvents.printNoteCounter();
-	noteInStream.printTotalCount();
+	//midiEvents.printNoteCounter();
+	//noteInStream.printTotalCount();
+	
 	noteInStream.calculateTotalScore(midiEvents);