changeset 2:5581023e0de4

Added separate CannamMidiFileLoader class to handle the loading in.
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 19 Aug 2011 01:26:40 +0100
parents 1a32ce016bb9
children de86d77f2612
files src/BayesianArrayStructure.cpp src/BayesianArrayStructure.h src/CannamMidiFileLoader.cpp src/CannamMidiFileLoader.h src/DynamicVector.cpp src/DynamicVector.h src/midiEventHolder.cpp src/midiEventHolder.h src/testApp.cpp src/testApp.h
diffstat 10 files changed, 548 insertions(+), 85 deletions(-) [+]
line wrap: on
line diff
--- a/src/BayesianArrayStructure.cpp	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/BayesianArrayStructure.cpp	Fri Aug 19 01:26:40 2011 +0100
@@ -16,16 +16,16 @@
 	likelihood.createVector(1);
 	posterior.createVector(1);
 
-	
-	tmpPrior.createVector(240);
-	tmpPrior.addGaussianShape(100, 40, 1);
-	tmpPrior.addGaussianShape(200, 10, 0.2);
-	tmpPrior.translateDistribution(20);
-	
+
 	lastEventTime = ofGetElapsedTimeMillis();
 	
-	speedDecayWidth = 20;
-	speedDecayAmount = 10;
+	/*
+	 tmpPrior.createVector(240);
+	 tmpPrior.addGaussianShape(100, 40, 1);
+	 tmpPrior.addGaussianShape(200, 10, 0.2);
+	 tmpPrior.translateDistribution(20);
+	 */
+	tmpBestEstimate = 0;
 }
 
 BayesianArrayStructure::BayesianArrayStructure(int length){
@@ -34,6 +34,8 @@
 	prior.createVector(length);
 	likelihood.createVector(length);
 	posterior.createVector(length);
+	
+	lastEventTime = 0;
 
 }
 
@@ -46,6 +48,7 @@
 	likelihood.createVector(length);
 	posterior.createVector(length);
 	
+	
 	acceleration.createVector(length);
 	
 }
@@ -57,13 +60,24 @@
 	relativeSpeedPosterior.zero();
 	relativeSpeedLikelihood.zero();
 	
-	relativeSpeedPosterior.addGaussianShape(40, 5, 0.6);
+	//relativeSpeedPosterior.addGaussianShape(40, 5, 0.6);
 	
-	relativeSpeedPosterior.addGaussianShape(100, 5, 0.8);
+	relativeSpeedPosterior.addGaussianShape(100, 20, 0.8);
+//	relativeSpeedPosterior.addGaussianShape(50, 1, 0.8);
+	
+//	relativeSpeedPosterior.addToIndex(100, 1);
+	//relativeSpeedPosterior.addToIndex(50, 1);
 	relativeSpeedPosterior.renormalise();
 	relativeSpeedPosterior.getMaximum();
 	
-	acceleration.addGaussianShape(2000, 20, 0.8);
+	prior.zero();
+	posterior.zero();
+//	posterior.offset = - 200;
+//	posterior.addGaussianShape(200, 40, 1);
+	posterior.addToIndex(0, 1);
+	posterior.renormalise();
+	
+	//acceleration.addGaussianShape(2000, 20, 0.8);
 	
 }
 
@@ -73,32 +87,44 @@
 	relativeSpeedPrior.createVector(length);
 	relativeSpeedLikelihood.createVector(length);
 	relativeSpeedPosterior.createVector(length);
-	
+	tmpPosteriorForStorage.createVector(length);
 	
 
 }
+
 void BayesianArrayStructure::setRelativeSpeedScalar(double f){
 	relativeSpeedPrior.scalar = f;
 	relativeSpeedPosterior.scalar = f;
 	relativeSpeedLikelihood.scalar = f;
 }
 
