diff src/testApp.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/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
+}
+*/
+