diff options
Diffstat (limited to 'scumm')
-rw-r--r-- | scumm/imuse_digi/dimuse.h | 1 | ||||
-rw-r--r-- | scumm/smush/smush_mixer.h | 3 | ||||
-rw-r--r-- | scumm/smush/smush_player.h | 3 | ||||
-rw-r--r-- | scumm/sound.cpp | 146 | ||||
-rw-r--r-- | scumm/sound.h | 14 |
5 files changed, 163 insertions, 4 deletions
diff --git a/scumm/imuse_digi/dimuse.h b/scumm/imuse_digi/dimuse.h index 0b2a057f6d..eb1e0df68f 100644 --- a/scumm/imuse_digi/dimuse.h +++ b/scumm/imuse_digi/dimuse.h @@ -28,6 +28,7 @@ #include "scumm/imuse_digi/dimuse_sndmgr.h" #include "scumm/music.h" #include "scumm/saveload.h" +#include "scumm/sound.h" #include "sound/mixer.h" #include "sound/audiostream.h" diff --git a/scumm/smush/smush_mixer.h b/scumm/smush/smush_mixer.h index 29d40766cc..051303997e 100644 --- a/scumm/smush/smush_mixer.h +++ b/scumm/smush/smush_mixer.h @@ -23,8 +23,7 @@ #define SMUSH_MIXER_H #include "stdafx.h" -#include "sound/audiostream.h" -#include "sound/mixer.h" +#include "scumm/sound.h" namespace Scumm { diff --git a/scumm/smush/smush_player.h b/scumm/smush/smush_player.h index 08629450b5..4238e0f053 100644 --- a/scumm/smush/smush_player.h +++ b/scumm/smush/smush_player.h @@ -26,8 +26,7 @@ #include "scumm/smush/chunk.h" #include "scumm/smush/codec37.h" #include "scumm/smush/codec47.h" -#include "sound/audiostream.h" -#include "sound/mixer.h" +#include "scumm/sound.h" namespace Scumm { diff --git a/scumm/sound.cpp b/scumm/sound.cpp index 2d277a1bcf..6892579cf4 100644 --- a/scumm/sound.cpp +++ b/scumm/sound.cpp @@ -2237,4 +2237,150 @@ int ScummEngine::readSoundResourceSmallHeader(int type, int idx) { } +#pragma mark - +#pragma mark --- Appendable audio stream --- +#pragma mark - + + +/** + * Wrapped memory stream. + */ +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +class AppendableMemoryStream : public AppendableAudioStream { +protected: + OSystem::MutexRef _mutex; + + byte *_bufferStart; + byte *_bufferEnd; + byte *_pos; + byte *_end; + bool _finalized; + const int _rate; + + inline bool eosIntern() const { return _end == _pos; }; +public: + AppendableMemoryStream(int rate, uint bufferSize); + ~AppendableMemoryStream(); + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { return stereo; } + bool endOfStream() const { return _finalized && eosIntern(); } + bool endOfData() const { return eosIntern(); } + + int getRate() const { return _rate; } + + void append(const byte *data, uint32 len); + 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) { + + // 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); + _pos = _end = _bufferStart; + _bufferEnd = _bufferStart + bufferSize; + + _mutex = g_system->createMutex(); +} + +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::~AppendableMemoryStream() { + free(_bufferStart); + g_system->deleteMutex(_mutex); +} + +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +int AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::readBuffer(int16 *buffer, const int numSamples) { + Common::StackLock lock(_mutex); + + int samples = 0; + while (samples < numSamples && !eosIntern()) { + // Wrap around? + if (_pos >= _bufferEnd) + _pos = _pos - (_bufferEnd - _bufferStart); + + const byte *endMarker = (_pos > _end) ? _bufferEnd : _end; + const int len = MIN(numSamples, samples + (int)(endMarker - _pos) / (is16Bit ? 2 : 1)); + while (samples < len) { + *buffer++ = READ_ENDIAN_SAMPLE(is16Bit, isUnsigned, _pos, isLE); + _pos += (is16Bit ? 2 : 1); + samples++; + } + } + + return samples; +} + +template<bool stereo, bool is16Bit, bool isUnsigned, bool isLE> +void AppendableMemoryStream<stereo, is16Bit, isUnsigned, isLE>::append(const byte *data, uint32 len) { + Common::StackLock lock(_mutex); + + // Verify the buffer size is sane + if (is16Bit && stereo) + assert((len & 3) == 0); + else if (is16Bit || stereo) + assert((len & 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; + } +} + + +#define MAKE_WRAPPED(STEREO, UNSIGNED) \ + if (is16Bit) { \ + if (isLE) \ + return new AppendableMemoryStream<STEREO, true, UNSIGNED, true>(rate, len); \ + else \ + return new AppendableMemoryStream<STEREO, true, UNSIGNED, false>(rate, len); \ + } else \ + return new AppendableMemoryStream<STEREO, false, UNSIGNED, false>(rate, len) + +AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len) { + const bool isStereo = (_flags & SoundMixer::FLAG_STEREO) != 0; + const bool is16Bit = (_flags & SoundMixer::FLAG_16BITS) != 0; + const bool isUnsigned = (_flags & SoundMixer::FLAG_UNSIGNED) != 0; + const bool isLE = (_flags & SoundMixer::FLAG_LITTLE_ENDIAN) != 0; + + if (isStereo) { + if (isUnsigned) { + MAKE_WRAPPED(true, true); + } else { + MAKE_WRAPPED(true, false); + } + } else { + if (isUnsigned) { + MAKE_WRAPPED(false, true); + } else { + MAKE_WRAPPED(false, false); + } + } +} + } // End of namespace Scumm diff --git a/scumm/sound.h b/scumm/sound.h index 6bbff1dfe2..16d1e7b738 100644 --- a/scumm/sound.h +++ b/scumm/sound.h @@ -22,6 +22,7 @@ #define SOUND_H #include "common/scummsys.h" +#include "sound/audiostream.h" #include "sound/mixer.h" class File; @@ -129,6 +130,19 @@ protected: bool isSoundInQueue(int sound) const; }; +/** + * An audio stream to which additional data can be appended on-the-fly. + * Used by SMUSH and iMuseDigital. + */ +class AppendableAudioStream : public AudioStream { +public: + virtual void append(const byte *data, uint32 len) = 0; + virtual void finish() = 0; +}; + +AppendableAudioStream *makeAppendableAudioStream(int rate, byte _flags, uint32 len); + + } // End of namespace Scumm #endif |