+
+void BayesianArrayStructure::setPositionDistributionScalar(double f){
+	if (f > 0){
+	prior.scalar = f;
+	posterior.scalar = f;
+	likelihood.scalar = f;
+	}
+}
+
 void BayesianArrayStructure::simpleExample(){
 	//simple example
-	prior.addGaussianShape(50, 10, 1);
-	prior.addGaussianShape(150, 30, 0.3);
-	prior.addGaussianShape(250, 30, 0.2);
 	
-	likelihood.addGaussianShape(90, 20, 0.6);
-	likelihood.addConstant(0.02);
-	posterior.doProduct(prior, likelihood);
+//	 prior.addGaussianShape(50, 10, 1);
+//	prior.addGaussianShape(150, 30, 0.3);
+//	prior.addGaussianShape(250, 30, 0.2);
+	
+//	likelihood.addGaussianShape(90, 20, 0.6);
+//	likelihood.addConstant(0.02);
+//	posterior.doProduct(prior, likelihood);
 	
 //	relativeSpeedPosterior.addToIndex(100, 1);
 //	relativeSpeedPosterior.addToIndex(40, 0.7);	
-	relativeSpeedPosterior.addGaussianShape(100, 20, 1);
-//	relativeSpeedPosterior.addGaussianShape(10, 2, 0.5);
+	
+//	relativeSpeedPosterior.addGaussianShape(100, 2, 1);
+//	relativeSpeedPosterior.addGaussianShape(40, 2, 0.5);
 	relativeSpeedPosterior.getMaximum();
-	
+	relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
 }
 
 void BayesianArrayStructure::copyPriorToPosterior(){
@@ -108,39 +134,82 @@
 	}
 }
 
+void BayesianArrayStructure::setStartPlaying(){
+	lastEventTime = 0;//ofGetElapsedTimeMillis();
+	bestEstimate = 0;
+	lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+	
+	resetArrays();
+}
+
 void BayesianArrayStructure::resetArrays(){
+	//called when we start playing
+	
 	prior.zero();
 	likelihood.zero();
-	prior.addGaussianShape(0, 80, 1);
+	posterior.zero();
+	
+	updateCounter = 0;
+	
+	posterior.offset = 0;
+	setNewDistributionOffsets(0);
+	
+	int zeroIndex = posterior.getRealTermsAsIndex(0);
+	
+	posterior.addGaussianShape(zeroIndex, 500, 1);
+	//	posterior.addToIndex(0, 1);
 	likelihood.addConstant(1);
-	posterior.zero();
-	posterior.addGaussianShape(0, 60, 1);
-	setNewDistributionOffsets(0);
+	
+	updateCounter = 0;
+	
 	bestEstimate = 0;
 //	lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
 	
 }
 
+void BayesianArrayStructure::zeroArrays(){
+	prior.zero();
+	likelihood.zero();
+	posterior.zero();
+	
+	relativeSpeedPrior.zero();
+	relativeSpeedPosterior.zero();
+	relativeSpeedLikelihood.zero();
+
+}
+
+
+void BayesianArrayStructure::updateTmpBestEstimate(const double& timeDifference){
+	//input is the time since the start of playing
+	
+//	double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;//lastBestEstimateUpdateTime;
+	
+	tmpBestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDifference*relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate);
+	// 
+	printf("tmp best %f and best %f time diff %f posterior MAP %f\n", tmpBestEstimate, bestEstimate, timeDifference, posterior.getIndexInRealTerms(posterior.MAPestimate));
+	//lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+}
+	
 void BayesianArrayStructure::updateBestEstimate(){
-	double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;//lastBestEstimateUpdateTime;
+//	double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;//
+	double timeDiff = ofGetElapsedTimeMillis() - lastBestEstimateUpdateTime;
+	bestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate);
 	
-	bestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate);
-	// 
-	//lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+//	bestEstimate = tmpBestEstimate;
 }
 
 void BayesianArrayStructure::calculatePosterior(){
-	posterior.doProduct(prior, likelihood);
+	//posterior.doProduct(prior, likelihood);
+	
+	int i;
+	for (i = 0;i < posterior.length;i++){
+		posterior.array[i] = likelihood.array[i] * prior.array[i];
+	}
+	
+	
 	posterior.renormalise();
 	
-	/*
-	int i;
-	for (i = 0;i < prior.length;i++){
-	//	printf("priori [%i] is %f\n", i, prior[i]);
-		*(posterior+i) = *(prior+i);
-	//	posterior[i] = likelihood[i] * prior[i];
-	}
-	 */
+
 
 	 
 }
@@ -151,7 +220,7 @@
 void BayesianArrayStructure::setNewDistributionOffsets(const double& newOffset){
 	prior.offset = newOffset;
 	likelihood.offset = newOffset;
-//	posterior.offset = newOffset;
+	//posterior.offset = newOffset;
 }
 
 
@@ -175,10 +244,10 @@
 		
 		if (speed.array[i] != 0){
 			
-		//	printf("speed [%i] gives %f moved %i\n", i, speedValue, distanceMoved);
+		//	printf("speed [%i] gives %f moved %i in %f units \n", i, speedValue, distanceMoved, timeDifferenceInPositionVectorUnits);
 			
 		for (int postIndex = 0;postIndex < position.arraySize;postIndex++){
-		//old posterior contributing to new prior
+			//old posterior contributing to new prior
 			int newPriorIndex = postIndex + position.offset - prior.offset + distanceMoved;
 			if (newPriorIndex >= 0 && newPriorIndex < prior.arraySize){
 				prior.addToIndex(newPriorIndex, position.array[postIndex]*speed.array[i]);
@@ -189,11 +258,38 @@
 			
 		}//if not zero
 	}//end speed
-
+	updateCounter++;
 	prior.renormalise();
 
 }
 
