Add sound effects support for PC version of BRA.

svn-id: r39716
This commit is contained in:
Travis Howell 2009-03-28 09:56:39 +00:00
parent 9131f20587
commit 4979179621
5 changed files with 91 additions and 67 deletions

View file

@ -404,7 +404,7 @@ Common::SeekableReadStream* DosDisk_br::loadMusic(const char* name) {
Common::SeekableReadStream* DosDisk_br::loadSound(const char* name) { Common::SeekableReadStream* DosDisk_br::loadSound(const char* name) {
debugC(5, kDebugDisk, "DosDisk_br::loadSound"); debugC(5, kDebugDisk, "DosDisk_br::loadSound");
return 0; return openFile("sfx/" + Common::String(name), ".sfx");
} }
@ -720,7 +720,7 @@ Common::SeekableReadStream* AmigaDisk_br::loadMusic(const char* name) {
Common::SeekableReadStream* AmigaDisk_br::loadSound(const char* name) { Common::SeekableReadStream* AmigaDisk_br::loadSound(const char* name) {
debugC(5, kDebugDisk, "AmigaDisk_br::loadSound"); debugC(5, kDebugDisk, "AmigaDisk_br::loadSound");
return tryOpenFile("sfx/" + Common::String(name), ".sfx"); return openFile("sfx/" + Common::String(name), ".sfx");
} }
static const uint16 objectsMax[5] = { static const uint16 objectsMax[5] = {

View file

@ -960,10 +960,12 @@ bool CharacterName::dummy() const {
} }
void Parallaction::beep() { void Parallaction::beep() {
_soundMan->execute(SC_SETSFXCHANNEL, 3); if (getGameType() == GType_Nippon) {
_soundMan->execute(SC_SETSFXVOLUME, 127); _soundMan->execute(SC_SETSFXCHANNEL, 3);
_soundMan->execute(SC_SETSFXLOOPING, (int32)0); _soundMan->execute(SC_SETSFXVOLUME, 127);
_soundMan->execute(SC_PLAYSFX, "beep"); _soundMan->execute(SC_SETSFXLOOPING, (int32)0);
_soundMan->execute(SC_PLAYSFX, "beep");
}
} }
void Parallaction::scheduleLocationSwitch(const char *location) { void Parallaction::scheduleLocationSwitch(const char *location) {

View file

@ -141,7 +141,7 @@ public:
void pause(bool p); void pause(bool p);
}; };
#define NUM_AMIGA_CHANNELS 4 #define NUM_SFX_CHANNELS 4
class AmigaSoundMan_ns : public SoundMan_ns { class AmigaSoundMan_ns : public SoundMan_ns {
@ -155,7 +155,7 @@ class AmigaSoundMan_ns : public SoundMan_ns {
bool dispose; bool dispose;
Audio::SoundHandle handle; Audio::SoundHandle handle;
uint32 flags; uint32 flags;
} _channels[NUM_AMIGA_CHANNELS]; } _channels[NUM_SFX_CHANNELS];
void loadChannelData(const char *filename, Channel *ch); void loadChannelData(const char *filename, Channel *ch);
@ -193,11 +193,23 @@ protected:
virtual void stopMusic() = 0; virtual void stopMusic() = 0;
virtual void pause(bool p) = 0; virtual void pause(bool p) = 0;
struct Channel {
Audio::Voice8Header header;
int8 *data;
uint32 dataSize;
bool dispose;
Audio::SoundHandle handle;
uint32 flags;
} _channels[NUM_SFX_CHANNELS];
virtual void loadChannelData(const char *filename, Channel *ch) = 0;
public: public:
SoundMan_br(Parallaction_br *vm); SoundMan_br(Parallaction_br *vm);
~SoundMan_br();
virtual void playSfx(const char *filename, uint channel, bool looping, int volume = -1) { } virtual void playSfx(const char *filename, uint channel, bool looping, int volume = -1) { }
virtual void stopSfx(uint channel) { } void stopSfx(uint channel);
virtual void execute(int command, const char *parm); virtual void execute(int command, const char *parm);
void setMusicFile(const char *parm); void setMusicFile(const char *parm);
@ -207,6 +219,8 @@ class DosSoundMan_br : public SoundMan_br {
MidiPlayer_MSC *_midiPlayer; MidiPlayer_MSC *_midiPlayer;
void loadChannelData(const char *filename, Channel *ch);
public: public:
DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver); DosSoundMan_br(Parallaction_br *vm, MidiDriver *midiDriver);
~DosSoundMan_br(); ~DosSoundMan_br();
@ -216,7 +230,6 @@ public:
void pause(bool p); void pause(bool p);
void playSfx(const char *filename, uint channel, bool looping, int volume); void playSfx(const char *filename, uint channel, bool looping, int volume);
void stopSfx(uint channel);
}; };
class AmigaSoundMan_br : public SoundMan_br { class AmigaSoundMan_br : public SoundMan_br {
@ -224,16 +237,7 @@ class AmigaSoundMan_br : public SoundMan_br {
Audio::AudioStream *_musicStream; Audio::AudioStream *_musicStream;
Audio::SoundHandle _musicHandle; Audio::SoundHandle _musicHandle;
struct Channel { void loadChannelData(const char *filename, Channel *ch);
Audio::Voice8Header header;
int8 *data;
uint32 dataSize;
bool dispose;
Audio::SoundHandle handle;
uint32 flags;
} _channels[NUM_AMIGA_CHANNELS];
bool loadChannelData(const char *filename, Channel *ch);
public: public:
AmigaSoundMan_br(Parallaction_br *vm); AmigaSoundMan_br(Parallaction_br *vm);
@ -244,7 +248,6 @@ public:
void pause(bool p); void pause(bool p);
void playSfx(const char *filename, uint channel, bool looping, int volume); void playSfx(const char *filename, uint channel, bool looping, int volume);
void stopSfx(uint channel);
}; };
} // namespace Parallaction } // namespace Parallaction

View file

@ -401,12 +401,37 @@ DosSoundMan_br::~DosSoundMan_br() {
delete _midiPlayer; delete _midiPlayer;
} }
void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) { void DosSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
warning("SC_PLAYSFX not yet supported!"); Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
ch->dataSize = stream->size();
ch->data = (int8*)malloc(ch->dataSize);
if (stream->read(ch->data, ch->dataSize) != ch->dataSize)
error("DosSoundMan_br::loadChannelData: Read failed");
ch->dispose = true;
delete stream;
// TODO: Confirm sound rate
ch->header.samplesPerSec = 11025;
} }
void DosSoundMan_br::stopSfx(uint channel) { void DosSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) {
warning("SC_STOPSFX not yet supported!"); stopSfx(channel);
debugC(1, kDebugAudio, "DosSoundMan_br::playSfx(%s, %u, %i, %i)", filename, channel, looping, volume);
Channel *ch = &_channels[channel];
loadChannelData(filename, ch);
uint32 loopStart = 0, loopEnd = 0, flags = Audio::Mixer::FLAG_UNSIGNED;
if (looping) {
loopEnd = ch->dataSize;
flags |= Audio::Mixer::FLAG_LOOP;
}
_mixer->playRaw(Audio::Mixer::kSFXSoundType, &ch->handle, ch->data, ch->dataSize,
ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd);
} }
void DosSoundMan_br::playMusic() { void DosSoundMan_br::playMusic() {
@ -429,40 +454,22 @@ void DosSoundMan_br::pause(bool p) {
AmigaSoundMan_br::AmigaSoundMan_br(Parallaction_br *vm) : SoundMan_br(vm) { AmigaSoundMan_br::AmigaSoundMan_br(Parallaction_br *vm) : SoundMan_br(vm) {
_musicStream = 0; _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() { AmigaSoundMan_br::~AmigaSoundMan_br() {
stopMusic(); stopMusic();
stopSfx(0);
stopSfx(1);
stopSfx(2);
stopSfx(3);
} }
bool AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch) { void AmigaSoundMan_br::loadChannelData(const char *filename, Channel *ch) {
Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename); Common::SeekableReadStream *stream = _vm->_disk->loadSound(filename);
// NOTE: Sound files don't always exist
if (!stream)
return false;
Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize); Audio::A8SVXDecoder decoder(*stream, ch->header, ch->data, ch->dataSize);
decoder.decode(); decoder.decode();
ch->dispose = true; ch->dispose = true;
delete stream; delete stream;
return true;
} }
void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) { void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping, int volume) {
if (channel >= NUM_AMIGA_CHANNELS) { if (channel >= NUM_SFX_CHANNELS) {
warning("unknown sfx channel"); warning("unknown sfx channel");
return; return;
} }
@ -472,10 +479,9 @@ void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping,
debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel); debugC(1, kDebugAudio, "AmigaSoundMan_ns::playSfx(%s, %i)", filename, channel);
Channel *ch = &_channels[channel]; Channel *ch = &_channels[channel];
if (!loadChannelData(filename, ch)) loadChannelData(filename, ch);
return;
uint32 loopStart, loopEnd, flags; uint32 loopStart = 0, loopEnd = 0, flags = 0;
if (looping) { if (looping) {
// the standard way to loop 8SVX audio implies use of the oneShotHiSamples and // the standard way to loop 8SVX audio implies use of the oneShotHiSamples and
// repeatHiSamples fields, but Nippon Safes handles loops according to flags // repeatHiSamples fields, but Nippon Safes handles loops according to flags
@ -483,9 +489,6 @@ void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping,
loopStart = 0; loopStart = 0;
loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples; loopEnd = ch->header.oneShotHiSamples + ch->header.repeatHiSamples;
flags = Audio::Mixer::FLAG_LOOP; flags = Audio::Mixer::FLAG_LOOP;
} else {
loopStart = loopEnd = 0;
flags = 0;
} }
if (volume == -1) { if (volume == -1) {
@ -496,20 +499,6 @@ void AmigaSoundMan_br::playSfx(const char *filename, uint channel, bool looping,
ch->header.samplesPerSec, flags, -1, volume, 0, loopStart, loopEnd); 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() { void AmigaSoundMan_br::playMusic() {
stopMusic(); stopMusic();
@ -544,12 +533,42 @@ void AmigaSoundMan_br::pause(bool p) {
SoundMan_br::SoundMan_br(Parallaction_br *vm) : _vm(vm) { SoundMan_br::SoundMan_br(Parallaction_br *vm) : _vm(vm) {
_mixer = _vm->_mixer; _mixer = _vm->_mixer;
_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;
}
SoundMan_br::~SoundMan_br() {
stopSfx(0);
stopSfx(1);
stopSfx(2);
stopSfx(3);
} }
void SoundMan_br::setMusicFile(const char *name) { void SoundMan_br::setMusicFile(const char *name) {
_musicFile = name; _musicFile = name;
} }
void SoundMan_br::stopSfx(uint channel) {
if (channel >= NUM_SFX_CHANNELS) {
warning("unknown sfx channel");
return;
}
if (_channels[channel].dispose) {
debugC(1, kDebugAudio, "SoundMan_br::stopSfx(%i)", channel);
_mixer->stopHandle(_channels[channel].handle);
free(_channels[channel].data);
_channels[channel].data = 0;
}
}
void SoundMan_br::execute(int command, const char *parm) { void SoundMan_br::execute(int command, const char *parm) {
uint32 n = parm ? strtoul(parm, 0, 10) : 0; uint32 n = parm ? strtoul(parm, 0, 10) : 0;
bool b = (n == 1) ? true : false; bool b = (n == 1) ? true : false;

View file

@ -387,7 +387,7 @@ void AmigaSoundMan_ns::loadChannelData(const char *filename, Channel *ch) {
} }
void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping, int volume) { void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping, int volume) {
if (channel >= NUM_AMIGA_CHANNELS) { if (channel >= NUM_SFX_CHANNELS) {
warning("unknown sfx channel"); warning("unknown sfx channel");
return; return;
} }
@ -421,7 +421,7 @@ void AmigaSoundMan_ns::playSfx(const char *filename, uint channel, bool looping,
} }
void AmigaSoundMan_ns::stopSfx(uint channel) { void AmigaSoundMan_ns::stopSfx(uint channel) {
if (channel >= NUM_AMIGA_CHANNELS) { if (channel >= NUM_SFX_CHANNELS) {
warning("unknown sfx channel"); warning("unknown sfx channel");
return; return;
} }