Add per map global EFX via mapheader

This commit is contained in:
NepDisk 2026-03-22 20:21:38 -04:00
parent dba94cce75
commit 9061274cdc
12 changed files with 404 additions and 153 deletions

View file

@ -214,6 +214,7 @@ BlanKart's namespace implements the following additional fields:
invertencore = <bool>; // true = encore remap rules are inverted.
flatlighting = <bool>; // true = directional lighting is forced off.
forcedirectionallighting = <bool>; // true = directional lighting is forced on.
noaudioeffects = <bool>; // true = global audio effects for objects in this sector are disabled.
nostepup = <bool>; // true = objects can't step up.
doublestepup = <bool>; // true = objects have increased step up.
nostepdown = <bool>; // true = objects can't step down.
@ -225,12 +226,13 @@ BlanKart's namespace implements the following additional fields:
zoomtubestart = <bool>; // true = sector is start of a zoom tube.
zoomtubeend = <bool>; // true = sector is end of a zoom tube.
speedpad = <bool>; // true = players are launched forward by this sector.
finishline = <bool>; // true = players gain a lap or finish the race in this sector. Used for legacy support.
sneakerpanel = <bool>; // true = players are speed boosted forward by this sector.
waterpanel = <bool>; // true = players are speed boosted forward by this sector and are able to drive on water.
redpogospring = <bool>; // true = players are bounced into the air by this sector.
yellowpogospring = <bool>; // true = players are bounced into the air and then speedcapped by this sector.
speedpad = <bool>; // true = players are launched forward by this sector.
finishline = <bool>; // true = players gain a lap or finish the race in this sector. Used for legacy support.
sneakerpanel = <bool>; // true = players are speed boosted forward by this sector.
waterpanel = <bool>; // true = players are speed boosted forward by this sector and are able to drive on water.
redpogospring = <bool>; // true = players are bounced into the air by this sector.
yellowpogospring = <bool>; // true = players are bounced into the air and then speedcapped by this sector.
walltransfer = <bool>; // true = players are allowed to slide up walls from this sector.
repeatspecial = <bool>; // true = repeatable action.
continuousspecial = <bool>; // true = action is executed every game tick.
@ -313,3 +315,6 @@ BK 1.0: 10.02.2025
BK 1.0: 11.03.2025
- Fixed up some typos.
- Added more effects.
BK 1.0 22.03.2026
- Added more effects.

View file

@ -1437,6 +1437,9 @@ void D_RegisterClientCommands(void)
CV_RegisterVar(&cv_digmusicvolume);
CV_RegisterVar(&cv_numChannels);
// al_sound.c
CV_RegisterVar(&cv_soundefx);
// screen.c
CV_RegisterVar(&cv_fullscreen);
CV_RegisterVar(&cv_renderview);

View file

@ -1270,6 +1270,77 @@ void readlevelheader(MYFILE *f, char * name)
else
mapheaderinfo[num]->use_terrain = false;
}
// Global EFX
else if (fastcmp(word, "GLOBALEFX"))
{
mapheaderinfo[num]->globalEFX->type = get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR1"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var1 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR2"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var2 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR3"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var3 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR4"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var4 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR5"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var5 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR6"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var6 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR7"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var7 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR8"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var8 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR9"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var9 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR10"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var10 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR11"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var11 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR12"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var12 = flonum ? flonum : get_number(word2);
}
else if (fastcmp(word, "GLOBALEFXVAR13"))
{
float flonum = atof(word2);
mapheaderinfo[num]->globalEFX->var13 = flonum ? flonum : get_number(word2);
}
// ignored for compatibility
else if (fastcmp(word, "NEXTLEVEL") || fastcmp(word, "TIMEATTACK") || fastcmp(word, "RECORDATTACK"))
continue;

View file

