Mercurial > hg > bayesian-drum-tracker
comparison src/BayesDrumTracker.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 /* | |
2 * BayesDrumTracker.cpp | |
3 * bayesianTempoInitialiser5 | |
4 * | |
5 * Created by Andrew on 14/07/2011. | |
6 * Copyright 2011 QMUL. All rights reserved. | |
7 * | |
8 */ | |
9 | |
10 #include "BayesDrumTracker.h" | |
11 #define OUTPORT 12346 | |
12 #define HOST "localhost" | |
13 | |
14 | |
15 //beatCorrection process indicates how the phase is changing from max | |
16 | |
17 | |
18 BayesDrumTracker::BayesDrumTracker(){ | |
19 | |
20 initialiseTracker(); | |
21 sender.setup( HOST, OUTPORT ); | |
22 } | |
23 | |
24 | |
25 BayesDrumTracker::~BayesDrumTracker(){} | |
26 | |
27 void BayesDrumTracker::initialiseTracker(){ | |
28 | |
29 beatDistribution.initialiseArray(); | |
30 tempoDistribution.initialiseArray(); | |
31 beatTimes.lastBeatTime = 0; | |
32 correctionFactor = 0.5; | |
33 | |
34 tempoDistribution.likelihoodStdDev = ARRAY_SIZE / 32; | |
35 // tempoDistribution.likelihoodNoise = 0.96; | |
36 tempoDistribution.likelihoodNoise = 0.7; | |
37 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1);//wide | |
38 | |
39 beatDistribution.likelihoodStdDev = ARRAY_SIZE / 32; | |
40 beatDistribution.likelihoodNoise = 0.56; | |
41 beatDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/1); | |
42 | |
43 | |
44 tempoMinimum = 180; | |
45 tempoMaximum = 400; | |
46 posteriorMaximum = 0.1; | |
47 | |
48 adaptiveStandardDeviationMode = false; | |
49 setDistributionOnStartTempo = true; | |
50 | |
51 setBeatToNowTime = ofGetElapsedTimeMillis(); | |
52 recentClickTime = ofGetElapsedTimeMillis(); | |
53 | |
54 resetParameters(); | |
55 //check what we can delete above SINCE RESET CALLED | |
56 | |
57 } | |
58 | |
59 | |
60 void BayesDrumTracker::resetParameters(){ | |
61 | |
62 beatTimes.startIndex = 0; | |
63 beatTimes.lastBeatTime = 0; | |
64 maxPhase = 0; | |
65 posteriorMaximum = 0.1; | |
66 | |
67 accompanimentStarted = false; | |
68 | |
69 tempoDistribution.likelihoodNoise = 0.8; | |
70 tempoDistribution.setGaussianPrior(ARRAY_SIZE/2, ARRAY_SIZE/2);//wide | |
71 | |
72 beatDistribution.initialiseArray(); | |
73 tempoDistribution.initialiseArray(); | |
74 | |
75 tempoDistribution.calculateStandardDeviation(); | |
76 beatDistribution.calculateStandardDeviation(); | |
77 | |
78 tempoStdDev = tempoDistribution.standardDeviation; | |
79 | |
80 beatTimes.resetBeatTimeArray(); | |
81 | |
82 } | |
83 | |
84 | |
85 | |
86 void BayesDrumTracker::decayDistributions(){ | |
87 | |
88 if (accompanimentStarted){ | |
89 tempoDistribution.decayPosteriorWithGaussianNoise (); | |
90 beatDistribution.decayPosteriorWithGaussianNoise(); | |
91 } | |
92 else{ | |
93 if (tempoStdDev < 0.8 && beatDistribution.standardDeviation < 5) | |
94 accompanimentStarted = true; | |
95 | |
96 } | |
97 } | |
98 | |
99 | |
100 void BayesDrumTracker::setBeatDistribution(int beatPosition){ | |
101 switch (beatPosition){ | |
102 //early sixteenth is that the beat is a sixteenth earlier | |
103 case 0: | |
104 case 1: | |
105 case 11: | |
106 //i.e. these zones are interpreted as "on the beat" | |
107 beatDistribution.eighthNoteProportion = 0; | |
108 beatDistribution.earlySixteenthNoteProportion = 0; | |
109 beatDistribution.lateSixteenthNoteProportion = 0; | |
110 break; | |
111 //10 and 2 were here | |
112 | |
113 case 2: | |
114 beatDistribution.eighthNoteProportion = 0; | |
115 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8 | |
116 //i.e. a 25% chance it is early sixteenth - 75% that the beat actually lies here | |
117 beatDistribution.lateSixteenthNoteProportion = 0; | |
118 break; | |
119 | |
120 case 3: | |
121 beatDistribution.eighthNoteProportion = 0; | |
122 beatDistribution.earlySixteenthNoteProportion = 0.3;//was 0.4 in Bayesian8 //half chance it is early | |
123 beatDistribution.lateSixteenthNoteProportion = 0; | |
124 break; | |
125 | |
126 case 5: | |
127 case 6: | |
128 case 7: | |
129 beatDistribution.eighthNoteProportion = 0.3;//i.e. nearly half a chance we are on the 8th note | |
130 beatDistribution.earlySixteenthNoteProportion = 0; | |
131 beatDistribution.lateSixteenthNoteProportion = 0; | |
132 break; | |
133 | |
134 case 4: | |
135 beatDistribution.eighthNoteProportion = 0; | |
136 beatDistribution.earlySixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8 | |
137 beatDistribution.lateSixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8 | |
138 //chsanged to 0.2 and 0.1 then back | |
139 break; | |
140 | |
141 case 8: | |
142 beatDistribution.eighthNoteProportion = 0; | |
143 beatDistribution.earlySixteenthNoteProportion = 0.05;//was 0.2 in Bayesian8 | |
144 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.3 in Bayesian8 | |
145 break; | |
146 | |
147 case 9: | |
148 beatDistribution.eighthNoteProportion = 0; | |
149 beatDistribution.earlySixteenthNoteProportion = 0; | |
150 beatDistribution.lateSixteenthNoteProportion = 0.35;//was 0.4 in Bayesian8 | |
151 break; | |
152 | |
153 case 10: | |
154 beatDistribution.eighthNoteProportion = 0; | |
155 beatDistribution.earlySixteenthNoteProportion = 0; | |
156 beatDistribution.lateSixteenthNoteProportion = 0.25;//was 0.2 in Bayesian8 | |
157 break; | |
158 | |
159 } | |
160 | |
161 } | |
162 | |
163 void BayesDrumTracker::newKickError(const float& error, const double& cpuEventTime, const string& onsetTypeString){ | |
164 | |
165 onsetType = onsetTypeString; | |
166 cpuBeatTime = cpuEventTime; | |
167 kickError = error; | |
168 | |
169 //printf("beat errror %f time %f\n", kickError, cpuBeatTime); | |
170 | |
171 while (kickError > 0.5){ | |
172 kickError -= 1; | |
173 } | |
174 | |
175 if (paused != true){ | |
176 updateTempoProcess(cpuBeatTime, onsetType); | |
177 //this also cross updates the distributions | |
178 beatTimes.beatMapTimeDifferences[beatTimes.beatSegment] = kickError*beatTimes.tatum; | |
179 }//end if paused | |
180 | |
181 | |
182 | |
183 if (onsetType == "kick"){ | |
184 if (accompanimentStarted) | |
185 beatDistribution.likelihoodNoise = 0.5; | |
186 else | |
187 beatDistribution.likelihoodNoise = 0.5; | |
188 // printf("kick %f ", cpuBeatTime); | |
189 } | |
190 else{ | |
191 //snare | |
192 if (accompanimentStarted) | |
193 beatDistribution.likelihoodNoise = 0.7; | |
194 else | |
195 beatDistribution.likelihoodNoise = 0.85; | |
196 // printf("snare %f ", cpuBeatTime); | |
197 } | |
198 | |
199 | |
200 setBeatDistribution(beatTimes.beatSegment%12); | |
201 | |
202 if (kickError <= 0.5 && kickError >= -0.5) | |
203 { | |
204 float beatStandardDeviation; | |
205 if (adaptiveStandardDeviationMode) | |
206 beatStandardDeviation = min((double)beatDistribution.likelihoodStdDev, beatDistribution.standardDeviation); | |
207 else | |
208 beatStandardDeviation = beatDistribution.likelihoodStdDev; | |
209 | |
210 | |
211 beatDistribution.resetPrior(); | |
212 beatDistribution.setGaussianLikelihoodForBeats((ARRAY_SIZE/2)+(kickError*ARRAY_SIZE), beatStandardDeviation); | |
213 beatDistribution.calculatePosterior(); | |
214 beatDistribution.renormalisePosterior(); | |
215 | |
216 sendMaxPhase(); | |
217 | |
218 beatDistribution.calculateStandardDeviation(); | |
219 | |
220 }//end if error < 0.5 | |
221 | |
222 | |
223 | |
224 if (beatTimes.beatSegment % 12 == 6){ | |
225 kickString = "Kick "; | |
226 kickString += ofToString(kickError); | |
227 kickString += " ERROR "; | |
228 kickString += ofToString(kickError, 2); | |
229 kickString += " at time diff "; | |
230 kickString += ofToString(cpuBeatTime - beatTimes.lastClickTime, 2); | |
231 kickString += " index "; | |
232 kickString += ofToString(beatTimes.lastClickIndex, 2); | |
233 kickString += " TYPE "; | |
234 kickString += ofToString(beatTimes.beatSegment%12); | |
235 kickString += " Time diff "; | |
236 kickString += ofToString(beatTimes.timeDifference, 2); | |
237 } | |
238 | |
239 | |
240 } | |
241 | |
242 | |
243 | |
244 void BayesDrumTracker::startTatum(const float& startTatum){ | |
245 beatTimes.tatum = startTatum; | |
246 | |
247 if (setDistributionOnStartTempo){ | |
248 beatDistribution.setGaussianPosterior(ARRAY_SIZE/2, 8); | |
249 tempoDistribution.setGaussianPosterior(ARRAY_SIZE/2, 12); | |
250 float tmpIndex; | |
251 tmpIndex = ( (beatTimes.tatum - ((tempoMinimum+tempoMaximum)/2) ) * ARRAY_SIZE)/(tempoMaximum - tempoMinimum); | |
252 tempoDistribution.translateDistribution(tmpIndex); | |
253 | |
254 sendMaxTempo(); | |
255 } | |
256 } | |
257 | |
258 | |
259 void BayesDrumTracker::setUniformTempo(){ | |
260 for (int i = 0;i < ARRAY_SIZE;i++) | |
261 tempoDistribution.posterior[i] = (float)1/ARRAY_SIZE; | |
262 } | |
263 | |
264 | |
265 void BayesDrumTracker::setUniformPhase(){ | |
266 for (int i = 0;i < ARRAY_SIZE;i++) | |
267 beatDistribution.posterior[i] = (float)1/ARRAY_SIZE; | |
268 } | |
269 | |
270 void BayesDrumTracker::setBeatNow(const double& beatTime){ | |
271 for (int i = 0;i < ARRAY_SIZE;i++) | |
272 beatDistribution.prior[i] = (float)1/ARRAY_SIZE; | |
273 | |
274 setBeatToNowTime = ofGetElapsedTimeMillis(); | |
275 double difference = (setBeatToNowTime - recentClickTime); | |
276 printf("SET BEAT TO NOW %f vs %f :: diff %f tatum %f :: ", setBeatToNowTime, recentClickTime, difference, beatTimes.tatum ); | |
277 | |
278 double beatTimeToUse = 0; | |
279 | |
280 if (difference < beatTimes.tatum)//tatum is the eighth note time | |
281 beatTimeToUse = difference/ (2*beatTimes.tatum); | |
282 else | |
283 beatTimeToUse = -1*(2*beatTimes.tatum - difference) / (2*beatTimes.tatum); | |
284 | |
285 printf("sending %f \n", beatTimeToUse); | |
286 | |
287 beatDistribution.setGaussianLikelihoodForBeats((ARRAY_SIZE/2)+(beatTimeToUse*ARRAY_SIZE), 2); | |
288 beatDistribution.calculatePosterior(); | |
289 beatDistribution.renormalisePosterior(); | |
290 | |
291 sendMaxPhase(); | |
292 | |
293 | |
294 } | |
295 | |
296 | |
297 void BayesDrumTracker::newBeat(int& beatIndex){ | |
298 ofxOscMessage m; | |
299 m.setAddress( "/beatInfo" ); | |
300 | |
301 m.addFloatArg(beatTimes.tatum); | |
302 m.addFloatArg(maxPhase); | |
303 | |
304 beatTimes.tatum = maxTempo; | |
305 printf("BEAT INFO %f, %f\n", beatTimes.tatum, maxPhase); | |
306 | |
307 sender.sendMessage( m ); | |
308 | |
309 } | |
310 | |
311 void BayesDrumTracker::sendMaxTempo(){ | |
312 ofxOscMessage m; | |
313 m.setAddress( "/tempo" ); | |
314 | |
315 //maxTempo = tempoDistribution.maximumIndex * (tempoMaximum - tempoMinimum) / ARRAY_SIZE; | |
316 //would be introduced new in bayesian8 | |
317 maxTempo = tempoDistribution.getIntegratedEstimateIndex() * (tempoMaximum - tempoMinimum) / ARRAY_SIZE; | |
318 maxTempo += tempoMinimum; | |
319 | |
320 beatTimes.tatum = maxTempo; | |
321 printf("SEND TATUM %f\n", beatTimes.tatum); | |
322 | |
323 m.addFloatArg( maxTempo ); | |
324 sender.sendMessage( m ); | |
325 | |
326 //printf("max tempo %f\n", maxTempo); | |
327 | |
328 } | |
329 | |
330 void BayesDrumTracker::sendMaxPhase(){ | |
331 | |
332 | |
333 // maxPhase = (beatDistribution.maximumIndex - (ARRAY_SIZE/2)) / ARRAY_SIZE; | |
334 maxPhase = (beatDistribution.getIntegratedEstimateIndex() - (ARRAY_SIZE/2)) / ARRAY_SIZE; | |
335 // printf("\nphase index %f :: %f\n", (float) beatDistribution.integratedEstimate , maxPhase); | |
336 ofxOscMessage m; | |
337 m.setAddress( "/phase" ); | |
338 m.addFloatArg( maxPhase ); | |
339 sender.sendMessage( m ); | |
340 | |
341 //beatCorrection = maxPhase * beatTimes.tatum / 4; | |
342 } | |
343 | |
344 | |
345 void BayesDrumTracker::setNewClickIndex(const int& clickIndex, const float& clickTime){ | |
346 | |
347 beatTimes.lastClickIndex = clickIndex; | |
348 beatTimes.lastClickTime = clickTime; | |
349 | |
350 int clickIndexToUse = clickIndex % 16; | |
351 beatTimes.clickIndex = clickIndex; | |
352 beatTimes.clickNumber[clickIndexToUse] = clickIndex; | |
353 beatTimes.clickTimes[clickIndexToUse] = clickTime; | |
354 | |
355 recentClickTime = ofGetElapsedTimeMillis(); | |
356 | |
357 } | |
358 | |
359 | |
360 void BayesDrumTracker::doBeatCorrection(const float& beatCorrFloat){ | |
361 beatCorrection = beatCorrFloat; | |
362 correctBeatBy = round(correctionFactor * beatCorrection * ARRAY_SIZE / (2 * beatTimes.tatum)); | |
363 beatDistribution.translateDistribution(-1 * correctBeatBy); | |
364 } | |
365 | |
366 | |
367 bool BayesDrumTracker::filterBeatTime(double newBeatTime){ | |
368 bool newBeatFound = false; | |
369 if ((newBeatTime - beatTimes.lastBeatTime) > 20 || beatTimes.lastBeatTime == 0){ | |
370 | |
371 crossUpdateArrays((float)(newBeatTime - beatTimes.lastBeatTime)); | |
372 beatTimes.lastBeatTime = newBeatTime; | |
373 newBeatFound = true; | |
374 } | |
375 return newBeatFound; | |
376 } | |
377 | |
378 void BayesDrumTracker::crossUpdateArrays(float timeInterval){ | |
379 | |
380 int finalBeatIndex, tmpTempoIndex, startBeatIndex; | |
381 //finalBeat has contribution from BEAT[finalBeat + INT.k] * TEMPO[Max_tempo + k] where INT = INTERVAL | |
382 float interval; | |
383 interval = timeInterval / maxTempo;//beatTimes.tatum; | |
384 tempoDistribution.resetMaximumPosterior(); | |
385 beatDistribution.resetMaximumPosterior(); | |
386 | |
387 | |
388 int tmpBeatIndex; | |
389 //&& interval > 0.8 idea? | |
390 if (timeInterval > 0 && timeInterval < 12000 ){//need between 0 and 12 seconds only to update | |
391 | |
392 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){ | |
393 | |
394 tmpArray[tmpBeatIndex] = 0; | |
395 float minusMsecToMakeUp = beatIndexToMsec(tmpBeatIndex) / interval; | |
396 float plusMsecToMakeUp = beatIndexToMsec(ARRAY_SIZE - tmpBeatIndex) / interval; | |
397 float convertMsecToTempoIndex = ARRAY_SIZE / (tempoMaximum - tempoMinimum) ; | |
398 | |
399 | |
400 int minTempoIndex = -1 * (int)(minusMsecToMakeUp * convertMsecToTempoIndex); | |
401 int maxTempoIndex = (int)(plusMsecToMakeUp * convertMsecToTempoIndex); | |
402 | |
403 | |
404 if (tmpBeatIndex == beatDistribution.maximumIndex){ | |
405 // minTmpDebug = tempoDistribution.maximumIndex + minTempoIndex; | |
406 // maxTmpDebug = tempoDistribution.maximumIndex + maxTempoIndex; | |
407 debugArray[0] = beatDistribution.maximumIndex;// | |
408 debugArray[1] = timeInterval; | |
409 debugArray[2] = interval;//beatDistribution.maximumIndex; | |
410 debugArray[3] = tempoDistribution.maximumIndex; | |
411 } | |
412 | |
413 for (tmpTempoIndex = minTempoIndex;tmpTempoIndex <= maxTempoIndex;tmpTempoIndex++){ | |
414 | |
415 if ((tempoDistribution.maximumIndex + tmpTempoIndex) >= 0 | |
416 && (tempoDistribution.maximumIndex + tmpTempoIndex) < ARRAY_SIZE | |
417 && (tmpBeatIndex - (int)(interval*tmpTempoIndex)) >= 0 | |
418 && (tmpBeatIndex - (int)(interval*tmpTempoIndex))< ARRAY_SIZE){ | |
419 tmpArray[tmpBeatIndex] += beatDistribution.posterior[tmpBeatIndex - (int)(interval*tmpTempoIndex)] * tempoDistribution.posterior[(int)tempoDistribution.maximumIndex + tmpTempoIndex]; | |
420 } | |
421 }//end for tmpTmepo | |
422 | |
423 | |
424 | |
425 } | |
426 | |
427 float tmpFloat; | |
428 for (tmpBeatIndex = 0;tmpBeatIndex < ARRAY_SIZE;tmpBeatIndex++){ | |
429 //debug - dont actually update:: | |
430 | |
431 tmpFloat = beatDistribution.posterior[tmpBeatIndex]; | |
432 beatDistribution.posterior[tmpBeatIndex] = tmpArray[tmpBeatIndex]; | |
433 tmpArray[tmpBeatIndex] = tmpFloat; | |
434 } | |
435 beatDistribution.renormaliseArray(&beatDistribution.posterior[0], ARRAY_SIZE); | |
436 | |
437 } //end if | |
438 | |
439 | |
440 } | |
441 | |
442 | |
443 void BayesDrumTracker::updateTempoProcess(const double& cpuTime, const string& onsetDescription){ | |
444 | |
445 if (filterBeatTime(cpuTime) == true){ | |
446 //checks for no repeat | |
447 | |
448 if (onsetDescription == "kick") | |
449 beatTimes.addBeatTime(cpuTime, 1); | |
450 else | |
451 beatTimes.addBeatTime(cpuTime, 2); | |
452 | |
453 | |
454 //recalculate the distribution | |
455 int altIndex = 0; | |
456 | |
457 tempoDataString = "Tatum :"; | |
458 tempoDataString += ofToString(beatTimes.tatum, 2); | |
459 tempoDataString += " BPM "; | |
460 tempoDataString += ofToString((double)30000/beatTimes.tatum, 2); | |
461 | |
462 timeString = "Last BEAT "; | |
463 timeString += ofToString(beatTimes.lastBeatTime); | |
464 timeString += " CLICK "; | |
465 timeString += ofToString(beatTimes.lastClickTime); | |
466 timeString += " DIFDF "; | |
467 timeString += ofToString(beatTimes.timeDifference); | |
468 timeString += " segment "; | |
469 timeString += ofToString(beatTimes.beatSegment); | |
470 | |
471 | |
472 for (altIndex = 0;altIndex< 16;altIndex++){ | |
473 tempoInterval = beatTimes.intervalDifferences[beatTimes.index][altIndex]; | |
474 integerMultipleOfTatum = beatTimes.relativeIntervals[altIndex][1]; | |
475 | |
476 | |
477 ///NEW VERSION | |
478 tempoUpdateStrings[altIndex] = ""; | |
479 double timeInterval = beatTimes.beatTimes[beatTimes.index] - beatTimes.beatTimes[altIndex]; | |
480 //raw time difference | |
481 beatTimes.intervalDifferences[beatTimes.index][altIndex] = 0; | |
482 beatTimes.intervalUsed[beatTimes.index][altIndex] = false; | |
483 | |
484 if (onsetType == "kick") | |
485 beatTimes.OnsetIsKick[beatTimes.index] = true; | |
486 else | |
487 beatTimes.OnsetIsKick[beatTimes.index] = false; | |
488 | |
489 | |
490 | |
491 if (!accompanimentStarted){ | |
492 //if we need to find tempo and start use this method | |
493 //we have 'started' once std dev is sufficiently low | |
494 | |
495 updateTempoIfWithinRange(timeInterval);//taken as being the tatum interval | |
496 | |
497 | |
498 | |
499 for (int i = 1;i <= 4;i++){ | |
500 //we test the main beats and the two bar (16 tatum intervals) | |
501 | |
502 double testInterval = timeInterval / 2*i;//pow(2, i);//pow(2.0, i); | |
503 | |
504 if (updateTempoIfWithinRange(testInterval)){ | |
505 //printf("test time %f, beats %i\n", testInterval, i); | |
506 | |
507 beatTimes.intervalUsed[beatTimes.index][altIndex] = true; | |
508 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval; | |
509 //xx what if two within range here? | |
510 | |
511 tempoUpdateStrings[altIndex] = "Tempo Updates ("; | |
512 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0); | |
513 tempoUpdateStrings[altIndex] += ") : ["; | |
514 tempoUpdateStrings[altIndex] += ofToString(altIndex); | |
515 tempoUpdateStrings[altIndex] += "]] : "; | |
516 tempoUpdateStrings[altIndex] += ofToString(timeInterval); | |
517 tempoUpdateStrings[altIndex] += ", ioi:"; | |
518 tempoUpdateStrings[altIndex] += ofToString(i); | |
519 //tempoUpdateStrings[altIndex] += ""; | |
520 | |
521 } | |
522 | |
523 } | |
524 | |
525 double testInterval = timeInterval / 16;//pow(2, i);//pow(2.0, i); | |
526 if (updateTempoIfWithinRange(testInterval)){ | |
527 beatTimes.intervalUsed[beatTimes.index][altIndex] = true; | |
528 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval; | |
529 } | |
530 | |
531 }else{ | |
532 //OLD VERSON | |
533 //THIS USES THE CURRENT TEMPO ESTIMATE TO DECIDE WHAT THE BEST INTERVAL IS | |
534 //&& integerMultipleOfTatum % 2 == 0 removed below XXX put back | |
535 if (altIndex != beatTimes.index && integerMultipleOfTatum < 17 | |
536 && integerMultipleOfTatum > 0 && beatTimes.startIndex > 8//beattimes.index > 8 - the start | |
537 && integerMultipleOfTatum%2 == 0){//mod 2 - i.e. proper beat intervals only | |
538 | |
539 double testInterval = timeInterval / integerMultipleOfTatum; | |
540 | |
541 if (updateTempoIfWithinRange(testInterval)){ | |
542 | |
543 beatTimes.intervalUsed[beatTimes.index][altIndex] = true; | |
544 beatTimes.intervalDifferences[beatTimes.index][altIndex] = testInterval; | |
545 | |
546 if (paused == false){ | |
547 tempoUpdateStrings[altIndex] = "Tempo Updates : ("; | |
548 tempoUpdateStrings[altIndex] += ofToString(beatTimes.index, 0); | |
549 tempoUpdateStrings[altIndex] += ") : ["; | |
550 tempoUpdateStrings[altIndex] += ofToString(altIndex, 0); | |
551 tempoUpdateStrings[altIndex] += "] :: "; | |
552 tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum); | |
553 tempoUpdateStrings[altIndex] += " intervals :: "; | |
554 tempoUpdateStrings[altIndex] += ofToString(tempoInterval); | |
555 tempoUpdateStrings[altIndex] += " ms."; | |
556 // tempoUpdateStrings[altIndex] += ", ioi:"; | |
557 | |
558 // tempoUpdateStrings[altIndex] += ofToString(integerMultipleOfTatum); | |
559 | |
560 | |
561 | |
562 | |
563 }//end if not paused | |
564 | |
565 | |
566 }//end if good interval to update | |
567 | |
568 }//end if not same index etc | |
569 | |
570 | |
571 } | |
572 | |
573 | |
574 | |
575 }//end for all intervals | |
576 | |
577 sendMaxTempo(); | |
578 }//end if new beat time | |
579 double tempoEstimate = tempoDistribution.getIntegratedEstimateIndex(); | |
580 tempoDistribution.calculateStandardDeviation(); | |
581 tempoStdDev = tempoDistribution.standardDeviation; | |
582 | |
583 } | |
584 | |
585 | |
586 bool BayesDrumTracker::updateTempoIfWithinRange(double timeInterval){ | |
587 | |
588 bool updated = false; | |
589 | |
590 if (timeInterval > tempoMinimum && timeInterval < tempoMaximum ){ | |
591 calculateTempoUpdate(timeInterval); | |
592 updated = true; | |
593 } | |
594 | |
595 return updated; | |
596 } | |
597 | |
598 | |
599 void BayesDrumTracker::calculateTempoUpdate(double tempoInterval){ | |
600 | |
601 | |
602 tempoDistribution.resetPrior(); | |
603 //need to relook at likelihood for the tempo distribution - not the same as.... | |
604 tempoDistribution.setGaussianLikelihood(ARRAY_SIZE * (tempoInterval-tempoMinimum)/(tempoMaximum - tempoMinimum), tempoDistribution.likelihoodStdDev); | |
605 tempoDistribution.calculatePosterior(); | |
606 tempoDistribution.renormalisePosterior(); | |
607 | |
608 //did take pic of screen here - see initialiser4 | |
609 } | |
610 | |
611 | |
612 float BayesDrumTracker::tempoIndexToMsec(const int& index){ | |
613 float msec; | |
614 msec = index * (tempoMaximum - tempoMinimum) / ARRAY_SIZE; | |
615 msec += tempoMinimum; | |
616 return msec; | |
617 } | |
618 | |
619 float BayesDrumTracker::beatIndexToMsec(const int& index){ | |
620 float msec; | |
621 msec = index * maxTempo / ARRAY_SIZE; | |
622 msec += tempoMinimum; | |
623 return msec; | |
624 } | |
625 |