+
+void BayesianArrayStructure::addGaussianNoiseToSpeedPosterior(const double& std_dev){
+	tmpPosteriorForStorage.copyFromDynamicVector(relativeSpeedPosterior);
+	
+	for (int i = 0;i < relativeSpeedPosterior.length;i++){
+		tmpPosteriorForStorage.addGaussianShape(i, std_dev, relativeSpeedPosterior.array[i]);
+		}
+												
+	tmpPosteriorForStorage.renormalise();
+	
+	relativeSpeedPosterior.copyFromDynamicVector(tmpPosteriorForStorage);											
+}
+
+
+void BayesianArrayStructure::addTriangularNoiseToSpeedPosterior(const double& std_dev){
+	tmpPosteriorForStorage.copyFromDynamicVector(relativeSpeedPosterior);
+	
+	for (int i = 0;i < relativeSpeedPosterior.length;i++){
+		//adding a linear amount depending on distance
+		tmpPosteriorForStorage.addTriangularShape(i, std_dev*2.0, relativeSpeedPosterior.array[i]);
+	}
+	
+	tmpPosteriorForStorage.renormalise();
+	
+	relativeSpeedPosterior.copyFromDynamicVector(tmpPosteriorForStorage);											
+}
+
 void BayesianArrayStructure::calculateNewPriorOffset(const double& timeDifference){
 	
 	double maxSpeed = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.MAPestimate);
@@ -246,7 +342,7 @@
 		
 		//set new likelihood
 		relativeSpeedLikelihood.zero();
-		relativeSpeedLikelihood.addConstant(0.05);
+		relativeSpeedLikelihood.addConstant(speedLikelihoodNoise);
 		
 	relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5*matchFactor);
 	
@@ -303,14 +399,13 @@
 	//bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200);
 	
 	int displaySize = prior.arraySize;
-	ofSetColor(255,0,0);
+	ofSetColor(0,0,255);
 	prior.drawVector(0, displaySize);
 	ofSetColor(0,255,0);
 	likelihood.drawVector(0, displaySize);
-	ofSetColor(0,0,255);
+	ofSetColor(255,0,255);
 	posterior.drawVector(0, displaySize);
-	ofSetColor(255,255,0);
-	relativeSpeedPosterior.drawVector(0, relativeSpeedPosterior.arraySize);
+	
 	
 //	ofSetColor(255,255,255);
 //	tmpPrior.drawVector(0,300);
@@ -328,6 +423,9 @@
 	ofSetColor(255,255,0);
 	relativeSpeedPosterior.drawVector(0, relativeSpeedPosterior.arraySize);
 	
+	ofSetColor(0,0,255);
+	tmpPosteriorForStorage.drawVector(0, tmpPosteriorForStorage.arraySize);
+	
 	ofSetColor(255,255, 255);
 	ofLine(screenWidth/2, 0, screenWidth/2, ofGetHeight());//middle of screen
 	
--- a/src/BayesianArrayStructure.h	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/BayesianArrayStructure.h	Fri Aug 19 01:26:40 2011 +0100
@@ -6,6 +6,9 @@
  *  Copyright 2011 QMUL. All rights reserved.
  *
  */
+#ifndef BAYESIAN_ARRAY_STRUCTURE
+#define BAYESIAN_ARRAY_STRUCTURE
+
 
 #include "ofMain.h"
 //#include "DynamicBayesianArray.h"
@@ -27,6 +30,8 @@
 	void resetSize(int length);
 	void resetArrays();
 	void simpleExample();
+	void setStartPlaying();
+	void zeroArrays();
 	
 	double screenWidth;
 	
@@ -34,9 +39,11 @@
 //	DynamicBayesianArray bayesArray;
 	
 	double lastEventTime;
+	double likelihoodNoise;
+	double speedLikelihoodNoise;
 	
 	DynamicVector tmpPrior;
-	
+	DynamicVector tmpPosteriorForStorage;
 	DynamicVector prior;
 	DynamicVector posterior;
 	DynamicVector likelihood;
@@ -46,11 +53,20 @@
 	DynamicVector relativeSpeedPosterior;
 	DynamicVector acceleration;
 	
