andrew@2
|
1 /*
|
andrew@2
|
2 * PreciseOnsetVisualiser.cpp
|
andrew@2
|
3 * ofxPreciseOnsetDetectionOffline
|
andrew@2
|
4 *
|
andrew@2
|
5 * Created by Andrew Robertson on 28/12/2013.
|
andrew@2
|
6 * Copyright 2013 QMUL. All rights reserved.
|
andrew@2
|
7 *
|
andrew@2
|
8 */
|
andrew@2
|
9
|
andrew@2
|
10 #include "PreciseOnsetVisualiser.h"
|
andrew@2
|
11
|
andrew@2
|
12 PreciseOnsetVisualiser::PreciseOnsetVisualiser(){
|
andrew@2
|
13
|
andrew@2
|
14 }
|
andrew@2
|
15
|
andrew@2
|
16 PreciseOnsetVisualiser::~PreciseOnsetVisualiser(){
|
andrew@3
|
17 printf("deleting pointer in visualiser\n");
|
andrew@6
|
18 pod = NULL;
|
andrew@2
|
19 delete pod;
|
andrew@6
|
20
|
andrew@2
|
21 }
|
andrew@2
|
22
|
andrew@2
|
23 void PreciseOnsetVisualiser::newFile(){
|
andrew@2
|
24 resetWindow();
|
Venetian@7
|
25
|
Venetian@7
|
26 //problem example
|
Venetian@7
|
27 //soundPlay.loadSound("/Users/andrew/Music/Logic/GreenOnionsEvaluationThree/GreenOnionsEvaluationMetronome3/Audio Files/SM57_Metronome#13.aif");//.c_str());
|
Venetian@7
|
28
|
andrew@2
|
29 windowPress = 0;
|
Venetian@7
|
30 printf("Precise onset, loading...'%s'\n", pod->loadedFilename.c_str());
|
andrew@2
|
31 soundPlay.loadSound(pod->loadedFilename, false);
|
Venetian@7
|
32 stop();//sets it not playing at beginning
|
andrew@2
|
33 }
|
andrew@2
|
34
|
andrew@4
|
35 double PreciseOnsetVisualiser::windowWidth(){
|
andrew@4
|
36 return windowEnd - windowStart;
|
andrew@4
|
37 }
|
andrew@4
|
38
|
andrew@2
|
39 void PreciseOnsetVisualiser::update(){
|
andrew@6
|
40 currentPlayPosition = positionSeconds();
|
andrew@6
|
41 if (currentPlayPosition > windowEnd){
|
andrew@4
|
42 double tmp = windowWidth();
|
andrew@4
|
43 windowEnd += tmp;
|
andrew@4
|
44 windowStart += tmp;
|
andrew@4
|
45 //printf("Scrolling\n");
|
andrew@4
|
46 }
|
andrew@2
|
47
|
andrew@2
|
48 }
|
andrew@2
|
49
|
andrew@4
|
50
|
andrew@2
|
51 void PreciseOnsetVisualiser::draw(){
|
Venetian@7
|
52 ofSetLineWidth(1);
|
andrew@2
|
53 //if plotting use this, else comment out
|
andrew@2
|
54
|
andrew@2
|
55 ofSetColor(ofColor::white);
|
andrew@2
|
56 window.drawBackground();
|
andrew@2
|
57 ofSetColor(ofColor::black);
|
andrew@2
|
58 window.drawOutline();
|
andrew@4
|
59
|
Venetian@7
|
60 ofDrawBitmapString(title, window.x+60, window.y - 10);
|
Venetian@7
|
61
|
andrew@4
|
62 //draw df function
|
andrew@4
|
63 /*
|
andrew@4
|
64 int startIndex = 0;
|
andrew@4
|
65 while (startIndex < (int)pod->dfValues.size() && pod->frameIndexToSeconds(startIndex) < windowStart)
|
andrew@4
|
66 startIndex++;
|
andrew@4
|
67
|
andrew@4
|
68 int endIndex = 0;
|
andrew@4
|
69 while (endIndex < (int)pod->dfValues.size()-1 && pod->frameIndexToSeconds(endIndex) < windowEnd)
|
andrew@4
|
70 endIndex++;
|
andrew@4
|
71 */
|
andrew@4
|
72 ofSetColor(ofColor::tan);
|
andrew@4
|
73 // plotter.drawVector(pod->dfValues, startIndex, endIndex, window);
|
andrew@4
|
74 plotter.drawVector(pod->dfValues, round(pod->secondsToFrameIndex(windowStart)), round(pod->secondsToFrameIndex(windowEnd)), window);
|
Venetian@7
|
75
|
andrew@4
|
76 ofSetColor(ofColor::black);
|
andrew@4
|
77 ofDrawBitmapString(ofToString(round(pod->secondsToFrameIndex(windowStart)), 1), window.x, window.y-10);
|
andrew@4
|
78 ofDrawBitmapString(ofToString(round(pod->secondsToFrameIndex(windowEnd)), 1), window.x+window.width, window.y-10);
|
andrew@4
|
79
|
andrew@2
|
80 ofSetColor(ofColor::blue);
|
Venetian@7
|
81 // plotter.drawBeatStripes(pod->onsetLocations, window, windowStart, windowEnd);
|
Venetian@7
|
82 plotter.drawBeatStripes(pod->onsetList, window, windowStart, windowEnd);
|
Venetian@7
|
83 drawOnsetInfo(pod->onsetList, window, windowStart, windowEnd);
|
andrew@2
|
84
|
andrew@4
|
85 //play position
|
andrew@2
|
86 ofSetColor(ofColor::red);
|
andrew@3
|
87 plotter.drawStripe(positionSeconds(), window, windowStart, windowEnd);
|
andrew@2
|
88
|
andrew@4
|
89 ofSetColor(ofColor::black);
|
andrew@4
|
90 ofDrawBitmapString(ofToString(windowStart, 1), window.x, window.y+window.height+10);
|
andrew@4
|
91 ofDrawBitmapString(ofToString(windowEnd, 1), window.x+window.width, window.y+window.height+10);
|
andrew@4
|
92
|
andrew@2
|
93 }
|
andrew@2
|
94
|
Venetian@7
|
95 void PreciseOnsetVisualiser::drawOnsetInfo(std::vector<OnsetInfo> onsetList, ofxWindowRegion& window, double startTime, double endTime){
|
Venetian@7
|
96 ofSetColor(ofColor::darkBlue);
|
Venetian@7
|
97 if (endTime > startTime){
|
Venetian@7
|
98 int index = 0;
|
Venetian@7
|
99 while (index < onsetList.size() && onsetList[index].onsetLocation < startTime) {
|
Venetian@7
|
100 index++;
|
Venetian@7
|
101 }
|
Venetian@7
|
102
|
Venetian@7
|
103 int pos = max(0, window.x - 45);
|
Venetian@7
|
104 ofDrawBitmapString("onsetLocation", pos, window.y+window.height+10);
|
Venetian@7
|
105 ofDrawBitmapString("beatPosition", pos, window.y+window.height+30);
|
Venetian@7
|
106 ofDrawBitmapString("onsetType", pos, window.y+window.height+50);
|
Venetian@7
|
107 if (pod->isBass){
|
Venetian@7
|
108 ofDrawBitmapString("pitch", pos, window.y+window.height+70);
|
Venetian@7
|
109 ofDrawBitmapString("midiPitch", pos, window.y+window.height+90);
|
Venetian@7
|
110 ofDrawBitmapString("midiPrediction", pos, window.y+window.height+110);
|
Venetian@7
|
111 ofDrawBitmapString("midiName", pos, window.y+window.height+130);
|
Venetian@7
|
112 ofDrawBitmapString("exp timing", pos, window.y+window.height+150);
|
Venetian@7
|
113 }
|
Venetian@7
|
114
|
Venetian@7
|
115 while (index < onsetList.size() && onsetList[index].onsetLocation <= endTime){
|
Venetian@7
|
116 pos = window.width*((onsetList[index].onsetLocation - startTime)/(endTime - startTime));
|
Venetian@7
|
117 pos += window.x;
|
Venetian@7
|
118 int lineWidth = 20;
|
Venetian@7
|
119 ofDrawBitmapString(ofToString(onsetList[index].onsetLocation, 2), pos, window.y+window.height+10);
|
Venetian@7
|
120 ofDrawBitmapString(ofToString(onsetList[index].beatPosition, 0), pos, window.y+window.height+30);
|
Venetian@7
|
121 ofDrawBitmapString(ofToString(onsetList[index].onsetType, 0), pos, window.y+window.height+50);
|
Venetian@7
|
122 if (pod->isBass){
|
Venetian@7
|
123 ofDrawBitmapString(ofToString(onsetList[index].pitch, 1), pos, window.y+window.height+70);
|
Venetian@7
|
124 ofDrawBitmapString(ofToString(onsetList[index].midiPitch, 0), pos, window.y+window.height+90);
|
Venetian@7
|
125 if (onsetList[index].midiPrediction == onsetList[index].roundedPitch)
|
Venetian@7
|
126 ofSetColor(ofColor::darkGreen);
|
Venetian@7
|
127 else if (abs(onsetList[index].midiPrediction - onsetList[index].roundedPitch) == 12)
|
Venetian@7
|
128 ofSetColor(ofColor::orange);
|
Venetian@7
|
129 else
|
Venetian@7
|
130 ofSetColor(ofColor::darkRed);
|
Venetian@7
|
131
|
Venetian@7
|
132 ofDrawBitmapString(ofToString(onsetList[index].midiPrediction, 0), pos, window.y+window.height+110);
|
Venetian@7
|
133 ofSetColor(ofColor::darkBlue);
|
Venetian@7
|
134 ofDrawBitmapString(onsetList[index].midiName, pos, window.y+window.height+130);
|
Venetian@7
|
135 if (onsetList[index].expressiveTiming)
|
Venetian@7
|
136 ofDrawBitmapString(ofToString(1000.0*onsetList[index].expressiveTiming, 1), pos, window.y+window.height+150);
|
Venetian@7
|
137 }
|
Venetian@7
|
138
|
Venetian@7
|
139 // ofLine(pos, window.y, pos, window.y+window.height);
|
Venetian@7
|
140 index++;
|
Venetian@7
|
141 }
|
Venetian@7
|
142 }
|
Venetian@7
|
143 }
|
Venetian@7
|
144
|
Venetian@7
|
145
|
Venetian@7
|
146
|
andrew@3
|
147 double PreciseOnsetVisualiser::positionSeconds(){
|
andrew@3
|
148 return soundPlay.getPosition()*pod->samples/44100.;
|
andrew@3
|
149 }
|
andrew@3
|
150
|
andrew@2
|
151 //void PreciseOnsetVisualiser::drawOnsets(DoubleVector& onsetTimesSeconds, ofxWindowregion& window, double startTime, double endTime){
|
andrew@2
|
152 //}
|
andrew@2
|
153
|
andrew@2
|
154 void PreciseOnsetVisualiser::resetWindow(){
|
andrew@2
|
155 windowStart = 0;
|
andrew@3
|
156 windowEnd = 8;
|
andrew@3
|
157 // while (windowEnd < pod->samples/44100.)
|
andrew@3
|
158 // windowEnd *= 2;
|
andrew@3
|
159
|
Venetian@7
|
160 // windowEnd = pod->samples/44100.;
|
andrew@3
|
161
|
andrew@2
|
162 printf("reset: start %.1f end %.1f\n", windowStart, windowEnd);
|
andrew@2
|
163 }
|
andrew@2
|
164
|
andrew@2
|
165 void PreciseOnsetVisualiser::cropStart(){
|
andrew@3
|
166 if (soundPlay.getPositionMS()/1000. < windowEnd){
|
andrew@3
|
167 windowStart = soundPlay.getPositionMS()/1000.;
|
andrew@3
|
168 printf("s: start %.1f end %.1f\n", windowStart, windowEnd);
|
andrew@3
|
169 }
|
andrew@2
|
170 }
|
andrew@2
|
171
|
andrew@3
|
172 void PreciseOnsetVisualiser::cropStartSeconds(double& val){
|
andrew@3
|
173 if (val < windowEnd)
|
andrew@3
|
174 windowStart = val;
|
andrew@3
|
175 }
|
andrew@3
|
176
|
andrew@3
|
177 void PreciseOnsetVisualiser::cropEnd(){//crops to play position
|
andrew@3
|
178
|
andrew@3
|
179 if (soundPlay.getPositionMS()/1000. > windowStart){
|
andrew@3
|
180 windowEnd = soundPlay.getPositionMS()/1000.;
|
andrew@3
|
181 printf("crop end: start %.1f end %.1f\n", windowStart, windowEnd);
|
andrew@3
|
182 }
|
andrew@3
|
183 }
|
andrew@3
|
184
|
andrew@3
|
185
|
andrew@3
|
186 void PreciseOnsetVisualiser::cropEndSeconds(double& val){
|
andrew@3
|
187 if (val > windowStart)
|
andrew@3
|
188 windowEnd = val;
|
andrew@2
|
189
|
andrew@2
|
190 printf("crop end: start %.1f end %.1f\n", windowStart, windowEnd);
|
andrew@2
|
191 }
|
andrew@2
|
192
|
andrew@2
|
193
|
andrew@2
|
194 void PreciseOnsetVisualiser::mousePressed(int& x, int& y){
|
andrew@2
|
195 if (window.tapped(x, y)){
|
andrew@2
|
196 windowPress = windowStart + (windowEnd-windowStart)*(x - window.x)/window.width;
|
andrew@3
|
197 double newPos = windowPress/(double)(pod->samples/44100.);
|
andrew@3
|
198 printf("window position is %.1f new pos %f\n", windowPress, newPos);
|
andrew@3
|
199 soundPlay.setPositionMS(windowPress*1000.0);
|
andrew@2
|
200 }
|
andrew@2
|
201 }
|
andrew@2
|
202
|
andrew@2
|
203 void PreciseOnsetVisualiser::togglePlay(){
|
andrew@2
|
204 if (!paused ){
|
andrew@2
|
205 soundPlay.setPaused(true);
|
andrew@2
|
206 paused = true;
|
Venetian@7
|
207 //printf("was playing\n");
|
andrew@2
|
208 }
|
andrew@2
|
209 else {
|
andrew@2
|
210 soundPlay.setPaused(false);//
|
andrew@2
|
211 paused = false;
|
Venetian@7
|
212 //printf("was not playing\n");
|
andrew@2
|
213 }
|
andrew@3
|
214 }
|
andrew@2
|
215
|
andrew@3
|
216 void PreciseOnsetVisualiser::stop(){
|
andrew@3
|
217 soundPlay.stop();
|
andrew@3
|
218 //then get set to be played
|
andrew@3
|
219 soundPlay.play();
|
andrew@3
|
220 soundPlay.setPaused(true);
|
andrew@3
|
221 soundPlay.setPositionMS(windowStart*1000.0);
|
andrew@3
|
222 paused = true;
|
andrew@4
|
223 }
|
andrew@4
|
224
|
andrew@4
|
225 void PreciseOnsetVisualiser::zoomIn(){
|
andrew@4
|
226 double positionNow = positionSeconds();
|
andrew@4
|
227 if (positionNow > windowEnd){
|
andrew@4
|
228 double tmp = windowWidth();
|
andrew@4
|
229 windowEnd += windowWidth();
|
andrew@4
|
230 windowStart += tmp;
|
andrew@4
|
231 }
|
andrew@4
|
232
|
andrew@4
|
233 windowStart = positionNow - (windowEnd-windowStart)/4;
|
andrew@4
|
234 if (windowStart < 0)
|
andrew@4
|
235 windowStart = 0;
|
andrew@4
|
236 windowEnd = positionNow + (windowEnd-windowStart)/4;
|
andrew@4
|
237 }
|
andrew@4
|
238
|
andrew@4
|
239
|
andrew@4
|
240 void PreciseOnsetVisualiser::zoomOut(){
|
andrew@4
|
241 double positionNow = positionSeconds();
|
andrew@4
|
242 if (positionNow > windowEnd){
|
andrew@4
|
243 double tmp = windowWidth();
|
andrew@4
|
244 windowEnd += tmp;
|
andrew@4
|
245 windowStart += tmp;
|
andrew@4
|
246 }
|
andrew@4
|
247
|
andrew@4
|
248 windowStart = positionNow - (windowEnd-windowStart);
|
andrew@4
|
249 windowEnd = positionNow + (windowEnd-windowStart);
|
andrew@4
|
250 if (windowStart < 0)
|
andrew@4
|
251 windowStart = 0;
|
andrew@4
|
252 }
|
andrew@4
|
253
|
andrew@4
|
254 void PreciseOnsetVisualiser::scrollLeft(){
|
andrew@4
|
255 double tmp = windowWidth();
|
andrew@4
|
256 windowStart = max(0., windowStart - windowWidth()/2.);
|
andrew@4
|
257 windowEnd = windowStart + tmp;
|
andrew@4
|
258 checkPosition();
|
andrew@4
|
259 }
|
andrew@4
|
260
|
andrew@4
|
261
|
andrew@4
|
262 void PreciseOnsetVisualiser::scrollRight(){
|
andrew@4
|
263 double tmp = windowWidth();
|
andrew@4
|
264 windowStart = min( windowStart+tmp/2., pod->samples/44100.);
|
andrew@4
|
265 windowEnd = windowStart + tmp;
|
andrew@4
|
266 checkPosition();
|
andrew@4
|
267 }
|
andrew@4
|
268
|
andrew@6
|
269 void PreciseOnsetVisualiser::scrollRightSecs(double secs){
|
andrew@6
|
270 double positionNow = positionSeconds();
|
andrew@6
|
271 double newPosition = min(positionNow+secs, pod->samples/44100.);
|
andrew@6
|
272 soundPlay.setPositionMS(newPosition*1000.);
|
andrew@6
|
273 double tmp = windowWidth()/2.;
|
andrew@6
|
274 while (windowEnd < newPosition){
|
andrew@6
|
275 windowEnd += tmp;
|
andrew@6
|
276 windowStart += tmp;
|
andrew@6
|
277 }
|
andrew@6
|
278 }
|
andrew@6
|
279
|
andrew@6
|
280
|
andrew@6
|
281 void PreciseOnsetVisualiser::scrollLeftSecs(double secs){
|
andrew@6
|
282 double positionNow = positionSeconds();
|
andrew@6
|
283 double newPosition = max(positionNow-secs, 0.);
|
andrew@6
|
284 soundPlay.setPositionMS(newPosition*1000.);
|
andrew@6
|
285 double tmp = windowWidth()/2.;
|
andrew@6
|
286 while (windowStart > newPosition){
|
andrew@6
|
287 windowEnd -= tmp;
|
andrew@6
|
288 windowStart -= tmp;
|
andrew@6
|
289 }
|
andrew@6
|
290 }
|
andrew@6
|
291
|
andrew@6
|
292
|
andrew@4
|
293 void PreciseOnsetVisualiser::checkPosition(){
|
andrew@4
|
294 double positionNow = positionSeconds();
|
andrew@4
|
295 if (positionNow < windowStart || positionNow > windowEnd)
|
andrew@6
|
296 soundPlay.setPositionMS(windowStart*1000.);
|
andrew@6
|
297 }
|
andrew@6
|
298
|
andrew@6
|
299
|
andrew@6
|
300 void PreciseOnsetVisualiser::setPositionSeconds(double secs){
|
andrew@6
|
301 soundPlay.setPositionMS(secs*1000.);
|
andrew@6
|
302 double tmp = windowEnd - windowStart;
|
andrew@6
|
303 while (windowStart > max(0. , secs)){
|
andrew@6
|
304 windowStart -= tmp;
|
andrew@6
|
305 windowEnd -= tmp;
|
andrew@6
|
306 }
|
andrew@6
|
307 while (windowEnd < min(pod->samples/44100. , secs)){
|
andrew@6
|
308 windowStart += tmp;
|
andrew@6
|
309 windowEnd += tmp;
|
andrew@6
|
310 }
|
andrew@6
|
311 }
|
andrew@6
|
312
|
andrew@6
|
313 double PreciseOnsetVisualiser::lengthSeconds(){
|
andrew@6
|
314 return pod->samples/44100.;
|
andrew@6
|
315 }
|
Venetian@7
|
316
|
Venetian@7
|
317
|
Venetian@7
|
318 void PreciseOnsetVisualiser::keyPressed(int key){
|
Venetian@7
|
319 switch (key) {
|
Venetian@7
|
320 case 'r':
|
Venetian@7
|
321 resetWindow();
|
Venetian@7
|
322 break;
|
Venetian@7
|
323 case 's':
|
Venetian@7
|
324 cropStart();
|
Venetian@7
|
325 break;
|
Venetian@7
|
326 case 'e':
|
Venetian@7
|
327 cropEnd();
|
Venetian@7
|
328 break;
|
Venetian@7
|
329 case ' ':
|
Venetian@7
|
330 togglePlay();
|
Venetian@7
|
331 break;
|
Venetian@7
|
332 case OF_KEY_RETURN:
|
Venetian@7
|
333 stop();
|
Venetian@7
|
334
|
Venetian@7
|
335 break;
|
Venetian@7
|
336
|
Venetian@7
|
337 case OF_KEY_UP: case 'u':
|
Venetian@7
|
338 zoomIn();
|
Venetian@7
|
339 break;
|
Venetian@7
|
340 case OF_KEY_DOWN:
|
Venetian@7
|
341 zoomOut();
|
Venetian@7
|
342 break;
|
Venetian@7
|
343 case OF_KEY_RIGHT:
|
Venetian@7
|
344 scrollRight();
|
Venetian@7
|
345 break;
|
Venetian@7
|
346 case OF_KEY_LEFT:
|
Venetian@7
|
347 scrollLeft();
|
Venetian@7
|
348 break;
|
Venetian@7
|
349
|
Venetian@7
|
350 default:
|
Venetian@7
|
351 break;
|
Venetian@7
|
352 }
|
Venetian@7
|
353 }
|