diff src/BayesDrumTracker.cpp @ 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
line wrap: on
line diff
--- /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;
+}
+