+	double tmpBestEstimate;
+	void updateTmpBestEstimate(const double& timeDifference);
+	
+	int updateCounter;
+	
+	void setPositionDistributionScalar(double f);
+	
 	void resetSpeedToOne();
+	void addGaussianNoiseToSpeedPosterior(const double& std_dev);
+	void addTriangularNoiseToSpeedPosterior(const double& std_dev);
 	
 	double bestEstimate;
 	void updateBestEstimate();
-//	double lastBestEstimateUpdateTime;
+	double lastBestEstimateUpdateTime;
 	
 	double speedDecayWidth, speedDecayAmount;
 	void decaySpeedDistribution(double timeDifference);
@@ -69,4 +85,4 @@
 	void crossUpdateArrays(DynamicVector& position, DynamicVector& speed, double timeDifference);
 	
 };
-
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CannamMidiFileLoader.cpp	Fri Aug 19 01:26:40 2011 +0100
@@ -0,0 +1,236 @@
+/*
+ *  CannamMidiFileLoader.cpp
+ *  midi-score-follower
+ *
+ *  Created by Andrew on 19/08/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+#include "MIDIFileReader.h"
+#include "CannamMidiFileLoader.h"
+
+int CannamMidiFileLoader::loadFile(std::string& filename, midiEventHolder& myMidiEvents){
+		
+		
+		myMidiEvents.clearAllEvents();
+		
+		//int main(int argc, char **argv)
+		//{
+		//	if (argc != 2) {
+		//		cerr << "Usage: midifile <file.mid>" << endl;
+		//		return 1;
+		//	}
+		
+	//	std::string filename = midiFileName;//argv[1];
+		
+		MIDIFileReader fr(filename);
+	
+		if (!fr.isOK()) {
+			std::cerr << "Error: " << fr.getError().c_str() << std::endl;
+			return 1;
+		}
+		
+		MIDIComposition c = fr.load();
+		
+		switch (fr.getFormat()) {
+			case MIDI_SINGLE_TRACK_FILE: cout << "Format: MIDI Single Track File" << endl; break;
+			case MIDI_SIMULTANEOUS_TRACK_FILE: cout << "Format: MIDI Simultaneous Track File" << endl; break;
+			case MIDI_SEQUENTIAL_TRACK_FILE: cout << "Format: MIDI Sequential Track File" << endl; break;
+			default: cout << "Format: Unknown MIDI file format?" << endl; break;
+		}
+		
+		cout << "Tracks: " << c.size() << endl;
+		
+		int td = fr.getTimingDivision();
+		if (td < 32768) {
+			cout << "Timing division: " << fr.getTimingDivision() << " ppq" << endl;
+			
+			myMidiEvents.pulsesPerQuarternote = fr.getTimingDivision();
+		} else {
+			int frames = 256 - (td >> 8);
+			int subframes = td & 0xff;
+			cout << "SMPTE timing: " << frames << " fps, " << subframes << " subframes" << endl;
+		}
+		
+		for (MIDIComposition::const_iterator i = c.begin(); i != c.end(); ++i) {
+			
+			cout << "Start of track: " << i->first+1 << endl;
+			
+			for (MIDITrack::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
+				
+				unsigned int t = j->getTime();
+				int ch = j->getChannelNumber();
+				
+				if (j->isMeta()) {
+					int code = j->getMetaEventCode();
+					string name;
+					bool printable = true;
+					switch (code) {
+							
+						case MIDI_END_OF_TRACK:
+							cout << t << ": End of track" << endl;
+							break;
+							
+						case MIDI_TEXT_EVENT: name = "Text"; break;
+						case MIDI_COPYRIGHT_NOTICE: name = "Copyright"; break;
+						case MIDI_TRACK_NAME: name = "Track name"; break;
+						case MIDI_INSTRUMENT_NAME: name = "Instrument name"; break;
+						case MIDI_LYRIC: name = "Lyric"; break;
+						case MIDI_TEXT_MARKER: name = "Text marker"; break;
+						case MIDI_SEQUENCE_NUMBER: name = "Sequence number"; printable = false; break;
+						case MIDI_CHANNEL_PREFIX_OR_PORT: name = "Channel prefix or port"; printable = false; break;
+						case MIDI_CUE_POINT: name = "Cue point"; break;
+						case MIDI_CHANNEL_PREFIX: name = "Channel prefix"; printable = false; break;
+						case MIDI_SEQUENCER_SPECIFIC: name = "Sequencer specific"; printable = false; break;
+						case MIDI_SMPTE_OFFSET: name = "SMPTE offset"; printable = false; break;
+							
+						case MIDI_SET_TEMPO:
+						{
+							int m0 = j->getMetaMessage()[0];
+							int m1 = j->getMetaMessage()[1];
+							int m2 = j->getMetaMessage()[2];
+							long tempo = (((m0 << 8) + m1) << 8) + m2;
+							
+							cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
+							myMidiEvents.tempo = 60000000.0 / double(tempo);
+							myMidiEvents.period = double(tempo)/1000.0;
+							
+							printf("period double is %f\n", myMidiEvents.period);
+						}
+							break;
+							
+						case MIDI_TIME_SIGNATURE:
+						{
+							int numerator = j->getMetaMessage()[0];
+							int denominator = 1 << (int)j->getMetaMessage()[1];
+							
+							cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
+						}
+							
+						case MIDI_KEY_SIGNATURE:
+						{
+							int accidentals = j->getMetaMessage()[0];
+							int isMinor = j->getMetaMessage()[1];
+							bool isSharp = accidentals < 0 ? false : true;
+							accidentals = accidentals < 0 ? -accidentals : accidentals;
+							cout << t << ": Key signature: " << accidentals << " "
+							<< (isSharp ?
+								(accidentals > 1 ? "sharps" : "sharp") :
+								(accidentals > 1 ? "flats" : "flat"))
+							<< (isMinor ? ", minor" : ", major") << endl;
+						}
+							
+					}
+					
+					
+					if (name != "") {
+						if (printable) {
+							cout << t << ": File meta event: code " << code
+							<< ": " << name << ": \"" << j->getMetaMessage()
+							<< "\"" << endl;
+						} else {
+							cout << t << ": File meta event: code " << code
+							<< ": " << name << ": ";
+							for (int k = 0; k < j->getMetaMessage().length(); ++k) {
+								cout << (int)j->getMetaMessage()[k] << " ";
+							}
+						}
+					}
+					continue;
+				}
+				
+				switch (j->getMessageType()) {
+						
+					case MIDI_NOTE_ON:
+						cout << t << ": Note: channel " << ch
+						<< " duration " << j->getDuration()
+						<< " pitch " << j->getPitch()
+						<< " velocity " << j->getVelocity() 
+						<< "event time " << myMidiEvents.getEventTimeMillis(t) << endl;
+						v.clear();
+						v.push_back(t);
+						v.push_back(j->getPitch());
+						v.push_back(j->getVelocity());
+						v.push_back(j->getDuration());
+						myMidiEvents.recordedNoteOnMatrix.push_back(v);
+						myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t));
+						break;
+						
+					case MIDI_POLY_AFTERTOUCH:
+						cout << t << ": Polyphonic aftertouch: channel " << ch
+						<< " pitch " << j->getPitch()
+						<< " pressure " << j->getData2() << endl;
+						break;
+						
+					case MIDI_CTRL_CHANGE:
+					{
+						int controller = j->getData1();
+						string name;
+						switch (controller) {
+							case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
+							case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
+							case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
+							case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
+							case MIDI_CONTROLLER_PAN: name = "Pan"; break;
+							case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
+							case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
+							case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
+							case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
+							case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
+							case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
+							case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
+							case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
+							case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
+							case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
+							case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
+							case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
+							case MIDI_CONTROLLER_RESET: name = "Reset"; break;
+							case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
+							case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
+						}
+						cout << t << ": Controller change: channel " << ch
+						<< " controller " << j->getData1();
+						if (name != "") cout << " (" << name << ")";
+						cout << " value " << j->getData2() << endl;
+					}
+						break;
+						
+					case MIDI_PROG_CHANGE:
+						cout << t << ": Program change: channel " << ch
+						<< " program " << j->getData1() << endl;
+						break;
+						
+					case MIDI_CHNL_AFTERTOUCH:
+						cout << t << ": Channel aftertouch: channel " << ch
+						<< " pressure " << j->getData1() << endl;
+						break;
+						
+					case MIDI_PITCH_BEND:
+						cout << t << ": Pitch bend: channel " << ch
+						<< " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
+						break;
+						
+					case MIDI_SYSTEM_EXCLUSIVE:
+						cout << t << ": System exclusive: code "
+						<< (int)j->getMessageType() << " message length " <<
+						j->getMetaMessage().length() << endl;
+						break;
+						
+						
+				}
+				
+				
+			}
+			
+			
+		}
+		
+		
+		
+		
+}//end cannam midi main
+	
+	
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/CannamMidiFileLoader.h	Fri Aug 19 01:26:40 2011 +0100
@@ -0,0 +1,27 @@
+/*
+ *  CannamMidiFileLoader.h
+ *  midi-score-follower
+ *
+ *  Created by Chris Cannam on 19/08/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+#ifndef CANNAM_MIDI_FILE_LOADER
+#define  CANNAM_MIDI_FILE_LOADER
+
+#include "MIDIFileReader.h"
+//#include "MIDIEvent.h"
+#include "midiEventHolder.h"
+using namespace MIDIConstants;
+
+class CannamMidiFileLoader{
+	
+public:
+	int loadFile(std::string& filename, midiEventHolder& myMidiEvents);
+
+	typedef std::vector<int> IntVector;
+	IntVector v;
+	
+};
+#endif
\ No newline at end of file
--- a/src/DynamicVector.cpp	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/DynamicVector.cpp	Fri Aug 19 01:26:40 2011 +0100
@@ -7,6 +7,7 @@
  *
  */
 
