changeset 0:0f9165f96bdb

started drum tracker project svn
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Tue, 30 Aug 2011 20:16:35 +0100
parents
children 690ec1eb8180
files .DS_Store src/BayesDrumTracker.cpp src/BayesDrumTracker.h src/bayesianArray.cpp src/bayesianArray.h src/beatTempo.cpp src/beatTempo.h src/main.cpp src/testApp.cpp src/testApp.h
diffstat 10 files changed, 3017 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
Binary file .DS_Store has changed
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/BayesDrumTracker.cpp	Tue Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,625 @@
+/*
+ *  BayesDrumTracker.cpp
+ *  bayesianTempoInitialiser5
+ *
+ *  Created by Andrew on 14/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+#include "BayesDrumTracker.h"
+#define OUTPORT 12346
+#define HOST "localhost"
+
+
+//beatCorrection process indicates how the phase is changing from max
+
+
+BayesDrumTracker::BayesDrumTracker(){
+
+	initialiseTracker();
+	sender.setup( HOST, OUTPORT );
+}
+
+
+BayesDrumTracker::~BayesDrumTracker(){}
+
+void BayesDrumTracker::initialiseTracker(){
+	
+	beatDistribution.initialiseArray();
+	tempoDistribution.initialiseArray();
+	beatTimes.lastBeatTime = 0;
+	correctionFactor = 0.5;
+	
+	tempoDistribution.likelihoodStdDev =  ARRAY_SIZE / 32;
+	//	tempoDistribution.likelihoodNoise = 0.96;
+	tempoDistribution.likelihoodNoise = 0.7;	
+	tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);//wide 
+	
+	beatDistribution.likelihoodStdDev = ARRAY_SIZE  / 32;
+	beatDistribution.likelihoodNoise = 0.56;	
+	beatDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);
+	
+	
+	tempoMinimum = 180;
+	tempoMaximum = 400;
+	posteriorMaximum = 0.1;
+	
+	adaptiveStandardDeviationMode = false;
+	setDistributionOnStartTempo = true;
+	
+	setBeatToNowTime = ofGetElapsedTimeMillis();
+	recentClickTime = ofGetElapsedTimeMillis();
+	
+	resetParameters();
+	//check what we can delete above SINCE RESET CALLED
+
+}
+
+
+void BayesDrumTracker::resetParameters(){
+	
+	beatTimes.startIndex = 0;
+	beatTimes.lastBeatTime = 0;
+	maxPhase = 0;
+	posteriorMaximum = 0.1;
+	
+	accompanimentStarted = false;
+	
+	tempoDistribution.likelihoodNoise = 0.8;	
+	tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/2);//wide 
+	
+	beatDistribution.initialiseArray();
+	tempoDistribution.initialiseArray();
+	
+	tempoDistribution.calculateStandardDeviation();
+	beatDistribution.calculateStandardDeviation();
+	
+	tempoStdDev = tempoDistribution.standardDeviation;
+	
+	beatTimes.resetBeatTimeArray();
+	
+}
+
+
+
+void BayesDrumTracker::decayDistributions(){
+	
+	if (accompanimentStarted){
+		tempoDistribution.decayPosteriorWithGaussianNoise ();
+		beatDistribution.decayPosteriorWithGaussianNoise();
+	}
+	else{
+		if (tempoStdDev < 0.8 && beatDistribution.standardDeviation < 5)
+			accompanimentStarted = true;
+			
+		}
+}
+
+
+void BayesDrumTracker::setBeatDistribution(int beatPosition){
+	switch (beatPosition){
+			//early sixteenth is that the beat is a sixteenth earlier
+		case 0:
+		case 1:
+		case 11:
+			//i.e. these zones are interpreted as "on the beat"
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;
+			//10 and 2 were here
+			
+		case 2:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
+			//i.e. a 25% chance it is early sixteenth - 75% that the beat actually lies here
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;	
+			
+		case 3:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.3;//was 0.4 in Bayesian8 //half chance it is early 
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;
+			
+		case 5:
+		case 6:
+		case 7:
+			beatDistribution.eighthNoteProportion = 0.3;//i.e. nearly half a chance we are on the 8th note
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;
+			
+		case 4:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
+			beatDistribution.lateSixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
+			//chsanged to 0.2 and 0.1 then back
+			break;
+			
+		case 8:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
+			beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
+			break;
+			
+		case 9:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0.35;//was 0.4 in Bayesian8
+			break;
+			
+		case 10:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.2 in Bayesian8
+			break;
+			
+	}
+	
+}
+
+void BayesDrumTracker::newKickError(const float& error, const double& cpuEventTime, const string& onsetTypeString){
+
+	onsetType = onsetTypeString;
+	cpuBeatTime = cpuEventTime;
+	kickError = error;
+	
+	//printf("beat errror %f time %f\n", kickError, cpuBeatTime);
+	
+	while (kickError > 0.5){
+		kickError -= 1;
+	}
+	
+	if (paused != true){
+		updateTempoProcess(cpuBeatTime, onsetType);
+		//this also cross updates the distributions
+		beatTimes.beatMapTimeDifferences[beatTimes.beatSegment] = kickError*beatTimes.tatum;
+	}//end if paused
+	
+	
+	
+	if (onsetType == "kick"){
+		if (accompanimentStarted)
+			beatDistribution.likelihoodNoise = 0.5;
+		else
+			beatDistribution.likelihoodNoise = 0.5;		
+		//	printf("kick %f ", cpuBeatTime);
+	}
+	else{
+		//snare
+		if (accompanimentStarted)
+			beatDistribution.likelihoodNoise = 0.7;
+		else
+			beatDistribution.likelihoodNoise = 0.85;	
+	//	printf("snare %f ", cpuBeatTime);
+	}
+	
+	
+	setBeatDistribution(beatTimes.beatSegment%12);
+	
+	if (kickError <= 0.5 && kickError >= -0.5)
+	{		
+		float beatStandardDeviation;
+		if (adaptiveStandardDeviationMode)
+			beatStandardDeviation = min((double)beatDistribution.likelihoodStdDev, beatDistribution.standardDeviation);
+		else
+			beatStandardDeviation = beatDistribution.likelihoodStdDev;	
+		
+		
+		beatDistribution.resetPrior();		
+		beatDistribution.setGaussianLikelihoodForBeats((ARRAY_SIZE/2)+(kickError*ARRAY_SIZE), beatStandardDeviation);
+		beatDistribution.calculatePosterior();
+		beatDistribution.renormalisePosterior();
+		
+		sendMaxPhase();
+		
+		beatDistribution.calculateStandardDeviation();
+		
+	}//end if error < 0.5
+	
+	
+	
+	if (beatTimes.beatSegment % 12 == 6){
+		kickString = "Kick ";
+		kickString += ofToString(kickError);
+		kickString += "  ERROR  ";
+		kickString += ofToString(kickError, 2);
+		kickString += " at time diff ";
+		kickString += ofToString(cpuBeatTime - beatTimes.lastClickTime, 2);
+		kickString += "  index ";
+		kickString += ofToString(beatTimes.lastClickIndex, 2);
+		kickString += " TYPE ";
+		kickString += ofToString(beatTimes.beatSegment%12);
+		kickString += " Time diff ";
+		kickString += ofToString(beatTimes.timeDifference, 2);
+	}
+	
+	
+}
+
+
+
+void BayesDrumTracker::startTatum(const float& startTatum){		
+		   beatTimes.tatum = startTatum;
+		   
+		   if (setDistributionOnStartTempo){
+			   beatDistribution.setGaussianPosterior(ARRAY_SIZE/2, 8);
+			   tempoDistribution.setGaussianPosterior(ARRAY_SIZE/2, 12);
+			   float tmpIndex;
+			   tmpIndex = ( (beatTimes.tatum - ((tempoMinimum+tempoMaximum)/2) ) * ARRAY_SIZE)/(tempoMaximum - tempoMinimum);
+			   tempoDistribution.translateDistribution(tmpIndex);
+			   
+			   sendMaxTempo();
+		   }
+}
+
+
+void BayesDrumTracker::setUniformTempo(){
+	for (int i = 0;i < ARRAY_SIZE;i++)
+		tempoDistribution.posterior[i] = (float)1/ARRAY_SIZE;
+}
+
+
+void BayesDrumTracker::setUniformPhase(){
+	for (int i = 0;i < ARRAY_SIZE;i++)
+		beatDistribution.posterior[i] = (float)1/ARRAY_SIZE;
+}
+
+void BayesDrumTracker::setBeatNow(const double& beatTime){
+	for (int i = 0;i < ARRAY_SIZE;i++)
+		beatDistribution.prior[i] = (float)1/ARRAY_SIZE;
+	
+	setBeatToNowTime = ofGetElapsedTimeMillis();
+	double difference = (setBeatToNowTime - recentClickTime);
+	printf("SET BEAT TO NOW %f vs %f :: diff %f tatum %f :: ", setBeatToNowTime, recentClickTime, difference, beatTimes.tatum );
+	
+	double beatTimeToUse = 0;
+	
+	if (difference < beatTimes.tatum)//tatum is the eighth note time
+		beatTimeToUse = difference/ (2*beatTimes.tatum);
+	else 
+		beatTimeToUse = -1*(2*beatTimes.tatum - difference) / (2*beatTimes.tatum);
+	
+	printf("sending %f \n", beatTimeToUse);
+	
+	beatDistribution.setGaussianLikelihoodForBeats((ARRAY_SIZE/2)+(beatTimeToUse*ARRAY_SIZE), 2);
+	beatDistribution.calculatePosterior();
+	beatDistribution.renormalisePosterior();	
+	
+	sendMaxPhase();
+	
+
+}
+
+
+void BayesDrumTracker::newBeat(int& beatIndex){
+	ofxOscMessage m;
+	m.setAddress( "/beatInfo" );
+	
+	m.addFloatArg(beatTimes.tatum);
+	m.addFloatArg(maxPhase);
+	
+	beatTimes.tatum = maxTempo;
+	printf("BEAT INFO %f, %f\n", beatTimes.tatum, maxPhase);
+	
+	sender.sendMessage( m );
+	
+}
+
+void BayesDrumTracker::sendMaxTempo(){
+	ofxOscMessage m;
+	m.setAddress( "/tempo" );
+	
+	//maxTempo = tempoDistribution.maximumIndex * (tempoMaximum - tempoMinimum) /  ARRAY_SIZE;
+	//would be introduced new in bayesian8
+	maxTempo = tempoDistribution.getIntegratedEstimateIndex() * (tempoMaximum - tempoMinimum) /  ARRAY_SIZE;
+	maxTempo += tempoMinimum;
+	
+	beatTimes.tatum = maxTempo;
+	printf("SEND TATUM %f\n", beatTimes.tatum);
+	
+	m.addFloatArg( maxTempo );
+	sender.sendMessage( m );
+	
+	//printf("max tempo %f\n", maxTempo);
+	
+}
+
+void BayesDrumTracker::sendMaxPhase(){
+	
+	
+	//	maxPhase = (beatDistribution.maximumIndex - (ARRAY_SIZE/2)) / ARRAY_SIZE;
+	maxPhase = (beatDistribution.getIntegratedEstimateIndex() - (ARRAY_SIZE/2)) / ARRAY_SIZE;
+//	printf("\nphase index %f :: %f\n", (float) beatDistribution.integratedEstimate , maxPhase);
+	ofxOscMessage m;
+	m.setAddress( "/phase" );
+	m.addFloatArg( maxPhase );
+	sender.sendMessage( m );
+	
+	//beatCorrection = maxPhase * beatTimes.tatum / 4;
+}
+
+
+void BayesDrumTracker::setNewClickIndex(const int& clickIndex, const float& clickTime){
+	
+	beatTimes.lastClickIndex =  clickIndex;
+	beatTimes.lastClickTime =  clickTime;
+
+	int clickIndexToUse = clickIndex % 16;
+	beatTimes.clickIndex = clickIndex;
+	beatTimes.clickNumber[clickIndexToUse] = clickIndex;
+	beatTimes.clickTimes[clickIndexToUse] = clickTime;
+	
+	recentClickTime = ofGetElapsedTimeMillis();
+	
+}
+
+
+void BayesDrumTracker::doBeatCorrection(const float& beatCorrFloat){
+	beatCorrection = beatCorrFloat;
+	correctBeatBy = round(correctionFactor * beatCorrection * ARRAY_SIZE / (2 * beatTimes.tatum));
+	beatDistribution.translateDistribution(-1 * correctBeatBy);
+}
+
+
+bool BayesDrumTracker::filterBeatTime(double newBeatTime){
+	bool newBeatFound = false;
+	if ((newBeatTime - 	beatTimes.lastBeatTime) > 20 || beatTimes.lastBeatTime == 0){
+		
+		crossUpdateArrays((float)(newBeatTime - beatTimes.lastBeatTime));
+		beatTimes.lastBeatTime = newBeatTime;
+		newBeatFound = true;
+	}
+	return newBeatFound;
+}
+
+void BayesDrumTracker::crossUpdateArrays(float timeInterval){
+	
+	int finalBeatIndex, tmpTempoIndex, startBeatIndex;
+	//finalBeat has contribution from BEAT[finalBeat + INT.k] * TEMPO[Max_tempo + k] where INT = INTERVAL
+	float interval;
+	interval = timeInterval / maxTempo;//beatTimes.tatum;
+	tempoDistribution.resetMaximumPosterior();
+	beatDistribution.resetMaximumPosterior();
+	
+	
+	int tmpBeatIndex;
+	//&& interval > 0.8 idea?
+	if (timeInterval > 0 && timeInterval < 12000 ){//need between 0 and 12 seconds only to update
+		
+		for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
+			
+			tmpArray[tmpBeatIndex] = 0;
+			float minusMsecToMakeUp =  beatIndexToMsec(tmpBeatIndex) / interval;
+			float plusMsecToMakeUp =  beatIndexToMsec(ARRAY_SIZE - tmpBeatIndex) / interval;
+			float convertMsecToTempoIndex = ARRAY_SIZE / (tempoMaximum - tempoMinimum) ;
+			
+			
+			int minTempoIndex = -1 * (int)(minusMsecToMakeUp * convertMsecToTempoIndex);
+			int maxTempoIndex = (int)(plusMsecToMakeUp * convertMsecToTempoIndex);
+			
+			
+			if (tmpBeatIndex == beatDistribution.maximumIndex){
+			//	minTmpDebug = tempoDistribution.maximumIndex + minTempoIndex;
+			//	maxTmpDebug = tempoDistribution.maximumIndex + maxTempoIndex;
+				debugArray[0] = beatDistribution.maximumIndex;//
+				debugArray[1] = timeInterval;
+				debugArray[2]  = interval;//beatDistribution.maximumIndex;
+				debugArray[3]  = tempoDistribution.maximumIndex;
+			}
+			
+			for (tmpTempoIndex = minTempoIndex;tmpTempoIndex <= maxTempoIndex;tmpTempoIndex++){
+				
+				if ((tempoDistribution.maximumIndex + tmpTempoIndex) >= 0 
+					&& (tempoDistribution.maximumIndex + tmpTempoIndex) < ARRAY_SIZE 
+					&& (tmpBeatIndex - (int)(interval*tmpTempoIndex)) >= 0 
+					&& (tmpBeatIndex - (int)(interval*tmpTempoIndex))< ARRAY_SIZE){	
+					tmpArray[tmpBeatIndex] += beatDistribution.posterior[tmpBeatIndex - (int)(interval*tmpTempoIndex)] * tempoDistribution.posterior[(int)tempoDistribution.maximumIndex + tmpTempoIndex];
+				}
+			}//end for tmpTmepo
+			
+			
+			
+		}
+		
+		float tmpFloat;
+		for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
+			//debug - dont actually update::
+			
+			tmpFloat = 	beatDistribution.posterior[tmpBeatIndex];
+			beatDistribution.posterior[tmpBeatIndex] = tmpArray[tmpBeatIndex];
+			tmpArray[tmpBeatIndex] = tmpFloat;
+		}
+		beatDistribution.renormaliseArray(&beatDistribution.posterior[0], ARRAY_SIZE);
+		
+	}	//end if
+	
+	
+}
+
+
+void BayesDrumTracker::updateTempoProcess(const double& cpuTime, const string& onsetDescription){
+	
+	if (filterBeatTime(cpuTime) == true){
+		//checks for no repeat
+		
+		if (onsetDescription == "kick")
+			beatTimes.addBeatTime(cpuTime, 1);
+		else 
+			beatTimes.addBeatTime(cpuTime, 2);		
+		
+		
+		//recalculate the distribution
+		int altIndex = 0;
+		
+		tempoDataString = "Tatum :";
+		tempoDataString += ofToString(beatTimes.tatum, 2);
+		tempoDataString += "   BPM ";
+		tempoDataString += ofToString((double)30000/beatTimes.tatum, 2);
+		
+		timeString = "Last BEAT ";
+		timeString += ofToString(beatTimes.lastBeatTime);
+		timeString += "  CLICK ";
+		timeString += ofToString(beatTimes.lastClickTime);
+		timeString += "  DIFDF ";
+		timeString += ofToString(beatTimes.timeDifference);
+		timeString += "  segment ";
+		timeString += ofToString(beatTimes.beatSegment);
+		
+		
+		for (altIndex = 0;altIndex< 16;altIndex++){
+			tempoInterval = beatTimes.intervalDifferences[beatTimes.index][altIndex];
+			integerMultipleOfTatum = beatTimes.relativeIntervals[altIndex][1];
+			
+			
+			///NEW VERSION	
+			tempoUpdateStrings[altIndex] = "";
+			double timeInterval = beatTimes.beatTimes[beatTimes.index] - beatTimes.beatTimes[altIndex];	
+			//raw time difference
+			beatTimes.intervalDifferences[beatTimes.index][altIndex] = 0;
+			beatTimes.intervalUsed[beatTimes.index][altIndex] = false;
+			
+			if (onsetType == "kick")
+				beatTimes.OnsetIsKick[beatTimes.index] = true;
+			else 
+				beatTimes.OnsetIsKick[beatTimes.index] = false;
+			
+			
+			
+			if (!accompanimentStarted){
+				//if we need to find tempo and start use this method
+				//we have 'started' once std dev is sufficiently low
+				
+				updateTempoIfWithinRange(timeInterval);//taken as being the tatum interval
+				
+				
+				
+				for (int i = 1;i <= 4;i++){
+					//we test the main beats and the two bar (16 tatum intervals)
+					
+					double	testInterval = timeInterval / 2*i;//pow(2, i);//pow(2.0, i);
+					
+					if (updateTempoIfWithinRange(testInterval)){
+						//printf("test time %f, beats %i\n", testInterval, i);
+						
+						beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
+						beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
+						//xx what if two within range here?
+						
+						tempoUpdateStrings[altIndex] = "Tempo Updates (";
+						tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
+						tempoUpdateStrings[altIndex]  +=  ") : [";
+						tempoUpdateStrings[altIndex] += ofToString(altIndex);
+						tempoUpdateStrings[altIndex] += "]] : ";
+						tempoUpdateStrings[altIndex] += ofToString(timeInterval);
+						tempoUpdateStrings[altIndex] += ", ioi:";
+						tempoUpdateStrings[altIndex] += ofToString(i);
+						//tempoUpdateStrings[altIndex] += "";
+						
+					}
+					
+				}
+				
+				double	testInterval = timeInterval / 16;//pow(2, i);//pow(2.0, i);
+				if (updateTempoIfWithinRange(testInterval)){
+					beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
+					beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
+				}
+				
+			}else{
+				//OLD VERSON
+				//THIS USES THE CURRENT TEMPO ESTIMATE TO DECIDE WHAT THE BEST INTERVAL IS
+				//&& integerMultipleOfTatum % 2 == 0 removed below XXX put back
+				if (altIndex != beatTimes.index && integerMultipleOfTatum < 17 
+					&& integerMultipleOfTatum > 0 && beatTimes.startIndex > 8//beattimes.index > 8 - the start
+					&& integerMultipleOfTatum%2 == 0){//mod 2 - i.e. proper beat intervals only
+					
+					double testInterval = timeInterval / integerMultipleOfTatum;
+					
+					if (updateTempoIfWithinRange(testInterval)){
+						
+						beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
+						beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
+						
+						if (paused == false){
+							tempoUpdateStrings[altIndex] = "Tempo Updates : (";
+							tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
+							tempoUpdateStrings[altIndex]  +=  ") : ["; 
+							tempoUpdateStrings[altIndex] += ofToString(altIndex, 0);
+							tempoUpdateStrings[altIndex]  +=  "] :: "; 	 
+							tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
+							tempoUpdateStrings[altIndex] += " intervals :: ";
+							tempoUpdateStrings[altIndex] += ofToString(tempoInterval);
+							tempoUpdateStrings[altIndex] += " ms.";
+							// tempoUpdateStrings[altIndex] += ", ioi:";
+							
+							// tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
+							
+							
+							
+							
+						}//end if not paused
+						
+						
+					}//end if good interval to update
+					
+				}//end if not same index etc
+				
+				
+			}
+			
+			
+			
+		}//end for all intervals
+		
+		sendMaxTempo();
+	}//end if new beat time
+	double tempoEstimate = tempoDistribution.getIntegratedEstimateIndex();
+	tempoDistribution.calculateStandardDeviation();
+	tempoStdDev = tempoDistribution.standardDeviation;	
+	
+}
+
+
+bool BayesDrumTracker::updateTempoIfWithinRange(double timeInterval){
+	
+	bool updated = false;
+	
+	if (timeInterval > tempoMinimum && timeInterval < tempoMaximum ){
+		calculateTempoUpdate(timeInterval);
+		updated = true;
+	}
+	
+	return updated;
+}
+
+
+void BayesDrumTracker::calculateTempoUpdate(double tempoInterval){
+	
+	
+	tempoDistribution.resetPrior();		
+	//need to relook at likelihood for the tempo distribution - not the same as....
+	tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval-tempoMinimum)/(tempoMaximum - tempoMinimum), tempoDistribution.likelihoodStdDev);
+	tempoDistribution.calculatePosterior();
+	tempoDistribution.renormalisePosterior();
+	
+	//did take pic of screen here - see initialiser4
+}
+
+
+float BayesDrumTracker::tempoIndexToMsec(const int& index){
+	float msec;
+	msec = index * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
+	msec += tempoMinimum;
+	return msec;
+}
+
+float BayesDrumTracker::beatIndexToMsec(const int& index){
+	float msec;
+	msec = index * maxTempo / ARRAY_SIZE;
+	msec += tempoMinimum;
+	return msec;
+}
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/BayesDrumTracker.h	Tue Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,107 @@
+/*
+ *  BayesDrumTracker.h
+ *  bayesianTempoInitialiser5
+ *
+ *  Created by Andrew on 14/07/2011.
+ *  Copyright 2011 QMUL. All rights reserved.
+ *
+ */
+
+#include "ofxOsc.h"
+#include "bayesianArray.h"
+#include "beatTempo.h"
+
+class BayesDrumTracker{
+
+#ifndef	_BAYES_DRUM_TRACKER
+#define _BAYES_DRUM_TRACKER
+#define ARRAY_SIZE 240	
+//#define BAYES_ARRAY_SIZE 240
+
+	public:
+		
+		BayesDrumTracker();
+		~BayesDrumTracker();
+	
+	void initialiseTracker();
+	void resetParameters();
+	void decayDistributions();//on update
+	
+	void setBeatDistribution(int beatPosition);
+	
+	void newKickError(const float& error, const double& cpuEventTime, const string& onsetTypeString);
+	void startTatum(const float& startTatum);	
+	void setNewClickIndex(const int& clickIndex, const float& clickTime);
+	void sendMaxTempo();
+	void sendMaxPhase();
+	void newBeat(int& beatIndex);
+	
+	void setUniformTempo();
+	void setUniformPhase();
+	void setBeatNow(const double& beatTime);
+	void doBeatCorrection(const float& beatCorrFloat);
+	
+	
+	bool filterBeatTime(double newBeatTime);
+	void crossUpdateArrays(float timeInterval);
+	bool updateTempoIfWithinRange(double timeInterval);
+	void calculateTempoUpdate(double tempoInterval);
+	void updateTempoProcess(const double& cpuTime, const string& onsetDescription);
+
+	
+	float beatIndexToMsec(const int& index);
+	float tempoIndexToMsec(const int& index);
+	
+	
+	float kickError, snareError;
+	double cpuBeatTime;
+	float testArray[5];
+	
+	double setBeatToNowTime;
+	
+	float prior [ARRAY_SIZE];
+	float posterior [ARRAY_SIZE];
+	float likelihood [ARRAY_SIZE];
+	float likelihoodMean, likelihoodStdDev, likelihoodNoise, stepSize;
+	float maximumEstimate;	
+	float maximumTest, posteriorDecayRate, maximumIndex;
+	float eighthNoteProportion;
+	
+	bool paused;
+	double maxPhase, maxTempo;
+	
+	float tmpArray[ARRAY_SIZE];
+	
+	float correctionFactor;
+	float beatCorrection;
+	int correctBeatBy;
+	
+	bayesianArray beatDistribution;
+	bayesianArray tempoDistribution;
+	double tempoMinimum, tempoMaximum;
+	double tempoInterval;
+	beatTempo	beatTimes;
+	
+	string onsetType;
+	string timeString;
+	//double cpuBeatTime;
+	
+	ofxOscSender sender;
+	
+	double posteriorMaximum;
+	bool adaptiveStandardDeviationMode;
+	double tempoStdDev;
+	bool accompanimentStarted;
+	bool setDistributionOnStartTempo;
+	int integerMultipleOfTatum;
+	
+	double recentClickTime;
+	
+	string kickString;//for info
+	
+	float debugArray [4];
+	string tempoUpdateStrings[16];
+	string tempoDataString;
+};
+
+#endif
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/bayesianArray.cpp	Tue Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,290 @@
+/*
+ *  bayesianArray.cpp
+ *  bayesianTest5
+ *
+ *  Created by Andrew Robertson on 08/05/2010.
+ *  Copyright 2010 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "bayesianArray.h"
+#include "math.h"
+#include "ofMain.h"
+
+bayesianArray::bayesianArray(){
+	likelihoodNoise = 0.5;
+	likelihoodMean = ARRAY_SIZE/2;
+	likelihoodStdDev = ARRAY_SIZE / 12;
+initialiseArray();
+}
+
+void bayesianArray::initialiseArray(){
+
+	//maximumIndex = 12;//change this
+	setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);	
+	setGaussianLikelihood(ARRAY_SIZE/2, ARRAY_SIZE/1);//likelihoodMean, likelihoodStdDev);
+	
+	calculatePosterior();
+	renormalisePosterior();
+	posteriorDecayRate = 0.06;
+	
+	eighthNoteProportion = 0.35;//must be less than 0.5 to discriminate - was 0.4
+	earlySixteenthNoteProportion = 0;
+	lateSixteenthNoteProportion = 0;
+	decayNoiseAmount = 0.1;
+	decayNoiseStdDev = ARRAY_SIZE/24;
+	standardDeviation = likelihoodStdDev;
+	setDecayNoiseGaussian(ARRAY_SIZE/2, decayNoiseStdDev);
+	
+	setGaussianLikelihood(likelihoodMean, likelihoodStdDev);
+}
+
+
+void bayesianArray::setGaussianPrior(float mean, float StdDev){
+int i;
+	for (i=0;i<ARRAY_SIZE;i++){
+	prior[i] = (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev));
+	//posterior[i] = prior[i];
+	}
+}
+
+void bayesianArray::setGaussianPosterior(float mean, float StdDev){
+int i;
+	for (i=0;i<ARRAY_SIZE;i++){
+	posterior[i] = (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev));
+	}
+}
+
+void bayesianArray::setGaussianLikelihoodForBeats(float mean, float StdDev){
+	//this has eighth and sixteenth positions included
+	
+if (mean >= 0 && mean <= ARRAY_SIZE){
+int i;	float eighthDifference;
+int eighthPosition = ((int)mean + ARRAY_SIZE/2)%ARRAY_SIZE;
+int earlySixteenthPosition = ((int)mean + (3*ARRAY_SIZE/4))%ARRAY_SIZE;;
+int lateSixteenthPosition = ((int)mean + (ARRAY_SIZE/4))%ARRAY_SIZE;;
+
+float mainDifference, sixteenthDifference;
+float gaussianProportion = 1 - likelihoodNoise;
+float mainProportion = (1 - eighthNoteProportion - earlySixteenthNoteProportion - lateSixteenthNoteProportion);
+
+	for (i=0;i < ARRAY_SIZE;i++){
+	
+	mainDifference = min( fabs(i-mean) , (double)(i + ARRAY_SIZE - mean));
+	likelihood[i] = gaussianProportion * mainProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(mainDifference)*(mainDifference)/(2*StdDev*StdDev)) ;
+	
+	eighthDifference = min( abs(i - eighthPosition) , i + ARRAY_SIZE - eighthPosition);
+	eighthDifference = min(eighthDifference , (float)(ARRAY_SIZE + eighthPosition - i ));
+	//for e.g. +0.43, or -0.47 we require the gaussian around the half note too
+	likelihood[i] += gaussianProportion * eighthNoteProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(eighthDifference)*(eighthDifference)/(2*StdDev*StdDev)) ;
+	
+	sixteenthDifference = min( abs(i - earlySixteenthPosition) , i + ARRAY_SIZE - earlySixteenthPosition);
+	sixteenthDifference = min(sixteenthDifference , (float)(ARRAY_SIZE + earlySixteenthPosition - i ));
+	//for e.g. +0.43, or -0.47 we require the gaussian around the half note too
+	likelihood[i] += gaussianProportion * earlySixteenthNoteProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(sixteenthDifference)*(sixteenthDifference)/(2*StdDev*StdDev)) ;
+	
+	sixteenthDifference = min( abs(i - lateSixteenthPosition) , i + ARRAY_SIZE - lateSixteenthPosition);
+	sixteenthDifference = min(sixteenthDifference , (float)(ARRAY_SIZE + lateSixteenthPosition - i ));
+	//for e.g. +0.43, or -0.47 we require the gaussian around the half note too
+	likelihood[i] += gaussianProportion * lateSixteenthNoteProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(sixteenthDifference)*(sixteenthDifference)/(2*StdDev*StdDev)) ;
+	
+
+
+	likelihood[i] += (likelihoodNoise / ARRAY_SIZE);
+	//likelihood[i] = (float) max(gaussianProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev)) , 
+	//(double) (likelihoodNoise / ARRAY_SIZE) );
+	}
+//	renormaliseArray(&likelihood[0], ARRAY_SIZE);
+}//end if mean within limits
+}
+
+
+void bayesianArray::setGaussianLikelihood(float mean, float StdDev){
+if (mean >= 0 && mean <= ARRAY_SIZE){
+int i;	float eighthDifference;
+int eighthPosition = ((int)mean + ARRAY_SIZE/2)%ARRAY_SIZE;
+float mainDifference;
+float gaussianProportion = 1 - likelihoodNoise;
+
+	for (i=0;i < ARRAY_SIZE;i++){
+	
+	mainDifference = min( fabs(i-mean) , (double)(i + ARRAY_SIZE - mean));
+	//without * (1 - eighthNoteProportion)
+	likelihood[i] = gaussianProportion  * (1/(StdDev*sqrt(2*PI)))*exp(-1*(mainDifference)*(mainDifference)/(2*StdDev*StdDev)) ;
+		
+	likelihood[i] += (likelihoodNoise / ARRAY_SIZE);
+	//likelihood[i] = (float) max(gaussianProportion * (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev)) , 
+	//(double) (likelihoodNoise / ARRAY_SIZE) );
+	}
+//	renormaliseArray(&likelihood[0], ARRAY_SIZE);
+}//end if mean within limits
+}
+
+void bayesianArray::calculatePosterior(){
+int i;
+	for (i=0;i < ARRAY_SIZE;i++){
+	posterior[i] = likelihood[i] * prior[i];
+	}
+	//renormalisePosterior();
+}
+
+
+float bayesianArray::getMaximum(float *ptr, int length){
+int i;
+float max = 0;
+	for (i=0;i < length;i++){	
+		if (*(ptr+i)>max)
+		max = *(ptr+i);
+	}
+	maximumValue = max;
+	return max;
+}
+
+float* bayesianArray::getMaximumEstimate(float *ptr, int length){
+float returnArray[2];
+int i;
+float max = 0;
+maximumIndex = 0;
+	for (i=0;i < length;i++){	
+		if (*(ptr+i)>max){
+		max = *(ptr+i);
+		maximumIndex = i;
+		}
+	}
+	returnArray[0] = max;
+	returnArray[1] = maximumIndex;
+	maximumValue = max;
+	return &returnArray[0];
+}
+
+
+
+double bayesianArray::getIntegratedEstimateIndex(){
+	int i;
+	float integratedQuantity = 0;
+	float integratedTotal = 0;
+	double integratedIndex = 0;
+	for (i=0;i < ARRAY_SIZE;i++){	
+		integratedQuantity += posterior[i];//the values of the probability distribution
+		integratedTotal += i*posterior[i];
+	}
+	if (integratedQuantity > 0){
+		integratedIndex = integratedTotal / integratedQuantity;
+	}
+	integratedEstimate = (float) integratedIndex;
+	return integratedIndex;
+}
+
+
+double bayesianArray::calculateStandardDeviation(){
+
+	double total = 0;
+	double pdfSum;
+	double variance = 0;
+	for (int i=0;i < ARRAY_SIZE;i++){	
+//*posterior[i] * 		
+		total += posterior[i] * (i - integratedEstimate) * (i - integratedEstimate);//the values of the probability distribution
+		pdfSum += posterior[i];
+	}
+	
+	if (pdfSum > 0)
+	variance = total / pdfSum;
+	else 
+	variance = ARRAY_SIZE;
+
+	standardDeviation = sqrt(variance);
+	return standardDeviation;
+}
+
+
+
+void bayesianArray::renormaliseArray(float *ptr, int length){
+int i;
+float totalArea = 0;
+	for (i=0;i < length;i++){
+		totalArea += *(ptr+i);
+	}
+	
+	for (i=0;i < length;i++){
+		*(ptr+i) /= totalArea;
+	}
+	
+}
+
+void bayesianArray::resetPrior(){
+	int i;
+	for (i=0;i<ARRAY_SIZE;i++){
+	prior[i] = posterior[i];
+	}
+}
+
+void bayesianArray::renormalisePosterior(){
+int i;
+float totalArea = 0;
+	for (i=0;i < ARRAY_SIZE;i++){
+		totalArea += posterior[i];
+	}
+	
+	for (i=0;i < ARRAY_SIZE;i++){
+		posterior[i] /= totalArea;
+	}
+	
+}
+
+void bayesianArray::decayPosterior(){
+	float *pointer;
+	pointer = getMaximumEstimate(&posterior[0], ARRAY_SIZE);	
+	 float maximum;
+	 maximum = *pointer;
+	int i;
+	for (i=0;i<ARRAY_SIZE;i++){
+	posterior[i] += (maximum - posterior[i]) * posteriorDecayRate * 0.01;;//usded to be * maximum not minus value
+	}
+	maximumIndex = *(pointer+1);
+}
+
+void bayesianArray::setDecayNoiseGaussian(float mean, float StdDev){
+int i;
+	for (i=0;i<ARRAY_SIZE;i++){
+	decayNoiseArray[i] = (1/(StdDev*sqrt(2*PI)))*exp(-1*(i-mean)*(i-mean)/(2*StdDev*StdDev));
+	}
+}
+
+void bayesianArray::decayPosteriorWithGaussianNoise(){
+
+	int i;
+	float currentMaximum = getMaximum(&posterior[0], ARRAY_SIZE);
+	for (i=0;i<ARRAY_SIZE;i++){
+	posterior[i] += decayNoiseArray[(i - (int)maximumIndex + ((3*ARRAY_SIZE)/2)) % ARRAY_SIZE] * currentMaximum * decayNoiseAmount;
+	//posteriorDecayRate * 0.01;;//usded to be * maximum not minus value
+	}
+
+}
+
+void bayesianArray::resetMaximumPosterior(){
+int i;
+float max = 0;
+	for (i=0;i < ARRAY_SIZE;i++){	
+		if (posterior[i]>max){
+		maximumIndex = i;
+		max = posterior[i];
+		}
+	}
+}
+
+void bayesianArray::translateDistribution(int translationIndex){
+int tmpIndex;
+		//copy array
+		int i;
+		for (i=0;i < ARRAY_SIZE;i++){
+		tempPosteriorArray[i] =	posterior[i] ;
+		}
+		//translate values
+	for (i=0;i < ARRAY_SIZE;i++){
+	tmpIndex = (i + translationIndex + ARRAY_SIZE)%ARRAY_SIZE;
+	posterior[tmpIndex] = tempPosteriorArray[i]; 
+	}
+	//now delete tmp array
+}
+
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/bayesianArray.h	Tue Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,62 @@
+/*
+ *  bayesianArray.h
+ *  bayesianTest5
+ *
+ *  Created by Andrew Robertson on 08/05/2010.
+ *  Copyright 2010 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#ifndef	_BAYESIAN_ARRAY
+#define _BAYESIAN_ARRAY
+
+#define ARRAY_SIZE 240
+
+
+class bayesianArray{
+
+public:
+	
+	bayesianArray();
+	void initialiseArray();
+
+		void setGaussianLikelihoodForBeats(float mean, float StdDev);		
+		void setGaussianLikelihood(float mean, float StdDev);	
+		void setGaussianPrior(float mean, float StdDev);
+		void setGaussianPosterior(float mean, float StdDev);
+			
+		void calculatePosterior();
+		void renormalisePosterior();
+		void resetMaximumPosterior();//resets the max index
+		void decayPosteriorWithGaussianNoise();
+		void translateDistribution(int translationIndex);
+		void setDecayNoiseGaussian(float mean, float StdDev);
+		double calculateStandardDeviation();
+	
+		
+		float getMaximum(float *ptr, int length);
+		void renormaliseArray(float *ptr, int length);
+		void resetPrior();
+		void decayPosterior();
+		float* getMaximumEstimate(float *ptr, int length);
+		double getIntegratedEstimateIndex();
+	
+		float prior [ARRAY_SIZE];
+		float posterior [ARRAY_SIZE];
+		float likelihood [ARRAY_SIZE];	
+		float tempPosteriorArray[ARRAY_SIZE];
+
+		float decayNoiseArray[ARRAY_SIZE];
+		float decayNoiseStdDev, decayNoiseAmount;
+
+		float likelihoodMean, likelihoodStdDev, likelihoodNoise;
+		float maximumTest, posteriorDecayRate, maximumValue;
+		float eighthNoteProportion, earlySixteenthNoteProportion, lateSixteenthNoteProportion ;
+		float maximumEstimate, maximumIndex, integratedEstimate;
+		double standardDeviation;
+			
+private:
+};
+
+#endif
+	
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/beatTempo.cpp	Tue Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,188 @@
+/*
+ *  beatTempo.cpp
+ *  bayesianTempo1
+ *
+ *  Created by Andrew Robertson on 08/05/2010.
+ *  Copyright 2010 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+#include "beatTempo.h"
+
+beatTempo::beatTempo(){
+index = 0;
+lastBeatTime = 0;
+decayAmount = 0;
+}
+
+//records a loop of cpu times for the last 16 events received
+
+void beatTempo::addBeatTime(double f, int type){
+//type 1 is kick, type 2 is snare
+
+	index++;
+	startIndex++;
+	if (index == 16){
+	index = 0;
+	}
+	lastBeatTime = f;
+	beatTimes[index] = f;
+	
+	//find the closest click time to this new cputime
+	//NOT ACTUALLY USED ANYWHERE....
+	double useThisClickTime = lastClickTime;
+	int useThisClickIndex = lastClickIndex ;
+	
+		if (lastClickTime + (tatum/2) < f){
+		//next click time
+		closestClickIndexToBeat[index] = lastClickIndex + 1;
+		//useThisClickTime += tatum;
+		//	useThisClickIndex++;
+		}
+		else{
+		//recent click time
+		closestClickIndexToBeat[index] = lastClickIndex;
+		}
+		//end not used
+
+	
+	int lastBeatSegment = beatSegment;
+	
+	//timeDifference = f - lastClickTime;
+	timeDifference = f - lastClickTime;
+	//[0, 1] => [0, 2*tatum]
+	beatSegment = (6*(lastClickIndex%8));
+	beatSegment +=  ( ( (int)floor( ( ( (timeDifference + (tatum/12)) * 6) ) / tatum) ) );
+	
+
+	
+	//this calculates the probabilities of events in the different zones
+	//not yet used in the algorithm
+	beatSegment = beatSegment%48;
+	//wipe old onez
+	while (lastBeatSegment%48 != beatSegment){
+		lastBeatSegment++;
+		if (lastBeatSegment%12 == 0)
+	decayProbabilityDistributionRow((lastBeatSegment/12)%4);
+		
+	beatMap[lastBeatSegment%48] = 0;
+
+	}
+	addToProbabilityDistribution(beatSegment, type);
+	//end of new addition
+	
+	beatMap[beatSegment] = type;
+	
+	
+	
+	double intervalCalculation;
+	int otherIndex;
+	for (otherIndex = 0;otherIndex < 16;otherIndex++){
+		
+		if (otherIndex != index){
+		intervalCalculation = calculateInterval(index, otherIndex);
+		relativeIntervals[otherIndex][0] = intervalCalculation;
+		intervalDifferences[index][otherIndex] =  intervalCalculation;
+			
+		//integer multiple is relativeIntervals[otherIndex][1]
+		}
+		else{
+		intervalDifferences[index][otherIndex] =  0;
+		}
+	}
+	
+	
+	
+}
+
+
+void beatTempo::addToProbabilityDistribution(int beatSegment, int type){
+	//printf("beat segment %i\n", beatSegment);
+	int beatNumber = (int) (beatSegment + 1)/12;
+	beatNumber = beatNumber%4;
+	float newProbabilityContribution = 1 - decayAmount;
+	switch (beatSegment%12) {
+		case 0:
+			beatProbabilityDistribution[beatNumber][0][type - 1] = newProbabilityContribution;
+			break;
+		case 1:
+			beatProbabilityDistribution[beatNumber][0][type - 1] = 1*newProbabilityContribution;
+			break;
+		case 2:
+			beatProbabilityDistribution[beatNumber][0][type - 1] = 0.5*newProbabilityContribution;
+			beatProbabilityDistribution[beatNumber][1][type - 1] = 0.5*newProbabilityContribution;
+			break;	
+		case 3:
+			beatProbabilityDistribution[beatNumber][1][type - 1] = 1*newProbabilityContribution;
+			break;		
+		case 4:
+			beatProbabilityDistribution[beatNumber][1][type - 1] = 0.4*newProbabilityContribution;
+			beatProbabilityDistribution[beatNumber][2][type - 1] = 0.6*newProbabilityContribution;
+			break;	
+		case 5:
+			beatProbabilityDistribution[beatNumber][2][type - 1] = 0.4*newProbabilityContribution;
+			beatProbabilityDistribution[beatNumber][3][type - 1] = 0.6*newProbabilityContribution;
+			break;		
+		case 6:
+			beatProbabilityDistribution[beatNumber][3][type - 1] = 1*newProbabilityContribution;
+			break;
+		case 7:
+			beatProbabilityDistribution[beatNumber][3][type - 1] = 1*newProbabilityContribution;
+			break;	
+		case 8:
+			beatProbabilityDistribution[beatNumber][4][type - 1] = 0.6*newProbabilityContribution;
+			beatProbabilityDistribution[beatNumber][5][type - 1] = 0.4*newProbabilityContribution;
+			break;		
+		case 9:
+			beatProbabilityDistribution[beatNumber][5][type - 1] = 1*newProbabilityContribution;
+			break;	
+		case 10:
+			beatProbabilityDistribution[beatNumber][5][type - 1] = 0.5*newProbabilityContribution;
+			break;		
+		case 11:
+			beatProbabilityDistribution[(beatNumber+1)%4][0][type - 1] = 1*newProbabilityContribution;
+			break;		
+	}
+	
+	
+}
+
+void beatTempo::decayProbabilityDistributionRow(int row){
+	
+	for (int x = 0;x<6;x++){
+		beatProbabilityDistribution[row][x][0] *= decayAmount;
+		beatProbabilityDistribution[row][x][1] *= decayAmount;
+	}
+	
+	
+}
+
+double beatTempo::calculateInterval(int newIndex, int otherIndex){
+
+	double newTime, otherTime, interval, relativeInterval;
+	relativeInterval = tatum;
+	int tatumMultiple;
+	newTime = beatTimes[newIndex];
+	otherTime = beatTimes[otherIndex];
+	if (otherTime > 0){
+	interval = newTime - otherTime;
+//	tatumMultiple = closestClickIndexToBeat[newIndex] - closestClickIndexToBeat[otherIndex]; - to be added
+	tatumMultiple = round (interval / tatum);
+		if (tatumMultiple > 0){
+		relativeInterval = interval / (tatumMultiple);
+		relativeIntervals[otherIndex][1] = tatumMultiple;
+		tatumMultiples[newIndex][otherIndex] = tatumMultiple;
+		}//end if
+	}
+	return relativeInterval;
+
+}
+
+
+void beatTempo::resetBeatTimeArray(){
+	for (int i = 0;i < 16;i++){
+	beatTimes[i] = 0;
+		for (int k = 0;k < 16;k++)
+			intervalDifferences[i][k] = 0;
+	}
+}
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/beatTempo.h	Tue Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,49 @@
+/*
+ *  beatTempo.h
+ *  bayesianTempo1
+ *
+ *  Created by Andrew Robertson on 08/05/2010.
+ *  Copyright 2010 __MyCompanyName__. All rights reserved.
+ *
+ */
+
+class beatTempo{
+
+public:
+	beatTempo();
+	
+	double beatTimes[16];
+	double relativeIntervals[16][2];
+	double intervalDifferences[16][16];//diff between new index , other index
+	bool   intervalUsed[16][16];
+	int tatumMultiples[16][16];
+	bool OnsetIsKick[16];
+	
+	int closestClickIndexToBeat[16];
+	int clickIndex;//used by testApp but to be replaced
+//	int clickPosition[16];
+	
+	double clickTimes[16];
+	int clickNumber[16];
+	float beatMapTimeDifferences[48];
+	
+	float beatProbabilityDistribution[4][6][2];
+	
+//	int recentClickIndex;
+	
+	int index, startIndex;
+	
+	char beatMap[48];
+	
+	void addBeatTime(double f, int type);
+	double calculateInterval(int newIndex, int otherIndex);
+	void addToProbabilityDistribution(int beatSegment, int typeToAdd);
+	void decayProbabilityDistributionRow(int row);
+	void resetBeatTimeArray();
+	
+	double tatum;
+	double lastClickTime, lastBeatTime;
+	int lastClickIndex, beatSegment, timeDifference;
+	float decayAmount;//amount that the old probability observation contributed to the probability array
+	
+};
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/main.cpp	Tue Aug 30 20:16:35 2011 +0100
@@ -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 Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,1521 @@
+#include "testApp.h"
+
+
+//--------------------------------------------------------------
+//relooking at this problem
+//bayesianTempo7 - have had working well with Bayesian8NEW maxmsp set
+
+//updated in bayesian8
+//integrate so that maxPhase and tempo are the integrated result across the pdf
+//rather tahn the maximum index - tends to reflect the actuial distribution better
+//and is the "correct" bayesian method
+
+//added [ and ] tpo change the alignment when rescue is needed
+
+//in Bayesian9 (BayesianTest8NEW)
+//added noise in phase process
+//started probability distribution for observed beat events
+
+//in bayesian 11
+//get s.d. of posterior
+//this is set to be used as the s.d. of the likelihood
+
+
+//Initialiser : the algorithm has an initialisation stage with flat prior that detects liekly tempo
+
+
+
+//BAYESIAN DISTRIBUTION SET by class BayesianArray
+//SETUP - initialises array
+//UPDATE - decay the distribution with noise 
+//this should be done using tempo and noise
+//DRAW - Draw current distributions and also the maximum
+
+//Runs with bayesian11NEW
+//and B-KeeperOldBayesianTestNew in Live 
+//Needs - categorisation of beats and tempo
+//can we use our distribution to filter the input or is that cheating?
+
+//INtroduce lock scheme for tempo - we know where the beat fell, so can calculate the appropriate tempo interval
+
+void testApp::setup(){
+// listen on the given port
+	cout << "listening for osc messages on port " << PORT << "\n";
+	receiver.setup( PORT );
+	
+//	sender.setup( HOST, OUTPORT );
+	ofSetCircleResolution(50);
+	ofBackground(255,255,255);
+	bSmooth = false;
+	msg_string = "setup";
+	
+	ofSetWindowTitle("Bayesian Test");
+
+	ofSetFrameRate(60); // if vertical sync is off, we can go a bit fast... this caps the framerate at 60fps.
+
+/*
+	beatDistribution.initialiseArray();
+	tempoDistribution.initialiseArray();
+	beatTimes.lastBeatTime = 0;
+	correctionFactor = 0.5;
+
+
+	
+	tempoDistribution.likelihoodStdDev =  ARRAY_SIZE / 32;
+//	tempoDistribution.likelihoodNoise = 0.96;
+	tempoDistribution.likelihoodNoise = 0.7;	
+	tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);//wide 
+	
+	beatDistribution.likelihoodStdDev = ARRAY_SIZE  / 32;
+	beatDistribution.likelihoodNoise = 0.56;	
+	beatDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);
+
+	
+	tempoMinimum = 180;
+	tempoMaximum = 400;
+	posteriorMaximum = 0.1;
+ 
+ */
+	hidePriorMode = false;
+
+	printInterval = true;
+	drawData = false;
+
+	screenToDraw = 0;
+
+	ofSetLineWidth(2); 
+	ofEnableSmoothing();
+	
+	
+	bSnapshot = false;
+	snapCounter = 0;
+
+	drumTracker.paused = false;
+	
+//	setDistributionOnStartTempo = true;
+	
+	resetParameters();
+	
+	arrayToMsecScaleFactor = (drumTracker.tempoMaximum - drumTracker.tempoMinimum)/ ARRAY_SIZE;//turns array into ms	
+	tempoWindowMinimum = 100;
+	tempoWindowMaximum = 150;
+	tempoWindowWidth = 50;
+}
+
+
+void testApp::resetParameters(){
+	/*
+	beatTimes.startIndex = 0;
+	beatTimes.lastBeatTime = 0;
+	maxPhase = 0;
+	posteriorMaximum = 0.1;
+	
+	accompanimentStarted = false;
+
+	tempoDistribution.likelihoodNoise = 0.8;	
+	tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/2);//wide 
+	
+	beatDistribution.initialiseArray();
+	tempoDistribution.initialiseArray();
+	
+	tempoDistribution.calculateStandardDeviation();
+	beatDistribution.calculateStandardDeviation();
+	
+	tempoStdDev = tempoDistribution.standardDeviation;
+	
+	beatTimes.resetBeatTimeArray();
+	*/
+}
+
+//--------------------------------------------------------------
+void testApp::update(){
+
+
+	updateOSCmessages();
+
+	//update tempo window range - this for viewing tempo closeup
+	while (tempoWindowMinimum + tempoWindowWidth/4 > drumTracker.tempoDistribution.integratedEstimate)
+		tempoWindowMinimum  -= tempoWindowWidth/4;
+	
+	while (tempoWindowMinimum + 3*tempoWindowWidth/4 < drumTracker.tempoDistribution.integratedEstimate)
+		tempoWindowMinimum  += tempoWindowWidth/4;
+	
+	tempoWindowMaximum = tempoWindowMinimum + tempoWindowWidth;
+	
+	drumTracker.decayDistributions();
+
+}
+
+
+void testApp::updateOSCmessages(){
+
+	
+	// check for waiting messages
+	while( receiver.hasWaitingMessages() )
+	{
+		ofxOscMessage m;
+		receiver.getNextMessage( &m );
+		string newAddress = m.getAddress();
+
+		if ( m.getAddress() == "/Reset" ){
+			printf("baysian reset\n");
+			drumTracker.resetParameters();
+		}
+		
+		
+		if ( m.getAddress() == "/beatError" ){
+			double timeNow = ofGetElapsedTimeMillis();
+			if (timeNow - drumTracker.setBeatToNowTime > 1000)
+			drumTracker.newKickError(m.getArgAsFloat(0), m.getArgAsFloat(2), m.getArgAsString(1));
+			}//end if new error
+		
+
+		
+			if ( m.getAddress() == "/tatum" ){
+			drumTracker.beatTimes.tatum = m.getArgAsFloat(0);
+			printf("got tatum as %f\n", m.getArgAsFloat(0));
+			}
+			
+			if ( m.getAddress() == "/startTatum" ){
+			drumTracker.startTatum(m.getArgAsFloat(0));
+			printf("START TATUM %f\n", m.getArgAsFloat(0));
+			//then change so tempo distribution is correct....
+			}//end start tatum
+		
+		
+			if ( m.getAddress() == "/uniformTempo" ){
+				drumTracker.setUniformTempo();
+				
+			}
+
+		
+		if ( m.getAddress() == "/uniformPhase" ){
+			drumTracker.setUniformPhase();
+			
+		}
+		
+		
+		if ( m.getAddress() == "/setBeatNow" ){
+			
+			double beatTime = m.getArgAsFloat(0);
+			drumTracker.setBeatNow(beatTime);			
+			//printf("SET BEAT NOW %f\n", beatTime);
+		}
+		 
+		
+			if ( m.getAddress() == "/clickindex" ){
+				
+				int clickIndex = m.getArgAsInt32(0);
+				float clickTime = m.getArgAsFloat(1);
+				drumTracker.setNewClickIndex(clickIndex, clickTime);
+			}
+		
+		
+		if ( m.getAddress() == "/newBeat" ){
+			int beatIndex = m.getArgAsInt32(0);
+			drumTracker.newBeat(beatIndex);
+		}
+		
+		
+	if ( m.getAddress() == "/beatCorrection" )
+		{
+			float beatCorrValue = m.getArgAsFloat(0);
+			drumTracker.doBeatCorrection(beatCorrValue);
+
+		}//end correction by
+		
+			
+			if ( m.getAddress() == "/BayesianNoise" ){
+				drumTracker.beatDistribution.likelihoodNoise = m.getArgAsFloat(0);;	
+				printf("bayesian noise set to %f\n", drumTracker.beatDistribution.likelihoodNoise);
+			//	beatDistribution.setGaussianLikelihood(beatDistribution.likelihoodMean, beatDistribution.likelihoodStdDev);
+			}
+			
+			if ( m.getAddress() == "/BayesianStdDev" ){
+				drumTracker.beatDistribution.likelihoodStdDev = ARRAY_SIZE / m.getArgAsFloat(0);	
+			//	beatDistribution.setGaussianLikelihood(beatDistribution.likelihoodMean, beatDistribution.likelihoodStdDev);
+			}		
+		
+		
+	}//end while there is new message
+
+
+}
+
+
+void testApp::takePictureOfScreen(){
+	// grab a rectangle at 200,200, width and height of 300,180
+	img.grabScreen(0,0,screenWidth,screenHeight);
+	char fileName[255];
+	sprintf(fileName, "snapshot_%0.3i.png", snapCounter);
+	img.saveImage(fileName);
+	//printf("saved %s\n", fileName);
+	snapCounter++;	
+	bSnapshot = false;
+}
+
+/*
+void testApp::setBeatDistribution(int beatPosition){
+	switch (beatPosition){
+			//early sixteenth is that the beat is a sixteenth earlier
+		case 0:
+		case 1:
+		case 11:
+			//i.e. these zones are interpreted as "on the beat"
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;
+			//10 and 2 were here
+			
+		case 2:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
+			//i.e. a 25% chance it is early sixteenth - 75% that the beat actually lies here
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;	
+			
+		case 3:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.3;//was 0.4 in Bayesian8 //half chance it is early 
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;
+			
+		case 5:
+		case 6:
+		case 7:
+			beatDistribution.eighthNoteProportion = 0.3;//i.e. nearly half a chance we are on the 8th note
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0;
+			break;
+			
+		case 4:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
+			beatDistribution.lateSixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
+			//chsanged to 0.2 and 0.1 then back
+			break;
+			
+		case 8:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
+			beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
+			break;
+			
+		case 9:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0.35;//was 0.4 in Bayesian8
+			break;
+			
+		case 10:
+			beatDistribution.eighthNoteProportion = 0;
+			beatDistribution.earlySixteenthNoteProportion = 0;
+			beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.2 in Bayesian8
+			break;
+			
+	}
+
+}
+*/
+//--------------------------------------------------------------
+void testApp::draw(){
+	//---------------------------  lines
+	// a bunch of red lines, make them smooth if the flag is set
+
+	
+	
+	if (bSmooth){
+		ofEnableSmoothing();
+	}
+	
+	switch (screenToDraw){
+		case 0:
+			drawBayesianDistribution();
+			break;
+		case 1:	
+			drawTempoDistribution();
+			break;
+		case 2:
+			drawBeatMap();
+			break;
+		case  3:
+	//		drawNormalisedLikelihood();
+			drawRestrictedTempoDistribution(tempoWindowMinimum, tempoWindowMaximum);
+			break;
+		case  4:
+			drawTempoData();
+			break;
+		case 5:
+			drawBeatProbabilityDistribution();
+			break;
+		case 6:
+			drawPosterior();
+			break;	
+		case 7:
+			drawGreyscaleBayesianDistribution();
+			break;		
+			
+	}	
+	
+	
+	
+	if (bSnapshot == true){
+		takePictureOfScreen();
+		bSnapshot = false;
+	}
+	
+}//end draw
+
+
+void testApp::drawTempoData(){
+	
+	ofSetColor(0xFFFF00);	
+//yellow line in centre
+ofLine(	0, (screenHeight/2), screenWidth, (screenHeight/2));
+
+ofSetColor(0x0000FF);	
+int tempoIndex = 0;	
+int widthOffset = 20;
+float stepWidth = screenWidth / 16;
+	ofDrawBitmapString("tatums : ", 600,180);
+	ofDrawBitmapString(ofToString(drumTracker.beatTimes.tatum, 1), 700,180);
+		ofDrawBitmapString("bpm : ", 600,200);
+	ofDrawBitmapString(ofToString((drumTracker.beatTimes.tatum/30000), 1), 700,200);
+int intervalIndex;
+int intervalWidth = 2;
+float magnifyingFactor = 8;	
+for (tempoIndex = 0;tempoIndex < 16; tempoIndex++){
+
+for (intervalIndex = 0;intervalIndex < 16;intervalIndex++){
+//new color code
+if (drumTracker.beatTimes.intervalUsed[tempoIndex][intervalIndex] == true){
+ofSetColor(0x00FFFF);
+}
+else{
+ofSetColor(0xFF00FF);
+}
+//end new code
+
+ofLine((stepWidth*tempoIndex)+ (intervalWidth*intervalIndex) + widthOffset, screenHeight,
+		(stepWidth*tempoIndex) + (intervalWidth*intervalIndex) + widthOffset, (screenHeight/2) * (1 + (magnifyingFactor * (1-drumTracker.beatTimes.intervalDifferences[tempoIndex][intervalIndex]))));
+		
+		if (printInterval == true){
+		ofDrawBitmapString(ofToString(drumTracker.beatTimes.intervalDifferences[tempoIndex][intervalIndex], 3), 
+		(stepWidth*tempoIndex) + widthOffset,20+(intervalIndex*20));	
+		}
+		
+		
+		ofDrawBitmapString(ofToString(drumTracker.beatTimes.relativeIntervals[tempoIndex][0], 3), 700,220+(tempoIndex*20));
+		ofDrawBitmapString(ofToString(drumTracker.beatTimes.relativeIntervals[tempoIndex][1], 1), 750,220+(tempoIndex*20));
+}//end for interval index
+}//end for tempo index
+	
+		ofDrawBitmapString(ofToString(drumTracker.beatTimes.clickIndex), 750,20);
+	
+	ofDrawBitmapString(ofToString(mouseBPM), 50,20);
+	ofDrawBitmapString(drumTracker.tempoDataString, 50, 100);
+
+}//end draw tempo data
+
+
+void testApp::drawTempoDistribution(){
+	float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
+	
+	maximum *= 1.1;
+	
+	float stepHeight = screenHeight/maximum;
+	
+
+
+//draw prior in green
+	ofSetColor(0x888888);
+	for (int i = 1; i < ARRAY_SIZE; i+=2){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i]*stepHeight));
+	}
+
+
+//draw posterior in dark
+	ofSetColor(0x000000);
+	for (int i = 1; i < ARRAY_SIZE; i++){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i]*stepHeight));
+	}
+
+		
+//black line is the max probability		
+ofSetColor(0x000000);
+		ofLine(drumTracker.tempoDistribution.integratedEstimate *stepSize, screenHeight, drumTracker.tempoDistribution.integratedEstimate *stepSize, 0);
+	
+	//blue is the current kick received	
+	ofSetColor(0xAAAAAA);
+
+int altIndex = 0;
+		for (altIndex = 0;altIndex< 16;altIndex++){
+		
+			double tempoInterval = drumTracker.beatTimes.intervalDifferences[drumTracker.beatTimes.index][altIndex];
+		
+			if (altIndex != drumTracker.beatTimes.index && tempoInterval > drumTracker.tempoMinimum && tempoInterval < drumTracker.tempoMaximum){
+		
+
+
+				//draw likelihood
+				//draw likelhood in blue
+//				//need to reset likelihood for this!
+				//XXX remove
+				double timeInterval = drumTracker.beatTimes.beatTimes[drumTracker.beatTimes.index] - drumTracker.beatTimes.beatTimes[altIndex];
+				if (timeInterval > 2*drumTracker.tempoMinimum && timeInterval < 2*drumTracker.tempoMaximum)
+				{
+					
+				ofLine(stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)), screenHeight,
+						stepSize*(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)) , 0);
+					
+				drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
+				for (int i = 1; i < ARRAY_SIZE; i++){
+				ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i]*stepHeight));
+				}
+				}
+			
+			 }
+			 
+		}//end for
+
+	if (bSmooth){
+		ofDisableSmoothing();
+	}
+
+	drawTempoInfo();	
+	
+}
+
+
+int testApp::xcoordinateFromTempoDataPoint(float f){
+	//f is the time
+	
+	int xcoordinateForInterval = 0;
+	if (f >= drumTracker.tempoMinimum && f <= drumTracker.tempoMaximum)
+		xcoordinateForInterval = ((float)(f - drumTracker.tempoMinimum)*screenWidth/(float)(drumTracker.tempoMaximum - drumTracker.tempoMinimum));
+	return xcoordinateForInterval;
+
+}
+
+
+int testApp::xcoordinateFromRestrictedTempoDataPoint(float f, const int& tmpMin, const int& tmpMax){
+
+
+	int xcoordinateForInterval = -1;
+	if (f >= drumTracker.tempoMinimum+tmpMin && f <= min(drumTracker.tempoMinimum+tmpMax,drumTracker.tempoMaximum))
+		xcoordinateForInterval = ((float)(f - drumTracker.tempoMinimum - tmpMin*arrayToMsecScaleFactor)*screenWidth/(float)((tmpMax - tmpMin)*arrayToMsecScaleFactor));
+	return xcoordinateForInterval;
+	
+}
+
+
+void testApp::drawTempoInfo(){
+	float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
+
+	
+	ofSetColor(0x000000);
+	string testString;
+	testString = "max is ";
+	testString += ofToString(maximum);
+	ofDrawBitmapString(testString, 700,620);
+	
+	ofDrawBitmapString(msg_string, 700,650);
+	
+	ofDrawBitmapString(kickString, 700,670);
+	
+	testString = "std dev : ";
+	testString += ofToString(drumTracker.tempoStdDev, 6);
+	
+	testString += ",   ";
+	testString += ofToString(drumTracker.accompanimentStarted);
+	ofDrawBitmapString(testString, 20, 120);	
+	
+	int tempoUpdateIndex;
+	for (tempoUpdateIndex = 0;tempoUpdateIndex<16;tempoUpdateIndex++){ 
+//		ofDrawBitmapString(tempoUpdateStrings[tempoUpdateIndex], 700, 200 + (20 * tempoUpdateIndex));
+	}
+	
+	ofDrawBitmapString("Mouse located at tempo: ", 50,10);
+	ofDrawBitmapString(ofToString(mouseBPM, 1), 50,20);
+
+	ofDrawBitmapString("Current tempo: ", 50,40);
+	ofDrawBitmapString(ofToString(30000/drumTracker.beatTimes.tatum, 1), 50,50);	
+	
+	ofDrawBitmapString(drumTracker.tempoDataString, 50, 100);
+	
+	
+	for (int i = 1;i < 16; i++){
+		for (int altIndex = 0; altIndex < 16;altIndex++){
+		string newString;
+		newString = "   :";
+			int recentIndex = (altIndex-i+16)%16;
+			if (drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex] > 0 && drumTracker.beatTimes.intervalUsed[altIndex][recentIndex]){
+
+	
+				int xcoordinateForInterval = xcoordinateFromTempoDataPoint(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex]);
+				float beatInterval = (float) drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2;
+			
+				if (drumTracker.beatTimes.OnsetIsKick[altIndex])
+				ofSetColor(255*(8-beatInterval)/(float)8, 0, 255*beatInterval/(float)8);
+				else 
+					ofSetColor(0, 255*(8-beatInterval)/(float)8, 255*beatInterval/(float)8);
+				//red kick, green snare
+				
+				ofCircle(xcoordinateForInterval, 200 + (altIndex * 20), 3);
+				
+				newString += ofToString(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex],0);
+				newString += " (";
+				newString += ofToString(drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2, 0);
+				newString += ")";
+				
+			}
+			ofSetColor(0,0,0);
+			//ofDrawBitmapString(newString, 200 + i*80, 200 + (altIndex * 20));
+			
+			
+		}
+	}
+	
+}
+
+
+
+
+void testApp::drawTempoDataPoints(const int& tmpMin, const int& tmpMax, const float& tmpStepSize){
+	
+	for (int i = 1;i < 16; i++){
+		for (int altIndex = 0; altIndex < 16;altIndex++){
+		//	string newString;
+		//	newString = "   :";
+			
+			int recentIndex = (altIndex-i+16)%16;
+			if (drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex] > 0 && drumTracker.beatTimes.intervalUsed[altIndex][recentIndex]){
+				
+				int xcoordinateForInterval = xcoordinateFromRestrictedTempoDataPoint(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex], tmpMin, tmpMax);
+				float beatInterval = (float) drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2;
+				
+				if (drumTracker.beatTimes.OnsetIsKick[altIndex])
+					ofSetColor(255*(7-beatInterval+1)/(float)7, 255*(beatInterval-1)/(float)7, 0);//100+155*(8-beatInterval)/(float)8
+				else 
+					ofSetColor(0, 255*(7-beatInterval+1)/(float)7, 255*(beatInterval-1)/(float)7);//, 155*beatInterval/(float)8);
+				//red kick, green snare
+				
+				ofCircle(xcoordinateForInterval, 200 + (altIndex * 20), 3);
+				ofDrawBitmapString(ofToString(beatInterval, 0), xcoordinateForInterval-2, 200 + (altIndex * 20) - 3);
+			/*	newString += ofToString(beatTimes.intervalDifferences[altIndex][recentIndex],0);
+				newString += " (";
+				newString += ofToString(beatTimes.tatumMultiples[altIndex][recentIndex]/2, 0);
+				newString += ")";
+			*/	
+			}
+			ofSetColor(0,0,0);
+			//ofDrawBitmapString(newString, 200 + i*80, 200 + (altIndex * 20));
+			
+			
+		}
+	}
+	
+}
+
+
+void testApp::drawRestrictedTempoDistribution(int tmpMin, int tmpMax){
+	//min and max are in the tempo array coordinates
+	
+	tmpMin = max(tmpMin, 0);
+	tmpMax = min(tmpMax, ARRAY_SIZE-1);
+	
+	float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
+	
+	maximum *= 1.1;
+	
+	float stepHeight = screenHeight/maximum;
+	int tmpWidth = tmpMax - 1 - tmpMin;
+	float tmpStepSize = screenWidth / (float) tmpWidth;
+	
+	
+	//draw prior in green
+	ofSetColor(0x888888);
+	for (int i = 1; i < tmpWidth; i+=2){
+		ofLine((i-1)*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.prior[tmpMin+i-1]*stepHeight), i * tmpStepSize, screenHeight - (drumTracker.tempoDistribution.prior[tmpMin+i]*stepHeight));
+	}
+	
+	
+	//draw posterior in dark
+	ofSetColor(0x000000);
+	for (int i = 1; i < tmpWidth; i++){
+		ofLine((i-1) * tmpStepSize, screenHeight - (drumTracker.tempoDistribution.posterior[tmpMin+i-1]*stepHeight), i*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.posterior[tmpMin+i]*stepHeight));
+	}
+	
+	
+	//black line is the max probability		
+	ofSetColor(0x000000);
+	ofLine((drumTracker.tempoDistribution.integratedEstimate - tmpMin)* tmpStepSize, screenHeight, (drumTracker.tempoDistribution.integratedEstimate-tmpMin) *tmpStepSize, 0);
+	
+	//blue is the current kick received	
+	ofSetColor(0xAAAAAA);
+	
+	int altIndex = 0;
+	for (altIndex = 0;altIndex< 16;altIndex++){
+		//iterate through all recent beat intervals
+		
+		double tempoInterval = drumTracker.beatTimes.intervalDifferences[drumTracker.beatTimes.index][altIndex];
+		
+		if (altIndex != drumTracker.beatTimes.index && tempoInterval > drumTracker.tempoMinimum && tempoInterval < drumTracker.tempoMaximum){
+			
+			double timeInterval = drumTracker.beatTimes.beatTimes[drumTracker.beatTimes.index] - drumTracker.beatTimes.beatTimes[altIndex];
+			
+			if (timeInterval > 2*drumTracker.tempoMinimum && timeInterval < 2*drumTracker.tempoMaximum){
+				//i.e. within the beat range only
+				//so we only draw the likelihood realtime for happening beat intervals
+				//in fact much more is going on than this but harder to visualise
+			
+				float indexOfNewLocation = ARRAY_SIZE*(tempoInterval-drumTracker.tempoMinimum)/(float)(drumTracker.tempoMaximum - drumTracker.tempoMinimum);
+				
+
+				if (indexOfNewLocation >= tmpMin){
+					ofLine(tmpStepSize * (indexOfNewLocation-tmpMin), screenHeight, tmpStepSize * (indexOfNewLocation-tmpMin) , 0);
+				}
+				
+				
+				drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
+			//setting the tempo distribution likeihood just for visualisation purposes
+				for (int i = 1; i < tmpWidth; i++){
+					ofLine((i-1)*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i+tmpMin-1]*stepHeight), i*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i+tmpMin]*stepHeight));
+					
+				}
+			}
+			
+		}
+		
+	}//end for
+	
+	if (bSmooth){
+		ofDisableSmoothing();
+	}
+	
+	
+	drawTempoDataPoints(tmpMin, tmpMax, tmpStepSize);
+	
+// lines for background
+	for (int i = tmpMin-(tmpMin%20);i < tmpMax; i+=20){
+		ofSetColor(0,0,200,100);
+		ofLine(tmpStepSize * (i-tmpMin), screenHeight, tmpStepSize * (i-tmpMin) , 0);
+		string tmpTempoString = ofToString(drumTracker.tempoMinimum + i*arrayToMsecScaleFactor, 0);
+		ofDrawBitmapString(tmpTempoString, tmpStepSize * (i-tmpMin) , 20);
+	}
+
+	string currentTatumString = "Beat Period : ";
+	currentTatumString += ofToString(drumTracker.beatTimes.tatum, 1);
+	currentTatumString += "  MaxIndex : ";
+	currentTatumString += ofToString(drumTracker.tempoDistribution.integratedEstimate, 1);
+	
+	ofDrawBitmapString(currentTatumString, 20, 40);
+	//drawTempoInfo();	
+	
+}
+
+
+
+
+
+
+
+
+
+
+
+void testApp::drawBeatMap(){
+int x,y;
+
+for (x=0;x < 6;x++){
+	for (y=0;y<8;y++){
+	int cell = x+(y*6);
+	if (cell == drumTracker.beatTimes.beatSegment){
+		if (drumTracker.beatTimes.beatMap[cell] == 1)//for kick
+	ofSetColor(drumTracker.beatTimes.beatMap[cell]*255, 0, 0);
+	
+		if (drumTracker.beatTimes.beatMap[cell] == 2)//for kick
+	ofSetColor(0, drumTracker.beatTimes.beatMap[cell]*255, 100);			
+	
+	}
+	else{
+		if (drumTracker.beatTimes.beatMap[cell] == 1)//for kick
+	ofSetColor(drumTracker.beatTimes.beatMap[cell]*155, 0, 0);
+		else //for snare
+	ofSetColor(0,drumTracker.beatTimes.beatMap[cell]*155, 0);//beatTimes.beatMap[cell]*155);
+		
+	}
+	ofRect(screenWidth*x/6, screenHeight*y/8, screenWidth/6, screenHeight/8);
+
+	ofSetColor(255,0,0);
+		ofDrawBitmapString(ofToString(x+(y*6)), screenWidth*x/6, screenHeight*y/8);
+		
+		if (drumTracker.beatTimes.beatMap[cell] == 1){
+		ofSetColor(0,255,255);//
+		ofDrawBitmapString(ofToString(drumTracker.beatTimes.beatMapTimeDifferences[cell], 2), (screenWidth*(x+0.5)/6) , (screenHeight*(y+0.5)/8) );
+		}
+		if (drumTracker.beatTimes.beatMap[cell] == 2){
+			ofSetColor(0,0,100);//
+			ofDrawBitmapString(ofToString(drumTracker.beatTimes.beatMapTimeDifferences[cell], 2), (screenWidth*(x+0.5)/6) , (screenHeight*(y+0.5)/8) );
+		}		
+		
+		
+	}
+}
+
+}
+
+
+
+
+void testApp::drawBeatProbabilityDistribution(){
+	int x,y;
+	
+	for (x=0;x < 6;x++){
+		for (y=0;y<4;y++){
+			int cell = x+(y*6);
+			ofSetColor(drumTracker.beatTimes.beatProbabilityDistribution[y][x][0]*255, 0, 0);
+			ofRect(screenWidth*x/6, screenHeight*y/8, screenWidth/6, screenHeight/8);
+				}
+	}
+	for (x=0;x < 6;x++){
+		for (y=0;y<4;y++){
+			int cell = x+(y*6);
+			ofSetColor(0, drumTracker.beatTimes.beatProbabilityDistribution[y][x][1]*255, 0);
+			ofRect(screenWidth*x/6, screenHeight*(y+4)/8, screenWidth/6, screenHeight/8);
+		}
+	}
+	
+}
+
+
+void testApp::drawNormalisedLikelihood(){
+	float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
+	//maximum = max(maximum, beatDistribution.getMaximum(&beatDistribution.posterior[0], ARRAY_SIZE));
+	float stepHeight = screenHeight/maximum;
+	
+if (!hidePriorMode){	
+//draw likelhood in blue
+	
+	ofSetColor(0x0000FF);
+	for (int i = 1; i < ARRAY_SIZE; i++){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
+	}
+
+//draw prior in green
+	ofSetColor(0x00AA00);
+	for (int i = 1; i < ARRAY_SIZE; i++){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
+	}
+}//end hide prior mode
+
+
+
+}
+
+
+
+void testApp::drawPosterior(){
+	float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE);
+	
+	if (drumTracker.posteriorMaximum < maximum){
+		drumTracker.posteriorMaximum = 1.2*maximum;
+	}
+	
+	float stepHeight = screenHeight/drumTracker.posteriorMaximum;
+		ofSetColor(0xFF00FF);
+		for (int i = 1; i < ARRAY_SIZE; i++){
+			ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
+		}
+			
+	
+	//yellow is the middle
+	ofSetColor(0xFFFF00);
+	ofLine(ARRAY_SIZE*stepSize/2, screenHeight, ARRAY_SIZE*stepSize/2, 0);
+
+	
+	
+	//blue is the current kick received	
+	ofSetColor(0x0000FF);
+	ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), screenHeight,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), 0);
+
+	//purple line is the integrated max probability	
+	int integratedBeatEstimateDrawPoint = round(drumTracker.beatDistribution.integratedEstimate*stepSize) ;
+	ofSetColor(0xFF22FF);
+	ofLine(integratedBeatEstimateDrawPoint, screenHeight, integratedBeatEstimateDrawPoint, 0);
+	
+	string testString = "maximum: ";
+	testString += ofToString(drumTracker.posteriorMaximum, 2);	
+	ofDrawBitmapString(testString, 100,120);
+	
+	
+}
+
+
+
+
+
+void testApp::drawBayesianDistribution(){
+	float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
+	maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
+	float stepHeight = screenHeight/maximum;
+	
+	if (!hidePriorMode){	
+		//draw likelhood in blue
+		if (drumTracker.onsetType == "kick")
+			ofSetColor(0xff0000);//red : kick
+		else
+			ofSetColor(0x00FF00);//green : snare	
+
+		for (int i = 1; i < ARRAY_SIZE; i++){
+			ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
+		}
+		
+		//;line where the current kick is received	
+		ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), screenHeight,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), 0);
+		
+		
+		//draw prior in aqua blue
+		ofSetColor(0x00AAAA);
+		for (int i = 1; i < ARRAY_SIZE; i++){
+			ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
+		}
+	}//end hide prior mode
+	
+	//draw posterior in red
+	ofSetColor(0x0000FF);
+	for (int i = 1; i < ARRAY_SIZE; i++){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
+	}
+	
+	//draw the previous updated posteriror in purple
+	/*	ofSetColor(0xFF22FF);
+	 for (int i = 1; i < ARRAY_SIZE; i++){
+	 ofLine((i-1)*stepSize, screenHeight - (tmpArray[i-1]*stepHeight), i*stepSize, screenHeight - (tmpArray[i]*stepHeight));
+	 }
+	 */
+	
+	//yellow is the middle
+	ofSetColor(0xFFFF00);
+	ofLine(ARRAY_SIZE*stepSize/2, screenHeight, ARRAY_SIZE*stepSize/2, 0);
+	
+	//black line is the max probability		
+	ofSetColor(0x000000);
+	ofLine(drumTracker.beatDistribution.maximumIndex*stepSize, screenHeight, drumTracker.beatDistribution.maximumIndex*stepSize, 0);
+	
+	
+	//purple line is the integrated max probability	
+	int integratedBeatEstimate = drumTracker.beatDistribution.integratedEstimate ;
+	ofSetColor(0x2222FF);
+	ofLine(integratedBeatEstimate *stepSize, screenHeight, integratedBeatEstimate *stepSize, 0);
+	
+
+	if (bSmooth){
+		ofDisableSmoothing();
+	}
+	
+	printBayesianData();
+}
+
+void testApp::printBayesianData(){
+	//not optimised!!! XXX
+	float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
+	maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
+	
+	ofSetColor(0x000000);
+	string testString;
+	testString = "max2 is ";
+	testString += ofToString(maximum, 3);
+	testString += " :: ";
+	
+	testString = "correction of ";
+	testString += ofToString(drumTracker.beatCorrection);
+	testString += " corr by :";
+	testString += ofToString(drumTracker.correctBeatBy);
+	
+	//ofDrawBitmapString(testString, 100,120);
+	
+	testString = "MaxPhase ";
+	testString += ofToString(drumTracker.maxPhase);
+//	ofDrawBitmapString(testString, 100,140);
+	
+	
+	testString = "Likelihood noise ";
+	testString += ofToString(drumTracker.beatDistribution.likelihoodNoise, 2);
+	//ofDrawBitmapString(testString, 100,160);	
+	
+//	ofDrawBitmapString(msg_string, 100,140);
+	
+//	ofDrawBitmapString(kickString, 100,180);
+	
+/*	debugString = "Min Debug = ";
+	debugString += ofToString(drumTracker.tempoDistribution.maximumIndex + drumTracker.minTempoIndex);
+	debugString += "  Max  Debug = ";
+	debugString += ofToString(drumTracker.tempoDistribution.maximumIndex + drumTracker.maxTempoIndex);
+*/	
+	//ofDrawBitmapString(debugString, 300,370);
+	
+	debugString = "CLICK INDEX = ";
+	debugString += ofToString(drumTracker.beatTimes.clickIndex);
+	//ofDrawBitmapString(debugString, 100, 20);
+	
+	debugString = "STD DEV = ";
+	debugString += ofToString(drumTracker.beatDistribution.standardDeviation, 2);
+//	ofDrawBitmapString(debugString, 100, 40);
+	
+	
+	
+	debugString = "interval ";
+	debugString += ofToString(drumTracker.debugArray[2], 2);
+	debugString += " time int = ";
+	debugString += ofToString(drumTracker.debugArray[1], 2);
+	debugString += " Beat max = ";
+	debugString += ofToString(drumTracker.debugArray[0 ], 2);	
+	debugString += " Tempo max = ";
+	debugString += ofToString(drumTracker.debugArray[3 ], 2);	
+//	ofDrawBitmapString(debugString, 300,570);
+	
+	debugString = " last = ";
+	debugString += ofToString(drumTracker.beatTimes.lastBeatTime, 2);
+//	ofDrawBitmapString(debugString, 300,470);
+	
+	
+	string closestClickString = "Closest Click ";
+	closestClickString += ofToString(drumTracker.beatTimes.closestClickIndexToBeat[drumTracker.beatTimes.index]);
+	closestClickString += "  beat seg ";
+	closestClickString += ofToString(drumTracker.beatTimes.beatSegment%12);
+	closestClickString += "  lastCindex";
+	closestClickString += ofToString(drumTracker.beatTimes.lastClickIndex);
+	closestClickString += "  TD ";
+	closestClickString += ofToString(drumTracker.beatTimes.timeDifference);
+	
+//	ofDrawBitmapString(closestClickString, 100,100);
+	
+//	ofDrawBitmapString(timeString, 100,60);
+}
+
+
+
+void testApp::drawGreyscaleBayesianDistribution(){
+	ofSetColor(255,255,255);
+	ofRect(0,0,screenWidth, screenHeight);
+	
+	float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
+	maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
+	maximum *= 1.1;
+	float stepHeight = screenHeight/maximum;
+	
+	if (!hidePriorMode){	
+		//draw likelhood in blue
+		ofSetColor(0x555555);
+		for (int i = 1; i < ARRAY_SIZE; i+=2){
+			ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
+		}
+		
+		//draw prior in green
+		ofSetColor(0xAAAAAA);
+		for (int i = 1; i < ARRAY_SIZE; i++){
+			ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
+		}
+	}//end hide prior mode
+	
+	//draw posterior in dark grey
+	ofSetColor(0x222222);
+	for (int i = 1; i < ARRAY_SIZE; i++){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
+	}
+	 
+	/*
+	//dotted the middle
+	ofSetColor(0x555555);
+	for (int i = 1; i < screenHeight; i+=4){
+		ofLine(ARRAY_SIZE*stepSize/2, i, ARRAY_SIZE*stepSize/2, i-2);
+	}
+	*/
+	
+	//purple line is the integrated max probability	
+//	int integratedBeatEstimate = beatDistribution.integratedEstimate ;
+//	ofSetColor(0x000000);
+//	ofLine(integratedBeatEstimate *stepSize, screenHeight, integratedBeatEstimate *stepSize, 0);
+	
+	//purple line is the integrated max probability	
+	float tmpIntegratedBeatEstimate = drumTracker.beatDistribution.getIntegratedEstimateIndex();
+	ofSetColor(0x000000);
+	int drawLinePoint = round(tmpIntegratedBeatEstimate *stepSize);
+	ofLine(drawLinePoint, screenHeight, drawLinePoint, 0);
+	
+	//blue is the current kick received	
+	ofSetColor(0x555555);
+	for (int i = 1; i < screenHeight; i+=40){
+	ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), i,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), i-20);
+	}
+	
+	
+}
+
+
+
+
+void testApp::drawGreyscaleTempoDistribution(double tempoInterval){
+	ofSetColor(255,255,255);
+	ofRect(0,0,screenWidth, screenHeight);
+	
+	float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
+	maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
+	
+	maximum *= 1.1;
+	
+	float stepHeight = screenHeight/maximum;
+	
+	//draw prior in green
+	ofSetColor(0x777777);
+	for (int i = 1; i < ARRAY_SIZE; i++){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i]*stepHeight));
+	}
+	
+	
+	//draw posterior in dark
+	ofSetColor(0x000000);
+	for (int i = 1; i < ARRAY_SIZE; i++){
+		ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i]*stepHeight));
+	}
+	
+	
+	//black line is the max probability		
+	ofSetColor(0xFF0000);
+	ofLine(drumTracker.tempoDistribution.integratedEstimate *stepSize, screenHeight, drumTracker.tempoDistribution.integratedEstimate *stepSize, 0);
+	
+	//blue is the current kick received	
+	ofSetColor(0xAAAAAA);
+
+		
+		
+				
+				for (int k =1;k < screenHeight/12;k+=2){
+				ofLine(stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)), 12*k,
+					   stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)) , 12*(k-1));
+				}
+				
+				drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
+				for (int i = 1; i < ARRAY_SIZE; i+=2){
+					//dotted line likelihood fn
+					ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i]*stepHeight));
+				}
+			
+			
+		
+	
+	if (bSmooth){
+		ofDisableSmoothing();
+	}
+	
+}
+
+
+
+
+//--------------------------------------------------------------
+void testApp::keyPressed  (int key){
+	if (key == 's'){
+		bSmooth = !bSmooth;
+	}
+
+	if (key == 'x'){
+	printInterval = !printInterval;
+	}
+	
+	
+	if (key == 'y'){
+	drawData = !drawData;
+	}
+	
+	if (key == 'f'){
+		ofToggleFullscreen();
+	}
+
+	if (key == 'h' || key == 'H'){
+	hidePriorMode = !hidePriorMode;//drawData;
+	}
+
+
+
+if ( key =='a' || key == 'A' )
+	{
+
+	}
+
+	if (key == ' '){
+	drumTracker.paused = !drumTracker.paused;
+	}
+
+	if (key == OF_KEY_RIGHT){
+		screenToDraw++;
+		screenToDraw = screenToDraw % NUMBER_OF_SCREENS;
+	}
+	if (key == OF_KEY_LEFT){
+		screenToDraw += NUMBER_OF_SCREENS - 1;
+		screenToDraw = screenToDraw % NUMBER_OF_SCREENS;
+	}
+	
+	if (key == ']')
+		drumTracker.beatDistribution.translateDistribution(ARRAY_SIZE / 4);
+	
+	if (key == '[')
+		drumTracker.beatDistribution.translateDistribution(-1*ARRAY_SIZE / 4);
+	
+	if (key == 'x'){
+		bSnapshot = true;
+	}
+	
+	if (key == 'q')
+		drumTracker.adaptiveStandardDeviationMode = !drumTracker.adaptiveStandardDeviationMode;
+	
+}
+
+/*
+void testApp::sendMaxTempo(){
+	ofxOscMessage m;
+		m.setAddress( "/tempo" );
+	
+		//maxTempo = tempoDistribution.maximumIndex * (tempoMaximum - tempoMinimum) /  ARRAY_SIZE;
+		//would be introduced new in bayesian8
+		maxTempo = drumTracker.tempoDistribution.getIntegratedEstimateIndex() * (tempoMaximum - tempoMinimum) /  ARRAY_SIZE;
+		maxTempo += tempoMinimum;
+		
+	
+		m.addFloatArg( maxTempo );
+		sender.sendMessage( m );
+
+	printf("max tempo %f\n", maxTempo);
+
+}
+
+void testApp::sendMaxPhase(){
+
+
+	//	maxPhase = (beatDistribution.maximumIndex - (ARRAY_SIZE/2)) / ARRAY_SIZE;
+		maxPhase = (drumTracker.beatDistribution.getIntegratedEstimateIndex() - (ARRAY_SIZE/2)) / ARRAY_SIZE;
+	printf("\nphase index %f :: %i\n", drumTracker.beatDistribution.integratedEstimate , maxPhase);
+		ofxOscMessage m;
+		m.setAddress( "/phase" );
+		m.addFloatArg( maxPhase );
+		sender.sendMessage( m );
+		
+		//beatCorrection = maxPhase * beatTimes.tatum / 4;
+}
+ */
+//--------------------------------------------------------------
+void testApp::keyReleased  (int key){
+
+}
+
+//--------------------------------------------------------------
+void testApp::mouseMoved(int x, int y ){
+
+	mouseBPM = convertToBPM(drumTracker.tempoMinimum+ ((x * (drumTracker.tempoMaximum - drumTracker.tempoMinimum) ) / ofGetWidth() )) ;
+}
+
+//--------------------------------------------------------------
+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){
+	screenWidth = ofGetWidth();
+	screenHeight = ofGetHeight();	
+	stepSize = screenWidth / (float)(ARRAY_SIZE);
+}
+
+double testApp::convertToBPM(double interval){
+//interval is in ms and is the tatum interval - eighth nbote - so 250ms for 120bpm
+return (30000/interval);
+
+}
+/*
+noyt needed?
+float testApp::tempoIndexToMsec(int index){
+float msec;
+msec = index * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
+msec += tempoMinimum;
+return msec;
+}
+
+float testApp::beatIndexToMsec(int index){
+float msec;
+msec = index * maxTempo / ARRAY_SIZE;
+msec += tempoMinimum;
+return msec;
+}
+*/
+/*
+ 
+ bool testApp::filterBeatTime(double newBeatTime){
+ bool newBeatFound = false;
+ if ((newBeatTime - 	beatTimes.lastBeatTime) > 20 || beatTimes.lastBeatTime == 0){
+ 
+ crossUpdateArrays((float)(newBeatTime - beatTimes.lastBeatTime));
+ beatTimes.lastBeatTime = newBeatTime;
+ newBeatFound = true;
+ }
+ return newBeatFound;
+ }
+ 
+ void testApp::crossUpdateArrays(float timeInterval){
+ 
+ int finalBeatIndex, tmpTempoIndex, startBeatIndex;
+ //finalBeat has contribution from BEAT[finalBeat + INT.k] * TEMPO[Max_tempo + k] where INT = INTERVAL
+ float interval;
+ interval = timeInterval / maxTempo;//beatTimes.tatum;
+ tempoDistribution.resetMaximumPosterior();
+ beatDistribution.resetMaximumPosterior();
+ 
+ 
+ int tmpBeatIndex;
+ //&& interval > 0.8 idea?
+ if (timeInterval > 0 && timeInterval < 12000 ){//need between 0 and 12 seconds only to update
+ 
+ for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
+ 
+ tmpArray[tmpBeatIndex] = 0;
+ float minusMsecToMakeUp =  beatIndexToMsec(tmpBeatIndex) / interval;
+ float plusMsecToMakeUp =  beatIndexToMsec(ARRAY_SIZE - tmpBeatIndex) / interval;
+ float convertMsecToTempoIndex = ARRAY_SIZE / (tempoMaximum - tempoMinimum) ;
+ 
+ 
+ int minTempoIndex = -1 * (int)(minusMsecToMakeUp * convertMsecToTempoIndex);
+ int maxTempoIndex = (int)(plusMsecToMakeUp * convertMsecToTempoIndex);
+ 
+ 
+ if (tmpBeatIndex == beatDistribution.maximumIndex){
+ minTmpDebug = tempoDistribution.maximumIndex + minTempoIndex;
+ maxTmpDebug = tempoDistribution.maximumIndex + maxTempoIndex;
+ debugArray[0] = beatDistribution.maximumIndex;//
+ debugArray[1] = timeInterval;
+ debugArray[2]  = interval;//beatDistribution.maximumIndex;
+ debugArray[3]  = tempoDistribution.maximumIndex;
+ }
+ 
+ for (tmpTempoIndex = minTempoIndex;tmpTempoIndex <= maxTempoIndex;tmpTempoIndex++){
+ 
+ if ((tempoDistribution.maximumIndex + tmpTempoIndex) >= 0 
+ && (tempoDistribution.maximumIndex + tmpTempoIndex) < ARRAY_SIZE 
+ && (tmpBeatIndex - (int)(interval*tmpTempoIndex)) >= 0 
+ && (tmpBeatIndex - (int)(interval*tmpTempoIndex))< ARRAY_SIZE){	
+ tmpArray[tmpBeatIndex] += beatDistribution.posterior[tmpBeatIndex - (int)(interval*tmpTempoIndex)] * tempoDistribution.posterior[(int)tempoDistribution.maximumIndex + tmpTempoIndex];
+ }
+ }//end for tmpTmepo
+ 
+ 
+ 
+ }
+ 
+ float tmpFloat;
+ for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
+ //debug - dont actually update::
+ 
+ tmpFloat = 	beatDistribution.posterior[tmpBeatIndex];
+ beatDistribution.posterior[tmpBeatIndex] = tmpArray[tmpBeatIndex];
+ tmpArray[tmpBeatIndex] = tmpFloat;
+ }
+ beatDistribution.renormaliseArray(&beatDistribution.posterior[0], ARRAY_SIZE);
+ 
+ }	//end if
+ 
+ 
+ }
+ 
+ 
+ void testApp::updateTempoProcess(double cpuTime, string onsetDescription){
+ 
+ if (filterBeatTime(cpuTime) == true){
+ //checks for no repeat
+ 
+ if (onsetDescription == "kick")
+ beatTimes.addBeatTime(cpuTime, 1);
+ else 
+ beatTimes.addBeatTime(cpuTime, 2);		
+ 
+ 
+ //recalculate the distribution
+ int altIndex = 0;
+ 
+ tempoDataString = "Tatum :";
+ tempoDataString += ofToString(beatTimes.tatum, 2);
+ tempoDataString += "   BPM ";
+ tempoDataString += ofToString((double)30000/beatTimes.tatum, 2);
+ 
+ timeString = "Last BEAT ";
+ timeString += ofToString(beatTimes.lastBeatTime);
+ timeString += "  CLICK ";
+ timeString += ofToString(beatTimes.lastClickTime);
+ timeString += "  DIFDF ";
+ timeString += ofToString(beatTimes.timeDifference);
+ timeString += "  segment ";
+ timeString += ofToString(beatTimes.beatSegment);
+ 
+ 
+ for (altIndex = 0;altIndex< 16;altIndex++){
+ tempoInterval = beatTimes.intervalDifferences[beatTimes.index][altIndex];
+ integerMultipleOfTatum = beatTimes.relativeIntervals[altIndex][1];
+ 
+ 
+ ///NEW VERSION	
+ tempoUpdateStrings[altIndex] = "";
+ double timeInterval = beatTimes.beatTimes[beatTimes.index] - beatTimes.beatTimes[altIndex];	
+ //raw time difference
+ beatTimes.intervalDifferences[beatTimes.index][altIndex] = 0;
+ beatTimes.intervalUsed[beatTimes.index][altIndex] = false;
+ 
+ if (onsetType == "kick")
+ beatTimes.OnsetIsKick[beatTimes.index] = true;
+ else 
+ beatTimes.OnsetIsKick[beatTimes.index] = false;
+ 
+ 
+ 
+ if (!accompanimentStarted){
+ //if we need to find tempo and start use this method
+ //we have 'started' once std dev is sufficiently low
+ 
+ updateTempoIfWithinRange(timeInterval);//taken as being the tatum interval
+ 
+ 
+ 
+ for (int i = 1;i <= 4;i++){
+ //we test the main beats and the two bar (16 tatum intervals)
+ 
+ double	testInterval = timeInterval / 2*i;//pow(2, i);//pow(2.0, i);
+ 
+ if (updateTempoIfWithinRange(testInterval)){
+ printf("test time %f, beats %i\n", testInterval, i);
+ 
+ beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
+ beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
+ //xx what if two within range here?
+ 
+ tempoUpdateStrings[altIndex] = "Tempo Updates (";
+ tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
+ tempoUpdateStrings[altIndex]  +=  ") : [";
+ tempoUpdateStrings[altIndex] += ofToString(altIndex);
+ tempoUpdateStrings[altIndex] += "]] : ";
+ tempoUpdateStrings[altIndex] += ofToString(timeInterval);
+ tempoUpdateStrings[altIndex] += ", ioi:";
+ tempoUpdateStrings[altIndex] += ofToString(i);
+ //tempoUpdateStrings[altIndex] += "";
+ 
+ }
+ 
+ }
+ 
+ double	testInterval = timeInterval / 16;//pow(2, i);//pow(2.0, i);
+ if (updateTempoIfWithinRange(testInterval)){
+ beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
+ beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
+ }
+ 
+ }else{
+ //OLD VERSON
+ //THIS USES THE CURRENT TEMPO ESTIMATE TO DECIDE WHAT THE BEST INTERVAL IS
+ //&& integerMultipleOfTatum % 2 == 0 removed below XXX put back
+ if (altIndex != beatTimes.index && integerMultipleOfTatum < 17 
+ && integerMultipleOfTatum > 0 && beatTimes.startIndex > 8//beattimes.index > 8 - the start
+ && integerMultipleOfTatum%2 == 0){//mod 2 - i.e. proper beat intervals only
+ 
+ double testInterval = timeInterval / integerMultipleOfTatum;
+ 
+ if (updateTempoIfWithinRange(testInterval)){
+ 
+ beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
+ beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
+ 
+ if (paused == false){
+ tempoUpdateStrings[altIndex] = "Tempo Updates : (";
+ tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
+ tempoUpdateStrings[altIndex]  +=  ") : ["; 
+ tempoUpdateStrings[altIndex] += ofToString(altIndex, 0);
+ tempoUpdateStrings[altIndex]  +=  "] :: "; 	 
+ tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
+ tempoUpdateStrings[altIndex] += " intervals :: ";
+ tempoUpdateStrings[altIndex] += ofToString(tempoInterval);
+ tempoUpdateStrings[altIndex] += " ms.";
+ // tempoUpdateStrings[altIndex] += ", ioi:";
+ 
+ // tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
+ 
+ 
+ 
+ 
+ }//end if not paused
+ 
+ 
+ }//end if good interval to update
+ 
+ }//end if not same index etc
+ 
+ 
+ }
+ 
+ 
+ 
+ }//end for all intervals
+ 
+ sendMaxTempo();
+ }//end if new beat time
+ double tempoEstimate = tempoDistribution.getIntegratedEstimateIndex();
+ tempoDistribution.calculateStandardDeviation();
+ tempoStdDev = tempoDistribution.standardDeviation;	
+ 
+ }
+ 
+ 
+ bool testApp::updateTempoIfWithinRange(double timeInterval){
+ 
+ bool updated = false;
+ 
+ if (timeInterval > tempoMinimum && timeInterval < tempoMaximum ){
+ calculateTempoUpdate(timeInterval);
+ updated = true;
+ }
+ 
+ return updated;
+ }
+ 
+ 
+ */
+//end
+/*
+void testApp::calculateTempoUpdate(double tempoInterval){
+	
+	
+	tempoDistribution.resetPrior();		
+	//need to relook at likelihood for the tempo distribution - not the same as....
+	tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval-tempoMinimum)/(tempoMaximum - tempoMinimum), tempoDistribution.likelihoodStdDev);
+	tempoDistribution.calculatePosterior();
+	tempoDistribution.renormalisePosterior();
+
+	//did take pic of screen here - see initialiser4
+}
+*/
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/testApp.h	Tue Aug 30 20:16:35 2011 +0100
@@ -0,0 +1,159 @@
+#ifndef _TEST_APP
+#define _TEST_APP
+
+
+
+#include "ofMain.h"
+#include "ofxOsc.h"
+//#include "bayesianArray.h"
+//#include "beatTempo.h"
+#include "BayesDrumTracker.h"
+
+// listen on port 12345
+#define PORT 12345
+#define NUM_MSG_STRINGS 45
+#define HOST "localhost"
+#define ARRAY_SIZE 240//need to replace this with const int in drumtracker
+
+#define NUMBER_OF_SCREENS 8
+
+class testApp : public ofBaseApp{
+	
+	public:
+		
+		void setup();
+		void update();
+		void draw();
+		void drawBayesianDistribution();
+		void drawTempoData();
+		void drawTempoDistribution();
+		void drawRestrictedTempoDistribution(int tmpMin, int tmpMax);
+	
+		void drawBeatMap();
+		void drawNormalisedLikelihood();
+		void drawBeatProbabilityDistribution();
+		void drawPosterior();
+		void printBayesianData();
+		void drawGreyscaleBayesianDistribution();
+	void drawGreyscaleTempoDistribution(double tempoInterval);
+		void drawTempoInfo();
+	
+		void resetParameters();
+		void takePictureOfScreen();
+	
+		void crossUpdateArrays(float timeInterval);
+		void updateTempoProcess(double cpuTime, string onsetType);
+		
+		void sendMaxTempo();
+		void sendMaxPhase();
+		double convertToBPM(double interval);
+		bool filterBeatTime(double newBeatTime);
+		
+//		float beatIndexToMsec(int index);
+//		float tempoIndexToMsec(int index);
+		
+		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 setGaussianLikelihood(float mean, float StdDev);	
+		void setGaussianPrior(float mean, float StdDev);	
+		void calculatePosterior();
+		void renormalisePosterior();
+		float getMaximum(float *ptr, int length);
+		void renormaliseArray(float *ptr, int length);
+		void updateOSCmessages();
+		void resetPrior();
+		void decayPosterior();
+		void translateDistribution(int translationIndex);
+		void setBeatDistribution(int beatPosition);
+		void calculateTempoUpdate(double tempoInterval);
+		bool updateTempoIfWithinRange(double timeInterval);
+		
+		float* getMaximumEstimate(float *ptr, int length);
+		void drawTempoDataPoints(const int& tmpMin, const int& tmpMax, const float& tmpStepSize);
+		int xcoordinateFromTempoDataPoint(float f);
+		int xcoordinateFromRestrictedTempoDataPoint(float f, const int& tmpMin, const int& tmpMax);
+	
+		float arrayToMsecScaleFactor;// = (tempoMaximum - tempoMinimum)/ ARRAY_SIZE;//turns array into ms
+	
+	
+	
+		int tempoWindowMinimum, tempoWindowMaximum, tempoWindowWidth;
+	
+		ofTrueTypeFont		font;
+		
+		ofxOscReceiver	receiver;
+		string msg_string, debugString, kickString;
+
+		bool	bSmooth;
+	//	float kickError, snareError;
+	//	float testArray[5];
+		
+	//	float prior [ARRAY_SIZE];
+	//	float posterior [ARRAY_SIZE];
+	//	float likelihood [ARRAY_SIZE];
+	//	float likelihoodMean, likelihoodStdDev, likelihoodNoise, stepSize;
+	//	float maximumEstimate;	
+	//	float maximumTest, posteriorDecayRate, maximumIndex;
+	//	float eighthNoteProportion;
+	
+		float stepSize;
+		int screenWidth, screenHeight;
+	
+		bool printInterval, paused;
+		bool drawData, hidePriorMode;
+
+	
+	/*
+		bayesianArray beatDistribution;
+		
+		double tempoMinimum, tempoMaximum;
+				double tempoInterval;
+		beatTempo	beatTimes;
+*/
+	//double tempoInterval;
+		float mouseBPM;
+//		int correctBeatBy;
+//		string tempoUpdateStrings[16];
+//		string tempoDataString;
+
+	private:
+
+	//	ofxOscSender sender;
+		
+		//float noiseFactor, stdDevFactor;
+	//	int minTmpDebug, maxTmpDebug;
+		
+	//	float correctionFactor;
+		
+	
+			
+//			string onsetType;
+//			string timeString;
+//			double cpuBeatTime;
+		
+//			double cpuClockTime;
+			int screenToDraw;
+//	double posteriorMaximum;
+//	bool adaptiveStandardDeviationMode;
+	
+	bool bSnapshot;
+	int snapCounter;
+	ofImage img;
+
+	//	double tempoStdDev;
+//	bool accompanimentStarted;
+//	bool setDistributionOnStartTempo;
+//	int integerMultipleOfTatum;
+	
+	BayesDrumTracker drumTracker;
+	
+};
+
+#endif
+