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