From b7b5fbbad2808a0c5112bebbb59a5a1c43042e29 Mon Sep 17 00:00:00 2001 From: Evgeny Grechnikov Date: Wed, 17 Oct 2018 23:03:00 +0300 Subject: LASTEXPRESS: support for looped sounds --- engines/lastexpress/data/snd.cpp | 30 ++++++++++++++++++++++-------- engines/lastexpress/data/snd.h | 6 ++++-- engines/lastexpress/debug.cpp | 2 +- engines/lastexpress/sound/entry.cpp | 6 +++--- engines/lastexpress/sound/entry.h | 3 +-- 5 files changed, 31 insertions(+), 16 deletions(-) (limited to 'engines/lastexpress') diff --git a/engines/lastexpress/data/snd.cpp b/engines/lastexpress/data/snd.cpp index 7fb2c07706..835a1ab8fb 100644 --- a/engines/lastexpress/data/snd.cpp +++ b/engines/lastexpress/data/snd.cpp @@ -349,13 +349,18 @@ static const int imaTable[1424] = { class LastExpress_ADPCMStream : public Audio::ADPCMStream { public: - LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize, uint32 volume) : + LastExpress_ADPCMStream(Common::SeekableReadStream *stream, DisposeAfterUse::Flag disposeAfterUse, uint32 size, uint32 blockSize, uint32 volume, bool looped) : Audio::ADPCMStream(stream, disposeAfterUse, size, 44100, 1, blockSize) { _currentVolume = 0; _nextVolume = volume; _smoothChangeTarget = volume; _volumeHoldBlocks = 0; _running = true; + _looped = looped; + } + + virtual bool endOfData() const { + return !_running || (!_looped && Audio::ADPCMStream::endOfData()); } int readBuffer(int16 *buffer, const int numSamples) { @@ -367,7 +372,12 @@ public: assert(numSamples % 2 == 0); - while (_running && samples < numSamples && !_stream->eos() && _stream->pos() < _endpos) { + while (_running && samples < numSamples) { + if (Audio::ADPCMStream::endOfData()) { + if (!_looped) + break; + rewind(); + } if (_blockPos[0] == _blockAlign) { // read block header _status.ima_ch[0].last = _stream->readSint16LE(); @@ -425,7 +435,7 @@ private: uint32 _nextVolume; uint32 _smoothChangeTarget; uint32 _volumeHoldBlocks; // smooth change of volume keeps volume on hold for 4 blocks = 133ms for every value; this is the counter - bool _running; + bool _running, _looped; }; ////////////////////////////////////////////////////////////////////////// @@ -451,8 +461,8 @@ void SimpleSound::loadHeader(Common::SeekableReadStream *in) { _blockSize = _size / _blocks; } -LastExpress_ADPCMStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, uint32 volume) const { - return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize, volume); +LastExpress_ADPCMStream *SimpleSound::makeDecoder(Common::SeekableReadStream *in, uint32 size, uint32 volume, bool looped) const { + return new LastExpress_ADPCMStream(in, DisposeAfterUse::YES, size, _blockSize, volume, looped); } void SimpleSound::play(Audio::AudioStream *as, DisposeAfterUse::Flag autofreeStream) { @@ -460,6 +470,10 @@ void SimpleSound::play(Audio::AudioStream *as, DisposeAfterUse::Flag autofreeStr -1, Audio::Mixer::kMaxChannelVolume, 0, autofreeStream); } +uint32 SimpleSound::getTimeMS() { + return g_system->getMixer()->getSoundElapsedTime(_handle); +} + ////////////////////////////////////////////////////////////////////////// // StreamedSound ////////////////////////////////////////////////////////////////////////// @@ -470,7 +484,7 @@ StreamedSound::~StreamedSound() { _as = NULL; } -bool StreamedSound::load(Common::SeekableReadStream *stream, uint32 volume) { +bool StreamedSound::load(Common::SeekableReadStream *stream, uint32 volume, bool looped) { if (!stream) return false; @@ -483,7 +497,7 @@ bool StreamedSound::load(Common::SeekableReadStream *stream, uint32 volume) { delete _as; } // Start decoding the input stream - _as = makeDecoder(stream, _size, volume); + _as = makeDecoder(stream, _size, volume, looped); // Start playing the decoded audio stream play(_as, DisposeAfterUse::NO); @@ -547,7 +561,7 @@ void AppendableSound::queueBuffer(Common::SeekableReadStream *bufferIn) { // Setup the ADPCM decoder uint32 sizeIn = (uint32)bufferIn->size(); - LastExpress_ADPCMStream *adpcm = makeDecoder(bufferIn, sizeIn, kVolumeFull); + LastExpress_ADPCMStream *adpcm = makeDecoder(bufferIn, sizeIn, kVolumeFull, false); // Queue the stream _as->queueAudioStream(adpcm); diff --git a/engines/lastexpress/data/snd.h b/engines/lastexpress/data/snd.h index f6f2c5ec04..9672167a97 100644 --- a/engines/lastexpress/data/snd.h +++ b/engines/lastexpress/data/snd.h @@ -59,9 +59,11 @@ public: void stop() const; virtual bool isFinished() = 0; + uint32 getTimeMS(); + protected: void loadHeader(Common::SeekableReadStream *in); - LastExpress_ADPCMStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, uint32 volume) const; + LastExpress_ADPCMStream *makeDecoder(Common::SeekableReadStream *in, uint32 size, uint32 volume, bool looped) const; void play(Audio::AudioStream *as, DisposeAfterUse::Flag autofreeStream); uint32 _size; ///< data size @@ -78,7 +80,7 @@ public: StreamedSound(); ~StreamedSound(); - bool load(Common::SeekableReadStream *stream, uint32 volume); + bool load(Common::SeekableReadStream *stream, uint32 volume, bool looped); virtual bool isFinished(); void setVolume(uint32 newVolume); diff --git a/engines/lastexpress/debug.cpp b/engines/lastexpress/debug.cpp index dec57a4c39..72be4df6f3 100644 --- a/engines/lastexpress/debug.cpp +++ b/engines/lastexpress/debug.cpp @@ -540,7 +540,7 @@ bool Debugger::cmdPlaySnd(int argc, const char **argv) { _engine->_system->getMixer()->stopAll(); - _soundStream->load(getArchive(name), 16); + _soundStream->load(getArchive(name), kVolumeFull, false); if (argc == 3) restoreArchive(); diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp index 9f7395bdd3..0eb6077d78 100644 --- a/engines/lastexpress/sound/entry.cpp +++ b/engines/lastexpress/sound/entry.cpp @@ -48,7 +48,6 @@ SoundEntry::SoundEntry(LastExpressEngine *engine) : _engine(engine) { _currentDataPtr = NULL; _blockCount = 0; - _time = 0; _stream = NULL; @@ -124,7 +123,7 @@ void SoundEntry::play() { _stream->seek(0); // Load the stream and start playing - _soundStream->load(_stream, _status & kSoundVolumeMask); + _soundStream->load(_stream, _status & kSoundVolumeMask, (_status & kSoundFlagLooped) != 0); } bool SoundEntry::isFinished() { @@ -369,7 +368,8 @@ void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsUint32LE(_status); s.syncAsUint32LE(_type); s.syncAsUint32LE(_blockCount); // field_8; - s.syncAsUint32LE(_time); + uint32 time = getTime(); + s.syncAsUint32LE(time); s.syncAsUint32LE(_field_34); // field_10; s.syncAsUint32LE(_field_38); // field_14; s.syncAsUint32LE(_entity); diff --git a/engines/lastexpress/sound/entry.h b/engines/lastexpress/sound/entry.h index 938bbaf19a..48e802ed9a 100644 --- a/engines/lastexpress/sound/entry.h +++ b/engines/lastexpress/sound/entry.h @@ -116,7 +116,7 @@ public: uint32 getStatus() { return _status; } SoundType getType() { return _type; } - uint32 getTime() { return _time; } + uint32 getTime() { return _soundStream ? (_soundStream->getTimeMS() * 30 / 1000) : 0; } EntityIndex getEntity() { return _entity; } uint32 getPriority() { return _priority; } Common::String getName2() { return _name2; } @@ -137,7 +137,6 @@ private: byte * _currentDataPtr; //int _currentBufferPtr; int _blockCount; - uint32 _time; //int _size; //int _field_28; Common::SeekableReadStream *_stream; // The file stream -- cgit v1.2.3