Skip to content

Commit

Permalink
KYRA: implement LOL sfx priority handling
Browse files Browse the repository at this point in the history
  • Loading branch information
athrxx committed Nov 11, 2012
1 parent 8789087 commit e016e7d
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 22 deletions.
29 changes: 19 additions & 10 deletions engines/kyra/sound.cpp
Expand Up @@ -73,15 +73,15 @@ bool Sound::isVoicePresent(const char *file) const {
return false;
}

int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) {
int32 Sound::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) {
Audio::SeekableAudioStream *audioStream = getVoiceStream(file);

if (!audioStream) {
return 0;
}

int playTime = audioStream->getLength().msecs();
playVoiceStream(audioStream, handle, volume, isSfx);
playVoiceStream(audioStream, handle, volume, priority, isSfx);
return playTime;
}

Expand Down Expand Up @@ -109,11 +109,19 @@ Audio::SeekableAudioStream *Sound::getVoiceStream(const char *file) const {
}
}

bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle, uint8 volume, bool isSfx) {
bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool isSfx) {
int h = 0;
while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h]))
while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h].handle))
++h;

if (h >= kNumChannelHandles) {
h = 0;
while (h < kNumChannelHandles && _soundChannels[h].priority > priority)
++h;
if (h < kNumChannelHandles)
voiceStop(&_soundChannels[h].handle);
}

if (h >= kNumChannelHandles) {
// When we run out of handles we need to destroy the stream object,
// this is to avoid memory leaks in some scenes where too many sfx
Expand All @@ -123,18 +131,19 @@ bool Sound::playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *hand
return false;
}

_mixer->playStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h], stream, -1, volume);
_mixer->playStream(isSfx ? Audio::Mixer::kSFXSoundType : Audio::Mixer::kSpeechSoundType, &_soundChannels[h].handle, stream, -1, volume);
_soundChannels[h].priority = priority;
if (handle)
*handle = _soundChannels[h];
*handle = _soundChannels[h].handle;

return true;
}

