Mercurial > hg > multitrack-audio-matcher
view 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 |
line wrap: on
line source
/* * AudioEventMatcher.cpp * MultipleAudioMathcher * * Created by Andrew on 31/01/2012. * Copyright 2012 QMUL. All rights reserved. * */ #include "AudioEventMatcher.h" const int matchWindowWidth = 6000; AudioEventMatcher::AudioEventMatcher(){ bayesPositionWindow.setToRelativeSize(0, 0.4, 1, 0.2); bayesTempoWindow.setToRelativeSize(0, 0.8, 1, 0.2); bayesLikelihoodWindow.setToRelativeSize(0, 0.6, 1, 0.2); setArraySizes(); usingRealTime = false; bayesianStruct.realTimeMode = &usingRealTime; } void AudioEventMatcher::setArraySizes(){ bayesianStruct.resetSpeedSize(200); bayesianStruct.setRelativeSpeedScalar(0.01); bayesianStruct.setSpeedPrior(1.0); bayesianStruct.relativeSpeedPrior.getMaximum(); bayesianStruct.resetSize(matchWindowWidth); bayesianStruct.setPositionDistributionScalar(1); } void AudioEventMatcher::startPlaying(){ bayesianStruct.setStartPlaying(); //bayesianStruct.posterior.printArray(); } void AudioEventMatcher::draw(){ ofSetColor(20,200,200); bayesPositionWindow.drawOutline(); bayesTempoWindow.drawOutline(); recordedTracks.drawTracks(); ofSetColor(255); // bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow); double screenWidthMillis = recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.framesToMillis(recordedTracks.loadedAudioFiles[0].fileLoader.onsetDetect.amplitudeNumber); bayesianStruct.likelihood.drawVector(bayesianStruct.likelihood.getRealTermsAsIndex(0), bayesianStruct.likelihood.getRealTermsAsIndex(screenWidthMillis), bayesLikelihoodWindow); bayesianStruct.relativeSpeedPosterior.drawVector(0, bayesianStruct.relativeSpeedPosterior.getRealTermsAsIndex(2), bayesTempoWindow); bayesianStruct.posterior.drawVector(bayesianStruct.posterior.getRealTermsAsIndex(0), bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis), bayesPositionWindow); string tmpStr = "zero is "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(0)); tmpStr += " offsetis "+ofToString(bayesianStruct.posterior.offset); tmpStr += " screenWidth = "+ofToString(bayesianStruct.posterior.getRealTermsAsIndex(screenWidthMillis)); ofDrawBitmapString(tmpStr, 20,140); tmpStr = "best est "+ofToString(bayesianStruct.bestEstimate); ofDrawBitmapString(tmpStr, 20, 180); ofDrawBitmapString("screenamp "+ofToString(screenWidthMillis), 20, 100); } void AudioEventMatcher::newPitchEvent(const double& pitchIn, const double& timeIn){ liveInput.addPitchEvent(pitchIn, timeIn); matchNewPitchEvent(0, pitchIn, timeIn); } void AudioEventMatcher::newKickEvent(const double& timeIn){ // liveInput.addKickEvent(time); matchNewOnsetEvent(0, timeIn); } void AudioEventMatcher::newSnareEvent(const double& timeIn){ matchNewOnsetEvent(0, timeIn); } //Needs just to set bounds for the matching process, not have TimeIn void AudioEventMatcher::matchNewOnsetEvent(const int& channel, const double& timeIn){ //start at beginning but OPTIMISE later double onsetLikelihoodToNoise = 0.5; double likelihoodWidth = 40; bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; bayesianStruct.likelihood.zero();//set to zero double quantity = 1;//likelihoodToNoiseRatio / numberOfMatches; int numberOfMatchesFound = 0; double startTime = bayesianStruct.likelihood.offset; double endTime = bayesianStruct.likelihood.offset + matchWindowWidth; if (channel <= recordedTracks.numberOfAudioTracks){ for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ double millisTime = recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime; if (millisTime >= startTime && millisTime <= endTime){ bayesianStruct.likelihood.addGaussianShapeFromRealTime(millisTime, likelihoodWidth, quantity); numberOfMatchesFound++; printf("Adding Gaussian for onset at time %f offset %f\n", millisTime, bayesianStruct.likelihood.offset); } } } // bayesianStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesianStruct.likelihood.length); bayesianStruct.likelihood.addConstant(numberOfMatchesFound*(1-onsetLikelihoodToNoise)/(onsetLikelihoodToNoise*bayesianStruct.likelihood.length)); bayesianStruct.likelihood.renormalise(); } void AudioEventMatcher::matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){ //start at beginning but OPTIMISE later updateBayesianDistributions(timeIn); ///set offsets // bayesianStruct.likelihood.offset = bayesianStruct.prior.offset; double pitchLikelihoodToNoise = 0.5; int numberOfMatches = 0; bayesianStruct.likelihood.zero();//set to zero double quantity = 0; if (channel <= recordedTracks.numberOfAudioTracks){ for (int i = 0;i < recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ if (checkMatch(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { quantity = getPitchDistance(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn, 40); bayesianStruct.likelihood.addGaussianShapeFromRealTime(recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].millisTime, 30, quantity); recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; numberOfMatches++; } else{ recordedTracks.loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false; } } } bayesianStruct.likelihood.addConstant(numberOfMatches*(1-pitchLikelihoodToNoise)/(pitchLikelihoodToNoise*bayesianStruct.likelihood.length)); recordedTracks.recentPitch = pitchIn; } double AudioEventMatcher::getPitchDistance(const double& pitchOne, const double& pitchTwo, const double& scale){ double distance = abs(pitchOne - pitchTwo); if (distance < scale) distance = 1 - (distance/scale); else distance = 0; // printf("[pitch distance %f vs %f = %f\n", pitchOne, pitchTwo, distance); return distance; } bool AudioEventMatcher::checkMatch(const double& recordedPitch, const double& livePitch){ if (abs(recordedPitch - livePitch) < 40) return true; else return false; } void AudioEventMatcher::windowResized(const int& w, const int& h){ recordedTracks.windowResized(w,h); bayesTempoWindow.resized(w,h); bayesPositionWindow.resized(w,h); } void AudioEventMatcher::updateBayesianDistributions(const double& newEventTime){ //MOVE INTO bayesianStruct?? XX //NEED TO CHECK HERE THAT THEY HAVE THE SAME OFFSETS bayesianStruct.prior.copyFromDynamicVector(bayesianStruct.posterior);//try the otehr way //bayesianStruct.copyPriorToPosterior(); //need to get new MAP position and set the offset of the arrays //currently bestEstimate is the approx for the new MAP position double timeDifference = newEventTime - bayesianStruct.lastEventTime; printf("updating distributions at time %f diff %f\n", newEventTime, timeDifference); //addnoise to the tempo distribution //bayesianStruct.decaySpeedDistribution(timeDifference); if (timeDifference > 50){ bayesianStruct.addGaussianNoiseToSpeedPosterior(timeDifference * 10.0 / 100.); } bayesianStruct.updateBestEstimate(timeDifference); bayesianStruct.lastBestEstimateUpdateTime = newEventTime;//getTimeNow(timePlayed); bayesianStruct.setNewDistributionOffsets(max(0., bayesianStruct.bestEstimate - (bayesianStruct.prior.scalar*bayesianStruct.prior.arraySize/2))); bayesianStruct.crossUpdateArrays(bayesianStruct.posterior, bayesianStruct.relativeSpeedPosterior, timeDifference); 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)); bayesianStruct.lastEventTime = newEventTime;//bayesianStruct.lastEventTime = ofGetElapsedTimeMillis(); }