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