mirror of
https://github.com/libretro/scummvm.git
synced 2025-02-02 08:55:45 +00:00
Changed the AppendableAudioStream code to use a queue of buffers, instead of a fixed size wrap-around memory buffer (this reduces memory usage in some cases by 500-700k, while actually being more flexible)
svn-id: r25909
This commit is contained in:
parent
dea688d0f5
commit
8c8abca6f8
@ -268,8 +268,8 @@ bool VQAMovie::open(const char *filename) {
|
||||
_numPartialCodeBooks = 0;
|
||||
|
||||
if (_header.flags & 1) {
|
||||
// A 2-second buffer ought to be enough
|
||||
_stream = Audio::makeAppendableAudioStream(_header.freq, Audio::Mixer::FLAG_UNSIGNED, 2 * _header.freq * _header.channels);
|
||||
// TODO/FIXME: Shouldn't we set FLAG_STEREO if _header.channels == 2 (wonders Fingolfin)
|
||||
_stream = Audio::makeAppendableAudioStream(_header.freq, Audio::Mixer::FLAG_UNSIGNED);
|
||||
} else {
|
||||
_stream = NULL;
|
||||
}
|
||||
@ -399,9 +399,10 @@ void VQAMovie::displayFrame(uint frameNum) {
|
||||
switch (tag) {
|
||||
case MKID_BE('SND0'): // Uncompressed sound
|
||||
foundSound = true;
|
||||
inbuf = (byte *)allocBuffer(0, size);
|
||||
inbuf = new byte[size];
|
||||
_file.read(inbuf, size);
|
||||
_stream->append(inbuf, size);
|
||||
assert(_stream);
|
||||
_stream->queueBuffer(inbuf, size);
|
||||
break;
|
||||
|
||||
case MKID_BE('SND1'): // Compressed sound, almost like AUD
|
||||
@ -409,15 +410,18 @@ void VQAMovie::displayFrame(uint frameNum) {
|
||||
outsize = _file.readUint16LE();
|
||||
insize = _file.readUint16LE();
|
||||
|
||||
inbuf = (byte *)allocBuffer(0, insize);
|
||||
inbuf = new byte[insize];
|
||||
_file.read(inbuf, insize);
|
||||
|
||||
if (insize == outsize) {
|
||||
_stream->append(inbuf, insize);
|
||||
assert(_stream);
|
||||
_stream->queueBuffer(inbuf, insize);
|
||||
} else {
|
||||
outbuf = (byte *)allocBuffer(1, outsize);
|
||||
outbuf = new byte[outsize];
|
||||
decodeSND1(inbuf, insize, outbuf, outsize);
|
||||
_stream->append(outbuf, outsize);
|
||||
assert(_stream);
|
||||
_stream->queueBuffer(outbuf, outsize);
|
||||
delete[] inbuf;
|
||||
}
|
||||
break;
|
||||
|
||||
@ -589,24 +593,25 @@ void VQAMovie::play() {
|
||||
|
||||
switch (tag) {
|
||||
case MKID_BE('SND0'): // Uncompressed sound
|
||||
inbuf = (byte *)allocBuffer(0, size);
|
||||
inbuf = new byte[size];
|
||||
_file.read(inbuf, size);
|
||||
_stream->append(inbuf, size);
|
||||
_stream->queueBuffer(inbuf, size);
|
||||
break;
|
||||
|
||||
case MKID_BE('SND1'): // Compressed sound
|
||||
outsize = _file.readUint16LE();
|
||||
insize = _file.readUint16LE();
|
||||
|
||||
inbuf = (byte *)allocBuffer(0, insize);
|
||||
inbuf = new byte[insize];
|
||||
_file.read(inbuf, insize);
|
||||
|
||||
if (insize == outsize) {
|
||||
_stream->append(inbuf, insize);
|
||||
_stream->queueBuffer(inbuf, insize);
|
||||
} else {
|
||||
outbuf = (byte *)allocBuffer(1, outsize);
|
||||
outbuf = new byte[outsize];
|
||||
decodeSND1(inbuf, insize, outbuf, outsize);
|
||||
_stream->append(outbuf, outsize);
|
||||
_stream->queueBuffer(outbuf, outsize);
|
||||
delete[] inbuf;
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -188,9 +188,8 @@ void IMuseDigital::saveOrLoad(Serializer *ser) {
|
||||
track->mixerFlags |= Audio::Mixer::FLAG_LITTLE_ENDIAN;
|
||||
#endif
|
||||
|
||||
int32 streamBufferSize = track->iteration;
|
||||
track->stream2 = NULL;
|
||||
track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
|
||||
track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags);
|
||||
|
||||
const int pan = (track->pan != 64) ? 2 * track->pan - 127 : 0;
|
||||
const int vol = track->vol / 1000;
|
||||
@ -324,10 +323,10 @@ void IMuseDigital::callback() {
|
||||
if (_mixer->isReady()) {
|
||||
_mixer->setChannelVolume(track->handle, vol);
|
||||
_mixer->setChannelBalance(track->handle, pan);
|
||||
track->stream->append(data, result);
|
||||
track->stream->queueBuffer(data, result);
|
||||
track->regionOffset += result;
|
||||
}
|
||||
free(data);
|
||||
} else
|
||||
delete[] data;
|
||||
|
||||
if (_sound->isEndOfRegion(track->soundHandle, track->curRegion)) {
|
||||
switchToNextRegion(track);
|
||||
|
@ -583,11 +583,11 @@ int32 ImuseDigiSndMgr::getDataFromRegion(soundStruct *soundHandle, int region, b
|
||||
if ((soundHandle->bundle) && (!soundHandle->compressed)) {
|
||||
size = soundHandle->bundle->decompressSampleByCurIndex(start + offset, size, buf, header_size, header_outside);
|
||||
} else if (soundHandle->resPtr) {
|
||||
*buf = (byte *)malloc(size);
|
||||
*buf = new byte[size];
|
||||
assert(*buf);
|
||||
memcpy(*buf, soundHandle->resPtr + start + offset + header_size, size);
|
||||
} else if ((soundHandle->bundle) && (soundHandle->compressed)) {
|
||||
*buf = (byte *)malloc(size);
|
||||
*buf = new byte[size];
|
||||
assert(*buf);
|
||||
char fileName[24];
|
||||
sprintf(fileName, "%s_reg%03d", soundHandle->name, region);
|
||||
|
@ -176,9 +176,8 @@ void IMuseDigital::startSound(int soundId, const char *soundName, int soundType,
|
||||
type = Audio::Mixer::kMusicSoundType;
|
||||
|
||||
// setup 1 second stream wrapped buffer
|
||||
int32 streamBufferSize = track->iteration;
|
||||
track->stream2 = NULL;
|
||||
track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags, streamBufferSize);
|
||||
track->stream = Audio::makeAppendableAudioStream(freq, track->mixerFlags);
|
||||
_mixer->playInputStream(type, &track->handle, track->stream, -1, vol, pan, false);
|
||||
track->started = true;
|
||||
}
|
||||
@ -356,8 +355,7 @@ IMuseDigital::Track *IMuseDigital::cloneToFadeOutTrack(Track *track, int fadeDel
|
||||
type = Audio::Mixer::kMusicSoundType;
|
||||
|
||||
// setup 1 second stream wrapped buffer
|
||||
int32 streamBufferSize = fadeTrack->iteration;
|
||||
fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), fadeTrack->mixerFlags, streamBufferSize);
|
||||
fadeTrack->stream = Audio::makeAppendableAudioStream(_sound->getFreq(fadeTrack->soundHandle), fadeTrack->mixerFlags);
|
||||
_mixer->playInputStream(type, &fadeTrack->handle, fadeTrack->stream, -1, fadeTrack->vol / 1000, fadeTrack->pan, false);
|
||||
fadeTrack->started = true;
|
||||
fadeTrack->used = true;
|
||||
|
@ -105,6 +105,7 @@ bool SmushMixer::handleFrame() {
|
||||
|
||||
_channels[i].chan->getParameters(stereo, is_16bit, vol, pan);
|
||||
|
||||
// Grab the audio data from the channel
|
||||
int32 size = _channels[i].chan->getAvailableSoundDataSize();
|
||||
byte *data = _channels[i].chan->getSoundData();
|
||||
|
||||
@ -116,15 +117,16 @@ bool SmushMixer::handleFrame() {
|
||||
}
|
||||
|
||||
if (_mixer->isReady()) {
|
||||
// Stream the data
|
||||
if (!_channels[i].stream) {
|
||||
_channels[i].stream = Audio::makeAppendableAudioStream(_channels[i].chan->getRate(), flags, 500000);
|
||||
_channels[i].stream = Audio::makeAppendableAudioStream(_channels[i].chan->getRate(), flags);
|
||||
_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_channels[i].handle, _channels[i].stream);
|
||||
}
|
||||
_mixer->setChannelVolume(_channels[i].handle, vol);
|
||||
_mixer->setChannelBalance(_channels[i].handle, pan);
|
||||
_channels[i].stream->append(data, size);
|
||||
}
|
||||
delete[] data;
|
||||
_channels[i].stream->queueBuffer(data, size); // The stream will free the buffer for us
|
||||
} else
|
||||
delete[] data;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -462,7 +462,7 @@ void SmushPlayer::handleIACT(Chunk &b) {
|
||||
c->checkParameters(index, nbframes, size, track_flags, unknown);
|
||||
c->appendData(b, bsize);
|
||||
} else {
|
||||
byte output_data[4096];
|
||||
// TODO: Move this code into another SmushChannel subclass?
|
||||
byte *src = (byte *)malloc(bsize);
|
||||
b.read(src, bsize);
|
||||
byte *d_src = src;
|
||||
@ -477,6 +477,8 @@ void SmushPlayer::handleIACT(Chunk &b) {
|
||||
_IACTpos += bsize;
|
||||
bsize = 0;
|
||||
} else {
|
||||
byte *output_data = new byte[4096];
|
||||
|
||||
memcpy(_IACToutput + _IACTpos, d_src, len);
|
||||
byte *dst = output_data;
|
||||
byte *d_src2 = _IACToutput;
|
||||
@ -507,10 +509,10 @@ void SmushPlayer::handleIACT(Chunk &b) {
|
||||
} while (--count);
|
||||
|
||||
if (!_IACTstream) {
|
||||
_IACTstream = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_STEREO | Audio::Mixer::FLAG_16BITS, 900000);
|
||||
_IACTstream = Audio::makeAppendableAudioStream(22050, Audio::Mixer::FLAG_STEREO | Audio::Mixer::FLAG_16BITS);
|
||||
_vm->_mixer->playInputStream(Audio::Mixer::kSFXSoundType, &_IACTchannel, _IACTstream);
|
||||
}
|
||||
_IACTstream->append(output_data, 0x1000);
|
||||
_IACTstream->queueBuffer(output_data, 0x1000);
|
||||
|
||||
bsize -= len;
|
||||
d_src += len;
|
||||
|
@ -382,10 +382,8 @@ void Sound::initCowSystem(void) {
|
||||
}
|
||||
|
||||
void Sound::closeCowSystem(void) {
|
||||
if (_cowFile.isOpen())
|
||||
_cowFile.close();
|
||||
if (_cowHeader)
|
||||
free(_cowHeader);
|
||||
_cowFile.close();
|
||||
free(_cowHeader);
|
||||
_cowHeader = NULL;
|
||||
_currentCowFile = 0;
|
||||
}
|
||||
|
@ -23,6 +23,7 @@
|
||||
#include "common/stdafx.h"
|
||||
#include "common/endian.h"
|
||||
#include "common/file.h"
|
||||
#include "common/list.h"
|
||||
#include "common/util.h"
|
||||
|
||||
#include "sound/audiostream.h"
|
||||
@ -128,7 +129,6 @@ protected:
|
||||
const int _rate;
|
||||
const byte *_origPtr;
|
||||
|
||||
inline bool eosIntern() const { return _ptr >= _end; };
|
||||
public:
|
||||
LinearMemoryStream(int rate, const byte *ptr, uint len, uint loopOffset, uint loopLen, bool autoFreeMemory)
|
||||
: _ptr(ptr), _end(ptr+len), _loopPtr(0), _loopEnd(0), _rate(rate) {
|
||||
@ -154,7 +154,7 @@ public:
|
||||
int readBuffer(int16 *buffer, const int numSamples);
|
||||
|
||||
bool isStereo() const { return stereo; }
|
||||
bool endOfData() const { return eosIntern(); }
|
||||
bool endOfData() const { return _ptr >= _end; }
|
||||
|
||||
int getRate() const { return _rate; }
|
||||
};
|
||||
@ -162,7 +162,7 @@ public:
|
||||
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
|
||||
int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) {
|
||||
int samples = 0;
|
||||
while (samples < numSamples && !eosIntern()) {
|
||||
while (samples < numSamples && _ptr < _end) {
|
||||
const int len = MIN(numSamples, samples + (int)(_end - _ptr) / (is16Bit ? 2 : 1));
|
||||
while (samples < len) {
|
||||
*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _ptr, isLE);
|
||||
@ -170,7 +170,7 @@ int LinearMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buf
|
||||
samples++;
|
||||
}
|
||||
// Loop, if looping was specified
|
||||
if (_loopPtr && eosIntern()) {
|
||||
if (_loopPtr && _ptr >= _end) {
|
||||
_ptr = _loopPtr;
|
||||
_end = _loopEnd;
|
||||
}
|
||||
@ -228,6 +228,10 @@ AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32
|
||||
#pragma mark --- Appendable audio stream ---
|
||||
#pragma mark -
|
||||
|
||||
struct Buffer {
|
||||
byte *start;
|
||||
byte *end;
|
||||
};
|
||||
|
||||
/**
|
||||
* Wrapped memory stream.
|
||||
@ -235,18 +239,22 @@ AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32
|
||||
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
|
||||
class AppendableMemoryStream : public AppendableAudioStream {
|
||||
protected:
|
||||
|
||||
// A mutex to avoid access problems (causing e.g. corruption of
|
||||
// the linked list) in thread aware environments.
|
||||
Common::Mutex _mutex;
|
||||
|
||||
byte *_bufferStart;
|
||||
byte *_bufferEnd;
|
||||
byte *_pos;
|
||||
byte *_end;
|
||||
// List of all queueud buffers
|
||||
Common::List<Buffer> _bufferQueue;
|
||||
|
||||
// Position in the front buffer, if any
|
||||
bool _finalized;
|
||||
const int _rate;
|
||||
byte *_pos;
|
||||
|
||||
inline bool eosIntern() const { return _end == _pos; };
|
||||
inline bool eosIntern() const { return _bufferQueue.empty(); };
|
||||
public:
|
||||
AppendableMemoryStream(int rate, uint bufferSize);
|
||||
AppendableMemoryStream(int rate);
|
||||
~AppendableMemoryStream();
|
||||
int readBuffer(int16 *buffer, const int numSamples);
|
||||
|
||||
@ -256,30 +264,22 @@ public:
|
||||
|
||||
int getRate() const { return _rate; }
|
||||
|
||||
void append(const byte *data, uint32 len);
|
||||
void queueBuffer(byte *data, uint32 size);
|
||||
void finish() { _finalized = true; }
|
||||
};
|
||||
|
||||
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
|
||||
AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::AppendableMemoryStream(int rate, uint bufferSize)
|
||||
: _finalized(false), _rate(rate) {
|
||||
AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::AppendableMemoryStream(int rate)
|
||||
: _finalized(false), _rate(rate), _pos(0) {
|
||||
|
||||
// Verify the buffer size is sane
|
||||
if (is16Bit && stereo)
|
||||
assert((bufferSize & 3) == 0);
|
||||
else if (is16Bit || stereo)
|
||||
assert((bufferSize & 1) == 0);
|
||||
|
||||
_bufferStart = (byte *)malloc(bufferSize);
|
||||
assert(_bufferStart != NULL);
|
||||
|
||||
_pos = _end = _bufferStart;
|
||||
_bufferEnd = _bufferStart + bufferSize;
|
||||
}
|
||||
|
||||
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
|
||||
AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::~AppendableMemoryStream() {
|
||||
free(_bufferStart);
|
||||
// Clear the queue
|
||||
Common::List<Buffer>::iterator iter;
|
||||
for (iter = _bufferQueue.begin(); iter != _bufferQueue.end(); ++iter)
|
||||
delete[] iter->start;
|
||||
}
|
||||
|
||||
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
|
||||
@ -288,12 +288,19 @@ int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16
|
||||
|
||||
int samples = 0;
|
||||
while (samples < numSamples && !eosIntern()) {
|
||||
// Wrap around?
|
||||
if (_pos >= _bufferEnd)
|
||||
_pos = _pos - (_bufferEnd - _bufferStart);
|
||||
Buffer buf = *_bufferQueue.begin();
|
||||
if (_pos == 0)
|
||||
_pos = buf.start;
|
||||
|
||||
const byte *endMarker = (_pos > _end) ? _bufferEnd : _end;
|
||||
const int len = MIN(numSamples, samples + (int)(endMarker - _pos) / (is16Bit ? 2 : 1));
|
||||
assert(buf.start <= _pos && _pos <= buf.end);
|
||||
const int samplesLeftInCurBuffer = buf.end - _pos;
|
||||
if (samplesLeftInCurBuffer == 0) {
|
||||
_bufferQueue.erase(_bufferQueue.begin());
|
||||
_pos = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
const int len = MIN(numSamples, samples + samplesLeftInCurBuffer / (is16Bit ? 2 : 1));
|
||||
while (samples < len) {
|
||||
*buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _pos, isLE);
|
||||
_pos += (is16Bit ? 2 : 1);
|
||||
@ -305,50 +312,45 @@ int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16
|
||||
}
|
||||
|
||||
template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE>
|
||||
void AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::append(const byte *data, uint32 len) {
|
||||
void AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::queueBuffer(byte *data, uint32 size) {
|
||||
Common::StackLock lock(_mutex);
|
||||
|
||||
// Verify the buffer size is sane
|
||||
if (is16Bit && stereo)
|
||||
assert((len & 3) == 0);
|
||||
assert((size & 3) == 0);
|
||||
else if (is16Bit || stereo)
|
||||
assert((len & 1) == 0);
|
||||
assert((size & 1) == 0);
|
||||
|
||||
// Verify that the stream has not yet been finalized (by a call to finish())
|
||||
assert(!_finalized);
|
||||
|
||||
if (_end + len > _bufferEnd) {
|
||||
// Wrap-around case
|
||||
uint32 size_to_end_of_buffer = _bufferEnd - _end;
|
||||
len -= size_to_end_of_buffer;
|
||||
if ((_end < _pos) || (_bufferStart + len >= _pos)) {
|
||||
debug(2, "AppendableMemoryStream: buffer overflow (A)");
|
||||
return;
|
||||
}
|
||||
memcpy(_end, data, size_to_end_of_buffer);
|
||||
memcpy(_bufferStart, data + size_to_end_of_buffer, len);
|
||||
_end = _bufferStart + len;
|
||||
} else {
|
||||
if ((_end < _pos) && (_end + len >= _pos)) {
|
||||
debug(2, "AppendableMemoryStream: buffer overflow (B)");
|
||||
return;
|
||||
}
|
||||
memcpy(_end, data, len);
|
||||
_end += len;
|
||||
}
|
||||
// Queue the buffer
|
||||
Buffer buf = {data, data+size};
|
||||
_bufferQueue.push_back(buf);
|
||||
|
||||
|
||||
#if 0
|
||||
// Output some stats
|
||||
uint totalSize = 0;
|
||||
Common::List<Buffer>::iterator iter;
|
||||
for (iter = _bufferQueue.begin(); iter != _bufferQueue.end(); ++iter)
|
||||
totalSize += iter->end - iter->start;
|
||||
printf("AppendableMemoryStream::queueBuffer: added a %d byte buf, a total of %d bytes are queued\n",
|
||||
size, totalSize);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#define MAKE_WRAPPED(STEREO, UNSIGNED) \
|
||||
if (is16Bit) { \
|
||||
if (isLE) \
|
||||
return new AppendableMemoryStream<STEREO, true, UNSIGNED, true>(rate, len); \
|
||||
return new AppendableMemoryStream<STEREO, true, UNSIGNED, true>(rate); \
|
||||
else \
|
||||
return new AppendableMemoryStream<STEREO, true, UNSIGNED, false>(rate, len); \
|
||||
return new AppendableMemoryStream<STEREO, true, UNSIGNED, false>(rate); \
|
||||
} else \
|
||||
return new AppendableMemoryStream<STEREO, false, UNSIGNED, false>(rate, len)
|
||||
return new AppendableMemoryStream<STEREO, false, UNSIGNED, false>(rate)
|
||||
|
||||
AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len) {
|
||||
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;
|
||||
|
@ -31,7 +31,8 @@
|
||||
namespace Audio {
|
||||
|
||||
/**
|
||||
* Generic input stream for the resampling code.
|
||||
* Generic audio input stream. Subclasses of this are used to feed arbitrary
|
||||
* sampled audio data into ScummVM's audio mixer.
|
||||
*/
|
||||
class AudioStream {
|
||||
public:
|
||||
@ -89,6 +90,13 @@ public:
|
||||
static AudioStream* openStreamFile(const char *filename);
|
||||
};
|
||||
|
||||
/**
|
||||
* Factory function for a raw linear AudioStream, which will simply treat all data
|
||||
* in the buffer described by ptr and len as raw sample data in the specified
|
||||
* format. It will then simply pass this data directly to the mixer, after converting
|
||||
* it to the sample format used by the mixer (i.e. 16 bit signed native endian).
|
||||
* Optionally supports (infinite) looping of a portion of the data.
|
||||
*/
|
||||
AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32 len, uint loopOffset, uint loopLen);
|
||||
|
||||
/**
|
||||
@ -97,11 +105,29 @@ AudioStream *makeLinearInputStream(int rate, byte flags, const byte *ptr, uint32
|
||||
*/
|
||||
class AppendableAudioStream : public Audio::AudioStream {
|
||||
public:
|
||||
virtual void append(const byte *data, uint32 len) = 0;
|
||||
|
||||
/**
|
||||
* Queue another audio data buffer for playback. The stream
|
||||
* will playback 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).
|
||||
*/
|
||||
virtual void queueBuffer(byte *data, uint32 size) = 0;
|
||||
|
||||
/**
|
||||
* Mark the stream as finished, that is, signal that no further data
|
||||
* will be appended to it. Only after this has been done can the
|
||||
* AppendableAudioStream ever 'end' (
|
||||
*/
|
||||
virtual void finish() = 0;
|
||||
};
|
||||
|
||||
AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len);
|
||||
/**
|
||||
* Factory function for an AppendableAudioStream. The rate and flags
|
||||
* parameters are analog to those used in makeLinearInputStream.
|
||||
*/
|
||||
AppendableAudioStream *makeAppendableAudioStream(int rate, byte flags);
|
||||
|
||||
|
||||
} // End of namespace Audio
|
||||
|
Loading…
x
Reference in New Issue
Block a user