void Sound::voiceStop(const Audio::SoundHandle *handle) {
if (!handle) {
for (int h = 0; h < kNumChannelHandles; ++h) {
if (_mixer->isSoundHandleActive(_soundChannels[h]))
_mixer->stopHandle(_soundChannels[h]);
if (_mixer->isSoundHandleActive(_soundChannels[h].handle))
_mixer->stopHandle(_soundChannels[h].handle);
}
} else {
_mixer->stopHandle(*handle);
Expand All @@ -144,7 +153,7 @@ void Sound::voiceStop(const Audio::SoundHandle *handle) {
bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) const {
if (!handle) {
for (int h = 0; h < kNumChannelHandles; ++h) {
if (_mixer->isSoundHandleActive(_soundChannels[h]))
if (_mixer->isSoundHandleActive(_soundChannels[h].handle))
return true;
}
} else {
Expand All @@ -156,7 +165,7 @@ bool Sound::voiceIsPlaying(const Audio::SoundHandle *handle) const {

bool Sound::allVoiceChannelsPlaying() const {
for (int i = 0; i < kNumChannelHandles; ++i)
if (!_mixer->isSoundHandleActive(_soundChannels[i]))
if (!_mixer->isSoundHandleActive(_soundChannels[i].handle))
return false;
return true;
}
Expand Down
12 changes: 9 additions & 3 deletions engines/kyra/sound.h
Expand Up @@ -184,11 +184,11 @@ class Sound {
* @param handle store a copy of the sound handle
* @return playtime of the voice file (-1 marks unknown playtime)
*/
virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false);
virtual int32 voicePlay(const char *file, Audio::SoundHandle *handle = 0, uint8 volume = 255, uint8 priority = 255, bool isSfx = false);

Audio::SeekableAudioStream *getVoiceStream(const char *file) const;

bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, bool isSfx = false);
bool playVoiceStream(Audio::AudioStream *stream, Audio::SoundHandle *handle = 0, uint8 volume = 255, uint8 priority = 255, bool isSfx = false);

/**
* Checks if a voice is being played.
Expand Down Expand Up @@ -238,7 +238,13 @@ class Sound {
kNumChannelHandles = 4
};

Audio::SoundHandle _soundChannels[kNumChannelHandles];
struct SoundChannel {
SoundChannel() : handle(), priority(0) {}
Audio::SoundHandle handle;
int priority;
};

SoundChannel _soundChannels[kNumChannelHandles];

int _musicEnabled;
bool _sfxEnabled;
Expand Down
2 changes: 1 addition & 1 deletion engines/kyra/sound_intern.h
Expand Up @@ -193,7 +193,7 @@ class SoundTownsPC98_v2 : public Sound {
void haltTrack();
void beginFadeOut();

int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx);
int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume = 255, uint8 priority = 255, bool isSfx = true);
void playSoundEffect(uint8 track, uint8 volume = 0xff);

void updateVolumeSettings();
Expand Down
7 changes: 3 additions & 4 deletions engines/kyra/sound_lol.cpp
Expand Up @@ -165,9 +165,8 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) {
return;

volume &= 0xff;
// Priority setting (used for acquiring one of the 4 pcm channels) currently not implemented.
// int16 vprIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]);
// uint16 priority = (vprIndex > 0) ? (vprIndex * volume) >> 8 : -vprIndex;
int16 prIndex = (int16)READ_LE_UINT16(&_ingameSoundIndex[track * 2 + 1]);
uint16 priority = (prIndex > 0) ? (prIndex * volume) >> 8 : -prIndex;

static const uint8 volTable1[] = { 223, 159, 95, 47, 15, 0 };
static const uint8 volTable2[] = { 255, 191, 127, 63, 30, 0 };
Expand All @@ -189,7 +188,7 @@ void LoLEngine::snd_playSoundEffect(int track, int volume) {

if (hasVocFile) {
if (_sound->isVoicePresent(_ingameSoundList[vocIndex]))
_sound->voicePlay(_ingameSoundList[vocIndex], 0, volume, true);
_sound->voicePlay(_ingameSoundList[vocIndex], 0, volume, priority, true);
} else if (_flags.platform == Common::kPlatformPC) {
if (_sound->getSfxType() == Sound::kMidiMT32)
track = (track < _ingameMT32SoundIndexSize) ? (_ingameMT32SoundIndex[track] - 1) : -1;
Expand Down
18 changes: 14 additions & 4 deletions engines/kyra/sound_towns.cpp
Expand Up @@ -569,15 +569,24 @@ void SoundTownsPC98_v2::beginFadeOut() {
haltTrack();
}

int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8, bool) {
int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, uint8 priority, bool) {
static const uint16 rates[] = { 0x10E1, 0x0CA9, 0x0870, 0x0654, 0x0438, 0x032A, 0x021C, 0x0194 };
static const char patternHOF[] = "%s.PCM";
static const char patternLOL[] = "%s.VOC";

int h = 0;
if (_currentSFX) {
while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h]))
while (h < kNumChannelHandles && _mixer->isSoundHandleActive(_soundChannels[h].handle))
h++;

if (h >= kNumChannelHandles) {
h = 0;
while (h < kNumChannelHandles && _soundChannels[h].priority > priority)
++h;
if (h < kNumChannelHandles)
voiceStop(&_soundChannels[h].handle);
}

if (h >= kNumChannelHandles)
return 0;
}
Expand Down Expand Up @@ -630,9 +639,10 @@ int32 SoundTownsPC98_v2::voicePlay(const char *file, Audio::SoundHandle *handle,
}

_currentSFX = Audio::makeRawStream(sfx, outsize, sfxRate * 10, Audio::FLAG_UNSIGNED | Audio::FLAG_LITTLE_ENDIAN);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h], _currentSFX);
_mixer->playStream(Audio::Mixer::kSFXSoundType, &_soundChannels[h].handle, _currentSFX, -1, volume);
_soundChannels[h].priority = priority;
if (handle)
*handle = _soundChannels[h];
*handle = _soundChannels[h].handle;

delete[] data;
return 1;
Expand Down

0 comments on commit e016e7d

Please sign in to comment.