aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/sound.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/sound.cpp')
-rw-r--r--engines/glk/sound.cpp83
1 files changed, 79 insertions, 4 deletions
diff --git a/engines/glk/sound.cpp b/engines/glk/sound.cpp
index 5c98b93e09..85f7e01702 100644
--- a/engines/glk/sound.cpp
+++ b/engines/glk/sound.cpp
@@ -21,6 +21,13 @@
*/
#include "glk/sound.h"
+#include "glk/glk.h"
+#include "glk/events.h"
+#include "common/file.h"
+#include "audio/audiostream.h"
+#include "audio/decoders/raw.h"
+#include "audio/decoders/mp3.h"
+#include "audio/decoders/wave.h"
namespace Glk {
@@ -39,7 +46,7 @@ void Sounds::removeSound(schanid_t snd) {
}
schanid_t Sounds::create(glui32 rock) {
- schanid_t snd = new SoundChannel();
+ schanid_t snd = new SoundChannel(this);
_sounds.push_back(snd);
return snd;
}
@@ -58,15 +65,83 @@ schanid_t Sounds::iterate(schanid_t chan, glui32 *rockptr) {
return nullptr;
}
+void Sounds::poll() {
+ for (uint idx = 0; idx < _sounds.size(); ++idx)
+ _sounds[idx]->poll();
+}
+
/*--------------------------------------------------------------------------*/
+SoundChannel::SoundChannel(Sounds *owner) : _owner(owner), _soundNum(0),
+ _rock(0), _notify(0) {
+}
+
SoundChannel::~SoundChannel() {
+ stop();
_owner->removeSound(this);
- delete _stream;
}
-void SoundChannel::play(uint soundNum) {
- // TODO
+glui32 SoundChannel::play(glui32 soundNum, glui32 repeats, glui32 notify) {
+ stop();
+ if (repeats == 0)
+ return 1;
+
+ // Find a sound of the given name
+ Audio::AudioStream *stream;
+ Common::File f;
+ Common::String nameSnd = Common::String::format("sound%u.snd", soundNum);
+ Common::String nameMp3 = Common::String::format("sound%u.mp3", soundNum);
+ Common::String nameWav = Common::String::format("sound%u.wav", soundNum);
+
+ if (f.exists(nameSnd) && f.open(nameSnd)) {
+ if (f.readUint16BE() != (f.size() - 2))
+ error("Invalid sound filesize");
+ repeats = f.readByte();
+ f.skip(1);
+ uint freq = f.readUint16BE();
+ f.skip(2);
+ uint size = f.readUint16BE();
+
+ Common::SeekableReadStream *s = f.readStream(size);
+ stream = Audio::makeRawStream(s, freq, Audio::FLAG_UNSIGNED);
+
+ } else if (f.exists(nameMp3) && f.open(nameMp3)) {
+ Common::SeekableReadStream *s = f.readStream(f.size());
+ stream = Audio::makeMP3Stream(s, DisposeAfterUse::YES);
+
+ } else if (f.exists(nameWav) && f.open(nameWav)) {
+ Common::SeekableReadStream *s = f.readStream(f.size());
+ stream = Audio::makeWAVStream(s, DisposeAfterUse::YES);
+
+ } else {
+ warning("Could not find sound %u", soundNum);
+ return 1;
+ }
+
+ _soundNum = soundNum;
+ _notify = notify;
+
+ // Set up a repeat if multiple repeats are specified
+ if (repeats > 1) {
+ Audio::RewindableAudioStream *rwStream = dynamic_cast<Audio::RewindableAudioStream *>(stream);
+ assert(rwStream);
+ stream = new Audio::LoopingAudioStream(rwStream, repeats, DisposeAfterUse::YES);
+ }
+
+ // Start playing the audio
+ g_vm->_mixer->playStream(Audio::Mixer::kPlainSoundType, &_handle, stream);
+ return 0;
+}
+
+void SoundChannel::stop() {
+ g_vm->_mixer->stopHandle(_handle);
+}
+
+void SoundChannel::poll() {
+ if (!g_vm->_mixer->isSoundHandleActive(_handle) && _notify != 0)
+ g_vm->_events->store(evtype_SoundNotify, 0,
+ _soundNum, _notify);
+
}
} // End of namespace Glk