diff options
author | Matthew Hoops | 2012-09-07 11:45:28 -0400 |
---|---|---|
committer | Matthew Hoops | 2012-09-07 11:48:22 -0400 |
commit | c01dfba093f0a2506c912f644dbb44df7b877d92 (patch) | |
tree | 095b353294a512ca1d0c36443b249fca22de8a8c | |
parent | 7e2f7099c892c212409f1c7b69426cd1a1f00552 (diff) | |
download | scummvm-rg350-c01dfba093f0a2506c912f644dbb44df7b877d92.tar.gz scummvm-rg350-c01dfba093f0a2506c912f644dbb44df7b877d92.tar.bz2 scummvm-rg350-c01dfba093f0a2506c912f644dbb44df7b877d92.zip |
AUDIO: Begin basic playback of QuickTime MIDI files
Sounds almost correct, but too fast
-rw-r--r-- | audio/midiparser_qt.cpp | 109 | ||||
-rw-r--r-- | audio/midiparser_qt.h | 5 |
2 files changed, 113 insertions, 1 deletions
diff --git a/audio/midiparser_qt.cpp b/audio/midiparser_qt.cpp index 7b20f62cb7..b7a201d801 100644 --- a/audio/midiparser_qt.cpp +++ b/audio/midiparser_qt.cpp @@ -96,8 +96,103 @@ bool MidiParser_QT::loadFromContainerFile(const Common::String &fileName) { return true; } +void MidiParser_QT::resetTracking() { + _loadedInstruments = 0; +} + void MidiParser_QT::parseNextEvent(EventInfo &info) { - // TODO + if (_loadedInstruments < _trackInfo[_active_track].noteRequests.size()) { + // Load instruments first + info.event = 0xC0 | _loadedInstruments; + info.basic.param1 = _trackInfo[_active_track].noteRequests[_loadedInstruments].tone.gmNumber; + _loadedInstruments++; + return; + } + + info.delta = readNextEvent(info); +} + +uint32 MidiParser_QT::readNextEvent(EventInfo &info) { + uint32 control = readUint32(); + + switch (control >> 28) { + case 0x0: + case 0x1: + // Rest + // We handle this by recursively adding up all the rests into the + // next event's delta + return readNextEvent(info) + (control & 0xFFFFFF); + case 0x2: + case 0x3: + // Note event + info.event = 0x90 | ((control >> 24) & 0x1F); + info.basic.param1 = ((control >> 18) & 0x3F) + 32; + info.basic.param2 = (control >> 11) & 0x7F; + info.length = (info.basic.param2 == 0) ? 0 : (control & 0x7FF); + break; + case 0x4: + case 0x5: + // Controller + info.event = 0xB0 | ((control >> 24) & 0x1F); + info.basic.param1 = (control >> 16) & 0xFF; + info.basic.param2 = (control >> 8) & 0xFF; + break; + case 0x6: + case 0x7: + // Marker + switch ((control >> 16) & 0xFF) { + case 0: + // End + info.event = 0xFF; + info.ext.type = 0x2F; + break; + case 1: + // Beat + warning("Encountered beat marker"); + break; + case 2: + // Tempo + warning("Encountered tempo marker"); + break; + default: + warning("Unknown marker"); + } + break; + case 0x9: { + // Extended note event + uint32 extra = readUint32(); + info.event = 0x90 | ((control >> 16) & 0xFFF); + info.basic.param1 = (control >> 8) & 0xFF; + info.basic.param2 = (extra >> 22) & 0x7F; + info.length = (info.basic.param2 == 0) ? 0 : (extra & 0x3FFFFF); + break; + } + case 0xA: { + // Extended controller + uint32 extra = readUint32(); + info.event = 0xB0 | ((control >> 16) & 0xFFF); + info.basic.param1 = (extra >> 16) & 0x3FFF; + info.basic.param2 = (extra >> 8) & 0xFF; // ??? + break; + } + case 0xB: + // Knob + error("Encountered knob event in QuickTime MIDI"); + break; + case 0x8: + case 0xC: + case 0xD: + case 0xE: + // Reserved + readUint32(); + break; + case 0xF: + // General + error("Encountered general event in QuickTime MIDI"); + break; + } + + return 0; } Common::QuickTimeParser::SampleDesc *MidiParser_QT::readSampleDesc(Track *track, uint32 format) { @@ -196,9 +291,15 @@ void MidiParser_QT::initCommon() { // form, we can fill in the MidiParser tracks. _num_tracks = _trackInfo.size(); + assert(_num_tracks > 0); for (uint32 i = 0; i < _trackInfo.size(); i++) MidiParser::_tracks[i] = _trackInfo[i].data; + + _ppqn = _trackInfo[0].timeScale; + resetTracking(); + setTempo(500000); + setTrack(0); } byte *MidiParser_QT::readWholeTrack(Common::QuickTimeParser::Track *track) { @@ -229,6 +330,12 @@ byte *MidiParser_QT::readWholeTrack(Common::QuickTimeParser::Track *track) { return output.getData(); } +uint32 MidiParser_QT::readUint32() { + uint32 value = READ_BE_UINT32(_position._play_pos); + _position._play_pos += 4; + return value; +} + MidiParser *MidiParser::createParser_QT() { return new MidiParser_QT(); } diff --git a/audio/midiparser_qt.h b/audio/midiparser_qt.h index 6e4ded8e74..2dcd61b9f9 100644 --- a/audio/midiparser_qt.h +++ b/audio/midiparser_qt.h @@ -43,6 +43,7 @@ public: protected: // MidiParser + void resetTracking(); void parseNextEvent(EventInfo &info); // QuickTimeParser @@ -86,6 +87,8 @@ private: NoteRequestList _noteRequests; }; + uint32 readNextEvent(EventInfo &info); + Common::String readString31(Common::SeekableReadStream *stream); Common::Rational readFixed(Common::SeekableReadStream *stream); NoteRequestList readNoteRequestList(Common::SeekableReadStream *stream); @@ -93,9 +96,11 @@ private: byte *readWholeTrack(Common::QuickTimeParser::Track *track); Common::Array<MIDITrackInfo> _trackInfo; + uint32 _loadedInstruments; void initFromContainerTracks(); void initCommon(); + uint32 readUint32(); }; #endif |