aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/mohawk/video/qt_player.cpp47
-rw-r--r--engines/mohawk/video/qt_player.h27
-rw-r--r--sound/audiostream.cpp159
-rw-r--r--sound/audiostream.h45
4 files changed, 188 insertions, 90 deletions
diff --git a/engines/mohawk/video/qt_player.cpp b/engines/mohawk/video/qt_player.cpp
index 8c6e9b1a95..d9d4a68dac 100644
--- a/engines/mohawk/video/qt_player.cpp
+++ b/engines/mohawk/video/qt_player.cpp
@@ -51,47 +51,6 @@
namespace Mohawk {
////////////////////////////////////////////
-// QueuedAudioStream
-////////////////////////////////////////////
-
-QueuedAudioStream::QueuedAudioStream(int rate, int channels, bool autofree) {
- _rate = rate;
- _channels = channels;
- _autofree = autofree;
- _finished = false;
-}
-
-QueuedAudioStream::~QueuedAudioStream() {
- if (_autofree)
- while (!_queue.empty())
- delete _queue.pop();
- _queue.clear();
-}
-
-void QueuedAudioStream::queueAudioStream(Audio::AudioStream *audStream) {
- if (audStream->getRate() != getRate() && audStream->isStereo() && isStereo())
- error("QueuedAudioStream::queueAudioStream: audStream has mismatched parameters");
-
- _queue.push(audStream);
-}
-
-int QueuedAudioStream::readBuffer(int16 *buffer, const int numSamples) {
- int samplesDecoded = 0;
-
- while (samplesDecoded < numSamples && !_queue.empty()) {
- samplesDecoded += _queue.front()->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
-
- if (_queue.front()->endOfData()) {
- Audio::AudioStream *temp = _queue.pop();
- if (_autofree)
- delete temp;
- }
- }
-
- return samplesDecoded;
-}
-
-////////////////////////////////////////////
// QTPlayer
////////////////////////////////////////////
@@ -189,7 +148,7 @@ void QTPlayer::reset() {
stopAudio();
if (_audioStreamIndex >= 0) {
_curAudioChunk = 0;
- _audStream = new QueuedAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels);
+ _audStream = Audio::makeQueuedAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels == 2);
}
startAudio();
}
@@ -345,7 +304,7 @@ bool QTPlayer::loadFile(Common::SeekableReadStream *stream) {
}
if (_audioStreamIndex >= 0 && checkAudioCodecSupport(_streams[_audioStreamIndex]->codec_tag)) {
- _audStream = new QueuedAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels);
+ _audStream = Audio::makeQueuedAudioStream(_streams[_audioStreamIndex]->sample_rate, _streams[_audioStreamIndex]->channels == 2);
_curAudioChunk = 0;
// Make sure the bits per sample transfers to the sample size
@@ -1229,7 +1188,7 @@ void QTPlayer::updateAudioBuffer() {
return;
// Keep two streams in buffer so that when the first ends, it goes right into the next
- for (; _audStream->streamsInQueue() < 2 && _curAudioChunk < _streams[_audioStreamIndex]->chunk_count; _curAudioChunk++) {
+ for (; _audStream->numQueuedStreams() < 2 && _curAudioChunk < _streams[_audioStreamIndex]->chunk_count; _curAudioChunk++) {
Common::MemoryWriteStreamDynamic *wStream = new Common::MemoryWriteStreamDynamic();
_fd->seek(_streams[_audioStreamIndex]->chunk_offsets[_curAudioChunk]);
diff --git a/engines/mohawk/video/qt_player.h b/engines/mohawk/video/qt_player.h
index 4bdf5b869b..5ff27a57c5 100644
--- a/engines/mohawk/video/qt_player.h
+++ b/engines/mohawk/video/qt_player.h
@@ -46,31 +46,6 @@ namespace Common {
namespace Mohawk {
-class QueuedAudioStream : public Audio::AudioStream {
-public:
- QueuedAudioStream(int rate, int channels, bool autofree = true);
- ~QueuedAudioStream();
-
- int readBuffer(int16 *buffer, const int numSamples);
- bool isStereo() const { return _channels == 2; }
- int getRate() const { return _rate; }
- bool endOfData() const { return _queue.empty(); }
- bool endOfStream() const { return _finished; }
-
- void queueAudioStream(Audio::AudioStream *audStream);
- void finish() { _finished = true; }
-
- uint32 streamsInQueue() { return _queue.size(); }
-
-private:
- bool _autofree;
- bool _finished;
- int _rate;
- int _channels;
-
- Common::Queue<Audio::AudioStream*> _queue;
-};
-
enum ScaleMode {
kScaleNormal = 1,
kScaleHalf = 2,
@@ -271,7 +246,7 @@ protected:
void resetInternal();
uint32 getFrameDuration();
- QueuedAudioStream *_audStream;
+ Audio::QueuedAudioStream *_audStream;
int8 _videoStreamIndex;
int8 _audioStreamIndex;
uint _curAudioChunk;
diff --git a/sound/audiostream.cpp b/sound/audiostream.cpp
index 98cece6dfb..16c5ff673a 100644
--- a/sound/audiostream.cpp
+++ b/sound/audiostream.cpp
@@ -27,6 +27,7 @@
#include "common/endian.h"
#include "common/file.h"
#include "common/list.h"
+#include "common/queue.h"
#include "common/util.h"
#include "sound/audiostream.h"
@@ -523,15 +524,15 @@ bool LinearDiskStream<stereo, is16Bit, isUnsigned, isLE>::seek(const Timestamp &
return new LinearMemoryStream<STEREO, false, UNSIGNED, false>(rate, ptr, len, loopOffset, loopLen, autoFree)
SeekableAudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate, byte flags, uint loopStart, uint loopEnd) {
- const bool isStereo = (flags & Audio::Mixer::FLAG_STEREO) != 0;
- const bool is16Bit = (flags & Audio::Mixer::FLAG_16BITS) != 0;
- const bool isUnsigned = (flags & Audio::Mixer::FLAG_UNSIGNED) != 0;
- const bool isLE = (flags & Audio::Mixer::FLAG_LITTLE_ENDIAN) != 0;
- const bool autoFree = (flags & Audio::Mixer::FLAG_AUTOFREE) != 0;
+ const bool isStereo = (flags & Mixer::FLAG_STEREO) != 0;
+ const bool is16Bit = (flags & Mixer::FLAG_16BITS) != 0;
+ const bool isUnsigned = (flags & Mixer::FLAG_UNSIGNED) != 0;
+ const bool isLE = (flags & Mixer::FLAG_LITTLE_ENDIAN) != 0;
+ const bool autoFree = (flags & Mixer::FLAG_AUTOFREE) != 0;
uint loopOffset = 0, loopLen = 0;
- if (flags & Audio::Mixer::FLAG_LOOP) {
+ if (flags & Mixer::FLAG_LOOP) {
if (loopEnd == 0)
loopEnd = len;
assert(loopStart <= loopEnd);
@@ -578,11 +579,11 @@ SeekableAudioStream *makeLinearInputStream(const byte *ptr, uint32 len, int rate
SeekableAudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, LinearDiskStreamAudioBlock *block, int numBlocks, int rate, byte flags, bool takeOwnership, uint loopStart, uint loopEnd) {
- const bool isStereo = (flags & Audio::Mixer::FLAG_STEREO) != 0;
- const bool is16Bit = (flags & Audio::Mixer::FLAG_16BITS) != 0;
- const bool isUnsigned = (flags & Audio::Mixer::FLAG_UNSIGNED) != 0;
- const bool isLE = (flags & Audio::Mixer::FLAG_LITTLE_ENDIAN) != 0;
- const bool loop = (flags & Audio::Mixer::FLAG_LOOP) != 0;
+ const bool isStereo = (flags & Mixer::FLAG_STEREO) != 0;
+ const bool is16Bit = (flags & Mixer::FLAG_16BITS) != 0;
+ const bool isUnsigned = (flags & Mixer::FLAG_UNSIGNED) != 0;
+ const bool isLE = (flags & Mixer::FLAG_LITTLE_ENDIAN) != 0;
+ const bool loop = (flags & Mixer::FLAG_LOOP) != 0;
if (isStereo) {
if (isUnsigned) {
@@ -600,8 +601,6 @@ SeekableAudioStream *makeLinearDiskStream(Common::SeekableReadStream *stream, Li
}
-
-
#pragma mark -
#pragma mark --- Appendable audio stream ---
#pragma mark -
@@ -617,16 +616,18 @@ struct Buffer {
class BaseAppendableMemoryStream : public AppendableAudioStream {
protected:
- // A mutex to avoid access problems (causing e.g. corruption of
- // the linked list) in thread aware environments.
+ /**
+ * A mutex to avoid access problems (causing e.g. corruption of
+ * the linked list) in thread aware environments.
+ */
Common::Mutex _mutex;
// List of all queued buffers
Common::List<Buffer> _bufferQueue;
- // Position in the front buffer, if any
bool _finalized;
const int _rate;
+ // Position in the front buffer, if any
byte *_pos;
inline bool eosIntern() const { return _bufferQueue.empty(); };
@@ -739,10 +740,10 @@ void BaseAppendableMemoryStream::queueBuffer(byte *data, uint32 size) {
return new AppendableMemoryStream<STEREO, false, UNSIGNED, false>(rate)
AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags) {
- const bool isStereo = (_flags & Audio::Mixer::FLAG_STEREO) != 0;
- const bool is16Bit = (_flags & Audio::Mixer::FLAG_16BITS) != 0;
- const bool isUnsigned = (_flags & Audio::Mixer::FLAG_UNSIGNED) != 0;
- const bool isLE = (_flags & Audio::Mixer::FLAG_LITTLE_ENDIAN) != 0;
+ const bool isStereo = (_flags & Mixer::FLAG_STEREO) != 0;
+ const bool is16Bit = (_flags & Mixer::FLAG_16BITS) != 0;
+ const bool isUnsigned = (_flags & Mixer::FLAG_UNSIGNED) != 0;
+ const bool isLE = (_flags & Mixer::FLAG_LITTLE_ENDIAN) != 0;
if (isStereo) {
if (isUnsigned) {
@@ -760,4 +761,122 @@ AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags) {
}
+
+
+
+#pragma mark -
+#pragma mark --- Appendable audio stream ---
+#pragma mark -
+
+
+class QueuedAudioStreamImpl : public QueuedAudioStream {
+private:
+ /**
+ * We queue a number of (pointers to) audio stream objects.
+ * In addition, we need to remember for each stream whether
+ * to dispose it after all data has been read from it.
+ * Hence, we don't store pointers to stream objects directly,
+ * but rather StreamHolder structs.
+ */
+ struct StreamHolder {
+ AudioStream *_stream;
+ bool _disposeAfterUse;
+ StreamHolder(AudioStream *stream, bool disposeAfterUse)
+ : _stream(stream),
+ _disposeAfterUse(disposeAfterUse) {}
+ };
+
+ /**
+ * The sampling rate of this audio stream.
+ */
+ const int _rate;
+
+ /**
+ * Whether this audio stream is mono (=false) or stereo (=true).
+ */
+ const int _stereo;
+
+ /**
+ * This flag is set by the finish() method only. See there for more details.
+ */
+ bool _finished;
+
+ /**
+ * A mutex to avoid access problems (causing e.g. corruption of
+ * the linked list) in thread aware environments.
+ */
+ Common::Mutex _mutex;
+
+ /**
+ * The queue of audio streams.
+ */
+ Common::Queue<StreamHolder> _queue;
+
+public:
+ QueuedAudioStreamImpl(int rate, bool stereo)
+ : _rate(rate), _stereo(stereo), _finished(false) {}
+ ~QueuedAudioStreamImpl();
+
+ // Implement the AudioStream API
+ virtual int readBuffer(int16 *buffer, const int numSamples);
+ virtual bool isStereo() const { return _stereo; }
+ virtual int getRate() const { return _rate; }
+ virtual bool endOfData() const {
+ //Common::StackLock lock(_mutex);
+ return _queue.empty();
+ }
+ virtual bool endOfStream() const { return _finished; }
+
+ // Implement the QueuedAudioStream API
+ virtual void queueAudioStream(AudioStream *stream, bool disposeAfterUse);
+ virtual void finish() { _finished = true; }
+
+ uint32 numQueuedStreams() const {
+ //Common::StackLock lock(_mutex);
+ return _queue.size();
+ }
+};
+
+QueuedAudioStreamImpl::~QueuedAudioStreamImpl() {
+ while (!_queue.empty()) {
+ StreamHolder tmp = _queue.pop();
+ if (tmp._disposeAfterUse)
+ delete tmp._stream;
+ }
+}
+
+void QueuedAudioStreamImpl::queueAudioStream(AudioStream *stream, bool disposeAfterUse) {
+ if ((stream->getRate() != getRate()) || (stream->isStereo() != isStereo()))
+ error("QueuedAudioStreamImpl::queueAudioStream: stream has mismatched parameters");
+
+ Common::StackLock lock(_mutex);
+ _queue.push(StreamHolder(stream, disposeAfterUse));
+}
+
+int QueuedAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) {
+ Common::StackLock lock(_mutex);
+ int samplesDecoded = 0;
+
+ while (samplesDecoded < numSamples && !_queue.empty()) {
+ AudioStream *stream = _queue.front()._stream;
+ samplesDecoded += stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
+
+ if (stream->endOfData() ) {
+ StreamHolder tmp = _queue.pop();
+ if (tmp._disposeAfterUse)
+ delete stream;
+ }
+ }
+
+ return samplesDecoded;
+}
+
+
+
+QueuedAudioStream *makeQueuedAudioStream(int rate, bool stereo) {
+ return new QueuedAudioStreamImpl(rate, stereo);
+}
+
+
+
} // End of namespace Audio
diff --git a/sound/audiostream.h b/sound/audiostream.h
index e418c2d524..7ffbeab5cb 100644
--- a/sound/audiostream.h
+++ b/sound/audiostream.h
@@ -319,6 +319,51 @@ public:
*/
AppendableAudioStream *makeAppendableAudioStream(int rate, byte flags);
+
+class QueuedAudioStream : public Audio::AudioStream {
+public:
+
+ /**
+ * Queue an audio stream for playback. This stream will
+ * play all queued streams, in the order they were queued.
+ * If the disposeAfterUse is true, then the stream is
+ * deleted after all data contained in it has been played.
+ */
+ virtual void queueAudioStream(Audio::AudioStream *audStream,
+ bool disposeAfterUse = true) = 0;
+
+ /**
+ * Queue a block of raw audio data for playback. This stream
+ * will play all queued buffers, in the order they were
+ * queued. After all data contained in them has been played,
+ * the buffer will be delete[]'d (so make sure to allocate them
+ * with new[], not with malloc).
+ */
+ void queueBuffer(byte *data, uint32 size, byte flags) {
+ AudioStream *stream = makeLinearInputStream(data, size, getRate(), flags, 0, 0);
+ queueAudioStream(stream, true);
+ }
+
+ /**
+ * Mark the stream as finished, that is, signal that no further data
+ * will be appended to it. Only after this has been done can this
+ * stream ever 'end'.
+ */
+ virtual void finish() = 0;
+
+ /**
+ * Return the number of streams still queued for playback (including
+ * the currently playing stream).
+ */
+ virtual uint32 numQueuedStreams() const = 0;
+};
+
+/**
+ * Factory function for an QueuedAudioStream.
+ */
+QueuedAudioStream *makeQueuedAudioStream(int rate, bool stereo);
+
+
/**
* Calculates the sample, which the timestamp describes in a
* AudioStream with the given framerate.