[Scummvm-cvs-logs] scummvm master -> 46aabed3f5bdb3549e3c804793b5198de4b1702c

clone2727 clone2727 at gmail.com
Sun Jul 10 21:53:48 CEST 2011


This automated email contains information about 2 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
c46aa548d6 AUDIO: Fix remaining AAC bugs by decoding with the same AAC context
46aabed3f5 AUDIO: Fix QDM2 sound in QuickTime files


Commit: c46aa548d6d8a1eabb968bfd0152215490bf746c
    https://github.com/scummvm/scummvm/commit/c46aa548d6d8a1eabb968bfd0152215490bf746c
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-07-10T12:50:47-07:00

Commit Message:
AUDIO: Fix remaining AAC bugs by decoding with the same AAC context

This introduces a new Audio::Codec class, based on DrMcCoy's solution for WMA in eos.

Changed paths:
  A audio/decoders/codec.h
    audio/decoders/aac.cpp
    audio/decoders/aac.h
    audio/decoders/quicktime.cpp
    audio/decoders/quicktime_intern.h



diff --git a/audio/decoders/aac.cpp b/audio/decoders/aac.cpp
index 874062a..50325dc 100644
--- a/audio/decoders/aac.cpp
+++ b/audio/decoders/aac.cpp
@@ -28,74 +28,34 @@
 #ifdef USE_FAAD
 
 #include "common/debug.h"
+#include "common/memstream.h"
 #include "common/stream.h"
 #include "common/textconsole.h"
 #include "common/util.h"
 
 #include "audio/audiostream.h"
