[Scummvm-cvs-logs] scummvm master -> c8a7e39e0522b32e29ab403188f56bee9cf1da27
clone2727
clone2727 at gmail.com
Mon Aug 31 03:05:28 CEST 2015
This automated email contains information about 13 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
030e4d0608 AUDIO: Make Rewindable- and SeekableAudioStream inherit virtually
52f67cba39 AUDIO: Split the seeking MP3 class from the base decoding stream
ccd8dbf4ba AUDIO: Add an AudioStream subclass for packetized audio
562234b96b AUDIO: Implement a packetized version of MP3
14e57ca76f VIDEO: Switch MPEG-PS audio code to use the packetized MP3 code
ba4469da6a ZVISION: Cleanup the AVI decoder subclass
de2f4e6982 VIDEO: Add support for MP3 in AVI
a64aff0287 AUDIO: Add a class to easily make stateless PacketizedAudioStreams
3aa9e2c581 AUDIO: Add a packetized version of the PCM stream
331d8ece21 AUDIO: Add a packetized version of ADPCM streams
72239a25f9 AUDIO: Add a NullAudioStream for streams that are dead-on-arrival
561d1a1d62 VIDEO: Switch to all packetized streams for AVI
c8a7e39e05 AUDIO: Mark the old Codec class as deprecated
Commit: 030e4d06088cb75e871f1373b662d14262fbfc93
https://github.com/scummvm/scummvm/commit/030e4d06088cb75e871f1373b662d14262fbfc93
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:53-04:00
Commit Message:
AUDIO: Make Rewindable- and SeekableAudioStream inherit virtually
Changed paths:
audio/audiostream.h
engines/groovie/music.cpp
engines/lastexpress/data/snd.cpp
engines/lastexpress/data/snd.h
engines/mohawk/sound.cpp
engines/mohawk/sound.h
diff --git a/audio/audiostream.h b/audio/audiostream.h
index 347a37b..840a25a 100644
--- a/audio/audiostream.h
+++ b/audio/audiostream.h
@@ -86,7 +86,7 @@ public:
* to its initial state. Note that rewinding itself is not required to
* be working when the stream is being played by Mixer!
*/
-class RewindableAudioStream : public AudioStream {
+class RewindableAudioStream : public virtual AudioStream {
public:
/**
* Rewinds the stream to its start.
@@ -153,7 +153,7 @@ AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops);
* interface for seeking. The seeking itself is not required to be
* working while the stream is being played by Mixer!
*/
-class SeekableAudioStream : public RewindableAudioStream {
+class SeekableAudioStream : public virtual RewindableAudioStream {
public:
/**
* Tries to load a file by trying all available formats.
diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp
index c00290b..cf65e01 100644
--- a/engines/groovie/music.cpp
+++ b/engines/groovie/music.cpp
@@ -934,16 +934,18 @@ bool MusicPlayerIOS::load(uint32 fileref, bool loop) {
}
// Create the audio stream
- Audio::AudioStream *audStream = Audio::SeekableAudioStream::openStreamFile(info.filename);
+ Audio::SeekableAudioStream *seekStream = Audio::SeekableAudioStream::openStreamFile(info.filename);
- if (!audStream) {
+ if (!seekStream) {
warning("Could not play audio file '%s'", info.filename.c_str());
return false;
}
+ Audio::AudioStream *audStream = seekStream;
+
// Loop if requested
if (loop)
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ audStream = Audio::makeLoopingAudioStream(seekStream, 0);
// MIDI player handles volume reset on load, IOS player doesn't - force update here
updateVolume();
diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp
index 2a221af..e310baf 100644
--- a/engines/lastexpress/data/snd.cpp
+++ b/engines/lastexpress/data/snd.cpp
@@ -442,7 +442,7 @@ void SimpleSound::loadHeader(Common::SeekableReadStream *in) {
_blockSize = _size / _blocks;
}
-Audio::AudioStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId) const {
+LastExpress_ADPCMStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId) const {
return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize, filterId);
}
@@ -489,7 +489,7 @@ void StreamedSound::setFilterId(int32 filterId) {
if (!_as)
return;
- ((LastExpress_ADPCMStream *)_as)->setFilterId(filterId);
+ _as->setFilterId(filterId);
}
//////////////////////////////////////////////////////////////////////////
@@ -525,8 +525,8 @@ void AppendableSound::queueBuffer(Common::SeekableReadStream *bufferIn) {
// Setup the ADPCM decoder
uint32 sizeIn = (uint32)bufferIn->size();
- Audio::AudioStream *adpcm = makeDecoder(bufferIn, sizeIn);
- ((LastExpress_ADPCMStream *)adpcm)->setFilterId(16);
+ LastExpress_ADPCMStream *adpcm = makeDecoder(bufferIn, sizeIn);
+ adpcm->setFilterId(16);
// Queue the stream
_as->queueAudioStream(adpcm);
diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h
index f489304..19e5fda 100644
--- a/engines/lastexpress/data/snd.h
+++ b/engines/lastexpress/data/snd.h
@@ -49,6 +49,8 @@ class SeekableReadStream;
namespace LastExpress {
+class LastExpress_ADPCMStream;
+
class SimpleSound {
public:
SimpleSound();
@@ -59,7 +61,7 @@ public:
protected:
void loadHeader(Common::SeekableReadStream *in);
- Audio::AudioStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId = -1) const;
+ LastExpress_ADPCMStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, int32 filterId = -1) const;
void play(Audio::AudioStream *as);
uint32 _size; ///< data size
@@ -82,7 +84,7 @@ public:
void setFilterId(int32 filterId);
private:
- Audio::AudioStream *_as;
+ LastExpress_ADPCMStream *_as;
bool _loaded;
};
diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp
index 6f18d71..198627e 100644
--- a/engines/mohawk/sound.cpp
+++ b/engines/mohawk/sound.cpp
@@ -77,8 +77,8 @@ void Sound::initMidi() {
_midiParser->setTimerRate(_midiDriver->getBaseTempo());
}
-Audio::AudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
- Audio::AudioStream *audStream = NULL;
+Audio::RewindableAudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
+ Audio::RewindableAudioStream *audStream = NULL;
switch (_vm->getGameType()) {
case GType_MYST:
@@ -109,17 +109,18 @@ Audio::AudioStream *Sound::makeAudioStream(uint16 id, CueList *cueList) {
Audio::SoundHandle *Sound::playSound(uint16 id, byte volume, bool loop, CueList *cueList) {
debug (0, "Playing sound %d", id);
- Audio::AudioStream *audStream = makeAudioStream(id, cueList);
+ Audio::RewindableAudioStream *rewindStream = makeAudioStream(id, cueList);
- if (audStream) {
+ if (rewindStream) {
SndHandle *handle = getHandle();
handle->type = kUsedHandle;
handle->id = id;
- handle->samplesPerSecond = audStream->getRate();
+ handle->samplesPerSecond = rewindStream->getRate();
// Set the stream to loop here if it's requested
+ Audio::AudioStream *audStream = rewindStream;
if (loop)
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &handle->handle, audStream, -1, volume);
return &handle->handle;
@@ -335,11 +336,12 @@ void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16
sndHandle.id = id;
_currentSLSTSounds.push_back(sndHandle);
- Audio::AudioStream *audStream = makeMohawkWaveStream(_vm->getResource(ID_TWAV, id));
+ Audio::RewindableAudioStream *rewindStream = makeMohawkWaveStream(_vm->getResource(ID_TWAV, id));
// Loop here if necessary
+ Audio::AudioStream *audStream = rewindStream;
if (loop)
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
// TODO: Handle fading, possibly just raise the volume of the channel in increments?
@@ -363,7 +365,7 @@ void Sound::resumeSLST() {
_vm->_mixer->pauseHandle(*_currentSLSTSounds[i].handle, false);
}
-Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList) {
+Audio::RewindableAudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList) {
uint32 tag = 0;
ADPCMStatus adpcmStatus;
DataChunk dataChunk;
@@ -507,7 +509,7 @@ Audio::AudioStream *Sound::makeMohawkWaveStream(Common::SeekableReadStream *stre
return NULL;
}
-Audio::AudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
+Audio::RewindableAudioStream *Sound::makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream) {
uint16 header = stream->readUint16BE();
uint16 rate = 0;
uint32 size = 0;
@@ -646,15 +648,15 @@ Audio::SoundHandle *Sound::replaceBackgroundMyst(uint16 id, uint16 volume) {
stopBackgroundMyst();
// Play new sound
- Audio::AudioStream *audStream = makeAudioStream(id);
+ Audio::RewindableAudioStream *rewindStream = makeAudioStream(id);
- if (audStream) {
+ if (rewindStream) {
_mystBackgroundSound.type = kUsedHandle;
_mystBackgroundSound.id = id;
- _mystBackgroundSound.samplesPerSecond = audStream->getRate();
+ _mystBackgroundSound.samplesPerSecond = rewindStream->getRate();
// Set the stream to loop
- audStream = Audio::makeLoopingAudioStream((Audio::RewindableAudioStream *)audStream, 0);
+ Audio::AudioStream *audStream = Audio::makeLoopingAudioStream(rewindStream, 0);
_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_mystBackgroundSound.handle, audStream, -1, volume >> 8);
return &_mystBackgroundSound.handle;
diff --git a/engines/mohawk/sound.h b/engines/mohawk/sound.h
index 49f6751..75c9492 100644
--- a/engines/mohawk/sound.h
+++ b/engines/mohawk/sound.h
@@ -156,13 +156,13 @@ private:
MidiParser *_midiParser;
byte *_midiData;
- static Audio::AudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = NULL);
- static Audio::AudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
+ static Audio::RewindableAudioStream *makeMohawkWaveStream(Common::SeekableReadStream *stream, CueList *cueList = NULL);
+ static Audio::RewindableAudioStream *makeLivingBooksWaveStream_v1(Common::SeekableReadStream *stream);
void initMidi();
Common::Array<SndHandle> _handles;
SndHandle *getHandle();
- Audio::AudioStream *makeAudioStream(uint16 id, CueList *cueList = NULL);
+ Audio::RewindableAudioStream *makeAudioStream(uint16 id, CueList *cueList = NULL);
uint16 convertMystID(uint16 id);
// Myst-specific
Commit: 52f67cba39f466c41ec7e6505e7f48626642e62e
https://github.com/scummvm/scummvm/commit/52f67cba39f466c41ec7e6505e7f48626642e62e
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:53-04:00
Commit Message:
AUDIO: Split the seeking MP3 class from the base decoding stream
Changed paths:
audio/decoders/mp3.cpp
diff --git a/audio/decoders/mp3.cpp b/audio/decoders/mp3.cpp
index feb531f..8550d91 100644
--- a/audio/decoders/mp3.cpp
+++ b/audio/decoders/mp3.cpp
@@ -27,6 +27,7 @@
#include "common/debug.h"
#include "common/ptr.h"
#include "common/stream.h"
+#include "common/substream.h"
#include "common/textconsole.h"
#include "common/util.h"
@@ -45,20 +46,34 @@ namespace Audio {
#pragma mark -
-class MP3Stream : public SeekableAudioStream {
+class BaseMP3Stream : public virtual AudioStream {
+public:
+ BaseMP3Stream();
+ virtual ~BaseMP3Stream();
+
+ bool endOfData() const { return _state == MP3_STATE_EOS; }
+ bool isStereo() const { return MAD_NCHANNELS(&_frame.header) == 2; }
+ int getRate() const { return _frame.header.samplerate; }
+
protected:
+ void decodeMP3Data(Common::ReadStream &stream);
+ void readMP3Data(Common::ReadStream &stream);
+
+ void initStream(Common::ReadStream &stream);
+ void readHeader(Common::ReadStream &stream);
+ void deinitStream();
+
+ int fillBuffer(Common::ReadStream &stream, int16 *buffer, const int numSamples);
+
enum State {
MP3_STATE_INIT, // Need to init the decoder
MP3_STATE_READY, // ready for processing data
MP3_STATE_EOS // end of data reached (may need to loop)
};
- Common::DisposablePtr<Common::SeekableReadStream> _inStream;
-
uint _posInFrame;
State _state;
- Timestamp _length;
mad_timer_t _curTime;
mad_stream _stream;
@@ -71,81 +86,54 @@ protected:
// This buffer contains a slab of input data
byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD];
+};
+class MP3Stream : public BaseMP3Stream, public SeekableAudioStream {
public:
MP3Stream(Common::SeekableReadStream *inStream,
DisposeAfterUse::Flag dispose);
- ~MP3Stream();
+ virtual ~MP3Stream() {}
int readBuffer(int16 *buffer, const int numSamples);
-
- bool endOfData() const { return _state == MP3_STATE_EOS; }
- bool isStereo() const { return MAD_NCHANNELS(&_frame.header) == 2; }
- int getRate() const { return _frame.header.samplerate; }
-
bool seek(const Timestamp &where);
Timestamp getLength() const { return _length; }
+
protected:
- void decodeMP3Data();
- void readMP3Data();
+ Common::ScopedPtr<Common::SeekableReadStream> _inStream;
- void initStream();
- void readHeader();
- void deinitStream();
+ Timestamp _length;
+
+private:
+ static Common::SeekableReadStream *skipID3(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose);
};
-MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
- _inStream(inStream, dispose),
+
+BaseMP3Stream::BaseMP3Stream() :
_posInFrame(0),
_state(MP3_STATE_INIT),
- _length(0, 1000),
_curTime(mad_timer_zero) {
// The MAD_BUFFER_GUARD must always contain zeros (the reason
// for this is that the Layer III Huffman decoder of libMAD
// may read a few bytes beyond the end of the input buffer).
memset(_buf + BUFFER_SIZE, 0, MAD_BUFFER_GUARD);
-
- // Calculate the length of the stream
- initStream();
-
- while (_state != MP3_STATE_EOS)
- readHeader();
-
- // To rule out any invalid sample rate to be encountered here, say in case the
- // MP3 stream is invalid, we just check the MAD error code here.
- // We need to assure this, since else we might trigger an assertion in Timestamp
- // (When getRate() returns 0 or a negative number to be precise).
- // Note that we allow "MAD_ERROR_BUFLEN" as error code here, since according
- // to mad.h it is also set on EOF.
- if ((_stream.error == MAD_ERROR_NONE || _stream.error == MAD_ERROR_BUFLEN) && getRate() > 0)
- _length = Timestamp(mad_timer_count(_curTime, MAD_UNITS_MILLISECONDS), getRate());
-
- deinitStream();
-
- // Reinit stream
- _state = MP3_STATE_INIT;
-
- // Decode the first chunk of data. This is necessary so that _frame
- // is setup and isStereo() and getRate() return correct results.
- decodeMP3Data();
}
-MP3Stream::~MP3Stream() {
+BaseMP3Stream::~BaseMP3Stream() {
deinitStream();
}
-void MP3Stream::decodeMP3Data() {
+void BaseMP3Stream::decodeMP3Data(Common::ReadStream &stream) {
do {
if (_state == MP3_STATE_INIT)
- initStream();
+ initStream(stream);
if (_state == MP3_STATE_EOS)
return;
// If necessary, load more data into the stream decoder
if (_stream.error == MAD_ERROR_BUFLEN)
- readMP3Data();
+ readMP3Data(stream);
while (_state == MP3_STATE_READY) {
_stream.error = MAD_ERROR_NONE;
@@ -179,11 +167,11 @@ void MP3Stream::decodeMP3Data() {
_state = MP3_STATE_EOS;
}
-void MP3Stream::readMP3Data() {
+void BaseMP3Stream::readMP3Data(Common::ReadStream &stream) {
uint32 remaining = 0;
// Give up immediately if we already used up all data in the stream
- if (_inStream->eos()) {
+ if (stream.eos()) {
_state = MP3_STATE_EOS;
return;
}
@@ -198,7 +186,7 @@ void MP3Stream::readMP3Data() {
}
// Try to read the next block
- uint32 size = _inStream->read(_buf + remaining, BUFFER_SIZE - remaining);
+ uint32 size = stream.read(_buf + remaining, BUFFER_SIZE - remaining);
if (size <= 0) {
_state = MP3_STATE_EOS;
return;
@@ -209,31 +197,7 @@ void MP3Stream::readMP3Data() {
mad_stream_buffer(&_stream, _buf, size + remaining);
}
-bool MP3Stream::seek(const Timestamp &where) {
- if (where == _length) {
- _state = MP3_STATE_EOS;
- return true;
- } else if (where > _length) {
- return false;
- }
-
- const uint32 time = where.msecs();
-
- mad_timer_t destination;
- mad_timer_set(&destination, time / 1000, time % 1000, 1000);
-
- if (_state != MP3_STATE_READY || mad_timer_compare(destination, _curTime) < 0)
- initStream();
-
- while (mad_timer_compare(destination, _curTime) > 0 && _state != MP3_STATE_EOS)
- readHeader();
-
- decodeMP3Data();
-
- return (_state != MP3_STATE_EOS);
-}
-
-void MP3Stream::initStream() {
+void BaseMP3Stream::initStream(Common::ReadStream &stream) {
if (_state != MP3_STATE_INIT)
deinitStream();
@@ -243,41 +207,23 @@ void MP3Stream::initStream() {
mad_synth_init(&_synth);
// Reset the stream data
- _inStream->seek(0, SEEK_SET);
_curTime = mad_timer_zero;
_posInFrame = 0;
-
- // Skip ID3 TAG if any
- // ID3v1 (beginning with with 'TAG') is located at the end of files. So we can ignore those.
- // ID3v2 can be located at the start of files and begins with a 10 bytes header, the first 3 bytes being 'ID3'.
- // The tag size is coded on the last 4 bytes of the 10 bytes header as a 32 bit synchsafe integer.
- // See http://id3.org/id3v2.4.0-structure for details.
- char data[10];
- _inStream->read(data, 10);
- if (data[0] == 'I' && data[1] == 'D' && data[2] == '3') {
- uint32 size = data[9] + 128 * (data[8] + 128 * (data[7] + 128 * data[6]));
- // This size does not include an optional 10 bytes footer. Check if it is present.
- if (data[5] & 0x10)
- size += 10;
- debug("Skipping ID3 TAG (%d bytes)", size + 10);
- _inStream->seek(size, SEEK_CUR);
- } else
- _inStream->seek(0, SEEK_SET);
// Update state
_state = MP3_STATE_READY;
// Read the first few sample bytes
- readMP3Data();
+ readMP3Data(stream);
}
-void MP3Stream::readHeader() {
+void BaseMP3Stream::readHeader(Common::ReadStream &stream) {
if (_state != MP3_STATE_READY)
return;
// If necessary, load more data into the stream decoder
if (_stream.error == MAD_ERROR_BUFLEN)
- readMP3Data();
+ readMP3Data(stream);
while (_state != MP3_STATE_EOS) {
_stream.error = MAD_ERROR_NONE;
@@ -287,7 +233,7 @@ void MP3Stream::readHeader() {
// be far too slow). Hence we perform this explicitly in a separate step.
if (mad_header_decode(&_frame.header, &_stream) == -1) {
if (_stream.error == MAD_ERROR_BUFLEN) {
- readMP3Data(); // Read more data
+ readMP3Data(stream); // Read more data
continue;
} else if (MAD_RECOVERABLE(_stream.error)) {
debug(6, "MP3Stream: Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
@@ -307,7 +253,7 @@ void MP3Stream::readHeader() {
_state = MP3_STATE_EOS;
}
-void MP3Stream::deinitStream() {
+void BaseMP3Stream::deinitStream() {
if (_state == MP3_STATE_INIT)
return;
@@ -319,7 +265,7 @@ void MP3Stream::deinitStream() {
_state = MP3_STATE_EOS;
}
-static inline int scale_sample(mad_fixed_t sample) {
+static inline int scaleSample(mad_fixed_t sample) {
// round
sample += (1L << (MAD_F_FRACBITS - 16));
@@ -333,28 +279,115 @@ static inline int scale_sample(mad_fixed_t sample) {
return sample >> (MAD_F_FRACBITS + 1 - 16);
}
-int MP3Stream::readBuffer(int16 *buffer, const int numSamples) {
+int BaseMP3Stream::fillBuffer(Common::ReadStream &stream, int16 *buffer, const int numSamples) {
int samples = 0;
// Keep going as long as we have input available
while (samples < numSamples && _state != MP3_STATE_EOS) {
const int len = MIN(numSamples, samples + (int)(_synth.pcm.length - _posInFrame) * MAD_NCHANNELS(&_frame.header));
while (samples < len) {
- *buffer++ = (int16)scale_sample(_synth.pcm.samples[0][_posInFrame]);
+ *buffer++ = (int16)scaleSample(_synth.pcm.samples[0][_posInFrame]);
samples++;
if (MAD_NCHANNELS(&_frame.header) == 2) {
- *buffer++ = (int16)scale_sample(_synth.pcm.samples[1][_posInFrame]);
+ *buffer++ = (int16)scaleSample(_synth.pcm.samples[1][_posInFrame]);
samples++;
}
_posInFrame++;
}
if (_posInFrame >= _synth.pcm.length) {
// We used up all PCM data in the current frame -- read & decode more
- decodeMP3Data();
+ decodeMP3Data(stream);
}
}
return samples;
}
+MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag dispose) :
+ BaseMP3Stream(),
+ _inStream(skipID3(inStream, dispose)),
+ _length(0, 1000) {
+
+ // Initialize the stream with some data
+ decodeMP3Data(*_inStream);
+
+ // Calculate the length of the stream
+ while (_state != MP3_STATE_EOS)
+ readHeader(*_inStream);
+
+ // To rule out any invalid sample rate to be encountered here, say in case the
+ // MP3 stream is invalid, we just check the MAD error code here.
+ // We need to assure this, since else we might trigger an assertion in Timestamp
+ // (When getRate() returns 0 or a negative number to be precise).
+ // Note that we allow "MAD_ERROR_BUFLEN" as error code here, since according
+ // to mad.h it is also set on EOF.
+ if ((_stream.error == MAD_ERROR_NONE || _stream.error == MAD_ERROR_BUFLEN) && getRate() > 0)
+ _length = Timestamp(mad_timer_count(_curTime, MAD_UNITS_MILLISECONDS), getRate());
+
+ deinitStream();
+
+ // Reinit stream
+ _state = MP3_STATE_INIT;
+ _inStream->seek(0);
+
+ // Decode the first chunk of data. This is necessary so that _frame
+ // is setup and isStereo() and getRate() return correct results.
+ decodeMP3Data(*_inStream);
+}
+
+int MP3Stream::readBuffer(int16 *buffer, const int numSamples) {
+ return fillBuffer(*_inStream, buffer, numSamples);
+}
+
+bool MP3Stream::seek(const Timestamp &where) {
+ if (where == _length) {
+ _state = MP3_STATE_EOS;
+ return true;
+ } else if (where > _length) {
+ return false;
+ }
+
+ const uint32 time = where.msecs();
+
+ mad_timer_t destination;
+ mad_timer_set(&destination, time / 1000, time % 1000, 1000);
+
+ if (_state != MP3_STATE_READY || mad_timer_compare(destination, _curTime) < 0) {
+ _inStream->seek(0);
+ initStream(*_inStream);
+ }
+
+ while (mad_timer_compare(destination, _curTime) > 0 && _state != MP3_STATE_EOS)
+ readHeader(*_inStream);
+
+ decodeMP3Data(*_inStream);
+
+ return (_state != MP3_STATE_EOS);
+}
+
+Common::SeekableReadStream *MP3Stream::skipID3(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose) {
+ // Skip ID3 TAG if any
+ // ID3v1 (beginning with with 'TAG') is located at the end of files. So we can ignore those.
+ // ID3v2 can be located at the start of files and begins with a 10 bytes header, the first 3 bytes being 'ID3'.
+ // The tag size is coded on the last 4 bytes of the 10 bytes header as a 32 bit synchsafe integer.
+ // See http://id3.org/id3v2.4.0-structure for details.
+ char data[10];
+ stream->read(data, sizeof(data));
+
+ uint32 offset = 0;
+ if (!stream->eos() && data[0] == 'I' && data[1] == 'D' && data[2] == '3') {
+ uint32 size = data[9] + 128 * (data[8] + 128 * (data[7] + 128 * data[6]));
+ // This size does not include an optional 10 bytes footer. Check if it is present.
+ if (data[5] & 0x10)
+ size += 10;
+
+ // Add in the 10 bytes we read in
+ size += sizeof(data);
+ debug("Skipping ID3 TAG (%d bytes)", size);
+ offset = size;
+ }
+
+ return new Common::SeekableSubReadStream(stream, offset, stream->size(), dispose);
+}
+
#pragma mark -
#pragma mark --- MP3 factory functions ---
Commit: ccd8dbf4baba33bda41d1d8aa7657ef7d1400463
https://github.com/scummvm/scummvm/commit/ccd8dbf4baba33bda41d1d8aa7657ef7d1400463
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:53-04:00
Commit Message:
AUDIO: Add an AudioStream subclass for packetized audio
Changed paths:
audio/audiostream.h
diff --git a/audio/audiostream.h b/audio/audiostream.h
index 840a25a..c3dbdcf 100644
--- a/audio/audiostream.h
+++ b/audio/audiostream.h
@@ -30,6 +30,10 @@
#include "audio/timestamp.h"
+namespace Common {
+class SeekableReadStream;
+}
+
namespace Audio {
/**
@@ -367,6 +371,30 @@ Timestamp convertTimeToStreamPos(const Timestamp &where, int rate, bool isStereo
*/
AudioStream *makeLimitingAudioStream(AudioStream *parentStream, const Timestamp &length, DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
+/**
+ * An AudioStream designed to work in terms of packets.
+ *
+ * It is similar in concept to QueuingAudioStream, but does not
+ * necessarily rely on the data from each queued AudioStream
+ * being separate.
+ */
+class PacketizedAudioStream : public virtual AudioStream {
+public:
+ virtual ~PacketizedAudioStream() {}
+
+ /**
+ * Queue the next packet to be decoded.
+ */
+ virtual void queuePacket(Common::SeekableReadStream *data) = 0;
+
+ /**
+ * Mark this stream as finished. That is, signal that no further data
+ * will be queued to it. Only after this has been done can this
+ * stream ever 'end'.
+ */
+ virtual void finish() = 0;
+};
+
} // End of namespace Audio
#endif
Commit: 562234b96b37a8944b6c626354220f5d21357dee
https://github.com/scummvm/scummvm/commit/562234b96b37a8944b6c626354220f5d21357dee
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:53-04:00
Commit Message:
AUDIO: Implement a packetized version of MP3
Changed paths:
audio/decoders/mp3.cpp
audio/decoders/mp3.h
diff --git a/audio/decoders/mp3.cpp b/audio/decoders/mp3.cpp
index 8550d91..49d4d85 100644
--- a/audio/decoders/mp3.cpp
+++ b/audio/decoders/mp3.cpp
@@ -25,7 +25,9 @@
#ifdef USE_MAD
#include "common/debug.h"
+#include "common/mutex.h"
#include "common/ptr.h"
+#include "common/queue.h"
#include "common/stream.h"
#include "common/substream.h"
#include "common/textconsole.h"
@@ -51,9 +53,9 @@ public:
BaseMP3Stream();
virtual ~BaseMP3Stream();
- bool endOfData() const { return _state == MP3_STATE_EOS; }
- bool isStereo() const { return MAD_NCHANNELS(&_frame.header) == 2; }
- int getRate() const { return _frame.header.samplerate; }
+ bool endOfData() const { return _state == MP3_STATE_EOS; }
+ bool isStereo() const { return _channels == 2; }
+ int getRate() const { return _rate; }
protected:
void decodeMP3Data(Common::ReadStream &stream);
@@ -80,6 +82,9 @@ protected:
mad_frame _frame;
mad_synth _synth;
+ uint _channels;
+ uint _rate;
+
enum {
BUFFER_SIZE = 5 * 8192
};
@@ -88,11 +93,10 @@ protected:
byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD];
};
-class MP3Stream : public BaseMP3Stream, public SeekableAudioStream {
+class MP3Stream : private BaseMP3Stream, public SeekableAudioStream {
public:
MP3Stream(Common::SeekableReadStream *inStream,
DisposeAfterUse::Flag dispose);
- virtual ~MP3Stream() {}
int readBuffer(int16 *buffer, const int numSamples);
bool seek(const Timestamp &where);
@@ -107,6 +111,26 @@ private:
static Common::SeekableReadStream *skipID3(Common::SeekableReadStream *stream, DisposeAfterUse::Flag dispose);
};
+class PacketizedMP3Stream : private BaseMP3Stream, public PacketizedAudioStream {
+public:
+ PacketizedMP3Stream(Common::SeekableReadStream &firstPacket);
+ PacketizedMP3Stream(uint channels, uint rate);
+ ~PacketizedMP3Stream();
+
+ // AudioStream API
+ int readBuffer(int16 *buffer, const int numSamples);
+ bool endOfStream() const;
+
+ // PacketizedAudioStream API
+ void queuePacket(Common::SeekableReadStream *packet);
+ void finish();
+
+private:
+ Common::Mutex _mutex;
+ Common::Queue<Common::SeekableReadStream *> _queue;
+ bool _finished;
+};
+
BaseMP3Stream::BaseMP3Stream() :
_posInFrame(0),
@@ -329,8 +353,11 @@ MP3Stream::MP3Stream(Common::SeekableReadStream *inStream, DisposeAfterUse::Flag
_inStream->seek(0);
// Decode the first chunk of data. This is necessary so that _frame
- // is setup and isStereo() and getRate() return correct results.
+ // is setup and we can retrieve channels/rate.
decodeMP3Data(*_inStream);
+
+ _channels = MAD_NCHANNELS(&_frame.header);
+ _rate = _frame.header.samplerate;
}
int MP3Stream::readBuffer(int16 *buffer, const int numSamples) {
@@ -388,6 +415,91 @@ Common::SeekableReadStream *MP3Stream::skipID3(Common::SeekableReadStream *strea
return new Common::SeekableSubReadStream(stream, offset, stream->size(), dispose);
}
+PacketizedMP3Stream::PacketizedMP3Stream(Common::SeekableReadStream &firstPacket) :
+ BaseMP3Stream(),
+ _finished(false) {
+
+ // Load some data to get the channels/rate
+ _queue.push(&firstPacket);
+ decodeMP3Data(firstPacket);
+ _channels = MAD_NCHANNELS(&_frame.header);
+ _rate = _frame.header.samplerate;
+
+ // Clear everything
+ deinitStream();
+ _state = MP3_STATE_INIT;
+ _queue.clear();
+}
+
+PacketizedMP3Stream::PacketizedMP3Stream(uint channels, uint rate) :
+ BaseMP3Stream(),
+ _finished(false) {
+ _channels = channels;
+ _rate = rate;
+}
+
+PacketizedMP3Stream::~PacketizedMP3Stream() {
+ while (!_queue.empty()) {
+ delete _queue.front();
+ _queue.pop();
+ }
+}
+
+int PacketizedMP3Stream::readBuffer(int16 *buffer, const int numSamples) {
+ int samples = 0;
+
+ while (samples < numSamples) {
+ Common::StackLock lock(_mutex);
+
+ // Empty? Bail out for now
+ if (_queue.empty())
+ return samples;
+
+ Common::SeekableReadStream *packet = _queue.front();
+
+ if (_state == MP3_STATE_INIT) {
+ // Initialize everything
+ decodeMP3Data(*packet);
+ } else if (_state == MP3_STATE_EOS) {
+ // Reset the end-of-stream setting
+ _state = MP3_STATE_READY;
+ }
+
+ samples += fillBuffer(*packet, buffer + samples, numSamples - samples);
+
+ // If the stream is done, kill it
+ if (packet->pos() >= packet->size()) {
+ _queue.pop();
+ delete packet;
+ }
+ }
+
+ return samples;
+}
+
+bool PacketizedMP3Stream::endOfStream() const {
+ if (!endOfData())
+ return false;
+
+ // Lock the mutex
+ Common::StackLock lock(_mutex);
+ if (!_queue.empty())
+ return false;
+
+ return _finished;
+}
+
+void PacketizedMP3Stream::queuePacket(Common::SeekableReadStream *packet) {
+ Common::StackLock lock(_mutex);
+ assert(!_finished);
+ _queue.push(packet);
+}
+
+void PacketizedMP3Stream::finish() {
+ Common::StackLock lock(_mutex);
+ _finished = true;
+}
+
#pragma mark -
#pragma mark --- MP3 factory functions ---
@@ -416,6 +528,15 @@ SeekableAudioStream *makeMP3Stream(
}
}
+PacketizedAudioStream *makePacketizedMP3Stream(Common::SeekableReadStream &firstPacket) {
+ return new PacketizedMP3Stream(firstPacket);
+}
+
+PacketizedAudioStream *makePacketizedMP3Stream(uint channels, uint rate) {
+ return new PacketizedMP3Stream(channels, rate);
+}
+
+
} // End of namespace Audio
#endif // #ifdef USE_MAD
diff --git a/audio/decoders/mp3.h b/audio/decoders/mp3.h
index 609181b..709aad8 100644
--- a/audio/decoders/mp3.h
+++ b/audio/decoders/mp3.h
@@ -51,6 +51,7 @@ class SeekableReadStream;
namespace Audio {
+class PacketizedAudioStream;
class SeekableAudioStream;
/**
@@ -65,6 +66,26 @@ SeekableAudioStream *makeMP3Stream(
Common::SeekableReadStream *stream,
DisposeAfterUse::Flag disposeAfterUse);
+/**
+ * Create a new PacketizedAudioStream from the first packet in the given
+ * stream. It does not own the packet and must be queued again later.
+ *
+ * @param firstPacket the SeekableReadStream from which to read the MP3 data
+ * @return a new PacketizedAudioStream
+ */
+PacketizedAudioStream *makePacketizedMP3Stream(
+ Common::SeekableReadStream &firstPacket);
+
+/**
+ * Create a new PacketizedAudioStream for a given number of channels
+ * and sample rate.
+ *
+ * @param firstPacket the SeekableReadStream from which to read the MP3 data
+ * @return a new PacketizedAudioStream
+ */
+PacketizedAudioStream *makePacketizedMP3Stream(
+ uint channels, uint rate);
+
} // End of namespace Audio
#endif // #ifdef USE_MAD
Commit: 14e57ca76fc90de9f5ea454aa5bf543a8f97d898
https://github.com/scummvm/scummvm/commit/14e57ca76fc90de9f5ea454aa5bf543a8f97d898
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:53-04:00
Commit Message:
VIDEO: Switch MPEG-PS audio code to use the packetized MP3 code
Changed paths:
video/mpegps_decoder.cpp
video/mpegps_decoder.h
diff --git a/video/mpegps_decoder.cpp b/video/mpegps_decoder.cpp
index d8f7f5a..6942efb 100644
--- a/video/mpegps_decoder.cpp
+++ b/video/mpegps_decoder.cpp
@@ -22,6 +22,7 @@
#include "audio/audiostream.h"
#include "audio/decoders/raw.h"
+#include "audio/decoders/mp3.h"
#include "common/debug.h"
#include "common/endian.h"
#include "common/stream.h"
@@ -142,7 +143,7 @@ void MPEGPSDecoder::readNextPacket() {
} else if (startCode >= 0x1C0 && startCode <= 0x1DF) {
#ifdef USE_MAD
// MPEG Audio stream
- MPEGAudioTrack *audioTrack = new MPEGAudioTrack(packet);
+ MPEGAudioTrack *audioTrack = new MPEGAudioTrack(*packet);
stream = audioTrack;
_streamMap[startCode] = audioTrack;
addTrack(audioTrack);
@@ -158,6 +159,8 @@ void MPEGPSDecoder::readNextPacket() {
}
if (stream) {
+ packet->seek(0);
+
bool done = stream->sendPacket(packet, pts, dts);
if (done && stream->getStreamType() == MPEGStream::kStreamTypeVideo)
@@ -510,54 +513,16 @@ void MPEGPSDecoder::MPEGVideoTrack::findDimensions(Common::SeekableReadStream *f
// The audio code here is almost entirely based on what we do in mp3.cpp
-MPEGPSDecoder::MPEGAudioTrack::MPEGAudioTrack(Common::SeekableReadStream *firstPacket) {
- // The MAD_BUFFER_GUARD must always contain zeros (the reason
- // for this is that the Layer III Huffman decoder of libMAD
- // may read a few bytes beyond the end of the input buffer).
- memset(_buf + BUFFER_SIZE, 0, MAD_BUFFER_GUARD);
-
- _state = MP3_STATE_INIT;
- _audStream = 0;
-
- // Find out our audio parameters
- initStream(firstPacket);
-
- while (_state != MP3_STATE_EOS)
- readHeader(firstPacket);
-
- _audStream = Audio::makeQueuingAudioStream(_frame.header.samplerate, MAD_NCHANNELS(&_frame.header) == 2);
-
- deinitStream();
-
- firstPacket->seek(0);
- _state = MP3_STATE_INIT;
+MPEGPSDecoder::MPEGAudioTrack::MPEGAudioTrack(Common::SeekableReadStream &firstPacket) {
+ _audStream = Audio::makePacketizedMP3Stream(firstPacket);
}
MPEGPSDecoder::MPEGAudioTrack::~MPEGAudioTrack() {
- deinitStream();
delete _audStream;
}
-static inline int scaleSample(mad_fixed_t sample) {
- // round
- sample += (1L << (MAD_F_FRACBITS - 16));
-
- // clip
- if (sample > MAD_F_ONE - 1)
- sample = MAD_F_ONE - 1;
- else if (sample < -MAD_F_ONE)
- sample = -MAD_F_ONE;
-
- // quantize and scale to not saturate when mixing a lot of channels
- return sample >> (MAD_F_FRACBITS + 1 - 16);
-}
-
bool MPEGPSDecoder::MPEGAudioTrack::sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts) {
- while (_state != MP3_STATE_EOS)
- decodeMP3Data(packet);
-
- _state = MP3_STATE_READY;
- delete packet;
+ _audStream->queuePacket(packet);
return true;
}
@@ -565,168 +530,6 @@ Audio::AudioStream *MPEGPSDecoder::MPEGAudioTrack::getAudioStream() const {
return _audStream;
}
-void MPEGPSDecoder::MPEGAudioTrack::initStream(Common::SeekableReadStream *packet) {
- if (_state != MP3_STATE_INIT)
- deinitStream();
-
- // Init MAD
- mad_stream_init(&_stream);
- mad_frame_init(&_frame);
- mad_synth_init(&_synth);
-
- // Reset the stream data
- packet->seek(0, SEEK_SET);
-
- // Update state
- _state = MP3_STATE_READY;
-
- // Read the first few sample bytes
- readMP3Data(packet);
-}
-
-void MPEGPSDecoder::MPEGAudioTrack::deinitStream() {
- if (_state == MP3_STATE_INIT)
- return;
-
- // Deinit MAD
- mad_synth_finish(&_synth);
- mad_frame_finish(&_frame);
- mad_stream_finish(&_stream);
-
- _state = MP3_STATE_EOS;
-}
-
-void MPEGPSDecoder::MPEGAudioTrack::readMP3Data(Common::SeekableReadStream *packet) {
- uint32 remaining = 0;
-
- // Give up immediately if we already used up all data in the stream
- if (packet->eos()) {
- _state = MP3_STATE_EOS;
- return;
- }
-
- if (_stream.next_frame) {
- // If there is still data in the MAD stream, we need to preserve it.
- // Note that we use memmove, as we are reusing the same buffer,
- // and hence the data regions we copy from and to may overlap.
- remaining = _stream.bufend - _stream.next_frame;
- assert(remaining < BUFFER_SIZE); // Paranoia check
- memmove(_buf, _stream.next_frame, remaining);
- }
-
- memset(_buf + remaining, 0, BUFFER_SIZE - remaining);
-
- // Try to read the next block
- uint32 size = packet->read(_buf + remaining, BUFFER_SIZE - remaining);
- if (size == 0) {
- _state = MP3_STATE_EOS;
- return;
- }
-
- // Feed the data we just read into the stream decoder
- _stream.error = MAD_ERROR_NONE;
- mad_stream_buffer(&_stream, _buf, size + remaining);
-}
-
-void MPEGPSDecoder::MPEGAudioTrack::readHeader(Common::SeekableReadStream *packet) {
- if (_state != MP3_STATE_READY)
- return;
-
- // If necessary, load more data into the stream decoder
- if (_stream.error == MAD_ERROR_BUFLEN)
- readMP3Data(packet);
-
- while (_state != MP3_STATE_EOS) {
- _stream.error = MAD_ERROR_NONE;
-
- // Decode the next header. Note: mad_frame_decode would do this for us, too.
- // However, for seeking we don't want to decode the full frame (else it would
- // be far too slow). Hence we perform this explicitly in a separate step.
- if (mad_header_decode(&_frame.header, &_stream) == -1) {
- if (_stream.error == MAD_ERROR_BUFLEN) {
- readMP3Data(packet); // Read more data
- continue;
- } else if (MAD_RECOVERABLE(_stream.error)) {
- debug(6, "MPEGAudioTrack::readHeader(): Recoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
- continue;
- } else {
- warning("MPEGAudioTrack::readHeader(): Unrecoverable error in mad_header_decode (%s)", mad_stream_errorstr(&_stream));
- break;
- }
- }
-
- break;
- }
-
- if (_stream.error != MAD_ERROR_NONE)
- _state = MP3_STATE_EOS;
-}
-
-void MPEGPSDecoder::MPEGAudioTrack::decodeMP3Data(Common::SeekableReadStream *packet) {
- if (_state == MP3_STATE_INIT)
- initStream(packet);
-
- if (_state == MP3_STATE_EOS)
- return;
-
- do {
- // If necessary, load more data into the stream decoder
- if (_stream.error == MAD_ERROR_BUFLEN)
- readMP3Data(packet);
-
- while (_state == MP3_STATE_READY) {
- _stream.error = MAD_ERROR_NONE;
-
- // Decode the next frame
- if (mad_frame_decode(&_frame, &_stream) == -1) {
- if (_stream.error == MAD_ERROR_BUFLEN) {
- break; // Read more data
- } else if (MAD_RECOVERABLE(_stream.error)) {
- // Note: we will occasionally see MAD_ERROR_BADDATAPTR errors here.
- // These are normal and expected (caused by our frame skipping (i.e. "seeking")
- // code above).
- debug(6, "MPEGAudioTrack::decodeMP3Data(): Recoverable error in mad_frame_decode (%s)", mad_stream_errorstr(&_stream));
- continue;
- } else {
- warning("MPEGAudioTrack::decodeMP3Data(): Unrecoverable error in mad_frame_decode (%s)", mad_stream_errorstr(&_stream));
- break;
- }
- }
-
- // Synthesize PCM data
- mad_synth_frame(&_synth, &_frame);
-
- // Output it to our queue
- if (_synth.pcm.length != 0) {
- byte *buffer = (byte *)malloc(_synth.pcm.length * 2 * MAD_NCHANNELS(&_frame.header));
- int16 *ptr = (int16 *)buffer;
-
- for (int i = 0; i < _synth.pcm.length; i++) {
- *ptr++ = (int16)scaleSample(_synth.pcm.samples[0][i]);
-
- if (MAD_NCHANNELS(&_frame.header) == 2)
- *ptr++ = (int16)scaleSample(_synth.pcm.samples[1][i]);
- }
-
- int flags = Audio::FLAG_16BITS;
-
- if (_audStream->isStereo())
- flags |= Audio::FLAG_STEREO;
-
-#ifdef SCUMM_LITTLE_ENDIAN
- flags |= Audio::FLAG_LITTLE_ENDIAN;
-#endif
-
- _audStream->queueBuffer(buffer, _synth.pcm.length * 2 * MAD_NCHANNELS(&_frame.header), DisposeAfterUse::YES, flags);
- }
- break;
- }
- } while (_state != MP3_STATE_EOS && _stream.error == MAD_ERROR_BUFLEN);
-
- if (_stream.error != MAD_ERROR_NONE)
- _state = MP3_STATE_EOS;
-}
-
#endif
} // End of namespace Video
diff --git a/video/mpegps_decoder.h b/video/mpegps_decoder.h
index 0184d6f..bdff879 100644
--- a/video/mpegps_decoder.h
+++ b/video/mpegps_decoder.h
@@ -27,12 +27,8 @@
#include "graphics/surface.h"
#include "video/video_decoder.h"
-#ifdef USE_MAD
-#include <mad.h>
-#endif
-
namespace Audio {
-class QueuingAudioStream;
+class PacketizedAudioStream;
}
namespace Common {
@@ -115,10 +111,9 @@ private:
#ifdef USE_MAD
// An MPEG audio track
- // TODO: Merge this with the normal MP3Stream somehow
class MPEGAudioTrack : public AudioTrack, public MPEGStream {
public:
- MPEGAudioTrack(Common::SeekableReadStream *firstPacket);
+ MPEGAudioTrack(Common::SeekableReadStream &firstPacket);
~MPEGAudioTrack();
bool sendPacket(Common::SeekableReadStream *packet, uint32 pts, uint32 dts);
@@ -128,32 +123,7 @@ private:
Audio::AudioStream *getAudioStream() const;
private:
- Audio::QueuingAudioStream *_audStream;
-
- enum State {
- MP3_STATE_INIT, // Need to init the decoder
- MP3_STATE_READY, // ready for processing data
- MP3_STATE_EOS // end of data reached (may need to loop)
- };
-
- State _state;
-
- mad_stream _stream;
- mad_frame _frame;
- mad_synth _synth;
-
- enum {
- BUFFER_SIZE = 5 * 8192
- };
-
- // This buffer contains a slab of input data
- byte _buf[BUFFER_SIZE + MAD_BUFFER_GUARD];
-
- void initStream(Common::SeekableReadStream *packet);
- void deinitStream();
- void readMP3Data(Common::SeekableReadStream *packet);
- void readHeader(Common::SeekableReadStream *packet);
- void decodeMP3Data(Common::SeekableReadStream *packet);
+ Audio::PacketizedAudioStream *_audStream;
};
#endif
Commit: ba4469da6a111e208d40808cba50e797180a8edd
https://github.com/scummvm/scummvm/commit/ba4469da6a111e208d40808cba50e797180a8edd
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:53-04:00
Commit Message:
ZVISION: Cleanup the AVI decoder subclass
Changed paths:
engines/zvision/video/zork_avi_decoder.cpp
engines/zvision/video/zork_avi_decoder.h
diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp
index cf8505e..e69b27b 100644
--- a/engines/zvision/video/zork_avi_decoder.cpp
+++ b/engines/zvision/video/zork_avi_decoder.cpp
@@ -34,44 +34,32 @@
namespace ZVision {
Video::AVIDecoder::AVIAudioTrack *ZorkAVIDecoder::createAudioTrack(Video::AVIDecoder::AVIStreamHeader sHeader, Video::AVIDecoder::PCMWaveFormat wvInfo) {
- ZorkAVIDecoder::ZorkAVIAudioTrack *audioTrack = new ZorkAVIDecoder::ZorkAVIAudioTrack(sHeader, wvInfo, _soundType);
- return (Video::AVIDecoder::AVIAudioTrack *)audioTrack;
+ if (wvInfo.tag != kWaveFormatZorkPCM)
+ return new AVIAudioTrack(sHeader, wvInfo, _soundType);
+
+ assert(wvInfo.size == 8);
+ return new ZorkAVIAudioTrack(sHeader, wvInfo, _soundType);
}
-void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
- bool updateCurChunk = true;
- if (_audStream) {
- if (_wvInfo.tag == kWaveFormatZorkPCM) {
- assert(_wvInfo.size == 8);
- RawChunkStream::RawChunk chunk = decoder->readNextChunk(stream);
- delete stream;
+void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
+ RawChunkStream::RawChunk chunk = _decoder.readNextChunk(stream);
+ delete stream;
- if (chunk.data) {
- byte flags = Audio::FLAG_16BITS | Audio::FLAG_STEREO;
+ if (chunk.data) {
+ byte flags = Audio::FLAG_16BITS | Audio::FLAG_STEREO;
#ifdef SCUMM_LITTLE_ENDIAN
- // RawChunkStream produces native endianness int16
- flags |= Audio::FLAG_LITTLE_ENDIAN;
+ // RawChunkStream produces native endianness int16
+ flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
- _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags);
- }
- } else {
- updateCurChunk = false;
- AVIAudioTrack::queueSound(stream);
- }
- } else {
- delete stream;
+ _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags);
}
- // The superclass always updates _curChunk, whether or not audio has
- // been queued, so we should do that too. Unless the superclass already
- // has done it for us.
- if (updateCurChunk) {
- _curChunk++;
- }
+ _curChunk++;
}
void ZorkAVIDecoder::ZorkAVIAudioTrack::resetStream() {
- decoder->init();
+ AVIAudioTrack::resetStream();
+ _decoder.init();
}
} // End of namespace ZVision
diff --git a/engines/zvision/video/zork_avi_decoder.h b/engines/zvision/video/zork_avi_decoder.h
index 89c0d1e..8e7be71 100644
--- a/engines/zvision/video/zork_avi_decoder.h
+++ b/engines/zvision/video/zork_avi_decoder.h
@@ -41,20 +41,14 @@ private:
public:
ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) :
Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType),
- decoder(NULL) {
- if (_audStream) {
- decoder = new RawChunkStream(_audStream->isStereo());
- }
- }
- virtual ~ZorkAVIAudioTrack() {
- if (decoder)
- delete decoder;
+ _decoder(waveFormat.channels == 2) {
}
void queueSound(Common::SeekableReadStream *stream);
void resetStream();
+
private:
- RawChunkStream *decoder;
+ RawChunkStream _decoder;
};
Video::AVIDecoder::AVIAudioTrack *createAudioTrack(Video::AVIDecoder::AVIStreamHeader sHeader, Video::AVIDecoder::PCMWaveFormat wvInfo);
Commit: de2f4e698270937251f0655c19555fb9099df55f
https://github.com/scummvm/scummvm/commit/de2f4e698270937251f0655c19555fb9099df55f
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:53-04:00
Commit Message:
VIDEO: Add support for MP3 in AVI
Changed paths:
engines/zvision/video/zork_avi_decoder.cpp
video/avi_decoder.cpp
video/avi_decoder.h
diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp
index e69b27b..53b0a9a 100644
--- a/engines/zvision/video/zork_avi_decoder.cpp
+++ b/engines/zvision/video/zork_avi_decoder.cpp
@@ -51,7 +51,7 @@ void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *s
// RawChunkStream produces native endianness int16
flags |= Audio::FLAG_LITTLE_ENDIAN;
#endif
- _audStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags);
+ _queueStream->queueBuffer((byte *)chunk.data, chunk.size, DisposeAfterUse::YES, flags);
}
_curChunk++;
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index 700975d..aef5e76 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -31,6 +31,7 @@
// Audio Codecs
#include "audio/decoders/adpcm.h"
+#include "audio/decoders/mp3.h"
#include "audio/decoders/raw.h"
// Video Codecs
@@ -841,15 +842,18 @@ void AVIDecoder::AVIVideoTrack::setDither(const byte *palette) {
AVIDecoder::AVIAudioTrack::AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType)
: _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType), _curChunk(0) {
- _audStream = createAudioStream();
+ createAudioStream();
}
AVIDecoder::AVIAudioTrack::~AVIAudioTrack() {
- delete _audStream;
+ delete _queueStream;
+ delete _packetStream;
}
void AVIDecoder::AVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
- if (_audStream) {
+ if (_packetStream) {
+ _packetStream->queuePacket(stream);
+ } else if (_queueStream) {
if (_wvInfo.tag == kWaveFormatPCM) {
byte flags = 0;
if (_audsHeader.sampleSize == 2)
@@ -860,13 +864,13 @@ void AVIDecoder::AVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
if (_wvInfo.channels == 2)
flags |= Audio::FLAG_STEREO;
- _audStream->queueAudioStream(Audio::makeRawStream(stream, _wvInfo.samplesPerSec, flags, DisposeAfterUse::YES), DisposeAfterUse::YES);
+ _queueStream->queueAudioStream(Audio::makeRawStream(stream, _wvInfo.samplesPerSec, flags, DisposeAfterUse::YES), DisposeAfterUse::YES);
} else if (_wvInfo.tag == kWaveFormatMSADPCM) {
- _audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMS, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
+ _queueStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMS, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
} else if (_wvInfo.tag == kWaveFormatMSIMAADPCM) {
- _audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMSIma, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
+ _queueStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMSIma, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
} else if (_wvInfo.tag == kWaveFormatDK3) {
- _audStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
+ _queueStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
}
} else {
delete stream;
@@ -882,17 +886,22 @@ void AVIDecoder::AVIAudioTrack::skipAudio(const Audio::Timestamp &time, const Au
if (skipFrames <= 0)
return;
- if (_audStream->isStereo())
+ Audio::AudioStream *audioStream = getAudioStream();
+ if (!audioStream)
+ return;
+
+ if (audioStream->isStereo())
skipFrames *= 2;
int16 *tempBuffer = new int16[skipFrames];
- _audStream->readBuffer(tempBuffer, skipFrames);
+ audioStream->readBuffer(tempBuffer, skipFrames);
delete[] tempBuffer;
}
void AVIDecoder::AVIAudioTrack::resetStream() {
- delete _audStream;
- _audStream = createAudioStream();
+ delete _queueStream;
+ delete _packetStream;
+ createAudioStream();
_curChunk = 0;
}
@@ -902,18 +911,32 @@ bool AVIDecoder::AVIAudioTrack::rewind() {
}
Audio::AudioStream *AVIDecoder::AVIAudioTrack::getAudioStream() const {
- return _audStream;
-}
-
-Audio::QueuingAudioStream *AVIDecoder::AVIAudioTrack::createAudioStream() {
- if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatMSADPCM || _wvInfo.tag == kWaveFormatMSIMAADPCM || _wvInfo.tag == kWaveFormatDK3)
- return Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2);
- else if (_wvInfo.tag == kWaveFormatMP3)
- warning("Unsupported AVI MP3 tracks");
- else if (_wvInfo.tag != kWaveFormatNone) // No sound
+ if (_packetStream)
+ return _packetStream;
+
+ return _queueStream;
+}
+
+void AVIDecoder::AVIAudioTrack::createAudioStream() {
+ _queueStream = 0;
+ _packetStream = 0;
+
+ if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatMSADPCM || _wvInfo.tag == kWaveFormatMSIMAADPCM || _wvInfo.tag == kWaveFormatDK3) {
+ // For now, a QueuingAudioStream will be created
+ } else if (_wvInfo.tag == kWaveFormatMP3) {
+ // MPEG audio
+#ifdef USE_MAD
+ _packetStream = Audio::makePacketizedMP3Stream(_wvInfo.channels, _wvInfo.samplesPerSec);
+#else
+ warning("AVI MP3 stream found, but no libmad support compiled in");
+#endif
+ } else if (_wvInfo.tag != kWaveFormatNone) {
+ // No supported format
warning("Unsupported AVI audio format %d", _wvInfo.tag);
+ }
- return 0;
+ if (!_packetStream)
+ _queueStream = Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2);
}
AVIDecoder::TrackStatus::TrackStatus() : track(0), chunkSearchOffset(0) {
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 6c1ce1a..8b12c23 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -32,6 +32,7 @@
#include "audio/mixer.h"
namespace Audio {
+class PacketizedAudioStream;
class QueuingAudioStream;
}
@@ -241,8 +242,9 @@ protected:
AVIStreamHeader _audsHeader;
PCMWaveFormat _wvInfo;
Audio::Mixer::SoundType _soundType;
- Audio::QueuingAudioStream *_audStream;
- Audio::QueuingAudioStream *createAudioStream();
+ Audio::QueuingAudioStream *_queueStream;
+ Audio::PacketizedAudioStream *_packetStream;
+ void createAudioStream();
uint32 _curChunk;
};
Commit: a64aff02878eaaeda3a014cbfc71daf760000136
https://github.com/scummvm/scummvm/commit/a64aff02878eaaeda3a014cbfc71daf760000136
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:54-04:00
Commit Message:
AUDIO: Add a class to easily make stateless PacketizedAudioStreams
Changed paths:
audio/audiostream.h
diff --git a/audio/audiostream.h b/audio/audiostream.h
index c3dbdcf..6019aca 100644
--- a/audio/audiostream.h
+++ b/audio/audiostream.h
@@ -395,6 +395,44 @@ public:
virtual void finish() = 0;
};
+/**
+ * A PacketizedAudioStream that works closer to a QueuingAudioStream.
+ * It queues individual packets as whole AudioStream to an internal
+ * QueuingAudioStream. This is used for writing quick wrappers against
+ * e.g. RawStream, which can be made into PacketizedAudioStreams with
+ * little effort.
+ */
+class StatelessPacketizedAudioStream : public PacketizedAudioStream {
+public:
+ StatelessPacketizedAudioStream(uint rate, uint channels) :
+ _rate(rate), _channels(channels), _stream(makeQueuingAudioStream(rate, channels == 2)) {}
+ virtual ~StatelessPacketizedAudioStream() {}
+
+ // AudioStream API
+ bool isStereo() const { return _channels == 2; }
+ int getRate() const { return _rate; }
+ int readBuffer(int16 *data, const int numSamples) { return _stream->readBuffer(data, numSamples); }
+ bool endOfData() const { return _stream->endOfData(); }
+ bool endOfStream() const { return _stream->endOfStream(); }
+
+ // PacketizedAudioStream API
+ void queuePacket(Common::SeekableReadStream *data) { _stream->queueAudioStream(makeStream(data)); }
+ void finish() { _stream->finish(); }
+
+ uint getChannels() const { return _channels; }
+
+protected:
+ /**
+ * Make the AudioStream for a given packet
+ */
+ virtual AudioStream *makeStream(Common::SeekableReadStream *data) = 0;
+
+private:
+ uint _rate;
+ uint _channels;
+ Common::ScopedPtr<QueuingAudioStream> _stream;
+};
+
} // End of namespace Audio
#endif
Commit: 3aa9e2c5816aad20aa18e04d3a6644a8f79a4e29
https://github.com/scummvm/scummvm/commit/3aa9e2c5816aad20aa18e04d3a6644a8f79a4e29
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:54-04:00
Commit Message:
AUDIO: Add a packetized version of the PCM stream
Changed paths:
audio/decoders/raw.cpp
audio/decoders/raw.h
diff --git a/audio/decoders/raw.cpp b/audio/decoders/raw.cpp
index 9a9f790..477a8e7 100644
--- a/audio/decoders/raw.cpp
+++ b/audio/decoders/raw.cpp
@@ -221,4 +221,24 @@ SeekableAudioStream *makeRawStream(const byte *buffer, uint32 size,
return makeRawStream(new Common::MemoryReadStream(buffer, size, disposeAfterUse), rate, flags, DisposeAfterUse::YES);
}
+class PacketizedRawStream : public StatelessPacketizedAudioStream {
+public:
+ PacketizedRawStream(int rate, byte flags) :
+ StatelessPacketizedAudioStream(rate, ((flags & FLAG_STEREO) != 0) ? 2 : 1), _flags(flags) {}
+
+protected:
+ AudioStream *makeStream(Common::SeekableReadStream *data);
+
+private:
+ byte _flags;
+};
+
+AudioStream *PacketizedRawStream::makeStream(Common::SeekableReadStream *data) {
+ return makeRawStream(data, getRate(), _flags);
+}
+
+PacketizedAudioStream *makePacketizedRawStream(int rate, byte flags) {
+ return new PacketizedRawStream(rate, flags);
+}
+
} // End of namespace Audio
diff --git a/audio/decoders/raw.h b/audio/decoders/raw.h
index 14e7bd4..7ccbcda 100644
--- a/audio/decoders/raw.h
+++ b/audio/decoders/raw.h
@@ -35,6 +35,7 @@ class SeekableReadStream;
namespace Audio {
+class PacketizedAudioStream;
class SeekableAudioStream;
/**
@@ -89,6 +90,17 @@ SeekableAudioStream *makeRawStream(Common::SeekableReadStream *stream,
int rate, byte flags,
DisposeAfterUse::Flag disposeAfterUse = DisposeAfterUse::YES);
+/**
+ * Creates a PacketizedAudioStream that will automatically queue
+ * packets as individual AudioStreams like returned by makeRawStream.
+ *
+ * @param rate Rate of the sound data.
+ * @param flags Audio flags combination.
+ * @see RawFlags
+ * @return The new PacketizedAudioStream.
+ */
+PacketizedAudioStream *makePacketizedRawStream(int rate, byte flags);
+
} // End of namespace Audio
#endif
Commit: 331d8ece21948bb07f43be512ab686bb41cf01fa
https://github.com/scummvm/scummvm/commit/331d8ece21948bb07f43be512ab686bb41cf01fa
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T19:53:54-04:00
Commit Message:
AUDIO: Add a packetized version of ADPCM streams
Changed paths:
audio/decoders/adpcm.cpp
audio/decoders/adpcm.h
diff --git a/audio/decoders/adpcm.cpp b/audio/decoders/adpcm.cpp
index 2f710f7..fe5eec5 100644
--- a/audio/decoders/adpcm.cpp
+++ b/audio/decoders/adpcm.cpp
@@ -457,4 +457,34 @@ RewindableAudioStream *makeADPCMStream(Common::SeekableReadStream *stream, Dispo
}
}
+class PacketizedADPCMStream : public StatelessPacketizedAudioStream {
+public:
+ PacketizedADPCMStream(ADPCMType type, int rate, int channels, uint32 blockAlign) :
+ StatelessPacketizedAudioStream(rate, channels), _type(type), _blockAlign(blockAlign) {}
+
+protected:
+ AudioStream *makeStream(Common::SeekableReadStream *data);
+
+private:
+ ADPCMType _type;
+ uint32 _blockAlign;
+};
+
+AudioStream *PacketizedADPCMStream::makeStream(Common::SeekableReadStream *data) {
+ return makeADPCMStream(data, DisposeAfterUse::YES, data->size(), _type, getRate(), getChannels(), _blockAlign);
+}
+
+PacketizedAudioStream *makePacketizedADPCMStream(ADPCMType type, int rate, int channels, uint32 blockAlign) {
+ // Filter out types we can't support (they're not fully stateless)
+ switch (type) {
+ case kADPCMOki:
+ case kADPCMDVI:
+ return 0;
+ default:
+ break;
+ }
+
+ return new PacketizedADPCMStream(type, rate, channels, blockAlign);
+}
+
} // End of namespace Audio
diff --git a/audio/decoders/adpcm.h b/audio/decoders/adpcm.h
index bf6e7f7..650bc34 100644
--- a/audio/decoders/adpcm.h
+++ b/audio/decoders/adpcm.h
@@ -44,6 +44,7 @@ class SeekableReadStream;
namespace Audio {
+class PacketizedAudioStream;
class RewindableAudioStream;
// There are several types of ADPCM encoding, only some are supported here
@@ -81,6 +82,26 @@ RewindableAudioStream *makeADPCMStream(
int channels,
uint32 blockAlign = 0);
+/**
+ * Creates a PacketizedAudioStream that will automatically queue
+ * packets as individual AudioStreams like returned by makeADPCMStream.
+ *
+ * Due to the ADPCM types not necessarily supporting stateless
+ * streaming, OKI and DVI are not supported by this function
+ * and will return NULL.
+ *
+ * @param type the compression type used
+ * @param rate the sampling rate
+ * @param channels the number of channels
+ * @param blockAlign block alignment ???
+ * @return The new PacketizedAudioStream or NULL, if the type isn't supported.
+ */
+PacketizedAudioStream *makePacketizedADPCMStream(
+ ADPCMType type,
+ int rate,
+ int channels,
+ uint32 blockAlign = 0);
+
} // End of namespace Audio
#endif
Commit: 72239a25f9608935024560ab07f17a47863de0d7
https://github.com/scummvm/scummvm/commit/72239a25f9608935024560ab07f17a47863de0d7
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T21:00:54-04:00
Commit Message:
AUDIO: Add a NullAudioStream for streams that are dead-on-arrival
Changed paths:
audio/audiostream.cpp
audio/audiostream.h
diff --git a/audio/audiostream.cpp b/audio/audiostream.cpp
index c413edb..88c41e8 100644
--- a/audio/audiostream.cpp
+++ b/audio/audiostream.cpp
@@ -33,6 +33,7 @@
#include "audio/decoders/quicktime.h"
#include "audio/decoders/raw.h"
#include "audio/decoders/vorbis.h"
+#include "audio/mixer.h"
namespace Audio {
@@ -465,4 +466,24 @@ AudioStream *makeLimitingAudioStream(AudioStream *parentStream, const Timestamp
return new LimitingAudioStream(parentStream, length, disposeAfterUse);
}
+/**
+ * An AudioStream that plays nothing and immediately returns that
+ * the endOfStream() has been reached
+ */
+class NullAudioStream : public AudioStream {
+public:
+ bool isStereo() const { return false; }
+ int getRate() const;
+ int readBuffer(int16 *data, const int numSamples) { return 0; }
+ bool endOfData() const { return true; }
+};
+
+int NullAudioStream::getRate() const {
+ return g_system->getMixer()->getOutputRate();
+}
+
+AudioStream *makeNullAudioStream() {
+ return new NullAudioStream();
+}
+
} // End of namespace Audio
diff --git a/audio/audiostream.h b/audio/audiostream.h
index 6019aca..a60d5a2 100644
--- a/audio/audiostream.h
+++ b/audio/audiostream.h
@@ -433,6 +433,12 @@ private:
Common::ScopedPtr<QueuingAudioStream> _stream;
};
+/**
+ * Create an AudioStream that plays nothing and immediately returns that
+ * endOfStream() has been reached.
+ */
+AudioStream *makeNullAudioStream();
+
} // End of namespace Audio
#endif
Commit: 561d1a1d62b8abd3f5ff51d66e0c32ea436e68de
https://github.com/scummvm/scummvm/commit/561d1a1d62b8abd3f5ff51d66e0c32ea436e68de
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T21:01:39-04:00
Commit Message:
VIDEO: Switch to all packetized streams for AVI
ZVision does not currently, but that's OK
Changed paths:
engines/zvision/video/zork_avi_decoder.cpp
engines/zvision/video/zork_avi_decoder.h
video/avi_decoder.cpp
video/avi_decoder.h
diff --git a/engines/zvision/video/zork_avi_decoder.cpp b/engines/zvision/video/zork_avi_decoder.cpp
index 53b0a9a..fb6bdba 100644
--- a/engines/zvision/video/zork_avi_decoder.cpp
+++ b/engines/zvision/video/zork_avi_decoder.cpp
@@ -41,6 +41,15 @@ Video::AVIDecoder::AVIAudioTrack *ZorkAVIDecoder::createAudioTrack(Video::AVIDec
return new ZorkAVIAudioTrack(sHeader, wvInfo, _soundType);
}
+ZorkAVIDecoder::ZorkAVIAudioTrack::ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) :
+ Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType), _queueStream(0), _decoder(waveFormat.channels == 2) {
+}
+
+void ZorkAVIDecoder::ZorkAVIAudioTrack::createAudioStream() {
+ _queueStream = Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2);
+ _audioStream = _queueStream;
+}
+
void ZorkAVIDecoder::ZorkAVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
RawChunkStream::RawChunk chunk = _decoder.readNextChunk(stream);
delete stream;
diff --git a/engines/zvision/video/zork_avi_decoder.h b/engines/zvision/video/zork_avi_decoder.h
index 8e7be71..afcdb05 100644
--- a/engines/zvision/video/zork_avi_decoder.h
+++ b/engines/zvision/video/zork_avi_decoder.h
@@ -39,15 +39,14 @@ public:
private:
class ZorkAVIAudioTrack : public Video::AVIDecoder::AVIAudioTrack {
public:
- ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType) :
- Video::AVIDecoder::AVIAudioTrack(streamHeader, waveFormat, soundType),
- _decoder(waveFormat.channels == 2) {
- }
+ ZorkAVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType);
+ void createAudioStream();
void queueSound(Common::SeekableReadStream *stream);
void resetStream();
private:
+ Audio::QueuingAudioStream *_queueStream;
RawChunkStream _decoder;
};
diff --git a/video/avi_decoder.cpp b/video/avi_decoder.cpp
index aef5e76..52a55f6 100644
--- a/video/avi_decoder.cpp
+++ b/video/avi_decoder.cpp
@@ -278,7 +278,9 @@ void AVIDecoder::handleStreamHeader(uint32 size) {
if (wvInfo.channels == 2)
sHeader.sampleSize /= 2;
- addTrack(createAudioTrack(sHeader, wvInfo));
+ AVIAudioTrack *track = createAudioTrack(sHeader, wvInfo);
+ track->createAudioStream();
+ addTrack(track);
}
// Ensure that we're at the end of the chunk
@@ -841,40 +843,18 @@ void AVIDecoder::AVIVideoTrack::setDither(const byte *palette) {
}
AVIDecoder::AVIAudioTrack::AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType)
- : _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType), _curChunk(0) {
- createAudioStream();
+ : _audsHeader(streamHeader), _wvInfo(waveFormat), _soundType(soundType), _audioStream(0), _packetStream(0), _curChunk(0) {
}
AVIDecoder::AVIAudioTrack::~AVIAudioTrack() {
- delete _queueStream;
- delete _packetStream;
+ delete _audioStream;
}
void AVIDecoder::AVIAudioTrack::queueSound(Common::SeekableReadStream *stream) {
- if (_packetStream) {
+ if (_packetStream)
_packetStream->queuePacket(stream);
- } else if (_queueStream) {
- if (_wvInfo.tag == kWaveFormatPCM) {
- byte flags = 0;
- if (_audsHeader.sampleSize == 2)
- flags |= Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
- else
- flags |= Audio::FLAG_UNSIGNED;
-
- if (_wvInfo.channels == 2)
- flags |= Audio::FLAG_STEREO;
-
- _queueStream->queueAudioStream(Audio::makeRawStream(stream, _wvInfo.samplesPerSec, flags, DisposeAfterUse::YES), DisposeAfterUse::YES);
- } else if (_wvInfo.tag == kWaveFormatMSADPCM) {
- _queueStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMS, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
- } else if (_wvInfo.tag == kWaveFormatMSIMAADPCM) {
- _queueStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMMSIma, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
- } else if (_wvInfo.tag == kWaveFormatDK3) {
- _queueStream->queueAudioStream(Audio::makeADPCMStream(stream, DisposeAfterUse::YES, stream->size(), Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign), DisposeAfterUse::YES);
- }
- } else {
+ else
delete stream;
- }
_curChunk++;
}
@@ -899,8 +879,7 @@ void AVIDecoder::AVIAudioTrack::skipAudio(const Audio::Timestamp &time, const Au
}
void AVIDecoder::AVIAudioTrack::resetStream() {
- delete _queueStream;
- delete _packetStream;
+ delete _audioStream;
createAudioStream();
_curChunk = 0;
}
@@ -910,33 +889,50 @@ bool AVIDecoder::AVIAudioTrack::rewind() {
return true;
}
-Audio::AudioStream *AVIDecoder::AVIAudioTrack::getAudioStream() const {
- if (_packetStream)
- return _packetStream;
-
- return _queueStream;
-}
-
void AVIDecoder::AVIAudioTrack::createAudioStream() {
- _queueStream = 0;
_packetStream = 0;
- if (_wvInfo.tag == kWaveFormatPCM || _wvInfo.tag == kWaveFormatMSADPCM || _wvInfo.tag == kWaveFormatMSIMAADPCM || _wvInfo.tag == kWaveFormatDK3) {
- // For now, a QueuingAudioStream will be created
- } else if (_wvInfo.tag == kWaveFormatMP3) {
- // MPEG audio
+ switch (_wvInfo.tag) {
+ case kWaveFormatPCM: {
+ byte flags = 0;
+ if (_audsHeader.sampleSize == 2)
+ flags |= Audio::FLAG_16BITS | Audio::FLAG_LITTLE_ENDIAN;
+ else
+ flags |= Audio::FLAG_UNSIGNED;
+
+ if (_wvInfo.channels == 2)
+ flags |= Audio::FLAG_STEREO;
+
+ _packetStream = Audio::makePacketizedRawStream(_wvInfo.samplesPerSec, flags);
+ break;
+ }
+ case kWaveFormatMSADPCM:
+ _packetStream = Audio::makePacketizedADPCMStream(Audio::kADPCMMS, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign);
+ break;
+ case kWaveFormatMSIMAADPCM:
+ _packetStream = Audio::makePacketizedADPCMStream(Audio::kADPCMMSIma, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign);
+ break;
+ case kWaveFormatDK3:
+ _packetStream = Audio::makePacketizedADPCMStream(Audio::kADPCMDK3, _wvInfo.samplesPerSec, _wvInfo.channels, _wvInfo.blockAlign);
+ break;
+ case kWaveFormatMP3:
#ifdef USE_MAD
_packetStream = Audio::makePacketizedMP3Stream(_wvInfo.channels, _wvInfo.samplesPerSec);
#else
warning("AVI MP3 stream found, but no libmad support compiled in");
#endif
- } else if (_wvInfo.tag != kWaveFormatNone) {
- // No supported format
+ break;
+ case kWaveFormatNone:
+ break;
+ default:
warning("Unsupported AVI audio format %d", _wvInfo.tag);
+ break;
}
- if (!_packetStream)
- _queueStream = Audio::makeQueuingAudioStream(_wvInfo.samplesPerSec, _wvInfo.channels == 2);
+ if (_packetStream)
+ _audioStream = _packetStream;
+ else
+ _audioStream = Audio::makeNullAudioStream();
}
AVIDecoder::TrackStatus::TrackStatus() : track(0), chunkSearchOffset(0) {
diff --git a/video/avi_decoder.h b/video/avi_decoder.h
index 8b12c23..96d9e82 100644
--- a/video/avi_decoder.h
+++ b/video/avi_decoder.h
@@ -32,8 +32,8 @@
#include "audio/mixer.h"
namespace Audio {
+class AudioStream;
class PacketizedAudioStream;
-class QueuingAudioStream;
}
namespace Common {
@@ -216,6 +216,7 @@ protected:
AVIAudioTrack(const AVIStreamHeader &streamHeader, const PCMWaveFormat &waveFormat, Audio::Mixer::SoundType soundType);
~AVIAudioTrack();
+ virtual void createAudioStream();
virtual void queueSound(Common::SeekableReadStream *stream);
Audio::Mixer::SoundType getSoundType() const { return _soundType; }
void skipAudio(const Audio::Timestamp &time, const Audio::Timestamp &frameTime);
@@ -227,7 +228,7 @@ protected:
bool rewind();
protected:
- Audio::AudioStream *getAudioStream() const;
+ Audio::AudioStream *getAudioStream() const { return _audioStream; }
// Audio Codecs
enum {
@@ -242,9 +243,8 @@ protected:
AVIStreamHeader _audsHeader;
PCMWaveFormat _wvInfo;
Audio::Mixer::SoundType _soundType;
- Audio::QueuingAudioStream *_queueStream;
+ Audio::AudioStream *_audioStream;
Audio::PacketizedAudioStream *_packetStream;
- void createAudioStream();
uint32 _curChunk;
};
Commit: c8a7e39e0522b32e29ab403188f56bee9cf1da27
https://github.com/scummvm/scummvm/commit/c8a7e39e0522b32e29ab403188f56bee9cf1da27
Author: Matthew Hoops (clone2727 at gmail.com)
Date: 2015-08-30T21:01:43-04:00
Commit Message:
AUDIO: Mark the old Codec class as deprecated
Once QuickTime audio edits are rewritten to use PacketizedAudioStream, we can remove this class.
Changed paths:
audio/decoders/codec.h
diff --git a/audio/decoders/codec.h b/audio/decoders/codec.h
index 93b6878..75910c0 100644
--- a/audio/decoders/codec.h
+++ b/audio/decoders/codec.h
@@ -31,6 +31,13 @@ namespace Audio {
class AudioStream;
+/**
+ * @deprecated The old method of handling audio codecs that rely
+ * on the state remaining the same between calls. This should
+ * only be used for old code.
+ *
+ * DEPRECATED; USE PacketizedAudioStream INSTEAD!
+ */
class Codec {
public:
Codec() {}
More information about the Scummvm-git-logs
mailing list