aboutsummaryrefslogtreecommitdiff
path: root/sound
diff options
context:
space:
mode:
authorMax Horn2010-01-08 22:04:30 +0000
committerMax Horn2010-01-08 22:04:30 +0000
commit95726dfe50eae85d0e7675f8891339fb0abb43fd (patch)
treebf4f9ebb29ce8f74e2f3eee786931859b76fcc1f /sound
parentf263393ef00517143876d26da2d35541307cb51c (diff)
downloadscummvm-rg350-95726dfe50eae85d0e7675f8891339fb0abb43fd.tar.gz
scummvm-rg350-95726dfe50eae85d0e7675f8891339fb0abb43fd.tar.bz2
scummvm-rg350-95726dfe50eae85d0e7675f8891339fb0abb43fd.zip
Move Mohawk's QueuedAudioStream to sound/ (with some tweaks)
svn-id: r47177
Diffstat (limited to 'sound')
-rw-r--r--sound/audiostream.cpp159
-rw-r--r--sound/audiostream.h45
2 files changed, 184 insertions, 20 deletions
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.