Mercurial > hg > drum-timing-analyser
diff DrumTimingLoader_OF/src/RecordedMultipleAudio.cpp @ 2:50ba55abea8c
updating files to newer version
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Sat, 23 Nov 2013 15:49:27 +0000 |
parents | 82352cfc0b23 |
children |
line wrap: on
line diff
--- a/DrumTimingLoader_OF/src/RecordedMultipleAudio.cpp Sat Nov 23 15:44:47 2013 +0000 +++ b/DrumTimingLoader_OF/src/RecordedMultipleAudio.cpp Sat Nov 23 15:49:27 2013 +0000 @@ -1,6 +1,6 @@ /* * RecordedMultipleAudio.cpp - * MultipleAudioMathcher + * Drum Timing Analyser * * Created by Andrew on 31/01/2012. * Copyright 2012 QMUL. All rights reserved. @@ -9,26 +9,42 @@ #include "RecordedMultipleAudio.h" +const bool printExportInfo = false; + RecordedMultipleAudio::RecordedMultipleAudio(){ infoFilepath = "../../../data/errorData.txt"; + + exactOnsetFilePath = "../../../data/exactOnsetTimes.txt"; + kickRelativeTempoFilePath = "../../../data/kickRelativeTempoTimes.txt"; + kickRelativeErrorsFilePath = "../../../data/kickRelativeErrorTimes.txt"; + kickRelativeClickFilePath = "../../../data/kickRelativeClickTimes.txt"; + + drumTimerTempoFilePath = "../../../data/drummerTimerTempoTimes.txt"; + drumTimerErrorsFilePath = "../../../data/drummerTimerErrorTimes.txt"; + drumTimerClickFilePath = "../../../data/drummerTimerClickTimes.txt"; + //infoFilepath = "/Users/andrew/errorData.txt"; timingOffset = 0; + playPositionSeconds = 3.4; } void RecordedMultipleAudio::loadTestAudio(){ + int multitrackToLoad = 7; numberOfAudioTracks = 2; printf("loaded max val is %f\n", loadedAudioFiles[0].fileLoader.onsetDetect.onsetDetector.maximumDetectionValue); - int multitrackToLoad = 5; + + setDifferentMultitracks(multitrackToLoad);//command to load this set of audio files - see below drumTimingAnalyser.phaseCost = 1000;//v high - i.e. dont do phase + drawWindow = 1; trackScreenHeight = 0.25; @@ -82,35 +98,71 @@ sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/PennyArcade_take4_beats.txt"; break; + /* case 5: roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/neuamnn_bip.wav"; kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/kick_bip.wav"; snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/snare_bip.wav"; sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/PennyArcade_take5_beats.txt"; break; + */ + case 5: + roomfilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/neuamnn_bip.wav"; + kickfilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/kick_bip.wav"; + snarefilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/snare_bip.wav"; + sonicVizBeatsFilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/PennyArcade_take5_beats.txt"; + break; + case 6: + roomfilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav"; + kickfilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav"; + snarefilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav"; + sonicVizBeatsFilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBeats.txt"; + break; + + case 7: + roomfilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav"; + kickfilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav"; + snarefilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav"; + sonicVizBeatsFilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/IsaakTake23MonoBeats.txt"; + break; + } if (kickfilename != NULL){ - + printf("Loading Kick file: %s\n", kickfilename); loadAudioTrack(kickfilename, 0); } if (roomfilename != NULL){ - printf("roomfilename: %s\n", roomfilename); + printf("loading room: %s\n", roomfilename); loadAudioTrack(roomfilename, 1); } - if (snarefilename != NULL) + if (snarefilename != NULL){ + printf("Loading Snare file: %s\n", kickfilename); loadAudioTrack(snarefilename, 2); + } if (sonicVizBeatsFilename.c_str() != NULL){ + printf("Reading sonic viz beats: %s\n", sonicVizBeatsFilename.c_str()); readInBeatsFile(sonicVizBeatsFilename); printBeatTimes(); checkFileErrors(0); checkFileErrors(2); findBeatOnsets(); + + exportErrorInformation(); + exportExactOnsetTimes(); + + exportKickRelativeTempoTimes(); + exportKickRelativeErrorTimes(); + exportKickRelativeClickTimes(); + + exportDrumTimerTempoTimes(); + exportDrumTimerErrorTimes(); + exportDrumTimerClickTimes(); } } @@ -177,7 +229,7 @@ }//end while - // printBeatTimes(); + printf("There are %i BEAT annotations\n", (int)beatTimes.size()); } @@ -191,8 +243,11 @@ void RecordedMultipleAudio::checkFileErrors(int channel){ int beatIndex = 0; - int cutoff = 50;//ms width to check + int cutoff = 60;//ms width to check for (int i = 0;i < loadedAudioFiles[channel].onsetTimesMillis.size();i++){ + + printf("onset time %i ms %i frames ", (int)loadedAudioFiles[channel].onsetTimesMillis[i], (int)loadedAudioFiles[channel].onsetTimesFrames[i]); + while (beatIndex < beatTimes.size() && 1000.0*beatTimes[beatIndex] < loadedAudioFiles[channel].onsetTimesMillis[i] - cutoff) { beatIndex++; } @@ -205,9 +260,9 @@ }else{ if (channel == 0) - printf("Out of Beat: Kick Time %f beat error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); + printf("Ch.0 Out of Beat: Kick Time %f beat error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); else - printf("Out of Beat: %f Snare Time %f best error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); + printf("Ch.2 Out of Beat: %f Snare Time %f best error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); } } @@ -235,6 +290,7 @@ double newBeatTime = beatTimes[k]*1000.0; int beatPosition = k % 4; OnsetInformation information; + double bestBeatDifference = 1000;//i.e. high switch (beatPosition) { case 0: case 2://check for kick when it is on the `one' or 'three' (0 or 2 in our metrical position) // printf("check %i kindex %i\n", beatPosition, kickIndex); @@ -242,14 +298,15 @@ kickIndex++; kickTime = loadedAudioFiles[0].onsetTimesMillis[kickIndex]; // printf("checking beat[%i] %f kick %f error %f\n", k, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0)); - if (fabs(kickTime - beatTimes[k]*1000.0) < cutoff){ + if (fabs(kickTime - beatTimes[k]*1000.0) < cutoff && fabs(kickTime - beatTimes[k]*1000.0) < bestBeatDifference){ beatFound = true; - printf("beat[%i] %f kick %f error %f\n", k, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0)); + printf("beat[%i] pos %i time %f kick %f error %f\n", k, beatPosition, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0)); information.error = (kickTime - beatTimes[k]*1000.0);//FOR NOW ONLY information.metricalPosition = beatPosition; information.type = 0; information.exactOnsetTime = kickTime; + bestBeatDifference = fabs(kickTime - beatTimes[k]*1000.0); // exactBeatPositions.push_back(kickTime); } } @@ -259,14 +316,15 @@ while (snareIndex < loadedAudioFiles[1].onsetTimesMillis.size() && loadedAudioFiles[1].onsetTimesMillis[snareIndex] < newBeatTime - cutoff ){ snareIndex++; snareTime = loadedAudioFiles[1].onsetTimesMillis[snareIndex]; - if (fabs(snareTime - beatTimes[k]*1000.0) < cutoff){ + if (fabs(snareTime - beatTimes[k]*1000.0) < cutoff && fabs(snareTime - beatTimes[k]*1000.0) < bestBeatDifference){ beatFound = true; // snareErrors.push_back((beatTimes[k]*1000.0 - snareTime)); information.error = (snareTime - beatTimes[k]*1000.0); information.metricalPosition = beatPosition;//.push_back(beatPosition); information.type = 1; information.exactOnsetTime = snareTime; - printf("beat[%i] %f snare %f error %f\n", k, beatTimes[k]*1000.0, snareTime, (snareTime - beatTimes[k]*1000.0)); + bestBeatDifference = fabs(snareTime - beatTimes[k]*1000.0); + printf("beat[%i] pos %i tim e%f snare %f error %f\n", k, beatPosition, beatTimes[k]*1000.0, snareTime, (snareTime - beatTimes[k]*1000.0)); // exactBeatPositions.push_back(snareTime); } } @@ -290,6 +348,9 @@ calculateTimingAnalysis(); + + //so our exact beat times are then information.exactOnsetTime + } #pragma mark -doTimingAnalysis @@ -320,8 +381,6 @@ alternativeKickRelativeAnalysis(); - exportErrorInformation(); - displayKickRelativeMedianErrors();//NB messes ther order of these //this was how we did it in multimatch program @@ -339,7 +398,8 @@ onsetInfo[i].error = drumTimingAnalyser.timingData[i][5]; onsetInfo[i].clickTime = drumTimingAnalyser.timingData[i][1] + timingOffset;//this is where teh timing analyser placed the click times errorsByMetricalPosition[onsetInfo[i].metricalPosition].push_back(onsetInfo[i].error); - printf("beat %i metrical posn %i exact beat time %f error %i\n", i, onsetInfo[i].metricalPosition, onsetInfo[i].exactOnsetTime, (int)onsetInfo[i].error); + printf("beat %i metrical posn %i exact onset time %f click time %i error %i\n", i, onsetInfo[i].metricalPosition, onsetInfo[i].exactOnsetTime, + onsetInfo[i].clickTime, (int)onsetInfo[i].error); } displayMedianErrors(); } @@ -352,23 +412,25 @@ double recentBeatTime, currentTempo; kickRelativeErrors.clear(); kickRelativeClickTimes.clear(); + kickRelativeTempo.clear(); for (int i = 0;i < drumTimingAnalyser.timingData.size();i++){ int beatPosition = i%4; - if (beatPosition == 0){ + if (beatPosition == 0){//then divide kicks and get even division recentBeatTime = onsetInfo[i].exactOnsetTime; if (i+4 < onsetInfo.size()) currentTempo = (onsetInfo[i+4].exactOnsetTime - onsetInfo[i].exactOnsetTime)/4.0; printf("new beat time %f tempo %f\n", recentBeatTime, currentTempo); } double error = onsetInfo[i].exactOnsetTime - (recentBeatTime + beatPosition*currentTempo); - printf("Beat %i KR Predicted Beat %f Actual exact %f KRerror %f DTerror %i\n", beatPosition, (recentBeatTime + beatPosition*currentTempo), onsetInfo[i].exactOnsetTime, error, (int)onsetInfo[i].error); + printf("Beat %i KR Predicted Beat: %f Onset: %f KRerror %f DTerror %i\n", beatPosition, (recentBeatTime + beatPosition*currentTempo), onsetInfo[i].exactOnsetTime, error, (int)onsetInfo[i].error); kickRelativeErrors.push_back(error); kickRelativeClickTimes.push_back(recentBeatTime + beatPosition*currentTempo); + kickRelativeTempo.push_back(currentTempo); } } -#pragma label -exportInfo +#pragma mark -exportInfo void RecordedMultipleAudio::exportErrorInformation(){ printf("Export final timing information\n"); @@ -382,6 +444,93 @@ } + +void RecordedMultipleAudio::exportExactOnsetTimes(){ + printf("Export exact beat times\n"); + + ofstream ofs(exactOnsetFilePath.c_str()); + for (int i = 0;i < onsetInfo.size();i++){// drumTimingAnalyser.timingData.size() + ofs << onsetInfo[i].exactOnsetTime/1000.0 << endl; + if (printExportInfo) + printf("exporting exact beat times %f\n", onsetInfo[i].exactOnsetTime); + } +} + +void RecordedMultipleAudio::exportKickRelativeTempoTimes(){ + printf("Export kick relative Tempo times\n"); + + ofstream ofs(kickRelativeTempoFilePath.c_str()); + for (int i = 0;i < kickRelativeTempo.size() && i < onsetInfo.size();i++){ + ofs << onsetInfo[i].exactOnsetTime << "\t" << kickRelativeTempo[i] << endl; + if (printExportInfo) + printf("exporting tempo[%i]: onset %f %f\n", i, onsetInfo[i].exactOnsetTime, kickRelativeTempo[i]); + } +} + +void RecordedMultipleAudio::exportKickRelativeErrorTimes(){ + printf("Export kick relative Error times\n"); + + ofstream ofs(kickRelativeErrorsFilePath.c_str()); + for (int i = 0;i < kickRelativeErrors.size() && i < onsetInfo.size();i++){ + ofs << onsetInfo[i].exactOnsetTime << "\t" << kickRelativeErrors[i] << endl; + if (printExportInfo) + printf("exporting tempo[%i]: onset %f %f\n", i, onsetInfo[i].exactOnsetTime, kickRelativeErrors[i]); + } +} + +void RecordedMultipleAudio::exportKickRelativeClickTimes(){ + printf("Export kick relative click times\n"); + + ofstream ofs(kickRelativeClickFilePath.c_str()); + for (int i = 0;i < kickRelativeClickTimes.size();i++){ + ofs << kickRelativeClickTimes[i]/1000.0 << endl; + if (printExportInfo) + printf("exporting KD click [%i]:%f\n", i,kickRelativeClickTimes[i]); + } +} + + +void RecordedMultipleAudio::exportDrumTimerTempoTimes(){ + printf("Export drum timing tempo times\n"); + + ofstream ofs(drumTimerTempoFilePath.c_str()); + for (int i = 0;i < drumTimingAnalyser.timingData.size() && i < onsetInfo.size();i++){ + ofs << onsetInfo[i].exactOnsetTime << "\t" << drumTimingAnalyser.timingData[i][0] << endl; + if (printExportInfo) + printf("exporting tempo[%i]: onset %f tempo %i\n", i, onsetInfo[i].exactOnsetTime, drumTimingAnalyser.timingData[i][0]); + } +} + + +void RecordedMultipleAudio::exportDrumTimerErrorTimes(){ + printf("Export drum timing Error times\n"); + + ofstream ofs(drumTimerErrorsFilePath.c_str()); + for (int i = 0;i < drumTimingAnalyser.timingData.size() && i < onsetInfo.size();i++){ + ofs << onsetInfo[i].exactOnsetTime << "\t" << drumTimingAnalyser.timingData[i][5] << endl; + if (printExportInfo) + printf("exporting [%i]: onset %f error %i\n", i, onsetInfo[i].exactOnsetTime, drumTimingAnalyser.timingData[i][5]); + } +} + + +void RecordedMultipleAudio::exportDrumTimerClickTimes(){ + printf("Export drum timing Click times\n"); + + ofstream ofs(drumTimerClickFilePath.c_str()); + for (int i = 0;i < onsetInfo.size();i++){ + ofs << onsetInfo[i].clickTime/1000.0 << endl; + if (printExportInfo) + printf("exporting click[%i] %i\n", i, onsetInfo[i].clickTime); + } +} + + + + + + + void RecordedMultipleAudio::printKickRelativeErrors(){ for (int i = 0;i < kickRelativeErrors.size();i++){ printf("KR error [%i] : %.1f\n", i, kickRelativeErrors[i]); @@ -456,12 +605,23 @@ } else { drumTimingAnalyser.drawTempoCurve(); } + +// ofDrawBitmapString(ofToString(playPositionSeconds),20, 40); } #pragma mark -update void RecordedMultipleAudio::updatePosition(){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].updateToPlayPosition(); + + playPositionSeconds = samplesToSeconds(loadedAudioFiles[0].fileLoader.audioHolder.playPosition); + drumTimingAnalyser.updatePlayIndex(playPositionSeconds); + + +} + +double RecordedMultipleAudio::samplesToSeconds(const double& samples){ + return samples/44100.0; } void RecordedMultipleAudio::updatePositionToMillis(const double& millis){ @@ -474,12 +634,6 @@ loadedAudioFiles[i].updatePlaybackPositionToMillis(millis); } -void RecordedMultipleAudio::switchScreens(){ - for (int i = 0;i < numberOfAudioTracks;i++) - loadedAudioFiles[i].switchScreens(); -} - - void RecordedMultipleAudio::togglePlay(){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].togglePlay(); @@ -496,6 +650,7 @@ loadedAudioFiles[0].printEvents(); } +#pragma mark -ScreenFunctions void RecordedMultipleAudio::windowResized(const int& w, const int& h){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].windowResized(w, h); @@ -522,4 +677,8 @@ } +void RecordedMultipleAudio::switchScreens(){ + for (int i = 0;i < numberOfAudioTracks;i++) + loadedAudioFiles[i].switchScreens(); +}