Mercurial > hg > bayesian-drum-tracker
view newOFsrc/testApp.cpp @ 9:0ad78ead0b75
adding output file capability
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Tue, 06 Mar 2012 17:20:18 +0000 |
parents | 525938caf772 |
children | d880f7f29fbe |
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(){ outputFile.open("my_output_test.txt"); // 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. KLdiv = 0; entropy = 0; 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(){ } //-------------------------------------------------------------- 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(); outputFile.close(); } if ( m.getAddress() == "/beatError" ){ double timeNow = ofGetElapsedTimeMillis(); if (timeNow - drumTracker.setBeatToNowTime > 1000) recentError = m.getArgAsFloat(0); int size = drumTracker.beatDistribution.arraySize; int newIndex = round((size/2)+(recentError*size)); priorValue = drumTracker.beatDistribution.posterior[newIndex]; drumTracker.newKickError(m.getArgAsFloat(0), m.getArgAsFloat(2), m.getArgAsString(1)); KLdiv = drumTracker.beatDistribution.getKLdivergence(); entropy = drumTracker.beatDistribution.getEntropyOfPosterior(); drumType = m.getArgAsString(1); beatPosition = m.getArgAsFloat(3); printf("NEW BEAT: time %f error %f, position %f, drum %s, ", m.getArgAsFloat(2), recentError, beatPosition, drumType.c_str()); printf("KL div %f, entropy %f prior value %f, ", KLdiv, entropy, priorValue); printf("tatum is %f\n", drumTracker.beatTimes.tatum ); if (outputFile.is_open()){ outputFile << m.getArgAsFloat(2) << ", " << recentError <<", "<<beatPosition<<", "<< drumType.c_str() << "\n"; }else{ printf("file not open\n"); } }//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; } drawKLdivAndEntropy(); }//end draw void testApp::drawKLdivAndEntropy(){ ofDrawBitmapString("KLdiv :"+ofToString(KLdiv, 3), 20, 40); ofSetColor(200,0,0,160); ofRect(0, ofGetHeight()*(1-KLdiv), 40, ofGetHeight()*KLdiv); ofSetColor(0,0, 200, 160); ofDrawBitmapString("Entropy :"+ofToString(entropy, 3), 20, 60); double entropyDrawFactor = 0.1; ofRect(60, ofGetHeight()*(1-entropy*entropyDrawFactor), 40, ofGetHeight()*entropy*entropyDrawFactor); ofSetColor(100,0,200, 220); ofDrawBitmapString("Error :"+ofToString(recentError, 3), 20, 80); ofRect(120, ofGetHeight()*(1-fabs(recentError)), 40, ofGetHeight()*2*fabs(recentError)); ofDrawBitmapString("prior val :"+ofToString(priorValue, 3), 20, 100); ofSetColor(100,0,100, 220); ofDrawBitmapString(drumType, 20, 0); } 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 } */ /* 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; */ /* 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(); */