+
 #include "DynamicVector.h"
 
 DynamicVector::DynamicVector(){
@@ -51,6 +52,20 @@
 	return max;
 }
 
+double DynamicVector::getIntegratedEstimate(){
+	//returns the index of the integrated average - where the probability distribution is centred
+	double estimate = 0;
+	double integratedTotal = 0;
+	for (int i = 0;i < length;i++){
+		estimate += array[i]*i;
+		integratedTotal += array[i];
+	}
+	if (integratedTotal > 0){
+		estimate /= integratedTotal;
+	}
+	return estimate;
+}
+
 void DynamicVector::zero(){
 	for (int i = 0;i < array.size();i++)
 		array[i] = 0;
@@ -99,12 +114,22 @@
 
 void DynamicVector::addGaussianShape(double mean, double StdDev, double factor){
 	int i;
+	factor *= (1/(StdDev*sqrt(2*PI)));
 	for (i=0;i<array.size();i++){
-		array[i] += factor*(1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev));
+		array[i] += factor*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev));
 	}
 	//printf("ADDED GAUSSIAN SHAPE %i\n", (int)array.size());
 }
 
+void DynamicVector::addTriangularShape(double mean, double width, double factor){
+	int i;
+
+	for (i= max(0., (double)(mean - width));i < min((mean+width), (double)array.size());i++){
+		array[i] += factor * abs(i - mean) / mean;		
+	}
+
+}
+
 void DynamicVector::addConstant(double value){
 	for (int i=0;i<array.size();i++){
 		array[i] += value;
--- a/src/DynamicVector.h	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/DynamicVector.h	Fri Aug 19 01:26:40 2011 +0100
@@ -25,11 +25,14 @@
 	typedef std::vector<double> DoubleVector;
 	DoubleVector array;
 	double getMaximum();
+	double getIntegratedEstimate();
+	
 	void drawVector(const int& minIndex, const int& maxIndex);
 	void drawConstrainedVector(const int& minIndex, const int& maxIndex, const int& minScreenIndex, const int& maxScreenIndex);
 
 	void addConstant(double value);
 	void addGaussianShape(double mean, double stddev, double factor);
+	void addTriangularShape(double mean, double width, double factor);
 	void addToIndex(int index, double constant);
 	
 	void doProduct(DynamicVector& arrayOne, DynamicVector& arrayTwo);
--- a/src/midiEventHolder.cpp	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/midiEventHolder.cpp	Fri Aug 19 01:26:40 2011 +0100
@@ -27,16 +27,25 @@
 	
 	minimumMatchSpeed = 0.7;
 	maximumMatchSpeed = 1.3;
+
 	likelihoodWidth = 100;
-	likelihoodToNoiseRatio = 50;
+	likelihoodToNoiseRatio = 0.02;
 	
-	matchWindowWidth = 4000;//window size for matching in ms 
+	bayesStruct.speedLikelihoodNoise = 0.05;//was 0.05
+	bayesStruct.speedDecayWidth = 20;
+	bayesStruct.speedDecayAmount = 10;
+	
+	
+	matchWindowWidth = 8000;//window size for matching in ms 
 	
 	bayesStruct.resetSize(matchWindowWidth);
+	bayesStruct.setPositionDistributionScalar(1);
+	
 	bayesStruct.resetSpeedSize(200);
 	bayesStruct.setRelativeSpeedScalar(0.01);
 	bayesStruct.relativeSpeedPrior.getMaximum();
-	bayesStruct.simpleExample();
+	//bayesStruct.simpleExample();
+	
 	
 	noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum);
 }
