andrew@33
|
1 /*
|
andrew@33
|
2 * CannamMidiFileLoader.cpp
|
andrew@33
|
3 * midi-score-follower
|
andrew@33
|
4 *
|
andrew@33
|
5 * Created by Andrew on 19/08/2011.
|
andrew@33
|
6 * Copyright 2011 QMUL. All rights reserved.
|
andrew@33
|
7 *
|
andrew@33
|
8 */
|
andrew@33
|
9
|
andrew@33
|
10 #include "MIDIFileReader.h"
|
andrew@33
|
11 #include "CannamMidiFileLoader.h"
|
andrew@33
|
12
|
andrew@33
|
13 CannamMidiFileLoader::CannamMidiFileLoader(){
|
andrew@35
|
14 chopBeginning = false;
|
andrew@33
|
15 firstTickTime = 0;
|
andrew@34
|
16 printMidiInfo = false;
|
andrew@33
|
17 }
|
andrew@33
|
18
|
andrew@33
|
19 int CannamMidiFileLoader::loadFile(std::string& filename, midiEventHolder& myMidiEvents){
|
andrew@33
|
20
|
andrew@33
|
21 noteOnIndex = 0;
|
andrew@33
|
22 firstTickTime = 0;
|
andrew@33
|
23 myMidiEvents.clearAllEvents();
|
andrew@35
|
24 beatsPerMeasure = 4;
|
andrew@35
|
25 numberOfBeatsAtLastPosition = 0;
|
andrew@35
|
26 lastBeatPosition = 0;
|
andrew@35
|
27
|
andrew@33
|
28 setTempoFromMidiValue(500000, myMidiEvents);//default is 120bpm
|
andrew@34
|
29
|
andrew@33
|
30 myMidiEvents.pulsesPerQuarternote = 240;//default
|
andrew@33
|
31 //myMidiEvents.measureVector.push_back(0);
|
andrew@33
|
32 //int main(int argc, char **argv)
|
andrew@33
|
33 //{
|
andrew@33
|
34 // if (argc != 2) {
|
andrew@33
|
35 // cerr << "Usage: midifile <file.mid>" << endl;
|
andrew@33
|
36 // return 1;
|
andrew@33
|
37 // }
|
andrew@33
|
38
|
andrew@33
|
39 // std::string filename = midiFileName;//argv[1];
|
andrew@33
|
40
|
andrew@33
|
41 MIDIFileReader fr(filename);
|
andrew@33
|
42
|
andrew@33
|
43 if (!fr.isOK()) {
|
andrew@33
|
44 std::cerr << "Error: " << fr.getError().c_str() << std::endl;
|
andrew@33
|
45 return 1;
|
andrew@33
|
46 }
|
andrew@33
|
47
|
andrew@33
|
48 MIDIComposition c = fr.load();
|
andrew@33
|
49
|
andrew@33
|
50 switch (fr.getFormat()) {
|
andrew@33
|
51 case MIDI_SINGLE_TRACK_FILE: cout << "Format: MIDI Single Track File" << endl; break;
|
andrew@33
|
52 case MIDI_SIMULTANEOUS_TRACK_FILE: cout << "Format: MIDI Simultaneous Track File" << endl; break;
|
andrew@33
|
53 case MIDI_SEQUENTIAL_TRACK_FILE: cout << "Format: MIDI Sequential Track File" << endl; break;
|
andrew@33
|
54 default: cout << "Format: Unknown MIDI file format?" << endl; break;
|
andrew@33
|
55 }
|
andrew@33
|
56
|
andrew@33
|
57 cout << "Tracks: " << c.size() << endl;
|
andrew@33
|
58
|
andrew@33
|
59 int td = fr.getTimingDivision();
|
andrew@33
|
60 if (td < 32768) {
|
andrew@33
|
61 if (printMidiInfo)
|
andrew@33
|
62 cout << "Timing division: " << fr.getTimingDivision() << " ppq" << endl;
|
andrew@33
|
63 myMidiEvents.pulsesPerQuarternote = fr.getTimingDivision();
|
andrew@33
|
64 ticksPerMeasure = myMidiEvents.pulsesPerQuarternote * 4;//default setting
|
andrew@33
|
65
|
andrew@33
|
66 } else {
|
andrew@33
|
67 int frames = 256 - (td >> 8);
|
andrew@33
|
68 int subframes = td & 0xff;
|
andrew@33
|
69 if (printMidiInfo)
|
andrew@33
|
70 cout << "SMPTE timing: " << frames << " fps, " << subframes << " subframes" << endl;
|
andrew@33
|
71 }
|
andrew@33
|
72
|
andrew@33
|
73 for (MIDIComposition::const_iterator i = c.begin(); i != c.end(); ++i) {
|
andrew@33
|
74 if (printMidiInfo)
|
andrew@33
|
75 cout << "Start of track: " << i->first+1 << endl;
|
andrew@33
|
76
|
andrew@33
|
77 for (MIDITrack::const_iterator j = i->second.begin(); j != i->second.end(); ++j) {
|
andrew@33
|
78
|
andrew@33
|
79 unsigned int t = j->getTime();
|
andrew@33
|
80 int ch = j->getChannelNumber();
|
andrew@33
|
81
|
andrew@33
|
82 if (j->isMeta()) {
|
andrew@33
|
83 int code = j->getMetaEventCode();
|
andrew@33
|
84 string name;
|
andrew@33
|
85 bool printable = true;
|
andrew@33
|
86 switch (code) {
|
andrew@33
|
87
|
andrew@33
|
88 case MIDI_END_OF_TRACK:
|
andrew@33
|
89 cout << t << ": End of track" << endl;
|
andrew@33
|
90 break;
|
andrew@33
|
91
|
andrew@33
|
92 case MIDI_TEXT_EVENT: name = "Text"; break;
|
andrew@33
|
93 case MIDI_COPYRIGHT_NOTICE: name = "Copyright"; break;
|
andrew@33
|
94 case MIDI_TRACK_NAME: name = "Track name"; break;
|
andrew@33
|
95 case MIDI_INSTRUMENT_NAME: name = "Instrument name"; break;
|
andrew@33
|
96 case MIDI_LYRIC: name = "Lyric"; break;
|
andrew@33
|
97 case MIDI_TEXT_MARKER: name = "Text marker"; break;
|
andrew@33
|
98 case MIDI_SEQUENCE_NUMBER: name = "Sequence number"; printable = false; break;
|
andrew@33
|
99 case MIDI_CHANNEL_PREFIX_OR_PORT: name = "Channel prefix or port"; printable = false; break;
|
andrew@33
|
100 case MIDI_CUE_POINT: name = "Cue point"; break;
|
andrew@33
|
101 case MIDI_CHANNEL_PREFIX: name = "Channel prefix"; printable = false; break;
|
andrew@33
|
102 case MIDI_SEQUENCER_SPECIFIC: name = "Sequencer specific"; printable = false; break;
|
andrew@33
|
103 case MIDI_SMPTE_OFFSET: name = "SMPTE offset"; printable = false; break;
|
andrew@33
|
104
|
andrew@33
|
105 case MIDI_SET_TEMPO:
|
andrew@33
|
106 {
|
andrew@33
|
107 int m0 = j->getMetaMessage()[0];
|
andrew@33
|
108 int m1 = j->getMetaMessage()[1];
|
andrew@33
|
109 int m2 = j->getMetaMessage()[2];
|
andrew@33
|
110 long tempo = (((m0 << 8) + m1) << 8) + m2;
|
andrew@33
|
111 //if (printMidiInfo)
|
andrew@33
|
112 cout << t << ": Tempo: " << 60000000.0 / double(tempo) << endl;
|
andrew@34
|
113 //setTempoFromMidiValue(tempo, myMidiEvents);
|
andrew@33
|
114 DoubleVector tmp;
|
andrew@33
|
115
|
andrew@34
|
116 /*
|
andrew@33
|
117 double lastTickInMillis = 0;
|
andrew@33
|
118 double millisTimeNow = lastTickInMillis;
|
andrew@33
|
119 int tickInterval = 0;
|
andrew@33
|
120 if (myMidiEvents.periodValues.size() > 0){
|
andrew@33
|
121 lastTickInMillis = myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][2];
|
andrew@33
|
122 tickInterval = (t - firstTickTime) - myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][0];
|
andrew@33
|
123 millisTimeNow = lastTickInMillis + (myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][1]*tickInterval);
|
andrew@33
|
124
|
andrew@33
|
125 }
|
andrew@33
|
126
|
andrew@33
|
127 if (!chopBeginning)
|
andrew@33
|
128 tmp.push_back(t);
|
andrew@33
|
129 else
|
andrew@33
|
130 tmp.push_back(t - firstTickTime);
|
andrew@33
|
131
|
andrew@33
|
132 tmp.push_back(60000000.0 / double(tempo));
|
andrew@33
|
133 tmp.push_back(millisTimeNow);
|
andrew@33
|
134 myMidiEvents.periodValues.push_back(tmp);
|
andrew@34
|
135 */
|
andrew@33
|
136
|
andrew@34
|
137 double lastTickInMillis = 0;
|
andrew@34
|
138 double millisTimeNow = lastTickInMillis;
|
andrew@34
|
139 int tickInterval = 0;
|
andrew@34
|
140 if (myMidiEvents.periodValues.size() > 0){
|
andrew@34
|
141 lastTickInMillis = myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][2];
|
andrew@34
|
142 tickInterval = t - myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][0];
|
andrew@34
|
143 millisTimeNow = lastTickInMillis + (myMidiEvents.periodValues[myMidiEvents.periodValues.size()-1][1]*tickInterval);
|
andrew@34
|
144
|
andrew@34
|
145 }
|
andrew@34
|
146
|
andrew@34
|
147 tmp.push_back(t);
|
andrew@34
|
148
|
andrew@34
|
149
|
andrew@34
|
150 tmp.push_back(60000000.0 / double(tempo));
|
andrew@34
|
151 double tmpTempoVal = 60000000.0 / double(tempo);
|
andrew@34
|
152 tmp.push_back(millisTimeNow);
|
andrew@34
|
153 //if (tmpTempoVal > 180.0)
|
andrew@34
|
154 myMidiEvents.periodValues.push_back(tmp);
|
andrew@34
|
155
|
andrew@34
|
156 printf("tick[%i]: TEMPO %d tempoVal %f : time now %f\n", t, tempo, tmpTempoVal, millisTimeNow);
|
andrew@33
|
157 //printf("period double is %f\n", myMidiEvents.period);
|
andrew@33
|
158
|
andrew@33
|
159 }
|
andrew@33
|
160 break;
|
andrew@33
|
161
|
andrew@33
|
162 case MIDI_TIME_SIGNATURE:
|
andrew@33
|
163 {
|
andrew@33
|
164 int numerator = j->getMetaMessage()[0];
|
andrew@33
|
165 int denominator = 1 << (int)j->getMetaMessage()[1];
|
andrew@33
|
166
|
andrew@33
|
167 newTimeSignature(t, numerator, denominator, myMidiEvents);
|
andrew@33
|
168
|
andrew@33
|
169 //if (printMidiInfo)
|
andrew@33
|
170 cout << t << ": Time signature: " << numerator << "/" << denominator << endl;
|
andrew@33
|
171 printf(" ticks %i Time signature: %i by %i \n", t, numerator , denominator );
|
andrew@33
|
172 }
|
andrew@33
|
173
|
andrew@33
|
174 case MIDI_KEY_SIGNATURE:
|
andrew@33
|
175 {
|
andrew@33
|
176 int accidentals = j->getMetaMessage()[0];
|
andrew@33
|
177 int isMinor = j->getMetaMessage()[1];
|
andrew@33
|
178 bool isSharp = accidentals < 0 ? false : true;
|
andrew@33
|
179 accidentals = accidentals < 0 ? -accidentals : accidentals;
|
andrew@33
|
180 if (printMidiInfo)
|
andrew@33
|
181 cout << t << ": Key signature: " << accidentals << " "
|
andrew@33
|
182 << (isSharp ?
|
andrew@33
|
183 (accidentals > 1 ? "sharps" : "sharp") :
|
andrew@33
|
184 (accidentals > 1 ? "flats" : "flat"))
|
andrew@33
|
185 << (isMinor ? ", minor" : ", major") << endl;
|
andrew@33
|
186 }
|
andrew@33
|
187
|
andrew@33
|
188 }
|
andrew@33
|
189
|
andrew@33
|
190
|
andrew@33
|
191 if (name != "") {
|
andrew@33
|
192 if (printable) {
|
andrew@33
|
193 cout << t << ": File meta event: code " << code
|
andrew@33
|
194 << ": " << name << ": \"" << j->getMetaMessage()
|
andrew@33
|
195 << "\"" << endl;
|
andrew@33
|
196 } else {
|
andrew@33
|
197 cout << t << ": File meta event: code " << code
|
andrew@33
|
198 << ": " << name << ": ";
|
andrew@33
|
199 for (int k = 0; k < j->getMetaMessage().length(); ++k) {
|
andrew@33
|
200 cout << (int)j->getMetaMessage()[k] << " ";
|
andrew@33
|
201 }
|
andrew@33
|
202 }
|
andrew@33
|
203 }
|
andrew@33
|
204 continue;
|
andrew@33
|
205 }
|
andrew@35
|
206 double newBeatLocation = 0;
|
andrew@33
|
207 switch (j->getMessageType()) {
|
andrew@33
|
208
|
andrew@33
|
209 case MIDI_NOTE_ON:
|
andrew@33
|
210 if (printMidiInfo)
|
andrew@33
|
211 cout << t << ": Note: channel " << ch
|
andrew@33
|
212 << " duration " << j->getDuration()
|
andrew@33
|
213 << " pitch " << j->getPitch()
|
andrew@33
|
214 << " velocity " << j->getVelocity()
|
andrew@33
|
215 << "event time " << myMidiEvents.getEventTimeMillis(t) << endl;
|
andrew@33
|
216
|
andrew@35
|
217 newBeatLocation = getBeatPositionForTickCount(t, myMidiEvents);
|
andrew@35
|
218
|
andrew@35
|
219 // printf("%i channel %i durn %i pitch %i vel %i event time %f beat pos %f\n", t, ch, (int)j->getDuration(), (int)j->getPitch(), (int)j->getVelocity(), myMidiEvents.getEventTimeMillis(t)
|
andrew@35
|
220 // , newBeatLocation);
|
andrew@35
|
221
|
andrew@35
|
222
|
andrew@35
|
223
|
andrew@35
|
224 // printf("Beat location %3.2f\n", newBeatLocation);
|
andrew@34
|
225
|
andrew@34
|
226 /*
|
andrew@33
|
227 if (noteOnIndex == 0 || t < firstTickTime){
|
andrew@33
|
228 //easier just to pick the minimum
|
andrew@33
|
229 firstTickTime = t;
|
andrew@33
|
230 printf("FIRST TICK TIME %i\n", firstTickTime);
|
andrew@33
|
231 }
|
andrew@33
|
232
|
andrew@33
|
233 noteOnIndex++;
|
andrew@34
|
234 */
|
andrew@33
|
235 v.clear();
|
andrew@33
|
236
|
andrew@33
|
237 // printf("note on at %i\n", t);
|
andrew@33
|
238
|
andrew@34
|
239 //if (!chopBeginning)
|
andrew@33
|
240 v.push_back(t);
|
andrew@34
|
241 //else
|
andrew@34
|
242 // v.push_back(t - firstTickTime);
|
andrew@33
|
243
|
andrew@33
|
244 v.push_back(j->getPitch());
|
andrew@33
|
245 v.push_back(j->getVelocity());
|
andrew@33
|
246 v.push_back(j->getDuration());
|
andrew@33
|
247 myMidiEvents.recordedNoteOnMatrix.push_back(v);
|
andrew@35
|
248 myMidiEvents.noteOnMatches.push_back(false);
|
andrew@35
|
249 myMidiEvents.beatPositions.push_back(newBeatLocation);
|
andrew@33
|
250
|
andrew@33
|
251
|
andrew@33
|
252 break;
|
andrew@33
|
253
|
andrew@33
|
254 case MIDI_POLY_AFTERTOUCH:
|
andrew@33
|
255 if (printMidiInfo)
|
andrew@33
|
256 cout << t << ": Polyphonic aftertouch: channel " << ch
|
andrew@33
|
257 << " pitch " << j->getPitch()
|
andrew@33
|
258 << " pressure " << j->getData2() << endl;
|
andrew@33
|
259 break;
|
andrew@33
|
260
|
andrew@33
|
261 case MIDI_CTRL_CHANGE:
|
andrew@33
|
262 {
|
andrew@33
|
263 int controller = j->getData1();
|
andrew@33
|
264 string name;
|
andrew@33
|
265 switch (controller) {
|
andrew@33
|
266 case MIDI_CONTROLLER_BANK_MSB: name = "Bank select MSB"; break;
|
andrew@33
|
267 case MIDI_CONTROLLER_VOLUME: name = "Volume"; break;
|
andrew@33
|
268 case MIDI_CONTROLLER_BANK_LSB: name = "Bank select LSB"; break;
|
andrew@33
|
269 case MIDI_CONTROLLER_MODULATION: name = "Modulation wheel"; break;
|
andrew@33
|
270 case MIDI_CONTROLLER_PAN: name = "Pan"; break;
|
andrew@33
|
271 case MIDI_CONTROLLER_SUSTAIN: name = "Sustain"; break;
|
andrew@33
|
272 case MIDI_CONTROLLER_RESONANCE: name = "Resonance"; break;
|
andrew@33
|
273 case MIDI_CONTROLLER_RELEASE: name = "Release"; break;
|
andrew@33
|
274 case MIDI_CONTROLLER_ATTACK: name = "Attack"; break;
|
andrew@33
|
275 case MIDI_CONTROLLER_FILTER: name = "Filter"; break;
|
andrew@33
|
276 case MIDI_CONTROLLER_REVERB: name = "Reverb"; break;
|
andrew@33
|
277 case MIDI_CONTROLLER_CHORUS: name = "Chorus"; break;
|
andrew@33
|
278 case MIDI_CONTROLLER_NRPN_1: name = "NRPN 1"; break;
|
andrew@33
|
279 case MIDI_CONTROLLER_NRPN_2: name = "NRPN 2"; break;
|
andrew@33
|
280 case MIDI_CONTROLLER_RPN_1: name = "RPN 1"; break;
|
andrew@33
|
281 case MIDI_CONTROLLER_RPN_2: name = "RPN 2"; break;
|
andrew@33
|
282 case MIDI_CONTROLLER_SOUNDS_OFF: name = "All sounds off"; break;
|
andrew@33
|
283 case MIDI_CONTROLLER_RESET: name = "Reset"; break;
|
andrew@33
|
284 case MIDI_CONTROLLER_LOCAL: name = "Local"; break;
|
andrew@33
|
285 case MIDI_CONTROLLER_ALL_NOTES_OFF: name = "All notes off"; break;
|
andrew@33
|
286 }
|
andrew@33
|
287 if (printMidiInfo)
|
andrew@33
|
288 cout << t << ": Controller change: channel " << ch
|
andrew@33
|
289 << " controller " << j->getData1();
|
andrew@33
|
290 if (name != "") cout << " (" << name << ")";
|
andrew@33
|
291 cout << " value " << j->getData2() << endl;
|
andrew@33
|
292 }
|
andrew@33
|
293 break;
|
andrew@33
|
294
|
andrew@33
|
295 case MIDI_PROG_CHANGE:
|
andrew@33
|
296 if (printMidiInfo)
|
andrew@33
|
297 cout << t << ": Program change: channel " << ch
|
andrew@33
|
298 << " program " << j->getData1() << endl;
|
andrew@33
|
299 break;
|
andrew@33
|
300
|
andrew@33
|
301 case MIDI_CHNL_AFTERTOUCH:
|
andrew@33
|
302 if (printMidiInfo)
|
andrew@33
|
303 cout << t << ": Channel aftertouch: channel " << ch
|
andrew@33
|
304 << " pressure " << j->getData1() << endl;
|
andrew@33
|
305 break;
|
andrew@33
|
306
|
andrew@33
|
307 case MIDI_PITCH_BEND:
|
andrew@33
|
308 if (printMidiInfo)
|
andrew@33
|
309 cout << t << ": Pitch bend: channel " << ch
|
andrew@33
|
310 << " value " << (int)j->getData2() * 128 + (int)j->getData1() << endl;
|
andrew@33
|
311 break;
|
andrew@33
|
312
|
andrew@33
|
313 case MIDI_SYSTEM_EXCLUSIVE:
|
andrew@33
|
314 if (printMidiInfo)
|
andrew@33
|
315 cout << t << ": System exclusive: code "
|
andrew@33
|
316 << (int)j->getMessageType() << " message length " <<
|
andrew@33
|
317 j->getMetaMessage().length() << endl;
|
andrew@33
|
318 break;
|
andrew@33
|
319
|
andrew@33
|
320
|
andrew@33
|
321 }
|
andrew@33
|
322
|
andrew@33
|
323
|
andrew@33
|
324 }
|
andrew@33
|
325
|
andrew@33
|
326
|
andrew@33
|
327 }
|
andrew@34
|
328 // if (printMidiInfo)
|
andrew@34
|
329 // myMidiEvents.printRecordedEvents();
|
andrew@33
|
330
|
andrew@33
|
331 //printMeasuresSoFar(myMidiEvents);
|
andrew@33
|
332
|
andrew@33
|
333 if (myMidiEvents.recordedNoteOnMatrix.size() > 0){
|
andrew@33
|
334
|
andrew@33
|
335 printf("END FILE MEASURE UPDATE\n");
|
andrew@33
|
336 updateMeasureToTickPosition(myMidiEvents.recordedNoteOnMatrix[myMidiEvents.recordedNoteOnMatrix.size()-1][0], myMidiEvents);
|
andrew@33
|
337 // printMeasuresSoFar(myMidiEvents);
|
andrew@33
|
338 }
|
andrew@33
|
339
|
andrew@33
|
340 // printf("|||||||||||||||||||||| \n\n\n\n\n\n\n");
|
andrew@33
|
341 myMidiEvents.reorderMatrixFromNoteTimes(myMidiEvents.recordedNoteOnMatrix);
|
andrew@33
|
342 myMidiEvents.correctTiming(myMidiEvents.recordedNoteOnMatrix);
|
andrew@33
|
343 myMidiEvents.doublecheckOrder(myMidiEvents.recordedNoteOnMatrix);
|
andrew@33
|
344
|
andrew@34
|
345 if (chopBeginning)
|
andrew@34
|
346 chopBeginningfromEvents(myMidiEvents);
|
andrew@34
|
347
|
andrew@33
|
348 createEventTiming(myMidiEvents);
|
andrew@33
|
349
|
andrew@33
|
350 printf("BEFORE DOING MEASURE UPDATE\n first tick pos is %i\n", firstTickTime);
|
andrew@33
|
351 // printMeasuresSoFar(myMidiEvents);
|
andrew@33
|
352 if (chopBeginning)
|
andrew@33
|
353 correctMeasuresTiming(myMidiEvents);
|
andrew@33
|
354
|
andrew@34
|
355 // if (printMidiInfo)
|
andrew@34
|
356 // myMidiEvents.printRecordedEvents();
|
andrew@33
|
357
|
andrew@33
|
358 printf("Duration of MIDI file is %f \n", myMidiEvents.recordedEventTimes[myMidiEvents.recordedEventTimes.size()-1]);
|
andrew@34
|
359 printf("And first note offset is %i ticks == %f msec \n", firstTickTime, firstNoteTime);
|
andrew@35
|
360 printUpToIndex(50, myMidiEvents);
|
andrew@33
|
361 //printMeasuresSoFar(myMidiEvents);
|
andrew@33
|
362
|
andrew@33
|
363 }//end cannam midi main
|
andrew@33
|
364
|
andrew@33
|
365
|
andrew@34
|
366 void CannamMidiFileLoader::chopBeginningfromEvents(midiEventHolder& myMidiEvents){
|
andrew@34
|
367
|
andrew@34
|
368 firstTickTime = myMidiEvents.recordedNoteOnMatrix[0][0];
|
andrew@34
|
369 firstNoteTime = myMidiEvents.getEventTimeMillis(myMidiEvents.recordedNoteOnMatrix[0][0]);
|
andrew@34
|
370 myMidiEvents.firstEventOffsetTimeMillis = firstNoteTime;
|
andrew@34
|
371
|
andrew@34
|
372 printf("BEFORE chop - FIRST NOTE IS %f and tick %i\n", firstNoteTime, firstTickTime);
|
andrew@34
|
373 // myMidiEvents.printRecordedEvents();
|
andrew@34
|
374
|
andrew@34
|
375 for (int i = 0;i < myMidiEvents.recordedNoteOnMatrix.size();i++){
|
andrew@34
|
376 myMidiEvents.recordedNoteOnMatrix[i][0] -= firstTickTime;
|
andrew@34
|
377 }
|
andrew@34
|
378
|
andrew@34
|
379 //here are period values, but we dont use them
|
andrew@34
|
380 for (int i = 0;i < myMidiEvents.periodValues.size();i++){
|
andrew@34
|
381 myMidiEvents.periodValues[i][0] -= firstTickTime;
|
andrew@34
|
382 myMidiEvents.periodValues[i][2] -= firstNoteTime;
|
andrew@34
|
383 printf("[%i], period values(%i):: @ %f is %f\n", (int)myMidiEvents.periodValues[i][0], i, myMidiEvents.periodValues[i][2], myMidiEvents.periodValues[i][1]);
|
andrew@34
|
384 }
|
andrew@34
|
385
|
andrew@34
|
386 printf("\n\n\nAFTER chop - \n");
|
andrew@35
|
387
|
andrew@35
|
388 //myMidiEvents.printRecordedEvents();
|
andrew@34
|
389
|
andrew@34
|
390 }
|
andrew@34
|
391
|
andrew@33
|
392 void CannamMidiFileLoader::createEventTiming( midiEventHolder& myMidiEvents){
|
andrew@33
|
393
|
andrew@33
|
394 long t;
|
andrew@34
|
395 // t = myMidiEvents.recordedNoteOnMatrix[0][0];
|
andrew@34
|
396 // firstTickTime = t;
|
andrew@34
|
397 // firstNoteTime = myMidiEvents.getEventTimeMillis(firstTickTime);
|
andrew@33
|
398
|
andrew@33
|
399 for (int i = 0; i < myMidiEvents.recordedNoteOnMatrix.size();i++){
|
andrew@33
|
400 t = myMidiEvents.recordedNoteOnMatrix[i][0];
|
andrew@33
|
401
|
andrew@33
|
402 if (!chopBeginning)
|
andrew@33
|
403 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t));
|
andrew@33
|
404 else {
|
andrew@34
|
405 myMidiEvents.recordedEventTimes.push_back(myMidiEvents.getEventTimeMillis(t));// - firstticktime
|
andrew@33
|
406 }
|
andrew@33
|
407 }
|
andrew@33
|
408
|
andrew@34
|
409
|
andrew@34
|
410
|
andrew@33
|
411 }
|
andrew@33
|
412
|
andrew@33
|
413 void CannamMidiFileLoader::setTempoFromMidiValue(long tempo, midiEventHolder& myMidiEvents){
|
andrew@33
|
414 myMidiEvents.tempo = 60000000.0 / double(tempo);
|
andrew@33
|
415 myMidiEvents.period = double(tempo)/1000.0;
|
andrew@33
|
416 myMidiEvents.ticksFactor = myMidiEvents.pulsesPerQuarternote / myMidiEvents.period;
|
andrew@33
|
417 }
|
andrew@33
|
418
|
andrew@33
|
419
|
andrew@33
|
420 void CannamMidiFileLoader::newTimeSignature(int ticks, int numerator, int denominator, midiEventHolder& myMidiEvents){
|
andrew@33
|
421
|
andrew@33
|
422 updateMeasureToTickPosition(ticks, myMidiEvents);
|
andrew@33
|
423
|
andrew@35
|
424 beatsPerMeasure = 4.0 * (float)numerator / denominator;
|
andrew@33
|
425 ticksPerMeasure = myMidiEvents.pulsesPerQuarternote * 4 * numerator / denominator;
|
andrew@33
|
426
|
andrew@33
|
427 }
|
andrew@33
|
428
|
andrew@33
|
429 void CannamMidiFileLoader::updateMeasureToTickPosition(int ticks, midiEventHolder& myMidiEvents){
|
andrew@33
|
430 printf("update measure at tick pos %i at tpm %i\n", ticks, ticksPerMeasure);
|
andrew@33
|
431
|
andrew@33
|
432 int measureVectorSize = myMidiEvents.measureVector.size();
|
andrew@33
|
433 int lastMeasurePosition = 0;
|
andrew@33
|
434 // if (chopBeginning)
|
andrew@33
|
435 // lastMeasurePosition = -1*firstTickTime;
|
andrew@33
|
436
|
andrew@33
|
437 if (measureVectorSize > 0)
|
andrew@33
|
438 lastMeasurePosition = myMidiEvents.measureVector[measureVectorSize-1];
|
andrew@33
|
439
|
andrew@33
|
440
|
andrew@33
|
441 while (lastMeasurePosition < ticks){
|
andrew@33
|
442 //update
|
andrew@33
|
443 lastMeasurePosition += ticksPerMeasure;
|
andrew@35
|
444 numberOfBeatsAtLastPosition += beatsPerMeasure;
|
andrew@35
|
445 lastBeatPosition = lastMeasurePosition;
|
andrew@33
|
446 myMidiEvents.measureVector.push_back(lastMeasurePosition);
|
andrew@35
|
447
|
andrew@33
|
448 // cout << "MEASURE " << myMidiEvents.measureVector.size()-1 << " is " << lastMeasurePosition << endl;
|
andrew@33
|
449 // printf("MEASURE %i is %i \n", (int)myMidiEvents.measureVector.size()-1 , lastMeasurePosition);
|
andrew@33
|
450 }
|
andrew@33
|
451 }
|
andrew@33
|
452
|
andrew@33
|
453
|
andrew@33
|
454 void CannamMidiFileLoader::correctMeasuresTiming(midiEventHolder& myMidiEvents){
|
andrew@33
|
455 //correct measures
|
andrew@33
|
456 for (int i = 0;i <myMidiEvents.measureVector.size();i++){
|
andrew@33
|
457 myMidiEvents.measureVector[i] -= firstTickTime;
|
andrew@33
|
458 }
|
andrew@33
|
459 printf("AFTER DOING MEASURE UPDATE\n");
|
andrew@34
|
460 //printMeasuresSoFar(myMidiEvents);
|
andrew@33
|
461 }
|
andrew@33
|
462
|
andrew@33
|
463 void CannamMidiFileLoader::printMeasuresSoFar(midiEventHolder& myMidiEvents){
|
andrew@33
|
464 for (int i = 0;i < myMidiEvents.measureVector.size();i++){
|
andrew@33
|
465 printf("measure [%i] at %i\n", i, myMidiEvents.measureVector[i]);
|
andrew@33
|
466 }
|
andrew@35
|
467 }
|
andrew@35
|
468
|
andrew@35
|
469 double CannamMidiFileLoader::getBeatPositionForTickCount(long t, midiEventHolder& myMidiEvents){
|
andrew@35
|
470 int lastMeasurePosition = 0;
|
andrew@35
|
471 if (myMidiEvents.measureVector.size() > 0)
|
andrew@35
|
472 lastMeasurePosition = myMidiEvents.measureVector[myMidiEvents.measureVector.size()-1];
|
andrew@35
|
473
|
andrew@35
|
474 int ticksSinceBeatCounted = t - lastMeasurePosition;
|
andrew@35
|
475 double beats = numberOfBeatsAtLastPosition;
|
andrew@35
|
476 beats += ticksSinceBeatCounted * beatsPerMeasure / ticksPerMeasure;
|
andrew@35
|
477 // printf("ticks since %i, beat per measure %f at %i tick per measure :: %f beats\n", ticksSinceBeatCounted, beatsPerMeasure, ticksPerMeasure, beats);
|
andrew@35
|
478 return beats;
|
andrew@35
|
479 }
|
andrew@35
|
480
|
andrew@35
|
481
|
andrew@35
|
482 void CannamMidiFileLoader::printUpToIndex(const int& index, midiEventHolder& myMidiEvents){
|
andrew@35
|
483 for (int i = 0;i < index;i++){
|
andrew@35
|
484 printf("Beat pos %f MIIDI %i event time %f\n", myMidiEvents.beatPositions[i], myMidiEvents.recordedNoteOnMatrix[i][1], myMidiEvents.recordedEventTimes[i]);
|
andrew@35
|
485 }
|
andrew@35
|
486 }
|