Mercurial > hg > multitrack-audio-matcher
comparison src/AudioEventMatcher.cpp @ 32:4be22a1a0e24
added in chroma comparison for fourth channel (guitar)
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Mon, 02 Apr 2012 17:19:22 +0100 |
parents | c47ea39b830d |
children | 0d52ba6844b9 |
comparison
equal
deleted
inserted
replaced
31:02f659277346 | 32:4be22a1a0e24 |
---|---|
9 | 9 |
10 #include "AudioEventMatcher.h" | 10 #include "AudioEventMatcher.h" |
11 | 11 |
12 | 12 |
13 const int matchWindowWidth = 6000; | 13 const int matchWindowWidth = 6000; |
14 const float pitchCutOff = 16;//within which pitches are even considered | |
14 | 15 |
15 AudioEventMatcher::AudioEventMatcher(){ | 16 AudioEventMatcher::AudioEventMatcher(){ |
16 | 17 |
17 | 18 |
18 pitchLikelihoodToNoise = 0.6;//more noise | 19 pitchLikelihoodToNoise = 0.6;//more noise |
20 chromaLikelihoodToNoise = 0.5;//lower => more noise, higher more weight for events | |
21 chromaLikelihoodWidth = 50;//ms round onset event | |
19 | 22 |
20 onsetLikelihoodToNoise = 0.4; | 23 onsetLikelihoodToNoise = 0.4; |
21 onsetLikelihoodWidth = 10;//in ms | 24 onsetLikelihoodWidth = 10;//in ms |
22 | 25 |
23 setArraySizes(); | 26 setArraySizes(); |
40 | 43 |
41 | 44 |
42 void AudioEventMatcher::setWindowDimensions(){ | 45 void AudioEventMatcher::setWindowDimensions(){ |
43 double startHeight = recordedTracks.numberOfAudioTracks * recordedTracks.trackScreenHeight; | 46 double startHeight = recordedTracks.numberOfAudioTracks * recordedTracks.trackScreenHeight; |
44 double heightAvailable = 1 - startHeight; | 47 double heightAvailable = 1 - startHeight; |
45 heightAvailable /= NUMBER_OF_CHANNELS; | 48 heightAvailable /= numberOfChannels; |
46 | 49 |
47 bayesPositionWindow.setToRelativeSize(0, startHeight, 1, heightAvailable); | 50 bayesPositionWindow.setToRelativeSize(0, startHeight, 1, heightAvailable); |
48 bayesLikelihoodWindow.setToRelativeSize(0, startHeight + 1*heightAvailable, 1, heightAvailable); | 51 bayesLikelihoodWindow.setToRelativeSize(0, startHeight + 1*heightAvailable, 1, heightAvailable); |
49 bayesTempoWindow.setToRelativeSize(0, startHeight + 2*heightAvailable, 1, heightAvailable); | 52 bayesTempoWindow.setToRelativeSize(0, startHeight + 2*heightAvailable, 1, heightAvailable); |
50 | 53 |
208 synchroniser.updateRecordedPosition(currentAlignmentPosition, newTime); | 211 synchroniser.updateRecordedPosition(currentAlignmentPosition, newTime); |
209 | 212 |
210 synchroniser.updateOutputSpeed(); | 213 synchroniser.updateOutputSpeed(); |
211 | 214 |
212 bayesianStruct.projectDistribution(newTime, currentAlignmentPosition, projectedPrior);//prior gets updated to where we are now | 215 bayesianStruct.projectDistribution(newTime, currentAlignmentPosition, projectedPrior);//prior gets updated to where we are now |
213 printf("alignment %i:: %i\n", newTime, (int) currentAlignmentPosition); | 216 |
217 // printf("updateBestAlignment:: alignment %i:: %i\n", newTime, (int) currentAlignmentPosition); | |
214 | 218 |
215 // printf("ALIGN pos %f time diff %f (now %f , last %f)speed %f :: ALIGN BEST %f\n", tmp, timetmp, (double)ofGetElapsedTimeMillis(), lastAlignmentTime, speedtmp, currentAlignmentPosition); | 219 // printf("ALIGN pos %f time diff %f (now %f , last %f)speed %f :: ALIGN BEST %f\n", tmp, timetmp, (double)ofGetElapsedTimeMillis(), lastAlignmentTime, speedtmp, currentAlignmentPosition); |
216 } | 220 } |
217 | 221 |
218 void AudioEventMatcher::draw(){ | 222 void AudioEventMatcher::draw(){ |
223 | |
224 //MAIN DRAW FUNCTION FOR ALL | |
225 | |
219 //draw some outlines in blue | 226 //draw some outlines in blue |
220 ofSetColor(20,200,200); | 227 ofSetColor(20,200,200); |
221 bayesPositionWindow.drawOutline(); | 228 bayesPositionWindow.drawOutline(); |
222 bayesTempoWindow.drawOutline(); | 229 bayesTempoWindow.drawOutline(); |
223 | 230 |
231 drawBayesianDistributions(); | 238 drawBayesianDistributions(); |
232 | 239 |
233 //bayesianStruct.posterior.drawVector(0, bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); | 240 //bayesianStruct.posterior.drawVector(0, bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); |
234 //bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); | 241 //bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); |
235 //bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow); | 242 //bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow); |
236 string tmpStr = "pitch "+ofToString(recentPitch, 2); | 243 |
237 tmpStr += " Nearest "+ofToString(pitchOfNearestMatch,2); | |
238 tmpStr += " dist "+ofToString(distanceOfNearestMatch, 2); | |
239 tmpStr += ", Time "+ofToString(recentTime, 0); | |
240 ofDrawBitmapString(tmpStr, 20, 20); | |
241 | |
242 | |
243 | |
244 string alignString = " align "+ofToString(currentAlignmentPosition, 2); | |
245 alignString += " playing "+ofToString(synchroniser.playingPositionRatio, 5); | |
246 alignString += " pos "+ofToString(synchroniser.playingPositionMillis,0)+" ms"; | |
247 alignString += " rec pos "+ofToString(synchroniser.recordedPositionMillis,0)+" ms"; | |
248 ofDrawBitmapString(alignString, 20, 50); | |
249 | |
250 ofDrawBitmapString("pos "+ofToString(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.playPosition), 200,600); | |
251 | |
252 temporal.drawTempoArray(bayesLikelihoodWindow); | 244 temporal.drawTempoArray(bayesLikelihoodWindow); |
253 | 245 |
254 drawRecordedTempo(); | 246 drawRecordedTempo(); |
255 drawPlayingTempo(); | 247 drawPlayingTempo(); |
256 | 248 |
302 }*/ | 294 }*/ |
303 } | 295 } |
304 | 296 |
305 void AudioEventMatcher::drawBayesianDistributions(){ | 297 void AudioEventMatcher::drawBayesianDistributions(){ |
306 | 298 |
307 | 299 |
300 drawPositionWindow(); | |
301 | |
302 // bayesianStruct.likelihood.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesLikelihoodWindow); | |
303 | |
304 bayesianStruct.relativeSpeedPosterior.drawConstrainedVector(0, bayesianStruct.relativeSpeedPosterior.arraySize, 0, ofGetWidth(), bayesTempoWindow); | |
305 | |
306 | |
307 drawTrackLikelihoods(); | |
308 | |
309 // int priorStartIndex = bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis); | |
310 // int priorEndIndex = bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis); | |
311 // ofSetColor(0,200,200);//recent prior | |
312 // recentPrior.drawConstrainedVector(priorStartIndex, priorEndIndex, 0, ofGetWidth(), bayesPositionWindow); | |
313 | |
314 drawInfo(); | |
315 | |
316 | |
317 } | |
318 | |
319 void AudioEventMatcher::drawPositionWindow(){ | |
308 int startIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenStartTimeMillis); | 320 int startIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenStartTimeMillis); |
309 int endIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenEndTimeMillis); | 321 int endIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenEndTimeMillis); |
310 | |
311 bayesianStruct.posterior.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesPositionWindow); | |
312 | |
313 string tmpString = "start "+ofToString(screenStartTimeMillis)+" (index "+ofToString(startIndex)+"), end "+ofToString(screenEndTimeMillis); | 322 string tmpString = "start "+ofToString(screenStartTimeMillis)+" (index "+ofToString(startIndex)+"), end "+ofToString(screenEndTimeMillis); |
314 ofDrawBitmapString(tmpString, bayesPositionWindow.x+20, bayesPositionWindow.y+20); | 323 ofDrawBitmapString(tmpString, bayesPositionWindow.x+20, bayesPositionWindow.y+20); |
315 | 324 |
316 // bayesianStruct.likelihood.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesLikelihoodWindow); | 325 //draw posterior in the bayes position window |
317 | 326 ofSetColor(255,0,255); |
318 bayesianStruct.relativeSpeedPosterior.drawConstrainedVector(0, bayesianStruct.relativeSpeedPosterior.arraySize, 0, ofGetWidth(), bayesTempoWindow); | 327 bayesianStruct.posterior.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesPositionWindow); |
319 | 328 |
329 //green line at current best estimate | |
330 ofSetColor(0,255,0);//green scrolling line best position | |
331 double currentEstimateIndex = (currentAlignmentPosition - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis; | |
332 ofLine(currentEstimateIndex, bayesPositionWindow.y, currentEstimateIndex, bayesPositionWindow.y + bayesPositionWindow.height); | |
333 | |
334 | |
335 ofSetColor(0,255,255);//synchroniser position | |
336 currentEstimateIndex = (synchroniser.playingPositionMillis - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis; | |
337 ofLine(currentEstimateIndex, bayesLikelihoodWindow.y, currentEstimateIndex, bayesLikelihoodWindow.y + bayesPositionWindow.height); | |
338 | |
339 ofSetColor(255,0,100);//purple prior | |
340 bayesianStruct.prior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow); | |
341 | |
342 ofSetColor(255,0,0);//projected prior in red | |
343 projectedPrior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow); | |
344 | |
345 | |
346 | |
347 } | |
348 | |
349 void AudioEventMatcher::drawTrackLikelihoods(){ | |
350 //draw track by track likelihoods | |
351 for (int i = 0; i <recordedTracks.numberOfAudioTracks;i++){ | |
352 ofSetColor(200,255,50);//channel likelihoods in yellow | |
353 likelihoodVisualisation[i].drawConstrainedVector(likelihoodVisualisation[i].getRealTermsAsIndex(screenStartTimeMillis), likelihoodVisualisation[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window); | |
354 | |
355 ofSetColor(0,255,150);//channel priors | |
356 recentPriors[i].drawConstrainedVector(recentPriors[i].getRealTermsAsIndex(screenStartTimeMillis), recentPriors[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window); | |
357 | |
358 | |
359 ofSetColor(255); | |
360 ofDrawBitmapString("recent event "+ofToString(recentEventTime[i]), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window.x + 20, recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window.y + recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window.height - 10); | |
361 } | |
362 } | |
363 | |
364 | |
365 void AudioEventMatcher::drawInfo(){ | |
320 string tmpStr = "zero is "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(0)); | 366 string tmpStr = "zero is "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(0)); |
321 tmpStr += " offsetis "+ofToString(bayesianStruct.posterior.offset); | 367 tmpStr += " offsetis "+ofToString(bayesianStruct.posterior.offset); |
322 tmpStr += " screenWidth = "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis)); | 368 tmpStr += " screenWidth = "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis)); |
323 ofDrawBitmapString(tmpStr, 20,140); | 369 ofDrawBitmapString(tmpStr, 20,140); |
324 tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate); | 370 tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate); |
325 ofDrawBitmapString(tmpStr, 20, 180); | 371 ofDrawBitmapString(tmpStr, 20, 180); |
326 | |
327 ofDrawBitmapString("screenwidth "+ofToString(screenWidthMillis), 20, 800); | 372 ofDrawBitmapString("screenwidth "+ofToString(screenWidthMillis), 20, 800); |
328 | 373 |
329 //green line at current best estimate | 374 ofSetColor(255); |
330 ofSetColor(0,255,0);//green scrolling line best position | 375 tmpStr = "pitch "+ofToString(recentPitch, 2); |
331 double currentEstimateIndex = (currentAlignmentPosition - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis; | 376 tmpStr += " Nearest "+ofToString(pitchOfNearestMatch,2); |
332 ofLine(currentEstimateIndex, bayesPositionWindow.y, currentEstimateIndex, bayesPositionWindow.y + bayesPositionWindow.height); | 377 tmpStr += " dist "+ofToString(distanceOfNearestMatch, 2); |
333 | 378 tmpStr += ", Time "+ofToString(recentTime, 0); |
334 | 379 ofDrawBitmapString(tmpStr, 20, 20); |
335 ofSetColor(0,255,255);//synchroniser position | 380 |
336 currentEstimateIndex = (synchroniser.playingPositionMillis - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis; | 381 string alignString = " align "+ofToString(currentAlignmentPosition, 2); |
337 ofLine(currentEstimateIndex, bayesLikelihoodWindow.y, currentEstimateIndex, bayesLikelihoodWindow.y + bayesPositionWindow.height); | 382 alignString += " playing "+ofToString(synchroniser.playingPositionRatio, 5); |
338 | 383 alignString += " pos "+ofToString(synchroniser.playingPositionMillis,0)+" ms"; |
339 | 384 alignString += " rec pos "+ofToString(synchroniser.recordedPositionMillis,0)+" ms"; |
340 | 385 ofDrawBitmapString(alignString, 20, 50); |
341 //draw track by track likelihoods | 386 |
342 for (int i = 0; i <recordedTracks.numberOfAudioTracks;i++){ | 387 ofDrawBitmapString("pos "+ofToString(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.playPosition), 200,600); |
343 ofSetColor(200,255,50);//channel likelihoods in yellow | |
344 likelihoodVisualisation[i].drawConstrainedVector(likelihoodVisualisation[i].getRealTermsAsIndex(screenStartTimeMillis), likelihoodVisualisation[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window); | |
345 | |
346 ofSetColor(0,255,150);//channel priors | |
347 recentPriors[i].drawConstrainedVector(recentPriors[i].getRealTermsAsIndex(screenStartTimeMillis), recentPriors[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window); | |
348 | |
349 | |
350 ofSetColor(255); | |
351 ofDrawBitmapString("recent event "+ofToString(recentEventTime[i]), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window.x + 20, recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window.y + recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window.height - 10); | |
352 } | |
353 | |
354 int priorStartIndex = bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis); | |
355 int priorEndIndex = bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis); | |
356 // ofSetColor(0,200,200);//recent prior | |
357 // recentPrior.drawConstrainedVector(priorStartIndex, priorEndIndex, 0, ofGetWidth(), bayesPositionWindow); | |
358 | |
359 ofSetColor(255,0,100);//purple prior | |
360 bayesianStruct.prior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow); | |
361 | |
362 ofSetColor(255,0,0); | |
363 projectedPrior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow); | |
364 | |
365 | |
366 | 388 |
367 } | 389 } |
368 | 390 |
369 void AudioEventMatcher::newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){ | 391 void AudioEventMatcher::newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){ |
370 if (pitchIn > 0){ | 392 if (pitchIn > 0){ |
377 likelihoodVisualisation[1] = bayesianStruct.likelihood; | 399 likelihoodVisualisation[1] = bayesianStruct.likelihood; |
378 | 400 |
379 recentPitch = pitchIn;//for drawing | 401 recentPitch = pitchIn;//for drawing |
380 recentTime = timeIn; | 402 recentTime = timeIn; |
381 } | 403 } |
382 | 404 } |
383 } | 405 |
406 | |
407 void AudioEventMatcher::newChromaEvent(const int& channel, float* chromaIn, const double& timeIn){ | |
408 | |
409 // could add event to the liveInput list? as in pitch event | |
410 // printf("match chroma channel %i\n", channel); | |
411 | |
412 matchNewChromaEvent(channel, chromaIn, timeIn);//main pitch matching fn | |
413 | |
414 likelihoodVisualisation[channel] = bayesianStruct.likelihood; | |
415 | |
416 | |
417 } | |
418 | |
384 | 419 |
385 void AudioEventMatcher::newKickEvent(const double& timeIn){ | 420 void AudioEventMatcher::newKickEvent(const double& timeIn){ |
386 // liveInput.addKickEvent(timeIn); | 421 // liveInput.addKickEvent(timeIn); |
387 matchNewOnsetEvent(0, timeIn); | 422 matchNewOnsetEvent(0, timeIn); |
388 likelihoodVisualisation[0] = bayesianStruct.likelihood; | 423 likelihoodVisualisation[0] = bayesianStruct.likelihood; |
410 void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){ | 445 void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){ |
411 | 446 |
412 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets | 447 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets |
413 | 448 |
414 //start at beginning but OPTIMISE later | 449 //start at beginning but OPTIMISE later |
415 | |
416 | |
417 bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; | 450 bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; |
418 bayesianStruct.likelihood.zero();//set to zero | 451 bayesianStruct.likelihood.zero();//set to zero |
419 | 452 |
420 double quantity = 1;//likelihoodToNoiseRatio / numberOfMatches; | 453 double quantity = 1;//likelihoodToNoiseRatio / numberOfMatches; |
421 int numberOfMatchesFound = 0; | 454 int numberOfMatchesFound = 0; |
422 | 455 |
423 | |
424 double startMatchingTime = bayesianStruct.likelihood.offset; | 456 double startMatchingTime = bayesianStruct.likelihood.offset; |
425 double endMatchingTime = bayesianStruct.likelihood.offset + matchWindowWidth; | 457 double endMatchingTime = bayesianStruct.likelihood.offset + matchWindowWidth; |
426 | 458 double millisTime = -1*INFINITY;//or 0 is fine |
459 int checkIndex = 0; | |
427 if (channel <= recordedTracks.numberOfAudioTracks){ | 460 if (channel <= recordedTracks.numberOfAudioTracks){ |
428 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ | 461 while (millisTime < startMatchingTime) { |
429 double millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime; | 462 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[checkIndex].millisTime; |
463 checkIndex++; | |
464 } | |
465 for (int i = checkIndex;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size() && millisTime <= endMatchingTime;i++){ | |
466 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime; | |
430 if (millisTime >= startMatchingTime && millisTime <= endMatchingTime){ | 467 if (millisTime >= startMatchingTime && millisTime <= endMatchingTime){ |
431 bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, onsetLikelihoodWidth, quantity); | 468 bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, onsetLikelihoodWidth, quantity); |
432 numberOfMatchesFound++; | 469 numberOfMatchesFound++; |
433 // printf("Adding Gaussian for onset at time %f offset %f\n", millisTime, bayesianStruct.likelihood.offset); | 470 // printf("Adding Gaussian for onset at time %f offset %f\n", millisTime, bayesianStruct.likelihood.offset); |
434 | 471 |
435 } | 472 }//end if within limits (changed so it now is 4 sure) |
436 } | 473 } |
437 } | 474 } |
438 | 475 |
439 if (numberOfMatchesFound > 0){ | 476 if (numberOfMatchesFound > 0){ |
440 // bayesianStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesianStruct.likelihood.length); | 477 // bayesianStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesianStruct.likelihood.length); |
449 projectedPrior = bayesianStruct.prior; | 486 projectedPrior = bayesianStruct.prior; |
450 | 487 |
451 | 488 |
452 temporal.updateTempo(channel, timeIn); | 489 temporal.updateTempo(channel, timeIn); |
453 } | 490 } |
454 | |
455 | |
456 | 491 |
457 } | 492 } |
458 | 493 |
459 | 494 |
460 | 495 |
474 bayesianStruct.likelihood.zero();//set to zero | 509 bayesianStruct.likelihood.zero();//set to zero |
475 double newOnsetTime; | 510 double newOnsetTime; |
476 double closestDistance = INFINITY; | 511 double closestDistance = INFINITY; |
477 | 512 |
478 double quantity = 0; | 513 double quantity = 0; |
514 double totalLikelihoodAdded = 0; | |
479 if (channel <= recordedTracks.numberOfAudioTracks){ | 515 if (channel <= recordedTracks.numberOfAudioTracks){ |
480 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ | 516 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ |
481 | 517 |
482 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { | 518 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { |
483 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 8); | 519 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 12); |
484 | 520 |
485 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity); | 521 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity); |
486 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; | 522 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; |
487 numberOfMatches++; | 523 numberOfMatches++; |
524 totalLikelihoodAdded += quantity; | |
488 } | 525 } |
489 else{ | 526 else{ |
490 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false; | 527 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false; |
491 } | 528 } |
492 //checking nearest pitch | 529 //checking nearest pitch |
501 } | 538 } |
502 | 539 |
503 | 540 |
504 | 541 |
505 if (numberOfMatches > 0){//no point updating unless there is a match | 542 if (numberOfMatches > 0){//no point updating unless there is a match |
506 | 543 //replacing numberOfMatches with totalLike below... |
507 bayesianStruct.likelihood.addConstant(numberOfMatches*(1-pitchLikelihoodToNoise)/(pitchLikelihoodToNoise*bayesianStruct.likelihood.length)); | 544 bayesianStruct.likelihood.addConstant(totalLikelihoodAdded*(1-pitchLikelihoodToNoise)/(pitchLikelihoodToNoise*bayesianStruct.likelihood.length)); |
508 | 545 |
509 //tmp set likelihood constant and calculate using that | 546 //tmp set likelihood constant and calculate using that |
510 //bayesianStruct.likelihood.zero(); | 547 //bayesianStruct.likelihood.zero(); |
511 //bayesianStruct.likelihood.addConstant(1); | 548 //bayesianStruct.likelihood.addConstant(1); |
512 | 549 |
527 | 564 |
528 double scaleFactor = scale * pitchOne / 110.0; | 565 double scaleFactor = scale * pitchOne / 110.0; |
529 | 566 |
530 int multiplicationFactor = 1; | 567 int multiplicationFactor = 1; |
531 if (pitchTwo > 0){ | 568 if (pitchTwo > 0){ |
532 int multiplicationFactor = round(pitchOne/pitchTwo); | 569 multiplicationFactor = round(pitchOne/pitchTwo); |
533 } | 570 } |
534 | 571 |
535 double distance = abs(pitchOne - pitchTwo*multiplicationFactor); | 572 double distance = abs(pitchOne - pitchTwo*multiplicationFactor); |
536 if (distance < scaleFactor) | 573 if (distance < scaleFactor) |
537 distance = 1 - (distance/scaleFactor); | 574 distance = 1 - (distance/scaleFactor); |
538 else | 575 else |
539 distance = 0; | 576 distance = 0; |
540 | 577 |
541 // printf("[pitch distance %f vs %f = %f\n", pitchOne, pitchTwo, distance); | 578 //printf("[pitch distance %f vs %f, factor %i = %f\n", pitchOne, pitchTwo, multiplicationFactor, distance); |
542 return distance; | 579 return distance; |
543 | 580 |
544 } | 581 } |
545 | 582 |
546 | 583 |
547 bool AudioEventMatcher::checkMatch(const double& recordedPitch, const double& livePitch){ | 584 bool AudioEventMatcher::checkMatch(const double& recordedPitch, const double& livePitch){ |
548 | 585 |
549 if (livePitch > 0){ | 586 if (livePitch > 0){ |
550 int multiplicationFactor = (int)(round(recordedPitch/livePitch)); | 587 int multiplicationFactor = (int)(round(recordedPitch/livePitch)); |
551 | 588 |
552 if (abs(recordedPitch - livePitch * multiplicationFactor) < 16) | 589 if (abs(recordedPitch - livePitch * multiplicationFactor) < pitchCutOff) |
553 return true; | 590 return true; |
554 else | 591 else |
555 return false; | 592 return false; |
556 }else { | 593 }else { |
557 return false; | 594 return false; |
558 } | 595 } |
559 | 596 |
560 } | 597 } |
561 | 598 |
562 | 599 |
600 void AudioEventMatcher::matchNewChromaEvent(const int& channel, float* chromaIn, const double& timeIn){ | |
601 //start at beginning but OPTIMISE later | |
602 | |
603 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets | |
604 | |
605 //set the likelihoods by matching the pitched note | |
606 | |
607 int numberOfMatches = 0; | |
608 bayesianStruct.likelihood.zero();//set to zero | |
609 double newOnsetTime; | |
610 double closestDistance = INFINITY; | |
611 | |
612 double quantity = 1; | |
613 double totalLikelihoodAdded = 0; | |
614 | |
615 double startMatchingTime = bayesianStruct.likelihood.offset; | |
616 double endMatchingTime = bayesianStruct.likelihood.offset + matchWindowWidth; | |
617 double millisTime = -1*INFINITY;//or 0 is fine | |
618 | |
619 int checkIndex = 0; | |
620 if (channel <= recordedTracks.numberOfAudioTracks){ | |
621 while (millisTime < startMatchingTime) { | |
622 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[checkIndex].millisTime; | |
623 checkIndex++; | |
624 }//go up to where we need to check from fast | |
625 | |
626 for (int i = checkIndex;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size() && millisTime <= endMatchingTime;i++){ | |
627 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime; | |
628 | |
629 if (millisTime >= startMatchingTime && millisTime <= endMatchingTime){ | |
630 quantity = getChromaDistance(chromaIn, &recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].chromaValues[0]); | |
631 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, chromaLikelihoodWidth, quantity); | |
632 | |
633 // bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, onsetLikelihoodWidth, quantity); | |
634 numberOfMatches++; | |
635 totalLikelihoodAdded += quantity; | |
636 printf("Adding CHROMA Gaussian for onset at time %.1f dist %.3f\n", millisTime, quantity); | |
637 | |
638 }//end if within limits (changed so it now is 4 sure) | |
639 } | |
640 } | |
641 | |
642 | |
643 if (numberOfMatches > 0){//no point updating unless there is a match | |
644 //replacing numberOfMatches with totalLike below... | |
645 | |
646 printf("CHROMA HAS %i MATCHES\n", numberOfMatches); | |
647 | |
648 bayesianStruct.likelihood.addConstant(totalLikelihoodAdded*(1-chromaLikelihoodToNoise)/(chromaLikelihoodToNoise*bayesianStruct.likelihood.length)); | |
649 | |
650 bayesianStruct.calculatePosterior(); | |
651 lastAlignmentTime = timeIn;//has to use the STAMPED time | |
652 recentEventTime[channel] = timeIn; | |
653 | |
654 recentPriors[channel] = bayesianStruct.prior; | |
655 projectedPrior = bayesianStruct.prior; | |
656 | |
657 temporal.eventTimes[channel].push_back(timeIn); | |
658 } | |
659 | |
660 } | |
661 | |
662 | |
663 double AudioEventMatcher::getChromaDistance(float* chromaOne, float* chromaTwo){ | |
664 double distance = 0; | |
665 double total = 0; | |
666 for (int i = 0;i < 12;i++){ | |
667 distance += chromaOne[i]*chromaTwo[i]; | |
668 total += chromaOne[i]*chromaOne[i] + (chromaTwo[i]*chromaTwo[i]); | |
669 } | |
670 | |
671 distance /= sqrt(total); | |
672 return distance; | |
673 } | |
563 | 674 |
564 void AudioEventMatcher::windowResized(const int& w, const int& h){ | 675 void AudioEventMatcher::windowResized(const int& w, const int& h){ |
565 recordedTracks.windowResized(w,h); | 676 recordedTracks.windowResized(w,h); |
566 bayesTempoWindow.resized(w,h); | 677 bayesTempoWindow.resized(w,h); |
567 bayesPositionWindow.resized(w,h); | 678 bayesPositionWindow.resized(w,h); |