@@ -44,6 +53,8 @@
 
 
 void midiEventHolder::reset(){
+	//called when we start playing
+	
 	noteArrayIndex = 0;
 	tickLocation = 0;
 	lastPeriodUpdateTime = ofGetElapsedTimeMillis();
@@ -108,18 +119,28 @@
 
 	
 	//would update the arrays at this point to show where out current location (phase) and tempo is.
-	double timeNow = ofGetElapsedTimeMillis() - startTime;
-	recentNoteOnTime = timeNow;
+//	double timeNow = ofGetElapsedTimeMillis() - startTime;
+	double timeNow = timePlayed;// - startTime;
+	recentNoteOnTime = timePlayed;
 	
-	printf("Max time %f OF time %f \n", timePlayed, timeNow);
+//	printf("Max time %f OF time %f \n", timePlayed, timeNow);
 	
 	playedEventTimes.push_back(timePlayed);
 	
-	double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; 
+//	double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; 
+	double timeDifference = timePlayed - bayesStruct.lastEventTime; 
 	
+	printf("note %i played at %f and last event %f\n", pitch, timePlayed, bayesStruct.lastEventTime);
 	//addnoise to the tempo distribution
-	bayesStruct.decaySpeedDistribution(timeDifference);
-
+	//bayesStruct.decaySpeedDistribution(timeDifference);
+	if (timeDifference > 50){
+	bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10 / 100.);
+//	bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.);
+	}
+	
+	bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work	bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate;
+	bayesStruct.updateBestEstimate();
+	bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
 	
 //	double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate);
 	//was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis
