Mercurial > hg > drum-timing-analyser
view DrumTimingLoader_OF/src/RecordedMultipleAudio.cpp @ 3:303edbbcf1bd tip
updated ofxAubioOnsetDetection file
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Sun, 24 Nov 2013 08:15:17 +0000 |
parents | 50ba55abea8c |
children |
line wrap: on
line source
/* * RecordedMultipleAudio.cpp * Drum Timing Analyser * * Created by Andrew on 31/01/2012. * Copyright 2012 QMUL. All rights reserved. * */ #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); 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; // printf("AFTER LOADING: \n"); // printInfo(); } #pragma mark -loadingPrerecordedTracks void RecordedMultipleAudio::setDifferentMultitracks(const int& setToLoad){ const char *kickfilename ;//= "../../../data/sound/LiveDues/kick_liveDues.wav"; const char *roomfilename ;//"../../../data/sound/LiveDues/bass_upsideLive.wav"; const char *snarefilename ; std::string sonicVizBeatsFilename ; switch (setToLoad) { case 0: kickfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/kickFuture.wav"; roomfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/roomFuture.wav"; snarefilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/snareFuture.wav"; sonicVizBeatsFilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/FutureHidesBeats.txt"; break; case 1: roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/Mixdown/PennyArcade_StudioMixdown.wav"; kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/kick.wav"; snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/snare.wav"; sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/Mixdown/PennyArcade_StudioMixdown_beats.txt"; break; case 2: roomfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/colesL_bip.wav"; kickfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/Kick_bip.wav"; snarefilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/Snare_bip.wav"; sonicVizBeatsFilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/IngramGreenSectionBeats.txt"; break; case 3: roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/coles_bip.wav"; kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/kick d112_bip.wav"; snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/snare bottom_bip.wav"; sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/TakeOneBeats.txt"; break; case 4: roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/neuamnn_bip.wav"; kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/kick_bip.wav"; snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/snare_bip.wav"; 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("loading room: %s\n", roomfilename); loadAudioTrack(roomfilename, 1); } 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(); } } void RecordedMultipleAudio::loadAudioTrack(std::string name, const int& channel){ //kick - track type 0 //bass - type 1 //snare type 2 //guitar type 3 if (channel >= 0 && channel <= numberOfAudioTracks){ loadedAudioPtr = new LoadedAudioHolder; //set tracktype before we do analysis //so we dont do unnecessary chroma and pitch calculations if (channel == 0 || channel == 2){ loadedAudioPtr->setTrackType(channel); } else{ loadedAudioPtr->setTrackType(0); } loadedAudioPtr->loadAudioFile(name); loadedAudioFiles[channel] = *loadedAudioPtr; loadedAudioFiles[channel].fileLoader.onsetDetect.window.setToRelativeSize(0, trackScreenHeight*channel, 1, trackScreenHeight); //loadedAudioFiles[channel].setTrackType(channel); } } void RecordedMultipleAudio::readInBeatsFile(std::string& pathName){ // "/Users/andrew/Documents/work/MuseScore/RWC/ANNOTATION/RM-C002_annotation+WavPos.csv" beatTimes.clear(); printf("- - - - \n\nREAD FILE %s\n", pathName.c_str()); ifstream file ( pathName.c_str()); string value, tmpLine; stringstream iss; int count = 0; while ( file.good() ) { getline(file, tmpLine); iss << tmpLine; int lineCount = 0; // printf("tmp line %s\n", tmpLine.c_str()); while(getline ( iss, value, '\t' )){ // read a string until next comma: http://www.cplusplus.com/reference/string/getline/ // cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it // printf("line:%s\n", value.c_str()); string::size_type start = value.find_first_not_of(" ,\t\v\n"); string part = value.substr(start, string::npos); //printf("%s\n", firstpart.c_str()); if (lineCount == 0){ //printf("First part of line found '%s'\n", part.c_str()); double newBeatTime = atof(part.c_str()); beatTimes.push_back(newBeatTime); } lineCount++; }//end while reading line iss.clear(); }//end while printf("There are %i BEAT annotations\n", (int)beatTimes.size()); } void RecordedMultipleAudio::printBeatTimes(){ for (int i = 0;i < beatTimes.size();i++){ printf("Beat[%i] = %f\n", i, beatTimes[i]); } } void RecordedMultipleAudio::checkFileErrors(int channel){ int beatIndex = 0; 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++; } double error = (1000.0*beatTimes[beatIndex] - loadedAudioFiles[channel].onsetTimesMillis[i]); if (fabs(error) < cutoff){ if (channel == 0) printf("Pos: %i Beat Time %f Kick Time %f Error %f\n", beatIndex%4, 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); else printf("Pos: %i Beat Time %f Snare Time %f Error %f\n", beatIndex%4, 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); }else{ if (channel == 0) printf("Ch.0 Out of Beat: Kick Time %f beat error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); else printf("Ch.2 Out of Beat: %f Snare Time %f best error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error); } } } #pragma mark -labelExactOnsets void RecordedMultipleAudio::findBeatOnsets(){ //tries to find kicks on 1, 3; snares on 2,4 int beatIndex = 0; int kickIndex = 0; int snareIndex = 0; double kickTime, snareTime; int cutoff = 50;//ms width to check onsetInfo.clear(); // kickErrors.clear(); // snareErrors.clear(); bool beatFound; for (int k = 0;k < beatTimes.size();k++){ beatFound = false; 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); while (kickIndex < loadedAudioFiles[0].onsetTimesMillis.size() && loadedAudioFiles[0].onsetTimesMillis[kickIndex] < newBeatTime - cutoff){ 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 && fabs(kickTime - beatTimes[k]*1000.0) < bestBeatDifference){ beatFound = true; 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); } } break; case 1: case 3://snare 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 && 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; 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); } } break; } if (!beatFound){ information.type = -1;//not a kick or snare information.exactOnsetTime = beatTimes[k]*1000.0; information.metricalPosition = beatPosition;//.push_ // exactBeatPositions.push_back(beatTimes[k]*1000.0);//have to go with the annotated beat instead (no matching kick or snare) printf("beat[%i] %f NOT FOUND, kicktime %f snaretime %f\n", k, beatTimes[k]*1000.0, kickTime, snareTime ); } onsetInfo.push_back(information); }//end for all beat annotations correctExactBeatTiming();//get rid of the first onset time calculateTimingAnalysis(); //so our exact beat times are then information.exactOnsetTime } #pragma mark -doTimingAnalysis void RecordedMultipleAudio::correctExactBeatTiming(){ //get rid of firtst onset time if (onsetInfo.size() > 0){ timingOffset = onsetInfo[0].exactOnsetTime;//s[0]; double tmpPosn; for (int i = 0;i < onsetInfo.size();i++){ onsetInfo[i].beatTimeToProcess = onsetInfo[i].exactOnsetTime - timingOffset; printf("exact [%i] type %i %f, corrected %f\n", i, onsetInfo[i].type, onsetInfo[i].exactOnsetTime, onsetInfo[i].beatTimeToProcess ); } } } void RecordedMultipleAudio::calculateTimingAnalysis(){ for (int i = 0;i < onsetInfo.size();i++){ drumTimingAnalyser.updateCostToPoint(onsetInfo[i].beatTimeToProcess, i); //updatecounter is the beat position for this note event - can be used to do other kinds of durations than just simple beats drumTimingAnalyser.beatPosition.push_back(onsetInfo[i].exactOnsetTime); } drumTimingAnalyser.processPathHistory(); drumTimingAnalyser.calculateTempoLimits(); getErrorTimesFromAnalysis(); alternativeKickRelativeAnalysis(); displayKickRelativeMedianErrors();//NB messes ther order of these //this was how we did it in multimatch program // timer.processPathHistory(); // timer.calculateTempoLimits(); // timer.exportTimingData(); // timer.exportProcessedBeatTimes(firstNoteTime); } void RecordedMultipleAudio::getErrorTimesFromAnalysis(){ printf("\nDrumTimingLoader: get error times from analysis!!!\n"); setUpErrorsByMetricalPosition(); //gets the errors from the drum timing analyser (i.e. ISMIR paper code) and attributes these to the onsets for (int i = 0;i < drumTimingAnalyser.timingData.size();i++){ 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 onset time %f click time %i error %i\n", i, onsetInfo[i].metricalPosition, onsetInfo[i].exactOnsetTime, onsetInfo[i].clickTime, (int)onsetInfo[i].error); } displayMedianErrors(); } void RecordedMultipleAudio::alternativeKickRelativeAnalysis(){ printf("\n\nAnalysis Relative to the Kick Drum on the ONE\n"); //this sees kicks as ON the beat, looks at relative error of the three other beats if we chop the bar evenly 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){//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 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 mark -exportInfo void RecordedMultipleAudio::exportErrorInformation(){ printf("Export final timing information\n"); ofstream ofs(infoFilepath.c_str()); for (int i = 0;i < onsetInfo.size() && kickRelativeErrors.size();i++){// drumTimingAnalyser.timingData.size() ofs << i << "," << (i%4) << "," << onsetInfo[i].exactOnsetTime << ","; ofs << onsetInfo[i].clickTime << "," << onsetInfo[i].error << ",";//the error for the ISMIR timing analyser ofs << kickRelativeClickTimes[i] << "," << kickRelativeErrors[i];//the click and error for beats evenly between kicks ofs << endl; } } 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]); } } void RecordedMultipleAudio::setUpErrorsByMetricalPosition(){ //clear this matrix errorsByMetricalPosition.clear(); for (int i = 0;i < 4;i++){ DoubleVector v; errorsByMetricalPosition.push_back(v); } } void RecordedMultipleAudio::displayMedianErrors(){ printf("Medians of the Decoded Tempo variations\n"); for (int i = 0;i < 4;i++){ //printErrorsForMetricalPosition(i); std::sort(errorsByMetricalPosition[i].begin(), errorsByMetricalPosition[i].end());//sort vector double median = errorsByMetricalPosition[i][(int)(errorsByMetricalPosition[i].size()/2)]; printf("median for metrical position %i is %f\n", i, median); } } void RecordedMultipleAudio::displayKickRelativeMedianErrors(){ printf("Medians of the KR variations\n"); DoubleVector tmpKRErrors; for (int i = 0;i < 4;i++){ tmpKRErrors.clear(); int index = 0; while (index+i < kickRelativeErrors.size()) { tmpKRErrors.push_back(kickRelativeErrors[index + i]); index += 4; } // for (int k = 0;k < tmpKRErrors.size();k++) // printf("kr %i [%i] = %f\n", i, k, tmpKRErrors[k]); //printErrorsForMetricalPosition(i); std::sort(tmpKRErrors.begin(), tmpKRErrors.end());//sort vector // for (int k = 0;k < tmpKRErrors.size();k++) // printf("sorted kr %i [%i] = %f\n", i, k, tmpKRErrors[k]); double median = tmpKRErrors[(int)(tmpKRErrors.size()/2)]; printf("median for metrical position %i is %f\n", i, median); } } void RecordedMultipleAudio::printErrorsForMetricalPosition(const int& i){ for (int k = 0;k < errorsByMetricalPosition[i].size();k++){ printf("metrical posn %i, [%i] = %f\n", i, k, errorsByMetricalPosition[i][k]); } } #pragma mark -drawTracks void RecordedMultipleAudio::drawTracks(){ if (drawWindow == 0){ for (int i = 0;i < numberOfAudioTracks;i++){ loadedAudioFiles[i].draw(); } } 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){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].updateToMillisPosition(millis); } void RecordedMultipleAudio::updatePlaybackPositionToMillis(const double& millis){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].updatePlaybackPositionToMillis(millis); } void RecordedMultipleAudio::togglePlay(){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].togglePlay(); } void RecordedMultipleAudio::stop(){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].stop(); } void RecordedMultipleAudio::printInfo(){ loadedAudioFiles[0].fileLoader.onsetDetect.printChromaInfo(); 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); } void RecordedMultipleAudio::zoomIn(){ if (drawWindow == 0){ printf("zoom in\n"); for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].fileLoader.zoomIn(); } if (drawWindow == 1) drumTimingAnalyser.zoomIn();//numberOfPointsPerPage /= 2; } void RecordedMultipleAudio::zoomOut(){ printf("zoom out\n"); for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].fileLoader.zoomOut(); if (drawWindow == 1) drumTimingAnalyser.zoomOut();//numberOfPointsPerPage *= 2; } void RecordedMultipleAudio::switchScreens(){ for (int i = 0;i < numberOfAudioTracks;i++) loadedAudioFiles[i].switchScreens(); }