@ -14,6 +14,7 @@
#include "d_ticcmd.h"
#include "doomdef.h" // Constants
#include "s_sound.h" // Sound constants
#include "i_sound.h"
#include "info.h" // Mobj, state, sprite, etc constants
#include "m_menu.h" // Menu constants
#include "y_inter.h" // Intermission constants
@ -537,6 +538,7 @@ const char *const MSF_LIST[] = {
"INVERTENCORE",
"FLATLIGHTING",
"DIRECTIONLIGHTING",
"NOEFX",
NULL
};
@ -559,6 +561,10 @@ const char *const SSF_LIST[] = {
"FINISHLINE",
"ZOOMTUBESTART",
"ZOOMTUBEEND",
"NOPHYSICSFLOOR",
"NOPHYSICSCEILING",
"GRAVITYOVERRIDE",
"WALLTRANSFER",
NULL
};
@ -1863,5 +1869,23 @@ struct int_const_s const INT_CONST[] = {
{"TICCMD_USINGTILT", TICCMD_USINGTILT},
{"TICCMD_EXCESSTILT", TICCMD_EXCESSTILT},
// EFX
{"EFFECT_NONE", EFFECT_NONE},
{"EFFECT_REVERB", EFFECT_REVERB},
{"EFFECT_CHORUS", EFFECT_CHORUS},
{"EFFECT_DISTORTION", EFFECT_DISTORTION},
{"EFFECT_ECHO", EFFECT_ECHO},
{"EFFECT_PITCHSHIFT", EFFECT_PITCHSHIFT},
{"EFFECT_RINGMOD", EFFECT_RINGMOD},
{"EFFECT_COMPRESSOR", EFFECT_COMPRESSOR},
{"EFFECT_EQ", EFFECT_EQ},
{"CHORUSWAVE_SINUSOID", CHORUSWAVE_SINUSOID},
{"CHORUSWAVE_TRIANGLE", CHORUSWAVE_TRIANGLE},
{"RINGMOD_SIN", RINGMOD_SIN},
{"RINGMOD_SAW", RINGMOD_SAW},
{"RINGMOD_SQUARE", RINGMOD_SQUARE},
{NULL,0}
};

View file

@ -29,6 +29,8 @@ extern "C" {
// We need the player data structure as well.
#include "d_player.h"
#include "i_sound.h"
// =============================
// Selected map etc.
// =============================
@ -435,6 +437,9 @@ struct mapheader_t
boolean use_terrain; ///< Whether to use gameplay affecting Terrain effects or not (leaves visuals alone)
INT32 base_track_complexity; ///< Decides what the base track compexity for the current map is.
fixed_t track_modifier_max; ///< Decides what the modifier max for the current map is.
// EFX
efx_t *globalEFX; ///< Decides what global EFX for the current map is. ONLY USE FOR TYPE AND VARS.
};

View file