@@ -149,8 +170,8 @@
 	
 	
 	//be able to draw the prior in correct location relative to the midi notes
+	//this calculates the cross update of all possible speeds and all possible positions
 	bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, timeDifference);
-//	bayesStruct.crossUpdateArrays(bayesStruct.prior, bayesStruct.relativeSpeedPosterior, timeDifference);
 
 	
 	timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1);
@@ -160,7 +181,8 @@
 //	bayesStruct.prior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
 	//trying to switch to prior
 	
-	bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
+	//bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
+	bayesStruct.lastEventTime = timePlayed;
 	
 	//do the cross update to find current posterior for location
 //	totalConfidence= 0;
@@ -171,7 +193,7 @@
 	//having found matches we have matches for new note and matches for previous notes
 	findLocalTempoPairs();
 	
-	
+	//bayesStruct.addGaussianNoiseToSpeedPosterior(10);
 	 
 }
 
@@ -197,7 +219,7 @@
 	bayesStruct.likelihood.offset = bayesStruct.prior.offset;
 	bayesStruct.likelihood.zero();//set to zero
 	
-	
+	double quantity = likelihoodToNoiseRatio / numberOfMatches;
 	
 	for (int i = 0;i < numberOfMatches && matchesFound[i] >= 0 && matchesFound[i] < recordedEventTimes.size();i++){
 	//	printf("match times %i of %i::%f adding likelihood to %f\n", i, numberOfMatches, recordedEventTimes[matchesFound[i]], recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset);
@@ -206,11 +228,11 @@
 	//		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
+			
+			bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth,  quantity);//* confidenceMeasure
 		}//end if
 	}
