diff --git a/engine/Quake/snd_fmod.c b/engine/Quake/snd_fmod.c index 36bd089..731bbd0 100644 --- a/engine/Quake/snd_fmod.c +++ b/engine/Quake/snd_fmod.c @@ -36,6 +36,10 @@ typedef struct entsounds_s static entsounds_t entsounds[MAX_CHANNELS]; +// Keep track of all the sounds started each frame +static sfx_t *sfxThisFrame[16]; +static int numSfxThisFrame; + void S_Startup(void) { FMOD_RESULT result; @@ -114,6 +118,8 @@ void S_Startup(void) FMOD_System_Set3DRolloffCallback(fmod_system, &SND_FMOD_Attenuation); memset(entsounds, 0, sizeof(entsounds)); + memset(sfxThisFrame, 0, sizeof(sfxThisFrame)); + numSfxThisFrame = 0; sound_started = true; } @@ -252,10 +258,12 @@ static soundslot_t *SND_PickSoundSlot(int entnum, int entchannel) void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float fvol, float attenuation) // Note: volume and attenuation are properly normalized here { + int i; FMOD_CHANNEL *channel; FMOD_VECTOR position; FMOD_RESULT result; soundslot_t *userdata; + unsigned long long dspclock; if (!fmod_system || !sfx) return; @@ -304,7 +312,20 @@ void S_StartSound(int entnum, int entchannel, sfx_t *sfx, vec3_t origin, float f FMOD_Channel_SetPriority(channel, 64); // Ensure local sounds always get priority over other entities } - // TODO: Use ChannelControl::setDelay and ChannelControl::getDSPClock to add a delay to move sounds out of phase if necessary + for (i = 0; i < numSfxThisFrame; i++) + { + // if an identical sound has also been started this frame, offset the pos + // a bit to keep it from just making the first one louder + if (sfxThisFrame[i] == sfx) + { + FMOD_ChannelGroup_GetDSPClock(sfx_channelGroup, &dspclock, NULL); + FMOD_Channel_SetDelay(channel, dspclock + SND_GetDelay(sfx, 0.1f), 0, 0); + break; + } + } + + if (numSfxThisFrame < 16) + sfxThisFrame[numSfxThisFrame++] = sfx; FMOD_Channel_SetPaused(channel, 0); } @@ -416,6 +437,10 @@ void S_Update(vec3_t origin, vec3_t forward, vec3_t right, vec3_t up) FMOD_ChannelGroup_SetVolume(sfx_channelGroup, sfxvolume.value); FMOD_System_Update(fmod_system); + + // Reset sounds played for the next frame + memset(sfxThisFrame, 0, sizeof(sfxThisFrame)); + numSfxThisFrame = 0; } void S_ExtraUpdate(void)