annotate 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
rev   line source
andrew@0 1 /*
andrew@0 2 * RecordedMultipleAudio.cpp
andrew@2 3 * Drum Timing Analyser
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 "RecordedMultipleAudio.h"
andrew@0 11
andrew@2 12 const bool printExportInfo = false;
andrew@2 13
andrew@0 14 RecordedMultipleAudio::RecordedMultipleAudio(){
andrew@0 15
andrew@0 16 infoFilepath = "../../../data/errorData.txt";
andrew@2 17
andrew@2 18 exactOnsetFilePath = "../../../data/exactOnsetTimes.txt";
andrew@2 19 kickRelativeTempoFilePath = "../../../data/kickRelativeTempoTimes.txt";
andrew@2 20 kickRelativeErrorsFilePath = "../../../data/kickRelativeErrorTimes.txt";
andrew@2 21 kickRelativeClickFilePath = "../../../data/kickRelativeClickTimes.txt";
andrew@2 22
andrew@2 23 drumTimerTempoFilePath = "../../../data/drummerTimerTempoTimes.txt";
andrew@2 24 drumTimerErrorsFilePath = "../../../data/drummerTimerErrorTimes.txt";
andrew@2 25 drumTimerClickFilePath = "../../../data/drummerTimerClickTimes.txt";
andrew@2 26
andrew@0 27 //infoFilepath = "/Users/andrew/errorData.txt";
andrew@0 28
andrew@0 29 timingOffset = 0;
andrew@2 30 playPositionSeconds = 3.4;
andrew@0 31 }
andrew@0 32
andrew@0 33 void RecordedMultipleAudio::loadTestAudio(){
andrew@0 34
andrew@2 35 int multitrackToLoad = 7;
andrew@0 36
andrew@0 37 numberOfAudioTracks = 2;
andrew@0 38
andrew@0 39 printf("loaded max val is %f\n", loadedAudioFiles[0].fileLoader.onsetDetect.onsetDetector.maximumDetectionValue);
andrew@0 40
andrew@2 41
andrew@2 42
andrew@0 43 setDifferentMultitracks(multitrackToLoad);//command to load this set of audio files - see below
andrew@0 44
andrew@0 45 drumTimingAnalyser.phaseCost = 1000;//v high - i.e. dont do phase
andrew@0 46
andrew@2 47
andrew@0 48 drawWindow = 1;
andrew@0 49 trackScreenHeight = 0.25;
andrew@0 50
andrew@0 51
andrew@0 52
andrew@0 53 // printf("AFTER LOADING: \n");
andrew@0 54 // printInfo();
andrew@0 55
andrew@0 56 }
andrew@0 57 #pragma mark -loadingPrerecordedTracks
andrew@0 58 void RecordedMultipleAudio::setDifferentMultitracks(const int& setToLoad){
andrew@0 59 const char *kickfilename ;//= "../../../data/sound/LiveDues/kick_liveDues.wav";
andrew@0 60 const char *roomfilename ;//"../../../data/sound/LiveDues/bass_upsideLive.wav";
andrew@0 61 const char *snarefilename ;
andrew@0 62 std::string sonicVizBeatsFilename ;
andrew@0 63
andrew@0 64 switch (setToLoad) {
andrew@0 65 case 0:
andrew@0 66 kickfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/kickFuture.wav";
andrew@0 67 roomfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/roomFuture.wav";
andrew@0 68 snarefilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/snareFuture.wav";
andrew@0 69 sonicVizBeatsFilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/futureHides/FutureHidesBeats.txt";
andrew@0 70 break;
andrew@0 71
andrew@0 72
andrew@0 73 case 1:
andrew@0 74 roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/Mixdown/PennyArcade_StudioMixdown.wav";
andrew@0 75 kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/kick.wav";
andrew@0 76 snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/snare.wav";
andrew@0 77 sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcadeStudio14aMultitrack/Mixdown/PennyArcade_StudioMixdown_beats.txt";
andrew@0 78 break;
andrew@0 79
andrew@0 80 case 2:
andrew@0 81 roomfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/colesL_bip.wav";
andrew@0 82 kickfilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/Kick_bip.wav";
andrew@0 83 snarefilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/Snare_bip.wav";
andrew@0 84 sonicVizBeatsFilename = "/Users/andrew/Documents/work/programming/MadMax/AudioFiles/MattIngramGreenSection/IngramGreenSectionBeats.txt";
andrew@0 85 break;
andrew@0 86
andrew@0 87 case 3:
andrew@0 88 roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/coles_bip.wav";
andrew@0 89 kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/kick d112_bip.wav";
andrew@0 90 snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/snare bottom_bip.wav";
andrew@0 91 sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDiamondWhite/tractorsDiamondWhite/Bounces/diamondWhiteMultiTakeOne/TakeOneBeats.txt";
andrew@0 92 break;
andrew@0 93
andrew@0 94 case 4:
andrew@0 95 roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/neuamnn_bip.wav";
andrew@0 96 kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/kick_bip.wav";
andrew@0 97 snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/snare_bip.wav";
andrew@0 98 sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeOne_4/PennyArcade_take4_beats.txt";
andrew@0 99 break;
andrew@0 100
andrew@2 101 /*
andrew@0 102 case 5:
andrew@0 103 roomfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/neuamnn_bip.wav";
andrew@0 104 kickfilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/kick_bip.wav";
andrew@0 105 snarefilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/snare_bip.wav";
andrew@0 106 sonicVizBeatsFilename = "/Volumes/Supersaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/PennyArcade_take5_beats.txt";
andrew@0 107 break;
andrew@2 108 */
andrew@2 109 case 5:
andrew@2 110 roomfilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/neuamnn_bip.wav";
andrew@2 111 kickfilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/kick_bip.wav";
andrew@2 112 snarefilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/snare_bip.wav";
andrew@2 113 sonicVizBeatsFilename = "/Volumes/MiniSaurus/TractorsAlbum/tractorsDemo/Bounces/PennyArcade_Multitracks/TakeTwo_5/PennyArcade_take5_beats.txt";
andrew@2 114 break;
andrew@0 115
andrew@0 116
andrew@2 117 case 6:
andrew@2 118 roomfilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav";
andrew@2 119 kickfilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav";
andrew@2 120 snarefilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBreak.wav";
andrew@2 121 sonicVizBeatsFilename = "/Users/andrew/Documents/work/Alignment/FunkyDrummerAnalysis/FunkyDrummerBeats.txt";
andrew@2 122 break;
andrew@2 123
andrew@2 124 case 7:
andrew@2 125 roomfilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav";
andrew@2 126 kickfilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav";
andrew@2 127 snarefilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/Take23_mono.wav";
andrew@2 128 sonicVizBeatsFilename = "/Users/andrew/Music/Logic/Tractors_April13/tractorIsaak2/Bounces/IsaakTake23MonoBeats.txt";
andrew@2 129 break;
andrew@2 130
andrew@0 131
andrew@0 132 }
andrew@0 133 if (kickfilename != NULL){
andrew@2 134 printf("Loading Kick file: %s\n", kickfilename);
andrew@0 135 loadAudioTrack(kickfilename, 0);
andrew@0 136 }
andrew@0 137
andrew@0 138 if (roomfilename != NULL){
andrew@2 139 printf("loading room: %s\n", roomfilename);
andrew@0 140 loadAudioTrack(roomfilename, 1);
andrew@0 141 }
andrew@0 142
andrew@2 143 if (snarefilename != NULL){
andrew@2 144 printf("Loading Snare file: %s\n", kickfilename);
andrew@0 145 loadAudioTrack(snarefilename, 2);
andrew@2 146 }
andrew@0 147
andrew@0 148 if (sonicVizBeatsFilename.c_str() != NULL){
andrew@2 149 printf("Reading sonic viz beats: %s\n", sonicVizBeatsFilename.c_str());
andrew@0 150 readInBeatsFile(sonicVizBeatsFilename);
andrew@0 151 printBeatTimes();
andrew@0 152 checkFileErrors(0);
andrew@0 153 checkFileErrors(2);
andrew@0 154 findBeatOnsets();
andrew@2 155
andrew@2 156 exportErrorInformation();
andrew@2 157 exportExactOnsetTimes();
andrew@2 158
andrew@2 159 exportKickRelativeTempoTimes();
andrew@2 160 exportKickRelativeErrorTimes();
andrew@2 161 exportKickRelativeClickTimes();
andrew@2 162
andrew@2 163 exportDrumTimerTempoTimes();
andrew@2 164 exportDrumTimerErrorTimes();
andrew@2 165 exportDrumTimerClickTimes();
andrew@0 166 }
andrew@0 167 }
andrew@0 168
andrew@0 169 void RecordedMultipleAudio::loadAudioTrack(std::string name, const int& channel){
andrew@0 170 //kick - track type 0
andrew@0 171 //bass - type 1
andrew@0 172 //snare type 2
andrew@0 173 //guitar type 3
andrew@0 174 if (channel >= 0 && channel <= numberOfAudioTracks){
andrew@0 175 loadedAudioPtr = new LoadedAudioHolder;
andrew@0 176 //set tracktype before we do analysis
andrew@0 177 //so we dont do unnecessary chroma and pitch calculations
andrew@0 178 if (channel == 0 || channel == 2){
andrew@0 179 loadedAudioPtr->setTrackType(channel);
andrew@0 180 }
andrew@0 181 else{
andrew@0 182 loadedAudioPtr->setTrackType(0);
andrew@0 183 }
andrew@0 184 loadedAudioPtr->loadAudioFile(name);
andrew@0 185
andrew@0 186 loadedAudioFiles[channel] = *loadedAudioPtr;
andrew@0 187 loadedAudioFiles[channel].fileLoader.onsetDetect.window.setToRelativeSize(0, trackScreenHeight*channel, 1, trackScreenHeight);
andrew@0 188 //loadedAudioFiles[channel].setTrackType(channel);
andrew@0 189 }
andrew@0 190 }
andrew@0 191
andrew@0 192
andrew@0 193
andrew@0 194 void RecordedMultipleAudio::readInBeatsFile(std::string& pathName){
andrew@0 195
andrew@0 196 // "/Users/andrew/Documents/work/MuseScore/RWC/ANNOTATION/RM-C002_annotation+WavPos.csv"
andrew@0 197 beatTimes.clear();
andrew@0 198
andrew@0 199 printf("- - - - \n\nREAD FILE %s\n", pathName.c_str());
andrew@0 200 ifstream file ( pathName.c_str());
andrew@0 201 string value, tmpLine;
andrew@0 202 stringstream iss;
andrew@0 203 int count = 0;
andrew@0 204
andrew@0 205 while ( file.good() )
andrew@0 206 {
andrew@0 207 getline(file, tmpLine);
andrew@0 208 iss << tmpLine;
andrew@0 209 int lineCount = 0;
andrew@0 210 // printf("tmp line %s\n", tmpLine.c_str());
andrew@0 211 while(getline ( iss, value, '\t' )){ // read a string until next comma: http://www.cplusplus.com/reference/string/getline/
andrew@0 212 // cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it
andrew@0 213 // printf("line:%s\n", value.c_str());
andrew@0 214 string::size_type start = value.find_first_not_of(" ,\t\v\n");
andrew@0 215
andrew@0 216 string part = value.substr(start, string::npos);
andrew@0 217
andrew@0 218 //printf("%s\n", firstpart.c_str());
andrew@0 219 if (lineCount == 0){
andrew@0 220 //printf("First part of line found '%s'\n", part.c_str());
andrew@0 221 double newBeatTime = atof(part.c_str());
andrew@0 222 beatTimes.push_back(newBeatTime);
andrew@0 223 }
andrew@0 224 lineCount++;
andrew@0 225
andrew@0 226 }//end while reading line
andrew@0 227 iss.clear();
andrew@0 228
andrew@0 229
andrew@0 230 }//end while
andrew@0 231
andrew@2 232
andrew@0 233 printf("There are %i BEAT annotations\n", (int)beatTimes.size());
andrew@0 234
andrew@0 235 }
andrew@0 236
andrew@0 237 void RecordedMultipleAudio::printBeatTimes(){
andrew@0 238 for (int i = 0;i < beatTimes.size();i++){
andrew@0 239 printf("Beat[%i] = %f\n", i, beatTimes[i]);
andrew@0 240 }
andrew@0 241 }
andrew@0 242
andrew@0 243
andrew@0 244 void RecordedMultipleAudio::checkFileErrors(int channel){
andrew@0 245 int beatIndex = 0;
andrew@2 246 int cutoff = 60;//ms width to check
andrew@0 247 for (int i = 0;i < loadedAudioFiles[channel].onsetTimesMillis.size();i++){
andrew@2 248
andrew@2 249 printf("onset time %i ms %i frames ", (int)loadedAudioFiles[channel].onsetTimesMillis[i], (int)loadedAudioFiles[channel].onsetTimesFrames[i]);
andrew@2 250
andrew@0 251 while (beatIndex < beatTimes.size() && 1000.0*beatTimes[beatIndex] < loadedAudioFiles[channel].onsetTimesMillis[i] - cutoff) {
andrew@0 252 beatIndex++;
andrew@0 253 }
andrew@0 254 double error = (1000.0*beatTimes[beatIndex] - loadedAudioFiles[channel].onsetTimesMillis[i]);
andrew@0 255 if (fabs(error) < cutoff){
andrew@0 256 if (channel == 0)
andrew@0 257 printf("Pos: %i Beat Time %f Kick Time %f Error %f\n", beatIndex%4, 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
andrew@0 258 else
andrew@0 259 printf("Pos: %i Beat Time %f Snare Time %f Error %f\n", beatIndex%4, 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
andrew@0 260
andrew@0 261 }else{
andrew@0 262 if (channel == 0)
andrew@2 263 printf("Ch.0 Out of Beat: Kick Time %f beat error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
andrew@0 264 else
andrew@2 265 printf("Ch.2 Out of Beat: %f Snare Time %f best error %f\n", 1000.0*beatTimes[beatIndex], loadedAudioFiles[0].onsetTimesMillis[i], error);
andrew@0 266
andrew@0 267 }
andrew@0 268 }
andrew@0 269 }
andrew@0 270
andrew@0 271
andrew@0 272 #pragma mark -labelExactOnsets
andrew@0 273
andrew@0 274 void RecordedMultipleAudio::findBeatOnsets(){
andrew@0 275 //tries to find kicks on 1, 3; snares on 2,4
andrew@0 276 int beatIndex = 0;
andrew@0 277 int kickIndex = 0;
andrew@0 278 int snareIndex = 0;
andrew@0 279 double kickTime, snareTime;
andrew@0 280 int cutoff = 50;//ms width to check
andrew@0 281
andrew@0 282 onsetInfo.clear();
andrew@0 283
andrew@0 284 // kickErrors.clear();
andrew@0 285 // snareErrors.clear();
andrew@0 286
andrew@0 287 bool beatFound;
andrew@0 288 for (int k = 0;k < beatTimes.size();k++){
andrew@0 289 beatFound = false;
andrew@0 290 double newBeatTime = beatTimes[k]*1000.0;
andrew@0 291 int beatPosition = k % 4;
andrew@0 292 OnsetInformation information;
andrew@2 293 double bestBeatDifference = 1000;//i.e. high
andrew@0 294 switch (beatPosition) {
andrew@0 295 case 0: case 2://check for kick when it is on the `one' or 'three' (0 or 2 in our metrical position)
andrew@0 296 // printf("check %i kindex %i\n", beatPosition, kickIndex);
andrew@0 297 while (kickIndex < loadedAudioFiles[0].onsetTimesMillis.size() && loadedAudioFiles[0].onsetTimesMillis[kickIndex] < newBeatTime - cutoff){
andrew@0 298 kickIndex++;
andrew@0 299 kickTime = loadedAudioFiles[0].onsetTimesMillis[kickIndex];
andrew@0 300 // printf("checking beat[%i] %f kick %f error %f\n", k, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0));
andrew@2 301 if (fabs(kickTime - beatTimes[k]*1000.0) < cutoff && fabs(kickTime - beatTimes[k]*1000.0) < bestBeatDifference){
andrew@0 302 beatFound = true;
andrew@2 303 printf("beat[%i] pos %i time %f kick %f error %f\n", k, beatPosition, beatTimes[k]*1000.0, kickTime, (kickTime - beatTimes[k]*1000.0));
andrew@0 304
andrew@0 305 information.error = (kickTime - beatTimes[k]*1000.0);//FOR NOW ONLY
andrew@0 306 information.metricalPosition = beatPosition;
andrew@0 307 information.type = 0;
andrew@0 308 information.exactOnsetTime = kickTime;
andrew@2 309 bestBeatDifference = fabs(kickTime - beatTimes[k]*1000.0);
andrew@0 310 // exactBeatPositions.push_back(kickTime);
andrew@0 311 }
andrew@0 312 }
andrew@0 313
andrew@0 314 break;
andrew@0 315 case 1: case 3://snare
andrew@0 316 while (snareIndex < loadedAudioFiles[1].onsetTimesMillis.size() && loadedAudioFiles[1].onsetTimesMillis[snareIndex] < newBeatTime - cutoff ){
andrew@0 317 snareIndex++;
andrew@0 318 snareTime = loadedAudioFiles[1].onsetTimesMillis[snareIndex];
andrew@2 319 if (fabs(snareTime - beatTimes[k]*1000.0) < cutoff && fabs(snareTime - beatTimes[k]*1000.0) < bestBeatDifference){
andrew@0 320 beatFound = true;
andrew@0 321 // snareErrors.push_back((beatTimes[k]*1000.0 - snareTime));
andrew@0 322 information.error = (snareTime - beatTimes[k]*1000.0);
andrew@0 323 information.metricalPosition = beatPosition;//.push_back(beatPosition);
andrew@0 324 information.type = 1;
andrew@0 325 information.exactOnsetTime = snareTime;
andrew@2 326 bestBeatDifference = fabs(snareTime - beatTimes[k]*1000.0);
andrew@2 327 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));
andrew@0 328 // exactBeatPositions.push_back(snareTime);
andrew@0 329 }
andrew@0 330 }
andrew@0 331
andrew@0 332 break;
andrew@0 333 }
andrew@0 334 if (!beatFound){
andrew@0 335 information.type = -1;//not a kick or snare
andrew@0 336 information.exactOnsetTime = beatTimes[k]*1000.0;
andrew@0 337 information.metricalPosition = beatPosition;//.push_
andrew@0 338 // exactBeatPositions.push_back(beatTimes[k]*1000.0);//have to go with the annotated beat instead (no matching kick or snare)
andrew@0 339
andrew@0 340 printf("beat[%i] %f NOT FOUND, kicktime %f snaretime %f\n", k, beatTimes[k]*1000.0, kickTime, snareTime );
andrew@0 341 }
andrew@0 342
andrew@0 343 onsetInfo.push_back(information);
andrew@0 344
andrew@0 345 }//end for all beat annotations
andrew@0 346
andrew@0 347 correctExactBeatTiming();//get rid of the first onset time
andrew@0 348
andrew@0 349 calculateTimingAnalysis();
andrew@0 350
andrew@2 351
andrew@2 352 //so our exact beat times are then information.exactOnsetTime
andrew@2 353
andrew@0 354 }
andrew@0 355
andrew@0 356 #pragma mark -doTimingAnalysis
andrew@0 357 void RecordedMultipleAudio::correctExactBeatTiming(){
andrew@0 358 //get rid of firtst onset time
andrew@0 359 if (onsetInfo.size() > 0){
andrew@0 360 timingOffset = onsetInfo[0].exactOnsetTime;//s[0];
andrew@0 361 double tmpPosn;
andrew@0 362 for (int i = 0;i < onsetInfo.size();i++){
andrew@0 363 onsetInfo[i].beatTimeToProcess = onsetInfo[i].exactOnsetTime - timingOffset;
andrew@0 364 printf("exact [%i] type %i %f, corrected %f\n", i, onsetInfo[i].type, onsetInfo[i].exactOnsetTime, onsetInfo[i].beatTimeToProcess );
andrew@0 365 }
andrew@0 366 }
andrew@0 367 }
andrew@0 368
andrew@0 369 void RecordedMultipleAudio::calculateTimingAnalysis(){
andrew@0 370
andrew@0 371 for (int i = 0;i < onsetInfo.size();i++){
andrew@0 372 drumTimingAnalyser.updateCostToPoint(onsetInfo[i].beatTimeToProcess, i);
andrew@0 373 //updatecounter is the beat position for this note event - can be used to do other kinds of durations than just simple beats
andrew@0 374
andrew@0 375 drumTimingAnalyser.beatPosition.push_back(onsetInfo[i].exactOnsetTime);
andrew@0 376 }
andrew@0 377 drumTimingAnalyser.processPathHistory();
andrew@0 378 drumTimingAnalyser.calculateTempoLimits();
andrew@0 379
andrew@0 380 getErrorTimesFromAnalysis();
andrew@0 381
andrew@0 382 alternativeKickRelativeAnalysis();
andrew@0 383
andrew@0 384 displayKickRelativeMedianErrors();//NB messes ther order of these
andrew@0 385
andrew@0 386 //this was how we did it in multimatch program
andrew@0 387 // timer.processPathHistory();
andrew@0 388 // timer.calculateTempoLimits();
andrew@0 389 // timer.exportTimingData();
andrew@0 390 // timer.exportProcessedBeatTimes(firstNoteTime);
andrew@0 391 }
andrew@0 392
andrew@0 393 void RecordedMultipleAudio::getErrorTimesFromAnalysis(){
andrew@0 394 printf("\nDrumTimingLoader: get error times from analysis!!!\n");
andrew@0 395 setUpErrorsByMetricalPosition();
andrew@0 396 //gets the errors from the drum timing analyser (i.e. ISMIR paper code) and attributes these to the onsets
andrew@0 397 for (int i = 0;i < drumTimingAnalyser.timingData.size();i++){
andrew@0 398 onsetInfo[i].error = drumTimingAnalyser.timingData[i][5];
andrew@0 399 onsetInfo[i].clickTime = drumTimingAnalyser.timingData[i][1] + timingOffset;//this is where teh timing analyser placed the click times
andrew@0 400 errorsByMetricalPosition[onsetInfo[i].metricalPosition].push_back(onsetInfo[i].error);
andrew@2 401 printf("beat %i metrical posn %i exact onset time %f click time %i error %i\n", i, onsetInfo[i].metricalPosition, onsetInfo[i].exactOnsetTime,
andrew@2 402 onsetInfo[i].clickTime, (int)onsetInfo[i].error);
andrew@0 403 }
andrew@0 404 displayMedianErrors();
andrew@0 405 }
andrew@0 406
andrew@0 407
andrew@0 408 void RecordedMultipleAudio::alternativeKickRelativeAnalysis(){
andrew@0 409 printf("\n\nAnalysis Relative to the Kick Drum on the ONE\n");
andrew@0 410 //this sees kicks as ON the beat, looks at relative error of the three other beats if we chop the bar evenly
andrew@0 411
andrew@0 412 double recentBeatTime, currentTempo;
andrew@0 413 kickRelativeErrors.clear();
andrew@0 414 kickRelativeClickTimes.clear();
andrew@2 415 kickRelativeTempo.clear();
andrew@0 416
andrew@0 417 for (int i = 0;i < drumTimingAnalyser.timingData.size();i++){
andrew@0 418 int beatPosition = i%4;
andrew@2 419 if (beatPosition == 0){//then divide kicks and get even division
andrew@0 420 recentBeatTime = onsetInfo[i].exactOnsetTime;
andrew@0 421 if (i+4 < onsetInfo.size())
andrew@0 422 currentTempo = (onsetInfo[i+4].exactOnsetTime - onsetInfo[i].exactOnsetTime)/4.0;
andrew@0 423 printf("new beat time %f tempo %f\n", recentBeatTime, currentTempo);
andrew@0 424 }
andrew@0 425 double error = onsetInfo[i].exactOnsetTime - (recentBeatTime + beatPosition*currentTempo);
andrew@2 426 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);
andrew@0 427 kickRelativeErrors.push_back(error);
andrew@0 428 kickRelativeClickTimes.push_back(recentBeatTime + beatPosition*currentTempo);
andrew@2 429 kickRelativeTempo.push_back(currentTempo);
andrew@0 430 }
andrew@0 431 }
andrew@0 432
andrew@2 433 #pragma mark -exportInfo
andrew@0 434 void RecordedMultipleAudio::exportErrorInformation(){
andrew@0 435 printf("Export final timing information\n");
andrew@0 436
andrew@0 437 ofstream ofs(infoFilepath.c_str());
andrew@0 438 for (int i = 0;i < onsetInfo.size() && kickRelativeErrors.size();i++){// drumTimingAnalyser.timingData.size()
andrew@0 439 ofs << i << "," << (i%4) << "," << onsetInfo[i].exactOnsetTime << ",";
andrew@0 440 ofs << onsetInfo[i].clickTime << "," << onsetInfo[i].error << ",";//the error for the ISMIR timing analyser
andrew@0 441 ofs << kickRelativeClickTimes[i] << "," << kickRelativeErrors[i];//the click and error for beats evenly between kicks
andrew@0 442 ofs << endl;
andrew@0 443 }
andrew@0 444
andrew@0 445 }
andrew@0 446
andrew@2 447
andrew@2 448 void RecordedMultipleAudio::exportExactOnsetTimes(){
andrew@2 449 printf("Export exact beat times\n");
andrew@2 450
andrew@2 451 ofstream ofs(exactOnsetFilePath.c_str());
andrew@2 452 for (int i = 0;i < onsetInfo.size();i++){// drumTimingAnalyser.timingData.size()
andrew@2 453 ofs << onsetInfo[i].exactOnsetTime/1000.0 << endl;
andrew@2 454 if (printExportInfo)
andrew@2 455 printf("exporting exact beat times %f\n", onsetInfo[i].exactOnsetTime);
andrew@2 456 }
andrew@2 457 }
andrew@2 458
andrew@2 459 void RecordedMultipleAudio::exportKickRelativeTempoTimes(){
andrew@2 460 printf("Export kick relative Tempo times\n");
andrew@2 461
andrew@2 462 ofstream ofs(kickRelativeTempoFilePath.c_str());
andrew@2 463 for (int i = 0;i < kickRelativeTempo.size() && i < onsetInfo.size();i++){
andrew@2 464 ofs << onsetInfo[i].exactOnsetTime << "\t" << kickRelativeTempo[i] << endl;
andrew@2 465 if (printExportInfo)
andrew@2 466 printf("exporting tempo[%i]: onset %f %f\n", i, onsetInfo[i].exactOnsetTime, kickRelativeTempo[i]);
andrew@2 467 }
andrew@2 468 }
andrew@2 469
andrew@2 470 void RecordedMultipleAudio::exportKickRelativeErrorTimes(){
andrew@2 471 printf("Export kick relative Error times\n");
andrew@2 472
andrew@2 473 ofstream ofs(kickRelativeErrorsFilePath.c_str());
andrew@2 474 for (int i = 0;i < kickRelativeErrors.size() && i < onsetInfo.size();i++){
andrew@2 475 ofs << onsetInfo[i].exactOnsetTime << "\t" << kickRelativeErrors[i] << endl;
andrew@2 476 if (printExportInfo)
andrew@2 477 printf("exporting tempo[%i]: onset %f %f\n", i, onsetInfo[i].exactOnsetTime, kickRelativeErrors[i]);
andrew@2 478 }
andrew@2 479 }
andrew@2 480
andrew@2 481 void RecordedMultipleAudio::exportKickRelativeClickTimes(){
andrew@2 482 printf("Export kick relative click times\n");
andrew@2 483
andrew@2 484 ofstream ofs(kickRelativeClickFilePath.c_str());
andrew@2 485 for (int i = 0;i < kickRelativeClickTimes.size();i++){
andrew@2 486 ofs << kickRelativeClickTimes[i]/1000.0 << endl;
andrew@2 487 if (printExportInfo)
andrew@2 488 printf("exporting KD click [%i]:%f\n", i,kickRelativeClickTimes[i]);
andrew@2 489 }
andrew@2 490 }
andrew@2 491
andrew@2 492
andrew@2 493 void RecordedMultipleAudio::exportDrumTimerTempoTimes(){
andrew@2 494 printf("Export drum timing tempo times\n");
andrew@2 495
andrew@2 496 ofstream ofs(drumTimerTempoFilePath.c_str());
andrew@2 497 for (int i = 0;i < drumTimingAnalyser.timingData.size() && i < onsetInfo.size();i++){
andrew@2 498 ofs << onsetInfo[i].exactOnsetTime << "\t" << drumTimingAnalyser.timingData[i][0] << endl;
andrew@2 499 if (printExportInfo)
andrew@2 500 printf("exporting tempo[%i]: onset %f tempo %i\n", i, onsetInfo[i].exactOnsetTime, drumTimingAnalyser.timingData[i][0]);
andrew@2 501 }
andrew@2 502 }
andrew@2 503
andrew@2 504
andrew@2 505 void RecordedMultipleAudio::exportDrumTimerErrorTimes(){
andrew@2 506 printf("Export drum timing Error times\n");
andrew@2 507
andrew@2 508 ofstream ofs(drumTimerErrorsFilePath.c_str());
andrew@2 509 for (int i = 0;i < drumTimingAnalyser.timingData.size() && i < onsetInfo.size();i++){
andrew@2 510 ofs << onsetInfo[i].exactOnsetTime << "\t" << drumTimingAnalyser.timingData[i][5] << endl;
andrew@2 511 if (printExportInfo)
andrew@2 512 printf("exporting [%i]: onset %f error %i\n", i, onsetInfo[i].exactOnsetTime, drumTimingAnalyser.timingData[i][5]);
andrew@2 513 }
andrew@2 514 }
andrew@2 515
andrew@2 516
andrew@2 517 void RecordedMultipleAudio::exportDrumTimerClickTimes(){
andrew@2 518 printf("Export drum timing Click times\n");
andrew@2 519
andrew@2 520 ofstream ofs(drumTimerClickFilePath.c_str());
andrew@2 521 for (int i = 0;i < onsetInfo.size();i++){
andrew@2 522 ofs << onsetInfo[i].clickTime/1000.0 << endl;
andrew@2 523 if (printExportInfo)
andrew@2 524 printf("exporting click[%i] %i\n", i, onsetInfo[i].clickTime);
andrew@2 525 }
andrew@2 526 }
andrew@2 527
andrew@2 528
andrew@2 529
andrew@2 530
andrew@2 531
andrew@2 532
andrew@2 533
andrew@0 534 void RecordedMultipleAudio::printKickRelativeErrors(){
andrew@0 535 for (int i = 0;i < kickRelativeErrors.size();i++){
andrew@0 536 printf("KR error [%i] : %.1f\n", i, kickRelativeErrors[i]);
andrew@0 537 }
andrew@0 538 }
andrew@0 539
andrew@0 540 void RecordedMultipleAudio::setUpErrorsByMetricalPosition(){
andrew@0 541 //clear this matrix
andrew@0 542 errorsByMetricalPosition.clear();
andrew@0 543 for (int i = 0;i < 4;i++){
andrew@0 544 DoubleVector v;
andrew@0 545 errorsByMetricalPosition.push_back(v);
andrew@0 546 }
andrew@0 547
andrew@0 548 }
andrew@0 549
andrew@0 550 void RecordedMultipleAudio::displayMedianErrors(){
andrew@0 551 printf("Medians of the Decoded Tempo variations\n");
andrew@0 552 for (int i = 0;i < 4;i++){
andrew@0 553 //printErrorsForMetricalPosition(i);
andrew@0 554 std::sort(errorsByMetricalPosition[i].begin(), errorsByMetricalPosition[i].end());//sort vector
andrew@0 555 double median = errorsByMetricalPosition[i][(int)(errorsByMetricalPosition[i].size()/2)];
andrew@0 556 printf("median for metrical position %i is %f\n", i, median);
andrew@0 557 }
andrew@0 558 }
andrew@0 559
andrew@0 560
andrew@0 561 void RecordedMultipleAudio::displayKickRelativeMedianErrors(){
andrew@0 562 printf("Medians of the KR variations\n");
andrew@0 563
andrew@0 564 DoubleVector tmpKRErrors;
andrew@0 565
andrew@0 566
andrew@0 567 for (int i = 0;i < 4;i++){
andrew@0 568
andrew@0 569 tmpKRErrors.clear();
andrew@0 570 int index = 0;
andrew@0 571
andrew@0 572 while (index+i < kickRelativeErrors.size()) {
andrew@0 573 tmpKRErrors.push_back(kickRelativeErrors[index + i]);
andrew@0 574 index += 4;
andrew@0 575 }
andrew@0 576
andrew@0 577 // for (int k = 0;k < tmpKRErrors.size();k++)
andrew@0 578 // printf("kr %i [%i] = %f\n", i, k, tmpKRErrors[k]);
andrew@0 579
andrew@0 580 //printErrorsForMetricalPosition(i);
andrew@0 581 std::sort(tmpKRErrors.begin(), tmpKRErrors.end());//sort vector
andrew@0 582
andrew@0 583 // for (int k = 0;k < tmpKRErrors.size();k++)
andrew@0 584 // printf("sorted kr %i [%i] = %f\n", i, k, tmpKRErrors[k]);
andrew@0 585
andrew@0 586
andrew@0 587 double median = tmpKRErrors[(int)(tmpKRErrors.size()/2)];
andrew@0 588 printf("median for metrical position %i is %f\n", i, median);
andrew@0 589 }
andrew@0 590 }
andrew@0 591
andrew@0 592 void RecordedMultipleAudio::printErrorsForMetricalPosition(const int& i){
andrew@0 593 for (int k = 0;k < errorsByMetricalPosition[i].size();k++){
andrew@0 594 printf("metrical posn %i, [%i] = %f\n", i, k, errorsByMetricalPosition[i][k]);
andrew@0 595 }
andrew@0 596 }
andrew@0 597
andrew@0 598 #pragma mark -drawTracks
andrew@0 599
andrew@0 600 void RecordedMultipleAudio::drawTracks(){
andrew@0 601 if (drawWindow == 0){
andrew@0 602 for (int i = 0;i < numberOfAudioTracks;i++){
andrew@0 603 loadedAudioFiles[i].draw();
andrew@0 604 }
andrew@0 605 } else {
andrew@0 606 drumTimingAnalyser.drawTempoCurve();
andrew@0 607 }
andrew@2 608
andrew@2 609 // ofDrawBitmapString(ofToString(playPositionSeconds),20, 40);
andrew@0 610 }
andrew@0 611
andrew@0 612 #pragma mark -update
andrew@0 613 void RecordedMultipleAudio::updatePosition(){
andrew@0 614 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 615 loadedAudioFiles[i].updateToPlayPosition();
andrew@2 616
andrew@2 617 playPositionSeconds = samplesToSeconds(loadedAudioFiles[0].fileLoader.audioHolder.playPosition);
andrew@2 618 drumTimingAnalyser.updatePlayIndex(playPositionSeconds);
andrew@2 619
andrew@2 620
andrew@2 621 }
andrew@2 622
andrew@2 623 double RecordedMultipleAudio::samplesToSeconds(const double& samples){
andrew@2 624 return samples/44100.0;
andrew@0 625 }
andrew@0 626
andrew@0 627 void RecordedMultipleAudio::updatePositionToMillis(const double& millis){
andrew@0 628 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 629 loadedAudioFiles[i].updateToMillisPosition(millis);
andrew@0 630 }
andrew@0 631
andrew@0 632 void RecordedMultipleAudio::updatePlaybackPositionToMillis(const double& millis){
andrew@0 633 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 634 loadedAudioFiles[i].updatePlaybackPositionToMillis(millis);
andrew@0 635 }
andrew@0 636
andrew@0 637 void RecordedMultipleAudio::togglePlay(){
andrew@0 638 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 639 loadedAudioFiles[i].togglePlay();
andrew@0 640 }
andrew@0 641
andrew@0 642 void RecordedMultipleAudio::stop(){
andrew@0 643 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 644 loadedAudioFiles[i].stop();
andrew@0 645 }
andrew@0 646
andrew@0 647
andrew@0 648 void RecordedMultipleAudio::printInfo(){
andrew@0 649 loadedAudioFiles[0].fileLoader.onsetDetect.printChromaInfo();
andrew@0 650 loadedAudioFiles[0].printEvents();
andrew@0 651 }
andrew@0 652
andrew@2 653 #pragma mark -ScreenFunctions
andrew@0 654 void RecordedMultipleAudio::windowResized(const int& w, const int& h){
andrew@0 655 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 656 loadedAudioFiles[i].windowResized(w, h);
andrew@0 657 }
andrew@0 658
andrew@0 659 void RecordedMultipleAudio::zoomIn(){
andrew@0 660 if (drawWindow == 0){
andrew@0 661 printf("zoom in\n");
andrew@0 662 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 663 loadedAudioFiles[i].fileLoader.zoomIn();
andrew@0 664 }
andrew@0 665
andrew@0 666 if (drawWindow == 1)
andrew@0 667 drumTimingAnalyser.zoomIn();//numberOfPointsPerPage /= 2;
andrew@0 668 }
andrew@0 669
andrew@0 670 void RecordedMultipleAudio::zoomOut(){
andrew@0 671 printf("zoom out\n");
andrew@0 672 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@0 673 loadedAudioFiles[i].fileLoader.zoomOut();
andrew@0 674
andrew@0 675 if (drawWindow == 1)
andrew@0 676 drumTimingAnalyser.zoomOut();//numberOfPointsPerPage *= 2;
andrew@0 677
andrew@0 678 }
andrew@0 679
andrew@2 680 void RecordedMultipleAudio::switchScreens(){
andrew@2 681 for (int i = 0;i < numberOfAudioTracks;i++)
andrew@2 682 loadedAudioFiles[i].switchScreens();
andrew@2 683 }
andrew@0 684