Mercurial > hg > multitrack-audio-matcher
comparison src/AudioEventMatcher.cpp @ 3:5e188c0035b6
checking the offsets of the arrays
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Wed, 01 Feb 2012 16:05:26 +0000 |
parents | 179c09199b3c |
children | 45b5cf9be377 |
comparison
equal
deleted
inserted
replaced
2:179c09199b3c | 3:5e188c0035b6 |
---|---|
11 | 11 |
12 | 12 |
13 const int matchWindowWidth = 6000; | 13 const int matchWindowWidth = 6000; |
14 | 14 |
15 AudioEventMatcher::AudioEventMatcher(){ | 15 AudioEventMatcher::AudioEventMatcher(){ |
16 | 16 bayesPositionWindow.setToRelativeSize(0, 0.4, 1, 0.2); |
17 bayesTempoWindow.setToRelativeSize(0, 0.6, 1, 0.2); | 17 bayesTempoWindow.setToRelativeSize(0, 0.8, 1, 0.2); |
18 bayesPositionWindow.setToRelativeSize(0, 0.8, 1, 0.2); | 18 bayesLikelihoodWindow.setToRelativeSize(0, 0.6, 1, 0.2); |
19 | 19 |
20 setArraySizes(); | 20 setArraySizes(); |
21 | |
22 usingRealTime = false; | |
23 bayesianStruct.realTimeMode = &usingRealTime; | |
21 } | 24 } |
22 | 25 |
23 | 26 |
24 void AudioEventMatcher::setArraySizes(){ | 27 void AudioEventMatcher::setArraySizes(){ |
25 bayesianStruct.resetSpeedSize(200); | 28 bayesianStruct.resetSpeedSize(200); |
30 bayesianStruct.resetSize(matchWindowWidth); | 33 bayesianStruct.resetSize(matchWindowWidth); |
31 bayesianStruct.setPositionDistributionScalar(1); | 34 bayesianStruct.setPositionDistributionScalar(1); |
32 | 35 |
33 } | 36 } |
34 | 37 |
38 void AudioEventMatcher::startPlaying(){ | |
39 bayesianStruct.setStartPlaying(); | |
40 //bayesianStruct.posterior.printArray(); | |
41 } | |
42 | |
35 void AudioEventMatcher::draw(){ | 43 void AudioEventMatcher::draw(){ |
36 //ofRect(20, 20, 300, 200); | 44 ofSetColor(20,200,200); |
45 bayesPositionWindow.drawOutline(); | |
46 bayesTempoWindow.drawOutline(); | |
37 | 47 |
38 recordedTracks.drawTracks(); | 48 recordedTracks.drawTracks(); |
39 | 49 |
40 ofSetColor(255); | 50 ofSetColor(255); |
41 // bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow); | 51 // bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow); |
42 | 52 |
43 double screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber); | 53 double screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber); |
44 | 54 |
45 | 55 bayesianStruct.likelihood.drawVector(bayesianStruct.likelihood.getRealTermsAsIndex(0), bayesianStruct.likelihood.getRealTermsAsIndex(screenWidthMillis), bayesLikelihoodWindow); |
46 bayesianStruct.likelihood.drawVector(0, screenWidthMillis, bayesTempoWindow); | 56 |
57 bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow); | |
58 | |
59 bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); | |
60 | |
61 string tmpStr = "zero is "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(0)); | |
62 tmpStr += " offsetis "+ofToString(bayesianStruct.posterior.offset); | |
63 tmpStr += " screenWidth = "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis)); | |
64 ofDrawBitmapString(tmpStr, 20,140); | |
65 tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate); | |
66 ofDrawBitmapString(tmpStr, 20, 180); | |
67 | |
68 ofDrawBitmapString("screenamp "+ofToString(screenWidthMillis), 20, 100); | |
69 | |
47 | 70 |
48 } | 71 } |
49 | 72 |
50 | 73 |
51 void AudioEventMatcher::newPitchEvent(const double& pitchIn, const double& timeIn){ | 74 void AudioEventMatcher::newPitchEvent(const double& pitchIn, const double& timeIn){ |
52 liveInput.addPitchEvent(pitchIn, timeIn); | 75 liveInput.addPitchEvent(pitchIn, timeIn); |
53 recordedTracks.matchNewPitchEvent(0, pitchIn, timeIn); | 76 matchNewPitchEvent(0, pitchIn, timeIn); |
54 } | 77 } |
55 | 78 |
56 void AudioEventMatcher::newKickEvent(const double& timeIn){ | 79 void AudioEventMatcher::newKickEvent(const double& timeIn){ |
80 // liveInput.addKickEvent(time); | |
57 matchNewOnsetEvent(0, timeIn); | 81 matchNewOnsetEvent(0, timeIn); |
58 } | 82 } |
59 | 83 |
60 | 84 |
61 void AudioEventMatcher::newSnareEvent(const double& timeIn){ | 85 void AudioEventMatcher::newSnareEvent(const double& timeIn){ |
62 matchNewOnsetEvent(0, timeIn); | 86 matchNewOnsetEvent(0, timeIn); |
63 } | 87 } |
64 | 88 |
65 //Needs just to set bounds for the matching process, not have TimeIn | 89 //Needs just to set bounds for the matching process, not have TimeIn |
66 void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){ | 90 void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){ |
91 | |
92 | |
67 //start at beginning but OPTIMISE later | 93 //start at beginning but OPTIMISE later |
68 double likelihoodToNoise = 0.5; | 94 double onsetLikelihoodToNoise = 0.5; |
69 | 95 |
70 double likelihoodWidth = 40; | 96 double likelihoodWidth = 40; |
71 | 97 |
72 bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; | 98 bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; |
73 bayesianStruct.likelihood.zero();//set to zero | 99 bayesianStruct.likelihood.zero();//set to zero |
89 | 115 |
90 } | 116 } |
91 } | 117 } |
92 } | 118 } |
93 | 119 |
120 // bayesianStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesianStruct.likelihood.length); | |
121 bayesianStruct.likelihood.addConstant(numberOfMatchesFound*(1-onsetLikelihoodToNoise)/(onsetLikelihoodToNoise*bayesianStruct.likelihood.length)); | |
122 | |
94 bayesianStruct.likelihood.renormalise(); | 123 bayesianStruct.likelihood.renormalise(); |
95 | 124 |
96 //bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length); | 125 |
97 | 126 } |
98 | 127 |
99 } | 128 |
129 | |
130 void AudioEventMatcher::matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){ | |
131 //start at beginning but OPTIMISE later | |
132 | |
133 | |
134 updateBayesianDistributions(timeIn); | |
135 | |
136 ///set offsets | |
137 // bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; | |
138 double pitchLikelihoodToNoise = 0.5; | |
139 int numberOfMatches = 0; | |
140 bayesianStruct.likelihood.zero();//set to zero | |
141 | |
142 double quantity = 0; | |
143 if (channel <= recordedTracks.numberOfAudioTracks){ | |
144 for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ | |
145 | |
146 if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { | |
147 quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 40); | |
148 bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity); | |
149 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; | |
150 numberOfMatches++; | |
151 } | |
152 else{ | |
153 recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false; | |
154 } | |
155 | |
156 } | |
157 } | |
158 | |
159 bayesianStruct.likelihood.addConstant(numberOfMatches*(1-pitchLikelihoodToNoise)/(pitchLikelihoodToNoise*bayesianStruct.likelihood.length)); | |
160 | |
161 recordedTracks.recentPitch = pitchIn; | |
162 } | |
163 | |
164 double AudioEventMatcher::getPitchDistance(const double& pitchOne, const double& pitchTwo, const double& scale){ | |
165 | |
166 double distance = abs(pitchOne - pitchTwo); | |
167 if (distance < scale) | |
168 distance = 1 - (distance/scale); | |
169 else | |
170 distance = 0; | |
171 | |
172 // printf("[pitch distance %f vs %f = %f\n", pitchOne, pitchTwo, distance); | |
173 return distance; | |
174 | |
175 } | |
176 | |
177 | |
178 bool AudioEventMatcher::checkMatch(const double& recordedPitch, const double& livePitch){ | |
179 if (abs(recordedPitch - livePitch) < 40) | |
180 return true; | |
181 else | |
182 return false; | |
183 } | |
184 | |
100 | 185 |
101 | 186 |
102 void AudioEventMatcher::windowResized(const int& w, const int& h){ | 187 void AudioEventMatcher::windowResized(const int& w, const int& h){ |
103 recordedTracks.windowResized(w,h); | 188 recordedTracks.windowResized(w,h); |
104 } | 189 bayesTempoWindow.resized(w,h); |
190 bayesPositionWindow.resized(w,h); | |
191 } | |
192 | |
193 | |
194 | |
195 void AudioEventMatcher::updateBayesianDistributions(const double& newEventTime){ | |
196 //MOVE INTO bayesianStruct?? XX | |
197 | |
198 | |
199 | |
200 //NEED TO CHECK HERE THAT THEY HAVE THE SAME OFFSETS | |
201 bayesianStruct.prior.copyFromDynamicVector(bayesianStruct.posterior);//try the otehr way | |
202 | |
203 //bayesianStruct.copyPriorToPosterior(); | |
204 //need to get new MAP position and set the offset of the arrays | |
205 //currently bestEstimate is the approx for the new MAP position | |
206 | |
207 double timeDifference = newEventTime - bayesianStruct.lastEventTime; | |
208 printf("updating distributions at time %f diff %f\n", newEventTime, timeDifference); | |
209 | |
210 //addnoise to the tempo distribution | |
211 //bayesianStruct.decaySpeedDistribution(timeDifference); | |
212 | |
213 if (timeDifference > 50){ | |
214 bayesianStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.); | |
215 } | |
216 | |
217 bayesianStruct.updateBestEstimate(timeDifference); | |
218 | |
219 bayesianStruct.lastBestEstimateUpdateTime = newEventTime;//getTimeNow(timePlayed); | |
220 | |
221 bayesianStruct.setNewDistributionOffsets(max(0., bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2))); | |
222 | |
223 bayesianStruct.crossUpdateArrays(bayesianStruct.posterior, bayesianStruct.relativeSpeedPosterior, timeDifference); | |
224 | |
225 bayesianStruct.posterior.offset = max(0., bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2));// bayesianStruct.prior.offset = max(0., bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2)); | |
226 | |
227 bayesianStruct.lastEventTime = newEventTime;//bayesianStruct.lastEventTime = ofGetElapsedTimeMillis(); | |
228 } |