comparison src/AudioEventMatcher.cpp @ 20:4f6006cac9de

added evaluation of recorded tempo, holding of this data, drawing of recorded and playing tempo estimates
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Sun, 12 Feb 2012 00:48:07 +0000
parents 1a62561bd72d
children 604add81822f
comparison
equal deleted inserted replaced
19:1a62561bd72d 20:4f6006cac9de
29 29
30 30
31 31
32 followingLiveInput = true; 32 followingLiveInput = true;
33 startedPlaying = false; 33 startedPlaying = false;
34 34 recordedTempoIndex = 0;
35 temporal.setUpEventTimeMatrix(); 35 // temporal.setUpEventTimeMatrix();
36 // recordedTempoData.setUpEventTimeMatrix();
36 } 37 }
37 38
38 39
39 40
40 41
63 64
64 void AudioEventMatcher::loadAudioFiles(){ 65 void AudioEventMatcher::loadAudioFiles(){
65 recordedTracks.loadTestAudio(); 66 recordedTracks.loadTestAudio();
66 synchroniser.fileLengthSamples = recordedTracks.loadedAudioFiles[0].fileLoader.totalNumberOfSamples; 67 synchroniser.fileLengthSamples = recordedTracks.loadedAudioFiles[0].fileLoader.totalNumberOfSamples;
67 printf("synchroniser has %f samples\n", synchroniser.fileLengthSamples); 68 printf("synchroniser has %f samples\n", synchroniser.fileLengthSamples);
69
70 calculateRecordedTempoData();
71 printf("\n\nFIRST PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
72 setTempoPrior(recordedTempoData.playingTempo);
73 calculateRecordedTempoData();//now calculate again using better prior
74
75 printf("\n\nSECOND PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
76 printf("GLOBAL TEMPO of RECORDED FILES\n");
77 recordedTempoData.printTempoTimes();
78 }
79
80 void AudioEventMatcher::setTempoPrior(double tempo){
81 recordedTempoData.zero();
82 recordedTempoData.tempoPosterior.zero();
83 recordedTempoData.tempoPosterior.addGaussianShapeFromRealTime(tempo, 3, 1);
84
85 }
86
87 void AudioEventMatcher::calculateRecordedTempoData(){
88 int indexForOnsets[3];
89 indexForOnsets[0] = 0;
90 indexForOnsets[1] = 0;
91 indexForOnsets[2] = 0;
92 int kickTime, snareTime;
93 while (indexForOnsets[0] < recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.chromaOnsets.size() ||
94 indexForOnsets[2] < recordedTracks.loadedAudioFiles[2].fileLoader.onsetDetect.chromaOnsets.size()) {
95
96 setNextOnsetTime(0, kickTime, &indexForOnsets[0]);
97 setNextOnsetTime(2, snareTime, &indexForOnsets[0]);
98
99 if (kickTime < snareTime){
100 printf("update kick at %i\n", kickTime);
101 recordedTempoData.updateTempo(0, kickTime);
102 printf("recorded tempo is %f\n", recordedTempoData.playingTempo);
103 indexForOnsets[0]++;
104 }else {
105 printf("update snare at %i\n", snareTime);
106 recordedTempoData.updateTempo(2, snareTime);
107 printf("recorded tempo is %f\n", recordedTempoData.playingTempo);
108 indexForOnsets[2]++;
109 }
110 }//end while
111
112
113 }
114
115 void AudioEventMatcher::setNextOnsetTime(const int& channel, int& time, int* indexForOnsets){
116 if (indexForOnsets[channel] < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size()){
117 time = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[indexForOnsets[channel]].millisTime;
118 }
119 else {
120 time = 2147483647;//infinity
121 }
68 } 122 }
69 123
70 void AudioEventMatcher::startPlaying(){ 124 void AudioEventMatcher::startPlaying(){
71 bayesianStruct.setStartPlaying(); 125 bayesianStruct.setStartPlaying();
72 currentAlignmentPosition = 0; 126 currentAlignmentPosition = 0;
75 projectedPrior = bayesianStruct.prior; 129 projectedPrior = bayesianStruct.prior;
76 startedPlaying = true; 130 startedPlaying = true;
77 synchroniser.reset(); 131 synchroniser.reset();
78 temporal.reset(); 132 temporal.reset();
79 133
134 recordedTempoIndex = 0;
135 recordedTempo = recordedTempoData.globalTempo[recordedTempoIndex];
136
137 currentSpeedRatio = 1;
138
139 //SET TEMPO PRIOR for Speed Ratio
140 //the update this
141 setSpeedRatioDistribution(currentSpeedRatio);
80 //bayesianStruct.posterior.printArray(); 142 //bayesianStruct.posterior.printArray();
81 } 143 }
82 144
145
146 void AudioEventMatcher::setSpeedRatioDistribution(const double& speedRatio){
147 bayesianStruct.relativeSpeedPosterior.zero();
148 bayesianStruct.relativeSpeedPosterior.addToIndex(bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(speedRatio), 1);
149 bayesianStruct.relativeSpeedPosterior.addGaussianShapeFromRealTime(1, 0.06, 0.5);
150 }
83 151
84 void AudioEventMatcher::stopPlaying(){ 152 void AudioEventMatcher::stopPlaying(){
85 startedPlaying = false; 153 startedPlaying = false;
86 temporal.printEventTimes(); 154 temporal.printEventTimes();
87 } 155 }
92 if (!followingLiveInput) 160 if (!followingLiveInput)
93 recordedTracks.updatePosition(); 161 recordedTracks.updatePosition();
94 else 162 else
95 recordedTracks.updatePositionToMillis(currentAlignmentPosition); 163 recordedTracks.updatePositionToMillis(currentAlignmentPosition);
96 164
97 updateBestAlignmentPosition(); 165 updateBestAlignmentPosition();
98 } 166 }
167
168 updateRecordedTempo();
99 169
100 temporal.tempoPosterior.addGaussianShape(temporal.tempoPosterior.MAPestimate, temporal.tempoArraySize / 4, 0.5 ); 170 temporal.tempoPosterior.addGaussianShape(temporal.tempoPosterior.MAPestimate, temporal.tempoArraySize / 4, 0.5 );
171 }
172
173 void AudioEventMatcher::updateRecordedTempo(){
174 //tempo of equivalent recorded position is updated
175 while(currentAlignmentPosition > recordedTempoData.globalTempoTimes[recordedTempoIndex]){
176 recordedTempoIndex++;
177 }
178 recordedTempo = recordedTempoData.globalTempo[recordedTempoIndex];
179 double tmpRatio = currentSpeedRatio;
180 currentSpeedRatio = temporal.playingTempo / recordedTempo;
181 if (currentSpeedRatio != tmpRatio)
182 setSpeedRatioDistribution(currentSpeedRatio);
101 } 183 }
102 184
103 void AudioEventMatcher::updateBestAlignmentPosition(){ 185 void AudioEventMatcher::updateBestAlignmentPosition(){
104 //THIS DEALS WITH WHERE WE ARE NOW! ON THE SCREEN 186 //THIS DEALS WITH WHERE WE ARE NOW! ON THE SCREEN
105 //DIFFERENT TO WHEN EVENTS COME IN AS THEY ARE TIMESTAMPED - SO EG A PITCH EVENT MAY ARRIVE 16 CHROMA FRAMES LATER - BIG DIFFERENCE 187 //DIFFERENT TO WHEN EVENTS COME IN AS THEY ARE TIMESTAMPED - SO EG A PITCH EVENT MAY ARRIVE 16 CHROMA FRAMES LATER - BIG DIFFERENCE
153 alignString += " pos "+ofToString(synchroniser.playingPositionMillis,0)+" ms"; 235 alignString += " pos "+ofToString(synchroniser.playingPositionMillis,0)+" ms";
154 alignString += " rec pos "+ofToString(synchroniser.recordedPositionMillis,0)+" ms"; 236 alignString += " rec pos "+ofToString(synchroniser.recordedPositionMillis,0)+" ms";
155 ofDrawBitmapString(alignString, 20, 50); 237 ofDrawBitmapString(alignString, 20, 50);
156 238
157 ofDrawBitmapString("pos "+ofToString(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.playPosition), 200,600); 239 ofDrawBitmapString("pos "+ofToString(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.playPosition), 200,600);
158 } 240
159 241 temporal.drawTempoArray(bayesLikelihoodWindow);
242
243 drawRecordedTempo();
244 drawPlayingTempo();
245
246
247 }
248
249 void AudioEventMatcher::drawRecordedTempo(){
250
251 int xTempoIndex = ofGetWidth() * (recordedTempo - recordedTempoData.minimumTempoInterval)/(recordedTempoData.maximumTempoInterval - recordedTempoData.minimumTempoInterval);
252 ofSetColor(0, 200, 0);
253 ofLine(xTempoIndex, bayesLikelihoodWindow.y, xTempoIndex, bayesLikelihoodWindow.y + bayesLikelihoodWindow.height);
254 ofDrawBitmapString(ofToString(recordedTempo), xTempoIndex, bayesLikelihoodWindow.y + 10);
255 }
256
257 void AudioEventMatcher::drawPlayingTempo(){
258
259 int xTempoIndex = ofGetWidth() * (temporal.playingTempo - temporal.minimumTempoInterval)/(temporal.maximumTempoInterval - temporal.minimumTempoInterval);
260 ofSetColor(200, 0, 200);
261 ofLine(xTempoIndex, bayesLikelihoodWindow.y, xTempoIndex, bayesLikelihoodWindow.y + bayesLikelihoodWindow.height);
262 ofDrawBitmapString(ofToString(recordedTempo), xTempoIndex, bayesLikelihoodWindow.y + 10);
263
264 int xSpeedRatioIndex = (double)(temporal.tempoPosterior.getIndexInRealTerms(currentSpeedRatio)*ofGetWidth())/(double)temporal.tempoPosterior.arraySize;
265 ofSetColor(200,0,0);
266 ofLine(xSpeedRatioIndex, bayesTempoWindow.y, xSpeedRatioIndex, bayesTempoWindow.y + bayesTempoWindow.height);
267 ofDrawBitmapString(ofToString(currentSpeedRatio), 100, bayesTempoWindow.y+50);
268
269 }
270
271
160 void AudioEventMatcher::setScreenDisplayTimes(){ 272 void AudioEventMatcher::setScreenDisplayTimes(){
161 screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber); 273 screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber);
162 // if (!followingLiveInput){ 274 // if (!followingLiveInput){
163 275
164 screenStartTimeMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.drawParams.windowStartFrame); 276 screenStartTimeMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.drawParams.windowStartFrame);
232 bayesianStruct.prior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow); 344 bayesianStruct.prior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow);
233 345
234 ofSetColor(255,0,0); 346 ofSetColor(255,0,0);
235 projectedPrior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow); 347 projectedPrior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow);
236 348
237 temporal.drawTempoArray(bayesLikelihoodWindow); 349
238 350
239 } 351 }
240 352
241 void AudioEventMatcher::newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){ 353 void AudioEventMatcher::newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){
242 if (pitchIn > 0){ 354 if (pitchIn > 0){