Mercurial > hg > multitrack-audio-matcher
changeset 2:179c09199b3c
bayesian vector now adding gaussians for kick onsets
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Tue, 31 Jan 2012 21:34:19 +0000 |
parents | 852173ca8365 |
children | 5e188c0035b6 |
files | README.txt bayesianArraySrc/DynamicVector.cpp bayesianArraySrc/DynamicVector.h src/AudioEventMatcher.cpp src/AudioEventMatcher.h src/RecordedMultitrackAudio.cpp src/RecordedMultitrackAudio.h src/testApp.cpp |
diffstat | 8 files changed, 148 insertions(+), 5 deletions(-) [+] |
line wrap: on
line diff
--- a/README.txt Tue Jan 31 17:35:30 2012 +0000 +++ b/README.txt Tue Jan 31 21:34:19 2012 +0000 @@ -9,3 +9,9 @@ ofxSoundfileloader ofxAubioOnsetDetector + + +Possible MIDI JNMR + +when adding gaussians - need to convert to the matrix indices - currently not done?? +
--- a/bayesianArraySrc/DynamicVector.cpp Tue Jan 31 17:35:30 2012 +0000 +++ b/bayesianArraySrc/DynamicVector.cpp Tue Jan 31 21:34:19 2012 +0000 @@ -157,6 +157,26 @@ //now delete tmp array } + + +void DynamicVector::addGaussianShapeFromRealTime(const double& actualTime, const double& StdDev, double factor){ + + double mean = getRealTermsAsIndex(actualTime); + printf("Gaussian realtime %f at index %f\n", actualTime, mean); + int i; + double std_dev_factor = (2*StdDev*StdDev); + factor *= (1/(StdDev*sqrt(2*PI))); + int maxVal = min((int) array.size(), (int)(mean + 4.8*StdDev)); + int minVal = max(0, (int)(mean - 4.8*StdDev)); + + for (i=minVal;i < maxVal;i++){ + array[i] += factor*exp(-1*(i-mean)*(i-mean)/(std_dev_factor)); + } + + // addGaussianShapeByLookupTable(mean, StdDev, factor); +} + + void DynamicVector::addGaussianShape(const double& mean, const double& StdDev, double factor){ int i;
--- a/bayesianArraySrc/DynamicVector.h Tue Jan 31 17:35:30 2012 +0000 +++ b/bayesianArraySrc/DynamicVector.h Tue Jan 31 21:34:19 2012 +0000 @@ -43,6 +43,11 @@ void addConstant(const double& value); void addGaussianShape(const double& mean, const double& stddev, double factor); + + void addGaussianShapeFromRealTime(const double& actualTime, const double& StdDev, double factor); + + + void addTriangularShape(double mean, double width, double factor); void addToIndex(const int& index, const double& constant);
--- a/src/AudioEventMatcher.cpp Tue Jan 31 17:35:30 2012 +0000 +++ b/src/AudioEventMatcher.cpp Tue Jan 31 21:34:19 2012 +0000 @@ -10,7 +10,7 @@ #include "AudioEventMatcher.h" -const int matchWindowWidth = 1200; +const int matchWindowWidth = 6000; AudioEventMatcher::AudioEventMatcher(){ @@ -36,14 +36,66 @@ //ofRect(20, 20, 300, 200); recordedTracks.drawTracks(); - bayesianStruct.relativeSpeedPrior.drawVector(0, 200, bayesTempoWindow); + + 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(0, screenWidthMillis, bayesTempoWindow); } void AudioEventMatcher::newPitchEvent(const double& pitchIn, const double& timeIn){ liveInput.addPitchEvent(pitchIn, timeIn); - //matchNewPitchEvent(); + recordedTracks.matchNewPitchEvent(0, pitchIn, timeIn); +} + +void AudioEventMatcher::newKickEvent(const double& timeIn){ + 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 likelihoodToNoise = 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.renormalise(); + + //bayesStruct.likelihood.addConstant((1-likelihoodToNoiseRatio)/bayesStruct.likelihood.length); + + }
--- a/src/AudioEventMatcher.h Tue Jan 31 17:35:30 2012 +0000 +++ b/src/AudioEventMatcher.h Tue Jan 31 21:34:19 2012 +0000 @@ -30,6 +30,11 @@ void draw(); void newPitchEvent(const double& pitchIn, const double& timeIn); + void newKickEvent(const double& timeIn); + void newSnareEvent(const double& timeIn); + + void matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn); + void matchNewOnsetEvent(const int& channel, const double& timeIn); BayesianArrayStructure bayesianStruct;//hold the probability distriubtions
--- a/src/RecordedMultitrackAudio.cpp Tue Jan 31 17:35:30 2012 +0000 +++ b/src/RecordedMultitrackAudio.cpp Tue Jan 31 21:34:19 2012 +0000 @@ -13,7 +13,7 @@ void RecordedMultitrackAudio::loadTestAudio(){ - const char *infilename = "../../../data/sound/bach4_short1.wav"; + const char *infilename = "../../../data/sound/basicClavScale.wav"; //LoadedAudioHolder lah; // lah.loadAudioFile(infilename); @@ -23,12 +23,13 @@ //but not then delete the instance before the vector of all audio tracks has been used //the above code using lah has problem that it deletes objects once out of the scope of testApp.setup() //when lah is in theory no longer used - something like that possible? - at least pointers to onset detection seem deleted - loadedAudioPtr = new LoadedAudioHolder; + loadedAudioPtr = new LoadedAudioHolder(); loadedAudioPtr->loadAudioFile(infilename); // loadedAudioFiles.push_back(*loadedAudioPtr); loadedAudioFiles[0] = *loadedAudioPtr; loadedAudioFiles[0].fileLoader.onsetDetect.window.setToRelativeSize(0, 0.0, 1, 0.25); + loadedAudioFiles[0].setTrackType(0);// fileLoader.onsetDetect.trackType = 0; // printf("Loaded audio %i\n", (int)numberOfAudioTracks); printf("loaded max val is %f\n", loadedAudioFiles[0].fileLoader.onsetDetect.onsetDetector.maximumDetectionValue); @@ -36,11 +37,15 @@ printf("BEFORE LOADING 1\n"); printInfo(); + infilename = "../../../data/sound/basicClavScale2.wav"; + loadedAudioPtr = new LoadedAudioHolder; loadedAudioPtr->loadAudioFile(infilename); // loadedAudioFiles.push_back(*loadedAudioPtr); loadedAudioFiles[1] = *loadedAudioPtr; loadedAudioFiles[1].fileLoader.onsetDetect.window.setToRelativeSize(0, 0.3, 1, 0.25); + loadedAudioFiles[1].setTrackType(1); +// loadedAudioFiles[1].fileLoader.onsetDetect.trackType = 0; printf("AFTER LOADING 1\n"); printInfo(); @@ -57,6 +62,8 @@ for (int i = 0;i < numberOfAudioTracks;i++){ loadedAudioFiles[i].draw(); } + + ofDrawBitmapString("pitch "+ofToString(recentPitch, 2), 20, 20); } @@ -66,6 +73,33 @@ } +void RecordedMultitrackAudio::matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn){ + //start at beginning but OPTIMISE later + + if (channel <= numberOfAudioTracks){ + for (int i = 0;i < loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets.size();i++){ + + if (checkMatch(loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].aubioPitch, pitchIn)) { + loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = true; + } + else{ + loadedAudioFiles[channel].fileLoader.onsetDetect.chromaOnsets[i].matched = false; + } + + } + } + + recentPitch = pitchIn; +} + +bool RecordedMultitrackAudio::checkMatch(const double& recordedPitch, const double& livePitch){ + if (abs(recordedPitch - livePitch) < 40) + return true; + else + return false; +} + + void RecordedMultitrackAudio::switchScreens(){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].switchScreens();
--- a/src/RecordedMultitrackAudio.h Tue Jan 31 17:35:30 2012 +0000 +++ b/src/RecordedMultitrackAudio.h Tue Jan 31 21:34:19 2012 +0000 @@ -43,9 +43,16 @@ void zoomOut(); + void matchNewPitchEvent(const int& channel, const double& pitchIn, const double& timeIn); + + bool checkMatch(const double& recordedPitch, const double& livePitch); + + double recentPitch; //variables int numberOfAudioTracks; LoadedAudioHolder* loadedAudioPtr; LoadedAudioHolder loadedAudioFiles[5]; + + }; #endif \ No newline at end of file
--- a/src/testApp.cpp Tue Jan 31 17:35:30 2012 +0000 +++ b/src/testApp.cpp Tue Jan 31 21:34:19 2012 +0000 @@ -99,6 +99,20 @@ printf("AUBIO PITCH RECEIVED %f at time %i\n", pitchIn, timeIn); eventMatcher.newPitchEvent(pitchIn, timeIn); } + + if ( m.getAddress() == "/kick" ){ + // float pitchIn = m.getArgAsFloat(0); + double timeIn = m.getArgAsInt32(0); + printf("kick RECEIVED at time %f\n", timeIn); + eventMatcher.newKickEvent(timeIn); + } + + if ( m.getAddress() == "/snare" ){ + // float pitchIn = m.getArgAsFloat(0); + double timeIn = m.getArgAsInt32(0); + printf("snare RECEIVED at time %f\n", timeIn); + eventMatcher.newSnareEvent(timeIn); + } } }