andrew@43: /* andrew@43: * BeatAnnotationReader.cpp andrew@43: * annotationResultCalculator andrew@43: * andrew@43: * Created by Andrew on 03/05/2012. andrew@43: * Copyright 2012 QMUL. All rights reserved. andrew@43: * andrew@43: */ andrew@43: andrew@43: #include "BeatAnnotationReader.h" andrew@43: andrew@43: andrew@43: andrew@43: void BeatAnnotationReader::readInBeatsFile(std::string& pathName){ andrew@43: andrew@43: // "/Users/andrew/Documents/work/MuseScore/RWC/ANNOTATION/RM-C002_annotation+WavPos.csv" andrew@43: beatTimes.clear(); andrew@43: andrew@53: printf("- - - - \n\nREAD FILE %s\n", pathName.c_str()); andrew@43: ifstream file ( pathName.c_str()); andrew@43: string value, tmpLine; andrew@43: stringstream iss; andrew@43: int count = 0; andrew@43: andrew@43: while ( file.good() ) andrew@43: { andrew@43: getline(file, tmpLine); andrew@43: iss << tmpLine; andrew@43: int lineCount = 0; andrew@43: // printf("tmp line %s\n", tmpLine.c_str()); andrew@43: while(getline ( iss, value, '\t' )){ // read a string until next comma: http://www.cplusplus.com/reference/string/getline/ andrew@43: // cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it andrew@43: // printf("line:%s\n", value.c_str()); andrew@43: string::size_type start = value.find_first_not_of(" ,\t\v\n"); andrew@43: andrew@43: string part = value.substr(start, string::npos); andrew@43: andrew@43: //printf("%s\n", firstpart.c_str()); andrew@43: if (lineCount == 0){ andrew@43: //printf("First part of line found '%s'\n", part.c_str()); andrew@43: double newBeatTime = atof(part.c_str()); andrew@43: beatTimes.push_back(newBeatTime); andrew@43: } andrew@43: lineCount++; andrew@46: andrew@43: }//end while reading line andrew@43: iss.clear(); andrew@43: andrew@43: andrew@43: }//end while andrew@43: andrew@46: // printBeatTimes(); andrew@48: printf("There are %i BEAT annotations\n", (int)beatTimes.size()); andrew@43: andrew@43: } andrew@43: andrew@43: void BeatAnnotationReader::printBeatTimes(){ andrew@43: for (int i = 0;i < beatTimes.size();i++){ andrew@43: printf("Beat[%i] = %f\n", i, beatTimes[i]); andrew@43: } andrew@43: } andrew@43: andrew@43: void BeatAnnotationReader::readInMultiAlignmentFile(std::string pathName){ andrew@43: andrew@43: alignmentTimes.clear(); andrew@43: andrew@44: DoubleVector liveFileTimes; andrew@43: DoubleVector multialignTimes; andrew@44: DoubleVector playedAlignTimes; andrew@44: andrew@43: andrew@43: ifstream file ( pathName.c_str()); andrew@43: string value, tmpLine; andrew@43: stringstream iss; andrew@43: int count = 0; andrew@43: andrew@43: while ( file.good() ) andrew@43: { andrew@43: getline(file, tmpLine); andrew@43: iss << tmpLine; andrew@43: int lineCount = 0; andrew@43: // printf("tmp line %s\n", tmpLine.c_str()); andrew@43: while(getline ( iss, value, '\t' )){ // read a string until next comma: http://www.cplusplus.com/reference/string/getline/ andrew@43: // cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it andrew@43: // printf("line:%s\n", value.c_str()); andrew@43: string::size_type start = value.find_first_not_of(" ,\t\v\n"); andrew@43: andrew@43: string part = value.substr(start, string::npos); andrew@43: andrew@43: //printf("%s\n", firstpart.c_str()); andrew@43: if (lineCount == 0){ andrew@46: // printf("First part of align found '%s'\n", part.c_str()); andrew@43: double newBeatTime = atof(part.c_str()); andrew@44: liveFileTimes.push_back(newBeatTime); andrew@43: } andrew@43: if (lineCount == 1){ andrew@46: // printf("Second part of align found '%s'\n", part.c_str()); andrew@43: double newAlignTime = atof(part.c_str()); andrew@43: multialignTimes.push_back(newAlignTime); andrew@43: andrew@43: } andrew@44: andrew@44: if (lineCount == 2){ andrew@46: // printf("Third part of align found '%s'\n", part.c_str()); andrew@44: double newAlignTime = atof(part.c_str()); andrew@44: playedAlignTimes.push_back(newAlignTime); andrew@44: andrew@44: } andrew@43: lineCount++; andrew@43: andrew@43: }//end while reading line andrew@43: iss.clear(); andrew@43: andrew@43: andrew@43: }//end while andrew@43: andrew@44: alignmentTimes.push_back(liveFileTimes); andrew@43: alignmentTimes.push_back(multialignTimes); andrew@44: alignmentTimes.push_back(playedAlignTimes); andrew@43: } andrew@43: andrew@45: andrew@45: double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment){ andrew@45: //use our alignment Times to calculate error rekative to these ground truth times andrew@45: errors.clear(); andrew@46: absoluteErrors.clear(); andrew@45: andrew@45: int alignmentLiveIndex = 0; andrew@45: for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){ andrew@45: double time = liveBeatTimes[i]; andrew@45: andrew@45: //now need alignment at this time andrew@45: //recorded, i.e. MAP estimate alignment, is alignmentTimes[1]; andrew@45: //getAlignmentErrorAtTime(time); andrew@45: andrew@45: while (alignmentLiveIndex < alignmentTimes[0].size() && alignmentTimes[0][alignmentLiveIndex] < time) { andrew@45: alignmentLiveIndex++; andrew@45: } andrew@45: andrew@45: while (alignmentLiveIndex > 0 && alignmentTimes[0][alignmentLiveIndex] > time) { andrew@45: alignmentLiveIndex--; andrew@45: } andrew@45: //now is less andrew@45: double result = alignmentTimes[1][alignmentLiveIndex]; andrew@45: andrew@45: double fractionOfNext = 0; andrew@45: if (alignmentLiveIndex < alignmentTimes[0].size() + 1 && time > alignmentTimes[0][alignmentLiveIndex]){ andrew@45: double numerator = time - alignmentTimes[0][alignmentLiveIndex]; andrew@45: double denom = alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex]; andrew@45: //printf("num %f / demon %f \n", numerator, denom); andrew@45: fractionOfNext = (time - alignmentTimes[0][alignmentLiveIndex])/(alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex]); andrew@45: result += fractionOfNext * (alignmentTimes[1][alignmentLiveIndex+1] - alignmentTimes[1][alignmentLiveIndex]); andrew@45: } andrew@45: double error = result - groundTruthAlignment[i];//error relative to ground truth andrew@45: error *= 1000.0;//now in ms andrew@45: printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error); andrew@45: // printf("time %.4f align time %f frac %.3f albelow %.4f above %.4f error %.2f\n", time, result, fractionOfNext, alignmentTimes[0][alignmentLiveIndex], alignmentTimes[0][alignmentLiveIndex+1], error); andrew@45: andrew@45: // printf("aligns to above %.4f below %.4f\n", alignmentTimes[1][alignmentLiveIndex+1], alignmentTimes[1][alignmentLiveIndex]); andrew@45: andrew@45: errors.push_back(error); andrew@46: absoluteErrors.push_back(fabs(error)); andrew@45: } andrew@46: std::sort(absoluteErrors.begin(), absoluteErrors.end());//sort vector andrew@46: double median = absoluteErrors[(int)(absoluteErrors.size()/2)]; andrew@46: printf("median is %f\n", median); andrew@45: } andrew@45: andrew@45: andrew@45: andrew@45: double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment, const DoubleVector& alignmentLiveTimes, const DoubleVector& alignmentRehearsalTimes){ andrew@45: //use our alignment Times to calculate error rekative to these ground truth times andrew@45: errors.clear(); andrew@46: absoluteErrors.clear(); andrew@45: andrew@45: int alignmentLiveIndex = 0; andrew@45: for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){ andrew@45: double time = liveBeatTimes[i]; andrew@45: andrew@45: //now need alignment at this time andrew@45: //recorded, i.e. MAP estimate alignment, is alignmentRehearsalTimes; andrew@45: //getAlignmentErrorAtTime(time); andrew@45: andrew@45: while (alignmentLiveIndex < alignmentLiveTimes.size() && alignmentLiveTimes[alignmentLiveIndex] < time) { andrew@45: alignmentLiveIndex++; andrew@45: } andrew@45: andrew@45: while (alignmentLiveIndex > 0 && alignmentLiveTimes[alignmentLiveIndex] > time) { andrew@45: alignmentLiveIndex--; andrew@45: } andrew@45: //now is less andrew@45: double result = alignmentRehearsalTimes[alignmentLiveIndex]; andrew@45: andrew@45: double fractionOfNext = 0; andrew@45: if (alignmentLiveIndex < alignmentLiveTimes.size() + 1 && time > alignmentLiveTimes[alignmentLiveIndex]){ andrew@46: // double numerator = time - alignmentLiveTimes[alignmentLiveIndex]; andrew@46: // double denom = alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex]; andrew@46: andrew@45: fractionOfNext = (time - alignmentLiveTimes[alignmentLiveIndex])/(alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex]); andrew@45: result += fractionOfNext * (alignmentRehearsalTimes[alignmentLiveIndex+1] - alignmentRehearsalTimes[alignmentLiveIndex]); andrew@45: } andrew@45: double error = result - groundTruthAlignment[i];//error relative to ground truth andrew@45: error *= 1000.0;//now in ms andrew@46: // printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error); andrew@45: andrew@45: errors.push_back(error); andrew@46: absoluteErrors.push_back(fabs(error)); andrew@45: } andrew@46: std::sort(absoluteErrors.begin(), absoluteErrors.end());//sort vector andrew@46: double median = absoluteErrors[(int)(absoluteErrors.size()/2)]; andrew@46: printf("median abs error is %f\n", median); andrew@45: } andrew@45: andrew@45: