diff options
Diffstat (limited to 'audio')
-rw-r--r-- | audio/midiparser.h | 1 | ||||
-rw-r--r-- | audio/midiparser_qt.cpp | 161 | ||||
-rw-r--r-- | audio/midiparser_qt.h | 90 |
3 files changed, 183 insertions, 69 deletions
diff --git a/audio/midiparser.h b/audio/midiparser.h index c935969e72..f26da456b6 100644 --- a/audio/midiparser.h +++ b/audio/midiparser.h @@ -394,6 +394,7 @@ public: static MidiParser *createParser_SMF(); static MidiParser *createParser_XMIDI(XMidiCallbackProc proc = defaultXMidiCallback, void *refCon = 0); + static MidiParser *createParser_QT(); static void timerCallback(void *data) { ((MidiParser *) data)->onTimer(); } }; diff --git a/audio/midiparser_qt.cpp b/audio/midiparser_qt.cpp index 0d42e6c1f9..ed4bb22242 100644 --- a/audio/midiparser_qt.cpp +++ b/audio/midiparser_qt.cpp @@ -20,61 +20,76 @@ * */ -#include "audio/midiparser.h" +#include "audio/midiparser_qt.h" #include "common/debug.h" -#include "common/quicktime.h" - -class MidiParser_QT : /* public MidiParser, */ public Common::QuickTimeParser { -public: - MidiParser_QT() {} - ~MidiParser_QT() {} - -protected: - SampleDesc *readSampleDesc(Track *track, uint32 format); - -private: - struct NoteRequestInfo { - byte flags; - byte reserved; - uint16 polyphony; - Common::Rational typicalPolyphony; - }; - - struct ToneDescription { - uint32 synthesizerType; - Common::String synthesizerName; - Common::String instrumentName; - uint32 instrumentNumber; - uint32 gmNumber; - }; - - struct NoteRequest { - uint16 part; - NoteRequestInfo info; - ToneDescription tone; - }; - - typedef Common::Array<NoteRequest> NoteRequestList; - - class MIDISampleDesc : public SampleDesc { - public: - MIDISampleDesc(Common::QuickTimeParser::Track *parentTrack, uint32 codecTag); - ~MIDISampleDesc() {} - - NoteRequestList _noteRequests; - }; - - Common::String readString31(); - Common::Rational readFixed(); - NoteRequestList readNoteRequestList(); -}; +#include "common/memstream.h" + +bool MidiParser_QT::loadMusic(byte *data, uint32 size) { + // Assume that this is a Tune and not a QuickTime container + Common::SeekableReadStream *stream = new Common::MemoryReadStream(data, size, DisposeAfterUse::NO); + + if (!loadFromTune(stream)) { + delete stream; + return false; + } + + return true; +} + +void MidiParser_QT::unloadMusic() { + MidiParser::unloadMusic(); + close(); + // TODO +} + +bool MidiParser_QT::loadFromTune(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) { + unloadMusic(); + + // a tune starts off with a sample description + stream->readUint32BE(); // header size + + if (stream->readUint32BE() != MKTAG('m', 'u', 's', 'i')) + return false; + + stream->readUint32BE(); // reserved + stream->readUint16BE(); // reserved + stream->readUint16BE(); // index + + // TODO + readNoteRequestList(stream); + return true; +} + +bool MidiParser_QT::loadFromContainerStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse) { + unloadMusic(); + + if (!parseStream(stream, disposeAfterUse)) + return false; + + initFromContainerTracks(); + return true; +} + +bool MidiParser_QT::loadFromContainerFile(const Common::String &fileName) { + unloadMusic(); + + if (!parseFile(fileName)) + return false; + + initFromContainerTracks(); + return true; +} + +void MidiParser_QT::parseNextEvent(EventInfo &info) { + // TODO +} Common::QuickTimeParser::SampleDesc *MidiParser_QT::readSampleDesc(Track *track, uint32 format) { if (track->codecType == CODEC_TYPE_MIDI) { debug(0, "MIDI Codec FourCC '%s'", tag2str(format)); MIDISampleDesc *entry = new MIDISampleDesc(track, format); - entry->_noteRequests = readNoteRequestList(); + entry->_noteRequests = readNoteRequestList(_fd); return entry; } @@ -85,31 +100,31 @@ MidiParser_QT::MIDISampleDesc::MIDISampleDesc(Common::QuickTimeParser::Track *pa Common::QuickTimeParser::SampleDesc(parentTrack, codecTag) { } -Common::String MidiParser_QT::readString31() { - byte size = _fd->readByte(); +Common::String MidiParser_QT::readString31(Common::SeekableReadStream *stream) { + byte size = stream->readByte(); assert(size < 32); Common::String string; for (byte i = 0; i < size; i++) - string += (char)_fd->readByte(); + string += (char)stream->readByte(); - _fd->skip(31 - size); + stream->skip(31 - size); return string; } -Common::Rational MidiParser_QT::readFixed() { - int16 integerPart = _fd->readSint16BE(); - uint16 fractionalPart = _fd->readUint16BE(); +Common::Rational MidiParser_QT::readFixed(Common::SeekableReadStream *stream) { + int16 integerPart = stream->readSint16BE(); + uint16 fractionalPart = stream->readUint16BE(); return integerPart + Common::Rational(fractionalPart, 0x10000); } -MidiParser_QT::NoteRequestList MidiParser_QT::readNoteRequestList() { +MidiParser_QT::NoteRequestList MidiParser_QT::readNoteRequestList(Common::SeekableReadStream *stream) { NoteRequestList requests; - /* uint32 flags = */ _fd->readUint32BE(); // always 0 + /* uint32 flags = */ stream->readUint32BE(); // always 0 for (;;) { - uint32 event = _fd->readUint32BE(); + uint32 event = stream->readUint32BE(); if (event == 0x60000000) // marker event break; @@ -118,17 +133,17 @@ MidiParser_QT::NoteRequestList MidiParser_QT::readNoteRequestList() { NoteRequest request; request.part = (event >> 16) & 0xFFF; - request.info.flags = _fd->readByte(); - request.info.reserved = _fd->readByte(); - request.info.polyphony = _fd->readUint16BE(); - request.info.typicalPolyphony = readFixed(); - request.tone.synthesizerType = _fd->readUint32BE(); - request.tone.synthesizerName = readString31(); - request.tone.instrumentName = readString31(); - request.tone.instrumentNumber = _fd->readUint32BE(); - request.tone.gmNumber = _fd->readUint32BE(); - - if (_fd->readUint32BE() != 0xC0010017) // general event note request + request.info.flags = stream->readByte(); + request.info.reserved = stream->readByte(); + request.info.polyphony = stream->readUint16BE(); + request.info.typicalPolyphony = readFixed(stream); + request.tone.synthesizerType = stream->readUint32BE(); + request.tone.synthesizerName = readString31(stream); + request.tone.instrumentName = readString31(stream); + request.tone.instrumentNumber = stream->readUint32BE(); + request.tone.gmNumber = stream->readUint32BE(); + + if (stream->readUint32BE() != 0xC0010017) // general event note request error("Invalid instrument end event"); requests.push_back(request); @@ -136,3 +151,11 @@ MidiParser_QT::NoteRequestList MidiParser_QT::readNoteRequestList() { return requests; } + +void MidiParser_QT::initFromContainerTracks() { + // TODO +} + +MidiParser *MidiParser::createParser_QT() { + return new MidiParser_QT(); +} diff --git a/audio/midiparser_qt.h b/audio/midiparser_qt.h new file mode 100644 index 0000000000..34abe4ced7 --- /dev/null +++ b/audio/midiparser_qt.h @@ -0,0 +1,90 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef AUDIO_MIDIPARSER_QT_H +#define AUDIO_MIDIPARSER_QT_H + +#include "audio/midiparser.h" +#include "common/array.h" +#include "common/quicktime.h" + +class MidiParser_QT : public MidiParser, public Common::QuickTimeParser { +public: + MidiParser_QT() {} + ~MidiParser_QT() {} + + // MidiParser + bool loadMusic(byte *data, uint32 size); + void unloadMusic(); + + // Custom + bool loadFromTune(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); + bool loadFromContainerStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES); + bool loadFromContainerFile(const Common::String &fileName); + +protected: + // MidiParser + void parseNextEvent(EventInfo &info); + + // QuickTimeParser + SampleDesc *readSampleDesc(Track *track, uint32 format); + +private: + struct NoteRequestInfo { + byte flags; + byte reserved; + uint16 polyphony; + Common::Rational typicalPolyphony; + }; + + struct ToneDescription { + uint32 synthesizerType; + Common::String synthesizerName; + Common::String instrumentName; + uint32 instrumentNumber; + uint32 gmNumber; + }; + + struct NoteRequest { + uint16 part; + NoteRequestInfo info; + ToneDescription tone; + }; + + typedef Common::Array<NoteRequest> NoteRequestList; + + class MIDISampleDesc : public SampleDesc { + public: + MIDISampleDesc(Common::QuickTimeParser::Track *parentTrack, uint32 codecTag); + ~MIDISampleDesc() {} + + NoteRequestList _noteRequests; + }; + + Common::String readString31(Common::SeekableReadStream *stream); + Common::Rational readFixed(Common::SeekableReadStream *stream); + NoteRequestList readNoteRequestList(Common::SeekableReadStream *stream); + + void initFromContainerTracks(); +}; + +#endif |