aboutsummaryrefslogtreecommitdiff
path: root/audio/audiostream.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'audio/audiostream.cpp')
-rw-r--r--audio/audiostream.cpp80
1 files changed, 67 insertions, 13 deletions
diff --git a/audio/audiostream.cpp b/audio/audiostream.cpp
index 8bd4b95c49..88c41e8503 100644
--- a/audio/audiostream.cpp
+++ b/audio/audiostream.cpp
@@ -8,12 +8,12 @@
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
-
+ *
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
-
+ *
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
@@ -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 {
@@ -98,7 +99,7 @@ LoopingAudioStream::LoopingAudioStream(RewindableAudioStream *stream, uint loops
// TODO: Properly indicate error
_loops = _completeIterations = 1;
}
- if (stream->endOfData()) {
+ if (stream->endOfStream()) {
// Apparently this is an empty stream
_loops = _completeIterations = 1;
}
@@ -122,7 +123,7 @@ int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
_loops = _completeIterations = 1;
return samplesRead;
}
- if (_parent->endOfData()) {
+ if (_parent->endOfStream()) {
// Apparently this is an empty stream
_loops = _completeIterations = 1;
}
@@ -134,7 +135,11 @@ int LoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
}
bool LoopingAudioStream::endOfData() const {
- return (_loops != 0 && (_completeIterations == _loops));
+ return (_loops != 0 && _completeIterations == _loops) || _parent->endOfData();
+}
+
+bool LoopingAudioStream::endOfStream() const {
+ return _loops != 0 && _completeIterations == _loops;
}
AudioStream *makeLoopingAudioStream(RewindableAudioStream *stream, uint loops) {
@@ -189,7 +194,7 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
int framesRead = _parent->readBuffer(buffer, framesLeft);
_pos = _pos.addFrames(framesRead);
- if (framesRead < framesLeft && _parent->endOfData()) {
+ if (framesRead < framesLeft && _parent->endOfStream()) {
// TODO: Proper error indication.
_done = true;
return framesRead;
@@ -216,6 +221,18 @@ int SubLoopingAudioStream::readBuffer(int16 *buffer, const int numSamples) {
}
}
+bool SubLoopingAudioStream::endOfData() const {
+ // We're out of data if this stream is finished or the parent
+ // has run out of data for now.
+ return _done || _parent->endOfData();
+}
+
+bool SubLoopingAudioStream::endOfStream() const {
+ // The end of the stream has been reached only when we've gone
+ // through all the iterations.
+ return _done;
+}
+
#pragma mark -
#pragma mark --- SubSeekableAudioStream ---
#pragma mark -
@@ -315,18 +332,27 @@ public:
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();
+ Common::StackLock lock(_mutex);
+ return _queue.empty() || _queue.front()._stream->endOfData();
+ }
+
+ virtual bool endOfStream() const {
+ Common::StackLock lock(_mutex);
+ return _finished && _queue.empty();
}
- virtual bool endOfStream() const { return _finished && _queue.empty(); }
// Implement the QueuingAudioStream API
virtual void queueAudioStream(AudioStream *stream, DisposeAfterUse::Flag disposeAfterUse);
- virtual void finish() { _finished = true; }
+
+ virtual void finish() {
+ Common::StackLock lock(_mutex);
+ _finished = true;
+ }
uint32 numQueuedStreams() const {
- //Common::StackLock lock(_mutex);
+ Common::StackLock lock(_mutex);
return _queue.size();
}
};
@@ -356,11 +382,17 @@ int QueuingAudioStreamImpl::readBuffer(int16 *buffer, const int numSamples) {
AudioStream *stream = _queue.front()._stream;
samplesDecoded += stream->readBuffer(buffer + samplesDecoded, numSamples - samplesDecoded);
- if (stream->endOfData()) {
+ // Done with the stream completely
+ if (stream->endOfStream()) {
StreamHolder tmp = _queue.pop();
if (tmp._disposeAfterUse == DisposeAfterUse::YES)
delete stream;
+ continue;
}
+
+ // Done with data but not the stream, bail out
+ if (stream->endOfData())
+ break;
}
return samplesDecoded;
@@ -416,12 +448,14 @@ public:
return samplesRead;
}
- bool endOfData() const { return _parentStream->endOfData() || _samplesRead >= _totalSamples; }
+ bool endOfData() const { return _parentStream->endOfData() || reachedLimit(); }
+ bool endOfStream() const { return _parentStream->endOfStream() || reachedLimit(); }
bool isStereo() const { return _parentStream->isStereo(); }
int getRate() const { return _parentStream->getRate(); }
private:
int getChannels() const { return isStereo() ? 2 : 1; }
+ bool reachedLimit() const { return _samplesRead >= _totalSamples; }
AudioStream *_parentStream;
DisposeAfterUse::Flag _disposeAfterUse;
@@ -432,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