diff options
-rw-r--r-- | engines/supernova2/resman.cpp | 60 | ||||
-rw-r--r-- | engines/supernova2/resman.h | 5 | ||||
-rw-r--r-- | engines/supernova2/sound.cpp | 8 | ||||
-rw-r--r-- | engines/supernova2/sound.h | 1 |
4 files changed, 74 insertions, 0 deletions
diff --git a/engines/supernova2/resman.cpp b/engines/supernova2/resman.cpp index 05ad7bdc12..42f6f62949 100644 --- a/engines/supernova2/resman.cpp +++ b/engines/supernova2/resman.cpp @@ -28,6 +28,7 @@ #include "common/system.h" #include "graphics/cursorman.h" #include "graphics/palette.h" +#include "common/sinetables.h" #include "supernova2/graphics.h" #include "supernova2/resman.h" @@ -128,6 +129,7 @@ void ResourceManager::initSoundFiles() { _soundSamples[i].reset(Audio::makeRawStream(buffer, length, _audioRate, streamFlag, DisposeAfterUse::YES)); } + initSiren(); _musicIntroBuffer.reset(convertToMod("ms2_data.052")); _musicMadMonkeysBuffer.reset(convertToMod("ms2_data.056")); @@ -191,6 +193,10 @@ Audio::AudioStream *ResourceManager::getSoundStream(MusicId index) { } } +Audio::AudioStream *ResourceManager::getSirenStream() { + return _sirenStream.get(); +} + MS2Image *ResourceManager::getImage(int filenumber) { if (filenumber < 47) return &_images[filenumber]; @@ -198,6 +204,10 @@ MS2Image *ResourceManager::getImage(int filenumber) { return nullptr; } +int ResourceManager::getAudioRate() { + return _audioRate; +} + const byte *ResourceManager::getCursor(CursorId id) const { switch (id) { case kCursorNormal: @@ -209,6 +219,56 @@ const byte *ResourceManager::getCursor(CursorId id) const { } } +// Generate a tone which minimal length is the length and ends at the end +// of sine period +byte *ResourceManager::generateTone(byte *buffer, int frequency, int length, int audioRate) { + Common::SineTable table = Common::SineTable(40000); + int numberOfSamplesPerT = audioRate / frequency; + int i = 0; + + // Generate minimal length of the tone + for(; i < length; i++) { + buffer[i] = (byte) + ((table.at((i * (40000 / numberOfSamplesPerT)) % 40000) * 127) + 127); + } + + // Generate the tone until the end of a sine period and try to make + // the transition to the next tone a little bit smoother + for(; buffer[i - 1] > 127; i++) + buffer[i] = (byte) + ((table.at((i * (40000 / numberOfSamplesPerT)) % 40000) * 127) + 127); + for(; buffer[i - 1] < 127; i++) + buffer[i] = (byte) + ((table.at((i * (40000 / numberOfSamplesPerT)) % 40000) * 127) + 127); + if (buffer[i - 1] == 127) + i++; + buffer[i - 2] = (1.2 * 127 + 0.8 * buffer[i - 3]) / 2; + return buffer + i - 1; +} + +// Tones with frequencies between 1500 Hz and 1800 Hz, frequencies go up and down +// with a step of 10 Hz. +void ResourceManager::initSiren() { + int audioRate = 80000; + int length = audioRate / 90; // minimal length of each tone + + // * 60 for the minimal length, another 20 * length as a spare, for longer tones + byte *buffer = new byte[length * 80]; + byte *pBuffer = buffer; + + for (int i = 0; i < 30; i++) + pBuffer = generateTone(pBuffer, 1770 - i * 10, length, audioRate); + + for (int i = 0; i < 30; i++) + pBuffer = generateTone(pBuffer, 1530 + i * 10, length, audioRate); + + byte streamFlag = Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN; + + _sirenStream.reset(Audio::makeLoopingAudioStream( + Audio::makeRawStream(buffer, pBuffer - buffer, audioRate, + streamFlag, DisposeAfterUse::YES), 0)); +} + static Common::MemoryReadStream *convertToMod(const char *filename, int version) { // MS2 format struct { diff --git a/engines/supernova2/resman.h b/engines/supernova2/resman.h index edcd294e77..8d06c60448 100644 --- a/engines/supernova2/resman.h +++ b/engines/supernova2/resman.h @@ -51,14 +51,18 @@ public: Audio::SeekableAudioStream *getSoundStream(AudioId index); Audio::AudioStream *getSoundStream(MusicId index); + Audio::AudioStream *getSirenStream(); MS2Image *getImage(int filenumber); const byte *getCursor(CursorId id) const; + int getAudioRate(); private: void initSoundFiles(); void initGraphics(); void initCursorGraphics(); void initImages(); + void initSiren(); + byte *generateTone(byte *buffer, int frequency, int length, int audioRate); private: Common::ScopedPtr<Audio::SeekableAudioStream> _soundSamples[kAudioNumSamples]; @@ -66,6 +70,7 @@ private: Common::ScopedPtr<Common::MemoryReadStream> _musicMadMonkeysBuffer; Common::ScopedPtr<Common::MemoryReadStream> _musicOutroBuffer; Common::ScopedPtr<Audio::AudioStream> _musicIntro; + Common::ScopedPtr<Audio::AudioStream> _sirenStream; Common::ScopedPtr<Audio::AudioStream> _musicMadMonkeys; Common::ScopedPtr<Audio::AudioStream> _musicOutro; int _audioRate; diff --git a/engines/supernova2/sound.cpp b/engines/supernova2/sound.cpp index f08158a879..c0688acd45 100644 --- a/engines/supernova2/sound.cpp +++ b/engines/supernova2/sound.cpp @@ -53,6 +53,14 @@ void Sound::play(MusicId index) { -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); } +void Sound::playSiren() { + Audio::AudioStream *stream = _resMan->getSirenStream(); + + stop(); + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, stream, + -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO); +} + bool Sound::isPlaying() { return _mixer->isSoundHandleActive(_soundHandle); } diff --git a/engines/supernova2/sound.h b/engines/supernova2/sound.h index d54bac9cf0..ac65b19d0b 100644 --- a/engines/supernova2/sound.h +++ b/engines/supernova2/sound.h @@ -66,6 +66,7 @@ public: void play(AudioId index); void play(MusicId index); + void playSiren(); void stop(); bool isPlaying(); private: |