Mercurial > hg > bayesian-drum-tracker
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 +} +*/ +