diff options
| author | Alyssa Milburn | 2011-08-22 20:03:05 +0200 | 
|---|---|---|
| committer | Alyssa Milburn | 2011-08-22 20:03:05 +0200 | 
| commit | 84063dc9727a9f55e09d39574027beab695680e6 (patch) | |
| tree | d71a9599cb550d9f7949a2d3209574064e054d85 /audio/decoders | |
| parent | c6e89df3d940747a85d447f172e2323c800f5eaf (diff) | |
| parent | a39a3eda46aea108a51556f001617ad28d29e520 (diff) | |
| download | scummvm-rg350-84063dc9727a9f55e09d39574027beab695680e6.tar.gz scummvm-rg350-84063dc9727a9f55e09d39574027beab695680e6.tar.bz2 scummvm-rg350-84063dc9727a9f55e09d39574027beab695680e6.zip  | |
Merge remote-tracking branch 'origin/master' into soltys_wip2
Diffstat (limited to 'audio/decoders')
| -rw-r--r-- | audio/decoders/aac.cpp | 127 | ||||
| -rw-r--r-- | audio/decoders/aac.h | 19 | ||||
| -rw-r--r-- | audio/decoders/adpcm.cpp | 10 | ||||
| -rw-r--r-- | audio/decoders/adpcm_intern.h | 5 | ||||
| -rw-r--r-- | audio/decoders/codec.h | 44 | ||||
| -rw-r--r-- | audio/decoders/mp3.cpp | 10 | ||||
| -rw-r--r-- | audio/decoders/qdm2.cpp | 116 | ||||
| -rw-r--r-- | audio/decoders/qdm2.h | 15 | ||||
| -rw-r--r-- | audio/decoders/quicktime.cpp | 58 | ||||
| -rw-r--r-- | audio/decoders/quicktime.h | 7 | ||||
| -rw-r--r-- | audio/decoders/quicktime_intern.h | 12 | ||||
| -rw-r--r-- | audio/decoders/raw.cpp | 22 | ||||
| -rw-r--r-- | audio/decoders/vorbis.cpp | 12 | 
13 files changed, 222 insertions, 235 deletions
diff --git a/audio/decoders/aac.cpp b/audio/decoders/aac.cpp index 874062a702..7700bb3215 100644 --- a/audio/decoders/aac.cpp +++ b/audio/decoders/aac.cpp @@ -8,19 +8,16 @@   * 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$ - *   */  #include "audio/decoders/aac.h" @@ -28,74 +25,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(); - -	int readBuffer(int16 *buffer, const int numSamples); +	~AACDecoder(); -	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 +74,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); + +		byte flags = FLAG_16BITS; -		memcpy(buffer + samples, decodedSamples, copySamples * 2); -		samples += copySamples; +		if (_channels == 2) +			flags |= FLAG_STEREO; -		// 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); -		} +#ifdef SCUMM_LITTLE_ENDIAN +		flags |= FLAG_LITTLE_ENDIAN; +#endif -		_inBufferPos += frameInfo.bytesconsumed; +		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 efcbcc6f42..68e322c844 100644 --- a/audio/decoders/aac.h +++ b/audio/decoders/aac.h @@ -8,19 +8,16 @@   * 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$ - *   */  /** @@ -43,23 +40,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/adpcm.cpp b/audio/decoders/adpcm.cpp index f75196c882..535652a0b3 100644 --- a/audio/decoders/adpcm.cpp +++ b/audio/decoders/adpcm.cpp @@ -41,8 +41,7 @@ namespace Audio {  //   <http://wiki.multimedia.cx/index.php?title=Microsoft_IMA_ADPCM>.  ADPCMStream::ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign) -	: _stream(stream), -		_disposeAfterUse(disposeAfterUse), +	: _stream(stream, disposeAfterUse),  		_startpos(stream->pos()),  		_endpos(_startpos + size),  		_channels(channels), @@ -52,11 +51,6 @@ ADPCMStream::ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Fl  	reset();  } -ADPCMStream::~ADPCMStream() { -	if (_disposeAfterUse == DisposeAfterUse::YES) -		delete _stream; -} -  void ADPCMStream::reset() {  	memset(&_status, 0, sizeof(_status));  	_blockPos[0] = _blockPos[1] = _blockAlign; // To make sure first header is read @@ -234,7 +228,7 @@ int MSIma_ADPCMStream::readBuffer(int16 *buffer, const int numSamples) {  		while (samples < numSamples && _samplesLeft[0] != 0) {  			for (int i = 0; i < _channels; i++) { -				buffer[samples] = _buffer[i][8 - _samplesLeft[i]]; +				buffer[samples + i] = _buffer[i][8 - _samplesLeft[i]];  				_samplesLeft[i]--;  			} diff --git a/audio/decoders/adpcm_intern.h b/audio/decoders/adpcm_intern.h index c9f894fb84..38514d7fca 100644 --- a/audio/decoders/adpcm_intern.h +++ b/audio/decoders/adpcm_intern.h @@ -33,6 +33,7 @@  #include "audio/audiostream.h"  #include "common/endian.h" +#include "common/ptr.h"  #include "common/stream.h"  #include "common/textconsole.h" @@ -41,8 +42,7 @@ namespace Audio {  class ADPCMStream : public RewindableAudioStream {  protected: -	Common::SeekableReadStream *_stream; -	const DisposeAfterUse::Flag _disposeAfterUse; +	Common::DisposablePtr<Common::SeekableReadStream> _stream;  	const int32 _startpos;  	const int32 _endpos;  	const int _channels; @@ -62,7 +62,6 @@ protected:  public:  	ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, int rate, int channels, uint32 blockAlign); -	~ADPCMStream();  	virtual bool endOfData() const { return (_stream->eos() || _stream->pos() >= _endpos); }  	virtual bool isStereo() const	{ return _channels == 2; } diff --git a/audio/decoders/codec.h b/audio/decoders/codec.h new file mode 100644 index 0000000000..93b6878dee --- /dev/null +++ b/audio/decoders/codec.h @@ -0,0 +1,44 @@ +/* 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_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/mp3.cpp b/audio/decoders/mp3.cpp index 8d7f006ec7..00669945c2 100644 --- a/audio/decoders/mp3.cpp +++ b/audio/decoders/mp3.cpp @@ -25,6 +25,7 @@  #ifdef USE_MAD  #include "common/debug.h" +#include "common/ptr.h"  #include "common/stream.h"  #include "common/textconsole.h"  #include "common/util.h" @@ -52,8 +53,7 @@ protected:  		MP3_STATE_EOS		// end of data reached (may need to loop)  	}; -	Common::SeekableReadStream *_inStream; -	DisposeAfterUse::Flag _disposeAfterUse; +	Common::DisposablePtr<Common::SeekableReadStream> _inStream;  	uint _posInFrame;  	State _state; @@ -95,8 +95,7 @@ protected:  };  MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) : -	_inStream(inStream), -	_disposeAfterUse(dispose), +	_inStream(inStream, dispose),  	_posInFrame(0),  	_state(MP3_STATE_INIT),  	_length(0, 1000), @@ -134,9 +133,6 @@ MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag  MP3Stream::~MP3Stream() {  	deinitStream(); - -	if (_disposeAfterUse == DisposeAfterUse::YES) -		delete _inStream;  }  void MP3Stream::decodeMP3Data() { diff --git a/audio/decoders/qdm2.cpp b/audio/decoders/qdm2.cpp index a178c363b5..19b30217e9 100644 --- a/audio/decoders/qdm2.cpp +++ b/audio/decoders/qdm2.cpp @@ -28,10 +28,13 @@  #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" +#include "common/math.h"  #include "common/stream.h"  #include "common/textconsole.h" @@ -150,19 +153,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 +202,6 @@ private:  	// I/O data  	uint8 *_compressedData;  	float _outputBuffer[1024]; -	Common::Array<int16> _outputSamples;  	// Synthesis filter  	int16 ff_mpa_synth_window[512]; @@ -285,7 +282,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 @@ -293,21 +290,6 @@ private:  typedef signed long long int int64_t;  #endif -// Integer log2 function. This is much faster than invoking -// double precision C99 log2 math functions or equivalent, since -// this is only used to determine maximum number of bits needed -// i.e. only non-fractional part is needed. Also, the double -// version is incorrect for exact cases due to floating point -// rounding errors. -static inline int scummvm_log2(int n) { -	int ret = -1; -	while(n != 0) { -		n /= 2; -		ret++; -	} -	return ret; -} -  #define QDM2_LIST_ADD(list, size, packet) \  	do { \  		if (size > 0) \ @@ -1711,7 +1693,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 +1701,6 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS  	debug(1, "QDM2Stream::QDM2Stream() Call"); -	_stream = stream;  	_compressedData = NULL;  	_subPacket = 0;  	_superBlockStart = 0; @@ -1841,11 +1822,11 @@ QDM2Stream::QDM2Stream(Common::SeekableReadStream *stream, Common::SeekableReadS  			warning("QDM2Stream::QDM2Stream() u4 field not 0");  	} -	_fftOrder = scummvm_log2(_frameSize) + 1; +	_fftOrder = Common::intLog2(_frameSize) + 1;  	_fftFrameSize = 2 * _frameSize; // complex has two floats  	// something like max decodable tones -	_groupOrder = scummvm_log2(_blockSize) + 1; +	_groupOrder = Common::intLog2(_blockSize) + 1;  	_sFrameSize = _blockSize / 16; // 16 iterations per super block  	_subSampling = _fftOrder - 7; @@ -1906,11 +1887,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 +3141,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 +3173,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 +3201,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 +3219,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 +3233,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 c0ec647bfd..f0793e3c1e 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 0ad2821cd5..8cf0305e88 100644 --- a/audio/decoders/quicktime.cpp +++ b/audio/decoders/quicktime.cpp @@ -8,19 +8,16 @@   * 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$ - *   */  #include "common/debug.h" @@ -30,6 +27,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 +84,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 +218,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 +270,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 +322,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,24 +344,32 @@ 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 -		return makeQDM2Stream(stream, _parentTrack->extraData); -#endif  	}  	error("Unsupported audio codec"); -  	return NULL;  } +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) +			_codec = makeAACDecoder(_parentTrack->extraData); +#endif +		break; +	default: +		break; +	} +} +  /**   * A wrapper around QuickTimeAudioDecoder that implements the RewindableAudioStream API   */ diff --git a/audio/decoders/quicktime.h b/audio/decoders/quicktime.h index 9f6c6c20e0..4dd1a57710 100644 --- a/audio/decoders/quicktime.h +++ b/audio/decoders/quicktime.h @@ -8,19 +8,16 @@   * 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$ - *   */  /** diff --git a/audio/decoders/quicktime_intern.h b/audio/decoders/quicktime_intern.h index f288d5604b..e31a1d3872 100644 --- a/audio/decoders/quicktime_intern.h +++ b/audio/decoders/quicktime_intern.h @@ -8,19 +8,16 @@   * 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$ - *   */  /** @@ -45,6 +42,7 @@ namespace Common {  namespace Audio {  class AudioStream; +class Codec;  class QueuingAudioStream;  class QuickTimeAudioDecoder : public Common::QuickTimeParser { @@ -68,10 +66,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 +79,8 @@ protected:  		uint32 _sampleRate;  		uint32 _samplesPerFrame;  		uint32 _bytesPerFrame; + +		Codec *_codec;  	};  	// Common::QuickTimeParser API diff --git a/audio/decoders/raw.cpp b/audio/decoders/raw.cpp index 4789fd0f36..881b8c1d6a 100644 --- a/audio/decoders/raw.cpp +++ b/audio/decoders/raw.cpp @@ -51,7 +51,7 @@ template<bool is16Bit, bool isUnsigned, bool isLE>  class RawStream : public SeekableAudioStream {  public:  	RawStream(int rate, bool stereo, DisposeAfterUse::Flag disposeStream, Common::SeekableReadStream *stream, const RawStreamBlockList &blocks) -		: _rate(rate), _isStereo(stereo), _playtime(0, rate), _stream(stream), _disposeAfterUse(disposeStream), _blocks(blocks), _curBlock(_blocks.begin()), _blockLeft(0), _buffer(0) { +		: _rate(rate), _isStereo(stereo), _playtime(0, rate), _stream(stream, disposeStream), _blocks(blocks), _curBlock(_blocks.begin()), _blockLeft(0), _buffer(0) {  		assert(_blocks.size() > 0); @@ -82,9 +82,6 @@ public:  	}  	~RawStream() { -		if (_disposeAfterUse == DisposeAfterUse::YES) -			delete _stream; -  		delete[] _buffer;  	} @@ -98,15 +95,14 @@ public:  	bool seek(const Timestamp &where);  private: -	const int _rate;                               ///< Sample rate of stream -	const bool _isStereo;                          ///< Whether this is an stereo stream -	Timestamp _playtime;                           ///< Calculated total play time -	Common::SeekableReadStream *_stream;           ///< Stream to read data from -	const DisposeAfterUse::Flag _disposeAfterUse;  ///< Indicates whether the stream object should be deleted when this RawStream is destructed -	const RawStreamBlockList _blocks;              ///< Audio block list - -	RawStreamBlockList::const_iterator _curBlock;  ///< Current audio block number -	int32 _blockLeft;                              ///< How many bytes are still left in the current block +	const int _rate;                                           ///< Sample rate of stream +	const bool _isStereo;                                      ///< Whether this is an stereo stream +	Timestamp _playtime;                                       ///< Calculated total play time +	Common::DisposablePtr<Common::SeekableReadStream> _stream; ///< Stream to read data from +	const RawStreamBlockList _blocks;                          ///< Audio block list + +	RawStreamBlockList::const_iterator _curBlock;              ///< Current audio block number +	int32 _blockLeft;                                          ///< How many bytes are still left in the current block  	/**  	 * Advance one block in the stream in case diff --git a/audio/decoders/vorbis.cpp b/audio/decoders/vorbis.cpp index 2724dd1f02..64cacb4d58 100644 --- a/audio/decoders/vorbis.cpp +++ b/audio/decoders/vorbis.cpp @@ -29,6 +29,7 @@  #ifdef USE_VORBIS +#include "common/ptr.h"  #include "common/stream.h"  #include "common/textconsole.h"  #include "common/util.h" @@ -42,6 +43,7 @@  #include <tremor/ivorbisfile.h>  #endif  #else +#define OV_EXCLUDE_STATIC_CALLBACKS  #include <vorbis/vorbisfile.h>  #endif @@ -88,8 +90,7 @@ static ov_callbacks g_stream_wrap = {  class VorbisStream : public SeekableAudioStream {  protected: -	Common::SeekableReadStream *_inStream; -	DisposeAfterUse::Flag _disposeAfterUse; +	Common::DisposablePtr<Common::SeekableReadStream> _inStream;  	bool _isStereo;  	int _rate; @@ -120,10 +121,9 @@ protected:  };  VorbisStream::VorbisStream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) : -	_inStream(inStream), -	_disposeAfterUse(dispose), +	_inStream(inStream, dispose),  	_length(0, 1000), -	_bufferEnd(_buffer + ARRAYSIZE(_buffer)) { +	_bufferEnd(ARRAYEND(_buffer)) {  	int res = ov_open_callbacks(inStream, &_ovFile, NULL, 0, g_stream_wrap);  	if (res < 0) { @@ -149,8 +149,6 @@ VorbisStream::VorbisStream(Common::SeekableReadStream *inStream, DisposeAfterUse  VorbisStream::~VorbisStream() {  	ov_clear(&_ovFile); -	if (_disposeAfterUse == DisposeAfterUse::YES) -		delete _inStream;  }  int VorbisStream::readBuffer(int16 *buffer, const int numSamples) {  | 
