S_StartSoundAtVolumeEx: Allow applying EFX to individual sounds

S_StartSoundAtVolume has been expanded to allow you to pass EFX info to it.
Just set the effect and the vars for the effect and OpenAL will handle the rest. Can be used in the future for all sorts of things.
I_SoundIsPlaying still needs to be modified to account for sounds lasting longer audibly then they do as a source.
This commit is contained in:
NepDisk 2026-03-22 10:58:04 -04:00
parent 122fbcc808
commit 9317f753bc
5 changed files with 196 additions and 17 deletions

View file

@ -18,6 +18,14 @@
#include "sounds.h"
#include "command.h"
#ifdef HAVE_OPENAL
#include "AL/al.h"
#include "AL/alc.h"
#include "AL/alext.h"
#include "AL/efx.h"
#include "AL/efx-presets.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
@ -37,6 +45,36 @@ typedef enum {
MU_MID_EX, // Non-native MIDI
} musictype_t;
typedef enum
{
EFFECT_NONE = 0,
EFFECT_REVERB,
EFFECT_DISTORTION,
} effecttypes_t;
typedef struct
{
// flags for effects
#ifdef HAVE_OPENAL
ALuint effect;
ALuint slot;
#endif
UINT32 type;
float var1;
float var2;
float var3;
float var4;
float var5;
float var6;
float var7;
float var8;
float var9;
float var10;
float var11;
float var12;
float var13;
} efx_t;
/** \brief Sound subsystem runing and waiting
*/
extern UINT8 sound_started;
@ -83,7 +121,7 @@ void I_ShutdownSound(void);
\return sfx handle
*/
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel);
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel, efx_t *efx);
/** \brief Stops a sound channel.
@ -105,6 +143,8 @@ void I_UpdateSound(void);
*/
boolean I_SoundIsPlaying(INT32 handle);
/** \brief Updates the sfx handle
\param handle sfx handle
@ -114,7 +154,7 @@ boolean I_SoundIsPlaying(INT32 handle);
\return void
*/
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch);
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t *efx);
/** \brief The I_SetSfxVolume function
@ -246,6 +286,9 @@ boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void));
boolean I_FadeOutStopSong(UINT32 ms);
boolean I_FadeInPlaySong(UINT32 ms, boolean looping);
efx_t *I_CreateEFX(efx_t *efx);
void I_DeleteEFX(efx_t *efx);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -15,6 +15,7 @@
#include "dehacked.h"
#include "doomdef.h"
#include "g_game.h"
#include "i_sound.h"
#include "p_local.h"
#include "p_setup.h"
#include "r_main.h"
@ -3233,11 +3234,23 @@ void A_AttractChase(void *thing)
actor->target->player->ringboost += K_GetKartRingPower(actor->target->player, true);
actor->target->player->ringtime += K_GetKartRingPower(actor->target->player, true);
//#define EFXTEST
#ifdef EFXTEST
efx_t efx;
S_InitEFXArray(&efx);
efx.type = EFFECT_REVERB;
S_StartSoundAtVolumeEx(actor->target, sfx_s1b5, actor->target->player->ringvolume, &efx);
#else
S_StartSoundAtVolume(actor->target, sfx_s1b5, actor->target->player->ringvolume);
#endif
if (actor->target->player->rings <= 10)
{
#ifdef EFXTEST
S_StartSoundAtVolumeEx(actor->target, sfx_ringlw, 255 - actor->target->player->rings*10, &efx);
#else
S_StartSoundAtVolume(actor->target, sfx_ringlw, 255 - actor->target->player->rings*10);
#endif
}
if (actor->target->player->ringboost > (4*TICRATE + TICRATE/2))

View file

@ -317,6 +317,7 @@ static void SetChannelsNum(void)
{
channels[i].sfxinfo = 0;
channels[i].origin = NULL;
channels[i].efx = NULL;
}
S_ResetCaptions();
@ -525,7 +526,7 @@ static INT32 S_ScaleVolumeWithSplitscreen(INT32 volume)
) / FRACUNIT;
}
void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
void S_StartSoundAtVolumeEx(const void *origin_p, sfxenum_t sfx_id, INT32 volume, efx_t *efx)
{
const mobj_t *origin = (const mobj_t *)origin_p;
const sfxenum_t actual_id = sfx_id;
@ -730,7 +731,17 @@ void S_StartSoundAtVolume(const void *origin_p, sfxenum_t sfx_id, INT32 volume)
channels[cnum].sfxinfo = sfx;
channels[cnum].origin = origin;
channels[cnum].volume = initial_volume;
channels[cnum].handle = I_StartSound(sfx_id, S_GetSoundVolume(sfx, volume), sep, pitch, priority, cnum);
if (efx != NULL && efx->type != EFFECT_NONE)
{
channels[cnum].efx = I_CreateEFX(efx);
}
else
{
channels[cnum].efx = NULL;
}
channels[cnum].handle = I_StartSound(sfx_id, S_GetSoundVolume(sfx, volume), sep, pitch, priority, cnum, channels[cnum].efx);
}
}
@ -951,7 +962,7 @@ notinlevel:
}
if (audible)
I_UpdateSoundParams(c->handle, S_GetSoundVolume(c->sfxinfo, volume), sep, pitch);
I_UpdateSoundParams(c->handle, S_GetSoundVolume(c->sfxinfo, volume), sep, pitch, c->efx);
else
S_StopChannel(cnum);
}
@ -1021,6 +1032,8 @@ static void S_StopChannel(INT32 cnum)
}
c->origin = NULL;
I_DeleteEFX(c->efx);
c->efx = NULL;
}
//
@ -2943,3 +2956,15 @@ void ModFilter_OnChange(void)
openmpt_module_set_render_param(openmpt_mhandle, OPENMPT_MODULE_RENDER_INTERPOLATIONFILTER_LENGTH, cv_modfilter.value);
}
#endif
void S_InitEFXArray(efx_t *efx)
{
if (efx == NULL)
return;
efx->type = EFFECT_NONE;
efx->var1 = efx->var2 = efx->var3 = -255;
efx->var4 = efx->var5 = efx->var6 = -255;
efx->var7 = efx->var8 = efx->var9 = -255;
efx->var10 = efx->var11 = efx->var12 = efx->var13 = -255;
}

View file

@ -88,6 +88,8 @@ struct channel_t
// handle of the sound being played
INT32 handle;
// EFX
efx_t *efx;
};
struct caption_t {
@ -139,7 +141,8 @@ boolean S_SoundDisabled(void);
void S_StartSound(const void *origin, sfxenum_t sound_id);
// Will start a sound at a given volume.
void S_StartSoundAtVolume(const void *origin, sfxenum_t sound_id, INT32 volume);
void S_StartSoundAtVolumeEx(const void *origin_p, sfxenum_t sfx_id, INT32 volume, efx_t *efx);
#define S_StartSoundAtVolume(origin, sound_id, volume) S_StartSoundAtVolumeEx(origin, sound_id, volume, NULL)
// Stop sound for thing at <origin>
void S_StopSound(void *origin);
@ -345,6 +348,8 @@ void S_StartSoundName(void *mo, const char *soundname);
void S_StopSoundByID(void *origin, sfxenum_t sfx_id);
void S_StopSoundByNum(sfxenum_t sfxnum);
void S_InitEFXArray(efx_t *efx);
#ifndef HW3SOUND
#define S_StartAttackSound S_StartSound
#define S_StartScreamSound S_StartSound

View file

@ -391,14 +391,6 @@ void I_StartupSound(void)
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv);
#undef LOAD_PROC
// Start EFX
// TODO: Discuss and see if we even want EFX flags for sounds and implement system if so.
//alGenEffects(1, &audio.effect);
//TRY(alEffecti, audio.effect, AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
//TRY(alEffectf, audio.effect, AL_DISTORTION_EDGE, AL_DISTORTION_MAX_EDGE);
//alGenAuxiliaryEffectSlots(1, &audio.effectslot);
//alAuxiliaryEffectSloti(audio.effectslot, AL_EFFECTSLOT_EFFECT, audio.effect);
audio.music = INVALID_HANDLE;
audio.bufferindex = 0;
@ -984,7 +976,7 @@ void I_FreeSfx(sfxinfo_t *sfx)
sfx->lumpnum = LUMPERROR;
}
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch)
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t *efx)
{
if (handle == INVALID_HANDLE)
return;
@ -1003,9 +995,14 @@ void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch)
pan = pan * 0.5f; // 0.5 = sin(30') for a +/- 30 degree arc
TRY(alSourcei, source, AL_SOURCE_RELATIVE, AL_TRUE);
TRY(alSource3f, source, AL_POSITION, pan, 0, -sqrtf(1.0f - pan*pan));
if (efx != NULL && TRY(alIsEffect, efx->effect) && TRY(alIsAuxiliaryEffectSlot, efx->slot))
{
TRY(alSource3i, source, AL_AUXILIARY_SEND_FILTER, efx->slot, 0, AL_FILTER_NULL);
}
}
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel)
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel, efx_t *efx)
{
ALuint source;
if (!TRY(alGenSources, 1, &source))
@ -1023,7 +1020,7 @@ INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priori
return INVALID_HANDLE;
}
I_UpdateSoundParams(source, vol, sep, pitch);
I_UpdateSoundParams(source, vol, sep, pitch, efx);
if (!TRY(alSourcePlay, source))
{
@ -1898,4 +1895,100 @@ boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
return false;
}
efx_t *I_CreateEFX(efx_t *efx)
{
LOCKAUDIO;
efx_t *efxc = Z_Calloc(sizeof(efx_t), PU_STATIC, NULL);
if (efxc == NULL)
I_Error("OpenAL: Ran out of memory generating EFX.\n");
if (efx != NULL)
memcpy(efxc, efx, sizeof(efx_t));
// Init effects and slots.
TRY(alGenEffects, 1, &efxc->effect);
TRY(alGenAuxiliaryEffectSlots, 1, &efxc->slot);
if (TRY(alIsEffect, efxc->effect) && TRY(alIsAuxiliaryEffectSlot, efxc->slot))
{
switch (efxc->type)
{
case EFFECT_REVERB:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_DENSITY, efxc->var1);
if (efxc->var2 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_DIFFUSION, efxc->var2);
if (efxc->var3 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_GAIN, efxc->var3);
if (efxc->var4 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_GAINHF, efxc->var4);
if (efxc->var5 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_DECAY_TIME, efxc->var5);
if (efxc->var6 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_DECAY_HFRATIO, efxc->var6);
if (efxc->var7 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_REFLECTIONS_GAIN, efxc->var7);
if (efxc->var8 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_REFLECTIONS_DELAY, efxc->var8);
if (efxc->var9 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_LATE_REVERB_GAIN, efxc->var9);
if (efxc->var10 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_LATE_REVERB_DELAY, efxc->var10);
if (efxc->var11 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_AIR_ABSORPTION_GAINHF, efxc->var11);
if (efxc->var12 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, efxc->var12);
if (efxc->var13 != -255)
TRY(alEffectf, efxc->effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, efxc->var13);
break;
case EFFECT_DISTORTION:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_DISTORTION_EDGE, efxc->var1);
if (efxc->var2 != -255)
TRY(alEffectf, efxc->effect, AL_DISTORTION_GAIN, efxc->var2);
if (efxc->var3 != -255)
TRY(alEffectf, efxc->effect, AL_DISTORTION_LOWPASS_CUTOFF, efxc->var3);
if (efxc->var4 != -255)
TRY(alEffectf, efxc->effect, AL_DISTORTION_EQCENTER, efxc->var4);
if (efxc->var5 != -255)
TRY(alEffectf, efxc->effect, AL_DISTORTION_EQBANDWIDTH, efxc->var5);
break;
}
TRY(alAuxiliaryEffectSloti, efxc->slot, AL_EFFECTSLOT_EFFECT, efxc->effect);
return efxc;
}
Z_Free(efxc);
return NULL;
}
void I_DeleteEFX(efx_t *efx)
{
LOCKAUDIO;
if (efx == NULL)
return;
if (TRY(alIsEffect, efx->effect))
{
TRY(alDeleteEffects, 1, &efx->effect);
}
if (TRY(alIsAuxiliaryEffectSlot, efx->slot))
{
TRY(alDeleteAuxiliaryEffectSlots, 1, &efx->slot);
}
Z_Free(efx);
}
#endif // defined(HAVE_OPENAL)