@ -58,13 +58,16 @@ typedef enum
EFFECT_EQ,
} effecttypes_t;
#ifdef HAVE_OPENAL
typedef enum
{
#ifdef HAVE_OPENAL
CHORUSWAVE_SINUSOID = AL_CHORUS_WAVEFORM_SINUSOID,
CHORUSWAVE_TRIANGLE = AL_CHORUS_WAVEFORM_TRIANGLE,
} choruswaves_t;
#else
CHORUSWAVE_SINUSOID = 0,
CHORUSWAVE_TRIANGLE = 0,
#endif
} choruswaves_t;
typedef enum
{
@ -142,7 +145,7 @@ void I_ShutdownSound(void);
\return sfx handle
*/
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel, efx_t *efx);
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel, efx_t *efx, const void *origin);
/** \brief Stops a sound channel.
@ -175,7 +178,7 @@ boolean I_SoundIsPlaying(INT32 handle);
\return void
*/
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t *efx);
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t *efx, const void *origin);
/** \brief The I_SetSfxVolume function
@ -311,6 +314,11 @@ efx_t *I_CreateEFX(efx_t *efx);
float I_GetEFXTail(efx_t *efx);
void I_DeleteEFX(efx_t *efx);
void I_CreateGlobalEFX(efx_t *efx);
void I_DeleteGlobalEFX(void);
extern consvar_t cv_soundefx;
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -26,6 +26,7 @@
#include "i_time.h"
#include "i_video.h" // for I_FinishUpdate()..
#include "r_defs.h"
#include "r_sky.h"
#include "i_system.h"
@ -470,6 +471,7 @@ static void P_ClearSingleMapHeaderInfo(INT16 num)
P_ClearMapHeaderLighting(&mapheaderinfo[num]->lighting);
P_ClearMapHeaderLighting(&mapheaderinfo[num]->lighting_encore);
mapheaderinfo[num]->use_encore_lighting = false;
S_InitEFXArray(mapheaderinfo[num]->globalEFX);
#if 1 // equivalent to "FlickyList = DEMO"
P_SetDemoFlickies(num);
#else // equivalent to "FlickyList = NONE"
@ -529,6 +531,11 @@ void P_AllocMapHeader(INT16 i)
mapheaderinfo[i]->minimapPic = NULL;
mapheaderinfo[i]->cup = NULL;
mapheaderinfo[i]->flickies = NULL;
mapheaderinfo[i]->globalEFX = Z_Calloc(sizeof(efx_t), PU_STATIC, NULL);
if (mapheaderinfo[i]->globalEFX == NULL)
I_Error("P_AllocMapHeader: Not enough memory to allocate new global mapheader EFX (ID %d).", i);
nummapheaders++;
}
P_ClearSingleMapHeaderInfo(i);
@ -1892,6 +1899,8 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
sectors[i].flags |= MSF_FLATLIGHTING;
else if (fastcmp(param, "forcedirectionallighting") && fastcmp("true", val))
sectors[i].flags |= MSF_DIRECTIONLIGHTING;
else if (fastcmp(param, "noaudioeffects") && fastcmp("true", val))
sectors[i].flags |= MSF_NOEFX;
else if (fastcmp(param, "nostepup") && fastcmp("true", val))
sectors[i].specialflags |= SSF_NOSTEPUP;
else if (fastcmp(param, "doublestepup") && fastcmp("true", val))
@ -1916,20 +1925,20 @@ static void ParseTextmapSectorParameter(UINT32 i, const char *param, const char
sectors[i].specialflags |= SSF_YELLOWPOGOSPRING;
else if (fastcmp(param, "fan") && fastcmp("true", val))
sectors[i].specialflags |= SSF_FAN;
else if (fastcmp(param, "finishline") && fastcmp("true", val))
sectors[i].specialflags |= SSF_FINISHLINE;
else if (fastcmp(param, "zoomtubestart") && fastcmp("true", val))
sectors[i].specialflags |= SSF_ZOOMTUBESTART;
else if (fastcmp(param, "zoomtubeend") && fastcmp("true", val))
sectors[i].specialflags |= SSF_ZOOMTUBEEND;
else if (fastcmp(param, "finishline") && fastcmp("true", val))
sectors[i].specialflags |= SSF_FINISHLINE;
else if (fastcmp(param, "gravityoverride") && fastcmp("true", val))
sectors[i].specialflags |= SSF_GRAVITYOVERRIDE;
else if (fastcmp(param, "walltransfer") && fastcmp("true", val))
sectors[i].specialflags |= SSF_WALLTRANSFER;
else if (fastcmp(param, "nophysics_floor") && fastcmp("true", val))
sectors[i].specialflags |= SSF_NOPHYSICSFLOOR;
else if (fastcmp(param, "nophysics_ceiling") && fastcmp("true", val))
sectors[i].specialflags |= SSF_NOPHYSICSCEILING;
else if (fastcmp(param, "gravityoverride") && fastcmp("true", val))
sectors[i].specialflags |= SSF_GRAVITYOVERRIDE;
else if (fastcmp(param, "walltransfer") && fastcmp("true", val))
sectors[i].specialflags |= SSF_WALLTRANSFER;
else if (fastcmp(param, "friction"))
sectors[i].friction = FLOAT_TO_FIXED(atof(val));
else if (fastcmp(param, "gravity"))
@ -3109,6 +3118,12 @@ static void P_WriteTextmap(void)
fprintf(f, "ripple_ceiling = true;\n");
if (wsectors[i].flags & MSF_INVERTENCORE)
fprintf(f, "invertencore = true;\n");
if (wsectors[i].flags & MSF_FLATLIGHTING)
fprintf(f, "flatlighting = true;\n");
if (wsectors[i].flags & MSF_DIRECTIONLIGHTING)
fprintf(f, "forcedirectionallighting = true;\n");
if (wsectors[i].flags & MSF_NOEFX)
fprintf(f, "noaudioeffects = true;\n");
if (wsectors[i].specialflags & SSF_NOSTEPUP)
fprintf(f, "nostepup = true;\n");
if (wsectors[i].specialflags & SSF_DOUBLESTEPUP)
@ -3133,14 +3148,20 @@ static void P_WriteTextmap(void)
fprintf(f, "yellowpogospring = true;\n");
if (wsectors[i].specialflags & SSF_FAN)
fprintf(f, "fan = true;\n");
if (wsectors[i].specialflags & SSF_FINISHLINE)
fprintf(f, "finishline = true;\n");
if (wsectors[i].specialflags & SSF_ZOOMTUBESTART)
fprintf(f, "zoomtubestart = true;\n");
if (wsectors[i].specialflags & SSF_ZOOMTUBEEND)
fprintf(f, "zoomtubeend = true;\n");
if (wsectors[i].specialflags & SSF_FINISHLINE)
fprintf(f, "finishline = true;\n");
if (wsectors[i].specialflags & SSF_NOPHYSICSFLOOR)
fprintf(f, "nophysics_floor = true;\n");
if (wsectors[i].specialflags & SSF_NOPHYSICSCEILING)
fprintf(f, "nophysics_ceiling = true;\n");
if (wsectors[i].specialflags & SSF_GRAVITYOVERRIDE)
fprintf(f, "gravityoverride = true;\n");
if (wsectors[i].specialflags & SSF_WALLTRANSFER)
fprintf(f, "walltransfer = true;\n");
if (wsectors[i].friction != ORIG_FRICTION)
fprintf(f, "friction = %f;\n", FIXED_TO_FLOAT(wsectors[i].friction));
if (wsectors[i].gravity != FRACUNIT)

View file

@ -6956,6 +6956,10 @@ void P_InitSpecials(void)
// Set weather
curWeather = globalweather = mapheaderinfo[gamemap-1]->weather;
// Set global EFX
S_DeleteGlobalEFX();
S_CreateGlobalEFX(mapheaderinfo[gamemap-1]->globalEFX);
}
void P_ApplyFlatAlignment(sector_t *sector, angle_t flatangle, fixed_t xoffs, fixed_t yoffs, boolean floor, boolean ceiling)

View file

@ -363,6 +363,8 @@ typedef enum
MSF_FLATLIGHTING = 1<<13,
// force it on (even if it was disabled)
MSF_DIRECTIONLIGHTING = 1<<14,
// Disable Audio EFX
MSF_NOEFX = 1<<15,
} sectorflags_t;
// Per-sector bot controller override

View file

@ -745,7 +745,7 @@ void S_StartSoundAtVolumeEx(const void *origin_p, sfxenum_t sfx_id, INT32 volume
channels[cnum].efx = NULL;
}
channels[cnum].handle = I_StartSound(sfx_id, S_GetSoundVolume(sfx, volume), sep, pitch, priority, cnum, channels[cnum].efx);
channels[cnum].handle = I_StartSound(sfx_id, S_GetSoundVolume(sfx, volume), sep, pitch, priority, cnum, channels[cnum].efx, channels[cnum].origin);
}
}
@ -979,7 +979,7 @@ notinlevel:
if (audible)
{
I_UpdateSoundParams(c->handle, S_GetSoundVolume(c->sfxinfo, volume), sep, pitch, c->efx);
I_UpdateSoundParams(c->handle, S_GetSoundVolume(c->sfxinfo, volume), sep, pitch, c->efx, c->origin);
}
else
S_StopChannel(cnum);
@ -2884,6 +2884,7 @@ static void Command_RestartAudio_f(void)
S_StopMusic();
S_StopSounds();
S_ClearSfx();
S_DeleteGlobalEFX();
I_ShutdownMusic();
I_ShutdownSound();
I_StartupSound();
@ -2897,7 +2898,10 @@ static void Command_RestartAudio_f(void)
S_StartSound(NULL, sfx_strpst);
if (Playing()) // Gotta make sure the player is in a level
{
S_CreateGlobalEFX(mapheaderinfo[gamemap-1]->globalEFX);
P_RestoreMusic(&players[consoleplayer]);
}
else
M_ChangeMenuMusic();
}
@ -2989,3 +2993,13 @@ void S_InitEFXArray(efx_t *efx)
efx->var7 = efx->var8 = efx->var9 = -255;
efx->var10 = efx->var11 = efx->var12 = efx->var13 = -255;
}
void S_CreateGlobalEFX(efx_t *efx)
{
I_CreateGlobalEFX(efx);
}
void S_DeleteGlobalEFX(void)
{
I_DeleteGlobalEFX();
}

View file

@ -353,7 +353,10 @@ void S_StartSoundName(void *mo, const char *soundname);
void S_StopSoundByID(void *origin, sfxenum_t sfx_id);
void S_StopSoundByNum(sfxenum_t sfxnum);
// EFX
void S_InitEFXArray(efx_t *efx);
void S_CreateGlobalEFX(efx_t *efx);
void S_DeleteGlobalEFX(void);
#ifndef HW3SOUND
#define S_StartAttackSound S_StartSound

View file

@ -79,6 +79,7 @@ typedef enum
#include "../i_threads.h"
#include "../i_system.h" // I_Sleep
#include "../fastcmp.h"
#include "../r_defs.h"
#include <SDL3/SDL.h>
@ -143,6 +144,13 @@ static void (*fading_callback)(void);
static boolean fading_do_callback;
static boolean fading_nocleanup;
static void SoundEFX_OnChange(void)
{
COM_ImmedExecute("restartaudio");
}
consvar_t cv_soundefx = CVAR_INIT ("soundefx", "On", CV_SAVE|CV_CALL|CV_NOINIT, CV_OnOff, SoundEFX_OnChange);
// any access (read/write) to this struct MUST lock the mutex
typedef struct audiostate_s
{
@ -159,6 +167,13 @@ typedef struct audiostate_s
float loop_point;
boolean looping;
struct
{
boolean enabled;
ALuint effect;
ALuint slot;
} globalefx;
boolean startplay;
boolean shutdown;
} audiostate_t;
@ -976,11 +991,14 @@ void I_FreeSfx(sfxinfo_t *sfx)
sfx->lumpnum = LUMPERROR;
}
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t *efx)
void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t *efx, const void *origin)
{
LOCKAUDIO;
if (handle == INVALID_HANDLE)
return;
const mobj_t *originmobj = (const mobj_t *)origin;
ALuint source = handle;
TRY(alSourcef, source, AL_GAIN, sfx_volume * (vol / 255.0f));
TRY(alSourcef, source, AL_PITCH, pitch / 128.0f);
@ -996,13 +1014,23 @@ void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t
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))
if (cv_soundefx.value && !dedicated)
{
TRY(alSource3i, source, AL_AUXILIARY_SEND_FILTER, efx->slot, 0, AL_FILTER_NULL);
if (efx != NULL && TRY(alIsEffect, efx->effect) && TRY(alIsAuxiliaryEffectSlot, efx->slot))
{
TRY(alSource3i, source, AL_AUXILIARY_SEND_FILTER, efx->slot, 0, AL_FILTER_NULL);
}
else if ((((originmobj != NULL) && originmobj->type && originmobj->subsector->sector->flags & MSF_NOEFX) || (origin != NULL))
&& audio.globalefx.enabled
&& TRY(alIsEffect, audio.globalefx.effect)
&& TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot))
{
TRY(alSource3i, source, AL_AUXILIARY_SEND_FILTER, audio.globalefx.slot, 0, AL_FILTER_NULL);
}
}
}
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel, efx_t *efx)
INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priority, INT32 channel, efx_t *efx, const void * origin)
{
ALuint source;
if (!TRY(alGenSources, 1, &source))
@ -1020,7 +1048,7 @@ INT32 I_StartSound(sfxenum_t id, UINT8 vol, UINT8 sep, UINT8 pitch, UINT8 priori
return INVALID_HANDLE;
}
I_UpdateSoundParams(source, vol, sep, pitch, efx);
I_UpdateSoundParams(source, vol, sep, pitch, efx, origin);
if (!TRY(alSourcePlay, source))
{
@ -1895,10 +1923,142 @@ boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
return false;
}
static void I_HandleEFXType(efx_t *efx, ALuint effect)
{
switch (efx->type)
{
case EFFECT_REVERB:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_REVERB_DENSITY, efx->var1);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_REVERB_DIFFUSION, efx->var2);
if (efx->var3 != -255)
TRY(alEffectf, effect, AL_REVERB_GAIN, efx->var3);
if (efx->var4 != -255)
TRY(alEffectf, effect, AL_REVERB_GAINHF, efx->var4);
if (efx->var5 != -255)
TRY(alEffectf, effect, AL_REVERB_DECAY_TIME, efx->var5);
if (efx->var6 != -255)
TRY(alEffectf, effect, AL_REVERB_DECAY_HFRATIO, efx->var6);
if (efx->var7 != -255)
TRY(alEffectf, effect, AL_REVERB_REFLECTIONS_GAIN, efx->var7);
if (efx->var8 != -255)
TRY(alEffectf, effect, AL_REVERB_REFLECTIONS_DELAY, efx->var8);
if (efx->var9 != -255)
TRY(alEffectf, effect, AL_REVERB_LATE_REVERB_GAIN, efx->var9);
if (efx->var10 != -255)
TRY(alEffectf, effect, AL_REVERB_LATE_REVERB_DELAY, efx->var10);
if (efx->var11 != -255)
TRY(alEffectf, effect, AL_REVERB_AIR_ABSORPTION_GAINHF, efx->var11);
if (efx->var12 != -255)
TRY(alEffectf, effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, efx->var12);
if (efx->var13 != -255)
TRY(alEffectf, effect, AL_REVERB_ROOM_ROLLOFF_FACTOR, efx->var13);
break;
case EFFECT_CHORUS:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_CHORUS_WAVEFORM, efx->var1);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_CHORUS_PHASE, efx->var2);
if (efx->var3 != -255)
TRY(alEffectf, effect, AL_CHORUS_RATE, efx->var3);
if (efx->var4 != -255)
TRY(alEffectf, effect, AL_CHORUS_DEPTH, efx->var4);
if (efx->var5 != -255)
TRY(alEffectf, effect, AL_CHORUS_FEEDBACK, efx->var5);
if (efx->var6 != -255)
TRY(alEffectf, effect, AL_CHORUS_DELAY, efx->var6);
break;
case EFFECT_DISTORTION:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_DISTORTION_EDGE, efx->var1);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_DISTORTION_GAIN, efx->var2);
if (efx->var3 != -255)
TRY(alEffectf, effect, AL_DISTORTION_LOWPASS_CUTOFF, efx->var3);
if (efx->var4 != -255)
TRY(alEffectf, effect, AL_DISTORTION_EQCENTER, efx->var4);
if (efx->var5 != -255)
TRY(alEffectf, effect, AL_DISTORTION_EQBANDWIDTH, efx->var5);
break;
case EFFECT_ECHO:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_ECHO);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_ECHO_DELAY, efx->var1);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_ECHO_LRDELAY, efx->var2);
if (efx->var3 != -255)
TRY(alEffectf, effect, AL_ECHO_DAMPING, efx->var3);
if (efx->var4 != -255)
TRY(alEffectf, effect, AL_ECHO_FEEDBACK, efx->var4);
if (efx->var5 != -255)
TRY(alEffectf, effect, AL_ECHO_SPREAD, efx->var5);
break;
case EFFECT_PITCHSHIFT:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_PITCH_SHIFTER_COARSE_TUNE, efx->var1);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_PITCH_SHIFTER_FINE_TUNE , efx->var2);
break;
case EFFECT_RINGMOD:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_RING_MODULATOR_FREQUENCY, efx->var1);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_RING_MODULATOR_HIGHPASS_CUTOFF, efx->var2);
if (efx->var3 != -255)
TRY(alEffectf, effect, AL_RING_MODULATOR_WAVEFORM, efx->var3);
break;
case EFFECT_COMPRESSOR:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_COMPRESSOR_ONOFF, efx->var1);
break;
case EFFECT_EQ:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
if (efx->var1 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_LOW_GAIN, efx->var1);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_LOW_CUTOFF, efx->var2);
if (efx->var3 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_MID1_GAIN, efx->var3);
if (efx->var4 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_MID1_CENTER, efx->var4);
if (efx->var5 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_MID1_WIDTH, efx->var5);
if (efx->var6 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_MID2_GAIN, efx->var6);
if (efx->var7 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_MID2_CENTER, efx->var7);
if (efx->var8 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_MID2_WIDTH, efx->var8);
if (efx->var9 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_HIGH_GAIN, efx->var9);
if (efx->var10 != -255)
TRY(alEffectf, effect, AL_EQUALIZER_HIGH_CUTOFF, efx->var10);
break;
}
}
efx_t *I_CreateEFX(efx_t *efx)
{
LOCKAUDIO;
if (!cv_soundefx.value || dedicated)
return NULL;
efx_t *efxc = Z_Calloc(sizeof(efx_t), PU_STATIC, NULL);
if (efxc == NULL)
@ -1913,134 +2073,7 @@ efx_t *I_CreateEFX(efx_t *efx)
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_CHORUS:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_CHORUS_WAVEFORM, efxc->var1);
if (efxc->var2 != -255)
TRY(alEffectf, efxc->effect, AL_CHORUS_PHASE, efxc->var2);
if (efxc->var3 != -255)
TRY(alEffectf, efxc->effect, AL_CHORUS_RATE, efxc->var3);
if (efxc->var4 != -255)
TRY(alEffectf, efxc->effect, AL_CHORUS_DEPTH, efxc->var4);
if (efxc->var5 != -255)
TRY(alEffectf, efxc->effect, AL_CHORUS_FEEDBACK, efxc->var5);
if (efxc->var6 != -255)
TRY(alEffectf, efxc->effect, AL_CHORUS_DELAY, efxc->var6);
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;
case EFFECT_ECHO:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_ECHO);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_ECHO_DELAY, efxc->var1);
if (efxc->var2 != -255)
TRY(alEffectf, efxc->effect, AL_ECHO_LRDELAY, efxc->var2);
if (efxc->var3 != -255)
TRY(alEffectf, efxc->effect, AL_ECHO_DAMPING, efxc->var3);
if (efxc->var4 != -255)
TRY(alEffectf, efxc->effect, AL_ECHO_FEEDBACK, efxc->var4);
if (efxc->var5 != -255)
TRY(alEffectf, efxc->effect, AL_ECHO_SPREAD, efxc->var5);
break;
case EFFECT_PITCHSHIFT:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_PITCH_SHIFTER_COARSE_TUNE, efxc->var1);
if (efxc->var2 != -255)
TRY(alEffectf, efxc->effect, AL_PITCH_SHIFTER_FINE_TUNE , efxc->var2);
break;
case EFFECT_RINGMOD:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_RING_MODULATOR_FREQUENCY, efxc->var1);
if (efxc->var2 != -255)
TRY(alEffectf, efxc->effect, AL_RING_MODULATOR_HIGHPASS_CUTOFF, efxc->var2);
if (efxc->var3 != -255)
TRY(alEffectf, efxc->effect, AL_RING_MODULATOR_WAVEFORM, efxc->var3);
break;
case EFFECT_COMPRESSOR:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_COMPRESSOR_ONOFF, efxc->var1);
break;
case EFFECT_EQ:
TRY(alEffecti, efxc->effect, AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
if (efxc->var1 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_LOW_GAIN, efxc->var1);
if (efxc->var2 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_LOW_CUTOFF, efxc->var2);
if (efxc->var3 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_MID1_GAIN, efxc->var3);
if (efxc->var4 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_MID1_CENTER, efxc->var4);
if (efxc->var5 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_MID1_WIDTH, efxc->var5);
if (efxc->var6 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_MID2_GAIN, efxc->var6);
if (efxc->var7 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_MID2_CENTER, efxc->var7);
if (efxc->var8 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_MID2_WIDTH, efxc->var8);
if (efxc->var9 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_HIGH_GAIN, efxc->var9);
if (efxc->var10 != -255)
TRY(alEffectf, efxc->effect, AL_EQUALIZER_HIGH_CUTOFF, efxc->var10);
break;
}
I_HandleEFXType(efxc, efxc->effect);
TRY(alAuxiliaryEffectSloti, efxc->slot, AL_EFFECTSLOT_EFFECT, efxc->effect);
return efxc;
@ -2055,6 +2088,9 @@ float I_GetEFXTail(efx_t *efx)
{
LOCKAUDIO;
if (!cv_soundefx.value || dedicated)
return 0;
if (efx == NULL)
return 0;
@ -2096,4 +2132,59 @@ void I_DeleteEFX(efx_t *efx)
Z_Free(efx);
}
void I_CreateGlobalEFX(efx_t *efx)
{
LOCKAUDIO;
if (!cv_soundefx.value || dedicated)
return;
if (efx == NULL)
return;
// Init effects and slots.
TRY(alGenEffects, 1, &audio.globalefx.effect);
TRY(alGenAuxiliaryEffectSlots, 1, &audio.globalefx.slot);
if (TRY(alIsEffect, audio.globalefx.effect) && TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot))
{
I_HandleEFXType(efx, audio.globalefx.effect);
TRY(alAuxiliaryEffectSloti, audio.globalefx.slot, AL_EFFECTSLOT_EFFECT, audio.globalefx.effect);
audio.globalefx.enabled = true;
return;
}
if (TRY(alIsEffect, audio.globalefx.effect))
{
TRY(alDeleteEffects, 1, &audio.globalefx.effect);
}
if (TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot))
{
TRY(alDeleteAuxiliaryEffectSlots, 1, &audio.globalefx.slot);
}
audio.globalefx.enabled = false;
}
void I_DeleteGlobalEFX(void)
{
LOCKAUDIO;
if (audio.globalefx.enabled == false)
return;
if (TRY(alIsEffect, audio.globalefx.effect))
{
TRY(alDeleteEffects, 1, &audio.globalefx.effect);
}
if (TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot))
{
TRY(alDeleteAuxiliaryEffectSlots, 1, &audio.globalefx.slot);
}
audio.globalefx.enabled = false;
}
#endif // defined(HAVE_OPENAL)