Skip to content

Commit

Permalink
[jak2] Workaround for sound effects getting dropped (#3660)
Browse files Browse the repository at this point in the history
Similar to the workaround added in jak 3, if too many sounds are
playing, a sound will be removed. If there are multiple instances of the
same sound being played, those will be removed first. Within that, older
sounds are removed first.

It's not exactly the same as the instance limits of 989snd, but it seems
to work well. It's at least better than what we had before.

Co-authored-by: water111 <awaterford1111445@gmail.com>
  • Loading branch information
water111 and water111 authored Sep 8, 2024
1 parent 7053090 commit a39af39
Show file tree
Hide file tree
Showing 4 changed files with 80 additions and 7 deletions.
75 changes: 73 additions & 2 deletions game/overlord/common/ssound.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,16 @@

s32 gMusicFade = 0;
s32 gSema;
Sound gSounds[64];
constexpr int kNumSounds = 64;
Sound gSounds[kNumSounds];
Vec3w gEarTrans[2];
Vec3w gCamTrans;
s32 gMusicFadeDir = 0;
Curve gCurves[16];
s32 gCamAngle;
u8 gMirrorMode = 0;
u32 sLastTick = 0;
s64 gAddIndex = 0;

static s32 sqrt_table[256] = {
0, 4096, 5793, 7094, 8192, 9159, 10033, 10837, 11585, 12288, 12953, 13585, 14189,
Expand Down Expand Up @@ -56,6 +58,7 @@ static s32 atan_table[257] = {
void ssound_init_globals() {
gMusicFade = 0;
gSema = 0;
gAddIndex = 0;
}

Sound* LookupSound(s32 id) {
Expand Down Expand Up @@ -268,20 +271,88 @@ void UpdateVolume(Sound* sound) {
}
}

Sound* AllocateSound() {
void RemoveOldSounds() {
int unique_sounds = 0;
struct Entry {
u32 id;
u32 count;
Sound* info;
};
Entry entries[kNumSounds];
Entry* best_entry = nullptr;

for (auto& sound : gSounds) {
if (sound.id) {
Entry* existing_entry = nullptr;
u32 uid = snd_GetSoundID(sound.sound_handle);

// look for entry:
for (int i = 0; i < unique_sounds; i++) {
if (entries[i].id == uid) {
existing_entry = &entries[i];
break;
}
}

// if none found, create
if (!existing_entry) {
existing_entry = &entries[unique_sounds];
unique_sounds++;
existing_entry->id = uid;
existing_entry->count = 0;
existing_entry->info = &sound;
}

// update
existing_entry->count++;
// pick oldest sound
if (sound.add_index < existing_entry->info->add_index) {
existing_entry->info = &sound;
}

// se if we're best
if (!best_entry) {
best_entry = existing_entry;
} else {
if (best_entry->count < existing_entry->count) {
best_entry = existing_entry;
}
}
}
}

if (best_entry) {
snd_StopSound(best_entry->info->sound_handle);
best_entry->info->id = 0;
}
}

Sound* AllocateSound(bool remove_old_sounds) {
for (auto& s : gSounds) {
if (s.id == 0) {
s.add_index = gAddIndex++;
return &s;
}
}

CleanSounds();
for (auto& s : gSounds) {
if (s.id == 0) {
s.add_index = gAddIndex++;
return &s;
}
}

if (remove_old_sounds) {
RemoveOldSounds();
for (auto& s : gSounds) {
if (s.id == 0) {
s.add_index = gAddIndex++;
return &s;
}
}
}

return nullptr;
}

Expand Down
4 changes: 3 additions & 1 deletion game/overlord/common/ssound.h
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,8 @@ struct Sound {
s32 auto_time;
SoundParams params;
SoundRecord* bank_entry;

s64 add_index = 0;
};

struct Curve {
Expand All @@ -61,7 +63,7 @@ extern u32 sLastTick;
void ssound_init_globals();

Sound* LookupSound(s32 id);
Sound* AllocateSound();
Sound* AllocateSound(bool remove_old_sounds);
s32 GetVolume(Sound* sound);
void UpdateVolume(Sound* sound);
s32 CalculateFalloffVolume(Vec3w* pos, s32 volume, s32 fo_curve, s32 fo_min, s32 fo_max);
Expand Down
4 changes: 2 additions & 2 deletions game/overlord/jak1/srpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ void* RPC_Player(unsigned int /*fno*/, void* data, int size) {
if (!PollSema(gSema)) {
if (gMusic) {
if (!gMusicPause && !LookupSound(666)) {
Sound* music = AllocateSound();
Sound* music = AllocateSound(false);
if (music != nullptr) {
gMusicFade = 0;
gMusicFadeDir = 1;
Expand Down Expand Up @@ -183,7 +183,7 @@ void* RPC_Player(unsigned int /*fno*/, void* data, int size) {
break;
}

sound = AllocateSound();
sound = AllocateSound(false);
if (!sound) {
break;
}
Expand Down
4 changes: 2 additions & 2 deletions game/overlord/jak2/srpc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ void* RPC_Player(unsigned int /*fno*/, void* data, int size) {
if (!PollSema(gSema)) {
if (gMusic) {
if (!gMusicPause && !LookupSound(666)) {
Sound* music = AllocateSound();
Sound* music = AllocateSound(true);
if (music != nullptr) {
gMusicFade = 0;
gMusicFadeDir = 1;
Expand Down Expand Up @@ -117,7 +117,7 @@ void* RPC_Player(unsigned int /*fno*/, void* data, int size) {

} else {
// new sound
sound = AllocateSound();
sound = AllocateSound(true);
if (sound == nullptr) {
// no free sounds
break;
Expand Down

0 comments on commit a39af39

Please sign in to comment.