-	bayesStruct.likelihood.addConstant(0.01);
+	bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length);
 }
 
 int midiEventHolder::findMatch(const int& notePitch, const int& startTime, const int& endTime){
@@ -290,13 +312,16 @@
 				
 				double speedRatio = recordedTimeDifference / playedTimeDifference;
 				if (speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){
-								printf("(%i)", matchMatrix[currentPlayedIndex][i+1]);
+						/*
+						 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
+					
+						 bayesStruct.updateTempoDistribution(speedRatio, 0.1);//second paramter is confidence in the match
 			
 				}
 	//		printf("\n");	
@@ -306,7 +331,7 @@
 		}//end while previousindex countdown
 	}//end for loop through possible current matches
 	
-		
+	//printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
 }
 
 
@@ -383,6 +408,10 @@
 		ofSetColor(250,100,0);
 		ofLine(xLocation, 0, xLocation, (*screenHeight));
 		
+		xLocation = getLocationFromMillis(bayesStruct.tmpBestEstimate);
+		ofSetColor(250,100,0);
+		ofLine(xLocation, 0, xLocation, (*screenHeight));
+		
 		
 		//lines where matching window start and end are 
 		ofSetColor(0,100,255);
@@ -416,8 +445,15 @@
 	ofDrawBitmapString(matchString, 20, ofGetHeight() - 20);
 	
 	double confidence = bayesStruct.posterior.getValueAtMillis(mouseX);
-	string mouseString = "mouseX "+ofToString(confidence, 3)+" .";
+/*
+ string mouseString = "mouseX "+ofToString(confidence, 3)+" .";
 	ofDrawBitmapString(mouseString, 20 ,  ofGetHeight() - 40);
+*/	
+	string mouseString = "updateCounter "+ofToString(bayesStruct.updateCounter);
+	ofDrawBitmapString(mouseString, 20 ,  ofGetHeight() - 40);
+	
+	string infostring = "speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate), 3);
+	ofDrawBitmapString(infostring, 20 ,  ofGetHeight() - 60);							   
 }
 
 int midiEventHolder::getLocationFromTicks(double tickPosition){
@@ -439,11 +475,15 @@
 
 void midiEventHolder::setStartPlayingTimes(){
 	lastPeriodUpdateTime = ofGetElapsedTimeMillis();
-	bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
 	startTime = lastPeriodUpdateTime;
 	
+/*	
+ 	bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis();
+	bayesStruct.bestEstimate = 0;
 	bayesStruct.resetArrays();
-//	bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+	bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+*/
+	bayesStruct.setStartPlaying();
 	matchString = "";
 }
 
--- a/src/midiEventHolder.h	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/midiEventHolder.h	Fri Aug 19 01:26:40 2011 +0100
@@ -6,6 +6,9 @@
  *  Copyright 2011 QMUL. All rights reserved.
  *
  */
+#ifndef MIDI_EVENT_HOLDER
+#define MIDI_EVENT_HOLDER
+ 
 #include "ofMain.h"
 #include "BayesianArrayStructure.h"
 
@@ -26,11 +29,13 @@
 	
 	//the rehearsal version
 	IntMatrix recordedNoteOnMatrix;//note, velocity, duration
+	DoubleVector recordedEventTimes;
+	
 	IntVector matchesFound;
 	BoolVector noteOnMatches;
 	
 //	int recordedNoteOnIndex;
-	DoubleVector recordedEventTimes;
+	
 	
 	IntMatrix playedNoteOnMatrix;
 	DoubleVector playedEventTimes;
@@ -110,4 +115,5 @@
 	string timeString;
 	double startTime;
 	
-};
\ No newline at end of file
+};
+#endif
\ No newline at end of file
--- a/src/testApp.cpp	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/testApp.cpp	Fri Aug 19 01:26:40 2011 +0100
@@ -19,7 +19,8 @@
 	screenHeight = ofGetHeight();
 	midiEvents.screenWidth = &screenWidth;
 	midiEvents.screenHeight = &screenHeight;
-	ofSetFrameRate(100);
+	midiEvents.drawTempoMode = false;
+	ofSetFrameRate(30);
 }
 
 //--------------------------------------------------------------
@@ -206,7 +207,7 @@
 int testApp::cannamMainFunction(){
 
 
-		midiEvents.clearAllEvents();
+	midiEvents.clearAllEvents();
 	
 	//int main(int argc, char **argv)
 	//{
@@ -216,8 +217,18 @@
 	//	}
 		
 	std::string filename = midiFileName;//argv[1];
-		
-		MIDIFileReader fr(filename);
+	
+	fileLoader.loadFile(filename, midiEvents);
+	
+}//new end of load function
+
+
+
+
+	//trying to port to new class
+	/*
+			MIDIFileReader fr(filename);
+	
 		if (!fr.isOK()) {
 			std::cerr << "Error: " << fr.getError().c_str() << std::endl;
 			return 1;
@@ -418,10 +429,8 @@
 			
 		}
 		
-	//}
+}//end cannam midi main	
 	
-	
-	
+*/
 
-}//end cannam midi main
 
--- a/src/testApp.h	Thu Aug 18 23:27:42 2011 +0100
+++ b/src/testApp.h	Fri Aug 19 01:26:40 2011 +0100
@@ -15,7 +15,7 @@
 
 
 
-
+//uses ftmMidiPlay in max5 via osc to communicate notes in
 
 #include "ofMain.h"
 
@@ -23,7 +23,7 @@
 #include "ofxFileDialogOSX.h"
 #include "drawMidiNotes.h"
 #include "DynamicBayesianArray.h"
-
+#include "CannamMidiFileLoader.h"
 #include <iostream>
 #include "midiEventHolder.h"
 
@@ -68,10 +68,13 @@
 //	BayesianArrayStructure bayesStruct;
 	
 	int screenWidth, screenHeight;
+	CannamMidiFileLoader fileLoader;
 	
 private:
 	ofxOscReceiver	receiver;
 	
+
+	
 };
 
 #endif