view annotationCalculatorSrc/BeatAnnotationReader.cpp @ 50:93d21c20cfbc

Added Markers and the ability to switch to these points in the file when playing
author Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk>
date Thu, 14 Jun 2012 20:04:49 +0100
parents 5359e2c0b0fb
children 5274e3b5479d
line wrap: on
line source
/*
 *  BeatAnnotationReader.cpp
 *  annotationResultCalculator
 *
 *  Created by Andrew on 03/05/2012.
 *  Copyright 2012 QMUL. All rights reserved.
 *
 */

#include "BeatAnnotationReader.h"



void BeatAnnotationReader::readInBeatsFile(std::string& pathName){
	
	// "/Users/andrew/Documents/work/MuseScore/RWC/ANNOTATION/RM-C002_annotation+WavPos.csv"
	beatTimes.clear();
	
		printf("READ 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
	
	//	printBeatTimes();
		printf("There are %i BEAT annotations\n", (int)beatTimes.size());
	
}

void BeatAnnotationReader::printBeatTimes(){
	for (int i = 0;i < beatTimes.size();i++){
		printf("Beat[%i] = %f\n", i, beatTimes[i]);
	}
}

void BeatAnnotationReader::readInMultiAlignmentFile(std::string pathName){
	
	alignmentTimes.clear();
	
	DoubleVector liveFileTimes;
	DoubleVector multialignTimes;
	DoubleVector playedAlignTimes;
	
	
	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 align found '%s'\n", part.c_str());
				double newBeatTime = atof(part.c_str());
				liveFileTimes.push_back(newBeatTime);
			}
			if (lineCount == 1){
	//			printf("Second part of align found '%s'\n", part.c_str());
				double newAlignTime = atof(part.c_str());
				multialignTimes.push_back(newAlignTime);
				
			}
			
			if (lineCount == 2){
	//			printf("Third part of align found '%s'\n", part.c_str());
				double newAlignTime = atof(part.c_str());
				playedAlignTimes.push_back(newAlignTime);
				
			}
			lineCount++;
		
		}//end while reading line
		iss.clear();
		
		
	}//end while
	
	alignmentTimes.push_back(liveFileTimes);
	alignmentTimes.push_back(multialignTimes);
	alignmentTimes.push_back(playedAlignTimes);
}


double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment){
	//use our alignment Times to calculate error rekative to these ground truth times
	errors.clear();
	absoluteErrors.clear();
	
	int alignmentLiveIndex = 0;
	for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){
		double time = liveBeatTimes[i];
	
		//now need alignment at this time
		//recorded, i.e. MAP estimate alignment, is alignmentTimes[1];
		//getAlignmentErrorAtTime(time);
		
		while (alignmentLiveIndex < alignmentTimes[0].size() && alignmentTimes[0][alignmentLiveIndex] < time) {
			alignmentLiveIndex++;
		}
		
		while (alignmentLiveIndex > 0 && alignmentTimes[0][alignmentLiveIndex] > time) {
			alignmentLiveIndex--;
		}
		//now is less
		double result = alignmentTimes[1][alignmentLiveIndex];
		
		double fractionOfNext = 0;
		if (alignmentLiveIndex < alignmentTimes[0].size() + 1 && time > alignmentTimes[0][alignmentLiveIndex]){
			double numerator = time - alignmentTimes[0][alignmentLiveIndex];
			double denom = alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex];
			//printf("num %f / demon %f \n", numerator, denom);
			fractionOfNext = (time - alignmentTimes[0][alignmentLiveIndex])/(alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex]);
			result += fractionOfNext * (alignmentTimes[1][alignmentLiveIndex+1] - alignmentTimes[1][alignmentLiveIndex]);
		}
		double error = result - groundTruthAlignment[i];//error relative to ground truth
		error *= 1000.0;//now in ms
		printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error);
	//	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);
		
	//	printf("aligns to above %.4f below %.4f\n", alignmentTimes[1][alignmentLiveIndex+1], alignmentTimes[1][alignmentLiveIndex]);
		
		errors.push_back(error);
		absoluteErrors.push_back(fabs(error));
	}
	std::sort(absoluteErrors.begin(), absoluteErrors.end());//sort vector
	double median = absoluteErrors[(int)(absoluteErrors.size()/2)];
	printf("median is %f\n", median);
}



double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment, const DoubleVector& alignmentLiveTimes, const DoubleVector& alignmentRehearsalTimes){
	//use our alignment Times to calculate error rekative to these ground truth times
	errors.clear();
	absoluteErrors.clear();
	
	int alignmentLiveIndex = 0;
	for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){
		double time = liveBeatTimes[i];
		
		//now need alignment at this time
		//recorded, i.e. MAP estimate alignment, is alignmentRehearsalTimes;
		//getAlignmentErrorAtTime(time);
		
		while (alignmentLiveIndex < alignmentLiveTimes.size() && alignmentLiveTimes[alignmentLiveIndex] < time) {
			alignmentLiveIndex++;
		}
		
		while (alignmentLiveIndex > 0 && alignmentLiveTimes[alignmentLiveIndex] > time) {
			alignmentLiveIndex--;
		}
		//now is less
		double result = alignmentRehearsalTimes[alignmentLiveIndex];
		
		double fractionOfNext = 0;
		if (alignmentLiveIndex < alignmentLiveTimes.size() + 1 && time > alignmentLiveTimes[alignmentLiveIndex]){
		//	double numerator = time - alignmentLiveTimes[alignmentLiveIndex];
		//	double denom = alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex];
		
			fractionOfNext = (time - alignmentLiveTimes[alignmentLiveIndex])/(alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex]);
			result += fractionOfNext * (alignmentRehearsalTimes[alignmentLiveIndex+1] - alignmentRehearsalTimes[alignmentLiveIndex]);
		}
		double error = result - groundTruthAlignment[i];//error relative to ground truth
		error *= 1000.0;//now in ms
	//	printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error);
		
		errors.push_back(error);
		absoluteErrors.push_back(fabs(error));
	}
	std::sort(absoluteErrors.begin(), absoluteErrors.end());//sort vector
	double median = absoluteErrors[(int)(absoluteErrors.size()/2)];
	printf("median abs error is %f\n", median);
}