diff options
| -rw-r--r-- | audio/decoders/qdm2.cpp | 96 | ||||
| -rw-r--r-- | audio/decoders/qdm2.h | 15 | ||||
| -rw-r--r-- | audio/decoders/quicktime.cpp | 10 | 
3 files changed, 64 insertions, 57 deletions
| diff --git a/audio/decoders/qdm2.cpp b/audio/decoders/qdm2.cpp index a178c363b5..ec2911ef20 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 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 4531ccee19..a39fedc1d6 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) | 
