Mercurial > hg > svcore
comparison data/fileio/MIDIFileReader.cpp @ 613:eb1b517f5eeb sv-v1.7
* Support SMPTE timecode in MIDI files (fixes #2739160)
author | Chris Cannam |
---|---|
date | Tue, 29 Sep 2009 10:34:57 +0000 |
parents | 2e50d95cf621 |
children | 06f13a3b9e9e |
comparison
equal
deleted
inserted
replaced
612:75f154085a4d | 613:eb1b517f5eeb |
---|---|
56 | 56 |
57 | 57 |
58 MIDIFileReader::MIDIFileReader(QString path, | 58 MIDIFileReader::MIDIFileReader(QString path, |
59 MIDIFileImportPreferenceAcquirer *acquirer, | 59 MIDIFileImportPreferenceAcquirer *acquirer, |
60 size_t mainModelSampleRate) : | 60 size_t mainModelSampleRate) : |
61 m_smpte(false), | |
61 m_timingDivision(0), | 62 m_timingDivision(0), |
63 m_fps(0), | |
64 m_subframes(0), | |
62 m_format(MIDI_FILE_BAD_FORMAT), | 65 m_format(MIDI_FILE_BAD_FORMAT), |
63 m_numberOfTracks(0), | 66 m_numberOfTracks(0), |
64 m_trackByteCount(0), | 67 m_trackByteCount(0), |
65 m_decrementCount(false), | 68 m_decrementCount(false), |
66 m_path(path), | 69 m_path(path), |
414 | 417 |
415 m_format = (MIDIFileFormatType) midiBytesToInt(midiHeader.substr(8,2)); | 418 m_format = (MIDIFileFormatType) midiBytesToInt(midiHeader.substr(8,2)); |
416 m_numberOfTracks = midiBytesToInt(midiHeader.substr(10,2)); | 419 m_numberOfTracks = midiBytesToInt(midiHeader.substr(10,2)); |
417 m_timingDivision = midiBytesToInt(midiHeader.substr(12,2)); | 420 m_timingDivision = midiBytesToInt(midiHeader.substr(12,2)); |
418 | 421 |
419 if (m_format == MIDI_SEQUENTIAL_TRACK_FILE) { | 422 if (m_timingDivision >= 32768) { |
420 #ifdef MIDI_DEBUG | 423 m_smpte = true; |
421 cerr << "MIDIFileReader::parseHeader()" | 424 m_fps = 256 - (m_timingDivision >> 8); |
422 << "- can't load sequential track file" | 425 m_subframes = (m_timingDivision & 0xff); |
423 << endl; | 426 } else { |
424 #endif | 427 m_smpte = false; |
425 return false; | 428 } |
426 } | |
427 | |
428 #ifdef MIDI_DEBUG | |
429 if (m_timingDivision < 0) { | |
430 cerr << "MIDIFileReader::parseHeader()" | |
431 << " - file uses SMPTE timing" | |
432 << endl; | |
433 } | |
434 #endif | |
435 | 429 |
436 return true; | 430 return true; |
437 } | 431 } |
438 | 432 |
439 // Extract the contents from a MIDI file track and places it into | 433 // Extract the contents from a MIDI file track and places it into |
704 // Event duration to length of track | 698 // Event duration to length of track |
705 // | 699 // |
706 if (!noteOffFound) { | 700 if (!noteOffFound) { |
707 MIDITrack::iterator j = m_midiComposition[track].end(); | 701 MIDITrack::iterator j = m_midiComposition[track].end(); |
708 --j; | 702 --j; |
709 (*i)->setDuration((*j)->getTime() - (*i)->getTime()); | 703 (*i)->setDuration((*j)->getTime() - (*i)->getTime()); |
710 } | 704 } |
711 } | 705 } |
712 } | 706 } |
713 | 707 |
714 return notesOnTrack; | 708 return notesOnTrack; |
955 bool minorKey = false; | 949 bool minorKey = false; |
956 bool sharpKey = true; | 950 bool sharpKey = true; |
957 | 951 |
958 for (MIDITrack::const_iterator i = track.begin(); i != track.end(); ++i) { | 952 for (MIDITrack::const_iterator i = track.begin(); i != track.end(); ++i) { |
959 | 953 |
960 RealTime rt = getTimeForMIDITime((*i)->getTime()); | 954 RealTime rt; |
955 unsigned long midiTime = (*i)->getTime(); | |
956 | |
957 if (m_smpte) { | |
958 rt = RealTime::frame2RealTime(midiTime, m_fps * m_subframes); | |
959 } else { | |
960 rt = getTimeForMIDITime(midiTime); | |
961 } | |
961 | 962 |
962 // We ignore most of these event types for now, though in | 963 // We ignore most of these event types for now, though in |
963 // theory some of the text ones could usefully be incorporated | 964 // theory some of the text ones could usefully be incorporated |
964 | 965 |
965 if ((*i)->isMeta()) { | 966 if ((*i)->isMeta()) { |
1004 | 1005 |
1005 case MIDI_NOTE_ON: | 1006 case MIDI_NOTE_ON: |
1006 | 1007 |
1007 if ((*i)->getVelocity() == 0) break; // effective note-off | 1008 if ((*i)->getVelocity() == 0) break; // effective note-off |
1008 else { | 1009 else { |
1009 RealTime endRT = getTimeForMIDITime((*i)->getTime() + | 1010 RealTime endRT; |
1010 (*i)->getDuration()); | 1011 unsigned long endMidiTime = (*i)->getTime() + (*i)->getDuration(); |
1012 if (m_smpte) { | |
1013 endRT = RealTime::frame2RealTime(endMidiTime, m_fps * m_subframes); | |
1014 } else { | |
1015 endRT = getTimeForMIDITime(endMidiTime); | |
1016 } | |
1011 | 1017 |
1012 long startFrame = RealTime::realTime2Frame | 1018 long startFrame = RealTime::realTime2Frame |
1013 (rt, model->getSampleRate()); | 1019 (rt, model->getSampleRate()); |
1014 | 1020 |
1015 long endFrame = RealTime::realTime2Frame | 1021 long endFrame = RealTime::realTime2Frame |