From 1162a759c03d266e2908bf669e289a511911ff77 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 25 May 2006 09:53:51 +0000 Subject: Added support for fading digital music in or out. svn-id: r22624 --- engines/kyra/kyra3.cpp | 2 +- engines/kyra/sound.h | 6 ++- engines/kyra/sound_digital.cpp | 83 +++++++++++++++++++++++++++++++++++------- 3 files changed, 76 insertions(+), 15 deletions(-) (limited to 'engines/kyra') diff --git a/engines/kyra/kyra3.cpp b/engines/kyra/kyra3.cpp index 8814e19cf7..1b7e4a5b2c 100644 --- a/engines/kyra/kyra3.cpp +++ b/engines/kyra/kyra3.cpp @@ -183,7 +183,7 @@ void KyraEngine_v3::playMenuAudioFile() { uint32 temp = 0; _res->fileHandle(_menuAudioFile, &temp, *handle); if (handle->isOpen()) { - _musicSoundChannel = _soundDigital->playSound(handle, true, -1); + _musicSoundChannel = _soundDigital->playSound(handle, true); } } diff --git a/engines/kyra/sound.h b/engines/kyra/sound.h index ea8501cc62..e43239efc1 100644 --- a/engines/kyra/sound.h +++ b/engines/kyra/sound.h @@ -39,6 +39,8 @@ class SoundHandle; namespace Kyra { +class AUDStream; + class Sound { public: Sound(KyraEngine *engine, Audio::Mixer *mixer); @@ -221,9 +223,10 @@ public: bool init(); - int playSound(Common::File *fileHandle, bool loop = false, int channel = -1); + int playSound(Common::File *fileHandle, bool loop = false, bool fadeIn = false, int channel = -1); bool isPlaying(int channel); void stopSound(int channel); + void beginFadeOut(int channel); private: KyraEngine *_vm; Audio::Mixer *_mixer; @@ -231,6 +234,7 @@ private: struct Sound { Common::File *fileHandle; Audio::SoundHandle handle; + AUDStream *stream; } _sounds[SOUND_STREAMS]; }; diff --git a/engines/kyra/sound_digital.cpp b/engines/kyra/sound_digital.cpp index 1db2e45d86..90e4f0b0da 100644 --- a/engines/kyra/sound_digital.cpp +++ b/engines/kyra/sound_digital.cpp @@ -42,6 +42,9 @@ public: bool endOfData() const { return _endOfData; } int getRate() const { return _rate; } + + void beginFadeIn(); + void beginFadeOut(); private: Common::File *_file; bool _loop; @@ -53,12 +56,16 @@ private: int _bytesLeft; - uint8 *_outBuffer; + byte *_outBuffer; int _outBufferOffset; uint _outBufferSize; - uint8 *_inBuffer; + byte *_inBuffer; uint _inBufferSize; + + int32 _fadeSamples; + int32 _fadeCount; + int _fading; int readChunk(int16 *buffer, const int maxSamples); @@ -90,6 +97,13 @@ AUDStream::AUDStream(Common::File *file, bool loop) : _file(0), _endOfData(true) _rate = _file->readUint16LE(); _totalSize = _file->readUint32LE(); _loop = loop; + + // TODO: Find the correct number of samples for a fade-in/out. Should + // probably take the same amount of time as a palette fade. + + _fadeSamples = 2 * getRate(); + _fading = 0; + // TODO?: add checks int flags = _file->readByte(); // flags int type = _file->readByte(); // type @@ -113,6 +127,18 @@ AUDStream::~AUDStream() { #endif } +void AUDStream::beginFadeIn() { + if (_fading == 0) + _fadeCount = 0; + _fading = 1; +} + +void AUDStream::beginFadeOut() { + if (_fading == 0) + _fadeCount = _fadeSamples; + _fading = -1; +} + int AUDStream::readBuffer(int16 *buffer, const int numSamples) { int samplesRead = 0, samplesLeft = numSamples; @@ -273,12 +299,34 @@ int AUDStream::readChunk(int16 *buffer, const int maxSamples) { samplesProcessed += samples; _bytesLeft -= samples; + // To help avoid overflows for long fade times, we divide both + // _fadeSamples and _fadeCount when calculating the new sample. + + int32 div = _fadeSamples / 256; + while (samples--) { - int16 sample = (int8)_outBuffer[_outBufferOffset++]; - *buffer++ = (sample << 8) ^ 0x8000; + int16 sample = (_outBuffer[_outBufferOffset++] << 8) ^ 0x8000; + + if (_fading) { + sample = (sample * (_fadeCount / 256)) / div; + _fadeCount += _fading; + + if (_fadeCount < 0) { + _fadeCount = 0; + _endOfData = true; + } else if (_fadeCount > _fadeSamples) { + _fadeCount = _fadeSamples; + _fading = 0; + } + } + + *buffer++ = sample; } } + if (_fading < 0 && _fadeCount == 0) + _fading = false; + return samplesProcessed; } @@ -298,15 +346,15 @@ bool SoundDigital::init() { return true; } -int SoundDigital::playSound(Common::File *fileHandle, bool loop, int channel) { +int SoundDigital::playSound(Common::File *fileHandle, bool loop, bool fadeIn, int channel) { Sound *use = 0; if (channel != -1 && channel < SOUND_STREAMS) { stopSound(channel); use = &_sounds[channel]; } else { - for (int i = 0; i < SOUND_STREAMS; ++i) { - if (!_sounds[i].fileHandle) { - use = &_sounds[i]; + for (channel = 0; channel < SOUND_STREAMS; ++channel) { + if (!_sounds[channel].fileHandle) { + use = &_sounds[channel]; break; } } @@ -317,16 +365,19 @@ int SoundDigital::playSound(Common::File *fileHandle, bool loop, int channel) { } } - Audio::AudioStream *stream = new AUDStream(fileHandle, loop); - if (stream->endOfData()) { - delete stream; + use->stream = new AUDStream(fileHandle, loop); + if (use->stream->endOfData()) { + delete use->stream; delete fileHandle; return -1; } + + if (fadeIn) + use->stream->beginFadeIn(); // TODO: set correct sound type from channel id - _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &use->handle, stream); + _mixer->playInputStream(Audio::Mixer::kPlainSoundType, &use->handle, use->stream); use->fileHandle = fileHandle; return use - _sounds; @@ -348,7 +399,13 @@ void SoundDigital::stopSound(int channel) { if (_sounds[channel].fileHandle) { delete _sounds[channel].fileHandle; - _sounds[channel].fileHandle = 0; + _sounds[channel].fileHandle = 0; + } +} + +void SoundDigital::beginFadeOut(int channel) { + if (isPlaying(channel)) { + _sounds[channel].stream->beginFadeOut(); } } -- cgit v1.2.3