aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/supernova2/resman.cpp60
-rw-r--r--engines/supernova2/resman.h5
-rw-r--r--engines/supernova2/sound.cpp8
-rw-r--r--engines/supernova2/sound.h1
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: