diff options
Diffstat (limited to 'engines')
-rw-r--r-- | engines/parallaction/sound.h | 25 | ||||
-rw-r--r-- | engines/parallaction/sound_br.cpp | 87 |
2 files changed, 107 insertions, 5 deletions
diff --git a/engines/parallaction/sound.h b/engines/parallaction/sound.h index 6890c1d2b5..3a66aea049 100644 --- a/engines/parallaction/sound.h +++ b/engines/parallaction/sound.h @@ -187,6 +187,11 @@ protected: Common::String _musicFile; + bool _sfxLooping; + int _sfxVolume; + int _sfxRate; + uint _sfxChannel; + virtual void playMusic() = 0; virtual void stopMusic() = 0; virtual void pause(bool p) = 0; @@ -194,6 +199,9 @@ protected: public: SoundMan_br(Parallaction_br *vm); + virtual void playSfx(const char *filename, uint channel, bool looping, int volume = -1) { } + virtual void stopSfx(uint channel) { } + virtual void execute(int command, const char *parm); void setMusicFile(const char *parm); }; @@ -209,6 +217,9 @@ public: void playMusic(); void stopMusic(); void pause(bool p); + + void playSfx(const char *filename, uint channel, bool looping, int volume); + void stopSfx(uint channel); }; class AmigaSoundMan_br : public SoundMan_br { @@ -216,6 +227,17 @@ class AmigaSoundMan_br : public SoundMan_br { Audio::AudioStream *_musicStream; Audio::SoundHandle _musicHandle; + struct Channel { + Audio::Voice8Header header; + int8 *data; + uint32 dataSize; + bool dispose; + Audio::SoundHandle handle; + uint32 flags; + } _channels[NUM_AMIGA_CHANNELS]; + + void loadChannelData(const char *filename, Channel *ch); + public: AmigaSoundMan_br(Parallaction_br *vm); ~AmigaSoundMan_br(); @@ -223,6 +245,9 @@ public: void playMusic(); void stopMusic(); void pause(bool p); + + void playSfx(const char *filename, uint channel, bool looping, int volume); + void stopSfx(uint channel); }; } // namespace Parallaction diff --git a/engines/parallaction/sound_br.cpp b/engines/parallaction/sound_br.cpp index 40a05d1bdd..4851d11b94 100644 --- a/engines/parallaction/sound_br.cpp +++ b/engines/parallaction/sound_br.cpp @@ -401,6 +401,14 @@ DosSoundMan_br::~DosSoundMan_br() { delete _midiPlayer; } +void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) { + warning("SC_PLAYSFX not yet supported!"); +} + +void DosSoundMan_br::stopSfx(uint channel) { + warning("SC_STOPSFX not yet supported!"); +} + void DosSoundMan_br::playMusic() { if (_musicFile.empty()) { return; @@ -421,9 +429,78 @@ void DosSoundMan_br::pause(bool p) { AmigaSoundMan_br::AmigaSoundMan_br(Parallaction_br *vm) : SoundMan_br(vm) { _musicStream = 0; + _channels[0].data = 0; + _channels[0].dispose = false; + _channels[1].data = 0; + _channels[1].dispose = false; + _channels[2].data = 0; + _channels[2].dispose = false; + _channels[3].data = 0; + _channels[3].dispose = false; } AmigaSoundMan_br::~AmigaSoundMan_br() { + stopMusic(); + stopSfx(0); + stopSfx(1); + stopSfx(2); + stopSfx(3); +} + +void AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch) { + Common::ReadStream *stream = _vm->_disk->loadSound(filename); + Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize); + decoder.decode(); + ch->dispose = true; + delete stream; +} + +void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) { + if (channel >= NUM_AMIGA_CHANNELS) { + warning("unknown sfx channel"); + return; + } + + stopSfx(channel); + + debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel); + + Channel *ch = &_channels[channel]; + loadChannelData(filename, ch); + + uint32 loopStart, loopEnd, flags; + if (looping) { + // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and + // repeatHiSamples fields, but Nippon Safes handles loops according to flags + // set in its location scripts and always operates on the whole data. + loopStart = 0; + loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples; + flags = Audio::Mixer::FLAG_LOOP; + } else { + loopStart = loopEnd = 0; + flags = 0; + } + + if (volume == -1) { + volume = ch->header.volume; + } + + _mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize, + ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd); +} + +void AmigaSoundMan_br::stopSfx(uint channel) { + if (channel >= NUM_AMIGA_CHANNELS) { + warning("unknown sfx channel"); + return; + } + + if (_channels[channel].dispose) { + debugC(1, kDebugAudio, "AmigaSoundMan_ns::stopSfx(%i)", channel); + _mixer->stopHandle(_channels[channel].handle); + free(_channels[channel].data); + _channels[channel].data = 0; + } } void AmigaSoundMan_br::playMusic() { @@ -481,20 +558,20 @@ void SoundMan_br::execute(int command, const char *parm) { break; case SC_PLAYSFX: - warning("SC_PLAYSFX not yet supported!"); + playSfx(parm, _sfxChannel, _sfxLooping, _sfxVolume); break; case SC_STOPSFX: - warning("SC_STOPSFX not yet supported!"); + stopSfx(n); break; case SC_SETSFXCHANNEL: - warning("SC_SETSFXCHANNEL not yet supported!"); + _sfxChannel = n; break; case SC_SETSFXLOOPING: - warning("SC_SETSFXLOOPING not yet supported!"); + _sfxLooping = b; break; case SC_SETSFXVOLUME: - warning("SC_SETSFXVOLUME not yet supported!"); + _sfxVolume = n; break; case SC_PAUSE: |