view src/testApp.cpp @ 12:e148d1534733 tip

adding new max player
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Fri, 09 Mar 2012 20:42:34 +0000
parents 0f9165f96bdb
children
line wrap: on
line source
#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
}
*/