andrew@0
|
1 /*
|
andrew@0
|
2 * AudioEventMatcher.cpp
|
andrew@0
|
3 * MultipleAudioMathcher
|
andrew@0
|
4 *
|
andrew@0
|
5 * Created by Andrew on 31/01/2012.
|
andrew@0
|
6 * Copyright 2012 QMUL. All rights reserved.
|
andrew@0
|
7 *
|
andrew@0
|
8 */
|
andrew@0
|
9
|
andrew@0
|
10 #include "AudioEventMatcher.h"
|
andrew@0
|
11
|
andrew@0
|
12
|
andrew@2
|
13 const int matchWindowWidth = 6000;
|
andrew@32
|
14 const float pitchCutOff = 16;//within which pitches are even considered
|
andrew@0
|
15
|
andrew@0
|
16 AudioEventMatcher::AudioEventMatcher(){
|
andrew@7
|
17
|
andrew@35
|
18 useChromaDotProduct = false;
|
andrew@15
|
19
|
andrew@23
|
20 pitchLikelihoodToNoise = 0.6;//more noise
|
andrew@32
|
21 chromaLikelihoodToNoise = 0.5;//lower => more noise, higher more weight for events
|
andrew@32
|
22 chromaLikelihoodWidth = 50;//ms round onset event
|
andrew@16
|
23
|
andrew@23
|
24 onsetLikelihoodToNoise = 0.4;
|
andrew@17
|
25 onsetLikelihoodWidth = 10;//in ms
|
andrew@15
|
26
|
andrew@0
|
27 setArraySizes();
|
andrew@3
|
28
|
andrew@3
|
29 usingRealTime = false;
|
andrew@3
|
30 bayesianStruct.realTimeMode = &usingRealTime;
|
andrew@7
|
31 recentPitch = 0;
|
andrew@8
|
32 currentAlignmentPosition = 0;
|
andrew@14
|
33
|
andrew@9
|
34 followingLiveInput = true;
|
andrew@15
|
35 startedPlaying = false;
|
andrew@20
|
36 recordedTempoIndex = 0;
|
andrew@20
|
37 // temporal.setUpEventTimeMatrix();
|
andrew@20
|
38 // recordedTempoData.setUpEventTimeMatrix();
|
andrew@0
|
39 }
|
andrew@0
|
40
|
andrew@14
|
41
|
andrew@19
|
42
|
andrew@19
|
43
|
andrew@7
|
44 void AudioEventMatcher::setWindowDimensions(){
|
andrew@7
|
45 double startHeight = recordedTracks.numberOfAudioTracks * recordedTracks.trackScreenHeight;
|
andrew@7
|
46 double heightAvailable = 1 - startHeight;
|
andrew@32
|
47 heightAvailable /= numberOfChannels;
|
andrew@7
|
48
|
andrew@7
|
49 bayesPositionWindow.setToRelativeSize(0, startHeight, 1, heightAvailable);
|
andrew@7
|
50 bayesLikelihoodWindow.setToRelativeSize(0, startHeight + 1*heightAvailable, 1, heightAvailable);
|
andrew@7
|
51 bayesTempoWindow.setToRelativeSize(0, startHeight + 2*heightAvailable, 1, heightAvailable);
|
andrew@7
|
52
|
andrew@7
|
53
|
andrew@7
|
54 }
|
andrew@0
|
55
|
andrew@0
|
56 void AudioEventMatcher::setArraySizes(){
|
andrew@0
|
57 bayesianStruct.resetSpeedSize(200);
|
andrew@0
|
58 bayesianStruct.setRelativeSpeedScalar(0.01);
|
andrew@0
|
59 bayesianStruct.setSpeedPrior(1.0);
|
andrew@0
|
60 bayesianStruct.relativeSpeedPrior.getMaximum();
|
andrew@0
|
61
|
andrew@0
|
62 bayesianStruct.resetSize(matchWindowWidth);
|
andrew@0
|
63 bayesianStruct.setPositionDistributionScalar(1);
|
andrew@0
|
64
|
andrew@0
|
65 }
|
andrew@0
|
66
|
andrew@16
|
67 void AudioEventMatcher::loadAudioFiles(){
|
andrew@16
|
68 recordedTracks.loadTestAudio();
|
andrew@16
|
69 synchroniser.fileLengthSamples = recordedTracks.loadedAudioFiles[0].fileLoader.totalNumberOfSamples;
|
andrew@16
|
70 printf("synchroniser has %f samples\n", synchroniser.fileLengthSamples);
|
andrew@20
|
71
|
andrew@20
|
72 calculateRecordedTempoData();
|
andrew@20
|
73 printf("\n\nFIRST PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
|
andrew@20
|
74 setTempoPrior(recordedTempoData.playingTempo);
|
andrew@20
|
75 calculateRecordedTempoData();//now calculate again using better prior
|
andrew@20
|
76
|
andrew@20
|
77 printf("\n\nSECOND PASS: FINAL recorded tempo is %f\n", recordedTempoData.playingTempo);
|
andrew@20
|
78 printf("GLOBAL TEMPO of RECORDED FILES\n");
|
andrew@20
|
79 recordedTempoData.printTempoTimes();
|
andrew@20
|
80 }
|
andrew@20
|
81
|
andrew@20
|
82 void AudioEventMatcher::setTempoPrior(double tempo){
|
andrew@20
|
83 recordedTempoData.zero();
|
andrew@20
|
84 recordedTempoData.tempoPosterior.zero();
|
andrew@20
|
85 recordedTempoData.tempoPosterior.addGaussianShapeFromRealTime(tempo, 3, 1);
|
andrew@20
|
86
|
andrew@20
|
87 }
|
andrew@20
|
88
|
andrew@20
|
89 void AudioEventMatcher::calculateRecordedTempoData(){
|
andrew@20
|
90 int indexForOnsets[3];
|
andrew@20
|
91 indexForOnsets[0] = 0;
|
andrew@20
|
92 indexForOnsets[1] = 0;
|
andrew@20
|
93 indexForOnsets[2] = 0;
|
andrew@20
|
94 int kickTime, snareTime;
|
andrew@20
|
95 while (indexForOnsets[0] < recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.chromaOnsets.size() ||
|
andrew@20
|
96 indexForOnsets[2] < recordedTracks.loadedAudioFiles[2].fileLoader.onsetDetect.chromaOnsets.size()) {
|
andrew@20
|
97
|
andrew@20
|
98 setNextOnsetTime(0, kickTime, &indexForOnsets[0]);
|
andrew@20
|
99 setNextOnsetTime(2, snareTime, &indexForOnsets[0]);
|
andrew@20
|
100
|
andrew@20
|
101 if (kickTime < snareTime){
|
andrew@20
|
102 printf("update kick at %i\n", kickTime);
|
andrew@20
|
103 recordedTempoData.updateTempo(0, kickTime);
|
andrew@20
|
104 printf("recorded tempo is %f\n", recordedTempoData.playingTempo);
|
andrew@20
|
105 indexForOnsets[0]++;
|
andrew@20
|
106 }else {
|
andrew@20
|
107 printf("update snare at %i\n", snareTime);
|
andrew@20
|
108 recordedTempoData.updateTempo(2, snareTime);
|
andrew@20
|
109 printf("recorded tempo is %f\n", recordedTempoData.playingTempo);
|
andrew@20
|
110 indexForOnsets[2]++;
|
andrew@20
|
111 }
|
andrew@20
|
112 }//end while
|
andrew@20
|
113
|
andrew@20
|
114
|
andrew@20
|
115 }
|
andrew@20
|
116
|
andrew@20
|
117 void AudioEventMatcher::setNextOnsetTime(const int& channel, int& time, int* indexForOnsets){
|
andrew@20
|
118 if (indexForOnsets[channel] < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size()){
|
andrew@20
|
119 time = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[indexForOnsets[channel]].millisTime;
|
andrew@20
|
120 }
|
andrew@20
|
121 else {
|
andrew@20
|
122 time = 2147483647;//infinity
|
andrew@20
|
123 }
|
andrew@16
|
124 }
|
andrew@16
|
125
|
andrew@9
|
126 void AudioEventMatcher::startPlaying(){
|
andrew@3
|
127 bayesianStruct.setStartPlaying();
|
andrew@8
|
128 currentAlignmentPosition = 0;
|
andrew@8
|
129 startTime = ofGetElapsedTimeMillis();
|
andrew@11
|
130
|
andrew@11
|
131 projectedPrior = bayesianStruct.prior;
|
andrew@15
|
132 startedPlaying = true;
|
andrew@17
|
133 synchroniser.reset();
|
andrew@19
|
134 temporal.reset();
|
andrew@17
|
135
|
andrew@20
|
136 recordedTempoIndex = 0;
|
andrew@20
|
137 recordedTempo = recordedTempoData.globalTempo[recordedTempoIndex];
|
andrew@20
|
138
|
andrew@20
|
139 currentSpeedRatio = 1;
|
andrew@20
|
140
|
andrew@21
|
141 temporal.tempoPosterior.zero();
|
andrew@21
|
142 temporal.tempoPosterior.addGaussianShapeFromRealTime(recordedTempo, 10, 1);
|
andrew@21
|
143
|
andrew@20
|
144 //SET TEMPO PRIOR for Speed Ratio
|
andrew@20
|
145 //the update this
|
andrew@20
|
146 setSpeedRatioDistribution(currentSpeedRatio);
|
andrew@3
|
147 //bayesianStruct.posterior.printArray();
|
andrew@3
|
148 }
|
andrew@3
|
149
|
andrew@9
|
150
|
andrew@20
|
151 void AudioEventMatcher::setSpeedRatioDistribution(const double& speedRatio){
|
andrew@20
|
152 bayesianStruct.relativeSpeedPosterior.zero();
|
andrew@20
|
153 bayesianStruct.relativeSpeedPosterior.addToIndex(bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(speedRatio), 1);
|
andrew@22
|
154 bayesianStruct.relativeSpeedPosterior.addGaussianShapeFromRealTime(1, 0.06, 0.8);
|
andrew@20
|
155 }
|
andrew@20
|
156
|
andrew@15
|
157 void AudioEventMatcher::stopPlaying(){
|
andrew@15
|
158 startedPlaying = false;
|
andrew@19
|
159 temporal.printEventTimes();
|
andrew@15
|
160 }
|
andrew@15
|
161
|
andrew@22
|
162 void AudioEventMatcher::rescue(){
|
andrew@22
|
163 bayesianStruct.posterior.zero();
|
andrew@22
|
164 bayesianStruct.posterior.addConstant(1);
|
andrew@22
|
165 bayesianStruct.prior.zero();
|
andrew@22
|
166 bayesianStruct.prior.addConstant(1);
|
andrew@22
|
167 }
|
andrew@22
|
168
|
andrew@9
|
169 void AudioEventMatcher::updatePosition(){
|
andrew@19
|
170
|
andrew@19
|
171 if (startedPlaying){
|
andrew@9
|
172 if (!followingLiveInput)
|
andrew@9
|
173 recordedTracks.updatePosition();
|
andrew@19
|
174 else
|
andrew@9
|
175 recordedTracks.updatePositionToMillis(currentAlignmentPosition);
|
andrew@9
|
176
|
andrew@20
|
177 updateBestAlignmentPosition();
|
andrew@19
|
178 }
|
andrew@19
|
179
|
andrew@20
|
180 updateRecordedTempo();
|
andrew@20
|
181
|
andrew@19
|
182 temporal.tempoPosterior.addGaussianShape(temporal.tempoPosterior.MAPestimate, temporal.tempoArraySize / 4, 0.5 );
|
andrew@9
|
183 }
|
andrew@9
|
184
|
andrew@20
|
185 void AudioEventMatcher::updateRecordedTempo(){
|
andrew@20
|
186 //tempo of equivalent recorded position is updated
|
andrew@20
|
187 while(currentAlignmentPosition > recordedTempoData.globalTempoTimes[recordedTempoIndex]){
|
andrew@20
|
188 recordedTempoIndex++;
|
andrew@20
|
189 }
|
andrew@20
|
190 recordedTempo = recordedTempoData.globalTempo[recordedTempoIndex];
|
andrew@20
|
191 double tmpRatio = currentSpeedRatio;
|
andrew@20
|
192 currentSpeedRatio = temporal.playingTempo / recordedTempo;
|
andrew@20
|
193 if (currentSpeedRatio != tmpRatio)
|
andrew@20
|
194 setSpeedRatioDistribution(currentSpeedRatio);
|
andrew@20
|
195 }
|
andrew@20
|
196
|
andrew@8
|
197 void AudioEventMatcher::updateBestAlignmentPosition(){
|
andrew@10
|
198 //THIS DEALS WITH WHERE WE ARE NOW! ON THE SCREEN
|
andrew@10
|
199 //DIFFERENT TO WHEN EVENTS COME IN AS THEY ARE TIMESTAMPED - SO EG A PITCH EVENT MAY ARRIVE 16 CHROMA FRAMES LATER - BIG DIFFERENCE
|
andrew@10
|
200
|
andrew@10
|
201 int newTime = ofGetElapsedTimeMillis() - startTime;
|
andrew@10
|
202 // double tmp = bayesianStruct.posterior.getIndexInRealTerms(bayesianStruct.posterior.MAPestimate);;
|
andrew@10
|
203 // double timetmp = (newTime - lastAlignmentTime);
|
andrew@10
|
204 // double speedtmp = bayesianStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesianStruct.relativeSpeedPosterior.MAPestimate);
|
andrew@11
|
205 // currentAlignmentTime = newTime;
|
andrew@9
|
206 currentAlignmentPosition = bayesianStruct.posterior.getIndexInRealTerms(bayesianStruct.posterior.MAPestimate);
|
andrew@10
|
207 currentAlignmentPosition += (newTime - lastAlignmentTime) * bayesianStruct.relativeSpeedPosterior.getIndexInRealTerms(bayesianStruct.relativeSpeedPosterior.MAPestimate);
|
andrew@10
|
208
|
andrew@16
|
209
|
andrew@17
|
210 synchroniser.updateRecordedPosition(currentAlignmentPosition, newTime);
|
andrew@16
|
211
|
andrew@16
|
212 synchroniser.updateOutputSpeed();
|
andrew@16
|
213
|
andrew@11
|
214 bayesianStruct.projectDistribution(newTime, currentAlignmentPosition, projectedPrior);//prior gets updated to where we are now
|
andrew@32
|
215
|
andrew@32
|
216 // printf("updateBestAlignment:: alignment %i:: %i\n", newTime, (int) currentAlignmentPosition);
|
andrew@11
|
217
|
andrew@10
|
218 // printf("ALIGN pos %f time diff %f (now %f , last %f)speed %f :: ALIGN BEST %f\n", tmp, timetmp, (double)ofGetElapsedTimeMillis(), lastAlignmentTime, speedtmp, currentAlignmentPosition);
|
andrew@8
|
219 }
|
andrew@8
|
220
|
andrew@0
|
221 void AudioEventMatcher::draw(){
|
andrew@32
|
222
|
andrew@32
|
223 //MAIN DRAW FUNCTION FOR ALL
|
andrew@32
|
224
|
andrew@6
|
225 //draw some outlines in blue
|
andrew@3
|
226 ofSetColor(20,200,200);
|
andrew@3
|
227 bayesPositionWindow.drawOutline();
|
andrew@3
|
228 bayesTempoWindow.drawOutline();
|
andrew@0
|
229
|
andrew@6
|
230 //draw the scrolling audio tracks
|
andrew@1
|
231 recordedTracks.drawTracks();
|
andrew@7
|
232
|
andrew@2
|
233 ofSetColor(255);
|
andrew@2
|
234 // bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow);
|
andrew@9
|
235
|
andrew@9
|
236 setScreenDisplayTimes();
|
andrew@6
|
237 drawBayesianDistributions();
|
andrew@8
|
238
|
andrew@11
|
239 //bayesianStruct.posterior.drawVector(0, bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow);
|
andrew@6
|
240 //bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow);
|
andrew@11
|
241 //bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow);
|
andrew@9
|
242
|
andrew@20
|
243 temporal.drawTempoArray(bayesLikelihoodWindow);
|
andrew@20
|
244
|
andrew@20
|
245 drawRecordedTempo();
|
andrew@20
|
246 drawPlayingTempo();
|
andrew@20
|
247
|
andrew@20
|
248
|
andrew@6
|
249 }
|
andrew@20
|
250
|
andrew@20
|
251 void AudioEventMatcher::drawRecordedTempo(){
|
andrew@6
|
252
|
andrew@21
|
253 int xTempoIndex = ofGetWidth() * (double)(recordedTempo - recordedTempoData.minimumTempoInterval)/(double)(recordedTempoData.maximumTempoInterval - recordedTempoData.minimumTempoInterval);
|
andrew@20
|
254 ofSetColor(0, 200, 0);
|
andrew@20
|
255 ofLine(xTempoIndex, bayesLikelihoodWindow.y, xTempoIndex, bayesLikelihoodWindow.y + bayesLikelihoodWindow.height);
|
andrew@20
|
256 ofDrawBitmapString(ofToString(recordedTempo), xTempoIndex, bayesLikelihoodWindow.y + 10);
|
andrew@20
|
257 }
|
andrew@20
|
258
|
andrew@20
|
259 void AudioEventMatcher::drawPlayingTempo(){
|
andrew@21
|
260 //purple line for MAP estimate of new intervals
|
andrew@21
|
261 int xTempoIndex = (double)(ofGetWidth() * (temporal.playingTempo - temporal.minimumTempoInterval))/(double)(temporal.maximumTempoInterval - temporal.minimumTempoInterval);
|
andrew@20
|
262 ofSetColor(200, 0, 200);
|
andrew@20
|
263 ofLine(xTempoIndex, bayesLikelihoodWindow.y, xTempoIndex, bayesLikelihoodWindow.y + bayesLikelihoodWindow.height);
|
andrew@21
|
264 ofDrawBitmapString(ofToString(temporal.playingTempo), xTempoIndex, bayesLikelihoodWindow.y + 10);
|
andrew@20
|
265
|
andrew@21
|
266 //red line where the ratio is between playing tempo and recorded one
|
andrew@20
|
267 int xSpeedRatioIndex = (double)(temporal.tempoPosterior.getIndexInRealTerms(currentSpeedRatio)*ofGetWidth())/(double)temporal.tempoPosterior.arraySize;
|
andrew@20
|
268 ofSetColor(200,0,0);
|
andrew@20
|
269 ofLine(xSpeedRatioIndex, bayesTempoWindow.y, xSpeedRatioIndex, bayesTempoWindow.y + bayesTempoWindow.height);
|
andrew@21
|
270 string tmpString = "playing "+ofToString(temporal.playingTempo);
|
andrew@21
|
271 tmpString += ", recorded "+ofToString(recordedTempo);
|
andrew@21
|
272 tmpString += " ratio "+ofToString(currentSpeedRatio);
|
andrew@21
|
273 ofSetColor(155,155,155);
|
andrew@21
|
274 ofDrawBitmapString(tmpString, 20, bayesTempoWindow.y+10);
|
andrew@20
|
275
|
andrew@20
|
276 }
|
andrew@20
|
277
|
andrew@20
|
278
|
andrew@9
|
279 void AudioEventMatcher::setScreenDisplayTimes(){
|
andrew@9
|
280 screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber);
|
andrew@9
|
281 // if (!followingLiveInput){
|
andrew@9
|
282
|
andrew@9
|
283 screenStartTimeMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.drawParams.windowStartFrame);
|
andrew@9
|
284 screenEndTimeMillis = screenStartTimeMillis + screenWidthMillis;
|
andrew@9
|
285
|
andrew@9
|
286 //need PRECISION in this alignment
|
andrew@9
|
287
|
andrew@9
|
288
|
andrew@9
|
289 /*}else{
|
andrew@9
|
290
|
andrew@9
|
291 screenStartTimeMillis = (int)(currentAlignmentPosition/screenWidthMillis) * screenWidthMillis;
|
andrew@9
|
292 screenEndTimeMillis = screenStartTimeMillis + screenWidthMillis;
|
andrew@9
|
293 }*/
|
andrew@9
|
294 }
|
andrew@9
|
295
|
andrew@6
|
296 void AudioEventMatcher::drawBayesianDistributions(){
|
andrew@6
|
297
|
andrew@32
|
298
|
andrew@32
|
299 drawPositionWindow();
|
andrew@4
|
300
|
andrew@8
|
301 // bayesianStruct.likelihood.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesLikelihoodWindow);
|
andrew@2
|
302
|
andrew@6
|
303 bayesianStruct.relativeSpeedPosterior.drawConstrainedVector(0, bayesianStruct.relativeSpeedPosterior.arraySize, 0, ofGetWidth(), bayesTempoWindow);
|
andrew@32
|
304
|
andrew@6
|
305
|
andrew@32
|
306 drawTrackLikelihoods();
|
andrew@32
|
307
|
andrew@32
|
308 // int priorStartIndex = bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis);
|
andrew@32
|
309 // int priorEndIndex = bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis);
|
andrew@32
|
310 // ofSetColor(0,200,200);//recent prior
|
andrew@32
|
311 // recentPrior.drawConstrainedVector(priorStartIndex, priorEndIndex, 0, ofGetWidth(), bayesPositionWindow);
|
andrew@32
|
312
|
andrew@32
|
313 drawInfo();
|
andrew@32
|
314
|
andrew@3
|
315
|
andrew@32
|
316 }
|
andrew@32
|
317
|
andrew@32
|
318 void AudioEventMatcher::drawPositionWindow(){
|
andrew@32
|
319 int startIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenStartTimeMillis);
|
andrew@32
|
320 int endIndex = bayesianStruct.posterior.getRealTermsAsIndex(screenEndTimeMillis);
|
andrew@32
|
321 string tmpString = "start "+ofToString(screenStartTimeMillis)+" (index "+ofToString(startIndex)+"), end "+ofToString(screenEndTimeMillis);
|
andrew@32
|
322 ofDrawBitmapString(tmpString, bayesPositionWindow.x+20, bayesPositionWindow.y+20);
|
andrew@32
|
323
|
andrew@32
|
324 //draw posterior in the bayes position window
|
andrew@32
|
325 ofSetColor(255,0,255);
|
andrew@32
|
326 bayesianStruct.posterior.drawConstrainedVector(startIndex, endIndex, 0, ofGetWidth(), bayesPositionWindow);
|
andrew@3
|
327
|
andrew@9
|
328 //green line at current best estimate
|
andrew@13
|
329 ofSetColor(0,255,0);//green scrolling line best position
|
andrew@8
|
330 double currentEstimateIndex = (currentAlignmentPosition - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis;
|
andrew@8
|
331 ofLine(currentEstimateIndex, bayesPositionWindow.y, currentEstimateIndex, bayesPositionWindow.y + bayesPositionWindow.height);
|
andrew@7
|
332
|
andrew@32
|
333
|
andrew@16
|
334 ofSetColor(0,255,255);//synchroniser position
|
andrew@16
|
335 currentEstimateIndex = (synchroniser.playingPositionMillis - screenStartTimeMillis)*ofGetWidth()/screenWidthMillis;
|
andrew@16
|
336 ofLine(currentEstimateIndex, bayesLikelihoodWindow.y, currentEstimateIndex, bayesLikelihoodWindow.y + bayesPositionWindow.height);
|
andrew@32
|
337
|
andrew@32
|
338 ofSetColor(255,0,100);//purple prior
|
andrew@32
|
339 bayesianStruct.prior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow);
|
andrew@16
|
340
|
andrew@32
|
341 ofSetColor(255,0,0);//projected prior in red
|
andrew@32
|
342 projectedPrior.drawConstrainedVector(bayesianStruct.prior.getRealTermsAsIndex(screenStartTimeMillis), bayesianStruct.prior.getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), bayesPositionWindow);
|
andrew@16
|
343
|
andrew@16
|
344
|
andrew@32
|
345
|
andrew@32
|
346 }
|
andrew@32
|
347
|
andrew@32
|
348 void AudioEventMatcher::drawTrackLikelihoods(){
|
andrew@7
|
349 //draw track by track likelihoods
|
andrew@7
|
350 for (int i = 0; i <recordedTracks.numberOfAudioTracks;i++){
|
andrew@13
|
351 ofSetColor(200,255,50);//channel likelihoods in yellow
|
andrew@8
|
352 likelihoodVisualisation[i].drawConstrainedVector(likelihoodVisualisation[i].getRealTermsAsIndex(screenStartTimeMillis), likelihoodVisualisation[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window);
|
andrew@11
|
353
|
andrew@13
|
354 ofSetColor(0,255,150);//channel priors
|
andrew@11
|
355 recentPriors[i].drawConstrainedVector(recentPriors[i].getRealTermsAsIndex(screenStartTimeMillis), recentPriors[i].getRealTermsAsIndex(screenEndTimeMillis), 0, ofGetWidth(), recordedTracks.loadedAudioFiles[i].fileLoader.onsetDetect.window);
|
andrew@11
|
356
|
andrew@11
|
357
|
andrew@8
|
358 ofSetColor(255);
|
andrew@8
|
359 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);
|
andrew@7
|
360 }
|
andrew@32
|
361 }
|
andrew@8
|
362
|
andrew@8
|
363
|
andrew@32
|
364 void AudioEventMatcher::drawInfo(){
|
andrew@32
|
365 string tmpStr = "zero is "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(0));
|
andrew@32
|
366 tmpStr += " offsetis "+ofToString(bayesianStruct.posterior.offset);
|
andrew@32
|
367 tmpStr += " screenWidth = "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis));
|
andrew@32
|
368 ofDrawBitmapString(tmpStr, 20,140);
|
andrew@32
|
369 tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate);
|
andrew@32
|
370 ofDrawBitmapString(tmpStr, 20, 180);
|
andrew@32
|
371 ofDrawBitmapString("screenwidth "+ofToString(screenWidthMillis), 20, 800);
|
andrew@11
|
372
|
andrew@32
|
373 ofSetColor(255);
|
andrew@32
|
374 tmpStr = "pitch "+ofToString(recentPitch, 2);
|
andrew@32
|
375 tmpStr += " Nearest "+ofToString(pitchOfNearestMatch,2);
|
andrew@32
|
376 tmpStr += " dist "+ofToString(distanceOfNearestMatch, 2);
|
andrew@32
|
377 tmpStr += ", Time "+ofToString(recentTime, 0);
|
andrew@32
|
378 ofDrawBitmapString(tmpStr, 20, 20);
|
andrew@7
|
379
|
andrew@32
|
380 string alignString = " align "+ofToString(currentAlignmentPosition, 2);
|
andrew@32
|
381 alignString += " playing "+ofToString(synchroniser.playingPositionRatio, 5);
|
andrew@32
|
382 alignString += " pos "+ofToString(synchroniser.playingPositionMillis,0)+" ms";
|
andrew@32
|
383 alignString += " rec pos "+ofToString(synchroniser.recordedPositionMillis,0)+" ms";
|
andrew@32
|
384 ofDrawBitmapString(alignString, 20, 50);
|
andrew@20
|
385
|
andrew@32
|
386 ofDrawBitmapString("pos "+ofToString(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.playPosition), 200,600);
|
andrew@19
|
387
|
andrew@1
|
388 }
|
andrew@1
|
389
|
andrew@6
|
390 void AudioEventMatcher::newPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){
|
andrew@7
|
391 if (pitchIn > 0){
|
andrew@1
|
392 liveInput.addPitchEvent(pitchIn, timeIn);
|
andrew@4
|
393
|
andrew@10
|
394 //printPosteriorMAPinfo();
|
andrew@11
|
395
|
andrew@7
|
396 matchNewPitchEvent(channel, pitchIn, timeIn);//main pitch matching fn
|
andrew@7
|
397
|
andrew@7
|
398 likelihoodVisualisation[1] = bayesianStruct.likelihood;
|
andrew@7
|
399
|
andrew@7
|
400 recentPitch = pitchIn;//for drawing
|
andrew@7
|
401 recentTime = timeIn;
|
andrew@7
|
402 }
|
andrew@32
|
403 }
|
andrew@32
|
404
|
andrew@32
|
405
|
andrew@32
|
406 void AudioEventMatcher::newChromaEvent(const int& channel, float* chromaIn, const double& timeIn){
|
andrew@32
|
407
|
andrew@32
|
408 // could add event to the liveInput list? as in pitch event
|
andrew@34
|
409 printf("match chroma channel %i\n", channel);
|
andrew@34
|
410 for (int i = 0;i < 12;i++){
|
andrew@34
|
411 printf("chroma in[%i] = %f\n", i, chromaIn[i]);
|
andrew@34
|
412 }
|
andrew@34
|
413
|
andrew@32
|
414 matchNewChromaEvent(channel, chromaIn, timeIn);//main pitch matching fn
|
andrew@32
|
415
|
andrew@32
|
416 likelihoodVisualisation[channel] = bayesianStruct.likelihood;
|
andrew@32
|
417
|
andrew@8
|
418
|
andrew@2
|
419 }
|
andrew@2
|
420
|
andrew@32
|
421
|
andrew@6
|
422 void AudioEventMatcher::newKickEvent(const double& timeIn){
|
andrew@6
|
423 // liveInput.addKickEvent(timeIn);
|
andrew@2
|
424 matchNewOnsetEvent(0, timeIn);
|
andrew@7
|
425 likelihoodVisualisation[0] = bayesianStruct.likelihood;
|
andrew@2
|
426 }
|
andrew@2
|
427
|
andrew@6
|
428 void AudioEventMatcher::newKickEvent(const int& channel, const double& timeIn){
|
andrew@6
|
429 // liveInput.addKickEvent(timeIn);
|
andrew@6
|
430 matchNewOnsetEvent(channel, timeIn);
|
andrew@7
|
431 likelihoodVisualisation[0] = bayesianStruct.likelihood;
|
andrew@6
|
432 }
|
andrew@6
|
433
|
andrew@2
|
434
|
andrew@2
|
435 void AudioEventMatcher::newSnareEvent(const double& timeIn){
|
andrew@6
|
436 matchNewOnsetEvent(2, timeIn);
|
andrew@7
|
437 likelihoodVisualisation[2] = bayesianStruct.likelihood;
|
andrew@7
|
438 }
|
andrew@7
|
439
|
andrew@7
|
440
|
andrew@7
|
441 void AudioEventMatcher::newSnareEvent(const int& channel, const double& timeIn){
|
andrew@7
|
442 matchNewOnsetEvent(channel, timeIn);
|
andrew@7
|
443 likelihoodVisualisation[2] = bayesianStruct.likelihood;
|
andrew@2
|
444 }
|
andrew@2
|
445
|
andrew@2
|
446 //Needs just to set bounds for the matching process, not have TimeIn
|
andrew@2
|
447 void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){
|
andrew@3
|
448
|
andrew@6
|
449 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets
|
andrew@10
|
450
|
andrew@2
|
451 //start at beginning but OPTIMISE later
|
andrew@2
|
452 bayesianStruct.likelihood.offset = bayesianStruct.prior.offset;
|
andrew@2
|
453 bayesianStruct.likelihood.zero();//set to zero
|
andrew@2
|
454
|
andrew@2
|
455 double quantity = 1;//likelihoodToNoiseRatio / numberOfMatches;
|
andrew@2
|
456 int numberOfMatchesFound = 0;
|
andrew@2
|
457
|
andrew@10
|
458 double startMatchingTime = bayesianStruct.likelihood.offset;
|
andrew@10
|
459 double endMatchingTime = bayesianStruct.likelihood.offset + matchWindowWidth;
|
andrew@32
|
460 double millisTime = -1*INFINITY;//or 0 is fine
|
andrew@32
|
461 int checkIndex = 0;
|
andrew@2
|
462 if (channel <= recordedTracks.numberOfAudioTracks){
|
andrew@32
|
463 while (millisTime < startMatchingTime) {
|
andrew@32
|
464 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[checkIndex].millisTime;
|
andrew@32
|
465 checkIndex++;
|
andrew@32
|
466 }
|
andrew@32
|
467 for (int i = checkIndex;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size() && millisTime <= endMatchingTime;i++){
|
andrew@32
|
468 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime;
|
andrew@10
|
469 if (millisTime >= startMatchingTime && millisTime <= endMatchingTime){
|
andrew@14
|
470 bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, onsetLikelihoodWidth, quantity);
|
andrew@2
|
471 numberOfMatchesFound++;
|
andrew@6
|
472 // printf("Adding Gaussian for onset at time %f offset %f\n", millisTime, bayesianStruct.likelihood.offset);
|
andrew@2
|
473
|
andrew@32
|
474 }//end if within limits (changed so it now is 4 sure)
|
andrew@2
|
475 }
|
andrew@2
|
476 }
|
andrew@2
|
477
|
andrew@11
|
478 if (numberOfMatchesFound > 0){
|
andrew@3
|
479 // bayesianStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesianStruct.likelihood.length);
|
andrew@3
|
480 bayesianStruct.likelihood.addConstant(numberOfMatchesFound*(1-onsetLikelihoodToNoise)/(onsetLikelihoodToNoise*bayesianStruct.likelihood.length));
|
andrew@2
|
481 bayesianStruct.likelihood.renormalise();
|
andrew@2
|
482
|
andrew@8
|
483 bayesianStruct.calculatePosterior();
|
andrew@10
|
484 lastAlignmentTime = timeIn;//use TIMESTAMP
|
andrew@10
|
485 recentEventTime[channel] = timeIn;//ofGetElapsedTimeMillis() - startTime;
|
andrew@11
|
486
|
andrew@11
|
487 recentPriors[channel] = bayesianStruct.prior;
|
andrew@13
|
488 projectedPrior = bayesianStruct.prior;
|
andrew@19
|
489
|
andrew@19
|
490
|
andrew@19
|
491 temporal.updateTempo(channel, timeIn);
|
andrew@11
|
492 }
|
andrew@11
|
493
|
andrew@3
|
494 }
|
andrew@3
|
495
|
andrew@3
|
496
|
andrew@3
|
497
|
andrew@3
|
498 void AudioEventMatcher::matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){
|
andrew@3
|
499 //start at beginning but OPTIMISE later
|
andrew@10
|
500 /*printf("TIME %i\n", ofGetElapsedTimeMillis());
|
andrew@10
|
501 //tmp debug
|
andrew@10
|
502 updateBestAlignmentPosition();
|
andrew@10
|
503 printf("current alignment best estimate %f\n", currentAlignmentPosition);
|
andrew@10
|
504 */
|
andrew@6
|
505 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets
|
andrew@8
|
506
|
andrew@7
|
507 //set the lielihoods by matching the pitched note
|
andrew@7
|
508
|
andrew@15
|
509
|
andrew@3
|
510 int numberOfMatches = 0;
|
andrew@3
|
511 bayesianStruct.likelihood.zero();//set to zero
|
andrew@18
|
512 double newOnsetTime;
|
andrew@18
|
513 double closestDistance = INFINITY;
|
andrew@3
|
514
|
andrew@3
|
515 double quantity = 0;
|
andrew@32
|
516 double totalLikelihoodAdded = 0;
|
andrew@3
|
517 if (channel <= recordedTracks.numberOfAudioTracks){
|
andrew@3
|
518 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){
|
andrew@3
|
519
|
andrew@3
|
520 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) {
|
andrew@32
|
521 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 12);
|
andrew@18
|
522
|
andrew@3
|
523 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity);
|
andrew@3
|
524 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true;
|
andrew@3
|
525 numberOfMatches++;
|
andrew@32
|
526 totalLikelihoodAdded += quantity;
|
andrew@3
|
527 }
|
andrew@3
|
528 else{
|
andrew@3
|
529 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false;
|
andrew@3
|
530 }
|
andrew@18
|
531 //checking nearest pitch
|
andrew@18
|
532 newOnsetTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime;
|
andrew@18
|
533 if (abs(newOnsetTime - currentAlignmentPosition) < closestDistance){
|
andrew@18
|
534 closestDistance = abs(newOnsetTime - currentAlignmentPosition);
|
andrew@18
|
535 pitchOfNearestMatch = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch;
|
andrew@18
|
536 distanceOfNearestMatch = quantity;
|
andrew@18
|
537 }
|
andrew@3
|
538
|
andrew@3
|
539 }
|
andrew@3
|
540 }
|
andrew@6
|
541
|
andrew@8
|
542
|
andrew@8
|
543
|
andrew@6
|
544 if (numberOfMatches > 0){//no point updating unless there is a match
|
andrew@32
|
545 //replacing numberOfMatches with totalLike below...
|
andrew@32
|
546 bayesianStruct.likelihood.addConstant(totalLikelihoodAdded*(1-pitchLikelihoodToNoise)/(pitchLikelihoodToNoise*bayesianStruct.likelihood.length));
|
andrew@4
|
547
|
andrew@4
|
548 //tmp set likelihood constant and calculate using that
|
andrew@6
|
549 //bayesianStruct.likelihood.zero();
|
andrew@6
|
550 //bayesianStruct.likelihood.addConstant(1);
|
andrew@7
|
551
|
andrew@6
|
552 bayesianStruct.calculatePosterior();
|
andrew@11
|
553 lastAlignmentTime = timeIn;//has to use the STAMPED time
|
andrew@11
|
554 recentEventTime[channel] = timeIn;
|
andrew@11
|
555
|
andrew@11
|
556 recentPriors[channel] = bayesianStruct.prior;
|
andrew@13
|
557 projectedPrior = bayesianStruct.prior;
|
andrew@19
|
558
|
andrew@19
|
559 temporal.eventTimes[channel].push_back(timeIn);
|
andrew@6
|
560 }
|
andrew@4
|
561
|
andrew@11
|
562
|
andrew@1
|
563 }
|
andrew@1
|
564
|
andrew@3
|
565 double AudioEventMatcher::getPitchDistance(const double& pitchOne, const double& pitchTwo, const double& scale){
|
andrew@3
|
566
|
andrew@18
|
567 double scaleFactor = scale * pitchOne / 110.0;
|
andrew@16
|
568
|
andrew@18
|
569 int multiplicationFactor = 1;
|
andrew@18
|
570 if (pitchTwo > 0){
|
andrew@32
|
571 multiplicationFactor = round(pitchOne/pitchTwo);
|
andrew@18
|
572 }
|
andrew@16
|
573
|
andrew@18
|
574 double distance = abs(pitchOne - pitchTwo*multiplicationFactor);
|
andrew@16
|
575 if (distance < scaleFactor)
|
andrew@16
|
576 distance = 1 - (distance/scaleFactor);
|
andrew@3
|
577 else
|
andrew@3
|
578 distance = 0;
|
andrew@3
|
579
|
andrew@32
|
580 //printf("[pitch distance %f vs %f, factor %i = %f\n", pitchOne, pitchTwo, multiplicationFactor, distance);
|
andrew@3
|
581 return distance;
|
andrew@3
|
582
|
andrew@3
|
583 }
|
andrew@3
|
584
|
andrew@3
|
585
|
andrew@3
|
586 bool AudioEventMatcher::checkMatch(const double& recordedPitch, const double& livePitch){
|
andrew@18
|
587
|
andrew@18
|
588 if (livePitch > 0){
|
andrew@18
|
589 int multiplicationFactor = (int)(round(recordedPitch/livePitch));
|
andrew@18
|
590
|
andrew@32
|
591 if (abs(recordedPitch - livePitch * multiplicationFactor) < pitchCutOff)
|
andrew@3
|
592 return true;
|
andrew@3
|
593 else
|
andrew@3
|
594 return false;
|
andrew@18
|
595 }else {
|
andrew@18
|
596 return false;
|
andrew@18
|
597 }
|
andrew@18
|
598
|
andrew@3
|
599 }
|
andrew@3
|
600
|
andrew@3
|
601
|
andrew@32
|
602 void AudioEventMatcher::matchNewChromaEvent(const int& channel, float* chromaIn, const double& timeIn){
|
andrew@32
|
603 //start at beginning but OPTIMISE later
|
andrew@32
|
604
|
andrew@32
|
605 bayesianStruct.updateBayesianDistributions(timeIn);//moves the posterior up into prior given the time interval and calculates new offsets
|
andrew@32
|
606
|
andrew@32
|
607 //set the likelihoods by matching the pitched note
|
andrew@32
|
608
|
andrew@32
|
609 int numberOfMatches = 0;
|
andrew@32
|
610 bayesianStruct.likelihood.zero();//set to zero
|
andrew@32
|
611 double newOnsetTime;
|
andrew@32
|
612 double closestDistance = INFINITY;
|
andrew@32
|
613
|
andrew@32
|
614 double quantity = 1;
|
andrew@32
|
615 double totalLikelihoodAdded = 0;
|
andrew@32
|
616
|
andrew@32
|
617 double startMatchingTime = bayesianStruct.likelihood.offset;
|
andrew@32
|
618 double endMatchingTime = bayesianStruct.likelihood.offset + matchWindowWidth;
|
andrew@32
|
619 double millisTime = -1*INFINITY;//or 0 is fine
|
andrew@32
|
620
|
andrew@32
|
621 int checkIndex = 0;
|
andrew@32
|
622 if (channel <= recordedTracks.numberOfAudioTracks){
|
andrew@32
|
623 while (millisTime < startMatchingTime) {
|
andrew@32
|
624 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[checkIndex].millisTime;
|
andrew@32
|
625 checkIndex++;
|
andrew@32
|
626 }//go up to where we need to check from fast
|
andrew@32
|
627
|
andrew@32
|
628 for (int i = checkIndex;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size() && millisTime <= endMatchingTime;i++){
|
andrew@32
|
629 millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime;
|
andrew@32
|
630
|
andrew@32
|
631 if (millisTime >= startMatchingTime && millisTime <= endMatchingTime){
|
andrew@35
|
632
|
andrew@35
|
633 if (useChromaDotProduct)
|
andrew@35
|
634 quantity = getChromaDotProductDistance(chromaIn, &recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].chromaValues[0]);
|
andrew@35
|
635 else
|
andrew@35
|
636 quantity = getChromaEuclideanDistance(chromaIn, &recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].chromaValues[0]);
|
andrew@35
|
637
|
andrew@35
|
638
|
andrew@32
|
639 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, chromaLikelihoodWidth, quantity);
|
andrew@32
|
640
|
andrew@32
|
641 // bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, onsetLikelihoodWidth, quantity);
|
andrew@32
|
642 numberOfMatches++;
|
andrew@32
|
643 totalLikelihoodAdded += quantity;
|
andrew@32
|
644 printf("Adding CHROMA Gaussian for onset at time %.1f dist %.3f\n", millisTime, quantity);
|
andrew@32
|
645
|
andrew@32
|
646 }//end if within limits (changed so it now is 4 sure)
|
andrew@32
|
647 }
|
andrew@32
|
648 }
|
andrew@32
|
649
|
andrew@32
|
650
|
andrew@32
|
651 if (numberOfMatches > 0){//no point updating unless there is a match
|
andrew@32
|
652 //replacing numberOfMatches with totalLike below...
|
andrew@32
|
653
|
andrew@32
|
654 printf("CHROMA HAS %i MATCHES\n", numberOfMatches);
|
andrew@32
|
655
|
andrew@32
|
656 bayesianStruct.likelihood.addConstant(totalLikelihoodAdded*(1-chromaLikelihoodToNoise)/(chromaLikelihoodToNoise*bayesianStruct.likelihood.length));
|
andrew@32
|
657
|
andrew@32
|
658 bayesianStruct.calculatePosterior();
|
andrew@32
|
659 lastAlignmentTime = timeIn;//has to use the STAMPED time
|
andrew@32
|
660 recentEventTime[channel] = timeIn;
|
andrew@32
|
661
|
andrew@32
|
662 recentPriors[channel] = bayesianStruct.prior;
|
andrew@32
|
663 projectedPrior = bayesianStruct.prior;
|
andrew@32
|
664
|
andrew@32
|
665 temporal.eventTimes[channel].push_back(timeIn);
|
andrew@32
|
666 }
|
andrew@32
|
667
|
andrew@32
|
668 }
|
andrew@32
|
669
|
andrew@32
|
670
|
andrew@35
|
671 double AudioEventMatcher::getChromaDotProductDistance(float* chromaOne, float* chromaTwo){
|
andrew@32
|
672 double distance = 0;
|
andrew@32
|
673 double total = 0;
|
andrew@32
|
674 for (int i = 0;i < 12;i++){
|
andrew@32
|
675 distance += chromaOne[i]*chromaTwo[i];
|
andrew@32
|
676 total += chromaOne[i]*chromaOne[i] + (chromaTwo[i]*chromaTwo[i]);
|
andrew@32
|
677 }
|
andrew@32
|
678
|
andrew@35
|
679 if (total > 0)
|
andrew@35
|
680 distance /= sqrt(total);
|
andrew@35
|
681
|
andrew@35
|
682 return distance;
|
andrew@35
|
683 }
|
andrew@35
|
684
|
andrew@35
|
685 double AudioEventMatcher::getChromaEuclideanDistance(float* chromaOne, float* chromaTwo){
|
andrew@35
|
686 double distance = 0;
|
andrew@35
|
687 double total = 0;
|
andrew@35
|
688 // printf("\n");
|
andrew@35
|
689 for (int i = 0;i < 12;i++){
|
andrew@35
|
690 total += (chromaOne[i] - chromaTwo[i])*(chromaOne[i] - chromaTwo[i]);
|
andrew@35
|
691 // printf("chroma1: %.2f; chroma2: %.2f\n", chromaOne[i], chromaTwo[i]);
|
andrew@35
|
692 // total += chromaOne[i]*chromaOne[i] + (chromaTwo[i]*chromaTwo[i]);
|
andrew@35
|
693 }
|
andrew@35
|
694
|
andrew@35
|
695 if (total > 0)
|
andrew@35
|
696 distance = 1.0/sqrt(total);
|
andrew@35
|
697 // printf("DISTANCE : %.3f\n", distance);
|
andrew@32
|
698 return distance;
|
andrew@32
|
699 }
|
andrew@1
|
700
|
andrew@1
|
701 void AudioEventMatcher::windowResized(const int& w, const int& h){
|
andrew@1
|
702 recordedTracks.windowResized(w,h);
|
andrew@3
|
703 bayesTempoWindow.resized(w,h);
|
andrew@3
|
704 bayesPositionWindow.resized(w,h);
|
andrew@3
|
705 }
|
andrew@3
|
706
|
andrew@10
|
707 /*
|
andrew@10
|
708
|
andrew@10
|
709 void printPosteriorMAPinfo(){ //tmp print stuff
|
andrew@10
|
710 printf("New pitch MAP post estimate now %i, ", bayesianStruct.posterior.MAPestimate);
|
andrew@10
|
711 double tmp = bayesianStruct.posterior.getMAPestimate();
|
andrew@10
|
712 printf(" getting it %f and offset %f == %f ms\n", tmp, bayesianStruct.posterior.offset, bayesianStruct.posterior.getIndexInRealTerms(tmp));
|
andrew@10
|
713
|
andrew@10
|
714 }
|
andrew@10
|
715 */
|
andrew@3
|
716
|