andrew@43
|
1 /*
|
andrew@43
|
2 * BeatAnnotationReader.cpp
|
andrew@43
|
3 * annotationResultCalculator
|
andrew@43
|
4 *
|
andrew@43
|
5 * Created by Andrew on 03/05/2012.
|
andrew@43
|
6 * Copyright 2012 QMUL. All rights reserved.
|
andrew@43
|
7 *
|
andrew@43
|
8 */
|
andrew@43
|
9
|
andrew@43
|
10 #include "BeatAnnotationReader.h"
|
andrew@43
|
11
|
andrew@43
|
12
|
andrew@43
|
13
|
andrew@43
|
14 void BeatAnnotationReader::readInBeatsFile(std::string& pathName){
|
andrew@43
|
15
|
andrew@43
|
16 // "/Users/andrew/Documents/work/MuseScore/RWC/ANNOTATION/RM-C002_annotation+WavPos.csv"
|
andrew@43
|
17 beatTimes.clear();
|
andrew@43
|
18
|
andrew@53
|
19 printf("- - - - \n\nREAD FILE %s\n", pathName.c_str());
|
andrew@43
|
20 ifstream file ( pathName.c_str());
|
andrew@43
|
21 string value, tmpLine;
|
andrew@43
|
22 stringstream iss;
|
andrew@43
|
23 int count = 0;
|
andrew@43
|
24
|
andrew@43
|
25 while ( file.good() )
|
andrew@43
|
26 {
|
andrew@43
|
27 getline(file, tmpLine);
|
andrew@43
|
28 iss << tmpLine;
|
andrew@43
|
29 int lineCount = 0;
|
andrew@43
|
30 // printf("tmp line %s\n", tmpLine.c_str());
|
andrew@43
|
31 while(getline ( iss, value, '\t' )){ // read a string until next comma: http://www.cplusplus.com/reference/string/getline/
|
andrew@43
|
32 // cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it
|
andrew@43
|
33 // printf("line:%s\n", value.c_str());
|
andrew@43
|
34 string::size_type start = value.find_first_not_of(" ,\t\v\n");
|
andrew@43
|
35
|
andrew@43
|
36 string part = value.substr(start, string::npos);
|
andrew@43
|
37
|
andrew@43
|
38 //printf("%s\n", firstpart.c_str());
|
andrew@43
|
39 if (lineCount == 0){
|
andrew@43
|
40 //printf("First part of line found '%s'\n", part.c_str());
|
andrew@43
|
41 double newBeatTime = atof(part.c_str());
|
andrew@43
|
42 beatTimes.push_back(newBeatTime);
|
andrew@43
|
43 }
|
andrew@43
|
44 lineCount++;
|
andrew@46
|
45
|
andrew@43
|
46 }//end while reading line
|
andrew@43
|
47 iss.clear();
|
andrew@43
|
48
|
andrew@43
|
49
|
andrew@43
|
50 }//end while
|
andrew@43
|
51
|
andrew@46
|
52 // printBeatTimes();
|
andrew@48
|
53 printf("There are %i BEAT annotations\n", (int)beatTimes.size());
|
andrew@43
|
54
|
andrew@43
|
55 }
|
andrew@43
|
56
|
andrew@43
|
57 void BeatAnnotationReader::printBeatTimes(){
|
andrew@43
|
58 for (int i = 0;i < beatTimes.size();i++){
|
andrew@43
|
59 printf("Beat[%i] = %f\n", i, beatTimes[i]);
|
andrew@43
|
60 }
|
andrew@43
|
61 }
|
andrew@43
|
62
|
andrew@43
|
63 void BeatAnnotationReader::readInMultiAlignmentFile(std::string pathName){
|
andrew@43
|
64
|
andrew@43
|
65 alignmentTimes.clear();
|
andrew@43
|
66
|
andrew@44
|
67 DoubleVector liveFileTimes;
|
andrew@43
|
68 DoubleVector multialignTimes;
|
andrew@44
|
69 DoubleVector playedAlignTimes;
|
andrew@44
|
70
|
andrew@43
|
71
|
andrew@43
|
72 ifstream file ( pathName.c_str());
|
andrew@43
|
73 string value, tmpLine;
|
andrew@43
|
74 stringstream iss;
|
andrew@43
|
75 int count = 0;
|
andrew@43
|
76
|
andrew@43
|
77 while ( file.good() )
|
andrew@43
|
78 {
|
andrew@43
|
79 getline(file, tmpLine);
|
andrew@43
|
80 iss << tmpLine;
|
andrew@43
|
81 int lineCount = 0;
|
andrew@43
|
82 // printf("tmp line %s\n", tmpLine.c_str());
|
andrew@43
|
83 while(getline ( iss, value, '\t' )){ // read a string until next comma: http://www.cplusplus.com/reference/string/getline/
|
andrew@43
|
84 // cout << string( value, 1, value.length()-2 ); // display value removing the first and the last character from it
|
andrew@43
|
85 // printf("line:%s\n", value.c_str());
|
andrew@43
|
86 string::size_type start = value.find_first_not_of(" ,\t\v\n");
|
andrew@43
|
87
|
andrew@43
|
88 string part = value.substr(start, string::npos);
|
andrew@43
|
89
|
andrew@43
|
90 //printf("%s\n", firstpart.c_str());
|
andrew@43
|
91 if (lineCount == 0){
|
andrew@46
|
92 // printf("First part of align found '%s'\n", part.c_str());
|
andrew@43
|
93 double newBeatTime = atof(part.c_str());
|
andrew@44
|
94 liveFileTimes.push_back(newBeatTime);
|
andrew@43
|
95 }
|
andrew@43
|
96 if (lineCount == 1){
|
andrew@46
|
97 // printf("Second part of align found '%s'\n", part.c_str());
|
andrew@43
|
98 double newAlignTime = atof(part.c_str());
|
andrew@43
|
99 multialignTimes.push_back(newAlignTime);
|
andrew@43
|
100
|
andrew@43
|
101 }
|
andrew@44
|
102
|
andrew@44
|
103 if (lineCount == 2){
|
andrew@46
|
104 // printf("Third part of align found '%s'\n", part.c_str());
|
andrew@44
|
105 double newAlignTime = atof(part.c_str());
|
andrew@44
|
106 playedAlignTimes.push_back(newAlignTime);
|
andrew@44
|
107
|
andrew@44
|
108 }
|
andrew@43
|
109 lineCount++;
|
andrew@43
|
110
|
andrew@43
|
111 }//end while reading line
|
andrew@43
|
112 iss.clear();
|
andrew@43
|
113
|
andrew@43
|
114
|
andrew@43
|
115 }//end while
|
andrew@43
|
116
|
andrew@44
|
117 alignmentTimes.push_back(liveFileTimes);
|
andrew@43
|
118 alignmentTimes.push_back(multialignTimes);
|
andrew@44
|
119 alignmentTimes.push_back(playedAlignTimes);
|
andrew@43
|
120 }
|
andrew@43
|
121
|
andrew@45
|
122
|
andrew@45
|
123 double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment){
|
andrew@45
|
124 //use our alignment Times to calculate error rekative to these ground truth times
|
andrew@45
|
125 errors.clear();
|
andrew@46
|
126 absoluteErrors.clear();
|
andrew@45
|
127
|
andrew@45
|
128 int alignmentLiveIndex = 0;
|
andrew@45
|
129 for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){
|
andrew@45
|
130 double time = liveBeatTimes[i];
|
andrew@45
|
131
|
andrew@45
|
132 //now need alignment at this time
|
andrew@45
|
133 //recorded, i.e. MAP estimate alignment, is alignmentTimes[1];
|
andrew@45
|
134 //getAlignmentErrorAtTime(time);
|
andrew@45
|
135
|
andrew@45
|
136 while (alignmentLiveIndex < alignmentTimes[0].size() && alignmentTimes[0][alignmentLiveIndex] < time) {
|
andrew@45
|
137 alignmentLiveIndex++;
|
andrew@45
|
138 }
|
andrew@45
|
139
|
andrew@45
|
140 while (alignmentLiveIndex > 0 && alignmentTimes[0][alignmentLiveIndex] > time) {
|
andrew@45
|
141 alignmentLiveIndex--;
|
andrew@45
|
142 }
|
andrew@45
|
143 //now is less
|
andrew@45
|
144 double result = alignmentTimes[1][alignmentLiveIndex];
|
andrew@45
|
145
|
andrew@45
|
146 double fractionOfNext = 0;
|
andrew@45
|
147 if (alignmentLiveIndex < alignmentTimes[0].size() + 1 && time > alignmentTimes[0][alignmentLiveIndex]){
|
andrew@45
|
148 double numerator = time - alignmentTimes[0][alignmentLiveIndex];
|
andrew@45
|
149 double denom = alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex];
|
andrew@45
|
150 //printf("num %f / demon %f \n", numerator, denom);
|
andrew@45
|
151 fractionOfNext = (time - alignmentTimes[0][alignmentLiveIndex])/(alignmentTimes[0][alignmentLiveIndex+1] - alignmentTimes[0][alignmentLiveIndex]);
|
andrew@45
|
152 result += fractionOfNext * (alignmentTimes[1][alignmentLiveIndex+1] - alignmentTimes[1][alignmentLiveIndex]);
|
andrew@45
|
153 }
|
andrew@45
|
154 double error = result - groundTruthAlignment[i];//error relative to ground truth
|
andrew@45
|
155 error *= 1000.0;//now in ms
|
andrew@45
|
156 printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error);
|
andrew@45
|
157 // 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
|
158
|
andrew@45
|
159 // printf("aligns to above %.4f below %.4f\n", alignmentTimes[1][alignmentLiveIndex+1], alignmentTimes[1][alignmentLiveIndex]);
|
andrew@45
|
160
|
andrew@45
|
161 errors.push_back(error);
|
andrew@46
|
162 absoluteErrors.push_back(fabs(error));
|
andrew@45
|
163 }
|
andrew@46
|
164 std::sort(absoluteErrors.begin(), absoluteErrors.end());//sort vector
|
andrew@46
|
165 double median = absoluteErrors[(int)(absoluteErrors.size()/2)];
|
andrew@46
|
166 printf("median is %f\n", median);
|
andrew@45
|
167 }
|
andrew@45
|
168
|
andrew@45
|
169
|
andrew@45
|
170
|
andrew@45
|
171 double BeatAnnotationReader::calculateMedianError(const DoubleVector& liveBeatTimes, const DoubleVector& groundTruthAlignment, const DoubleVector& alignmentLiveTimes, const DoubleVector& alignmentRehearsalTimes){
|
andrew@45
|
172 //use our alignment Times to calculate error rekative to these ground truth times
|
andrew@45
|
173 errors.clear();
|
andrew@46
|
174 absoluteErrors.clear();
|
andrew@45
|
175
|
andrew@45
|
176 int alignmentLiveIndex = 0;
|
andrew@45
|
177 for (int i = 0;i < liveBeatTimes.size() && i < groundTruthAlignment.size();i++){
|
andrew@45
|
178 double time = liveBeatTimes[i];
|
andrew@45
|
179
|
andrew@45
|
180 //now need alignment at this time
|
andrew@45
|
181 //recorded, i.e. MAP estimate alignment, is alignmentRehearsalTimes;
|
andrew@45
|
182 //getAlignmentErrorAtTime(time);
|
andrew@45
|
183
|
andrew@45
|
184 while (alignmentLiveIndex < alignmentLiveTimes.size() && alignmentLiveTimes[alignmentLiveIndex] < time) {
|
andrew@45
|
185 alignmentLiveIndex++;
|
andrew@45
|
186 }
|
andrew@45
|
187
|
andrew@45
|
188 while (alignmentLiveIndex > 0 && alignmentLiveTimes[alignmentLiveIndex] > time) {
|
andrew@45
|
189 alignmentLiveIndex--;
|
andrew@45
|
190 }
|
andrew@45
|
191 //now is less
|
andrew@45
|
192 double result = alignmentRehearsalTimes[alignmentLiveIndex];
|
andrew@45
|
193
|
andrew@45
|
194 double fractionOfNext = 0;
|
andrew@45
|
195 if (alignmentLiveIndex < alignmentLiveTimes.size() + 1 && time > alignmentLiveTimes[alignmentLiveIndex]){
|
andrew@46
|
196 // double numerator = time - alignmentLiveTimes[alignmentLiveIndex];
|
andrew@46
|
197 // double denom = alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex];
|
andrew@46
|
198
|
andrew@45
|
199 fractionOfNext = (time - alignmentLiveTimes[alignmentLiveIndex])/(alignmentLiveTimes[alignmentLiveIndex+1] - alignmentLiveTimes[alignmentLiveIndex]);
|
andrew@45
|
200 result += fractionOfNext * (alignmentRehearsalTimes[alignmentLiveIndex+1] - alignmentRehearsalTimes[alignmentLiveIndex]);
|
andrew@45
|
201 }
|
andrew@45
|
202 double error = result - groundTruthAlignment[i];//error relative to ground truth
|
andrew@45
|
203 error *= 1000.0;//now in ms
|
andrew@46
|
204 // printf("live time %.4f align time %f ground truth %.3f error %.1f\n", time, result, groundTruthAlignment[i], error);
|
andrew@45
|
205
|
andrew@45
|
206 errors.push_back(error);
|
andrew@46
|
207 absoluteErrors.push_back(fabs(error));
|
andrew@45
|
208 }
|
andrew@46
|
209 std::sort(absoluteErrors.begin(), absoluteErrors.end());//sort vector
|
andrew@46
|
210 double median = absoluteErrors[(int)(absoluteErrors.size()/2)];
|
andrew@46
|
211 printf("median abs error is %f\n", median);
|
andrew@45
|
212 }
|
andrew@45
|
213
|
andrew@45
|
214
|