Mercurial > hg > multitrack-audio-matcher
comparison src/AudioEventMatcher.cpp @ 16:680ba08e9925
Auto synchroniser added using the elastique~ object in max
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Mon, 06 Feb 2012 12:18:40 +0000 |
parents | 780def3a1f36 |
children | c96b18dd0f48 |
comparison
equal
deleted
inserted
replaced
15:780def3a1f36 | 16:680ba08e9925 |
---|---|
13 const int matchWindowWidth = 6000; | 13 const int matchWindowWidth = 6000; |
14 | 14 |
15 AudioEventMatcher::AudioEventMatcher(){ | 15 AudioEventMatcher::AudioEventMatcher(){ |
16 | 16 |
17 | 17 |
18 pitchLikelihoodToNoise = 0.4;//more noise | 18 pitchLikelihoodToNoise = 0.9;//more noise |
19 onsetLikelihoodToNoise = 0.3; | 19 |
20 onsetLikelihoodToNoise = 0.4; | |
20 onsetLikelihoodWidth = 20;//in ms | 21 onsetLikelihoodWidth = 20;//in ms |
21 | 22 |
22 setArraySizes(); | 23 setArraySizes(); |
23 | 24 |
24 usingRealTime = false; | 25 usingRealTime = false; |
52 bayesianStruct.relativeSpeedPrior.getMaximum(); | 53 bayesianStruct.relativeSpeedPrior.getMaximum(); |
53 | 54 |
54 bayesianStruct.resetSize(matchWindowWidth); | 55 bayesianStruct.resetSize(matchWindowWidth); |
55 bayesianStruct.setPositionDistributionScalar(1); | 56 bayesianStruct.setPositionDistributionScalar(1); |
56 | 57 |
58 } | |
59 | |
60 void AudioEventMatcher::loadAudioFiles(){ | |
61 recordedTracks.loadTestAudio(); | |
62 synchroniser.fileLengthSamples = recordedTracks.loadedAudioFiles[0].fileLoader.totalNumberOfSamples; | |
63 printf("synchroniser has %f samples\n", synchroniser.fileLengthSamples); | |
57 } | 64 } |
58 | 65 |
59 void AudioEventMatcher::startPlaying(){ | 66 void AudioEventMatcher::startPlaying(){ |
60 bayesianStruct.setStartPlaying(); | 67 bayesianStruct.setStartPlaying(); |
61 currentAlignmentPosition = 0; | 68 currentAlignmentPosition = 0; |
90 // double speedtmp = bayesianStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesianStruct.relativeSpeedPosterior.MAPestimate); | 97 // double speedtmp = bayesianStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesianStruct.relativeSpeedPosterior.MAPestimate); |
91 // currentAlignmentTime = newTime; | 98 // currentAlignmentTime = newTime; |
92 currentAlignmentPosition = bayesianStruct.posterior.getIndexInRealTerms(bayesianStruct.posterior.MAPestimate); | 99 currentAlignmentPosition = bayesianStruct.posterior.getIndexInRealTerms(bayesianStruct.posterior.MAPestimate); |
93 currentAlignmentPosition += (newTime - lastAlignmentTime) * bayesianStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesianStruct.relativeSpeedPosterior.MAPestimate); | 100 currentAlignmentPosition += (newTime - lastAlignmentTime) * bayesianStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesianStruct.relativeSpeedPosterior.MAPestimate); |
94 | 101 |
102 | |
103 synchroniser.updateRecordedPosition(currentAlignmentPosition); | |
104 | |
105 synchroniser.updateOutputSpeed(); | |
106 | |
95 bayesianStruct.projectDistribution(newTime, currentAlignmentPosition, projectedPrior);//prior gets updated to where we are now | 107 bayesianStruct.projectDistribution(newTime, currentAlignmentPosition, projectedPrior);//prior gets updated to where we are now |
96 | 108 |
97 // printf("ALIGN pos %f time diff %f (now %f , last %f)speed %f :: ALIGN BEST %f\n", tmp, timetmp, (double)ofGetElapsedTimeMillis(), lastAlignmentTime, speedtmp, currentAlignmentPosition); | 109 // printf("ALIGN pos %f time diff %f (now %f , last %f)speed %f :: ALIGN BEST %f\n", tmp, timetmp, (double)ofGetElapsedTimeMillis(), lastAlignmentTime, speedtmp, currentAlignmentPosition); |
98 } | 110 } |
99 | 111 |
115 //bayesianStruct.posterior.drawVector(0, bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); | 127 //bayesianStruct.posterior.drawVector(0, bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); |
116 //bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); | 128 //bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); |
117 //bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow); | 129 //bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow); |
118 | 130 |
119 ofDrawBitmapString("pitch "+ofToString(recentPitch, 2)+", Time "+ofToString(recentTime, 0), 20, 20); | 131 ofDrawBitmapString("pitch "+ofToString(recentPitch, 2)+", Time "+ofToString(recentTime, 0), 20, 20); |
132 | |
133 string alignString = " align "+ofToString(currentAlignmentPosition, 2); | |
134 alignString += " playing "+ofToString(synchroniser.playingPositionRatio, 5); | |
135 alignString += " "+ofToString(synchroniser.playingPositionMillis)+" ms"; | |
136 ofDrawBitmapString(alignString, 20, 50); | |
120 | 137 |
121 ofDrawBitmapString("pos "+ofToString(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.playPosition), 200,600); | 138 ofDrawBitmapString("pos "+ofToString(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.playPosition), 200,600); |
122 } | 139 } |
123 | 140 |
124 void AudioEventMatcher::setScreenDisplayTimes(){ | 141 void AudioEventMatcher::setScreenDisplayTimes(){ |
164 | 181 |
165 //green line at current best estimate | 182 //green line at current best estimate |
166 ofSetColor(0,255,0);//green scrolling line best position | 183 ofSetColor(0,255,0);//green scrolling line best position |
167 double currentEstimateIndex = (currentAlignmentPosition - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis; | 184 double currentEstimateIndex = (currentAlignmentPosition - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis; |
168 ofLine(currentEstimateIndex, bayesPositionWindow.y, currentEstimateIndex, bayesPositionWindow.y + bayesPositionWindow.height); | 185 ofLine(currentEstimateIndex, bayesPositionWindow.y, currentEstimateIndex, bayesPositionWindow.y + bayesPositionWindow.height); |
186 | |
187 | |
188 ofSetColor(0,255,255);//synchroniser position | |
189 currentEstimateIndex = (synchroniser.playingPositionMillis - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis; | |
190 ofLine(currentEstimateIndex, bayesLikelihoodWindow.y, currentEstimateIndex, bayesLikelihoodWindow.y + bayesPositionWindow.height); | |
191 | |
192 | |
169 | 193 |
170 //draw track by track likelihoods | 194 //draw track by track likelihoods |
171 for (int i = 0; i <recordedTracks.numberOfAudioTracks;i++){ | 195 for (int i = 0; i <recordedTracks.numberOfAudioTracks;i++){ |
172 ofSetColor(200,255,50);//channel likelihoods in yellow | 196 ofSetColor(200,255,50);//channel likelihoods in yellow |
173 likelihoodVisualisation[i].drawConstrainedVector(likelihoodVisualisation[i].getRealTermsAsIndex(screenStartTimeMillis), likelihoodVisualisation[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window); | 197 likelihoodVisualisation[i].drawConstrainedVector(likelihoodVisualisation[i].getRealTermsAsIndex(screenStartTimeMillis), likelihoodVisualisation[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window); |
300 double quantity = 0; | 324 double quantity = 0; |
301 if (channel <= recordedTracks.numberOfAudioTracks){ | 325 if (channel <= recordedTracks.numberOfAudioTracks){ |
302 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ | 326 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ |
303 | 327 |
304 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { | 328 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { |
305 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 10); | 329 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 16); |
306 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity); | 330 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity); |
307 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; | 331 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; |
308 numberOfMatches++; | 332 numberOfMatches++; |
309 } | 333 } |
310 else{ | 334 else{ |
335 | 359 |
336 } | 360 } |
337 | 361 |
338 double AudioEventMatcher::getPitchDistance(const double& pitchOne, const double& pitchTwo, const double& scale){ | 362 double AudioEventMatcher::getPitchDistance(const double& pitchOne, const double& pitchTwo, const double& scale){ |
339 | 363 |
364 double scaleFactor = scale ;//* pitchOne / 110.0; | |
365 | |
366 | |
340 double distance = abs(pitchOne - pitchTwo); | 367 double distance = abs(pitchOne - pitchTwo); |
341 if (distance < scale) | 368 if (distance < scaleFactor) |
342 distance = 1 - (distance/scale); | 369 distance = 1 - (distance/scaleFactor); |
343 else | 370 else |
344 distance = 0; | 371 distance = 0; |
345 | 372 |
346 // printf("[pitch distance %f vs %f = %f\n", pitchOne, pitchTwo, distance); | 373 // printf("[pitch distance %f vs %f = %f\n", pitchOne, pitchTwo, distance); |
347 return distance; | 374 return distance; |
348 | 375 |
349 } | 376 } |
350 | 377 |
351 | 378 |
352 bool AudioEventMatcher::checkMatch(const double& recordedPitch, const double& livePitch){ | 379 bool AudioEventMatcher::checkMatch(const double& recordedPitch, const double& livePitch){ |
353 if (abs(recordedPitch - livePitch) < 40) | 380 if (abs(recordedPitch - livePitch) < 16) |
354 return true; | 381 return true; |
355 else | 382 else |
356 return false; | 383 return false; |
357 } | 384 } |
358 | 385 |