diff options
author | Paul Gilbert | 2018-12-08 11:37:37 -0800 |
---|---|---|
committer | Paul Gilbert | 2018-12-08 19:05:59 -0800 |
commit | 0cbd51641b0bc1b205f90324399eca6b08a75c32 (patch) | |
tree | dd0a8f90993b7e3eb3332d07a3302d7f7db79cb7 /engines/glk | |
parent | 3661fc61ec319752a767e5981581ded026a57dd1 (diff) | |
download | scummvm-rg350-0cbd51641b0bc1b205f90324399eca6b08a75c32.tar.gz scummvm-rg350-0cbd51641b0bc1b205f90324399eca6b08a75c32.tar.bz2 scummvm-rg350-0cbd51641b0bc1b205f90324399eca6b08a75c32.zip |
GLK: FROTZ: Further sound handling
Diffstat (limited to 'engines/glk')
-rw-r--r-- | engines/glk/events.cpp | 5 | ||||
-rw-r--r-- | engines/glk/frotz/sound_folder.cpp | 2 | ||||
-rw-r--r-- | engines/glk/glk_api.cpp | 41 | ||||
-rw-r--r-- | engines/glk/sound.cpp | 83 | ||||
-rw-r--r-- | engines/glk/sound.h | 34 |
5 files changed, 142 insertions, 23 deletions
diff --git a/engines/glk/events.cpp b/engines/glk/events.cpp index 8f3d5ef190..e6f046ca25 100644 --- a/engines/glk/events.cpp +++ b/engines/glk/events.cpp @@ -25,6 +25,7 @@ #include "glk/glk.h" #include "glk/screen.h" #include "glk/selection.h" +#include "glk/sound.h" #include "glk/windows.h" #include "graphics/cursorman.h" @@ -107,7 +108,9 @@ void Events::checkForNextFrameCounter() { g_vm->_windows->redraw(); _redraw = false; g_vm->_screen->update(); - return; + + // Poll for any finished sounds + g_vm->_sounds->poll(); } } diff --git a/engines/glk/frotz/sound_folder.cpp b/engines/glk/frotz/sound_folder.cpp index 20f22a83b4..91916c4ddc 100644 --- a/engines/glk/frotz/sound_folder.cpp +++ b/engines/glk/frotz/sound_folder.cpp @@ -71,7 +71,7 @@ const Common::ArchiveMemberPtr SoundSubfolder::getMember(const Common::String &n Common::SeekableReadStream *SoundSubfolder::createReadStreamForMember(const Common::String &name) const { Common::File *f = new Common::File(); - if (f->open(_folder.getChild(name))) + if (_filenames.contains(name) && f->open(_folder.getChild(_filenames[name]))) return f; delete f; diff --git a/engines/glk/glk_api.cpp b/engines/glk/glk_api.cpp index 11047893ef..c24d452a50 100644 --- a/engines/glk/glk_api.cpp +++ b/engines/glk/glk_api.cpp @@ -975,7 +975,11 @@ schanid_t GlkAPI::glk_schannel_create(glui32 rock) { } void GlkAPI::glk_schannel_destroy(schanid_t chan) { - delete chan; + if (chan) { + delete chan; + } else { + warning("schannel_dest roy: invalid ref"); + } } schanid_t GlkAPI::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) { @@ -983,21 +987,38 @@ schanid_t GlkAPI::glk_schannel_iterate(schanid_t chan, glui32 *rockptr) { } glui32 GlkAPI::glk_schannel_get_rock(schanid_t chan) { - return chan->_rock; + if (chan) { + return chan->_rock; + } else { + warning("schannel_get_rock: invalid ref"); + return 0; + } } glui32 GlkAPI::glk_schannel_play(schanid_t chan, glui32 snd) { - // TODO - return 0; + if (chan) { + return chan->play(snd); + } else { + warning("schannel_play_ext: invalid ref"); + return 0; + } } glui32 GlkAPI::glk_schannel_play_ext(schanid_t chan, glui32 snd, glui32 repeats, glui32 notify) { - // TODO - return 0; + if (chan) { + chan->play(snd, repeats, notify); + } else { + warning("schannel_play_ext: invalid ref"); + return 0; + } } void GlkAPI::glk_schannel_stop(schanid_t chan) { - // TODO + if (chan) { + chan->stop(); + } else { + warning("schannel_stop: invalid ref"); + } } void GlkAPI::glk_schannel_set_volume(schanid_t chan, glui32 vol) { @@ -1005,17 +1026,17 @@ void GlkAPI::glk_schannel_set_volume(schanid_t chan, glui32 vol) { } void GlkAPI::glk_sound_load_hint(glui32 snd, glui32 flag) { - // TODO + // No implementation } schanid_t GlkAPI::glk_schannel_create_ext(glui32 rock, glui32 volume) { - // TODO + // No implementation return nullptr; } glui32 GlkAPI::glk_schannel_play_multi(schanid_t *chanarray, glui32 chancount, glui32 *sndarray, glui32 soundcount, glui32 notify) { - // TODO + // No implementation return 0; } 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 diff --git a/engines/glk/sound.h b/engines/glk/sound.h index 05875eaa32..514a5f6ad2 100644 --- a/engines/glk/sound.h +++ b/engines/glk/sound.h @@ -25,6 +25,7 @@ #include "glk/glk_types.h" #include "audio/audiostream.h" +#include "audio/mixer.h" #include "common/array.h" namespace Glk { @@ -34,15 +35,19 @@ class Sounds; /** * Holds the data for a playing sound */ -struct SoundChannel { +class SoundChannel { +private: Sounds *_owner; - Audio::AudioStream *_stream; + glui32 _soundNum; + glui32 _notify; + Audio::SoundHandle _handle; +public: glui32 _rock; - +public: /** - * Destructor + * Constructor */ - SoundChannel() : _stream(nullptr), _rock(0) {} + SoundChannel(Sounds *owner); /** * Destructor @@ -52,7 +57,17 @@ struct SoundChannel { /** * Play a sound */ - void play(uint soundNum); + glui32 play(glui32 soundNum, glui32 repeats = 1, glui32 notify = 0); + + /** + * Stop playing sound + */ + void stop(); + + /** + * Poll for whether a playing sound was finished + */ + void poll(); }; typedef SoundChannel *schanid_t; @@ -60,7 +75,7 @@ typedef SoundChannel *schanid_t; * Sound manager */ class Sounds { - friend struct SoundChannel; + friend class SoundChannel; private: Common::Array<schanid_t> _sounds; private: @@ -80,6 +95,11 @@ public: * Used to iterate over the current list of sound channels */ schanid_t iterate(schanid_t chan, glui32 *rockptr = nullptr); + + /** + * Poll for whether any playing sounds are finished + */ + void poll(); }; } // End of namespace Glk |