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 | 
