comparison 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
comparison
equal deleted inserted replaced
-1:000000000000 0:0f9165f96bdb
1 #include "testApp.h"
2
3
4 //--------------------------------------------------------------
5 //relooking at this problem
6 //bayesianTempo7 - have had working well with Bayesian8NEW maxmsp set
7
8 //updated in bayesian8
9 //integrate so that maxPhase and tempo are the integrated result across the pdf
10 //rather tahn the maximum index - tends to reflect the actuial distribution better
11 //and is the "correct" bayesian method
12
13 //added [ and ] tpo change the alignment when rescue is needed
14
15 //in Bayesian9 (BayesianTest8NEW)
16 //added noise in phase process
17 //started probability distribution for observed beat events
18
19 //in bayesian 11
20 //get s.d. of posterior
21 //this is set to be used as the s.d. of the likelihood
22
23
24 //Initialiser : the algorithm has an initialisation stage with flat prior that detects liekly tempo
25
26
27
28 //BAYESIAN DISTRIBUTION SET by class BayesianArray
29 //SETUP - initialises array
30 //UPDATE - decay the distribution with noise
31 //this should be done using tempo and noise
32 //DRAW - Draw current distributions and also the maximum
33
34 //Runs with bayesian11NEW
35 //and B-KeeperOldBayesianTestNew in Live
36 //Needs - categorisation of beats and tempo
37 //can we use our distribution to filter the input or is that cheating?
38
39 //INtroduce lock scheme for tempo - we know where the beat fell, so can calculate the appropriate tempo interval
40
41 void testApp::setup(){
42 // listen on the given port
43 cout << "listening for osc messages on port " << PORT << "\n";
44 receiver.setup( PORT );
45
46 // sender.setup( HOST, OUTPORT );
47 ofSetCircleResolution(50);
48 ofBackground(255,255,255);
49 bSmooth = false;
50 msg_string = "setup";
51
52 ofSetWindowTitle("Bayesian Test");
53
54 ofSetFrameRate(60); // if vertical sync is off, we can go a bit fast... this caps the framerate at 60fps.
55
56 /*
57 beatDistribution.initialiseArray();
58 tempoDistribution.initialiseArray();
59 beatTimes.lastBeatTime = 0;
60 correctionFactor = 0.5;
61
62
63
64 tempoDistribution.likelihoodStdDev = ARRAY_SIZE / 32;
65 // tempoDistribution.likelihoodNoise = 0.96;
66 tempoDistribution.likelihoodNoise = 0.7;
67 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);//wide
68
69 beatDistribution.likelihoodStdDev = ARRAY_SIZE / 32;
70 beatDistribution.likelihoodNoise = 0.56;
71 beatDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);
72
73
74 tempoMinimum = 180;
75 tempoMaximum = 400;
76 posteriorMaximum = 0.1;
77
78 */
79 hidePriorMode = false;
80
81 printInterval = true;
82 drawData = false;
83
84 screenToDraw = 0;
85
86 ofSetLineWidth(2);
87 ofEnableSmoothing();
88
89
90 bSnapshot = false;
91 snapCounter = 0;
92
93 drumTracker.paused = false;
94
95 // setDistributionOnStartTempo = true;
96
97 resetParameters();
98
99 arrayToMsecScaleFactor = (drumTracker.tempoMaximum - drumTracker.tempoMinimum)/ ARRAY_SIZE;//turns array into ms
100 tempoWindowMinimum = 100;
101 tempoWindowMaximum = 150;
102 tempoWindowWidth = 50;
103 }
104
105
106 void testApp::resetParameters(){
107 /*
108 beatTimes.startIndex = 0;
109 beatTimes.lastBeatTime = 0;
110 maxPhase = 0;
111 posteriorMaximum = 0.1;
112
113 accompanimentStarted = false;
114
115 tempoDistribution.likelihoodNoise = 0.8;
116 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/2);//wide
117
118 beatDistribution.initialiseArray();
119 tempoDistribution.initialiseArray();
120
121 tempoDistribution.calculateStandardDeviation();
122 beatDistribution.calculateStandardDeviation();
123
124 tempoStdDev = tempoDistribution.standardDeviation;
125
126 beatTimes.resetBeatTimeArray();
127 */
128 }
129
130 //--------------------------------------------------------------
131 void testApp::update(){
132
133
134 updateOSCmessages();
135
136 //update tempo window range - this for viewing tempo closeup
137 while (tempoWindowMinimum + tempoWindowWidth/4 > drumTracker.tempoDistribution.integratedEstimate)
138 tempoWindowMinimum -= tempoWindowWidth/4;
139
140 while (tempoWindowMinimum + 3*tempoWindowWidth/4 < drumTracker.tempoDistribution.integratedEstimate)
141 tempoWindowMinimum += tempoWindowWidth/4;
142
143 tempoWindowMaximum = tempoWindowMinimum + tempoWindowWidth;
144
145 drumTracker.decayDistributions();
146
147 }
148
149
150 void testApp::updateOSCmessages(){
151
152
153 // check for waiting messages
154 while( receiver.hasWaitingMessages() )
155 {
156 ofxOscMessage m;
157 receiver.getNextMessage( &m );
158 string newAddress = m.getAddress();
159
160 if ( m.getAddress() == "/Reset" ){
161 printf("baysian reset\n");
162 drumTracker.resetParameters();
163 }
164
165
166 if ( m.getAddress() == "/beatError" ){
167 double timeNow = ofGetElapsedTimeMillis();
168 if (timeNow - drumTracker.setBeatToNowTime > 1000)
169 drumTracker.newKickError(m.getArgAsFloat(0), m.getArgAsFloat(2), m.getArgAsString(1));
170 }//end if new error
171
172
173
174 if ( m.getAddress() == "/tatum" ){
175 drumTracker.beatTimes.tatum = m.getArgAsFloat(0);
176 printf("got tatum as %f\n", m.getArgAsFloat(0));
177 }
178
179 if ( m.getAddress() == "/startTatum" ){
180 drumTracker.startTatum(m.getArgAsFloat(0));
181 printf("START TATUM %f\n", m.getArgAsFloat(0));
182 //then change so tempo distribution is correct....
183 }//end start tatum
184
185
186 if ( m.getAddress() == "/uniformTempo" ){
187 drumTracker.setUniformTempo();
188
189 }
190
191
192 if ( m.getAddress() == "/uniformPhase" ){
193 drumTracker.setUniformPhase();
194
195 }
196
197
198 if ( m.getAddress() == "/setBeatNow" ){
199
200 double beatTime = m.getArgAsFloat(0);
201 drumTracker.setBeatNow(beatTime);
202 //printf("SET BEAT NOW %f\n", beatTime);
203 }
204
205
206 if ( m.getAddress() == "/clickindex" ){
207
208 int clickIndex = m.getArgAsInt32(0);
209 float clickTime = m.getArgAsFloat(1);
210 drumTracker.setNewClickIndex(clickIndex, clickTime);
211 }
212
213
214 if ( m.getAddress() == "/newBeat" ){
215 int beatIndex = m.getArgAsInt32(0);
216 drumTracker.newBeat(beatIndex);
217 }
218
219
220 if ( m.getAddress() == "/beatCorrection" )
221 {
222 float beatCorrValue = m.getArgAsFloat(0);
223 drumTracker.doBeatCorrection(beatCorrValue);
224
225 }//end correction by
226
227
228 if ( m.getAddress() == "/BayesianNoise" ){
229 drumTracker.beatDistribution.likelihoodNoise = m.getArgAsFloat(0);;
230 printf("bayesian noise set to %f\n", drumTracker.beatDistribution.likelihoodNoise);
231 // beatDistribution.setGaussianLikelihood(beatDistribution.likelihoodMean, beatDistribution.likelihoodStdDev);
232 }
233
234 if ( m.getAddress() == "/BayesianStdDev" ){
235 drumTracker.beatDistribution.likelihoodStdDev = ARRAY_SIZE / m.getArgAsFloat(0);
236 // beatDistribution.setGaussianLikelihood(beatDistribution.likelihoodMean, beatDistribution.likelihoodStdDev);
237 }
238
239
240 }//end while there is new message
241
242
243 }
244
245
246 void testApp::takePictureOfScreen(){
247 // grab a rectangle at 200,200, width and height of 300,180
248 img.grabScreen(0,0,screenWidth,screenHeight);
249 char fileName[255];
250 sprintf(fileName, "snapshot_%0.3i.png", snapCounter);
251 img.saveImage(fileName);
252 //printf("saved %s\n", fileName);
253 snapCounter++;
254 bSnapshot = false;
255 }
256
257 /*
258 void testApp::setBeatDistribution(int beatPosition){
259 switch (beatPosition){
260 //early sixteenth is that the beat is a sixteenth earlier
261 case 0:
262 case 1:
263 case 11:
264 //i.e. these zones are interpreted as "on the beat"
265 beatDistribution.eighthNoteProportion = 0;
266 beatDistribution.earlySixteenthNoteProportion = 0;
267 beatDistribution.lateSixteenthNoteProportion = 0;
268 break;
269 //10 and 2 were here
270
271 case 2:
272 beatDistribution.eighthNoteProportion = 0;
273 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
274 //i.e. a 25% chance it is early sixteenth - 75% that the beat actually lies here
275 beatDistribution.lateSixteenthNoteProportion = 0;
276 break;
277
278 case 3:
279 beatDistribution.eighthNoteProportion = 0;
280 beatDistribution.earlySixteenthNoteProportion = 0.3;//was 0.4 in Bayesian8 //half chance it is early
281 beatDistribution.lateSixteenthNoteProportion = 0;
282 break;
283
284 case 5:
285 case 6:
286 case 7:
287 beatDistribution.eighthNoteProportion = 0.3;//i.e. nearly half a chance we are on the 8th note
288 beatDistribution.earlySixteenthNoteProportion = 0;
289 beatDistribution.lateSixteenthNoteProportion = 0;
290 break;
291
292 case 4:
293 beatDistribution.eighthNoteProportion = 0;
294 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
295 beatDistribution.lateSixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
296 //chsanged to 0.2 and 0.1 then back
297 break;
298
299 case 8:
300 beatDistribution.eighthNoteProportion = 0;
301 beatDistribution.earlySixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8
302 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8
303 break;
304
305 case 9:
306 beatDistribution.eighthNoteProportion = 0;
307 beatDistribution.earlySixteenthNoteProportion = 0;
308 beatDistribution.lateSixteenthNoteProportion = 0.35;//was 0.4 in Bayesian8
309 break;
310
311 case 10:
312 beatDistribution.eighthNoteProportion = 0;
313 beatDistribution.earlySixteenthNoteProportion = 0;
314 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.2 in Bayesian8
315 break;
316
317 }
318
319 }
320 */
321 //--------------------------------------------------------------
322 void testApp::draw(){
323 //--------------------------- lines
324 // a bunch of red lines, make them smooth if the flag is set
325
326
327
328 if (bSmooth){
329 ofEnableSmoothing();
330 }
331
332 switch (screenToDraw){
333 case 0:
334 drawBayesianDistribution();
335 break;
336 case 1:
337 drawTempoDistribution();
338 break;
339 case 2:
340 drawBeatMap();
341 break;
342 case 3:
343 // drawNormalisedLikelihood();
344 drawRestrictedTempoDistribution(tempoWindowMinimum, tempoWindowMaximum);
345 break;
346 case 4:
347 drawTempoData();
348 break;
349 case 5:
350 drawBeatProbabilityDistribution();
351 break;
352 case 6:
353 drawPosterior();
354 break;
355 case 7:
356 drawGreyscaleBayesianDistribution();
357 break;
358
359 }
360
361
362
363 if (bSnapshot == true){
364 takePictureOfScreen();
365 bSnapshot = false;
366 }
367
368 }//end draw
369
370
371 void testApp::drawTempoData(){
372
373 ofSetColor(0xFFFF00);
374 //yellow line in centre
375 ofLine( 0, (screenHeight/2), screenWidth, (screenHeight/2));
376
377 ofSetColor(0x0000FF);
378 int tempoIndex = 0;
379 int widthOffset = 20;
380 float stepWidth = screenWidth / 16;
381 ofDrawBitmapString("tatums : ", 600,180);
382 ofDrawBitmapString(ofToString(drumTracker.beatTimes.tatum, 1), 700,180);
383 ofDrawBitmapString("bpm : ", 600,200);
384 ofDrawBitmapString(ofToString((drumTracker.beatTimes.tatum/30000), 1), 700,200);
385 int intervalIndex;
386 int intervalWidth = 2;
387 float magnifyingFactor = 8;
388 for (tempoIndex = 0;tempoIndex < 16; tempoIndex++){
389
390 for (intervalIndex = 0;intervalIndex < 16;intervalIndex++){
391 //new color code
392 if (drumTracker.beatTimes.intervalUsed[tempoIndex][intervalIndex] == true){
393 ofSetColor(0x00FFFF);
394 }
395 else{
396 ofSetColor(0xFF00FF);
397 }
398 //end new code
399
400 ofLine((stepWidth*tempoIndex)+ (intervalWidth*intervalIndex) + widthOffset, screenHeight,
401 (stepWidth*tempoIndex) + (intervalWidth*intervalIndex) + widthOffset, (screenHeight/2) * (1 + (magnifyingFactor * (1-drumTracker.beatTimes.intervalDifferences[tempoIndex][intervalIndex]))));
402
403 if (printInterval == true){
404 ofDrawBitmapString(ofToString(drumTracker.beatTimes.intervalDifferences[tempoIndex][intervalIndex], 3),
405 (stepWidth*tempoIndex) + widthOffset,20+(intervalIndex*20));
406 }
407
408
409 ofDrawBitmapString(ofToString(drumTracker.beatTimes.relativeIntervals[tempoIndex][0], 3), 700,220+(tempoIndex*20));
410 ofDrawBitmapString(ofToString(drumTracker.beatTimes.relativeIntervals[tempoIndex][1], 1), 750,220+(tempoIndex*20));
411 }//end for interval index
412 }//end for tempo index
413
414 ofDrawBitmapString(ofToString(drumTracker.beatTimes.clickIndex), 750,20);
415
416 ofDrawBitmapString(ofToString(mouseBPM), 50,20);
417 ofDrawBitmapString(drumTracker.tempoDataString, 50, 100);
418
419 }//end draw tempo data
420
421
422 void testApp::drawTempoDistribution(){
423 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
424 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
425 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
426
427 maximum *= 1.1;
428
429 float stepHeight = screenHeight/maximum;
430
431
432
433 //draw prior in green
434 ofSetColor(0x888888);
435 for (int i = 1; i < ARRAY_SIZE; i+=2){
436 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i]*stepHeight));
437 }
438
439
440 //draw posterior in dark
441 ofSetColor(0x000000);
442 for (int i = 1; i < ARRAY_SIZE; i++){
443 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i]*stepHeight));
444 }
445
446
447 //black line is the max probability
448 ofSetColor(0x000000);
449 ofLine(drumTracker.tempoDistribution.integratedEstimate *stepSize, screenHeight, drumTracker.tempoDistribution.integratedEstimate *stepSize, 0);
450
451 //blue is the current kick received
452 ofSetColor(0xAAAAAA);
453
454 int altIndex = 0;
455 for (altIndex = 0;altIndex< 16;altIndex++){
456
457 double tempoInterval = drumTracker.beatTimes.intervalDifferences[drumTracker.beatTimes.index][altIndex];
458
459 if (altIndex != drumTracker.beatTimes.index && tempoInterval > drumTracker.tempoMinimum && tempoInterval < drumTracker.tempoMaximum){
460
461
462
463 //draw likelihood
464 //draw likelhood in blue
465 // //need to reset likelihood for this!
466 //XXX remove
467 double timeInterval = drumTracker.beatTimes.beatTimes[drumTracker.beatTimes.index] - drumTracker.beatTimes.beatTimes[altIndex];
468 if (timeInterval > 2*drumTracker.tempoMinimum && timeInterval < 2*drumTracker.tempoMaximum)
469 {
470
471 ofLine(stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)), screenHeight,
472 stepSize*(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)) , 0);
473
474 drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
475 for (int i = 1; i < ARRAY_SIZE; i++){
476 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i]*stepHeight));
477 }
478 }
479
480 }
481
482 }//end for
483
484 if (bSmooth){
485 ofDisableSmoothing();
486 }
487
488 drawTempoInfo();
489
490 }
491
492
493 int testApp::xcoordinateFromTempoDataPoint(float f){
494 //f is the time
495
496 int xcoordinateForInterval = 0;
497 if (f >= drumTracker.tempoMinimum && f <= drumTracker.tempoMaximum)
498 xcoordinateForInterval = ((float)(f - drumTracker.tempoMinimum)*screenWidth/(float)(drumTracker.tempoMaximum - drumTracker.tempoMinimum));
499 return xcoordinateForInterval;
500
501 }
502
503
504 int testApp::xcoordinateFromRestrictedTempoDataPoint(float f, const int& tmpMin, const int& tmpMax){
505
506
507 int xcoordinateForInterval = -1;
508 if (f >= drumTracker.tempoMinimum+tmpMin && f <= min(drumTracker.tempoMinimum+tmpMax,drumTracker.tempoMaximum))
509 xcoordinateForInterval = ((float)(f - drumTracker.tempoMinimum - tmpMin*arrayToMsecScaleFactor)*screenWidth/(float)((tmpMax - tmpMin)*arrayToMsecScaleFactor));
510 return xcoordinateForInterval;
511
512 }
513
514
515 void testApp::drawTempoInfo(){
516 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
517 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
518 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
519
520
521 ofSetColor(0x000000);
522 string testString;
523 testString = "max is ";
524 testString += ofToString(maximum);
525 ofDrawBitmapString(testString, 700,620);
526
527 ofDrawBitmapString(msg_string, 700,650);
528
529 ofDrawBitmapString(kickString, 700,670);
530
531 testString = "std dev : ";
532 testString += ofToString(drumTracker.tempoStdDev, 6);
533
534 testString += ", ";
535 testString += ofToString(drumTracker.accompanimentStarted);
536 ofDrawBitmapString(testString, 20, 120);
537
538 int tempoUpdateIndex;
539 for (tempoUpdateIndex = 0;tempoUpdateIndex<16;tempoUpdateIndex++){
540 // ofDrawBitmapString(tempoUpdateStrings[tempoUpdateIndex], 700, 200 + (20 * tempoUpdateIndex));
541 }
542
543 ofDrawBitmapString("Mouse located at tempo: ", 50,10);
544 ofDrawBitmapString(ofToString(mouseBPM, 1), 50,20);
545
546 ofDrawBitmapString("Current tempo: ", 50,40);
547 ofDrawBitmapString(ofToString(30000/drumTracker.beatTimes.tatum, 1), 50,50);
548
549 ofDrawBitmapString(drumTracker.tempoDataString, 50, 100);
550
551
552 for (int i = 1;i < 16; i++){
553 for (int altIndex = 0; altIndex < 16;altIndex++){
554 string newString;
555 newString = " :";
556 int recentIndex = (altIndex-i+16)%16;
557 if (drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex] > 0 && drumTracker.beatTimes.intervalUsed[altIndex][recentIndex]){
558
559
560 int xcoordinateForInterval = xcoordinateFromTempoDataPoint(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex]);
561 float beatInterval = (float) drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2;
562
563 if (drumTracker.beatTimes.OnsetIsKick[altIndex])
564 ofSetColor(255*(8-beatInterval)/(float)8, 0, 255*beatInterval/(float)8);
565 else
566 ofSetColor(0, 255*(8-beatInterval)/(float)8, 255*beatInterval/(float)8);
567 //red kick, green snare
568
569 ofCircle(xcoordinateForInterval, 200 + (altIndex * 20), 3);
570
571 newString += ofToString(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex],0);
572 newString += " (";
573 newString += ofToString(drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2, 0);
574 newString += ")";
575
576 }
577 ofSetColor(0,0,0);
578 //ofDrawBitmapString(newString, 200 + i*80, 200 + (altIndex * 20));
579
580
581 }
582 }
583
584 }
585
586
587
588
589 void testApp::drawTempoDataPoints(const int& tmpMin, const int& tmpMax, const float& tmpStepSize){
590
591 for (int i = 1;i < 16; i++){
592 for (int altIndex = 0; altIndex < 16;altIndex++){
593 // string newString;
594 // newString = " :";
595
596 int recentIndex = (altIndex-i+16)%16;
597 if (drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex] > 0 && drumTracker.beatTimes.intervalUsed[altIndex][recentIndex]){
598
599 int xcoordinateForInterval = xcoordinateFromRestrictedTempoDataPoint(drumTracker.beatTimes.intervalDifferences[altIndex][recentIndex], tmpMin, tmpMax);
600 float beatInterval = (float) drumTracker.beatTimes.tatumMultiples[altIndex][recentIndex]/2;
601
602 if (drumTracker.beatTimes.OnsetIsKick[altIndex])
603 ofSetColor(255*(7-beatInterval+1)/(float)7, 255*(beatInterval-1)/(float)7, 0);//100+155*(8-beatInterval)/(float)8
604 else
605 ofSetColor(0, 255*(7-beatInterval+1)/(float)7, 255*(beatInterval-1)/(float)7);//, 155*beatInterval/(float)8);
606 //red kick, green snare
607
608 ofCircle(xcoordinateForInterval, 200 + (altIndex * 20), 3);
609 ofDrawBitmapString(ofToString(beatInterval, 0), xcoordinateForInterval-2, 200 + (altIndex * 20) - 3);
610 /* newString += ofToString(beatTimes.intervalDifferences[altIndex][recentIndex],0);
611 newString += " (";
612 newString += ofToString(beatTimes.tatumMultiples[altIndex][recentIndex]/2, 0);
613 newString += ")";
614 */
615 }
616 ofSetColor(0,0,0);
617 //ofDrawBitmapString(newString, 200 + i*80, 200 + (altIndex * 20));
618
619
620 }
621 }
622
623 }
624
625
626 void testApp::drawRestrictedTempoDistribution(int tmpMin, int tmpMax){
627 //min and max are in the tempo array coordinates
628
629 tmpMin = max(tmpMin, 0);
630 tmpMax = min(tmpMax, ARRAY_SIZE-1);
631
632 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
633 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
634 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
635
636 maximum *= 1.1;
637
638 float stepHeight = screenHeight/maximum;
639 int tmpWidth = tmpMax - 1 - tmpMin;
640 float tmpStepSize = screenWidth / (float) tmpWidth;
641
642
643 //draw prior in green
644 ofSetColor(0x888888);
645 for (int i = 1; i < tmpWidth; i+=2){
646 ofLine((i-1)*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.prior[tmpMin+i-1]*stepHeight), i * tmpStepSize, screenHeight - (drumTracker.tempoDistribution.prior[tmpMin+i]*stepHeight));
647 }
648
649
650 //draw posterior in dark
651 ofSetColor(0x000000);
652 for (int i = 1; i < tmpWidth; i++){
653 ofLine((i-1) * tmpStepSize, screenHeight - (drumTracker.tempoDistribution.posterior[tmpMin+i-1]*stepHeight), i*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.posterior[tmpMin+i]*stepHeight));
654 }
655
656
657 //black line is the max probability
658 ofSetColor(0x000000);
659 ofLine((drumTracker.tempoDistribution.integratedEstimate - tmpMin)* tmpStepSize, screenHeight, (drumTracker.tempoDistribution.integratedEstimate-tmpMin) *tmpStepSize, 0);
660
661 //blue is the current kick received
662 ofSetColor(0xAAAAAA);
663
664 int altIndex = 0;
665 for (altIndex = 0;altIndex< 16;altIndex++){
666 //iterate through all recent beat intervals
667
668 double tempoInterval = drumTracker.beatTimes.intervalDifferences[drumTracker.beatTimes.index][altIndex];
669
670 if (altIndex != drumTracker.beatTimes.index && tempoInterval > drumTracker.tempoMinimum && tempoInterval < drumTracker.tempoMaximum){
671
672 double timeInterval = drumTracker.beatTimes.beatTimes[drumTracker.beatTimes.index] - drumTracker.beatTimes.beatTimes[altIndex];
673
674 if (timeInterval > 2*drumTracker.tempoMinimum && timeInterval < 2*drumTracker.tempoMaximum){
675 //i.e. within the beat range only
676 //so we only draw the likelihood realtime for happening beat intervals
677 //in fact much more is going on than this but harder to visualise
678
679 float indexOfNewLocation = ARRAY_SIZE*(tempoInterval-drumTracker.tempoMinimum)/(float)(drumTracker.tempoMaximum - drumTracker.tempoMinimum);
680
681
682 if (indexOfNewLocation >= tmpMin){
683 ofLine(tmpStepSize * (indexOfNewLocation-tmpMin), screenHeight, tmpStepSize * (indexOfNewLocation-tmpMin) , 0);
684 }
685
686
687 drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
688 //setting the tempo distribution likeihood just for visualisation purposes
689 for (int i = 1; i < tmpWidth; i++){
690 ofLine((i-1)*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i+tmpMin-1]*stepHeight), i*tmpStepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i+tmpMin]*stepHeight));
691
692 }
693 }
694
695 }
696
697 }//end for
698
699 if (bSmooth){
700 ofDisableSmoothing();
701 }
702
703
704 drawTempoDataPoints(tmpMin, tmpMax, tmpStepSize);
705
706 // lines for background
707 for (int i = tmpMin-(tmpMin%20);i < tmpMax; i+=20){
708 ofSetColor(0,0,200,100);
709 ofLine(tmpStepSize * (i-tmpMin), screenHeight, tmpStepSize * (i-tmpMin) , 0);
710 string tmpTempoString = ofToString(drumTracker.tempoMinimum + i*arrayToMsecScaleFactor, 0);
711 ofDrawBitmapString(tmpTempoString, tmpStepSize * (i-tmpMin) , 20);
712 }
713
714 string currentTatumString = "Beat Period : ";
715 currentTatumString += ofToString(drumTracker.beatTimes.tatum, 1);
716 currentTatumString += " MaxIndex : ";
717 currentTatumString += ofToString(drumTracker.tempoDistribution.integratedEstimate, 1);
718
719 ofDrawBitmapString(currentTatumString, 20, 40);
720 //drawTempoInfo();
721
722 }
723
724
725
726
727
728
729
730
731
732
733
734 void testApp::drawBeatMap(){
735 int x,y;
736
737 for (x=0;x < 6;x++){
738 for (y=0;y<8;y++){
739 int cell = x+(y*6);
740 if (cell == drumTracker.beatTimes.beatSegment){
741 if (drumTracker.beatTimes.beatMap[cell] == 1)//for kick
742 ofSetColor(drumTracker.beatTimes.beatMap[cell]*255, 0, 0);
743
744 if (drumTracker.beatTimes.beatMap[cell] == 2)//for kick
745 ofSetColor(0, drumTracker.beatTimes.beatMap[cell]*255, 100);
746
747 }
748 else{
749 if (drumTracker.beatTimes.beatMap[cell] == 1)//for kick
750 ofSetColor(drumTracker.beatTimes.beatMap[cell]*155, 0, 0);
751 else //for snare
752 ofSetColor(0,drumTracker.beatTimes.beatMap[cell]*155, 0);//beatTimes.beatMap[cell]*155);
753
754 }
755 ofRect(screenWidth*x/6, screenHeight*y/8, screenWidth/6, screenHeight/8);
756
757 ofSetColor(255,0,0);
758 ofDrawBitmapString(ofToString(x+(y*6)), screenWidth*x/6, screenHeight*y/8);
759
760 if (drumTracker.beatTimes.beatMap[cell] == 1){
761 ofSetColor(0,255,255);//
762 ofDrawBitmapString(ofToString(drumTracker.beatTimes.beatMapTimeDifferences[cell], 2), (screenWidth*(x+0.5)/6) , (screenHeight*(y+0.5)/8) );
763 }
764 if (drumTracker.beatTimes.beatMap[cell] == 2){
765 ofSetColor(0,0,100);//
766 ofDrawBitmapString(ofToString(drumTracker.beatTimes.beatMapTimeDifferences[cell], 2), (screenWidth*(x+0.5)/6) , (screenHeight*(y+0.5)/8) );
767 }
768
769
770 }
771 }
772
773 }
774
775
776
777
778 void testApp::drawBeatProbabilityDistribution(){
779 int x,y;
780
781 for (x=0;x < 6;x++){
782 for (y=0;y<4;y++){
783 int cell = x+(y*6);
784 ofSetColor(drumTracker.beatTimes.beatProbabilityDistribution[y][x][0]*255, 0, 0);
785 ofRect(screenWidth*x/6, screenHeight*y/8, screenWidth/6, screenHeight/8);
786 }
787 }
788 for (x=0;x < 6;x++){
789 for (y=0;y<4;y++){
790 int cell = x+(y*6);
791 ofSetColor(0, drumTracker.beatTimes.beatProbabilityDistribution[y][x][1]*255, 0);
792 ofRect(screenWidth*x/6, screenHeight*(y+4)/8, screenWidth/6, screenHeight/8);
793 }
794 }
795
796 }
797
798
799 void testApp::drawNormalisedLikelihood(){
800 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
801 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
802 //maximum = max(maximum, beatDistribution.getMaximum(&beatDistribution.posterior[0], ARRAY_SIZE));
803 float stepHeight = screenHeight/maximum;
804
805 if (!hidePriorMode){
806 //draw likelhood in blue
807
808 ofSetColor(0x0000FF);
809 for (int i = 1; i < ARRAY_SIZE; i++){
810 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
811 }
812
813 //draw prior in green
814 ofSetColor(0x00AA00);
815 for (int i = 1; i < ARRAY_SIZE; i++){
816 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
817 }
818 }//end hide prior mode
819
820
821
822 }
823
824
825
826 void testApp::drawPosterior(){
827 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE);
828
829 if (drumTracker.posteriorMaximum < maximum){
830 drumTracker.posteriorMaximum = 1.2*maximum;
831 }
832
833 float stepHeight = screenHeight/drumTracker.posteriorMaximum;
834 ofSetColor(0xFF00FF);
835 for (int i = 1; i < ARRAY_SIZE; i++){
836 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
837 }
838
839
840 //yellow is the middle
841 ofSetColor(0xFFFF00);
842 ofLine(ARRAY_SIZE*stepSize/2, screenHeight, ARRAY_SIZE*stepSize/2, 0);
843
844
845
846 //blue is the current kick received
847 ofSetColor(0x0000FF);
848 ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), screenHeight,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), 0);
849
850 //purple line is the integrated max probability
851 int integratedBeatEstimateDrawPoint = round(drumTracker.beatDistribution.integratedEstimate*stepSize) ;
852 ofSetColor(0xFF22FF);
853 ofLine(integratedBeatEstimateDrawPoint, screenHeight, integratedBeatEstimateDrawPoint, 0);
854
855 string testString = "maximum: ";
856 testString += ofToString(drumTracker.posteriorMaximum, 2);
857 ofDrawBitmapString(testString, 100,120);
858
859
860 }
861
862
863
864
865
866 void testApp::drawBayesianDistribution(){
867 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
868 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
869 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
870 float stepHeight = screenHeight/maximum;
871
872 if (!hidePriorMode){
873 //draw likelhood in blue
874 if (drumTracker.onsetType == "kick")
875 ofSetColor(0xff0000);//red : kick
876 else
877 ofSetColor(0x00FF00);//green : snare
878
879 for (int i = 1; i < ARRAY_SIZE; i++){
880 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
881 }
882
883 //;line where the current kick is received
884 ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), screenHeight,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), 0);
885
886
887 //draw prior in aqua blue
888 ofSetColor(0x00AAAA);
889 for (int i = 1; i < ARRAY_SIZE; i++){
890 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
891 }
892 }//end hide prior mode
893
894 //draw posterior in red
895 ofSetColor(0x0000FF);
896 for (int i = 1; i < ARRAY_SIZE; i++){
897 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
898 }
899
900 //draw the previous updated posteriror in purple
901 /* ofSetColor(0xFF22FF);
902 for (int i = 1; i < ARRAY_SIZE; i++){
903 ofLine((i-1)*stepSize, screenHeight - (tmpArray[i-1]*stepHeight), i*stepSize, screenHeight - (tmpArray[i]*stepHeight));
904 }
905 */
906
907 //yellow is the middle
908 ofSetColor(0xFFFF00);
909 ofLine(ARRAY_SIZE*stepSize/2, screenHeight, ARRAY_SIZE*stepSize/2, 0);
910
911 //black line is the max probability
912 ofSetColor(0x000000);
913 ofLine(drumTracker.beatDistribution.maximumIndex*stepSize, screenHeight, drumTracker.beatDistribution.maximumIndex*stepSize, 0);
914
915
916 //purple line is the integrated max probability
917 int integratedBeatEstimate = drumTracker.beatDistribution.integratedEstimate ;
918 ofSetColor(0x2222FF);
919 ofLine(integratedBeatEstimate *stepSize, screenHeight, integratedBeatEstimate *stepSize, 0);
920
921
922 if (bSmooth){
923 ofDisableSmoothing();
924 }
925
926 printBayesianData();
927 }
928
929 void testApp::printBayesianData(){
930 //not optimised!!! XXX
931 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
932 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
933 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
934
935 ofSetColor(0x000000);
936 string testString;
937 testString = "max2 is ";
938 testString += ofToString(maximum, 3);
939 testString += " :: ";
940
941 testString = "correction of ";
942 testString += ofToString(drumTracker.beatCorrection);
943 testString += " corr by :";
944 testString += ofToString(drumTracker.correctBeatBy);
945
946 //ofDrawBitmapString(testString, 100,120);
947
948 testString = "MaxPhase ";
949 testString += ofToString(drumTracker.maxPhase);
950 // ofDrawBitmapString(testString, 100,140);
951
952
953 testString = "Likelihood noise ";
954 testString += ofToString(drumTracker.beatDistribution.likelihoodNoise, 2);
955 //ofDrawBitmapString(testString, 100,160);
956
957 // ofDrawBitmapString(msg_string, 100,140);
958
959 // ofDrawBitmapString(kickString, 100,180);
960
961 /* debugString = "Min Debug = ";
962 debugString += ofToString(drumTracker.tempoDistribution.maximumIndex + drumTracker.minTempoIndex);
963 debugString += " Max Debug = ";
964 debugString += ofToString(drumTracker.tempoDistribution.maximumIndex + drumTracker.maxTempoIndex);
965 */
966 //ofDrawBitmapString(debugString, 300,370);
967
968 debugString = "CLICK INDEX = ";
969 debugString += ofToString(drumTracker.beatTimes.clickIndex);
970 //ofDrawBitmapString(debugString, 100, 20);
971
972 debugString = "STD DEV = ";
973 debugString += ofToString(drumTracker.beatDistribution.standardDeviation, 2);
974 // ofDrawBitmapString(debugString, 100, 40);
975
976
977
978 debugString = "interval ";
979 debugString += ofToString(drumTracker.debugArray[2], 2);
980 debugString += " time int = ";
981 debugString += ofToString(drumTracker.debugArray[1], 2);
982 debugString += " Beat max = ";
983 debugString += ofToString(drumTracker.debugArray[0 ], 2);
984 debugString += " Tempo max = ";
985 debugString += ofToString(drumTracker.debugArray[3 ], 2);
986 // ofDrawBitmapString(debugString, 300,570);
987
988 debugString = " last = ";
989 debugString += ofToString(drumTracker.beatTimes.lastBeatTime, 2);
990 // ofDrawBitmapString(debugString, 300,470);
991
992
993 string closestClickString = "Closest Click ";
994 closestClickString += ofToString(drumTracker.beatTimes.closestClickIndexToBeat[drumTracker.beatTimes.index]);
995 closestClickString += " beat seg ";
996 closestClickString += ofToString(drumTracker.beatTimes.beatSegment%12);
997 closestClickString += " lastCindex";
998 closestClickString += ofToString(drumTracker.beatTimes.lastClickIndex);
999 closestClickString += " TD ";
1000 closestClickString += ofToString(drumTracker.beatTimes.timeDifference);
1001
1002 // ofDrawBitmapString(closestClickString, 100,100);
1003
1004 // ofDrawBitmapString(timeString, 100,60);
1005 }
1006
1007
1008
1009 void testApp::drawGreyscaleBayesianDistribution(){
1010 ofSetColor(255,255,255);
1011 ofRect(0,0,screenWidth, screenHeight);
1012
1013 float maximum = drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.likelihood[0], ARRAY_SIZE);
1014 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.prior[0], ARRAY_SIZE));
1015 maximum = max(maximum, drumTracker.beatDistribution.getMaximum(&drumTracker.beatDistribution.posterior[0], ARRAY_SIZE));
1016 maximum *= 1.1;
1017 float stepHeight = screenHeight/maximum;
1018
1019 if (!hidePriorMode){
1020 //draw likelhood in blue
1021 ofSetColor(0x555555);
1022 for (int i = 1; i < ARRAY_SIZE; i+=2){
1023 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.likelihood[i]*stepHeight));
1024 }
1025
1026 //draw prior in green
1027 ofSetColor(0xAAAAAA);
1028 for (int i = 1; i < ARRAY_SIZE; i++){
1029 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.prior[i]*stepHeight));
1030 }
1031 }//end hide prior mode
1032
1033 //draw posterior in dark grey
1034 ofSetColor(0x222222);
1035 for (int i = 1; i < ARRAY_SIZE; i++){
1036 ofLine((i-1)*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.beatDistribution.posterior[i]*stepHeight));
1037 }
1038
1039 /*
1040 //dotted the middle
1041 ofSetColor(0x555555);
1042 for (int i = 1; i < screenHeight; i+=4){
1043 ofLine(ARRAY_SIZE*stepSize/2, i, ARRAY_SIZE*stepSize/2, i-2);
1044 }
1045 */
1046
1047 //purple line is the integrated max probability
1048 // int integratedBeatEstimate = beatDistribution.integratedEstimate ;
1049 // ofSetColor(0x000000);
1050 // ofLine(integratedBeatEstimate *stepSize, screenHeight, integratedBeatEstimate *stepSize, 0);
1051
1052 //purple line is the integrated max probability
1053 float tmpIntegratedBeatEstimate = drumTracker.beatDistribution.getIntegratedEstimateIndex();
1054 ofSetColor(0x000000);
1055 int drawLinePoint = round(tmpIntegratedBeatEstimate *stepSize);
1056 ofLine(drawLinePoint, screenHeight, drawLinePoint, 0);
1057
1058 //blue is the current kick received
1059 ofSetColor(0x555555);
1060 for (int i = 1; i < screenHeight; i+=40){
1061 ofLine(stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), i,stepSize*((ARRAY_SIZE/2) + (ARRAY_SIZE*drumTracker.kickError)), i-20);
1062 }
1063
1064
1065 }
1066
1067
1068
1069
1070 void testApp::drawGreyscaleTempoDistribution(double tempoInterval){
1071 ofSetColor(255,255,255);
1072 ofRect(0,0,screenWidth, screenHeight);
1073
1074 float maximum = drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.likelihood[0], ARRAY_SIZE);
1075 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.prior[0], ARRAY_SIZE));
1076 maximum = max(maximum, drumTracker.tempoDistribution.getMaximum(&drumTracker.tempoDistribution.posterior[0], ARRAY_SIZE));
1077
1078 maximum *= 1.1;
1079
1080 float stepHeight = screenHeight/maximum;
1081
1082 //draw prior in green
1083 ofSetColor(0x777777);
1084 for (int i = 1; i < ARRAY_SIZE; i++){
1085 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.prior[i]*stepHeight));
1086 }
1087
1088
1089 //draw posterior in dark
1090 ofSetColor(0x000000);
1091 for (int i = 1; i < ARRAY_SIZE; i++){
1092 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.posterior[i]*stepHeight));
1093 }
1094
1095
1096 //black line is the max probability
1097 ofSetColor(0xFF0000);
1098 ofLine(drumTracker.tempoDistribution.integratedEstimate *stepSize, screenHeight, drumTracker.tempoDistribution.integratedEstimate *stepSize, 0);
1099
1100 //blue is the current kick received
1101 ofSetColor(0xAAAAAA);
1102
1103
1104
1105
1106 for (int k =1;k < screenHeight/12;k+=2){
1107 ofLine(stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)), 12*k,
1108 stepSize*(ARRAY_SIZE * (tempoInterval-drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum)) , 12*(k-1));
1109 }
1110
1111 drumTracker.tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval - drumTracker.tempoMinimum)/(drumTracker.tempoMaximum - drumTracker.tempoMinimum), drumTracker.tempoDistribution.likelihoodStdDev);
1112 for (int i = 1; i < ARRAY_SIZE; i+=2){
1113 //dotted line likelihood fn
1114 ofLine((i-1)*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i-1]*stepHeight), i*stepSize, screenHeight - (drumTracker.tempoDistribution.likelihood[i]*stepHeight));
1115 }
1116
1117
1118
1119
1120 if (bSmooth){
1121 ofDisableSmoothing();
1122 }
1123
1124 }
1125
1126
1127
1128
1129 //--------------------------------------------------------------
1130 void testApp::keyPressed (int key){
1131 if (key == 's'){
1132 bSmooth = !bSmooth;
1133 }
1134
1135 if (key == 'x'){
1136 printInterval = !printInterval;
1137 }
1138
1139
1140 if (key == 'y'){
1141 drawData = !drawData;
1142 }
1143
1144 if (key == 'f'){
1145 ofToggleFullscreen();
1146 }
1147
1148 if (key == 'h' || key == 'H'){
1149 hidePriorMode = !hidePriorMode;//drawData;
1150 }
1151
1152
1153
1154 if ( key =='a' || key == 'A' )
1155 {
1156
1157 }
1158
1159 if (key == ' '){
1160 drumTracker.paused = !drumTracker.paused;
1161 }
1162
1163 if (key == OF_KEY_RIGHT){
1164 screenToDraw++;
1165 screenToDraw = screenToDraw % NUMBER_OF_SCREENS;
1166 }
1167 if (key == OF_KEY_LEFT){
1168 screenToDraw += NUMBER_OF_SCREENS - 1;
1169 screenToDraw = screenToDraw % NUMBER_OF_SCREENS;
1170 }
1171
1172 if (key == ']')
1173 drumTracker.beatDistribution.translateDistribution(ARRAY_SIZE / 4);
1174
1175 if (key == '[')
1176 drumTracker.beatDistribution.translateDistribution(-1*ARRAY_SIZE / 4);
1177
1178 if (key == 'x'){
1179 bSnapshot = true;
1180 }
1181
1182 if (key == 'q')
1183 drumTracker.adaptiveStandardDeviationMode = !drumTracker.adaptiveStandardDeviationMode;
1184
1185 }
1186
1187 /*
1188 void testApp::sendMaxTempo(){
1189 ofxOscMessage m;
1190 m.setAddress( "/tempo" );
1191
1192 //maxTempo = tempoDistribution.maximumIndex * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
1193 //would be introduced new in bayesian8
1194 maxTempo = drumTracker.tempoDistribution.getIntegratedEstimateIndex() * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
1195 maxTempo += tempoMinimum;
1196
1197
1198 m.addFloatArg( maxTempo );
1199 sender.sendMessage( m );
1200
1201 printf("max tempo %f\n", maxTempo);
1202
1203 }
1204
1205 void testApp::sendMaxPhase(){
1206
1207
1208 // maxPhase = (beatDistribution.maximumIndex - (ARRAY_SIZE/2)) / ARRAY_SIZE;
1209 maxPhase = (drumTracker.beatDistribution.getIntegratedEstimateIndex() - (ARRAY_SIZE/2)) / ARRAY_SIZE;
1210 printf("\nphase index %f :: %i\n", drumTracker.beatDistribution.integratedEstimate , maxPhase);
1211 ofxOscMessage m;
1212 m.setAddress( "/phase" );
1213 m.addFloatArg( maxPhase );
1214 sender.sendMessage( m );
1215
1216 //beatCorrection = maxPhase * beatTimes.tatum / 4;
1217 }
1218 */
1219 //--------------------------------------------------------------
1220 void testApp::keyReleased (int key){
1221
1222 }
1223
1224 //--------------------------------------------------------------
1225 void testApp::mouseMoved(int x, int y ){
1226
1227 mouseBPM = convertToBPM(drumTracker.tempoMinimum+ ((x * (drumTracker.tempoMaximum - drumTracker.tempoMinimum) ) / ofGetWidth() )) ;
1228 }
1229
1230 //--------------------------------------------------------------
1231 void testApp::mouseDragged(int x, int y, int button){
1232 }
1233
1234 //--------------------------------------------------------------
1235 void testApp::mousePressed(int x, int y, int button){
1236 }
1237
1238
1239 //--------------------------------------------------------------
1240 void testApp::mouseReleased(int x, int y, int button){
1241
1242 }
1243
1244 //--------------------------------------------------------------
1245 void testApp::windowResized(int w, int h){
1246 screenWidth = ofGetWidth();
1247 screenHeight = ofGetHeight();
1248 stepSize = screenWidth / (float)(ARRAY_SIZE);
1249 }
1250
1251 double testApp::convertToBPM(double interval){
1252 //interval is in ms and is the tatum interval - eighth nbote - so 250ms for 120bpm
1253 return (30000/interval);
1254
1255 }
1256 /*
1257 noyt needed?
1258 float testApp::tempoIndexToMsec(int index){
1259 float msec;
1260 msec = index * (tempoMaximum - tempoMinimum) / ARRAY_SIZE;
1261 msec += tempoMinimum;
1262 return msec;
1263 }
1264
1265 float testApp::beatIndexToMsec(int index){
1266 float msec;
1267 msec = index * maxTempo / ARRAY_SIZE;
1268 msec += tempoMinimum;
1269 return msec;
1270 }
1271 */
1272 /*
1273
1274 bool testApp::filterBeatTime(double newBeatTime){
1275 bool newBeatFound = false;
1276 if ((newBeatTime - beatTimes.lastBeatTime) > 20 || beatTimes.lastBeatTime == 0){
1277
1278 crossUpdateArrays((float)(newBeatTime - beatTimes.lastBeatTime));
1279 beatTimes.lastBeatTime = newBeatTime;
1280 newBeatFound = true;
1281 }
1282 return newBeatFound;
1283 }
1284
1285 void testApp::crossUpdateArrays(float timeInterval){
1286
1287 int finalBeatIndex, tmpTempoIndex, startBeatIndex;
1288 //finalBeat has contribution from BEAT[finalBeat + INT.k] * TEMPO[Max_tempo + k] where INT = INTERVAL
1289 float interval;
1290 interval = timeInterval / maxTempo;//beatTimes.tatum;
1291 tempoDistribution.resetMaximumPosterior();
1292 beatDistribution.resetMaximumPosterior();
1293
1294
1295 int tmpBeatIndex;
1296 //&& interval > 0.8 idea?
1297 if (timeInterval > 0 && timeInterval < 12000 ){//need between 0 and 12 seconds only to update
1298
1299 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
1300
1301 tmpArray[tmpBeatIndex] = 0;
1302 float minusMsecToMakeUp = beatIndexToMsec(tmpBeatIndex) / interval;
1303 float plusMsecToMakeUp = beatIndexToMsec(ARRAY_SIZE - tmpBeatIndex) / interval;
1304 float convertMsecToTempoIndex = ARRAY_SIZE / (tempoMaximum - tempoMinimum) ;
1305
1306
1307 int minTempoIndex = -1 * (int)(minusMsecToMakeUp * convertMsecToTempoIndex);
1308 int maxTempoIndex = (int)(plusMsecToMakeUp * convertMsecToTempoIndex);
1309
1310
1311 if (tmpBeatIndex == beatDistribution.maximumIndex){
1312 minTmpDebug = tempoDistribution.maximumIndex + minTempoIndex;
1313 maxTmpDebug = tempoDistribution.maximumIndex + maxTempoIndex;
1314 debugArray[0] = beatDistribution.maximumIndex;//
1315 debugArray[1] = timeInterval;
1316 debugArray[2] = interval;//beatDistribution.maximumIndex;
1317 debugArray[3] = tempoDistribution.maximumIndex;
1318 }
1319
1320 for (tmpTempoIndex = minTempoIndex;tmpTempoIndex <= maxTempoIndex;tmpTempoIndex++){
1321
1322 if ((tempoDistribution.maximumIndex + tmpTempoIndex) >= 0
1323 && (tempoDistribution.maximumIndex + tmpTempoIndex) < ARRAY_SIZE
1324 && (tmpBeatIndex - (int)(interval*tmpTempoIndex)) >= 0
1325 && (tmpBeatIndex - (int)(interval*tmpTempoIndex))< ARRAY_SIZE){
1326 tmpArray[tmpBeatIndex] += beatDistribution.posterior[tmpBeatIndex - (int)(interval*tmpTempoIndex)] * tempoDistribution.posterior[(int)tempoDistribution.maximumIndex + tmpTempoIndex];
1327 }
1328 }//end for tmpTmepo
1329
1330
1331
1332 }
1333
1334 float tmpFloat;
1335 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){
1336 //debug - dont actually update::
1337
1338 tmpFloat = beatDistribution.posterior[tmpBeatIndex];
1339 beatDistribution.posterior[tmpBeatIndex] = tmpArray[tmpBeatIndex];
1340 tmpArray[tmpBeatIndex] = tmpFloat;
1341 }
1342 beatDistribution.renormaliseArray(&beatDistribution.posterior[0], ARRAY_SIZE);
1343
1344 } //end if
1345
1346
1347 }
1348
1349
1350 void testApp::updateTempoProcess(double cpuTime, string onsetDescription){
1351
1352 if (filterBeatTime(cpuTime) == true){
1353 //checks for no repeat
1354
1355 if (onsetDescription == "kick")
1356 beatTimes.addBeatTime(cpuTime, 1);
1357 else
1358 beatTimes.addBeatTime(cpuTime, 2);
1359
1360
1361 //recalculate the distribution
1362 int altIndex = 0;
1363
1364 tempoDataString = "Tatum :";
1365 tempoDataString += ofToString(beatTimes.tatum, 2);
1366 tempoDataString += " BPM ";
1367 tempoDataString += ofToString((double)30000/beatTimes.tatum, 2);
1368
1369 timeString = "Last BEAT ";
1370 timeString += ofToString(beatTimes.lastBeatTime);
1371 timeString += " CLICK ";
1372 timeString += ofToString(beatTimes.lastClickTime);
1373 timeString += " DIFDF ";
1374 timeString += ofToString(beatTimes.timeDifference);
1375 timeString += " segment ";
1376 timeString += ofToString(beatTimes.beatSegment);
1377
1378
1379 for (altIndex = 0;altIndex< 16;altIndex++){
1380 tempoInterval = beatTimes.intervalDifferences[beatTimes.index][altIndex];
1381 integerMultipleOfTatum = beatTimes.relativeIntervals[altIndex][1];
1382
1383
1384 ///NEW VERSION
1385 tempoUpdateStrings[altIndex] = "";
1386 double timeInterval = beatTimes.beatTimes[beatTimes.index] - beatTimes.beatTimes[altIndex];
1387 //raw time difference
1388 beatTimes.intervalDifferences[beatTimes.index][altIndex] = 0;
1389 beatTimes.intervalUsed[beatTimes.index][altIndex] = false;
1390
1391 if (onsetType == "kick")
1392 beatTimes.OnsetIsKick[beatTimes.index] = true;
1393 else
1394 beatTimes.OnsetIsKick[beatTimes.index] = false;
1395
1396
1397
1398 if (!accompanimentStarted){
1399 //if we need to find tempo and start use this method
1400 //we have 'started' once std dev is sufficiently low
1401
1402 updateTempoIfWithinRange(timeInterval);//taken as being the tatum interval
1403
1404
1405
1406 for (int i = 1;i <= 4;i++){
1407 //we test the main beats and the two bar (16 tatum intervals)
1408
1409 double testInterval = timeInterval / 2*i;//pow(2, i);//pow(2.0, i);
1410
1411 if (updateTempoIfWithinRange(testInterval)){
1412 printf("test time %f, beats %i\n", testInterval, i);
1413
1414 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
1415 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
1416 //xx what if two within range here?
1417
1418 tempoUpdateStrings[altIndex] = "Tempo Updates (";
1419 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
1420 tempoUpdateStrings[altIndex] += ") : [";
1421 tempoUpdateStrings[altIndex] += ofToString(altIndex);
1422 tempoUpdateStrings[altIndex] += "]] : ";
1423 tempoUpdateStrings[altIndex] += ofToString(timeInterval);
1424 tempoUpdateStrings[altIndex] += ", ioi:";
1425 tempoUpdateStrings[altIndex] += ofToString(i);
1426 //tempoUpdateStrings[altIndex] += "";
1427
1428 }
1429
1430 }
1431
1432 double testInterval = timeInterval / 16;//pow(2, i);//pow(2.0, i);
1433 if (updateTempoIfWithinRange(testInterval)){
1434 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
1435 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
1436 }
1437
1438 }else{
1439 //OLD VERSON
1440 //THIS USES THE CURRENT TEMPO ESTIMATE TO DECIDE WHAT THE BEST INTERVAL IS
1441 //&& integerMultipleOfTatum % 2 == 0 removed below XXX put back
1442 if (altIndex != beatTimes.index && integerMultipleOfTatum < 17
1443 && integerMultipleOfTatum > 0 && beatTimes.startIndex > 8//beattimes.index > 8 - the start
1444 && integerMultipleOfTatum%2 == 0){//mod 2 - i.e. proper beat intervals only
1445
1446 double testInterval = timeInterval / integerMultipleOfTatum;
1447
1448 if (updateTempoIfWithinRange(testInterval)){
1449
1450 beatTimes.intervalUsed[beatTimes.index][altIndex] = true;
1451 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval;
1452
1453 if (paused == false){
1454 tempoUpdateStrings[altIndex] = "Tempo Updates : (";
1455 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0);
1456 tempoUpdateStrings[altIndex] += ") : [";
1457 tempoUpdateStrings[altIndex] += ofToString(altIndex, 0);
1458 tempoUpdateStrings[altIndex] += "] :: ";
1459 tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
1460 tempoUpdateStrings[altIndex] += " intervals :: ";
1461 tempoUpdateStrings[altIndex] += ofToString(tempoInterval);
1462 tempoUpdateStrings[altIndex] += " ms.";
1463 // tempoUpdateStrings[altIndex] += ", ioi:";
1464
1465 // tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum);
1466
1467
1468
1469
1470 }//end if not paused
1471
1472
1473 }//end if good interval to update
1474
1475 }//end if not same index etc
1476
1477
1478 }
1479
1480
1481
1482 }//end for all intervals
1483
1484 sendMaxTempo();
1485 }//end if new beat time
1486 double tempoEstimate = tempoDistribution.getIntegratedEstimateIndex();
1487 tempoDistribution.calculateStandardDeviation();
1488 tempoStdDev = tempoDistribution.standardDeviation;
1489
1490 }
1491
1492
1493 bool testApp::updateTempoIfWithinRange(double timeInterval){
1494
1495 bool updated = false;
1496
1497 if (timeInterval > tempoMinimum && timeInterval < tempoMaximum ){
1498 calculateTempoUpdate(timeInterval);
1499 updated = true;
1500 }
1501
1502 return updated;
1503 }
1504
1505
1506 */
1507 //end
1508 /*
1509 void testApp::calculateTempoUpdate(double tempoInterval){
1510
1511
1512 tempoDistribution.resetPrior();
1513 //need to relook at likelihood for the tempo distribution - not the same as....
1514 tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval-tempoMinimum)/(tempoMaximum - tempoMinimum), tempoDistribution.likelihoodStdDev);
1515 tempoDistribution.calculatePosterior();
1516 tempoDistribution.renormalisePosterior();
1517
1518 //did take pic of screen here - see initialiser4
1519 }
1520 */
1521