Mercurial > hg > svcore
comparison data/fileio/MIDIFileReader.cpp @ 1429:48e9f538e6e9
Untabify
author | Chris Cannam |
---|---|
date | Thu, 01 Mar 2018 18:02:22 +0000 |
parents | 39271c98cbdd |
children | cee1be4fb8c1 |
comparison
equal
deleted
inserted
replaced
1428:87ae75da6527 | 1429:48e9f538e6e9 |
---|---|
56 //#define MIDI_DEBUG 1 | 56 //#define MIDI_DEBUG 1 |
57 | 57 |
58 | 58 |
59 MIDIFileReader::MIDIFileReader(QString path, | 59 MIDIFileReader::MIDIFileReader(QString path, |
60 MIDIFileImportPreferenceAcquirer *acquirer, | 60 MIDIFileImportPreferenceAcquirer *acquirer, |
61 sv_samplerate_t mainModelSampleRate) : | 61 sv_samplerate_t mainModelSampleRate) : |
62 m_smpte(false), | 62 m_smpte(false), |
63 m_timingDivision(0), | 63 m_timingDivision(0), |
64 m_fps(0), | 64 m_fps(0), |
65 m_subframes(0), | 65 m_subframes(0), |
66 m_format(MIDI_FILE_BAD_FORMAT), | 66 m_format(MIDI_FILE_BAD_FORMAT), |
72 m_fileSize(0), | 72 m_fileSize(0), |
73 m_mainModelSampleRate(mainModelSampleRate), | 73 m_mainModelSampleRate(mainModelSampleRate), |
74 m_acquirer(acquirer) | 74 m_acquirer(acquirer) |
75 { | 75 { |
76 if (parseFile()) { | 76 if (parseFile()) { |
77 m_error = ""; | 77 m_error = ""; |
78 } | 78 } |
79 } | 79 } |
80 | 80 |
81 MIDIFileReader::~MIDIFileReader() | 81 MIDIFileReader::~MIDIFileReader() |
82 { | 82 { |
83 for (MIDIComposition::iterator i = m_midiComposition.begin(); | 83 for (MIDIComposition::iterator i = m_midiComposition.begin(); |
84 i != m_midiComposition.end(); ++i) { | 84 i != m_midiComposition.end(); ++i) { |
85 | 85 |
86 for (MIDITrack::iterator j = i->second.begin(); | 86 for (MIDITrack::iterator j = i->second.begin(); |
87 j != i->second.end(); ++j) { | 87 j != i->second.end(); ++j) { |
88 delete *j; | 88 delete *j; |
89 } | 89 } |
90 | 90 |
91 i->second.clear(); | 91 i->second.clear(); |
92 } | 92 } |
93 | 93 |
94 m_midiComposition.clear(); | 94 m_midiComposition.clear(); |
95 } | 95 } |
96 | 96 |
108 | 108 |
109 long | 109 long |
110 MIDIFileReader::midiBytesToLong(const string& bytes) | 110 MIDIFileReader::midiBytesToLong(const string& bytes) |
111 { | 111 { |
112 if (bytes.length() != 4) { | 112 if (bytes.length() != 4) { |
113 throw MIDIException(tr("Wrong length for long data in MIDI stream (%1, should be %2)").arg(bytes.length()).arg(4)); | 113 throw MIDIException(tr("Wrong length for long data in MIDI stream (%1, should be %2)").arg(bytes.length()).arg(4)); |
114 } | 114 } |
115 | 115 |
116 long longRet = ((long)(((MIDIByte)bytes[0]) << 24)) | | 116 long longRet = ((long)(((MIDIByte)bytes[0]) << 24)) | |
117 ((long)(((MIDIByte)bytes[1]) << 16)) | | 117 ((long)(((MIDIByte)bytes[1]) << 16)) | |
118 ((long)(((MIDIByte)bytes[2]) << 8)) | | 118 ((long)(((MIDIByte)bytes[2]) << 8)) | |
123 | 123 |
124 int | 124 int |
125 MIDIFileReader::midiBytesToInt(const string& bytes) | 125 MIDIFileReader::midiBytesToInt(const string& bytes) |
126 { | 126 { |
127 if (bytes.length() != 2) { | 127 if (bytes.length() != 2) { |
128 throw MIDIException(tr("Wrong length for int data in MIDI stream (%1, should be %2)").arg(bytes.length()).arg(2)); | 128 throw MIDIException(tr("Wrong length for int data in MIDI stream (%1, should be %2)").arg(bytes.length()).arg(2)); |
129 } | 129 } |
130 | 130 |
131 int intRet = ((int)(((MIDIByte)bytes[0]) << 8)) | | 131 int intRet = ((int)(((MIDIByte)bytes[0]) << 8)) | |
132 ((int)(((MIDIByte)bytes[1]))); | 132 ((int)(((MIDIByte)bytes[1]))); |
133 return(intRet); | 133 return(intRet); |
140 // | 140 // |
141 MIDIByte | 141 MIDIByte |
142 MIDIFileReader::getMIDIByte() | 142 MIDIFileReader::getMIDIByte() |
143 { | 143 { |
144 if (!m_midiFile) { | 144 if (!m_midiFile) { |
145 throw MIDIException(tr("getMIDIByte called but no MIDI file open")); | 145 throw MIDIException(tr("getMIDIByte called but no MIDI file open")); |
146 } | 146 } |
147 | 147 |
148 if (m_midiFile->eof()) { | 148 if (m_midiFile->eof()) { |
149 throw MIDIException(tr("End of MIDI file encountered while reading")); | 149 throw MIDIException(tr("End of MIDI file encountered while reading")); |
150 } | 150 } |
153 throw MIDIException(tr("Attempt to get more bytes than expected on Track")); | 153 throw MIDIException(tr("Attempt to get more bytes than expected on Track")); |
154 } | 154 } |
155 | 155 |
156 char byte; | 156 char byte; |
157 if (m_midiFile->read(&byte, 1)) { | 157 if (m_midiFile->read(&byte, 1)) { |
158 --m_trackByteCount; | 158 --m_trackByteCount; |
159 return (MIDIByte)byte; | 159 return (MIDIByte)byte; |
160 } | 160 } |
161 | 161 |
162 throw MIDIException(tr("Attempt to read past MIDI file end")); | 162 throw MIDIException(tr("Attempt to read past MIDI file end")); |
163 } | 163 } |
164 | 164 |
169 // | 169 // |
170 string | 170 string |
171 MIDIFileReader::getMIDIBytes(unsigned long numberOfBytes) | 171 MIDIFileReader::getMIDIBytes(unsigned long numberOfBytes) |
172 { | 172 { |
173 if (!m_midiFile) { | 173 if (!m_midiFile) { |
174 throw MIDIException(tr("getMIDIBytes called but no MIDI file open")); | 174 throw MIDIException(tr("getMIDIBytes called but no MIDI file open")); |
175 } | 175 } |
176 | 176 |
177 if (m_midiFile->eof()) { | 177 if (m_midiFile->eof()) { |
178 throw MIDIException(tr("End of MIDI file encountered while reading")); | 178 throw MIDIException(tr("End of MIDI file encountered while reading")); |
179 } | 179 } |
210 // | 210 // |
211 long | 211 long |
212 MIDIFileReader::getNumberFromMIDIBytes(int firstByte) | 212 MIDIFileReader::getNumberFromMIDIBytes(int firstByte) |
213 { | 213 { |
214 if (!m_midiFile) { | 214 if (!m_midiFile) { |
215 throw MIDIException(tr("getNumberFromMIDIBytes called but no MIDI file open")); | 215 throw MIDIException(tr("getNumberFromMIDIBytes called but no MIDI file open")); |
216 } | 216 } |
217 | 217 |
218 long longRet = 0; | 218 long longRet = 0; |
219 MIDIByte midiByte; | 219 MIDIByte midiByte; |
220 | 220 |
221 if (firstByte >= 0) { | 221 if (firstByte >= 0) { |
222 midiByte = (MIDIByte)firstByte; | 222 midiByte = (MIDIByte)firstByte; |
223 } else if (m_midiFile->eof()) { | 223 } else if (m_midiFile->eof()) { |
224 return longRet; | 224 return longRet; |
225 } else { | 225 } else { |
226 midiByte = getMIDIByte(); | 226 midiByte = getMIDIByte(); |
227 } | 227 } |
228 | 228 |
229 longRet = midiByte; | 229 longRet = midiByte; |
230 if (midiByte & 0x80) { | 230 if (midiByte & 0x80) { |
231 longRet &= 0x7F; | 231 longRet &= 0x7F; |
232 do { | 232 do { |
233 midiByte = getMIDIByte(); | 233 midiByte = getMIDIByte(); |
234 longRet = (longRet << 7) + (midiByte & 0x7F); | 234 longRet = (longRet << 7) + (midiByte & 0x7F); |
235 } while (!m_midiFile->eof() && (midiByte & 0x80)); | 235 } while (!m_midiFile->eof() && (midiByte & 0x80)); |
236 } | 236 } |
237 | 237 |
238 return longRet; | 238 return longRet; |
239 } | 239 } |
240 | 240 |
244 // | 244 // |
245 bool | 245 bool |
246 MIDIFileReader::skipToNextTrack() | 246 MIDIFileReader::skipToNextTrack() |
247 { | 247 { |
248 if (!m_midiFile) { | 248 if (!m_midiFile) { |
249 throw MIDIException(tr("skipToNextTrack called but no MIDI file open")); | 249 throw MIDIException(tr("skipToNextTrack called but no MIDI file open")); |
250 } | 250 } |
251 | 251 |
252 string buffer, buffer2; | 252 string buffer, buffer2; |
253 m_trackByteCount = -1; | 253 m_trackByteCount = -1; |
254 m_decrementCount = false; | 254 m_decrementCount = false; |
255 | 255 |
256 while (!m_midiFile->eof() && (m_decrementCount == false)) { | 256 while (!m_midiFile->eof() && (m_decrementCount == false)) { |
257 buffer = getMIDIBytes(4); | 257 buffer = getMIDIBytes(4); |
258 if (buffer.compare(0, 4, MIDI_TRACK_HEADER) == 0) { | 258 if (buffer.compare(0, 4, MIDI_TRACK_HEADER) == 0) { |
259 m_trackByteCount = midiBytesToLong(getMIDIBytes(4)); | 259 m_trackByteCount = midiBytesToLong(getMIDIBytes(4)); |
260 m_decrementCount = true; | 260 m_decrementCount = true; |
261 } | 261 } |
262 } | 262 } |
263 | 263 |
264 if (m_trackByteCount == -1) { // we haven't found a track | 264 if (m_trackByteCount == -1) { // we haven't found a track |
265 return false; | 265 return false; |
266 } else { | 266 } else { |
282 SVDEBUG << "MIDIFileReader::open() : fileName = " << m_fileName.c_str() << endl; | 282 SVDEBUG << "MIDIFileReader::open() : fileName = " << m_fileName.c_str() << endl; |
283 #endif | 283 #endif |
284 | 284 |
285 // Open the file | 285 // Open the file |
286 m_midiFile = new ifstream(m_path.toLocal8Bit().data(), | 286 m_midiFile = new ifstream(m_path.toLocal8Bit().data(), |
287 ios::in | ios::binary); | 287 ios::in | ios::binary); |
288 | 288 |
289 if (!*m_midiFile) { | 289 if (!*m_midiFile) { |
290 m_error = "File not found or not readable."; | 290 m_error = "File not found or not readable."; |
291 m_format = MIDI_FILE_BAD_FORMAT; | 291 m_format = MIDI_FILE_BAD_FORMAT; |
292 delete m_midiFile; | 292 delete m_midiFile; |
293 m_midiFile = 0; | 293 m_midiFile = 0; |
294 return false; | 294 return false; |
295 } | 295 } |
296 | 296 |
297 bool retval = false; | 297 bool retval = false; |
298 | 298 |
299 try { | 299 try { |
300 | 300 |
301 // Set file size so we can count it off | 301 // Set file size so we can count it off |
302 // | 302 // |
303 m_midiFile->seekg(0, ios::end); | 303 m_midiFile->seekg(0, ios::end); |
304 std::streamoff off = m_midiFile->tellg(); | 304 std::streamoff off = m_midiFile->tellg(); |
305 m_fileSize = 0; | 305 m_fileSize = 0; |
306 if (off > 0) m_fileSize = off; | 306 if (off > 0) m_fileSize = off; |
307 m_midiFile->seekg(0, ios::beg); | 307 m_midiFile->seekg(0, ios::beg); |
308 | 308 |
309 // Parse the MIDI header first. The first 14 bytes of the file. | 309 // Parse the MIDI header first. The first 14 bytes of the file. |
310 if (!parseHeader(getMIDIBytes(14))) { | 310 if (!parseHeader(getMIDIBytes(14))) { |
311 m_format = MIDI_FILE_BAD_FORMAT; | 311 m_format = MIDI_FILE_BAD_FORMAT; |
312 m_error = "Not a MIDI file."; | 312 m_error = "Not a MIDI file."; |
313 goto done; | 313 goto done; |
314 } | 314 } |
315 | 315 |
316 unsigned int i = 0; | 316 unsigned int i = 0; |
317 | 317 |
318 for (unsigned int j = 0; j < m_numberOfTracks; ++j) { | 318 for (unsigned int j = 0; j < m_numberOfTracks; ++j) { |
319 | 319 |
320 #ifdef MIDI_DEBUG | 320 #ifdef MIDI_DEBUG |
321 SVDEBUG << "Parsing Track " << j << endl; | 321 SVDEBUG << "Parsing Track " << j << endl; |
322 #endif | 322 #endif |
323 | 323 |
324 if (!skipToNextTrack()) { | 324 if (!skipToNextTrack()) { |
325 #ifdef MIDI_DEBUG | 325 #ifdef MIDI_DEBUG |
326 SVDEBUG << "Couldn't find Track " << j << endl; | 326 SVDEBUG << "Couldn't find Track " << j << endl; |
327 #endif | 327 #endif |
328 m_error = "File corrupted or in non-standard format?"; | 328 m_error = "File corrupted or in non-standard format?"; |
329 m_format = MIDI_FILE_BAD_FORMAT; | 329 m_format = MIDI_FILE_BAD_FORMAT; |
330 goto done; | 330 goto done; |
331 } | 331 } |
332 | 332 |
333 #ifdef MIDI_DEBUG | 333 #ifdef MIDI_DEBUG |
334 SVDEBUG << "Track has " << m_trackByteCount << " bytes" << endl; | 334 SVDEBUG << "Track has " << m_trackByteCount << " bytes" << endl; |
335 #endif | 335 #endif |
336 | 336 |
337 // Run through the events taking them into our internal | 337 // Run through the events taking them into our internal |
338 // representation. | 338 // representation. |
339 if (!parseTrack(i)) { | 339 if (!parseTrack(i)) { |
340 #ifdef MIDI_DEBUG | 340 #ifdef MIDI_DEBUG |
341 SVDEBUG << "Track " << j << " parsing failed" << endl; | 341 SVDEBUG << "Track " << j << " parsing failed" << endl; |
342 #endif | 342 #endif |
343 m_error = "File corrupted or in non-standard format?"; | 343 m_error = "File corrupted or in non-standard format?"; |
344 m_format = MIDI_FILE_BAD_FORMAT; | 344 m_format = MIDI_FILE_BAD_FORMAT; |
345 goto done; | 345 goto done; |
346 } | 346 } |
347 | 347 |
348 ++i; // j is the source track number, i the destination | 348 ++i; // j is the source track number, i the destination |
349 } | 349 } |
350 | 350 |
351 m_numberOfTracks = i; | 351 m_numberOfTracks = i; |
352 retval = true; | 352 retval = true; |
353 | 353 |
354 } catch (MIDIException e) { | 354 } catch (MIDIException e) { |
355 | 355 |
356 SVDEBUG << "MIDIFileReader::open() - caught exception - " << e.what() << endl; | 356 SVDEBUG << "MIDIFileReader::open() - caught exception - " << e.what() << endl; |
357 m_error = e.what(); | 357 m_error = e.what(); |
358 } | 358 } |
359 | 359 |
360 done: | 360 done: |
361 m_midiFile->close(); | 361 m_midiFile->close(); |
362 delete m_midiFile; | 362 delete m_midiFile; |
365 | 365 |
366 // Convert the deltaTime to an absolute time since the track | 366 // Convert the deltaTime to an absolute time since the track |
367 // start. The addTime method returns the sum of the current | 367 // start. The addTime method returns the sum of the current |
368 // MIDI Event delta time plus the argument. | 368 // MIDI Event delta time plus the argument. |
369 | 369 |
370 unsigned long acc = 0; | 370 unsigned long acc = 0; |
371 | 371 |
372 for (MIDITrack::iterator i = m_midiComposition[track].begin(); | 372 for (MIDITrack::iterator i = m_midiComposition[track].begin(); |
373 i != m_midiComposition[track].end(); ++i) { | 373 i != m_midiComposition[track].end(); ++i) { |
374 acc = (*i)->addTime(acc); | 374 acc = (*i)->addTime(acc); |
375 } | 375 } |
376 | 376 |
377 if (consolidateNoteOffEvents(track)) { // returns true if some notes exist | 377 if (consolidateNoteOffEvents(track)) { // returns true if some notes exist |
378 m_loadableTracks.insert(track); | 378 m_loadableTracks.insert(track); |
379 } | 379 } |
380 } | 380 } |
381 | 381 |
382 for (unsigned int track = 0; track < m_numberOfTracks; ++track) { | 382 for (unsigned int track = 0; track < m_numberOfTracks; ++track) { |
383 updateTempoMap(track); | 383 updateTempoMap(track); |
384 } | 384 } |
400 return false; | 400 return false; |
401 } | 401 } |
402 | 402 |
403 if (midiHeader.compare(0, 4, MIDI_FILE_HEADER) != 0) { | 403 if (midiHeader.compare(0, 4, MIDI_FILE_HEADER) != 0) { |
404 #ifdef MIDI_DEBUG | 404 #ifdef MIDI_DEBUG |
405 SVDEBUG << "MIDIFileReader::parseHeader()" | 405 SVDEBUG << "MIDIFileReader::parseHeader()" |
406 << "- file header not found or malformed" | 406 << "- file header not found or malformed" |
407 << endl; | 407 << endl; |
408 #endif | 408 #endif |
409 return false; | 409 return false; |
410 } | 410 } |
411 | 411 |
412 if (midiBytesToLong(midiHeader.substr(4,4)) != 6L) { | 412 if (midiBytesToLong(midiHeader.substr(4,4)) != 6L) { |
413 #ifdef MIDI_DEBUG | 413 #ifdef MIDI_DEBUG |
414 SVDEBUG << "MIDIFileReader::parseHeader()" | 414 SVDEBUG << "MIDIFileReader::parseHeader()" |
415 << " - header length incorrect" | 415 << " - header length incorrect" |
416 << endl; | 416 << endl; |
417 #endif | 417 #endif |
418 return false; | 418 return false; |
419 } | 419 } |
420 | 420 |
421 m_format = (MIDIFileFormatType) midiBytesToInt(midiHeader.substr(8,2)); | 421 m_format = (MIDIFileFormatType) midiBytesToInt(midiHeader.substr(8,2)); |
472 | 472 |
473 bool firstTrack = true; | 473 bool firstTrack = true; |
474 | 474 |
475 while (!m_midiFile->eof() && (m_trackByteCount > 0)) { | 475 while (!m_midiFile->eof() && (m_trackByteCount > 0)) { |
476 | 476 |
477 if (eventCode < 0x80) { | 477 if (eventCode < 0x80) { |
478 #ifdef MIDI_DEBUG | 478 #ifdef MIDI_DEBUG |
479 SVDEBUG << "WARNING: Invalid event code " << eventCode | 479 SVDEBUG << "WARNING: Invalid event code " << eventCode |
480 << " in MIDI file" << endl; | 480 << " in MIDI file" << endl; |
481 #endif | 481 #endif |
482 throw MIDIException(tr("Invalid event code %1 found").arg(int(eventCode))); | 482 throw MIDIException(tr("Invalid event code %1 found").arg(int(eventCode))); |
483 } | 483 } |
484 | 484 |
485 deltaTime = getNumberFromMIDIBytes(); | 485 deltaTime = getNumberFromMIDIBytes(); |
486 | 486 |
487 #ifdef MIDI_DEBUG | 487 #ifdef MIDI_DEBUG |
488 SVDEBUG << "read delta time " << deltaTime << endl; | 488 SVDEBUG << "read delta time " << deltaTime << endl; |
489 #endif | 489 #endif |
490 | 490 |
491 // Get a single byte | 491 // Get a single byte |
492 midiByte = getMIDIByte(); | 492 midiByte = getMIDIByte(); |
493 | 493 |
494 if (!(midiByte & MIDI_STATUS_BYTE_MASK)) { | 494 if (!(midiByte & MIDI_STATUS_BYTE_MASK)) { |
495 | 495 |
496 if (runningStatus < 0) { | 496 if (runningStatus < 0) { |
497 throw MIDIException(tr("Running status used for first event in track")); | 497 throw MIDIException(tr("Running status used for first event in track")); |
498 } | 498 } |
499 | 499 |
500 eventCode = (MIDIByte)runningStatus; | 500 eventCode = (MIDIByte)runningStatus; |
501 data1 = midiByte; | 501 data1 = midiByte; |
502 | 502 |
503 #ifdef MIDI_DEBUG | 503 #ifdef MIDI_DEBUG |
504 SVDEBUG << "using running status (byte " << int(midiByte) << " found)" << endl; | 504 SVDEBUG << "using running status (byte " << int(midiByte) << " found)" << endl; |
505 #endif | 505 #endif |
506 } else { | 506 } else { |
507 #ifdef MIDI_DEBUG | 507 #ifdef MIDI_DEBUG |
508 SVDEBUG << "have new event code " << int(midiByte) << endl; | 508 SVDEBUG << "have new event code " << int(midiByte) << endl; |
509 #endif | 509 #endif |
510 eventCode = midiByte; | 510 eventCode = midiByte; |
511 data1 = getMIDIByte(); | 511 data1 = getMIDIByte(); |
512 } | 512 } |
513 | 513 |
514 if (eventCode == MIDI_FILE_META_EVENT) { | 514 if (eventCode == MIDI_FILE_META_EVENT) { |
515 | 515 |
516 metaEventCode = data1; | 516 metaEventCode = data1; |
517 messageLength = getNumberFromMIDIBytes(); | 517 messageLength = getNumberFromMIDIBytes(); |
518 | 518 |
519 //#ifdef MIDI_DEBUG | 519 //#ifdef MIDI_DEBUG |
520 SVDEBUG << "Meta event of type " << int(metaEventCode) << " and " << messageLength << " bytes found, putting on track " << metaTrack << endl; | 520 SVDEBUG << "Meta event of type " << int(metaEventCode) << " and " << messageLength << " bytes found, putting on track " << metaTrack << endl; |
521 //#endif | 521 //#endif |
522 metaMessage = getMIDIBytes(messageLength); | 522 metaMessage = getMIDIBytes(messageLength); |
523 | 523 |
524 long gap = accumulatedTime - trackTimeMap[metaTrack]; | 524 long gap = accumulatedTime - trackTimeMap[metaTrack]; |
525 accumulatedTime += deltaTime; | 525 accumulatedTime += deltaTime; |
526 deltaTime += gap; | 526 deltaTime += gap; |
527 trackTimeMap[metaTrack] = accumulatedTime; | 527 trackTimeMap[metaTrack] = accumulatedTime; |
528 | 528 |
529 MIDIEvent *e = new MIDIEvent(deltaTime, | 529 MIDIEvent *e = new MIDIEvent(deltaTime, |
530 MIDI_FILE_META_EVENT, | 530 MIDI_FILE_META_EVENT, |
531 metaEventCode, | 531 metaEventCode, |
532 metaMessage); | 532 metaMessage); |
533 | 533 |
534 m_midiComposition[metaTrack].push_back(e); | 534 m_midiComposition[metaTrack].push_back(e); |
535 | 535 |
536 if (metaEventCode == MIDI_TRACK_NAME) { | 536 if (metaEventCode == MIDI_TRACK_NAME) { |
537 m_trackNames[metaTrack] = metaMessage.c_str(); | 537 m_trackNames[metaTrack] = metaMessage.c_str(); |
538 } | 538 } |
539 | 539 |
540 } else { // non-meta events | 540 } else { // non-meta events |
541 | 541 |
542 runningStatus = eventCode; | 542 runningStatus = eventCode; |
543 | 543 |
544 MIDIEvent *midiEvent; | 544 MIDIEvent *midiEvent; |
545 | 545 |
546 int channel = (eventCode & MIDI_CHANNEL_NUM_MASK); | 546 int channel = (eventCode & MIDI_CHANNEL_NUM_MASK); |
547 if (channelTrackMap[channel] == -1) { | 547 if (channelTrackMap[channel] == -1) { |
548 if (!firstTrack) ++lastTrackNum; | 548 if (!firstTrack) ++lastTrackNum; |
549 else firstTrack = false; | 549 else firstTrack = false; |
550 channelTrackMap[channel] = lastTrackNum; | 550 channelTrackMap[channel] = lastTrackNum; |
551 } | 551 } |
552 | 552 |
553 unsigned int trackNum = channelTrackMap[channel]; | 553 unsigned int trackNum = channelTrackMap[channel]; |
554 | 554 |
555 // accumulatedTime is abs time of last event on any track; | 555 // accumulatedTime is abs time of last event on any track; |
556 // trackTimeMap[trackNum] is that of last event on this track | 556 // trackTimeMap[trackNum] is that of last event on this track |
557 | 557 |
558 long gap = accumulatedTime - trackTimeMap[trackNum]; | 558 long gap = accumulatedTime - trackTimeMap[trackNum]; |
559 accumulatedTime += deltaTime; | 559 accumulatedTime += deltaTime; |
560 deltaTime += gap; | 560 deltaTime += gap; |
561 trackTimeMap[trackNum] = accumulatedTime; | 561 trackTimeMap[trackNum] = accumulatedTime; |
562 | 562 |
563 switch (eventCode & MIDI_MESSAGE_TYPE_MASK) { | 563 switch (eventCode & MIDI_MESSAGE_TYPE_MASK) { |
564 | 564 |
565 case MIDI_NOTE_ON: | 565 case MIDI_NOTE_ON: |
566 case MIDI_NOTE_OFF: | 566 case MIDI_NOTE_OFF: |
570 | 570 |
571 // create and store our event | 571 // create and store our event |
572 midiEvent = new MIDIEvent(deltaTime, eventCode, data1, data2); | 572 midiEvent = new MIDIEvent(deltaTime, eventCode, data1, data2); |
573 | 573 |
574 /* | 574 /* |
575 SVDEBUG << "MIDI event for channel " << channel << " (track " | 575 SVDEBUG << "MIDI event for channel " << channel << " (track " |
576 << trackNum << ")" << endl; | 576 << trackNum << ")" << endl; |
577 midiEvent->print(); | 577 midiEvent->print(); |
578 */ | 578 */ |
579 | 579 |
580 | 580 |
581 m_midiComposition[trackNum].push_back(midiEvent); | 581 m_midiComposition[trackNum].push_back(midiEvent); |
582 | 582 |
583 if (midiEvent->getChannelNumber() == MIDI_PERCUSSION_CHANNEL) { | 583 if (midiEvent->getChannelNumber() == MIDI_PERCUSSION_CHANNEL) { |
584 m_percussionTracks.insert(trackNum); | 584 m_percussionTracks.insert(trackNum); |
585 } | 585 } |
586 | 586 |
587 break; | 587 break; |
588 | 588 |
589 case MIDI_PITCH_BEND: | 589 case MIDI_PITCH_BEND: |
590 data2 = getMIDIByte(); | 590 data2 = getMIDIByte(); |
603 | 603 |
604 case MIDI_SYSTEM_EXCLUSIVE: | 604 case MIDI_SYSTEM_EXCLUSIVE: |
605 messageLength = getNumberFromMIDIBytes(data1); | 605 messageLength = getNumberFromMIDIBytes(data1); |
606 | 606 |
607 #ifdef MIDI_DEBUG | 607 #ifdef MIDI_DEBUG |
608 SVDEBUG << "SysEx of " << messageLength << " bytes found" << endl; | 608 SVDEBUG << "SysEx of " << messageLength << " bytes found" << endl; |
609 #endif | 609 #endif |
610 | 610 |
611 metaMessage= getMIDIBytes(messageLength); | 611 metaMessage= getMIDIBytes(messageLength); |
612 | 612 |
613 if (MIDIByte(metaMessage[metaMessage.length() - 1]) != | 613 if (MIDIByte(metaMessage[metaMessage.length() - 1]) != |
642 } | 642 } |
643 } | 643 } |
644 } | 644 } |
645 | 645 |
646 if (lastTrackNum > metaTrack) { | 646 if (lastTrackNum > metaTrack) { |
647 for (unsigned int track = metaTrack + 1; track <= lastTrackNum; ++track) { | 647 for (unsigned int track = metaTrack + 1; track <= lastTrackNum; ++track) { |
648 m_trackNames[track] = QString("%1 <%2>") | 648 m_trackNames[track] = QString("%1 <%2>") |
649 .arg(m_trackNames[metaTrack]).arg(track - metaTrack + 1); | 649 .arg(m_trackNames[metaTrack]).arg(track - metaTrack + 1); |
650 } | 650 } |
651 } | 651 } |
652 | 652 |
653 return true; | 653 return true; |
654 } | 654 } |
655 | 655 |
662 { | 662 { |
663 bool notesOnTrack = false; | 663 bool notesOnTrack = false; |
664 bool noteOffFound; | 664 bool noteOffFound; |
665 | 665 |
666 for (MIDITrack::iterator i = m_midiComposition[track].begin(); | 666 for (MIDITrack::iterator i = m_midiComposition[track].begin(); |
667 i != m_midiComposition[track].end(); i++) { | 667 i != m_midiComposition[track].end(); i++) { |
668 | 668 |
669 if ((*i)->getMessageType() == MIDI_NOTE_ON && (*i)->getVelocity() > 0) { | 669 if ((*i)->getMessageType() == MIDI_NOTE_ON && (*i)->getVelocity() > 0) { |
670 | 670 |
671 notesOnTrack = true; | 671 notesOnTrack = true; |
672 noteOffFound = false; | 672 noteOffFound = false; |
673 | 673 |
674 for (MIDITrack::iterator j = i; | 674 for (MIDITrack::iterator j = i; |
675 j != m_midiComposition[track].end(); j++) { | 675 j != m_midiComposition[track].end(); j++) { |
676 | 676 |
677 if (((*j)->getChannelNumber() == (*i)->getChannelNumber()) && | 677 if (((*j)->getChannelNumber() == (*i)->getChannelNumber()) && |
678 ((*j)->getPitch() == (*i)->getPitch()) && | 678 ((*j)->getPitch() == (*i)->getPitch()) && |
679 ((*j)->getMessageType() == MIDI_NOTE_OFF || | 679 ((*j)->getMessageType() == MIDI_NOTE_OFF || |
680 ((*j)->getMessageType() == MIDI_NOTE_ON && | 680 ((*j)->getMessageType() == MIDI_NOTE_ON && |
681 (*j)->getVelocity() == 0x00))) { | 681 (*j)->getVelocity() == 0x00))) { |
682 | 682 |
683 (*i)->setDuration((*j)->getTime() - (*i)->getTime()); | 683 (*i)->setDuration((*j)->getTime() - (*i)->getTime()); |
692 | 692 |
693 // If no matching NOTE OFF has been found then set | 693 // If no matching NOTE OFF has been found then set |
694 // Event duration to length of track | 694 // Event duration to length of track |
695 // | 695 // |
696 if (!noteOffFound) { | 696 if (!noteOffFound) { |
697 MIDITrack::iterator j = m_midiComposition[track].end(); | 697 MIDITrack::iterator j = m_midiComposition[track].end(); |
698 --j; | 698 --j; |
699 (*i)->setDuration((*j)->getTime() - (*i)->getTime()); | 699 (*i)->setDuration((*j)->getTime() - (*i)->getTime()); |
700 } | 700 } |
701 } | 701 } |
702 } | 702 } |
703 | 703 |
704 return notesOnTrack; | 704 return notesOnTrack; |
705 } | 705 } |
710 MIDIFileReader::updateTempoMap(unsigned int track) | 710 MIDIFileReader::updateTempoMap(unsigned int track) |
711 { | 711 { |
712 SVDEBUG << "updateTempoMap for track " << track << " (" << m_midiComposition[track].size() << " events)" << endl; | 712 SVDEBUG << "updateTempoMap for track " << track << " (" << m_midiComposition[track].size() << " events)" << endl; |
713 | 713 |
714 for (MIDITrack::iterator i = m_midiComposition[track].begin(); | 714 for (MIDITrack::iterator i = m_midiComposition[track].begin(); |
715 i != m_midiComposition[track].end(); ++i) { | 715 i != m_midiComposition[track].end(); ++i) { |
716 | 716 |
717 if ((*i)->isMeta() && | 717 if ((*i)->isMeta() && |
718 (*i)->getMetaEventCode() == MIDI_SET_TEMPO) { | 718 (*i)->getMetaEventCode() == MIDI_SET_TEMPO) { |
719 | 719 |
720 MIDIByte m0 = (*i)->getMetaMessage()[0]; | 720 MIDIByte m0 = (*i)->getMetaMessage()[0]; |
721 MIDIByte m1 = (*i)->getMetaMessage()[1]; | 721 MIDIByte m1 = (*i)->getMetaMessage()[1]; |
722 MIDIByte m2 = (*i)->getMetaMessage()[2]; | 722 MIDIByte m2 = (*i)->getMetaMessage()[2]; |
723 | 723 |
724 long tempo = (((m0 << 8) + m1) << 8) + m2; | 724 long tempo = (((m0 << 8) + m1) << 8) + m2; |
725 | 725 |
726 SVDEBUG << "updateTempoMap: have tempo, it's " << tempo << " at " << (*i)->getTime() << endl; | 726 SVDEBUG << "updateTempoMap: have tempo, it's " << tempo << " at " << (*i)->getTime() << endl; |
727 | 727 |
728 if (tempo != 0) { | 728 if (tempo != 0) { |
729 double qpm = 60000000.0 / double(tempo); | 729 double qpm = 60000000.0 / double(tempo); |
730 m_tempoMap[(*i)->getTime()] = | 730 m_tempoMap[(*i)->getTime()] = |
731 TempoChange(RealTime::zeroTime, qpm); | 731 TempoChange(RealTime::zeroTime, qpm); |
732 } | 732 } |
733 } | 733 } |
734 } | 734 } |
735 } | 735 } |
736 | 736 |
737 void | 737 void |
742 double tempo = 120.0; | 742 double tempo = 120.0; |
743 int td = m_timingDivision; | 743 int td = m_timingDivision; |
744 if (td == 0) td = 96; | 744 if (td == 0) td = 96; |
745 | 745 |
746 for (TempoMap::iterator i = m_tempoMap.begin(); i != m_tempoMap.end(); ++i) { | 746 for (TempoMap::iterator i = m_tempoMap.begin(); i != m_tempoMap.end(); ++i) { |
747 | 747 |
748 unsigned long mtime = i->first; | 748 unsigned long mtime = i->first; |
749 unsigned long melapsed = mtime - lastMIDITime; | 749 unsigned long melapsed = mtime - lastMIDITime; |
750 double quarters = double(melapsed) / double(td); | 750 double quarters = double(melapsed) / double(td); |
751 double seconds = (60.0 * quarters) / tempo; | 751 double seconds = (60.0 * quarters) / tempo; |
752 | 752 |
753 RealTime t = lastRealTime + RealTime::fromSeconds(seconds); | 753 RealTime t = lastRealTime + RealTime::fromSeconds(seconds); |
754 | 754 |
755 i->second.first = t; | 755 i->second.first = t; |
756 | 756 |
757 lastRealTime = t; | 757 lastRealTime = t; |
758 lastMIDITime = mtime; | 758 lastMIDITime = mtime; |
759 tempo = i->second.second; | 759 tempo = i->second.second; |
760 } | 760 } |
761 } | 761 } |
762 | 762 |
763 RealTime | 763 RealTime |
764 MIDIFileReader::getTimeForMIDITime(unsigned long midiTime) const | 764 MIDIFileReader::getTimeForMIDITime(unsigned long midiTime) const |
767 RealTime tempoRealTime = RealTime::zeroTime; | 767 RealTime tempoRealTime = RealTime::zeroTime; |
768 double tempo = 120.0; | 768 double tempo = 120.0; |
769 | 769 |
770 TempoMap::const_iterator i = m_tempoMap.lower_bound(midiTime); | 770 TempoMap::const_iterator i = m_tempoMap.lower_bound(midiTime); |
771 if (i != m_tempoMap.begin()) { | 771 if (i != m_tempoMap.begin()) { |
772 --i; | 772 --i; |
773 tempoMIDITime = i->first; | 773 tempoMIDITime = i->first; |
774 tempoRealTime = i->second.first; | 774 tempoRealTime = i->second.first; |
775 tempo = i->second.second; | 775 tempo = i->second.second; |
776 } | 776 } |
777 | 777 |
778 int td = m_timingDivision; | 778 int td = m_timingDivision; |
779 if (td == 0) td = 96; | 779 if (td == 0) td = 96; |
780 | 780 |
782 double quarters = double(melapsed) / double(td); | 782 double quarters = double(melapsed) / double(td); |
783 double seconds = (60.0 * quarters) / tempo; | 783 double seconds = (60.0 * quarters) / tempo; |
784 | 784 |
785 /* | 785 /* |
786 SVDEBUG << "MIDIFileReader::getTimeForMIDITime(" << midiTime << ")" | 786 SVDEBUG << "MIDIFileReader::getTimeForMIDITime(" << midiTime << ")" |
787 << endl; | 787 << endl; |
788 SVDEBUG << "timing division = " << td << endl; | 788 SVDEBUG << "timing division = " << td << endl; |
789 SVDEBUG << "nearest tempo event (of " << m_tempoMap.size() << ") is at " << tempoMIDITime << " (" | 789 SVDEBUG << "nearest tempo event (of " << m_tempoMap.size() << ") is at " << tempoMIDITime << " (" |
790 << tempoRealTime << ")" << endl; | 790 << tempoRealTime << ")" << endl; |
791 SVDEBUG << "quarters since then = " << quarters << endl; | 791 SVDEBUG << "quarters since then = " << quarters << endl; |
792 SVDEBUG << "tempo = " << tempo << " quarters per minute" << endl; | 792 SVDEBUG << "tempo = " << tempo << " quarters per minute" << endl; |
793 SVDEBUG << "seconds since then = " << seconds << endl; | 793 SVDEBUG << "seconds since then = " << seconds << endl; |
794 SVDEBUG << "resulting time = " << (tempoRealTime + RealTime::fromSeconds(seconds)) << endl; | 794 SVDEBUG << "resulting time = " << (tempoRealTime + RealTime::fromSeconds(seconds)) << endl; |
795 */ | 795 */ |
805 if (m_loadableTracks.empty()) { | 805 if (m_loadableTracks.empty()) { |
806 if (m_acquirer) { | 806 if (m_acquirer) { |
807 m_acquirer->showError | 807 m_acquirer->showError |
808 (tr("MIDI file \"%1\" has no notes in any track").arg(m_path)); | 808 (tr("MIDI file \"%1\" has no notes in any track").arg(m_path)); |
809 } | 809 } |
810 return 0; | 810 return 0; |
811 } | 811 } |
812 | 812 |
813 std::set<unsigned int> tracksToLoad; | 813 std::set<unsigned int> tracksToLoad; |
814 | 814 |
815 if (m_loadableTracks.size() == 1) { | 815 if (m_loadableTracks.size() == 1) { |
816 | 816 |
817 tracksToLoad.insert(*m_loadableTracks.begin()); | 817 tracksToLoad.insert(*m_loadableTracks.begin()); |
818 | 818 |
819 } else { | 819 } else { |
820 | 820 |
821 QStringList displayNames; | 821 QStringList displayNames; |
822 | 822 |
823 for (set<unsigned int>::iterator i = m_loadableTracks.begin(); | 823 for (set<unsigned int>::iterator i = m_loadableTracks.begin(); |
824 i != m_loadableTracks.end(); ++i) { | 824 i != m_loadableTracks.end(); ++i) { |
825 | 825 |
826 unsigned int trackNo = *i; | 826 unsigned int trackNo = *i; |
827 QString label; | 827 QString label; |
828 | 828 |
829 QString perc; | 829 QString perc; |
830 if (m_percussionTracks.find(trackNo) != m_percussionTracks.end()) { | 830 if (m_percussionTracks.find(trackNo) != m_percussionTracks.end()) { |
831 perc = tr(" - uses GM percussion channel"); | 831 perc = tr(" - uses GM percussion channel"); |
832 } | 832 } |
833 | 833 |
834 if (m_trackNames.find(trackNo) != m_trackNames.end()) { | 834 if (m_trackNames.find(trackNo) != m_trackNames.end()) { |
835 label = tr("Track %1 (%2)%3") | 835 label = tr("Track %1 (%2)%3") |
836 .arg(trackNo).arg(m_trackNames.find(trackNo)->second) | 836 .arg(trackNo).arg(m_trackNames.find(trackNo)->second) |
837 .arg(perc); | 837 .arg(perc); |
838 } else { | 838 } else { |
839 label = tr("Track %1 (untitled)%3").arg(trackNo).arg(perc); | 839 label = tr("Track %1 (untitled)%3").arg(trackNo).arg(perc); |
840 } | 840 } |
841 | 841 |
842 displayNames << label; | 842 displayNames << label; |
843 } | 843 } |
844 | 844 |
845 QString singleTrack; | 845 QString singleTrack; |
846 | 846 |
847 bool haveSomePercussion = | 847 bool haveSomePercussion = |
848 (!m_percussionTracks.empty() && | 848 (!m_percussionTracks.empty() && |
864 pref == MIDIFileImportPreferenceAcquirer::MergeAllNonPercussionTracks) { | 864 pref == MIDIFileImportPreferenceAcquirer::MergeAllNonPercussionTracks) { |
865 | 865 |
866 for (set<unsigned int>::iterator i = m_loadableTracks.begin(); | 866 for (set<unsigned int>::iterator i = m_loadableTracks.begin(); |
867 i != m_loadableTracks.end(); ++i) { | 867 i != m_loadableTracks.end(); ++i) { |
868 | 868 |
869 if (pref == MIDIFileImportPreferenceAcquirer::MergeAllTracks || | 869 if (pref == MIDIFileImportPreferenceAcquirer::MergeAllTracks || |
870 m_percussionTracks.find(*i) == m_percussionTracks.end()) { | 870 m_percussionTracks.find(*i) == m_percussionTracks.end()) { |
871 | 871 |
872 tracksToLoad.insert(*i); | 872 tracksToLoad.insert(*i); |
873 } | 873 } |
874 } | 874 } |
875 | 875 |
876 } else { | 876 } else { |
877 | 877 |
878 int j = 0; | 878 int j = 0; |
879 | 879 |
880 for (set<unsigned int>::iterator i = m_loadableTracks.begin(); | 880 for (set<unsigned int>::iterator i = m_loadableTracks.begin(); |
881 i != m_loadableTracks.end(); ++i) { | 881 i != m_loadableTracks.end(); ++i) { |
882 | 882 |
883 if (singleTrack == displayNames[j]) { | 883 if (singleTrack == displayNames[j]) { |
884 tracksToLoad.insert(*i); | 884 tracksToLoad.insert(*i); |
885 break; | 885 break; |
886 } | 886 } |
887 | 887 |
888 ++j; | 888 ++j; |
889 } | 889 } |
890 } | 890 } |
891 } | 891 } |
892 | 892 |
893 if (tracksToLoad.empty()) return 0; | 893 if (tracksToLoad.empty()) return 0; |
894 | 894 |
895 int n = int(tracksToLoad.size()), count = 0; | 895 int n = int(tracksToLoad.size()), count = 0; |
896 Model *model = 0; | 896 Model *model = 0; |
897 | 897 |
898 for (std::set<unsigned int>::iterator i = tracksToLoad.begin(); | 898 for (std::set<unsigned int>::iterator i = tracksToLoad.begin(); |
899 i != tracksToLoad.end(); ++i) { | 899 i != tracksToLoad.end(); ++i) { |
900 | 900 |
901 int minProgress = (100 * count) / n; | 901 int minProgress = (100 * count) / n; |
902 int progressAmount = 100 / n; | 902 int progressAmount = 100 / n; |
903 | 903 |
904 model = loadTrack(*i, model, minProgress, progressAmount); | 904 model = loadTrack(*i, model, minProgress, progressAmount); |
905 | 905 |
906 ++count; | 906 ++count; |
907 } | 907 } |
908 | 908 |
909 if (dynamic_cast<NoteModel *>(model)) { | 909 if (dynamic_cast<NoteModel *>(model)) { |
910 dynamic_cast<NoteModel *>(model)->setCompletion(100); | 910 dynamic_cast<NoteModel *>(model)->setCompletion(100); |
911 } | 911 } |
912 | 912 |
913 return model; | 913 return model; |
914 } | 914 } |
915 | 915 |
916 Model * | 916 Model * |
917 MIDIFileReader::loadTrack(unsigned int trackToLoad, | 917 MIDIFileReader::loadTrack(unsigned int trackToLoad, |
918 Model *existingModel, | 918 Model *existingModel, |
919 int minProgress, | 919 int minProgress, |
920 int progressAmount) const | 920 int progressAmount) const |
921 { | 921 { |
922 if (m_midiComposition.find(trackToLoad) == m_midiComposition.end()) { | 922 if (m_midiComposition.find(trackToLoad) == m_midiComposition.end()) { |
923 return 0; | 923 return 0; |
924 } | 924 } |
925 | 925 |
926 NoteModel *model = 0; | 926 NoteModel *model = 0; |
927 | 927 |
928 if (existingModel) { | 928 if (existingModel) { |
929 model = dynamic_cast<NoteModel *>(existingModel); | 929 model = dynamic_cast<NoteModel *>(existingModel); |
930 if (!model) { | 930 if (!model) { |
931 SVDEBUG << "WARNING: MIDIFileReader::loadTrack: Existing model given, but it isn't a NoteModel -- ignoring it" << endl; | 931 SVDEBUG << "WARNING: MIDIFileReader::loadTrack: Existing model given, but it isn't a NoteModel -- ignoring it" << endl; |
932 } | 932 } |
933 } | 933 } |
934 | 934 |
935 if (!model) { | 935 if (!model) { |
936 model = new NoteModel(m_mainModelSampleRate, 1, 0.0, 0.0, false); | 936 model = new NoteModel(m_mainModelSampleRate, 1, 0.0, 0.0, false); |
937 model->setValueQuantization(1.0); | 937 model->setValueQuantization(1.0); |
938 model->setObjectName(QFileInfo(m_path).fileName()); | 938 model->setObjectName(QFileInfo(m_path).fileName()); |
939 } | 939 } |
940 | 940 |
941 const MIDITrack &track = m_midiComposition.find(trackToLoad)->second; | 941 const MIDITrack &track = m_midiComposition.find(trackToLoad)->second; |
942 | 942 |
954 rt = RealTime::frame2RealTime(midiTime, m_fps * m_subframes); | 954 rt = RealTime::frame2RealTime(midiTime, m_fps * m_subframes); |
955 } else { | 955 } else { |
956 rt = getTimeForMIDITime(midiTime); | 956 rt = getTimeForMIDITime(midiTime); |
957 } | 957 } |
958 | 958 |
959 // We ignore most of these event types for now, though in | 959 // We ignore most of these event types for now, though in |
960 // theory some of the text ones could usefully be incorporated | 960 // theory some of the text ones could usefully be incorporated |
961 | 961 |
962 if ((*i)->isMeta()) { | 962 if ((*i)->isMeta()) { |
963 | 963 |
964 switch((*i)->getMetaEventCode()) { | 964 switch((*i)->getMetaEventCode()) { |
965 | 965 |
966 case MIDI_KEY_SIGNATURE: | 966 case MIDI_KEY_SIGNATURE: |
967 // minorKey = (int((*i)->getMetaMessage()[1]) != 0); | 967 // minorKey = (int((*i)->getMetaMessage()[1]) != 0); |
968 sharpKey = (int((*i)->getMetaMessage()[0]) >= 0); | 968 sharpKey = (int((*i)->getMetaMessage()[0]) >= 0); |
969 break; | 969 break; |
970 | 970 |
971 case MIDI_TEXT_EVENT: | 971 case MIDI_TEXT_EVENT: |
972 case MIDI_LYRIC: | 972 case MIDI_LYRIC: |
973 case MIDI_TEXT_MARKER: | 973 case MIDI_TEXT_MARKER: |
974 case MIDI_COPYRIGHT_NOTICE: | 974 case MIDI_COPYRIGHT_NOTICE: |
975 case MIDI_TRACK_NAME: | 975 case MIDI_TRACK_NAME: |
976 // The text events that we could potentially use | 976 // The text events that we could potentially use |
977 break; | 977 break; |
978 | 978 |
979 case MIDI_SET_TEMPO: | 979 case MIDI_SET_TEMPO: |
980 // Already dealt with in a separate pass previously | 980 // Already dealt with in a separate pass previously |
981 break; | 981 break; |
982 | 982 |
983 case MIDI_TIME_SIGNATURE: | 983 case MIDI_TIME_SIGNATURE: |
984 // Not yet! | 984 // Not yet! |
985 break; | 985 break; |
986 | 986 |
987 case MIDI_SEQUENCE_NUMBER: | 987 case MIDI_SEQUENCE_NUMBER: |
988 case MIDI_CHANNEL_PREFIX_OR_PORT: | 988 case MIDI_CHANNEL_PREFIX_OR_PORT: |
989 case MIDI_INSTRUMENT_NAME: | 989 case MIDI_INSTRUMENT_NAME: |
990 case MIDI_CUE_POINT: | 990 case MIDI_CUE_POINT: |
991 case MIDI_CHANNEL_PREFIX: | 991 case MIDI_CHANNEL_PREFIX: |
992 case MIDI_SEQUENCER_SPECIFIC: | 992 case MIDI_SEQUENCER_SPECIFIC: |
993 case MIDI_SMPTE_OFFSET: | 993 case MIDI_SMPTE_OFFSET: |
994 default: | 994 default: |
995 break; | 995 break; |
996 } | 996 } |
997 | 997 |
998 } else { | 998 } else { |
999 | 999 |
1000 switch ((*i)->getMessageType()) { | 1000 switch ((*i)->getMessageType()) { |
1001 | 1001 |
1002 case MIDI_NOTE_ON: | 1002 case MIDI_NOTE_ON: |
1003 | 1003 |
1004 if ((*i)->getVelocity() == 0) break; // effective note-off | 1004 if ((*i)->getVelocity() == 0) break; // effective note-off |
1005 else { | 1005 else { |
1006 RealTime endRT; | 1006 RealTime endRT; |
1007 unsigned long endMidiTime = (*i)->getTime() + (*i)->getDuration(); | 1007 unsigned long endMidiTime = (*i)->getTime() + (*i)->getDuration(); |
1008 if (m_smpte) { | 1008 if (m_smpte) { |
1009 endRT = RealTime::frame2RealTime(endMidiTime, m_fps * m_subframes); | 1009 endRT = RealTime::frame2RealTime(endMidiTime, m_fps * m_subframes); |
1010 } else { | 1010 } else { |
1011 endRT = getTimeForMIDITime(endMidiTime); | 1011 endRT = getTimeForMIDITime(endMidiTime); |
1012 } | 1012 } |
1013 | 1013 |
1014 long startFrame = RealTime::realTime2Frame | 1014 long startFrame = RealTime::realTime2Frame |
1015 (rt, model->getSampleRate()); | 1015 (rt, model->getSampleRate()); |
1016 | 1016 |
1017 long endFrame = RealTime::realTime2Frame | 1017 long endFrame = RealTime::realTime2Frame |
1018 (endRT, model->getSampleRate()); | 1018 (endRT, model->getSampleRate()); |
1019 | 1019 |
1020 QString pitchLabel = Pitch::getPitchLabel((*i)->getPitch(), | 1020 QString pitchLabel = Pitch::getPitchLabel((*i)->getPitch(), |
1021 0, | 1021 0, |
1022 !sharpKey); | 1022 !sharpKey); |
1023 | 1023 |
1024 QString noteLabel = tr("%1 - vel %2") | 1024 QString noteLabel = tr("%1 - vel %2") |
1025 .arg(pitchLabel).arg(int((*i)->getVelocity())); | 1025 .arg(pitchLabel).arg(int((*i)->getVelocity())); |
1026 | 1026 |
1027 float level = float((*i)->getVelocity()) / 128.f; | 1027 float level = float((*i)->getVelocity()) / 128.f; |
1028 | 1028 |
1029 Note note(startFrame, (*i)->getPitch(), | 1029 Note note(startFrame, (*i)->getPitch(), |
1030 endFrame - startFrame, level, noteLabel); | 1030 endFrame - startFrame, level, noteLabel); |
1031 | 1031 |
1032 // SVDEBUG << "Adding note " << startFrame << "," << (endFrame-startFrame) << " : " << int((*i)->getPitch()) << endl; | 1032 // SVDEBUG << "Adding note " << startFrame << "," << (endFrame-startFrame) << " : " << int((*i)->getPitch()) << endl; |
1033 | 1033 |
1034 model->addPoint(note); | 1034 model->addPoint(note); |
1035 break; | 1035 break; |
1036 } | 1036 } |
1037 | 1037 |
1038 case MIDI_PITCH_BEND: | 1038 case MIDI_PITCH_BEND: |
1039 // I guess we could make some use of this... | 1039 // I guess we could make some use of this... |
1040 break; | 1040 break; |
1041 | 1041 |
1042 case MIDI_NOTE_OFF: | 1042 case MIDI_NOTE_OFF: |
1043 case MIDI_PROG_CHANGE: | 1043 case MIDI_PROG_CHANGE: |
1044 case MIDI_CTRL_CHANGE: | 1044 case MIDI_CTRL_CHANGE: |
1048 break; | 1048 break; |
1049 | 1049 |
1050 default: | 1050 default: |
1051 break; | 1051 break; |
1052 } | 1052 } |
1053 } | 1053 } |
1054 | 1054 |
1055 model->setCompletion(minProgress + | 1055 model->setCompletion(minProgress + |
1056 (count * progressAmount) / totalEvents); | 1056 (count * progressAmount) / totalEvents); |
1057 ++count; | 1057 ++count; |
1058 } | 1058 } |
1059 | 1059 |
1060 return model; | 1060 return model; |
1061 } | 1061 } |
1062 | 1062 |