diff --git a/docs/tr2/CHANGELOG.md b/docs/tr2/CHANGELOG.md index f5216814e..ae9293373 100644 --- a/docs/tr2/CHANGELOG.md +++ b/docs/tr2/CHANGELOG.md @@ -37,6 +37,7 @@ - fixed teleporting to an item on a ledge sometimes pushing Lara to the room below (#2372) - fixed the game crashing if a cinematic is triggered but the level contains no cinematic frames (#2413) - fixed being unable to load a level that contains no sound effect data (#2460) +- fixed issues with sound effects not playing or looping forever in some cases when many other effects are playing (#2494) - fixed Lara activating triggers one frame too early (#2205, regression from 0.7) - fixed savegame incompatibility with OG (#2271, regression from 0.8) - fixed stopwatch showing wrong UI in some circumstances (#2221, regression from 0.8) diff --git a/src/tr2/game/sound.c b/src/tr2/game/sound.c index 201eb930e..d4cf21c41 100644 --- a/src/tr2/game/sound.c +++ b/src/tr2/game/sound.c @@ -13,6 +13,8 @@ #include +#define MAX_VOLUME 0x8000 + typedef enum { SOUND_MODE_NORMAL = 0, SOUND_MODE_WAIT = 1, @@ -172,7 +174,7 @@ bool Sound_Effect( } SAMPLE_INFO *const info = Sound_GetSampleInfo(sample_id); - if (info == nullptr) { + if (info == nullptr || info->number < 0) { return false; } @@ -222,10 +224,6 @@ bool Sound_Effect( - SOUND_MAX_PITCH_CHANGE; } - if (info->number < 0) { - return false; - } - const SOUND_MODE mode = info->flags & SOUND_MODE_MASK; const int32_t num_samples = (info->flags >> 2) & 0xF; const int32_t track_id = num_samples == 1 @@ -240,7 +238,7 @@ bool Sound_Effect( for (int32_t i = 0; i < SOUND_MAX_SLOTS; i++) { SOUND_SLOT *const slot = &m_SoundSlots[i]; if (slot->effect_num == sample_id) { - if (Audio_Sample_IsPlaying(i)) { + if (Audio_Sample_IsPlaying(slot->handle)) { return true; } M_ClearSlot(slot); @@ -273,49 +271,45 @@ bool Sound_Effect( break; } - const bool is_looped = mode == SOUND_MODE_LOOPED; - int32_t handle = M_Play(track_id, volume, pitch, pan, is_looped); + int32_t free_slot = -1; + for (int32_t i = 0; i < SOUND_MAX_SLOTS; i++) { + SOUND_SLOT *const slot = &m_SoundSlots[i]; + if (slot->effect_num < 0) { + free_slot = i; + break; + } + } - if (handle == AUDIO_NO_SOUND) { - int32_t min_volume = 0x8000; - int32_t min_slot = -1; - for (int32_t i = 1; i < SOUND_MAX_SLOTS; i++) { + if (free_slot == -1) { + // No slot found - try to find the most silent track, and use this one + int32_t min_volume = MAX_VOLUME; + for (int32_t i = 0; i < SOUND_MAX_SLOTS; i++) { SOUND_SLOT *const slot = &m_SoundSlots[i]; if (slot->effect_num >= 0 && slot->volume < min_volume) { min_volume = slot->volume; - min_slot = i; + free_slot = i; } } - if (min_slot >= 0 && volume >= min_volume) { - SOUND_SLOT *const slot = &m_SoundSlots[min_slot]; - M_CloseSlot(slot); - handle = M_Play(track_id, volume, pitch, pan, is_looped); + if (free_slot == -1) { + // No slot found - give up + return false; } } - if (handle == AUDIO_NO_SOUND) { - info->number = -1; - return false; - } - - int32_t free_slot = -1; - for (int32_t i = 0; i < SOUND_MAX_SLOTS; i++) { - SOUND_SLOT *const slot = &m_SoundSlots[i]; - if (slot->effect_num < 0) { - free_slot = i; - break; - } - } + SOUND_SLOT *const slot = &m_SoundSlots[free_slot]; + M_CloseSlot(slot); - if (free_slot != -1) { - SOUND_SLOT *const slot = &m_SoundSlots[free_slot]; + const bool is_looped = mode == SOUND_MODE_LOOPED; + const int32_t handle = M_Play(track_id, volume, pitch, pan, is_looped); + if (handle != AUDIO_NO_SOUND) { slot->volume = volume; slot->pan = pan; slot->pitch = pitch; slot->effect_num = sample_id; slot->handle = handle; } + return true; }