+#include "audio/decoders/codec.h"
+#include "audio/decoders/raw.h"
 
 #include <neaacdec.h>
 
 namespace Audio {
 
-class AACStream : public AudioStream {
+class AACDecoder : public Codec {
 public:
-	AACStream(Common::SeekableReadStream *stream,
-	          DisposeAfterUse::Flag disposeStream,
-	          Common::SeekableReadStream *extraData,
+	AACDecoder(Common::SeekableReadStream *extraData,
 	          DisposeAfterUse::Flag disposeExtraData);
-	~AACStream();
+	~AACDecoder();
 
-	int readBuffer(int16 *buffer, const int numSamples);
-
-	bool endOfData() const { return _inBufferPos >= _inBufferSize && !_remainingSamples; }
-	bool isStereo() const { return _channels == 2; }
-	int getRate() const { return _rate; }
+	AudioStream *decodeFrame(Common::SeekableReadStream &stream);
 
 private:
 	NeAACDecHandle _handle;
 	byte _channels;
 	unsigned long _rate;
-
-	byte *_inBuffer;
-	uint32 _inBufferSize;
-	uint32 _inBufferPos;
-
-	int16 *_remainingSamples;
-	uint32 _remainingSamplesSize;
-	uint32 _remainingSamplesPos;
-
-	void init(Common::SeekableReadStream *extraData);
 };
 
-AACStream::AACStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeStream,
-		Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData) {
-
-	_remainingSamples = 0;
-	_inBufferPos = 0;
-
-	init(extraData);
-
-	// Copy all the data to a pointer so it can be passed through
-	// (At least MPEG-4 chunks shouldn't be large)
-	_inBufferSize = stream->size();
-	_inBuffer = new byte[_inBufferSize];
-	stream->read(_inBuffer, _inBufferSize);
-
-	if (disposeStream == DisposeAfterUse::YES)
-		delete stream;
-
-	if (disposeExtraData == DisposeAfterUse::YES)
-		delete extraData;
-}
-
-AACStream::~AACStream() {
-	NeAACDecClose(_handle);
-	delete[] _inBuffer;
-	delete[] _remainingSamples;
-}
-
-void AACStream::init(Common::SeekableReadStream *extraData) {
+AACDecoder::AACDecoder(Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData) {
 	// Open the library
 	_handle = NeAACDecOpen();
 
@@ -117,59 +77,55 @@ void AACStream::init(Common::SeekableReadStream *extraData) {
 
 	if (err < 0)
 		error("Could not initialize AAC decoder: %s", NeAACDecGetErrorMessage(err));
-}
-
-int AACStream::readBuffer(int16 *buffer, const int numSamples) {
-	int samples = 0;
 
-	assert((numSamples % _channels) == 0);
+	if (disposeExtraData == DisposeAfterUse::YES)
+		delete extraData;
+}
 
-	// Dip into our remaining samples pool if it's available
-	if (_remainingSamples) {
-		samples = MIN<int>(numSamples, _remainingSamplesSize - _remainingSamplesPos);
+AACDecoder::~AACDecoder() {
+	NeAACDecClose(_handle);
+}
 
-		memcpy(buffer, _remainingSamples + _remainingSamplesPos, samples * 2);
-		_remainingSamplesPos += samples;
+AudioStream *AACDecoder::decodeFrame(Common::SeekableReadStream &stream) {
+	// read everything into a buffer
+	uint32 inBufferPos = 0;
+	uint32 inBufferSize = stream.size();
+	byte *inBuffer = new byte[inBufferSize];
+	stream.read(inBuffer, inBufferSize);
 
-		if (_remainingSamplesPos == _remainingSamplesSize) {
-			delete[] _remainingSamples;
-			_remainingSamples = 0;
-		}
-	}
+	QueuingAudioStream *audioStream = makeQueuingAudioStream(_rate, _channels == 2);
 
 	// Decode until we have enough samples (or there's no more left)
-	while (samples < numSamples && !endOfData()) {
+	while (inBufferPos < inBufferSize) {
 		NeAACDecFrameInfo frameInfo;
-		uint16 *decodedSamples = (uint16 *)NeAACDecDecode(_handle, &frameInfo, _inBuffer + _inBufferPos, _inBufferSize - _inBufferPos);
+		void *decodedSamples = NeAACDecDecode(_handle, &frameInfo, inBuffer + inBufferPos, inBufferSize - inBufferPos);
 
 		if (frameInfo.error != 0)
 			error("Failed to decode AAC frame: %s", NeAACDecGetErrorMessage(frameInfo.error));
 
-		int decodedSampleSize = frameInfo.samples;
-		int copySamples = (decodedSampleSize > (numSamples - samples)) ? (numSamples - samples) : decodedSampleSize;
+		byte *buffer = (byte *)malloc(frameInfo.samples * 2);
+		memcpy(buffer, decodedSamples, frameInfo.samples * 2);
 
-		memcpy(buffer + samples, decodedSamples, copySamples * 2);
-		samples += copySamples;
+		byte flags = FLAG_16BITS;
 
-		// Copy leftover samples for use in a later readBuffer() call
-		if (copySamples != decodedSampleSize) {
-			_remainingSamplesSize = decodedSampleSize - copySamples;
-			_remainingSamples = new int16[_remainingSamplesSize];
-			_remainingSamplesPos = 0;
-			memcpy(_remainingSamples, decodedSamples + copySamples, _remainingSamplesSize * 2);
-		}
+		if (_channels == 2)
+			flags |= FLAG_STEREO;
 
-		_inBufferPos += frameInfo.bytesconsumed;
+#ifdef SCUMM_LITTLE_ENDIAN
+		flags |= FLAG_LITTLE_ENDIAN;
+#endif
+
+		audioStream->queueBuffer(buffer, frameInfo.samples * 2, DisposeAfterUse::YES, flags);
+
+		inBufferPos += frameInfo.bytesconsumed;
 	}
 
-	return samples;
+	return audioStream;
 }
 
 // Factory function
-AudioStream *makeAACStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeStream,
-		Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData) {
-
-	return new AACStream(stream, disposeStream, extraData, disposeExtraData);
+Codec *makeAACDecoder(Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData) {
+	return new AACDecoder(extraData, disposeExtraData);
 }
 
 } // End of namespace Audio
diff --git a/audio/decoders/aac.h b/audio/decoders/aac.h
index efcbcc6..c5085fa 100644
--- a/audio/decoders/aac.h
+++ b/audio/decoders/aac.h
@@ -43,23 +43,19 @@ namespace Common {
 
 namespace Audio {
 
-class AudioStream;
+class Codec;
 
 /**
- * Create a new AudioStream from the AAC data of an MPEG-4 file in the given stream.
+ * Create a new Codec for decoding AAC data of an MPEG-4 file in the given stream.
  *
  * @note This should *only* be called by our QuickTime/MPEG-4 decoder since it relies
  *       on the MPEG-4 extra data. If you want to decode a file using AAC, go use
  *       makeQuickTimeStream() instead!
- * @param stream            the SeekableReadStream from which to read the AAC data
- * @param disposeStream     whether to delete the stream after use
  * @param extraData         the SeekableReadStream from which to read the AAC extra data
  * @param disposeExtraData  whether to delete the extra data stream after use
- * @return  a new AudioStream, or NULL, if an error occurred
+ * @return  a new Codec, or NULL, if an error occurred
  */
-AudioStream *makeAACStream(
-	Common::SeekableReadStream *stream,
-	DisposeAfterUse::Flag disposeStream,
+Codec *makeAACDecoder(
 	Common::SeekableReadStream *extraData,
 	DisposeAfterUse::Flag disposeExtraData = DisposeAfterUse::NO);
 
diff --git a/audio/decoders/codec.h b/audio/decoders/codec.h
new file mode 100644
index 0000000..fde7e59
--- /dev/null
+++ b/audio/decoders/codec.h
@@ -0,0 +1,47 @@
+/* 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.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef AUDIO_DECODERS_CODEC_H
+#define AUDIO_DECODERS_CODEC_H
+
+namespace Common {
+	class SeekableReadStream;
+}
+
+namespace Audio {
+
+class AudioStream;
+
+class Codec {
+public:
+	Codec() {}
+	virtual ~Codec() {}
+
+	virtual AudioStream *decodeFrame(Common::SeekableReadStream &data) = 0;
+};
+
+} // End of namespace Audio
+
+#endif
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp
index 0ad2821..4531cce 100644
--- a/audio/decoders/quicktime.cpp
+++ b/audio/decoders/quicktime.cpp
@@ -30,6 +30,7 @@
 #include "common/textconsole.h"
 
 #include "audio/audiostream.h"
+#include "audio/decoders/codec.h"
 #include "audio/decoders/quicktime.h"
 #include "audio/decoders/quicktime_intern.h"
 
@@ -86,6 +87,9 @@ void QuickTimeAudioDecoder::init() {
 			// Make sure the bits per sample transfers to the sample size
 			if (entry->getCodecTag() == MKTAG('r', 'a', 'w', ' ') || entry->getCodecTag() == MKTAG('t', 'w', 'o', 's'))
 				_tracks[_audioTrackIndex]->sampleSize = (entry->_bitsPerSample / 8) * entry->_channels;
+
+			// Initialize the codec (if necessary)
+			entry->initCodec();
 		}
 	}
 }
@@ -217,6 +221,9 @@ void QuickTimeAudioDecoder::setAudioStreamPos(const Timestamp &where) {
 	Audio::QuickTimeAudioDecoder::AudioSampleDesc *entry = (Audio::QuickTimeAudioDecoder::AudioSampleDesc *)_tracks[_audioTrackIndex]->sampleDescs[0];
 	_audStream = Audio::makeQueuingAudioStream(entry->_sampleRate, entry->_channels == 2);
 
+	// Reinitialize the codec
+	entry->initCodec();
+
 	// First, we need to track down what audio sample we need
 	Audio::Timestamp curAudioTime = where.convertToFramerate(_tracks[_audioTrackIndex]->timeScale);
 	uint32 sample = curAudioTime.totalNumberOfFrames();
@@ -266,6 +273,11 @@ QuickTimeAudioDecoder::AudioSampleDesc::AudioSampleDesc(Common::QuickTimeParser:
 	_samplesPerFrame = 0;
 	_bytesPerFrame = 0;
 	_bitsPerSample = 0;
+	_codec = 0;
+}
+
+QuickTimeAudioDecoder::AudioSampleDesc::~AudioSampleDesc() {
+	delete _codec;
 }
 
 bool QuickTimeAudioDecoder::AudioSampleDesc::isAudioCodecSupported() const {
@@ -313,7 +325,12 @@ AudioStream *QuickTimeAudioDecoder::AudioSampleDesc::createAudioStream(Common::S
 	if (!stream)
 		return 0;
 
-	if (_codecTag == MKTAG('t', 'w', 'o', 's') || _codecTag == MKTAG('r', 'a', 'w', ' ')) {
+	if (_codec) {
+		// If we've loaded a codec, make sure we use first
+		AudioStream *audioStream = _codec->decodeFrame(*stream);
+		delete stream;
+		return audioStream;
+	} else if (_codecTag == MKTAG('t', 'w', 'o', 's') || _codecTag == MKTAG('r', 'a', 'w', ' ')) {
 		// Fortunately, most of the audio used in Myst videos is raw...
 		uint16 flags = 0;
 		if (_codecTag == MKTAG('r', 'a', 'w', ' '))
@@ -330,12 +347,6 @@ AudioStream *QuickTimeAudioDecoder::AudioSampleDesc::createAudioStream(Common::S
 	} else if (_codecTag == MKTAG('i', 'm', 'a', '4')) {
 		// Riven uses this codec (as do some Myst ME videos)
 		return makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), kADPCMApple, _sampleRate, _channels, 34);
-	} else if (_codecTag == MKTAG('m', 'p', '4', 'a')) {
-		// The 7th Guest iOS uses an MPEG-4 codec
-#ifdef USE_FAAD
-		if (_parentTrack->objectTypeMP4 == 0x40)
-			return makeAACStream(stream, DisposeAfterUse::YES, _parentTrack->extraData);
-#endif
 #ifdef AUDIO_QDM2_H
 	} else if (_codecTag == MKTAG('Q', 'D', 'M', '2')) {
 		// Myst ME uses this codec for many videos
@@ -344,10 +355,24 @@ AudioStream *QuickTimeAudioDecoder::AudioSampleDesc::createAudioStream(Common::S
 	}
 
 	error("Unsupported audio codec");
-
 	return NULL;
 }
 
+void QuickTimeAudioDecoder::AudioSampleDesc::initCodec() {
+	delete _codec; _codec = 0;
+
+	switch (_codecTag) {
+	case MKTAG('m', 'p', '4', 'a'):
+#ifdef USE_FAAD
+		if (_parentTrack->objectTypeMP4 == 0x40)
+			_codec = makeAACDecoder(_parentTrack->extraData);
+#endif
+		break;
+	default:
+		break;
+	}
+}
+
 /**
  * A wrapper around QuickTimeAudioDecoder that implements the RewindableAudioStream API
  */
diff --git a/audio/decoders/quicktime_intern.h b/audio/decoders/quicktime_intern.h
index f288d56..7ce06b8 100644
--- a/audio/decoders/quicktime_intern.h
+++ b/audio/decoders/quicktime_intern.h
@@ -45,6 +45,7 @@ namespace Common {
 namespace Audio {
 
 class AudioStream;
+class Codec;
 class QueuingAudioStream;
 
 class QuickTimeAudioDecoder : public Common::QuickTimeParser {
@@ -68,10 +69,12 @@ protected:
 	class AudioSampleDesc : public Common::QuickTimeParser::SampleDesc {
 	public:
 		AudioSampleDesc(Common::QuickTimeParser::Track *parentTrack, uint32 codecTag);
+		~AudioSampleDesc();
 
 		bool isAudioCodecSupported() const;
 		uint32 getAudioChunkSampleCount(uint chunk) const;
 		AudioStream *createAudioStream(Common::SeekableReadStream *stream) const;
+		void initCodec();
 
 		// TODO: Make private in the long run
 		uint16 _bitsPerSample;
@@ -79,6 +82,8 @@ protected:
 		uint32 _sampleRate;
 		uint32 _samplesPerFrame;
 		uint32 _bytesPerFrame;
+
+		Codec *_codec;
 	};
 
 	// Common::QuickTimeParser API


Commit: 46aabed3f5bdb3549e3c804793b5198de4b1702c
    https://github.com/scummvm/scummvm/commit/46aabed3f5bdb3549e3c804793b5198de4b1702c
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2011-07-10T12:50:47-07:00

Commit Message:
AUDIO: Fix QDM2 sound in QuickTime files

Changed paths:
    audio/decoders/qdm2.cpp
    audio/decoders/qdm2.h
    audio/decoders/quicktime.cpp



diff --git a/audio/decoders/qdm2.cpp b/audio/decoders/qdm2.cpp
index a178c36..ec2911e 100644
--- a/audio/decoders/qdm2.cpp
+++ b/audio/decoders/qdm2.cpp
@@ -28,7 +28,9 @@
 #ifdef AUDIO_QDM2_H
 
 #include "audio/audiostream.h"
+#include "audio/decoders/codec.h"
 #include "audio/decoders/qdm2data.h"
+#include "audio/decoders/raw.h"
 
 #include "common/array.h"
 #include "common/debug.h"
@@ -150,19 +152,14 @@ struct RDFTContext {
 	FFTContext fft;
 };
 
-class QDM2Stream : public AudioStream {
+class QDM2Stream : public Codec {
 public:
-	QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData);
+	QDM2Stream(Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData);
 	~QDM2Stream();
 
-	bool isStereo() const { return _channels == 2; }
-	bool endOfData() const { return _stream->pos() >= _stream->size() && _outputSamples.size() == 0 && _subPacket == 0; }
-	int getRate() const { return _sampleRate; }
-	int readBuffer(int16 *buffer, const int numSamples);
+	AudioStream *decodeFrame(Common::SeekableReadStream &stream);
 
 private:
-	Common::SeekableReadStream *_stream;
-
 	// Parameters from codec header, do not change during playback
 	uint8 _channels;
 	uint16 _sampleRate;
@@ -204,7 +201,6 @@ private:
 	// I/O data
 	uint8 *_compressedData;
 	float _outputBuffer[1024];
-	Common::Array<int16> _outputSamples;
 
 	// Synthesis filter
 	int16 ff_mpa_synth_window[512];
@@ -285,7 +281,7 @@ private:
 	void qdm2_fft_tone_synthesizer(uint8 sub_packet);
 	void qdm2_calculate_fft(int channel);
 	void qdm2_synthesis_filter(uint8 index);
-	int qdm2_decodeFrame(Common::SeekableReadStream *in);
+	bool qdm2_decodeFrame(Common::SeekableReadStream &in, QueuingAudioStream *audioStream);
 };
 
 // Fix compilation for non C99-compliant compilers, like MSVC
@@ -1711,7 +1707,7 @@ void QDM2Stream::initVlc(void) {
 	}
 }
 
-QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData) {
+QDM2Stream::QDM2Stream(Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData) {
 	uint32 tmp;
 	int32 tmp_s;
 	int tmp_val;
@@ -1719,7 +1715,6 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS
 
 	debug(1, "QDM2Stream::QDM2Stream() Call");
 
-	_stream = stream;
 	_compressedData = NULL;
 	_subPacket = 0;
 	_superBlockStart = 0;
@@ -1906,11 +1901,13 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS
 	initNoiseSamples();
 
 	_compressedData = new uint8[_packetSize];
+
+	if (disposeExtraData == DisposeAfterUse::YES)
+		delete extraData;
 }
 
 QDM2Stream::~QDM2Stream() {
 	delete[] _compressedData;
-	delete _stream;
 }
 
 static int qdm2_get_vlc(GetBitContext *gb, VLC *vlc, int flag, int depth) {
@@ -3158,30 +3155,30 @@ void QDM2Stream::qdm2_synthesis_filter(uint8 index)
 			_outputBuffer[_channels * i + ch] += (float)(samples[_channels * sub_sampling * i + ch] >> (sizeof(int16)*8-16));
 }
 
-int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
-	debug(1, "QDM2Stream::qdm2_decodeFrame in->pos(): %d in->size(): %d", in->pos(), in->size());
+bool QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream &in, QueuingAudioStream *audioStream) {
+	debug(1, "QDM2Stream::qdm2_decodeFrame in.pos(): %d in.size(): %d", in.pos(), in.size());
 	int ch, i;
 	const int frame_size = (_sFrameSize * _channels);
 
 	// If we're in any packet but the first, seek back to the first
 	if (_subPacket == 0)
-		_superBlockStart = in->pos();
+		_superBlockStart = in.pos();
 	else
-		in->seek(_superBlockStart);
+		in.seek(_superBlockStart);
 
 	// select input buffer
-	if (in->eos() || in->pos() >= in->size()) {
+	if (in.eos() || in.pos() >= in.size()) {
 		debug(1, "QDM2Stream::qdm2_decodeFrame End of Input Stream");
-		return 0;
+		return false;
 	}
 
-	if ((in->size() - in->pos()) < _packetSize) {
-		debug(1, "QDM2Stream::qdm2_decodeFrame Insufficient Packet Data in Input Stream Found: %d Need: %d", in->size() - in->pos(), _packetSize);
-		return 0;
+	if ((in.size() - in.pos()) < _packetSize) {
+		debug(1, "QDM2Stream::qdm2_decodeFrame Insufficient Packet Data in Input Stream Found: %d Need: %d", in.size() - in.pos(), _packetSize);
+		return false;
 	}
 
-	if (!in->eos()) {
-		in->read(_compressedData, _packetSize);
+	if (!in.eos()) {
+		in.read(_compressedData, _packetSize);
 		debug(1, "QDM2Stream::qdm2_decodeFrame constructed input data");
 	}
 
@@ -3190,7 +3187,7 @@ int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
 	memset(&_outputBuffer[frame_size], 0, frame_size * sizeof(float));
 	debug(1, "QDM2Stream::qdm2_decodeFrame cleared outputBuffer");
 
-	if (!in->eos()) {
+	if (!in.eos()) {
 		// decode block of QDM2 compressed data
 		debug(1, "QDM2Stream::qdm2_decodeFrame decode block of QDM2 compressed data");
 		if (_subPacket == 0) {
@@ -3218,7 +3215,7 @@ int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
 
 			if (!_hasErrors && _subPacketListC[0].packet != NULL) {
 				error("QDM2 : has errors, and C list is not empty");
-				return 0;
+				return false;
 			}
 		}
 
@@ -3236,6 +3233,12 @@ int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
 		debug(1, "QDM2Stream::qdm2_decodeFrame clip and convert output float[] to 16bit signed samples");
 	}
 
+	if (frame_size == 0)
+		return false;
+
+	// Prepare a buffer for queuing
+	uint16 *outputBuffer = (uint16 *)malloc(frame_size * 2);
+
 	for (i = 0; i < frame_size; i++) {
 		int value = (int)_outputBuffer[i];
 
@@ -3244,34 +3247,35 @@ int QDM2Stream::qdm2_decodeFrame(Common::SeekableReadStream *in) {
 		else if (value < -SOFTCLIP_THRESHOLD)
 			value = (value < -HARDCLIP_THRESHOLD) ? -32767 : -_softclipTable[-value - SOFTCLIP_THRESHOLD];
 
-		_outputSamples.push_back(value);
+		outputBuffer[i] = value;
 	}
-	return frame_size;
-}
 
-int QDM2Stream::readBuffer(int16 *buffer, const int numSamples) {
-	debug(1, "QDM2Stream::readBuffer numSamples: %d", numSamples);
-	int32 decodedSamples = _outputSamples.size();
-	int32 i;
+	// Queue the translated buffer to our stream
+	byte flags = FLAG_16BITS;
 
-	while (decodedSamples < numSamples) {
-		i = qdm2_decodeFrame(_stream);
-		if (i == 0)
-			break; // Out Of Decode Frames...
-		decodedSamples += i;
-	}
+	if (_channels == 2)
+		flags |= FLAG_STEREO;
+
+#ifdef SCUMM_LITTLE_ENDIAN
+	flags |= FLAG_LITTLE_ENDIAN;
+#endif
+
+	audioStream->queueBuffer((byte *)outputBuffer, frame_size * 2, DisposeAfterUse::YES, flags);
+
+	return true;
+}
 
-	if (decodedSamples > numSamples)
-		decodedSamples = numSamples;
+AudioStream *QDM2Stream::decodeFrame(Common::SeekableReadStream &stream) {
+	QueuingAudioStream *audioStream = makeQueuingAudioStream(_sampleRate, _channels == 2);
 
-	for (i = 0; i < decodedSamples; i++)
-		buffer[i] = _outputSamples.remove_at(0);
+	while (qdm2_decodeFrame(stream, audioStream))
+		;
 
-	return decodedSamples;
+	return audioStream;
 }
 
-AudioStream *makeQDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData) {
-	return new QDM2Stream(stream, extraData);
+Codec *makeQDM2Decoder(Common::SeekableReadStream *extraData, DisposeAfterUse::Flag disposeExtraData) {
+	return new QDM2Stream(extraData, disposeExtraData);
 }
 
 } // End of namespace Audio
diff --git a/audio/decoders/qdm2.h b/audio/decoders/qdm2.h
index c0ec647..f0793e3 100644
--- a/audio/decoders/qdm2.h
+++ b/audio/decoders/qdm2.h
@@ -26,22 +26,25 @@
 #ifndef AUDIO_QDM2_H
 #define AUDIO_QDM2_H
 
+#include "common/types.h"
+
 namespace Common {
 class SeekableReadStream;
 }
 
 namespace Audio {
 
-class AudioStream;
+class Codec;
 
 /**
- * Create a new AudioStream from the QDM2 data in the given stream.
+ * Create a new Codec from the QDM2 data in the given stream.
  *
- * @param stream       the SeekableReadStream from which to read the FLAC data
- * @param extraData    the QuickTime extra data stream
- * @return   a new AudioStream, or NULL, if an error occurred
+ * @param extraData           the QuickTime extra data stream
+ * @param disposeExtraData    the QuickTime extra data stream
+ * @return   a new Codec, or NULL, if an error occurred
  */
-AudioStream *makeQDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadStream *extraData);
+Codec *makeQDM2Decoder(Common::SeekableReadStream *extraData,
+                       DisposeAfterUse::Flag disposeExtraData = DisposeAfterUse::NO);
 
 } // End of namespace Audio
 
diff --git a/audio/decoders/quicktime.cpp b/audio/decoders/quicktime.cpp
index 4531cce..a39fedc 100644
--- a/audio/decoders/quicktime.cpp
+++ b/audio/decoders/quicktime.cpp
@@ -347,11 +347,6 @@ AudioStream *QuickTimeAudioDecoder::AudioSampleDesc::createAudioStream(Common::S
 	} else if (_codecTag == MKTAG('i', 'm', 'a', '4')) {
 		// Riven uses this codec (as do some Myst ME videos)
 		return makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), kADPCMApple, _sampleRate, _channels, 34);
-#ifdef AUDIO_QDM2_H
-	} else if (_codecTag == MKTAG('Q', 'D', 'M', '2')) {
-		// Myst ME uses this codec for many videos
-		return makeQDM2Stream(stream, _parentTrack->extraData);
-#endif
 	}
 
 	error("Unsupported audio codec");
@@ -362,6 +357,11 @@ void QuickTimeAudioDecoder::AudioSampleDesc::initCodec() {
 	delete _codec; _codec = 0;
 
 	switch (_codecTag) {
+	case MKTAG('Q', 'D', 'M', '2'):
+#ifdef AUDIO_QDM2_H
+		_codec = makeQDM2Decoder(_parentTrack->extraData);
+#endif
+		break;
 	case MKTAG('m', 'p', '4', 'a'):
 #ifdef USE_FAAD
 		if (_parentTrack->objectTypeMP4 == 0x40)






More information about the Scummvm-git-logs mailing list