changeset 0:c4f9e49226eb

Initialising repository. Live osc input registered. Files analysed offline.
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 31 Jan 2012 13:54:17 +0000
parents
children 852173ca8365
files README.txt bayesianArraySrc/BayesianArrayStructure.cpp bayesianArraySrc/BayesianArrayStructure.h bayesianArraySrc/DynamicVector.cpp bayesianArraySrc/DynamicVector.h bayesianArraySrc/midiEventHolder.cpp bayesianArraySrc/midiEventHolder.h src/AudioEventMatcher.cpp src/AudioEventMatcher.h src/LiveAudioInput.cpp src/LiveAudioInput.h src/main.cpp src/testApp.cpp src/testApp.h
diffstat 14 files changed, 3064 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/README.txt	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,11 @@
+Receives live input and matches to rehearsal
+
+
+ofxFileDialog
+ofxOSC
+
+Venetian:
+ofxWindowRegion
+ofxSoundfileloader
+ofxAubioOnsetDetector
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bayesianArraySrc/BayesianArrayStructure.cpp	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,585 @@
+/*
+ *  BayesianArrayStructure.cpp
+ *  midiCannamReader
+ *
+ *  Created by Andrew on 17/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+//look at reset speed to one - what does this do? - get rid of?
+
+
+#include "BayesianArrayStructure.h"
+
+BayesianArrayStructure::BayesianArrayStructure(){
+	printf("Bayesian structure: DeFault constructor called");
+
+	usingIntegratedTempoEstimate = true;// use max index
+	
+	relativeSpeedLikelihoodStdDev = 5.0;
+	
+	prior.createVector(1);
+	likelihood.createVector(1);
+	posterior.createVector(1);
+
+	speedPriorValue = 1.0;//default value for the speed prior
+	speedEstimate = speedPriorValue;
+	
+	lastEventTime = 0;//ofGetElapsedTimeMillis();
+
+	tmpBestEstimate = 0;
+	crossUpdateTimeThreshold = 60;
+	priorWidth = 50;
+	
+}
+
+BayesianArrayStructure::BayesianArrayStructure(int length){
+	printf("BAYESIAN STURCTURE CREATED LENGTH: %i\n", length);
+	//this constructor isnt called  it seems
+	prior.createVector(length);
+	likelihood.createVector(length);
+	posterior.createVector(length);
+	
+	lastEventTime = 0;
+	
+
+}
+
+
+
+void BayesianArrayStructure::resetSize(int length){
+	printf("BAYESIAN STRUCTURE size is : %i\n", length);
+	
+	prior.createVector(length);
+	likelihood.createVector(length);
+	posterior.createVector(length);
+	
+	acceleration.createVector(length);
+	
+}
+
+void BayesianArrayStructure::resetSpeedSize(int length){
+	printf("BAYESIAN reset SPEED size is : %i\n", length);
+	
+	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::resetSpeedToOne(){
+	relativeSpeedPrior.zero();
+	relativeSpeedPosterior.zero();
+	relativeSpeedLikelihood.zero();
+	
+	
+	relativeSpeedPosterior.addGaussianShape(100, 20, 0.8);
+	relativeSpeedPosterior.renormalise();
+	relativeSpeedPosterior.getMaximum();
+	
+	setSpeedPrior(speedPriorValue);
+	speedEstimate = speedPriorValue;
+	
+	prior.zero();
+	posterior.zero();
+	
+	posterior.addToIndex(0, 1);
+	posterior.renormalise();
+	
+}
+
+void BayesianArrayStructure::setSpeedPrior(double f){	
+	speedPriorValue = f;
+	int index = relativeSpeedPosterior.getRealTermsAsIndex(speedPriorValue);
+	relativeSpeedPosterior.zero();
+	relativeSpeedPosterior.addGaussianShape(index, priorWidth, 0.8);
+	relativeSpeedPosterior.renormalise();
+	relativeSpeedPosterior.getMaximum();
+	relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
+	printf("BAYES STRUCTU ' SPEED PRIOR %f . index %i\n", speedPriorValue, index);
+	
+}
+
+
+void BayesianArrayStructure::setPositionDistributionScalar(double f){
+	if (f > 0){
+	prior.scalar = f;
+	posterior.scalar = f;
+	likelihood.scalar = f;
+	}
+}
+
+void BayesianArrayStructure::simpleExample(){
+	relativeSpeedPosterior.getMaximum();
+	relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
+}
+
+void BayesianArrayStructure::copyPriorToPosterior(){
+
+	for (int i = 0;i < prior.arraySize;i++){
+		posterior.array[i] = prior.array[i];
+	}
+}
+
+void BayesianArrayStructure::setStartPlaying(){
+	
+	lastEventTime = 0;
+	bestEstimate = 0;
+	lastBestEstimateUpdateTime = 0;
+	if (*realTimeMode)
+		lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+	//cannot just be zero - offline bug
+	//printf("start playing - best estimate %f\n", lastBestEstimateUpdateTime);
+	
+	resetArrays();
+}
+
+void BayesianArrayStructure::resetArrays(){
+	//called when we start playing
+	
+	prior.zero();
+	likelihood.zero();
+	posterior.zero();
+	
+	updateCounter = 0;
+	
+	posterior.offset = -1000;
+	setNewDistributionOffsets(0);
+	
+	int zeroIndex = posterior.getRealTermsAsIndex(0);
+	
+	posterior.addGaussianShape(zeroIndex, 500, 1);
+	//	posterior.addToIndex(0, 1);
+	likelihood.addConstant(1);
+	
+	updateCounter = 0;
+	
+
+	printf("bayes reset arrays - best estimate %f\n", lastBestEstimateUpdateTime);
+	
+	setSpeedPrior(speedPriorValue);
+}
+
+
+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;
+	double timeDiff = timeDifference;
+	if (*realTimeMode)
+		timeDiff = ofGetElapsedTimeMillis() - lastBestEstimateUpdateTime;
+
+	double tmp = relativeSpeedPosterior.getIntegratedEstimate();
+	tmpBestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate);
+	// 
+	//printf("tmp best %f and best %f time diff %f posterior MAP %f at speed %f\n", 0Estimate, bestEstimate, timeDifference, posterior.getIndexInRealTerms(posterior.MAPestimate), relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate));
+	//lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+}
+	
+void BayesianArrayStructure::updateBestEstimate(const double& timeDifference){
+//	double timeDiff = ofGetElapsedTimeMillis() - lastEventTime;//
+	
+	double timeDiff = timeDifference;
+	
+	//Using timedifferencfe here will make it go wrong. Is time since beginning of playing
+	
+	if (*realTimeMode)
+		timeDiff = ofGetElapsedTimeMillis() - lastBestEstimateUpdateTime;
+	
+	//lastbest is time we started playing
+	
+	if (usingIntegratedTempoEstimate)
+		speedEstimateIndex = relativeSpeedPosterior.getIntegratedEstimate();
+	else
+		speedEstimateIndex = relativeSpeedPosterior.MAPestimate;
+	
+	speedEstimate = relativeSpeedPosterior.getIndexInRealTerms(speedEstimateIndex);
+	bestEstimate = posterior.getIndexInRealTerms(posterior.MAPestimate) + timeDiff*speedEstimate;
+	
+}
+
+void BayesianArrayStructure::calculatePosterior(){
+	//posterior.doProduct(prior, likelihood);
+	
+	int i;
+	for (i = 0;i < posterior.length;i++){
+		posterior.array[i] = likelihood.array[i] * prior.array[i];
+	}
+	
+	posterior.renormalise();
+	
+}
+
+
+
+
+void BayesianArrayStructure::setNewDistributionOffsets(const double& newOffset){
+	prior.offset = newOffset;
+	likelihood.offset = newOffset;
+	//posterior.offset = newOffset;
+}
+
+
+void BayesianArrayStructure::crossUpdateArrays(DynamicVector& position, DynamicVector& speed, double timeDifference){
+	//set the cutoff for offset of position first! XXX
+	
+//	printf("time difference %f, ", timeDifference);
+	
+	double timeDifferenceInPositionVectorUnits = timeDifference / prior.scalar;
+	
+
+	prior.zero();//kill prior
+	calculateNewPriorOffset(timeDifference);//set new prior offset here
+	
+	if (timeDifferenceInPositionVectorUnits > crossUpdateTimeThreshold)
+		complexCrossUpdate(timeDifferenceInPositionVectorUnits);
+	else
+		translateByMaximumSpeed(timeDifferenceInPositionVectorUnits);	
+			
+
+	updateCounter++;
+	prior.renormalise();
+
+}
+
+void BayesianArrayStructure::complexCrossUpdate(const double& timeDifferenceInPositionVectorUnits){
+	int distanceMoved, newPriorIndex;
+	
+	double speedValue = relativeSpeedPosterior.offset;
+	
+	for (int i = 0;i < relativeSpeedPosterior.arraySize;i++){
+		
+	//	double speedValue = relativeSpeedPosterior.getIndexInRealTerms(i);//so for scalar 0.01, 50 -> speed value of 0.5
+		
+		//so we have moved 
+		distanceMoved = round(timeDifferenceInPositionVectorUnits * speedValue);//round the value
+	
+		if (relativeSpeedPosterior.array[i] != 0){
+			double speedContribution = relativeSpeedPosterior.array[i];
+			//	printf("speed [%i] gives %f moved %i in %f units \n", i, speedValue, distanceMoved, timeDifferenceInPositionVectorUnits);
+			
+			newPriorIndex = posterior.offset - prior.offset + distanceMoved;
+			
+			for (int postIndex = 0;postIndex < posterior.arraySize;postIndex++){
+				//old posterior contributing to new prior
+			//	newPriorIndex = postIndex + posterior.offset - prior.offset + distanceMoved;
+				
+				if (newPriorIndex >= 0 && newPriorIndex < prior.arraySize){
+					prior.addToIndex(newPriorIndex, posterior.array[postIndex]*speedContribution);
+				}
+				
+				newPriorIndex++;//optimised code - the commented line above explains how this works
+			}//end for
+			
+			
+		}//if not zero
+		speedValue += relativeSpeedPosterior.scalar;
+		//optimised line
+		//as we wanted:
+		//	double speedValue = relativeSpeedPosterior.getIndexInRealTerms(i);//so for scalar 0.01, 50 -> speed value of 0.5
+	}//end speed
+}
+
+
+
+void BayesianArrayStructure::translateByMaximumSpeed(const double& timeDifferenceInPositionVectorUnits){
+
+	int distanceMoved, newPriorIndex;
+	
+	double speedValue = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate);
+	//so for scalar 0.01, 50 -> speed value of 0.5
+	double speedContribution = relativeSpeedPosterior.array[relativeSpeedPosterior.integratedEstimate];
+		//so we have moved 
+		distanceMoved = round(timeDifferenceInPositionVectorUnits * speedValue);//round the value
+					//	printf("speed [%i] gives %f moved %i in %f units \n", i, speedValue, distanceMoved, timeDifferenceInPositionVectorUnits);
+			
+			for (int postIndex = 0;postIndex < posterior.arraySize;postIndex++){
+				//old posterior contributing to new prior
+				newPriorIndex = postIndex + posterior.offset - prior.offset + distanceMoved;
+				if (newPriorIndex >= 0 && newPriorIndex < prior.arraySize){
+					prior.addToIndex(newPriorIndex, posterior.array[postIndex]*speedContribution);
+				}
+				
+			}
+	
+}
+
+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.integratedEstimate);
+	//	printf("Maxspeed is %f\n", maxSpeed);
+	
+	double priorMax = posterior.getMaximum();
+	double distanceTravelled = maxSpeed * (timeDifference / prior.scalar);
+	double newMaxLocation = posterior.MAPestimate + distanceTravelled;
+	//	printf("MAP: %i, tim df %f, distance %f, new location %f\n", posterior.MAPestimate, timeDifference, distanceTravelled, newMaxLocation);
+	
+}
+
+
+void BayesianArrayStructure::decaySpeedDistribution(double timeDifference){
+	
+	// commented for the moment
+	 double relativeAmount = max(1.0, timeDifference/1000.);
+//	printf("decay %f around %i \n", timeDifference, relativeSpeedPosterior.MAPestimate);
+	relativeAmount *= speedDecayAmount;
+	relativeSpeedPosterior.renormalise();
+	relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, relativeAmount);
+	
+	relativeSpeedPosterior.renormalise();
+	double newMax = relativeSpeedPosterior.getMaximum();
+	
+	//old code
+//	relativeSpeedPosterior.addGaussianShape(relativeSpeedPosterior.MAPestimate, speedDecayWidth, 10);
+	//relativeSpeedPosterior.addConstant(1);
+	
+	/*
+	relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
+	relativeSpeedLikelihood.zero();
+	relativeSpeedLikelihood.addConstant(0.2);
+	relativeSpeedLikelihood.addGaussianShape(relativeSpeedPosterior.maximumValue, speedDecayWidth, relativeAmount);
+	relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood);
+	relativeSpeedPosterior.renormalise();
+	 */
+	
+
+	
+}
+
+void BayesianArrayStructure::setLikelihoodToConstant(){
+	//set new likelihood
+	relativeSpeedLikelihood.zero();
+	relativeSpeedLikelihood.addConstant(speedLikelihoodNoise);
+}
+
+
+void BayesianArrayStructure::updateTempoLikelihood(const double& speedRatio, const double& matchFactor){
+	
+	//speedratio is speed of played relative to the recording
+	
+	double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio);
+	//	printf("index of likelihood would be %f for ratio %f\n", index, speedRatio);
+	if (index >= 0 && index < relativeSpeedPrior.length){	
+		relativeSpeedLikelihood.addGaussianShape(index , relativeSpeedLikelihoodStdDev, matchFactor);
+	}
+}
+	
+
+
+void BayesianArrayStructure::updateTempoDistribution(){
+
+	//copy posterior to prior
+	relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
+
+	//update
+	relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood);
+
+	//normalise
+	relativeSpeedPosterior.renormalise();
+		
+	relativeSpeedPosterior.getMaximum();	
+	
+	//relativeSpeedPosterior.updateIntegratedEstimate(); - could be swayed when off to side 
+	//so now limited to where there is room sround the MAP estimate
+	relativeSpeedPosterior.updateLimitedIntegratedEstimate();
+	
+	speedEstimate = relativeSpeedPosterior.getIndexInRealTerms(relativeSpeedPosterior.integratedEstimate);
+}
+
+
+void BayesianArrayStructure::calculateTempoUpdate(){
+	//copy posterior to prior
+	relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
+	
+	//update
+	relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood);
+	
+	//normalise
+	relativeSpeedPosterior.renormalise();
+	
+	relativeSpeedPosterior.getMaximum();	
+	
+}
+
+
+void BayesianArrayStructure::drawArrays(){
+	
+	//bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200);
+	//bayesArray.drawFloatArray(&bayesArray.prior[0], 0, 200);
+	
+	int displaySize = prior.arraySize;
+	ofSetColor(0,0,255);
+	prior.drawVector(0, displaySize);
+	ofSetColor(0,255,0);
+	likelihood.drawVector(0, displaySize);
+	ofSetColor(255,0,255);
+	posterior.drawVector(0, displaySize);
+	
+	
+	
+}
+
+
+void BayesianArrayStructure::drawTempoArrays(){
+	ofSetColor(0,0,255);
+//	relativeSpeedPrior.drawVector(0, relativeSpeedPrior.arraySize);
+	
+	ofSetColor(0,150,255);
+	relativeSpeedLikelihood.drawVector(0, relativeSpeedLikelihood.arraySize);
+	
+//	relativeSpeedLikelihood.drawConstrainedVector(0, 199, 0, 1000);// relativeSpeedLikelihood.arraySize);	
+	ofSetColor(255,0,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
+	
+	ofSetColor(25, 0, 250);
+	double fractionOfScreen = ((double)relativeSpeedPosterior.integratedEstimate / relativeSpeedPosterior.length);
+	ofLine(screenWidth * fractionOfScreen, 0, screenWidth * fractionOfScreen, ofGetHeight());
+	
+	ofSetColor(255, 0, 20);
+	fractionOfScreen = ((double)relativeSpeedPosterior.MAPestimate / relativeSpeedPosterior.length);
+	ofLine(screenWidth * fractionOfScreen, 0, screenWidth * fractionOfScreen, ofGetHeight());
+	 
+	
+}
+
+
+void BayesianArrayStructure::drawArraysRelativeToTimeframe(const double& startTimeMillis, const double& endTimeMillis){
+
+	screenWidth = ofGetWidth();
+	
+	int startArrayIndex = 0;
+	
+	if (prior.getIndexInRealTerms(prior.arraySize-1) > startTimeMillis){
+		//i.e. the array is on the page
+	
+	while (prior.getIndexInRealTerms(startArrayIndex) < startTimeMillis){
+		startArrayIndex++;
+	}
+	int endArrayIndex = prior.arraySize-1;
+	//could find constraints here
+	if (prior.getIndexInRealTerms(prior.arraySize-1) > endTimeMillis)
+		endArrayIndex = (floor)((endTimeMillis - prior.offset)/prior.scalar);
+	
+	//so we need to figure where start and end array are on screen
+	int startScreenPosition, endScreenPosition;
+	double screenWidthMillis = endTimeMillis - startTimeMillis;
+		
+	startScreenPosition = (prior.getIndexInRealTerms(startArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis;
+	endScreenPosition = (double)(prior.getIndexInRealTerms(endArrayIndex) - startTimeMillis)*screenWidth/screenWidthMillis;
+		
+	ofSetColor(0,0,100);
+	string relativeString = " offset "+ofToString(prior.offset, 1);//starttimes("+ofToString(startTimeMillis)+", "+ofToString(endTimeMillis);
+	relativeString += ": index "+ofToString(startArrayIndex)+" , "+ofToString(endArrayIndex)+" [";
+//	relativeString += ofToString(prior.getIndexInRealTerms(endArrayIndex), 3)+"] (sc-width:"+ofToString(screenWidthMillis, 1)+")  ";
+	relativeString += " mapped to screen "+ofToString(startScreenPosition)+" , "+ofToString(endScreenPosition);
+//	ofDrawBitmapString(relativeString, 100, 180);
+	
+		
+		
+	ofSetColor(100,100,100);//255, 255, 0);
+	likelihood.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
+
+//	ofSetColor(0,0,200);
+	ofSetColor(170,170,170);//00,200);
+	prior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
+		
+		ofSetColor(0,0,150);	
+//	ofSetColor(200, 0, 0);
+	posterior.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
+		
+		
+//	ofSetColor(0, 200, 255);
+//	acceleration.drawConstrainedVector(startArrayIndex, endArrayIndex, startScreenPosition, endScreenPosition);
+		
+		
+	}
+
+}
+
+
+/*
+ 
+ void BayesianArrayStructure::updateTempoDistribution(const double& speedRatio, const double& matchFactor){
+ //speedratio is speed of played relative to the recording
+ 
+ double index = relativeSpeedLikelihood.getRealTermsAsIndex(speedRatio);
+ //	printf("\nindex of likelihood would be %f\n", index);
+ if (index >= 0 && index < relativeSpeedPrior.length){
+ //then we can do update
+ 
+ //set new likelihood
+ relativeSpeedLikelihood.zero();
+ relativeSpeedLikelihood.addConstant(speedLikelihoodNoise);
+ 
+ relativeSpeedLikelihood.addGaussianShape(index , 5, 0.5*matchFactor);
+ 
+ 
+ //copy posterior to prior
+ relativeSpeedPrior.copyFromDynamicVector(relativeSpeedPosterior);
+ 
+ //update
+ relativeSpeedPosterior.doProduct(relativeSpeedPrior, relativeSpeedLikelihood);
+ 
+ //normalise
+ relativeSpeedPosterior.renormalise();
+ 
+ relativeSpeedPosterior.getMaximum();	
+ }//end if within range
+ 
+ 
+ }
+ 
+ */
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bayesianArraySrc/BayesianArrayStructure.h	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,99 @@
+/*
+ *  BayesianArrayStructure.h
+ *  midiCannamReader
+ *
+ *  Created by Andrew on 17/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+#ifndef BAYESIAN_ARRAY_STRUCTURE
+#define BAYESIAN_ARRAY_STRUCTURE
+
+
+#include "ofMain.h"
+//#include "DynamicBayesianArray.h"
+#include "DynamicVector.h"
+
+class BayesianArrayStructure {
+	
+public:
+//	BayesianArrayStructure();
+	BayesianArrayStructure();
+	BayesianArrayStructure(int length);
+	
+	void calculatePosterior();
+	void drawArrays();
+	void drawArraysRelativeToTimeframe(const double& startTimeMillis, const double& endTimeMillis);
+
+	void drawTempoArrays();
+	
+	void resetSize(int length);
+	void resetArrays();
+	void simpleExample();
+	void setStartPlaying();
+	void zeroArrays();
+	
+	double screenWidth;
+	
+	void copyPriorToPosterior();
+//	DynamicBayesianArray bayesArray;
+	
+	double lastEventTime;
+	double likelihoodNoise;
+	double speedLikelihoodNoise;
+	
+	//DynamicVector tmpPrior;
+	DynamicVector tmpPosteriorForStorage;
+	DynamicVector prior;
+	DynamicVector posterior;
+	DynamicVector likelihood;
+	
+	DynamicVector relativeSpeedPrior;
+	DynamicVector relativeSpeedLikelihood;
+	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(const double& timeDifference);
+	double lastBestEstimateUpdateTime;
+	double speedEstimate, speedEstimateIndex;
+	
+	double speedDecayWidth, speedDecayAmount;
+	void decaySpeedDistribution(double timeDifference);
+	
+	void resetSpeedSize(int length);
+	void setRelativeSpeedScalar(double f);
+	void setSpeedPrior(double f);
+	void calculateNewPriorOffset(const double& timeDifference);
+	void setNewDistributionOffsets(const double& newOffset);
+	
+	void setLikelihoodToConstant();
+	void updateTempoLikelihood(const double& speedRatio, const double& matchFactor);
+	void updateTempoDistribution();
+	
+	void calculateTempoUpdate();
+	
+	void crossUpdateArrays(DynamicVector& position, DynamicVector& speed, double timeDifference);
+	void complexCrossUpdate(const double& timeDifferenceInPositionVectorUnits);
+	void translateByMaximumSpeed(const double& timeDifferenceInPositionVectorUnits);
+	double crossUpdateTimeThreshold;//time after which we do complex update of multiple speeds
+	
+	double speedPriorValue;
+	int priorWidth;
+	bool* realTimeMode;
+	bool usingIntegratedTempoEstimate;
+	double relativeSpeedLikelihoodStdDev;
+
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bayesianArraySrc/DynamicVector.cpp	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,314 @@
+/*
+ *  DynamicVector.cpp
+ *  midiCannamReader
+ *
+ *  Created by Andrew on 18/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+
+#include "DynamicVector.h"
+
+DynamicVector::DynamicVector(){
+	length = 0;
+	arraySize = 0;
+	maximumValue = 0;
+	MAPestimate = 0;
+	offset = 0;
+	scalar = 1;
+	integratedEstimate = length/2;
+	
+	gaussianLookupMean = (double) GAUSSIAN_LOOKUP_LENGTH/2;
+	gaussianLookupStdDev = (double)(GAUSSIAN_LOOKUP_LENGTH/16);
+	double factor = 1.0;//(1.0 / (gaussianLookupStdDev*sqrt(2*PI)) );//1.0;//-1.0/(2*PI*sqrt(gaussianLookupStdDev));
+	for (int i = 0;i < GAUSSIAN_LOOKUP_LENGTH;i++){
+	gaussianLookupTable[i] = factor*exp(-1.0*(i-gaussianLookupMean)*(i-gaussianLookupMean)/(2.0*gaussianLookupStdDev*gaussianLookupStdDev));
+	}
+	
+}
+
+void DynamicVector::copyFromDynamicVector(const DynamicVector& dynamicVec){
+	if (dynamicVec.length == length){
+		for (int i = 0;i < length;i++)
+			array[i] = dynamicVec.array[i];
+	}
+	else{
+		printf("CANNOT COPY VECTORS OF NON SAME LENGTH!!\n");
+	}
+}
+
+void DynamicVector::createVector(int len){
+	array.clear();
+	for (int i = 0; i < len;i++){
+		array.push_back(0);
+	}
+	length = len;
+	arraySize = array.size();
+	integratedEstimate = length/2;
+}
+
+
+double DynamicVector::getMaximum(){
+	int i;
+	double max = 0;
+	for (i=0;i < length;i++){	
+		if (array[i] > max){
+			max = array[i];
+			MAPestimate = i;
+		}
+	}
+	maximumValue = max;
+	return max;
+}
+
+double DynamicVector::getIntegratedEstimate(){
+	//returns the index of the integrated average - where the probability distribution is centred
+	integratedEstimate = 0;
+	double integratedTotal = 0;
+	for (int i = 0;i < length;i++){
+		integratedEstimate += array[i]*i;
+		integratedTotal += array[i];
+	}
+	if (integratedTotal > 0){
+		integratedEstimate /= integratedTotal;
+	}
+	return integratedEstimate;
+}
+
+void DynamicVector::updateIntegratedEstimate(){
+	//returns the index of the integrated average - where the probability distribution is centred
+	integratedEstimate = 0;
+	double integratedTotal = 0;
+	for (int i = 0;i < length;i++){
+		integratedEstimate += array[i]*i;
+		integratedTotal += array[i];
+	}
+	if (integratedTotal > 0){
+		integratedEstimate /= integratedTotal;
+	}
+
+}
+
+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++)
+		array[i] = 0;
+}
+
+void DynamicVector::renormalise(){
+	double tmpMax = getMaximum();
+	if (tmpMax > 0){
+//	printf("renormalise : max is %f and size is %i\n", tmpMax, arraySize);		
+		for (int i = 0;i < array.size();i++)
+			array[i] /= tmpMax;
+
+	}
+	//printArray();
+}
+
+void DynamicVector::doProduct(DynamicVector& arrayOne, DynamicVector& arrayTwo){
+
+	for (int i = 0;i < arrayOne.length;i++)
+		array[i] = arrayOne.array[i] * arrayTwo.array[i];
+}
+
+
+void DynamicVector::printArray(){
+	for (int i = 0;i < arraySize;i++){
+		printf("[%i] = %f\n", i, array[i]);
+	}
+}
+
+void DynamicVector::translateDistribution(int translationIndex){
+	int tmpIndex;
+	DoubleVector tmpArray;
+	int i;
+
+	for (i=0;i < arraySize;i++){
+		tmpArray.push_back(array[i]);
+	}
+	//translate values
+	for (i=0;i < arraySize;i++){
+		tmpIndex = (i + translationIndex + arraySize)%arraySize;
+		array[tmpIndex] = tmpArray[i]; 
+	}
+	tmpArray.clear();
+	//now delete tmp array
+}
+
+void DynamicVector::addGaussianShape(const double& mean, const double& StdDev, double factor){
+	
+	int i;
+	double std_dev_factor = (2*StdDev*StdDev);
+	factor *= (1/(StdDev*sqrt(2*PI)));
+	int maxVal = min((int) array.size(), (int)(mean + 4.8*StdDev));
+	int minVal = max(0, (int)(mean - 4.8*StdDev));
+	
+	for (i=minVal;i < maxVal;i++){
+		array[i] += factor*exp(-1*(i-mean)*(i-mean)/(std_dev_factor));
+	}
+	
+//	addGaussianShapeByLookupTable(mean, StdDev, factor);
+}
+
+void DynamicVector::addGaussianShapeByLookupTable(double& mean, double& StdDev, double factor){
+	int i;
+	int lookupIndex ;
+	factor *= (1/(StdDev*sqrt(2*PI)));
+	for (i=0;i<array.size()-1;i++){
+		lookupIndex = round(getLookupIndex(i, mean, StdDev));
+		array[i] += factor*gaussianLookupTable[lookupIndex];
+	}
+	//printf("ADDED GAUSSIAN SHAPE %i\n", (int)array.size());
+}
+
+double DynamicVector::getLookupIndex(const int& i, const double& mean, const double& StdDev){
+	
+	double Z = ((double)i - mean)/StdDev;
+	double lookupIndex = Z*gaussianLookupStdDev + gaussianLookupMean;
+	
+	if (lookupIndex < 0)
+		lookupIndex = 0;
+	
+	if (lookupIndex >= GAUSSIAN_LOOKUP_LENGTH)
+		lookupIndex = GAUSSIAN_LOOKUP_LENGTH-1;
+	
+//	(i - mean)*(i-mean)*(GAUSSIAN_LOOKUP_LENGTH*GAUSSIAN_LOOKUP_LENGTH/16.0)/(StdDev*StdDev);
+	return lookupIndex;
+}
+
+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(const double& value){
+	for (int i=0;i<array.size();i++){
+		array[i] += value;
+	}
+}
+
+
+void DynamicVector::addToIndex(const int& index, const double& constant){
+	array[index] += constant;
+}
+
+
+double DynamicVector::getIndexInRealTerms(const int& index){
+	if (index < arraySize)
+		return (offset + scalar*index);
+	else
+		return 0;
+}
+
+double DynamicVector::getRealTermsAsIndex(double value){
+	value -= offset;
+	value /= scalar;
+	
+	return value;
+	
+}
+
+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){
+
+		
+		double stepSize = ofGetWidth() / (double)(maxIndex - minIndex);
+		double screenHeight = (double) ofGetHeight();
+		double maxVal = getMaximum();
+	
+		int startInt = max(1,minIndex+1);
+		int endInt = min(maxIndex, (int)array.size());
+		double heightConstant = screenHeight / maxVal;
+		int lastHeightPixel = heightConstant * (maxVal - array[startInt-1]);
+		int newHeightPixel;
+		for (int i = startInt;i < endInt;i++){
+			newHeightPixel = (int) heightConstant * (maxVal - array[i]);
+			ofLine (stepSize*(i-1), lastHeightPixel, stepSize*i, newHeightPixel);
+			lastHeightPixel = newHeightPixel;
+		}
+	
+}
+
+
+void DynamicVector::drawVector(const int& minIndex, const int& maxIndex, ofxWindowRegion window){
+	
+	
+	double stepSize = window.width / (double)(maxIndex - minIndex);
+	double screenHeight = (double) window.height;
+	double maxVal = getMaximum();
+	
+	int startInt = max(1,minIndex+1);
+	int endInt = min(maxIndex, (int)array.size());
+	double heightConstant = screenHeight / maxVal;
+	int lastHeightPixel = heightConstant * (maxVal - array[startInt-1]);
+	int newHeightPixel;
+	for (int i = startInt;i < endInt;i++){
+		newHeightPixel = (int) heightConstant * (maxVal - array[i]);
+		ofLine (window.x+stepSize*(i-1), window.y+lastHeightPixel, window.x+stepSize*i, window.y+newHeightPixel);
+		lastHeightPixel = newHeightPixel;
+	}
+	
+}
+
+
+void DynamicVector::drawConstrainedVector(const int& minIndex, const int& maxIndex, const int& minScreenIndex, const int& maxScreenIndex){
+	//constrain the height and width
+	
+	double stepSize = (maxScreenIndex - minScreenIndex) / (double)(maxIndex - minIndex);//step size in pixels per array bin 
+	double screenHeight = ofGetHeight();
+	double maxVal = getMaximum();
+
+	//OPTIMIZE!! XXX could just add stepsize each time
+	//not add minindex each time
+	int i = max(1,minIndex+1);
+//	ofDrawBitmapString("i = "+ofToString(i)+"  :: screen min: "+ofToString(minScreenIndex + stepSize*(i-minIndex-1)), 20, 640);
+	
+	while ((minScreenIndex + stepSize*(i-minIndex)) < 0)
+		i++;//only draw what is on the screen
+	
+	for ( ; i < min(maxIndex+1, (int)array.size());i++){
+		ofLine (minScreenIndex + (stepSize*(i-minIndex-1)), screenHeight * (1 - array[i-1] / maxVal), 
+				minScreenIndex + (stepSize*(i-minIndex)),	 screenHeight * (1 - array[i] / maxVal) );
+		
+	}
+	
+	ofLine(minScreenIndex, screenHeight, minScreenIndex, screenHeight/2);
+	ofLine(maxScreenIndex, screenHeight, maxScreenIndex, screenHeight/2);
+	
+//	ofDrawBitmapString(ofToString(stepSize, 2)+"  "+ofToString(maxScreenIndex - minScreenIndex, 0), 20, 600);
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bayesianArraySrc/DynamicVector.h	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,71 @@
+/*
+ *  DynamicVector.h
+ *  midiCannamReader
+ *
+ *  Created by Andrew on 18/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+//OPTIMIZE CONSTRAINED VECTOR
+
+#include "stdlib.h"
+#include "ofMain.h"
+#include "ofxWindowRegion.h"
+
+#ifndef _DYNAMIC_VECTOR
+#define _DYNAMIC_VECTOR
+#define GAUSSIAN_LOOKUP_LENGTH 1000000
+
+class DynamicVector{
+public:
+	DynamicVector();
+
+	void createVector(int len);
+	void renormalise();
+	void translateDistribution(int translationIndex);
+	typedef std::vector<double> DoubleVector;
+	DoubleVector array;
+	double getMaximum();
+	double getIntegratedEstimate();
+	double getLookupIndex(const int& i, const double& mean, const double& StdDev);
+	void addGaussianShapeByLookupTable(double& mean, double& StdDev, double factor);
+	double gaussianLookupTable[GAUSSIAN_LOOKUP_LENGTH];
+	double gaussianLookupMean, gaussianLookupStdDev;
+	double integratedEstimate;
+	void updateIntegratedEstimate();
+	void updateLimitedIntegratedEstimate();
+	
+	void drawVector(const int& minIndex, const int& maxIndex);
+	void drawVector(const int& minIndex, const int& maxIndex, ofxWindowRegion window);
+	
+	void drawConstrainedVector(const int& minIndex, const int& maxIndex, const int& minScreenIndex, const int& maxScreenIndex);
+
+	void addConstant(const double& value);
+	void addGaussianShape(const double& mean, const double& stddev, double factor);
+	void addTriangularShape(double mean, double width, double factor);
+	void addToIndex(const int& index, const double& constant);
+	
+	void doProduct(DynamicVector& arrayOne, DynamicVector& arrayTwo);
+		
+	double getIndexInRealTerms(const int& index);
+	double getRealTermsAsIndex(double value);
+	double getValueAtMillis(const double& millis);
+	
+	void printArray();
+	void zero();
+	
+	void copyFromDynamicVector(const DynamicVector& dynamicVec);
+	
+	//variables
+	int length, arraySize;
+	double maximumValue;
+	int MAPestimate;
+	
+	double offset;
+	double scalar;//each array point is this much of the quantity
+	//i.e. array[index] contributes to (offset + scalar*index) in real terms
+
+};
+
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bayesianArraySrc/midiEventHolder.cpp	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,1292 @@
+/*
+ *  midiEventHolder.cpp
+ *  midiCannamReader3
+ *
+ *  Created by Andrew on 19/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+
+//Main file to look at here is newNoteEvent() - this calls everything else to update the Bayesian array
+
+#include "midiEventHolder.h"
+
+#include <iostream>
+#include <fstream>
+#include <assert.h>
+
+midiEventHolder::midiEventHolder(){
+	
+
+	
+//	recordedNoteOnIndex = 0;
+	alignmentPosition = 0;
+	
+	useTempoPrior = false;//puts sine wave round tempo
+	confidenceWeightingUsed = true;
+	newOptimalMethod = true;
+	
+	matchWindowWidth = 16000;//window size for matching in ms 
+	interNoteRange = 1600;//preferred duration
+	//so max here is really four
+	
+	
+	likelihoodWidth = 100;//using 100 is good
+	likelihoodToNoiseRatio = 0.20;//was 0.02 on 18/11/11, changing to give more weight to observations
+									//was 0.08 on 11/12/11 but need more for tempo varn in rwc database
+	
+	bayesStruct.speedLikelihoodNoise = 0.1;//was 0.05
+	bayesStruct.speedDecayWidth = 40;
+	bayesStruct.speedDecayAmount = 10;
+	
+	drawTempoMode = false;
+	//there is option to use MAP estinate or integral in beayesianarraystricture class
+	
+	runningInRealTime = true;
+	bayesStruct.realTimeMode = &runningInRealTime;
+	
+	minimumMatchSpeed = 0.0;
+	maximumMatchSpeed = 2.0;
+	minimumTimeIntervalForTempoUpdate = 150;
+	
+	width = ofGetWidth();
+	height = ofGetHeight();
+	screenWidth= &width;
+	screenHeight = &height;
+	
+	ticksPerScreen = 4000;
+	tickLocation = 0;
+	pulsesPerQuarternote = 240;
+	noteArrayIndex = 0;
+	noteMinimum = 30;
+	noteMaximum = 96;
+
+
+
+
+	
+	speedPriorValue = 1.0;
+	
+	
+	bayesStruct.resetSize(matchWindowWidth);
+	bayesStruct.setPositionDistributionScalar(1);
+	
+	bayesStruct.resetSpeedSize(200);
+	bayesStruct.setRelativeSpeedScalar(0.01);
+	bayesStruct.relativeSpeedPrior.getMaximum();
+	//bayesStruct.simpleExample();
+	
+	
+	speedWindowWidthMillis =  1600;//4000
+
+	noteHeight = (*screenHeight) / (float)(noteMaximum - noteMinimum);
+	
+
+	intervalsToCheck.push_back(1);
+	intervalsToCheck.push_back(2);
+	//intervalsToCheck.push_back(3);
+	intervalsToCheck.push_back(4);
+	intervalsToCheck.push_back(6);
+	intervalsToCheck.push_back(8);
+	intervalsToCheck.push_back(16);
+
+	
+	drawPhaseMode = true;
+	
+	printf("lookup index %f value %f\n", bayesStruct.prior.getLookupIndex(100, 30., 10.0), bayesStruct.prior.gaussianLookupTable[(int)bayesStruct.prior.getLookupIndex(100, 30., 10.0)]);
+}
+
+
+
+void midiEventHolder::reset(){
+	//called when we start playing
+	
+	noteArrayIndex = 0;
+	tickLocation = 0;
+	startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis();
+	bayesStruct.lastEventTime = getTimeNow(0);//ofGetElapsedTimeMillis();
+	numberOfScreensIn = 0;
+//	recordedNoteOnIndex = 0;
+	bayesStruct.setNewDistributionOffsets(0);
+	bayesStruct.posterior.offset = 0;
+	
+	playedEventTimes.clear();
+	playedNoteOnMatrix.clear();
+	matchMatrix.clear();
+	bestMatchIndex = 0;
+	
+	recordedTotalNoteCounterByPitch.clear();
+	recordedTotalNoteCounterByPitch.assign(127,0);
+	totalNoteCounterIndex = 0;
+
+	interNoteIntervals.clear();
+	
+	smoothIndex = 0;
+	smoothPlayPosition = 0.0;
+//	relativeSpeedForSmooth = 1.0;
+//	storedSmoothPlayPosition = smoothPlayPosition;
+//	lastSmoothUpdateTime = getTimeNow(0);
+	
+	printf("reset speed prior is %f\n", speedPriorValue);
+	bayesStruct.resetSpeedToOne();
+	bayesStruct.setSpeedPrior(speedPriorValue);
+	setMatchedNotesBackToFalse();
+
+	periodCounter = 0;
+	for (int i = 0;i < periodValues.size();i++){
+	//	printf("period at %f is %f\n", periodValues[i][2], periodValues[i][1]);
+	}
+/*	if (periodValues.size() > 0){
+		updatePeriodValue(0);// periodValues[0][2];
+		printf("Resetting period to %f , size is %i\n", period,  (int)periodValues.size());
+	}
+*/
+	//period = 500.0;
+}
+
+void midiEventHolder::setMatchedNotesBackToFalse(){
+	for (int i = 0;i < noteOnMatches.size();i++)
+		noteOnMatches[i] = false;
+}
+
+void midiEventHolder::clearAllEvents(){
+	recordedNoteOnMatrix.clear();
+	matchesFound.clear();
+	noteOnMatches.clear();
+	recordedEventTimes.clear();
+	measureVector.clear();
+	//played events:
+	playedEventTimes.clear();
+	playedNoteOnMatrix.clear();
+	matchMatrix.clear();
+	bestMatchFound.clear();
+	periodValues.clear();
+	
+	beatPositions.clear();
+	
+	recordedTotalNoteCounterByPitch.clear();
+	recordedTotalNoteCounterByPitch.assign(127, 0);
+	totalNoteCounterIndex = 0;
+}
+
+void midiEventHolder::printNotes(){
+	printf("RECORDED MATRIX\n");
+	for (int i = 0;i < recordedNoteOnMatrix.size();i++){
+		printf("ticktime %i :: pitch %i @ millis %f\n", recordedNoteOnMatrix[i][0], recordedNoteOnMatrix[i][1], recordedEventTimes[i]);
+	}
+}
+
+
+double midiEventHolder::getEventTimeTicks(double millis){
+	return 0.0;
+	//return (millis * pulsesPerQuarternote / period);
+}
+
+double midiEventHolder::getEventTimeMillis(double ticks){
+	return (period * ticks / (double) pulsesPerQuarternote);
+}
+
+void midiEventHolder::newNoteOnEvent(int pitch, int velocity, double timePlayed){
+//	tempoSpeedString = "";
+	
+	//MOVE INTO BAYESSTRUCT?? XXX
+	//bayesStruct.copyPriorToPosterior();
+	//why was this here??
+	bayesStruct.prior.copyFromDynamicVector(bayesStruct.posterior);//try the otehr way
+	//bayesStruct.copyPriorToPosterior();
+	//need to get new MAP position and set the offset of the arrays
+	//currently bestEstimate is the approx for the new MAP position
+	
+	lastPlayedPitch = pitch;
+	//add the new event to our played information matrix
+	IntVector v;
+	v.push_back(pitch);
+	v.push_back(velocity);
+	playedNoteOnMatrix.push_back(v);
+
+	
+	//would update the arrays at this point to show where out current location (phase) and tempo is.
+//	double timeNow = ofGetElapsedTimeMillis() - startTime;
+	double timeNow = timePlayed;// - startTime;
+	recentNoteOnTime = timePlayed;
+	
+//	printf("Max time %f OF time %f \n", timePlayed, timeNow);
+	
+	playedEventTimes.push_back(timePlayed);
+	
+//	double timeDifference = ofGetElapsedTimeMillis() - bayesStruct.lastEventTime; 
+	double timeDifference = timePlayed - bayesStruct.lastEventTime; 
+	
+	//printf("note %i played at %f and last event %f time difference %f and current best estmate %f\n", pitch, timePlayed, bayesStruct.lastEventTime, timeDifference, bayesStruct.bestEstimate);
+
+	//addnoise to the tempo distribution
+	//bayesStruct.decaySpeedDistribution(timeDifference);
+	
+	if (timeDifference > 50){
+	bayesStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.);
+//	bayesStruct.addTriangularNoiseToSpeedPosterior(timeDifference * 10 / 100.);
+	}
+	
+//	bayesStruct.updateTmpBestEstimate(timeDifference);// debug - didnt work	bayesStruct.bestEstimate = bayesStruct.tmpBestEstimate;
+	bayesStruct.updateBestEstimate(timeDifference);
+
+	bayesStruct.lastBestEstimateUpdateTime = getTimeNow(timePlayed);
+	//updatePeriodValue(bayesStruct.lastBestEstimateUpdateTime);
+
+//	double newMAPestimateTime = bayesStruct.posterior.getIndexInRealTerms(bayesStruct.posterior.MAPestimate);
+	//was offset + bayesStruct.posterior.MAPestimate; but this doesnt include scalar to convert to millis
+
+	timeString = "Pitch:"+ofToString(pitch);
+	timeString += ", time now:"+ofToString(timeNow, 1);
+	timeString += "  TD "+ofToString(timeDifference, 1);
+	timeString += "  offset "+ofToString(bayesStruct.posterior.offset , 0);
+	timeString += " map Est: "+ofToString(bayesStruct.posterior.MAPestimate, 0); 
+//	timeString += " Previous time" + ofToString(newMAPestimateTime,0);
+	timeString += " speedMap "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 2);
+	timeString += " :: "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 2);
+	
+//	newMAPestimateTime += (timeDifference * bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
+//	timeString += " :  Predicted MAP time" + ofToString(newMAPestimateTime,0);
+
+	//then we recalculate the window start based on MAP being central
+	//then we do the matches on these and the likelihood on these.
+	
+	bayesStruct.setNewDistributionOffsets(max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2)));
+//	bayesStruct.prior.offset = max(0.,newMAPestimateTime - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
+	
+	timeString += " \n :  new offset " + ofToString(bayesStruct.prior.offset , 0);
+	timeString += " \n best estimate "+ofToString(bayesStruct.bestEstimate, 1);
+	timeString += " error "+ofToString(minimumMatchError, 0);
+	timeString += " map "+ofToString(bayesStruct.relativeSpeedPosterior.integratedEstimate, 1);
+	timeString += " rel speed "+ofToString(bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.integratedEstimate), 2);
+	
+	
+	//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);
+
+	
+	timeString += " new OFF "+ofToString(bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2), 1);
+	timeString += " notearrayindex "+ofToString(noteArrayIndex, 0);
+	//when this is off teh screen there is a problem somehow XXX
+	
+	bayesStruct.posterior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));//	bayesStruct.prior.offset = max(0., bayesStruct.bestEstimate - (bayesStruct.prior.scalar*bayesStruct.prior.arraySize/2));
+
+	//trying to switch to prior
+	
+	
+	bayesStruct.lastEventTime = timePlayed;//bayesStruct.lastEventTime = ofGetElapsedTimeMillis();
+	
+	//do the cross update to find current posterior for location
+//	totalConfidence= 0;
+	int numberOfMatchesFound = findLocalMatches(pitch);
+	setMatchLikelihoods(numberOfMatchesFound);
+	bayesStruct.calculatePosterior();
+	
+	if (recordedEventTimes.size() > 0){
+	updateTempo();
+	//calcuateNewInterNoteIntervals();
+	}
+	
+	//storedSmoothPlayPosition = smoothPlayPosition;
+	 
+}
+
+void midiEventHolder::updateTempo(){
+	//having found matches we have matches for new note and matches for previous notes
+	if (newOptimalMethod)
+		findOptimumTempoPairsToCurrentBestMatch();
+	else if (!confidenceWeightingUsed)
+		findLocalTempoPairs();
+	else
+		findLocalTempoPairsWeightedForConfidence();
+	
+	
+	//bayesStruct.addGaussianNoiseToSpeedPosterior(10);
+}
+
+double midiEventHolder::getTimeNow(double eventTime){
+	double timeNow = eventTime;
+	if (runningInRealTime)
+		timeNow = ofGetElapsedTimeMillis();
+	return timeNow;
+}
+
+int midiEventHolder::findLocalMatches(int notePitch){
+
+	//here we find the matches to the new note within appropriate range
+		
+	matchString = "";
+	
+	windowStartTime = max(0.0,(bayesStruct.bestEstimate - matchWindowWidth/2));//was playPositionInMillis
+//	cout << "best estimate is " << bayesStruct.bestEstimate << endl;
+	int numberOfMatches = findMatch(notePitch, windowStartTime, windowStartTime + matchWindowWidth);
+
+	
+	//matchString += " pitch: "+ofToString(notePitch)+" matches "+ofToString(numberOfMatches)+" win start "+ofToString(windowStartTime);	
+	
+	return numberOfMatches;
+	
+	
+}
+
+
+void midiEventHolder::setMatchLikelihoods(int numberOfMatches){
+//reset the offset to match the prior
+	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);
+		//this is the vent time since start of file
+		if (recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset < bayesStruct.likelihood.arraySize){
+	//		double confidenceMeasure = 0;
+	//		if (totalConfidence > 0)
+	//			confidenceMeasure =	bayesStruct.posterior.getValueAtMillis(recordedEventTimes[matchesFound[i]])/totalConfidence;
+			
+			bayesStruct.likelihood.addGaussianShape(recordedEventTimes[matchesFound[i]] - bayesStruct.likelihood.offset, likelihoodWidth,  quantity);//* confidenceMeasure
+		}//end if
+	}
+	bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length);
+}
+
+int midiEventHolder::findMatch(const int& notePitch, const int& startTime, const int& endTime){
+
+	matchesFound.clear();
+	int startIndex = 0;
+
+	if (recordedEventTimes.size() > 0){
+	
+		//get to the right range of events to check in
+		while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < startTime)
+			startIndex++;
+		   
+		}
+
+	IntVector v;
+	DoubleVector d;
+	double tmpError = 100000.;//v high error
+	
+	double minimumConfidence = 0;
+	while (startIndex < recordedEventTimes.size() && recordedEventTimes[startIndex] < endTime){
+		if (recordedNoteOnMatrix[startIndex][1] == notePitch){
+			
+			matchesFound.push_back(startIndex);
+			v.push_back(startIndex);
+			//so startIndex is registered as a match
+			
+			double eventConfidence = bayesStruct.posterior.getValueAtMillis(recordedEventTimes[startIndex]);
+				if (eventConfidence > minimumConfidence){
+					minimumConfidence = eventConfidence;
+					bestMatchIndex = startIndex;
+				}
+			d.push_back(eventConfidence);
+			
+			double confidence = eventConfidence;//bayesStruct.posterior.getValueAtMillis(mouseX);
+	//																   recordedEventTimes[startIndex]);
+	//		matchString += "["+ofToString(startIndex)+"] = "+ofToString(confidence, 3)+" .";
+			
+			if (abs(recordedEventTimes[startIndex] - bayesStruct.bestEstimate) < tmpError){
+				//record the error between expected and observed times
+				tmpError = abs(recordedEventTimes[startIndex] - bayesStruct.bestEstimate);
+				minimumMatchError = tmpError;//recordedEventTimes[startIndex] - bayesStruct.bestEstimate;
+			}
+			
+		}
+		startIndex++;
+	}
+	
+
+//	printf("%i MATCHES TO Note %i found\n", (int)matchesFound.size(), notePitch);
+	int size = matchesFound.size();
+		if (size > 0)
+		noteOnMatches[bestMatchIndex] = true;
+	
+	v.insert(v.begin() , (int)size);//at beginning, we list how many matches there are that we have found
+	d.insert(d.begin() , (double)size);
+	
+	//v.push_back(size);
+	//d.push_back(size);
+	//for (int i = 0;i < matchesFound.size()+1;i++){
+	//	v.push_back(matchesFound[i]);
+	//	printf("match %i,[%i] is %i\n", startIndex, i, v[i]);	
+	//}
+	 
+	
+	matchMatrix.push_back(v);
+	matchConfidence.push_back(d);
+	
+	//bringing in way to list only the best matches and use these in tempo process
+	bestMatchFound.push_back(bestMatchIndex);
+	
+//	printf("BEST MATCH TO note %i, start time %i, endtime %i, time %i is recorded time %i, confidence %0.2f\n", notePitch, startTime, endTime, (int) recordedEventTimes[bestMatchIndex], minimumConfidence);
+	
+	return size;
+}
+
+bool midiEventHolder::checkIfMatchedNote(const int& tmpIndex){
+	for (int i = 0;i < matchesFound.size();i++){
+	if (matchesFound[i] == tmpIndex)
+		return true;
+	}
+	return false;
+}
+
+
+
+void midiEventHolder::findLocalTempoPairs(){
+	
+	int currentPlayedIndex = playedNoteOnMatrix.size()-1;
+	//	printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]);
+	//	printMatchesFound();
+	//	printMatchMatrix();
+	//	printf("possible notes \n");
+	bool needToUpdate = false;
+	bayesStruct.setLikelihoodToConstant();
+	
+	
+	for (int i = 0;i < matchMatrix[currentPlayedIndex][0];i++){
+		//iterate through the recently matched events - even dodgy matches included
+		//size, index of match0, index of match1, ....
+		
+		
+		int recordedCurrentIndex = matchMatrix[currentPlayedIndex][i+1];
+		
+		int previousIndex = currentPlayedIndex-1;
+
+		
+		while (previousIndex >= 0 && playedEventTimes[previousIndex] + speedWindowWidthMillis > playedEventTimes[currentPlayedIndex]) {
+			double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
+			
+			for (int k = 0;k < matchMatrix[previousIndex][0];k++){
+				
+				int recordedPreviousIndex = matchMatrix[previousIndex][k+1];
+				
+				double recordedTimeDifference = recordedEventTimes[recordedCurrentIndex] - recordedEventTimes[recordedPreviousIndex];
+				
+				
+				//we want the speed of the recording relative to that of the playing live
+				
+				double speedRatio = recordedTimeDifference / playedTimeDifference;
+				if (recordedTimeDifference > minimumTimeIntervalForTempoUpdate &&
+					speedRatio <= maximumMatchSpeed && speedRatio >= minimumMatchSpeed){
+					
+					//adding in a prior that prefers 1
+					double priorWeighting = 1;
+					if (useTempoPrior)
+						priorWeighting = sin(speedRatio * PI/2);
+					
+					
+					
+					/*
+					 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
+					double amount =	(1-bayesStruct.speedLikelihoodNoise)/10;
+					amount *= priorWeighting;
+					bayesStruct.updateTempoLikelihood(speedRatio, amount);
+				//	tempoSpeedString += ofToString(recordedPreviousIndex) + "  "+ ofToString(speedRatio, 2) + "  "+ofToString(amount, 2) += " \n";
+					needToUpdate = true;
+				}
+				//		printf("\n");	
+			}
+			
+			previousIndex--;
+		}//end while previousindex countdown
+	}//end for loop through possible current matches
+	
+	if (needToUpdate)
+		bayesStruct.updateTempoDistribution();
+	
+	//printf("current speed is %f\n", bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate));
+}
+
+
+void midiEventHolder::findLocalTempoPairsWeightedForConfidence(){
+	bool needToUpdate = false;
+	
+	DoubleVector speedIntervalsFound;
+	
+	//adapted this to just use the best match for each note
+	
+	int currentPlayedIndex = playedNoteOnMatrix.size()-1;
+	//	printf("played %i : %i, vel %i\n", currentPlayedIndex, playedNoteOnMatrix[currentPlayedIndex][0], playedNoteOnMatrix[currentPlayedIndex][1]);
+	//	printMatchesFound();
+	//	printMatchMatrix();
+	//	printf("possible notes \n");
+	
+	bayesStruct.setLikelihoodToConstant();
+	
+	int recordedCurrentIndex = bestMatchFound[currentPlayedIndex];
+	//we only look at intervals between the current best match and other recent best matched notes
+	//that is the difference in confidence method
+	
+	
+		//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;
+				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));
+}
+
+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;
+	
+	double currentSpeedEstimate = bayesStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesStruct.relativeSpeedPosterior.MAPestimate);
+	
+	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 - matchWindowWidth){
+			
+			checkRecordedCurrentIndex--;
+		}
+		
+		double bestSpeedEstimate = getBestSpeedEstimate(currentPlayedIndex, bestMatchIndex);
+		
+		while (checkRecordedCurrentIndex < recordedEventTimes.size() && recordedEventTimes[checkRecordedCurrentIndex] <  recordedTimeOfBestMatch + matchWindowWidth ){
+			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-currentSpeedEstimate) < abs(speedRatio - currentSpeedEstimate) ){
+							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::calcuateNewInterNoteIntervals(){
+	DoubleVector v;
+	
+	int currentPlayedIndex = playedNoteOnMatrix.size()-1;
+//	int recordedCurrentIndex = bestMatchFound[currentPlayedIndex];
+	int previousIndex = currentPlayedIndex-1;
+	
+	//withing speedwindow i.e. 4 seconds
+	while (previousIndex >= 0 && playedEventTimes[previousIndex] + interNoteRange > playedEventTimes[currentPlayedIndex]) {
+		
+		double playedTimeDifference = playedEventTimes[currentPlayedIndex] - playedEventTimes[previousIndex];
+		
+		checkForCorrectInterval(playedTimeDifference, &v);
+			
+		previousIndex--;
+	}
+	
+	if (v.size() > 0)
+		interNoteIntervals.push_back(v);
+	//printf("\n");
+}
+
+void midiEventHolder::checkForCorrectInterval(const double& playedTimeDifference, DoubleVector* v){
+	double intervalDuration = 0.0;
+
+	for (int intervalIndex = 0;intervalIndex < 3;intervalIndex++){
+		//on;y check 1,2 and 4
+		double possibleDuration = playedTimeDifference / intervalsToCheck[intervalIndex];
+		if (possibleDuration >= 200 && possibleDuration < 400){
+			v->push_back(possibleDuration);
+		//	printf("int %f / %i :: %f  ", playedTimeDifference,  intervalsToCheck[intervalIndex], possibleDuration);
+		}
+	}
+}
+
+
+void midiEventHolder::updatePlayPosition(){
+	//timeDifference = ofGetElapsedTimeMillis() - startPlayingTime;//elpased 
+	
+	//in actual fact if we are changing the speed of the play position 
+	//we will need to update this via the file
+	
+	//actually time since beginning of file i think
+	
+	double timeDifference = 0;
+	
+	if (runningInRealTime){
+		
+		bayesStruct.updateBestEstimate(timeDifference);
+		//	bayesStruct.updateTmpBestEstimate(timeDifference);
+	}
+	
+	
+	
+	if (smoothPlayPosition < bayesStruct.bestEstimate){
+		updateSmoothPositionTo(bayesStruct.bestEstimate);
+		//smoothPlayPosition = bayesStruct.bestEstimate;
+	}
+	
+//	playPositionInMillis = timeDifference;//based on updating from when we change period
+	//this to be added
+
+	
+	//this is time diff in milliseconds
+	//then we have 
+	double quarterNoteIntervals = (timeDifference / period);
+	tickLocation = quarterNoteIntervals * pulsesPerQuarternote; 
+	
+	updateNoteCounter();
+	
+}
+
+void midiEventHolder::updateSmoothPositionTo(const double& newPosition){
+	//smooth play position was where we last outputted notes from.
+	//checking index is there to make sense.
+	while (smoothIndex > 0 && recordedEventTimes[smoothIndex] > smoothPlayPosition){
+		smoothIndex--;
+		//printf("going backewaers on smooth, ");
+	}
+	while (smoothIndex < recordedEventTimes.size()-1 && recordedEventTimes[smoothIndex] < smoothPlayPosition){
+		smoothIndex++;
+		//printf("outputting  smooth\n ");
+	}
+	
+
+	double playingTime = ofGetElapsedTimeMillis();
+	playingTime -= startPlayingTime;
+	//now at the last one
+	
+	float smoothLocation = beatPositions[smoothIndex];
+	int currentNote = recordedNoteOnMatrix[smoothIndex][1];
+	
+	while (smoothIndex < recordedEventTimes.size() && recordedEventTimes[smoothIndex] < newPosition){
+		float annotationTime = 0;
+		float annotationLocation = 0;
+		int annotationTick = 0;
+		int annotationNote = 0;
+		float difference = 10000;//very big
+		float currentLocationDifference = 1.0;
+		float range = 1.0;
+/*		if (smoothIndex < myNotation.rwcAnnotations.size()){
+			//add in test here to find closest matching note
+			
+		
+			annotationTime = myNotation.rwcAnnotations[smoothIndex].eventTime;
+			annotationNote = myNotation.rwcAnnotations[smoothIndex].midiNote;
+			annotationLocation = myNotation.rwcAnnotations[smoothIndex].beatLocation;
+			annotationTick = round(annotationLocation*480.0);
+		}else{
+			printf("No annotaion size %i\n", (int)myNotation.rwcAnnotations.size());
+		}
+		*/
+		difference = playingTime - (annotationTime*1000.0);
+		/*
+		if ((*fileOutput).is_open()){
+			(*fileOutput) << fixed << beatPositions[smoothIndex] <<",\t" <<  recordedNoteOnMatrix[smoothIndex][1] << ",\t";
+			(*fileOutput) << playingTime ;
+			
+				if ( recordedNoteOnMatrix[smoothIndex][1] == annotationNote){
+					(*fileOutput) << " corresponds to " << annotationTime;
+				}
+			(*fileOutput) << " \n";
+
+		}
+		 */
+	
+		printf("annotaions: rec tick time %i vs %i midi %i beat pos %f playing time now at %f :: annotaion %i loc % f time %f diff \t%f ms\n",  
+			   recordedNoteOnMatrix[smoothIndex][0], annotationTick, recordedNoteOnMatrix[smoothIndex][1], 
+			   beatPositions[smoothIndex], playingTime, 
+			   annotationNote, annotationLocation, annotationTime, difference);
+		
+//		assert(annotationNote == recordedNoteOnMatrix[smoothIndex][1]);
+	assert(annotationTick == recordedNoteOnMatrix[smoothIndex][0]);
+	
+	/*	
+		if ((*differenceOutput).is_open()){
+			(*differenceOutput) << beatPositions[smoothIndex] << "," << difference << "\n";
+		//	printf("midi %i beat pos %f playing time now at %f :: annotaion %i loc % f time %f diff \t%f ms\n",  
+		//		   recordedNoteOnMatrix[smoothIndex][1], 
+		//		   beatPositions[smoothIndex], playingTime, 
+		//		   annotationNote, annotationLocation, annotationTime, difference);
+		}else{
+			printf("file not open\n");
+		}
+	*/	
+		smoothIndex++;
+	}
+	
+		
+	smoothPlayPosition = newPosition;
+		
+}
+
+
+void midiEventHolder::updatePeriodValue(const double& millis){
+
+	double tmp = period;
+/*	
+	while (periodCounter >= 0 && periodCounter < periodValues.size()-1 && periodValues[periodCounter][2] < millis){
+		periodCounter++;
+	}
+	while (periodCounter > 0 && periodValues[periodCounter][2] > millis){
+		periodCounter--;
+	}
+ */
+	//period = periodValues[periodCounter][1];
+	
+	if (period != tmp){
+		printf("new period at %f of %f\n", millis, period);
+	}
+}
+
+void  midiEventHolder::updateNoteCounter(){
+	while (totalNoteCounterIndex < bestMatchIndex){
+		int tmpPitch = recordedNoteOnMatrix[totalNoteCounterIndex][1];
+		recordedTotalNoteCounterByPitch[tmpPitch] += 1;
+		totalNoteCounterIndex++;
+	}
+}
+
+
+void midiEventHolder::drawMidiFile(){
+	
+	//draws midi file on scrolling screen
+	int size = recordedNoteOnMatrix.size();
+	if (size > 0){
+		
+		numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in
+		
+		//	numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down
+		timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen);
+		
+		while (noteArrayIndex < recordedNoteOnMatrix.size()-1 && tickLocation > recordedNoteOnMatrix[noteArrayIndex][0] )
+			noteArrayIndex++;
+		
+		
+		while (noteArrayIndex > 0 && noteArrayIndex < size && tickLocation < recordedNoteOnMatrix[noteArrayIndex][0])
+			noteArrayIndex--;
+		
+		//need to start where we currently are in file
+		int maxNoteIndexToPrint	= noteArrayIndex;
+		int minNoteIndexToPrint = min(size-1,noteArrayIndex);//not needed as changed above
+		
+		while (maxNoteIndexToPrint < recordedNoteOnMatrix.size() && recordedNoteOnMatrix[maxNoteIndexToPrint][0] < (numberOfScreensIn+1)*ticksPerScreen )
+			maxNoteIndexToPrint++;
+		
+		while (minNoteIndexToPrint > 0 && recordedNoteOnMatrix[minNoteIndexToPrint][0] > numberOfScreensIn*ticksPerScreen)//&& minNoteIndexToPrint < size 
+			minNoteIndexToPrint--;
+		
+		for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)recordedNoteOnMatrix.size());tmpIndex++){
+			
+			ofSetColor(255,255,255);
+			if (checkIfMatchedNote(tmpIndex))
+				ofSetColor(100,100,100);//0,0,255);
+			else if(noteOnMatches[tmpIndex]){
+				ofSetColor(255,0,255);//dark grey
+			}
+			else{
+				ofSetColor(255,255,255);//255,255,255);
+			}
+			
+			//ofSetColor(255,255,255);
+			if (tmpIndex == bestMatchIndex)
+				ofSetColor(255,0,0);//best recent match is in red
+			
+			//		 XXX replace ofgetwidth below
+			//if (tmpIndex >= 0 && tmpIndex < size)
+			int xLocation = (float)(recordedNoteOnMatrix[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
+			int duration = (float)(recordedNoteOnMatrix[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen;
+			
+			
+			int yLocation = (*screenHeight) - ((recordedNoteOnMatrix[tmpIndex][1] - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));						 
+			ofRect(xLocation,yLocation, duration,  noteHeight);
+			
+		}
+		
+		
+		int xLocation;// = getLocationFromTicks(tickLocation);
+		//	ofLine(xLocation, 0, xLocation, (*screenHeight));
+		
+		//orange line at best estimate
+		xLocation = getLocationFromMillis(bayesStruct.bestEstimate);
+		ofSetColor(250,250,20);//250,100,0);
+		ofLine(xLocation, 0, xLocation, (*screenHeight));
+		
+		xLocation = getLocationFromMillis(smoothPlayPosition);//bayesStruct.tmpBestEstimate
+		ofSetColor(0,250,0);//250,150, 250,100,0);
+		ofLine(xLocation, 0, xLocation, (*screenHeight));
+		
+		
+		//lines where matching window start and end are 
+		ofSetColor(0);//0,100,255);
+		xLocation = getLocationFromMillis(windowStartTime);
+		ofLine(xLocation, 0, xLocation, (*screenHeight));
+		xLocation = getLocationFromMillis(windowStartTime+matchWindowWidth);
+		ofLine(xLocation, 0, xLocation, (*screenHeight));
+		
+		
+		int maxSize = recordedNoteOnMatrix[size-1][0];
+		
+		int tmpIndex = 0;
+		while (tmpIndex < measureVector.size() && measureVector[tmpIndex] < (numberOfScreensIn+1)*ticksPerScreen){
+			int measureLocation = measureVector[tmpIndex];
+		int xLocation = (float)(measureLocation - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
+			ofSetColor(155,155,0);
+			ofLine(xLocation, 0, xLocation, (*screenHeight));
+			tmpIndex++;
+		}
+		
+		
+	//	ofDrawBitmapString(tempoSpeedString, 20, 20);
+	/*	string indexString = "num screens in "+ofToString(numberOfScreensIn)+"; min index to print "+ofToString(minNoteIndexToPrint)+", max index to print "+ofToString(maxNoteIndexToPrint);
+		indexString += " size "+ofToString(size)+" tick loc "+ofToString(tickLocation)+" max size "+ofToString(maxSize);
+		ofDrawBitmapString(indexString, 20, 40);
+	 */
+	}	
+	
+	//ofDrawBitmapString(ofToString(timeOffsetForScreen, 1), 20,20);
+	
+	//ofDrawBitmapString(timeString, 20, 60);
+	
+//last played piutch
+	ofSetColor(0,200,0,50);
+	int yLocation = (*screenHeight) - ((lastPlayedPitch - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));						 
+	ofRect(0,yLocation, 100,  noteHeight);
+	
+	
+	
+}
+
+
+
+void midiEventHolder::drawMidiFile(IntMatrix& midiFileToDraw){
+	
+	//using this to draw the live input
+	
+	//draws midi file on scrolling screen
+	int size = midiFileToDraw.size();
+	if (size > 0){
+		
+		numberOfScreensIn = floor(bayesStruct.bestEstimate / getEventTimeMillis(ticksPerScreen));//rpounds down on no screens in
+		
+		//	numberOfScreensIn = tickLocation / ticksPerScreen;//rounds down
+		timeOffsetForScreen = getEventTimeMillis(numberOfScreensIn * ticksPerScreen);
+		
+		while (noteArrayIndex < midiFileToDraw.size()-1 && tickLocation > midiFileToDraw[noteArrayIndex][0] )
+			noteArrayIndex++;
+		
+		
+		while (noteArrayIndex > 0 && noteArrayIndex < size && tickLocation < midiFileToDraw[noteArrayIndex][0])
+			noteArrayIndex--;
+		
+		//need to start where we currently are in file
+		int maxNoteIndexToPrint	= noteArrayIndex;
+		int minNoteIndexToPrint = min(size-1,noteArrayIndex);//not needed as changed above
+		
+		while (maxNoteIndexToPrint < midiFileToDraw.size() && midiFileToDraw[maxNoteIndexToPrint][0] < (numberOfScreensIn+1)*ticksPerScreen )
+			maxNoteIndexToPrint++;
+		
+		while (minNoteIndexToPrint > 0 && midiFileToDraw[minNoteIndexToPrint][0] > numberOfScreensIn*ticksPerScreen)//&& minNoteIndexToPrint < size 
+			minNoteIndexToPrint--;
+		
+		for (int tmpIndex = max(0,minNoteIndexToPrint);tmpIndex < min(maxNoteIndexToPrint, (int)midiFileToDraw.size());tmpIndex++){
+			
+			ofSetColor(0,0,255, 200);
+
+			int xLocation = (float)(midiFileToDraw[tmpIndex][0] - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen;
+			int duration = (float)(midiFileToDraw[tmpIndex][3]*(*screenWidth))/(float)ticksPerScreen;
+			
+			
+			int yLocation = (*screenHeight) - ((midiFileToDraw[tmpIndex][1] - noteMinimum )*(*screenHeight)/ (float)(noteMaximum - noteMinimum));						 
+			ofRect(xLocation,yLocation, duration,  noteHeight);
+			
+		}
+		
+		
+
+	}	
+	
+	
+	
+}
+
+
+
+void midiEventHolder::drawFile(){	
+		drawMidiFile();
+		
+	ofSetColor(0,0,255);
+	ofDrawBitmapString("period"+ofToString(period, 2), ofGetWidth() - 180, 20);
+	
+//	bayesStruct.drawArrays();
+	
+//	ofSetColor(200,200,0);
+//	bayesStruct.prior.drawConstrainedVector(0, bayesStruct.prior.arraySize, 400, 800);
+	
+	//need to draw arrays within correct timescope
+	if (drawPhaseMode)
+	bayesStruct.drawArraysRelativeToTimeframe(timeOffsetForScreen, timeOffsetForScreen + getEventTimeMillis(ticksPerScreen));
+	
+	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);
+	
+	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);							   
+*/
+	
+	//drawInterNoteIntervals();
+	
+ }
+
+void midiEventHolder::drawInterNoteIntervals(){
+	
+	ofSetColor(0,0,150);
+	int size = interNoteIntervals.size();
+	int numberToShow = min(100, size);
+	double x ;
+	for (int y = 1;y < numberToShow;y++){
+		for (int point = 0;point < interNoteIntervals[y].size();point++){
+			double interval = interNoteIntervals[size - y][point];
+			x = interval - 200;
+			x *= (*screenWidth) / 200.0;
+		}
+		double h = (double)(y * (*screenHeight)) / numberToShow;
+		ofCircle(x, h, 5);
+	}
+	
+}
+
+
+void midiEventHolder::printInterNoteIntervals(){
+
+	int size = interNoteIntervals.size();
+	int numberToShow = 20;
+	double x ;
+	for (int y = max(0, size - numberToShow);y < interNoteIntervals.size();y++){
+		for (int point = 0;point < interNoteIntervals[y].size();point++){
+			printf("[%i][%i] : %f", y, point, interNoteIntervals[y][point]);
+			}
+				   printf("\n");
+	}			   
+	
+}
+
+int midiEventHolder::getLocationFromTicks(double tickPosition){
+	return 0;
+//	return (int)((float)(tickPosition - numberOfScreensIn*ticksPerScreen)*(*screenWidth)/(float)ticksPerScreen);
+//not used
+}
+
+int midiEventHolder::getLocationFromMillis(double millisPosition){
+	//(getEventTimeTicks(windowStartTime+matchWindowWidth) - numberOfScreensIn*ticksPerScreen)*(*screenWidth) / (double)ticksPerScreen
+	return (millisPosition - timeOffsetForScreen)*(*screenWidth)/getEventTimeMillis(ticksPerScreen);
+}
+
+
+void midiEventHolder::exampleCrossUpdate(){
+	
+	bayesStruct.crossUpdateArrays(bayesStruct.posterior, bayesStruct.relativeSpeedPosterior, 200);
+	
+}
+
+
+void midiEventHolder::setStartPlayingTimes(){
+	startPlayingTime = getTimeNow(0);//ofGetElapsedTimeMillis();
+	//startTime = startPlayingTime;
+	printf("starting playing at time %f\n", startPlayingTime);
+/*	
+ 	bayesStruct.lastEventTime = 0;//ofGetElapsedTimeMillis();
+	bayesStruct.bestEstimate = 0;
+	bayesStruct.resetArrays();
+	bayesStruct.lastBestEstimateUpdateTime = ofGetElapsedTimeMillis();
+*/
+	bayesStruct.setStartPlaying();
+	matchString = "";
+}
+
+
+void midiEventHolder::printMatchMatrix(){
+	printf("match matrix:\n");
+	for (int i = 0;i < matchMatrix.size();i++){
+		for (int k = 0;k < matchMatrix[i].size();k++){
+			printf("%i , ", matchMatrix[i][k]);
+		}
+		printf("\n");
+	}
+	
+}
+
+
+
+void midiEventHolder::printRecordedEvents(){
+	printf("Recorded Events:\n");
+	for (int i = 0;i < recordedNoteOnMatrix.size();i++){
+		for (int k = 0;k < recordedNoteOnMatrix[i].size();k++){
+			printf("[%i] = %i ,", i, recordedNoteOnMatrix[i][k]);
+		}
+		if (i < recordedEventTimes.size())
+			printf("time %f \n", recordedEventTimes[i]);
+		else
+			printf("\n");
+	}
+	
+}
+
+
+
+void midiEventHolder::reorderMatrixFromNoteTimes(IntMatrix& noteOnMatrix){
+	double currentTime = -19999.;
+	for (int i = 0;i < noteOnMatrix.size();i++){
+		int nextIndex = getIndexOfMinimumAboveTime(currentTime, noteOnMatrix);
+	//	cout << "index of min time " << currentTime << " is " << nextIndex << " at time " <<  noteOnMatrix[nextIndex][0] << endl;
+	
+		if (nextIndex >= 0 && nextIndex > i &&	noteOnMatrix[nextIndex][0] < noteOnMatrix[i][0] ){
+			//which it should be
+	//		cout << " index " << nextIndex << " at time " << noteOnMatrix[nextIndex][0] << " swaps with inex " << i << " at time  " << noteOnMatrix[i][0] << endl; 
+			noteOnMatrix[i].swap(noteOnMatrix[nextIndex]);
+		//	double tmp = beatPositions[i];
+		//	beatPositions[i] = beatPositions[nextIndex];
+		//	 = tmp; 
+		
+				swap (beatPositions[i], beatPositions[nextIndex]);
+			
+			
+			currentTime = noteOnMatrix[i][0];
+		}
+		
+	}	
+	//printRecordedEvents();
+
+}
+
+
+
+
+void midiEventHolder::doublecheckOrder(IntMatrix& noteOnMatrix){
+
+	for (int i = 0;i < noteOnMatrix.size();i++){
+		int nextIndex = getIndexOfMinimumAboveIndex(i, noteOnMatrix);
+		if (nextIndex > i){
+			noteOnMatrix[i].swap(noteOnMatrix[nextIndex]);
+			swap (beatPositions[i], beatPositions[nextIndex]);
+			
+		}
+	}	
+}
+
+int midiEventHolder::getIndexOfMinimumAboveIndex(const int& index, IntMatrix& noteOnMatrix){
+	int returnIndex = index;
+	int min = noteOnMatrix[index][0];
+	for (int i = index;i < noteOnMatrix.size();i++){
+		if (noteOnMatrix[i][0] < min){
+			returnIndex = i;
+			min = noteOnMatrix[i][0];
+		}
+	}
+	return returnIndex;
+}
+
+
+int midiEventHolder::getIndexOfMinimumAboveTime(const double& time, IntMatrix& noteOnMatrix){
+	int index = 0;
+	double minimumTime = 100000000.;
+	int bestIndex = -1;
+	while (index < noteOnMatrix.size()){
+	
+		if (noteOnMatrix[index][0] > time && noteOnMatrix[index][0] < minimumTime){
+			bestIndex = index;
+			minimumTime = noteOnMatrix[index][0];
+		}
+			index++;
+	}
+	return bestIndex;
+}
+
+
+
+
+void midiEventHolder::correctTiming(IntMatrix& noteOnMatrix){
+	
+	if (noteOnMatrix.size() > 0 && noteOnMatrix[0][0] < 0) {
+		int offset = noteOnMatrix[0][0];
+		for (int i = 0;i < noteOnMatrix.size();i++){
+			noteOnMatrix[i][0] -= offset;
+		}	
+	}
+
+}
+
+
+void midiEventHolder::printNoteCounter(){
+	for (int i = 0;i < recordedTotalNoteCounterByPitch.size();i++){
+		printf("RECORDED TOTAL[%i] := %i", i, recordedTotalNoteCounterByPitch[i]);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/bayesianArraySrc/midiEventHolder.h	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,185 @@
+/*
+ *  midiEventHolder.h
+ *  midiCannamReader3
+ *
+ *  Created by Andrew on 19/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+#ifndef MIDI_EVENT_HOLDER
+#define MIDI_EVENT_HOLDER
+ 
+#include "ofMain.h"
+#include "BayesianArrayStructure.h"
+
+
+class midiEventHolder{
+
+public:
+	
+	midiEventHolder();
+	void printNotes();
+	
+	typedef std::vector<int> IntVector;
+	typedef std::vector<IntVector> IntMatrix;
+	
+	typedef std::vector<bool> BoolVector;
+	
+	typedef std::vector<double> DoubleVector;
+	typedef std::vector<DoubleVector> DoubleMatrix;
+	
+	//the rehearsal version
+	IntMatrix recordedNoteOnMatrix;//note, velocity, duration
+	DoubleVector recordedEventTimes;
+	
+	IntVector matchesFound;
+	BoolVector noteOnMatches;
+	
+	void drawMidiFile(IntMatrix& midiFileToDraw);
+	
+//	int recordedNoteOnIndex;
+	
+	
+	IntMatrix playedNoteOnMatrix;
+	DoubleVector playedEventTimes;
+	int playedNoteIndex;
+	IntMatrix matchMatrix;
+	IntVector bestMatchFound;
+	IntVector measureVector;
+	
+	IntVector recordedTotalNoteCounterByPitch;
+	int totalNoteCounterIndex;
+	
+	DoubleMatrix matchConfidence;
+	double totalConfidence;
+	
+	double mouseX;
+	
+	void clearAllEvents();
+	bool drawTempoMode, drawPhaseMode;
+	
+	double minimumMatchSpeed , maximumMatchSpeed;
+	
+	double period, pulsesPerQuarternote;
+	double getEventTimeMillis(double ticks);
+	double getEventTimeTicks(double millis);
+	
+	int getLocationFromTicks(double tickPosition);
+	int getLocationFromMillis(double millisPosition);
+	
+	double getTimeNow(double eventTime);
+	bool runningInRealTime;
+	
+	double windowStartTime;
+	
+	//functions for finding match to incoming note
+	void newNoteOnEvent(int pitch, int velocity, double timePlayed);
+	int findLocalMatches(int notePitch);
+	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);
+	
+	
+	void 	calcuateNewInterNoteIntervals();
+	
+	double likelihoodWidth;
+	double likelihoodToNoiseRatio;
+	
+	void printMatchMatrix();
+	void printRecordedEvents();
+	void printNoteCounter();
+	void updateNoteCounter();
+	
+	void setMatchLikelihoods(int numberOfMatches);
+	
+	void setStartPlayingTimes();
+	void setSpeedPrior(double speedPriorValue);
+	
+	int width, height;
+	/////
+	string matchString;
+	void updatePlayPosition();
+	
+	DoubleMatrix beatPeriodMatrix;
+	
+	void drawFile();
+	void drawMidiFile();
+	void reset();
+	void setMatchedNotesBackToFalse();
+	
+	int ticksPerScreen;
+	int tickLocation;
+	int numberOfScreensIn;
+	int noteArrayIndex;
+	
+	int matchWindowWidth;
+	
+	int noteMinimum, noteMaximum;
+	int* screenWidth;
+	int* screenHeight;
+	float noteHeight;
+	float tempo;
+	double startPlayingTime;
+	int lastPlayedPitch;
+	
+	//double playPositionInMillis;
+	
+	double timeOffsetForScreen;
+	
+	double recentNoteOnTime;
+	
+	void exampleCrossUpdate();
+	BayesianArrayStructure bayesStruct;
+
+	double speedPriorValue;
+	int bestMatchIndex;
+	string timeString;
+	//double startTime;
+	int speedWindowWidthMillis;
+	
+	bool confidenceWeightingUsed;
+	
+	double minimumMatchError;//recent best error between observed note and aligned midi file
+	
+	void reorderMatrixFromNoteTimes(IntMatrix& noteOnMatrix);
+	int getIndexOfMinimumAboveTime(const double& time, IntMatrix& noteOnMatrix);
+	void correctTiming(IntMatrix& noteOnMatrix);
+	void doublecheckOrder(IntMatrix& noteOnMatrix);
+	int getIndexOfMinimumAboveIndex(const int& index, IntMatrix& noteOnMatrix);
+	bool useTempoPrior;
+	string	tempoSpeedString;
+	int minimumTimeIntervalForTempoUpdate;
+	
+	double ticksFactor;
+	
+	bool newOptimalMethod;
+	DoubleMatrix interNoteIntervals;
+	IntVector intervalsToCheck;
+	void checkForCorrectInterval(const double& playedTimeDifference, DoubleVector* v);
+	void drawInterNoteIntervals();
+	void printInterNoteIntervals();
+	int interNoteRange;
+	DoubleMatrix periodValues;
+	int 	periodCounter;
+	void updatePeriodValue(const double& miupdatesllis);
+	
+	double smoothPlayPosition;
+//	double storedSmoothPlayPosition;
+//	double lastSmoothUpdateTime;
+//	double relativeSpeedForSmooth;
+//	void updateSmoothPlaySpeed();;
+	//best alignment
+	double alignmentPosition;
+	double firstEventOffsetTimeMillis;
+	
+	void updateSmoothPositionTo(const double& newPosition);
+	int smoothIndex;
+	DoubleVector beatPositions;
+
+};
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/AudioEventMatcher.cpp	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,40 @@
+/*
+ *  AudioEventMatcher.cpp
+ *  MultipleAudioMathcher
+ *
+ *  Created by Andrew on 31/01/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#include "AudioEventMatcher.h"
+
+
+const int matchWindowWidth = 1200;
+
+AudioEventMatcher::AudioEventMatcher(){
+
+	bayesTempoWindow.setToRelativeSize(0, 0.6, 1, 0.2);
+	bayesPositionWindow.setToRelativeSize(0, 0.8, 1, 0.2);
+
+	setArraySizes();
+}
+
+
+void AudioEventMatcher::setArraySizes(){
+	bayesianStruct.resetSpeedSize(200);
+	bayesianStruct.setRelativeSpeedScalar(0.01);
+	bayesianStruct.setSpeedPrior(1.0);
+	bayesianStruct.relativeSpeedPrior.getMaximum();
+	
+	bayesianStruct.resetSize(matchWindowWidth);
+	bayesianStruct.setPositionDistributionScalar(1);
+	
+}
+
+void AudioEventMatcher::draw(){
+	//ofRect(20, 20, 300, 200);
+	
+	bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow);
+	
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/AudioEventMatcher.h	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,40 @@
+/*
+ *  AudioEventMatcher.h
+ *  MultipleAudioMathcher
+ *
+ *  Created by Andrew on 31/01/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+
+
+#ifndef AUDIO_EVENT_MATCHER_H
+#define AUDIO_EVENT_MATCHER_H
+
+
+#include "ofMain.h"
+#include "ChromaOnset.h"
+#include "LiveAudioInput.h"
+#include "ofxWindowRegion.h"
+#include "BayesianArrayStructure.h"
+
+class AudioEventMatcher{
+	
+	public:
+	AudioEventMatcher();
+	
+	void setArraySizes();
+	
+	void draw();
+	
+	BayesianArrayStructure bayesianStruct;//hold the probability distriubtions
+	
+	LiveAudioInput liveInput;//hold the new events that come in
+	
+	ofxWindowRegion bayesTempoWindow;
+	ofxWindowRegion bayesPositionWindow;	
+
+
+};
+#endif
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/LiveAudioInput.cpp	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,14 @@
+/*
+ *  LiveAudioInput.cpp
+ *  MultipleAudioMathcher
+ *
+ *  Created by Andrew on 30/01/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#include "LiveAudioInput.h"
+
+LiveAudioInput::LiveAudioInput(){
+
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/LiveAudioInput.h	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,37 @@
+/*
+ *  LiveAudioInput.h
+ *  MultipleAudioMathcher
+ *
+ *  Created by Andrew on 30/01/2012.
+ *  Copyright 2012 QMUL. All rights reserved.
+ *
+ */
+
+#ifndef LIVE_AUDIO_INPUT_H
+#define LIVE_AUDIO_INPUT_H
+
+
+#include "ofMain.h"
+#include "ChromaOnset.h"
+
+
+struct AudioEvent {
+	double millisTime;
+	double frameTime;
+	double pitch;
+	int type;
+};
+
+class LiveAudioInput{
+	
+public:
+	
+	LiveAudioInput();
+	
+	typedef std::vector<AudioEvent> EventVector; 
+	
+	
+
+	
+};
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.cpp	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,16 @@
+#include "ofMain.h"
+#include "testApp.h"
+#include "ofAppGlutWindow.h"
+
+//========================================================================
+int main( ){
+
+    ofAppGlutWindow window;
+	ofSetupOpenGL(&window, 1024,768, OF_WINDOW);			// <-------- setup the GL context
+
+	// this kicks off the running of my app
+	// can be OF_WINDOW or OF_FULLSCREEN
+	// pass in width and height too:
+	ofRunApp( new testApp());
+
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testApp.cpp	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,276 @@
+#include "testApp.h"
+#include "stdio.h"
+//#include "aubio.h"
+#include <iostream>
+#include <cstring>
+#include <string>
+#include <cstdlib> 
+
+
+const double samplingFrequency = 44100.0;
+	
+//--------------------------------------------------------------
+void testApp::setup(){
+
+	// 2 output channels,
+	// 0 input channels
+	// 22050 samples per second
+	// 256 samples per buffer
+	// 4 num buffers (latency)
+	
+	//nb THIS CODE WOULD BE USEFUL IF WE EVER WANTED REAL-TIME INPUT - VIA ofSoundSteam
+	
+	receiver.setup( PORT );
+	
+	sampleRate 			= 44100;
+	ofSoundStreamSetup(2,0,this, sampleRate,256, 4);
+
+	ofSetFrameRate(30);
+
+	LoadedAudioHolder lah;
+	const char	*infilename = "../../../data/sound/bach4_short1.wav";	
+	
+	
+//	lah.loadAudioFile(infilename);
+//	loadedAudioFiles.push_back(lah);
+
+	//Take care here - we need a pointer to create new instance
+	//but not then delete the instance before the vector of all audio tracks has been used
+	//the above code using lah has problem that it deletes objects once out of the scope of testApp.setup()
+	//when lah is in theory no longer used - something like that possible? - at least pointers to onset detection seem deleted
+	loadedAudioPtr = new LoadedAudioHolder;
+	loadedAudioPtr->loadAudioFile(infilename);
+//	loadedAudioFiles.push_back(*loadedAudioPtr);
+	loadedAudioFiles[0] = *loadedAudioPtr;
+	
+	loadedAudioFiles[0].fileLoader.onsetDetect.window.setToRelativeSize(0, 0.0, 1, 0.25);
+	
+//	printf("Loaded audio %i\n", (int)numberOfAudioTracks);
+	printf("loaded max val  is %f\n", loadedAudioFiles[0].fileLoader.onsetDetect.onsetDetector.maximumDetectionValue);
+	
+	printf("BEFORE LOADING 1\n");
+	keyPressed('p');
+	
+	loadedAudioPtr = new LoadedAudioHolder;
+	loadedAudioPtr->loadAudioFile(infilename);
+//	loadedAudioFiles.push_back(*loadedAudioPtr);
+	loadedAudioFiles[1] = *loadedAudioPtr;
+	loadedAudioFiles[1].fileLoader.onsetDetect.window.setToRelativeSize(0, 0.3, 1, 0.25);
+	
+		printf("AFTER LOADING 1\n");
+	keyPressed('p');
+	
+	numberOfAudioTracks = 2;
+	
+	
+	//audioFilePlayer.loadAudioFile(infilename);
+}
+
+
+
+//--------------------------------------------------------------
+void testApp::update(){
+
+	for (int i = 0;i < numberOfAudioTracks;i++)
+		loadedAudioFiles[i].updateToPlayPosition();
+//	audioFilePlayer.updateToPlayPosition();
+	
+	checkForOSCmessages();
+	
+}
+
+void testApp::checkForOSCmessages(){
+	// check for waiting messages
+	while( receiver.hasWaitingMessages() )
+	{
+		// get the next message
+		ofxOscMessage m;
+		receiver.getNextMessage( &m );
+		
+		// check for mouse moved message
+		if ( m.getAddress() == "/aubioPitch" )
+		{
+			float pitchIn = m.getArgAsFloat(0); 
+			int timeIn = m.getArgAsInt32(1); 
+			printf("AUBIO PITCH RECEIVED %f at time %i\n", pitchIn, timeIn);
+		}
+	}
+}
+
+//--------------------------------------------------------------
+void testApp::draw(){
+	
+	for (int i = 0;i < numberOfAudioTracks;i++){		
+		loadedAudioFiles[i].draw();
+	}
+		
+	
+	eventMatcher.draw();
+	
+//	audioFilePlayer.draw();
+
+}
+
+
+
+//--------------------------------------------------------------
+void testApp::keyPressed  (int key){
+	if (key == '-'){
+		volume -= 0.05;
+		volume = MAX(volume, 0);
+	} else if (key == '+'){
+		volume += 0.05;
+		volume = MIN(volume, 1);
+	}
+
+	if (key == 'q'){
+		for (int i = 0;i < numberOfAudioTracks;i++)
+			loadedAudioFiles[i].switchScreens();
+//		audioFilePlayer.switchScreens();
+	}
+	
+	if (key == OF_KEY_RIGHT){
+//		audioFilePlayer.loadedAudio.setPosition(min(1.0, audioFilePlayer.loadedAudio.getPosition() + (audioFilePlayer.fileLoader.audioHolder.audioScaleSamples/(4.0*audioFilePlayer.fileLoader.audioHolder.audioVector.size()))) );
+
+	}
+	
+	if (key == OF_KEY_LEFT){
+//		audioFilePlayer.loadedAudio.setPosition(max(0.0, audioFilePlayer.loadedAudio.getPosition() - (audioFilePlayer.fileLoader.audioHolder.audioScaleSamples/(4.0*audioFilePlayer.fileLoader.audioHolder.audioVector.size()))));
+		
+	}
+	
+	
+	if (key == ' '){
+		for (int i = 0;i < numberOfAudioTracks;i++)
+		loadedAudioFiles[i].togglePlay();
+//		audioFilePlayer.togglePlay();
+	}
+
+	if (key == OF_KEY_RETURN){
+		for (int i = 0;i < numberOfAudioTracks;i++)
+		loadedAudioFiles[i].stop();
+			
+//		audioFilePlayer.stop();
+	}
+	
+	
+	if (key == 'o'){
+		openNewAudioFileWithdialogBox();
+
+	}
+
+	if (key == 'p'){
+		loadedAudioFiles[0].fileLoader.onsetDetect.printChromaInfo();
+		loadedAudioFiles[0].printEvents();
+	}
+
+	
+	if (key == OF_KEY_UP){
+		for (int i = 0;i < numberOfAudioTracks;i++)
+			loadedAudioFiles[i].fileLoader.zoomOut();
+//		audioFilePlayer.fileLoader.zoomOut();
+	}
+	
+	if (key == OF_KEY_DOWN){
+		for (int i = 0;i < numberOfAudioTracks;i++)
+			loadedAudioFiles[i].fileLoader.zoomIn();
+			
+	//	audioFilePlayer.fileLoader.zoomIn();
+
+	}
+	
+}
+
+//--------------------------------------------------------------
+void testApp::keyReleased  (int key){
+
+}
+
+
+//--------------------------------------------------------------
+void testApp::mouseMoved(int x, int y ){
+
+
+}
+
+//--------------------------------------------------------------
+void testApp::mouseDragged(int x, int y, int button){
+
+}
+
+//--------------------------------------------------------------
+void testApp::mousePressed(int x, int y, int button){
+
+}
+
+
+//--------------------------------------------------------------
+void testApp::mouseReleased(int x, int y, int button){
+
+}
+
+//--------------------------------------------------------------
+void testApp::windowResized(int w, int h){
+	for (int i = 0;i < numberOfAudioTracks;i++)
+	loadedAudioFiles[i].windowResized(w, h);
+	//audioFilePlayer.windowResized(w, h);
+	
+	
+}
+//--------------------------------------------------------------
+void testApp::audioRequested 	(float * output, int bufferSize, int nChannels){
+	//pan = 0.5f;
+	float leftScale = 1 - pan;
+	float rightScale = pan;
+
+}
+
+
+
+//--------------------------------------------------------------
+void testApp::openNewAudioFileWithdialogBox(){
+	std::string filename;
+	getFilenameFromDialogBox(&filename);
+	loadNewAudio(filename);
+	
+}
+
+
+void testApp::loadNewAudio(string soundFileName){
+	
+	loadedAudioFiles[0].loadAudioFile(soundFileName);
+	
+//	for (int i = 0;i < numberOfAudioTracks;i++)
+//		loadedAudioFiles[i].loadAudioFile(soundFileName);
+	
+//	audioFilePlayer.loadAudioFile(soundFileName);
+
+}
+
+
+bool testApp::getFilenameFromDialogBox(std::string* fileNameToSave){
+	//this uses a pointer structure within the loader and returns true if the dialogue box was used successfully
+	// first, create a string that will hold the URL
+	string URL;
+	
+	// openFile(string& URL) returns 1 if a file was picked
+	// returns 0 when something went wrong or the user pressed 'cancel'
+	int response = ofxFileDialogOSX::openFile(URL);
+	if(response){
+		// now you can use the URL 
+		*fileNameToSave = URL;
+		//printf("\n filename is %s \n", soundFileName.c_str());
+		return true;
+	}
+	else {
+	//	soundFileName = "OPEN canceled. ";
+		printf("\n open file cancelled \n");
+		return false;
+	}
+	
+}
+ 
+
+
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testApp.h	Tue Jan 31 13:54:17 2012 +0000
@@ -0,0 +1,84 @@
+#ifndef _TEST_APP
+#define _TEST_APP
+
+
+#include "ofMain.h"
+#include "sndfile.h"
+#include "ofxFileDialogOSX.h"
+#include "LoadedAudioHolder.h"
+//#include "ofxSoundFileLoader.h"
+#include "AudioEventMatcher.h"
+
+#include "LoadedAudioHolder.h"
+
+#include "ofxOsc.h"
+#define PORT 10874
+
+
+//note the dependency on sndfile (libsndfile library needs to be accessible)
+//also the file dialogue addon
+
+//main commands:
+//O: open a new file
+//see the key pressed function for other bits - e.g. can view spectral difference
+
+//TO DO
+//Move all the soundfile stuff to the ofxSoundFileLoader
+//can hold the player, the audio samples and the onset class there
+
+//length in terms of frames (at 512 samples per frame - there are 90 per second) => 900: 10 seconds
+
+class testApp : public ofBaseApp{
+
+	public:
+
+
+		void setup();
+		void update();
+		void draw();
+
+		void keyPressed  (int key);
+		void keyReleased(int key);
+		void mouseMoved(int x, int y );
+		void mouseDragged(int x, int y, int button);
+		void mousePressed(int x, int y, int button);
+		void mouseReleased(int x, int y, int button);
+		void windowResized(int w, int h);
+
+		void audioRequested 	(float * input, int bufferSize, int nChannels);
+
+	void checkForOSCmessages();
+	
+	bool getFilenameFromDialogBox(string* fileNameToSave);
+	void openNewAudioFileWithdialogBox();		
+	void loadNewAudio(string soundFileName);
+	
+	typedef vector<LoadedAudioHolder> AudioFileVector;
+//	AudioFileVector loadedAudioFiles;
+
+	AudioEventMatcher eventMatcher;
+	
+	LoadedAudioHolder* loadedAudioPtr;
+	int numberOfAudioTracks;
+	
+	LoadedAudioHolder loadedAudioFiles[5];
+	
+//	LoadedAudioHolder audioFilePlayer;
+	
+//	LoadedAudioHolder bassFilePlayer;
+	
+	ofxOscReceiver	receiver;
+	
+	
+//live audio input	
+		float 	pan;
+		int		sampleRate;
+		bool 	bNoise;
+		float 	volume;
+		float 	* lAudio;
+		float   * rAudio;
+
+		
+};
+
+#endif