OpenAL EFX: Refactor EFX parameters, general cleanup, and debug

All that is left to do is Lua exposure and proper value clamping for Lua and SOC.
This commit is contained in:
NepDisk 2026-03-23 18:33:10 -04:00
parent 8942924a03
commit dba734515f
11 changed files with 954 additions and 207 deletions

View file

@ -804,6 +804,454 @@ static mapheader_lighting_t *usemaplighting(INT32 mapnum, const char *word)
} }
} }
static void processvector(char *word2, f_vector3_t *vec, SINT8 num)
{
char *tmp = strtok(word2,",");
float vector[num];
int i = 0;
do {
if (i >= num)
break;
vector[i++] = atof(tmp);
} while ((tmp = strtok(NULL, ",")) != NULL);
vec->x = vector[0];
vec->y = vector[1];
vec->z = vector[2];
}
// Handle parsing globalefx info
static void globalmapefxparameters(INT32 mapnum, INT32 i, char *word, char *word2)
{
// Take off GLOBALEFX_
word += 10;
// Check and take off effect name
if (fastncmp(word, "EAXREVERB_", 10))
{
word += 10;
if (fastcmp(word, "DENSITY"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.density = atof(word2);
}
else if (fastcmp(word, "DIFFUSION"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.diffusion = atof(word2);
}
else if (fastcmp(word, "GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.gain = atof(word2);
}
else if (fastcmp(word, "GAINHF"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.gainhf = atof(word2);
}
else if (fastcmp(word, "GAINLF"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.gainlf = atof(word2);
}
else if (fastcmp(word, "DECAY_TIME"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.decay_time = atof(word2);
}
else if (fastcmp(word, "DECAY_HFRATIO"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.decay_hfratio = atof(word2);
}
else if (fastcmp(word, "DECAY_LFRATIO"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.decay_lfratio = atof(word2);
}
else if (fastcmp(word, "REFLECTIONS_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.reflections_gain = atof(word2);
}
else if (fastcmp(word, "REFLECTIONS_DELAY"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.reflections_delay = atof(word2);
}
else if (fastcmp(word, "REFLECTIONS_PAN"))
{
processvector(word2, &mapheaderinfo[mapnum]->globalEFX->eaxreverb.reflections_pan, 3);
}
else if (fastcmp(word, "LATE_REVERB_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.late_reverb_gain = atof(word2);
}
else if (fastcmp(word, "LATE_REVERB_DELAY"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.late_reverb_gain = atof(word2);
}
else if (fastcmp(word, "LATE_REVERB_PAN"))
{
processvector(word2, &mapheaderinfo[mapnum]->globalEFX->eaxreverb.late_reverb_pan, 3);
}
else if (fastcmp(word, "ECHO_TIME"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.echo_time = atof(word2);
}
else if (fastcmp(word, "ECHO_DEPTH"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.echo_depth = atof(word2);
}
else if (fastcmp(word, "MODULATION_TIME"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.modulation_time = atof(word2);
}
else if (fastcmp(word, "MODULATION_DEPTH"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.modulation_depth = atof(word2);
}
else if (fastcmp(word, "AIR_ABSORPTION_GAINHF"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.air_absorption_gainhf = atof(word2);
}
else if (fastcmp(word, "HFREFERENCE"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.hfreference = atof(word2);
}
else if (fastcmp(word, "LFREFERENCE"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.lfreference = atof(word2);
}
else if (fastcmp(word, "ROOM_ROLLOFF_FACTOR"))
{
mapheaderinfo[mapnum]->globalEFX->eaxreverb.room_rolloff_factor = atof(word2);
}
else if (fastcmp(word, "DECAY_HFLIMIT"))
{
if (i || word2[0] == 'T' || word2[0] == 'O')
mapheaderinfo[mapnum]->globalEFX->eaxreverb.decay_hflimit = 1;
else
mapheaderinfo[mapnum]->globalEFX->eaxreverb.decay_hflimit = 0;
}
}
else if (fastncmp(word, "REVERB_", 7))
{
word += 7;
if (fastcmp(word, "DENSITY"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.density = atof(word2);
}
else if (fastcmp(word, "DIFFUSION"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.diffusion = atof(word2);
}
else if (fastcmp(word, "GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.gain = atof(word2);
}
else if (fastcmp(word, "GAINHF"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.gainhf = atof(word2);
}
else if (fastcmp(word, "DECAY_TIME"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.decay_time = atof(word2);
}
else if (fastcmp(word, "DECAY_HFRATIO"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.decay_hfratio = atof(word2);
}
else if (fastcmp(word, "REFLECTIONS_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.reflections_gain = atof(word2);
}
else if (fastcmp(word, "REFLECTIONS_DELAY"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.reflections_delay = atof(word2);
}
else if (fastcmp(word, "LATE_REVERB_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.late_reverb_gain = atof(word2);
}
else if (fastcmp(word, "LATE_REVERB_DELAY"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.late_reverb_delay = atof(word2);
}
else if (fastcmp(word, "AIR_ABSORPTION_GAINHF"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.air_absorption_gainhf = atof(word2);
}
else if (fastcmp(word, "ROOM_ROLLOFF_FACTOR"))
{
mapheaderinfo[mapnum]->globalEFX->reverb.room_rolloff_factor = atof(word2);
}
else if (fastcmp(word, "DECAY_HFLIMIT"))
{
if (i || word2[0] == 'T' || word2[0] == 'O')
mapheaderinfo[mapnum]->globalEFX->reverb.decay_hflimit = 1;
else
mapheaderinfo[mapnum]->globalEFX->reverb.decay_hflimit = 0;
}
}
else if (fastncmp(word, "CHORUS_", 7))
{
word += 7;
if (fastcmp(word, "WAVEFORM"))
{
mapheaderinfo[mapnum]->globalEFX->chorus.waveform = get_number(word2);
}
else if (fastcmp(word, "PHASE"))
{
mapheaderinfo[mapnum]->globalEFX->chorus.phase = i;
}
else if (fastcmp(word, "RATE"))
{
mapheaderinfo[mapnum]->globalEFX->chorus.rate = atof(word2);
}
else if (fastcmp(word, "DEPTH"))
{
mapheaderinfo[mapnum]->globalEFX->chorus.depth = atof(word2);
}
else if (fastcmp(word, "FEEDBACK"))
{
mapheaderinfo[mapnum]->globalEFX->chorus.feedback = atof(word2);
}
else if (fastcmp(word, "DELAY"))
{
mapheaderinfo[mapnum]->globalEFX->chorus.delay = atof(word2);
}
}
else if (fastncmp(word, "DISTORTION_", 11))
{
word += 11;
if (fastcmp(word, "EDGE"))
{
mapheaderinfo[mapnum]->globalEFX->distortion.edge = atof(word2);
}
else if (fastcmp(word, "GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->distortion.gain = atof(word2);
}
else if (fastcmp(word, "LOWPASS_CUTOFF"))
{
mapheaderinfo[mapnum]->globalEFX->distortion.lowpass_cutoff = atof(word2);
}
else if (fastcmp(word, "EQCENTER"))
{
mapheaderinfo[mapnum]->globalEFX->distortion.eqcenter = atof(word2);
}
else if (fastcmp(word, "EQBANDWIDTH"))
{
mapheaderinfo[mapnum]->globalEFX->distortion.eqbandwidth = atof(word2);
}
}
else if (fastncmp(word, "ECHO_", 5))
{
word += 5;
if (fastcmp(word, "DELAY"))
{
mapheaderinfo[mapnum]->globalEFX->echo.delay = atof(word2);
}
else if (fastcmp(word, "LRDELAY"))
{
mapheaderinfo[mapnum]->globalEFX->echo.lrdelay = atof(word2);
}
else if (fastcmp(word, "DAMPING"))
{
mapheaderinfo[mapnum]->globalEFX->echo.damping = atof(word2);
}
else if (fastcmp(word, "FEEDBACK"))
{
mapheaderinfo[mapnum]->globalEFX->echo.feedback = atof(word2);
}
else if (fastcmp(word, "SPREAD"))
{
mapheaderinfo[mapnum]->globalEFX->echo.spread = atof(word2);
}
}
else if (fastncmp(word, "FLANGER_", 8))
{
word += 8;
if (fastcmp(word, "WAVEFORM"))
{
mapheaderinfo[mapnum]->globalEFX->flanger.waveform = get_number(word2);
}
else if (fastcmp(word, "PHASE"))
{
mapheaderinfo[mapnum]->globalEFX->flanger.phase = i;
}
else if (fastcmp(word, "RATE"))
{
mapheaderinfo[mapnum]->globalEFX->flanger.rate = atof(word2);
}
else if (fastcmp(word, "DEPTH"))
{
mapheaderinfo[mapnum]->globalEFX->flanger.depth = atof(word2);
}
else if (fastcmp(word, "FEEDBACK"))
{
mapheaderinfo[mapnum]->globalEFX->flanger.feedback = atof(word2);
}
else if (fastcmp(word, "DELAY"))
{
mapheaderinfo[mapnum]->globalEFX->flanger.delay = atof(word2);
}
}
else if (fastncmp(word, "FREQSHIFT_", 10))
{
word += 10;
if (fastcmp(word, "FREQUENCY"))
{
mapheaderinfo[mapnum]->globalEFX->freqshift.frequency = atof(word2);
}
else if (fastcmp(word, "LEFT_DIRECTION"))
{
mapheaderinfo[mapnum]->globalEFX->freqshift.left_direction = get_number(word2);
}
else if (fastcmp(word, "RIGHT_DIRECTION"))
{
mapheaderinfo[mapnum]->globalEFX->freqshift.right_direction = get_number(word2);
}
}
else if (fastncmp(word, "VOCALMORPH_", 11))
{
word += 11;
if (fastcmp(word, "PHONEMEA"))
{
mapheaderinfo[mapnum]->globalEFX->vocal_morpher.phonemea = i;
}
else if (fastcmp(word, "PHONEMEB"))
{
mapheaderinfo[mapnum]->globalEFX->vocal_morpher.phonemeb = i;
}
else if (fastcmp(word, "PHONEMEA_COARSE_TUNING"))
{
mapheaderinfo[mapnum]->globalEFX->vocal_morpher.phonemea_coarse_tuning = i;
}
else if (fastcmp(word, "PHONEMEB_COARSE_TUNING"))
{
mapheaderinfo[mapnum]->globalEFX->vocal_morpher.phonemeb_coarse_tuning = i;
}
else if (fastcmp(word, "WAVEFORM"))
{
mapheaderinfo[mapnum]->globalEFX->vocal_morpher.waveform = get_number(word2);
}
else if (fastcmp(word, "RATE"))
{
mapheaderinfo[mapnum]->globalEFX->vocal_morpher.rate = atof(word2);
}
}
else if (fastncmp(word, "PITCHSHIFT_", 11))
{
word += 11;
if (fastcmp(word, "COARSE_TUNE"))
{
mapheaderinfo[mapnum]->globalEFX->pitchshift.coarse_tune = i;
}
else if (fastcmp(word, "FINE_TUNE"))
{
mapheaderinfo[mapnum]->globalEFX->pitchshift.fine_tune = i;
}
}
else if (fastncmp(word, "RINGMOD_", 8))
{
word += 8;
if (fastcmp(word, "FREQUENCY"))
{
mapheaderinfo[mapnum]->globalEFX->ringmod.frequency = atof(word2);
}
else if (fastcmp(word, "HIGHPASS_CUTOFF"))
{
mapheaderinfo[mapnum]->globalEFX->ringmod.highpass_cutoff = atof(word2);
}
else if (fastcmp(word, "WAVEFORM"))
{
mapheaderinfo[mapnum]->globalEFX->ringmod.waveform = get_number(word2);
}
}
else if (fastncmp(word, "AUTOWAH_", 8))
{
word += 8;
if (fastcmp(word, "ATTACK_TIME"))
{
mapheaderinfo[mapnum]->globalEFX->autowah.attack_time = atof(word2);
}
else if (fastcmp(word, "RELEASE_TIME"))
{
mapheaderinfo[mapnum]->globalEFX->autowah.release_time = atof(word2);
}
else if (fastcmp(word, "RESONANCE"))
{
mapheaderinfo[mapnum]->globalEFX->autowah.resonance = atof(word2);
}
else if (fastcmp(word, "PEAK_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->autowah.peak_gain = atof(word2);
}
}
else if (fastncmp(word, "COMPRESSOR_", 11))
{
word += 11;
if (fastcmp(word, "ONOFF"))
{
if (i || word2[0] == 'T' || word2[0] == 'O')
mapheaderinfo[mapnum]->globalEFX->compressor.onoff = 1;
else
mapheaderinfo[mapnum]->globalEFX->compressor.onoff = 0;
}
}
else if (fastncmp(word, "EQ_", 3))
{
word += 3;
if (fastcmp(word, "LOW_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->eq.low_gain = atof(word2);
}
else if (fastcmp(word, "LOW_CUTOFF"))
{
mapheaderinfo[mapnum]->globalEFX->eq.low_cutoff = atof(word2);
}
else if (fastcmp(word, "MID1_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->eq.mid1_gain = atof(word2);
}
else if (fastcmp(word, "MID1_CENTER"))
{
mapheaderinfo[mapnum]->globalEFX->eq.mid1_center = atof(word2);
}
else if (fastcmp(word, "MID1_WIDTH"))
{
mapheaderinfo[mapnum]->globalEFX->eq.mid1_width = atof(word2);
}
else if (fastcmp(word, "MID2_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->eq.mid2_gain = atof(word2);
}
else if (fastcmp(word, "MID2_CENTER"))
{
mapheaderinfo[mapnum]->globalEFX->eq.mid2_center = atof(word2);
}
else if (fastcmp(word, "MID2_WIDTH"))
{
mapheaderinfo[mapnum]->globalEFX->eq.mid2_width = atof(word2);
}
else if (fastcmp(word, "HIGH_GAIN"))
{
mapheaderinfo[mapnum]->globalEFX->eq.high_gain = atof(word2);
}
else if (fastcmp(word, "HIGH_CUTOFF"))
{
mapheaderinfo[mapnum]->globalEFX->eq.high_cutoff = atof(word2);
}
}
}
void readlevelheader(MYFILE *f, char * name) void readlevelheader(MYFILE *f, char * name)
{ {
char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL); char *s = Z_Malloc(MAXLINELEN, PU_STATIC, NULL);
@ -1275,72 +1723,10 @@ void readlevelheader(MYFILE *f, char * name)
{ {
mapheaderinfo[num]->globalEFX->type = get_number(word2); mapheaderinfo[num]->globalEFX->type = get_number(word2);
} }
else if (fastcmp(word, "GLOBALEFXVAR1")) else if (fastncmp("GLOBALEFX_",word,10))
{ {
float flonum = atof(word2); globalmapefxparameters(num, i, word, 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 // ignored for compatibility
else if (fastcmp(word, "NEXTLEVEL") || fastcmp(word, "TIMEATTACK") || fastcmp(word, "RECORDATTACK")) else if (fastcmp(word, "NEXTLEVEL") || fastcmp(word, "TIMEATTACK") || fastcmp(word, "RECORDATTACK"))
continue; continue;

View file

@ -1869,20 +1869,41 @@ struct int_const_s const INT_CONST[] = {
{"TICCMD_USINGTILT", TICCMD_USINGTILT}, {"TICCMD_USINGTILT", TICCMD_USINGTILT},
{"TICCMD_EXCESSTILT", TICCMD_EXCESSTILT}, {"TICCMD_EXCESSTILT", TICCMD_EXCESSTILT},
// EFX // effecttypes_t
{"EFFECT_NONE", EFFECT_NONE}, {"EFFECT_NONE", EFFECT_NONE},
{"EFFECT_EAXREVERB", EFFECT_EAXREVERB},
{"EFFECT_REVERB", EFFECT_REVERB}, {"EFFECT_REVERB", EFFECT_REVERB},
{"EFFECT_CHORUS", EFFECT_CHORUS}, {"EFFECT_CHORUS", EFFECT_CHORUS},
{"EFFECT_DISTORTION", EFFECT_DISTORTION}, {"EFFECT_DISTORTION", EFFECT_DISTORTION},
{"EFFECT_ECHO", EFFECT_ECHO}, {"EFFECT_ECHO", EFFECT_ECHO},
{"EFFECT_FLANGER", EFFECT_FLANGER},
{"EFFECT_FREQSHIFT", EFFECT_FREQSHIFT},
{"EFFECT_VOCALMORPH", EFFECT_VOCALMORPH},
{"EFFECT_PITCHSHIFT", EFFECT_PITCHSHIFT}, {"EFFECT_PITCHSHIFT", EFFECT_PITCHSHIFT},
{"EFFECT_RINGMOD", EFFECT_RINGMOD}, {"EFFECT_RINGMOD", EFFECT_RINGMOD},
{"EFFECT_AUTOWAH", EFFECT_AUTOWAH},
{"EFFECT_COMPRESSOR", EFFECT_COMPRESSOR}, {"EFFECT_COMPRESSOR", EFFECT_COMPRESSOR},
{"EFFECT_EQ", EFFECT_EQ}, {"EFFECT_EQ", EFFECT_EQ},
// choruswaves_t
{"CHORUSWAVE_SINUSOID", CHORUSWAVE_SINUSOID}, {"CHORUSWAVE_SINUSOID", CHORUSWAVE_SINUSOID},
{"CHORUSWAVE_TRIANGLE", CHORUSWAVE_TRIANGLE}, {"CHORUSWAVE_TRIANGLE", CHORUSWAVE_TRIANGLE},
// flangerwaves_t
{"FLANGERWAVE_SINUSOID", FLANGERWAVE_SINUSOID},
{"FLANGERWAVE_TRIANGLE", FLANGERWAVE_TRIANGLE},
// freqshiftdirection_t
{"FREQSHIFTDIR_DOWN", FREQSHIFTDIR_DOWN},
{"FREQSHIFTDIR_UP", FREQSHIFTDIR_UP},
{"FREQSHIFTDIR_OFF", FREQSHIFTDIR_OFF},
// vocalmorphwaves_t
{"VOCALMORPH_SIN", VOCALMORPH_SIN},
{"VOCALMORPH_TRIANGLE", VOCALMORPH_TRIANGLE},
{"VOCALMORPH_SAW", VOCALMORPH_SAW},
// ringmodwaves_t
{"RINGMOD_SIN", RINGMOD_SIN}, {"RINGMOD_SIN", RINGMOD_SIN},
{"RINGMOD_SAW", RINGMOD_SAW}, {"RINGMOD_SAW", RINGMOD_SAW},
{"RINGMOD_SQUARE", RINGMOD_SQUARE}, {"RINGMOD_SQUARE", RINGMOD_SQUARE},

View file

@ -339,6 +339,7 @@ typedef enum
DBG_LUA = 0x00000800, DBG_LUA = 0x00000800,
DBG_RNG = 0x00001000, DBG_RNG = 0x00001000,
DBG_DEMO = 0x00002000, DBG_DEMO = 0x00002000,
DBG_EFX = 0x00004000,
} debugFlags_t; } debugFlags_t;
struct debugFlagNames_s struct debugFlagNames_s

View file

@ -17,6 +17,7 @@
#include "doomdef.h" #include "doomdef.h"
#include "sounds.h" #include "sounds.h"
#include "command.h" #include "command.h"
#include "m_fixed.h"
#ifdef HAVE_OPENAL #ifdef HAVE_OPENAL
#include "AL/al.h" #include "AL/al.h"
@ -48,55 +49,204 @@ typedef enum {
typedef enum typedef enum
{ {
EFFECT_NONE = 0, EFFECT_NONE = 0,
EFFECT_EAXREVERB,
EFFECT_REVERB, EFFECT_REVERB,
EFFECT_CHORUS, EFFECT_CHORUS,
EFFECT_DISTORTION, EFFECT_DISTORTION,
EFFECT_ECHO, EFFECT_ECHO,
EFFECT_FLANGER,
EFFECT_FREQSHIFT,
EFFECT_VOCALMORPH,
EFFECT_PITCHSHIFT, EFFECT_PITCHSHIFT,
EFFECT_RINGMOD, EFFECT_RINGMOD,
EFFECT_AUTOWAH,
EFFECT_COMPRESSOR, EFFECT_COMPRESSOR,
EFFECT_EQ, EFFECT_EQ,
} effecttypes_t; } effecttypes_t;
typedef enum typedef enum
{ {
#ifdef HAVE_OPENAL
CHORUSWAVE_SINUSOID = AL_CHORUS_WAVEFORM_SINUSOID,
CHORUSWAVE_TRIANGLE = AL_CHORUS_WAVEFORM_TRIANGLE,
#else
CHORUSWAVE_SINUSOID = 0, CHORUSWAVE_SINUSOID = 0,
CHORUSWAVE_TRIANGLE = 0, CHORUSWAVE_TRIANGLE = 1,
#endif
} choruswaves_t; } choruswaves_t;
typedef enum
{
FLANGERWAVE_SINUSOID = 0,
FLANGERWAVE_TRIANGLE = 1,
} flangerwaves_t;
typedef enum
{
FREQSHIFTDIR_DOWN = 0,
FREQSHIFTDIR_UP = 1,
FREQSHIFTDIR_OFF = 2,
} freqshiftdirection_t;
typedef enum
{
VOCALMORPH_SIN = 0,
VOCALMORPH_TRIANGLE = 1,
VOCALMORPH_SAW = 2,
} vocalmorphwaves_t;
typedef enum typedef enum
{ {
RINGMOD_SIN = 0, RINGMOD_SIN = 0,
RINGMOD_SAW, RINGMOD_SAW = 1,
RINGMOD_SQUARE, RINGMOD_SQUARE = 2,
} ringmodwaves_t; } ringmodwaves_t;
typedef struct typedef struct
{ {
// flags for effects
#ifdef HAVE_OPENAL #ifdef HAVE_OPENAL
ALuint effect; struct
ALuint slot; {
ALuint effect;
ALuint slot;
} al;
#endif #endif
UINT32 type; UINT32 type;
float var1;
float var2; struct
float var3; {
float var4; float density;
float var5; float diffusion;
float var6; float gain;
float var7; float gainhf;
float var8; float gainlf;
float var9; float decay_time;
float var10; float decay_hfratio;
float var11; float decay_lfratio;
float var12; float reflections_gain;
float var13; float reflections_delay;
f_vector3_t reflections_pan;
float late_reverb_gain;
float late_reverb_delay;
f_vector3_t late_reverb_pan;
float echo_time;
float echo_depth;
float modulation_time;
float modulation_depth;
float air_absorption_gainhf;
float hfreference;
float lfreference;
float room_rolloff_factor;
boolean decay_hflimit;
} eaxreverb;
struct
{
float density;
float diffusion;
float gain;
float gainhf;
float decay_time;
float decay_hfratio;
float reflections_gain;
float reflections_delay;
float late_reverb_gain;
float late_reverb_delay;
float air_absorption_gainhf;
float room_rolloff_factor;
boolean decay_hflimit;
} reverb;
struct
{
SINT8 waveform;
INT16 phase;
float rate;
float depth;
float feedback;
float delay;
} chorus;
struct
{
float edge;
float gain;
float lowpass_cutoff;
float eqcenter;
float eqbandwidth;
} distortion;
struct
{
float delay;
float lrdelay;
float damping;
float feedback;
float spread;
} echo;
struct
{
SINT8 waveform;
INT16 phase;
float rate;
float depth;
float feedback;
float delay;
} flanger;
struct
{
float frequency;
SINT8 left_direction;
SINT8 right_direction;
} freqshift;
struct
{
SINT8 phonemea;
SINT8 phonemeb;
SINT8 phonemea_coarse_tuning;
SINT8 phonemeb_coarse_tuning;
SINT8 waveform;
float rate;
} vocal_morpher;
struct
{
SINT8 coarse_tune;
SINT8 fine_tune;
} pitchshift;
struct
{
float frequency;
float highpass_cutoff;
SINT8 waveform;
} ringmod;
struct
{
float attack_time;
float release_time;
float resonance;
float peak_gain;
} autowah;
struct
{
boolean onoff;
} compressor;
struct
{
float low_gain;
float low_cutoff;
float mid1_gain;
float mid1_center;
float mid1_width;
float mid2_gain;
float mid2_center;
float mid2_width;
float high_gain;
float high_cutoff;
} eq;
} efx_t; } efx_t;
/** \brief Sound subsystem runing and waiting /** \brief Sound subsystem runing and waiting
@ -317,6 +467,8 @@ void I_DeleteEFX(efx_t *efx);
void I_CreateGlobalEFX(efx_t *efx); void I_CreateGlobalEFX(efx_t *efx);
void I_DeleteGlobalEFX(void); void I_DeleteGlobalEFX(void);
void I_InitEFXArray(efx_t *efx);
extern consvar_t cv_soundefx; extern consvar_t cv_soundefx;
#ifdef __cplusplus #ifdef __cplusplus

View file

@ -9068,7 +9068,7 @@ INT32 K_GetKartRingPower(const player_t *player, boolean boosted)
efx_t efx; efx_t efx;
S_InitEFXArray(&efx); S_InitEFXArray(&efx);
efx.type = EFFECT_REVERB; efx.type = EFFECT_REVERB;
efx.var5 = 6; efx.reverb.decay_time = 6.0;
S_StartSoundAtVolumeEx(NULL, sfx_cdfm66, 255, &efx); S_StartSoundAtVolumeEx(NULL, sfx_cdfm66, 255, &efx);
} }

View file

@ -739,6 +739,8 @@ struct debugFlagNames_s const debug_flag_names[] =
{"Randomizer", DBG_RNG}, // alt name {"Randomizer", DBG_RNG}, // alt name
{"Demo", DBG_DEMO}, {"Demo", DBG_DEMO},
{"Replay", DBG_DEMO}, // alt name {"Replay", DBG_DEMO}, // alt name
{"EFX", DBG_EFX},
{"SoundEFX", DBG_EFX}, // alt name
{NULL, 0} {NULL, 0}
}; };

View file

@ -377,6 +377,13 @@ struct vector3_t
fixed_t x, y, z; fixed_t x, y, z;
}; };
struct f_vector3_t
{
float x;
float y;
float z;
};
vector3_t *FV3_Load(vector3_t *vec, fixed_t x, fixed_t y, fixed_t z); vector3_t *FV3_Load(vector3_t *vec, fixed_t x, fixed_t y, fixed_t z);
vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z); vector3_t *FV3_UnLoad(vector3_t *vec, fixed_t *x, fixed_t *y, fixed_t *z);
vector3_t *FV3_Copy(vector3_t *a_o, const vector3_t *a_i); vector3_t *FV3_Copy(vector3_t *a_o, const vector3_t *a_i);

View file

@ -2589,4 +2589,3 @@ int M_RoundUp(double number)
return (int)number; return (int)number;
} }

View file

@ -837,7 +837,11 @@ notinlevel:
if (c->efx == NULL || c->endtime > c->efxtail + c->duration) if (c->efx == NULL || c->endtime > c->efxtail + c->duration)
{ {
//CONS_Printf("endtime: %f efxtail: %f duration: %f \n", c->endtime, c->efxtail, c->duration); if (c->efx != NULL)
{
CONS_Debug(DBG_EFX, "S_UpdateSounds: endtime: %f efxtail: %f duration: %f \n", c->endtime, c->efxtail, c->duration);
}
S_StopChannel(cnum); S_StopChannel(cnum);
} }
@ -2904,14 +2908,7 @@ void ModFilter_OnChange(void)
void S_InitEFXArray(efx_t *efx) void S_InitEFXArray(efx_t *efx)
{ {
if (efx == NULL) I_InitEFXArray(efx);
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;
} }
void S_CreateGlobalEFX(efx_t *efx) void S_CreateGlobalEFX(efx_t *efx)

View file

@ -406,6 +406,7 @@ void I_StartupSound(void)
LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv); LOAD_PROC(LPALGETAUXILIARYEFFECTSLOTFV, alGetAuxiliaryEffectSlotfv);
#undef LOAD_PROC #undef LOAD_PROC
audio.globalefx.enabled = false;
audio.music = INVALID_HANDLE; audio.music = INVALID_HANDLE;
audio.bufferindex = 0; audio.bufferindex = 0;
@ -1016,9 +1017,9 @@ void I_UpdateSoundParams(INT32 handle, UINT8 vol, UINT8 sep, UINT8 pitch, efx_t
if (cv_soundefx.value && !dedicated) if (cv_soundefx.value && !dedicated)
{ {
if (efx != NULL && TRY(alIsEffect, efx->effect) && TRY(alIsAuxiliaryEffectSlot, efx->slot)) if (efx != NULL && TRY(alIsEffect, efx->al.effect) && TRY(alIsAuxiliaryEffectSlot, efx->al.slot))
{ {
TRY(alSource3i, source, AL_AUXILIARY_SEND_FILTER, efx->slot, 0, AL_FILTER_NULL); TRY(alSource3i, source, AL_AUXILIARY_SEND_FILTER, efx->al.slot, 0, AL_FILTER_NULL);
} }
else if (origin != NULL && audio.globalefx.enabled else if (origin != NULL && audio.globalefx.enabled
&& TRY(alIsEffect, audio.globalefx.effect) && TRY(alIsEffect, audio.globalefx.effect)
@ -1910,11 +1911,11 @@ boolean I_FadeSongFromVolume(UINT8 target_volume, UINT8 source_volume, UINT32 ms
boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void)) boolean I_FadeSong(UINT8 target_volume, UINT32 ms, void (*callback)(void))
{ {
return I_FadeSongFromVolume(target_volume, (internal_volume * 100.f), ms, callback); return I_FadeSongFromVolume(target_volume, (internal_volume * 100.f), ms, callback);
} }
boolean I_FadeOutStopSong(UINT32 ms) boolean I_FadeOutStopSong(UINT32 ms)
{ {
return I_FadeSongFromVolume(0, (internal_volume * 100.f), ms, &I_StopSong); return I_FadeSongFromVolume(0, (internal_volume * 100.f), ms, &I_StopSong);
} }
boolean I_FadeInPlaySong(UINT32 ms, boolean looping) boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
@ -1925,135 +1926,173 @@ boolean I_FadeInPlaySong(UINT32 ms, boolean looping)
return false; return false;
} }
// Debugging
#define VAL(x) #x
#define APPLY_EFFECT(alEffectType, field, altype, alfield) TRY(alEffectType, effect, AL_##altype##_##alfield, efx->field); \
CONS_Debug(DBG_EFX, VAL(AL_##altype##_##alfield) ": %f\n", (float)efx->field)
#define APPLY_EFFECT_BOOL(field, altype, alfield) TRY(alEffecti, effect, AL_##altype##_##alfield, efx->field ? AL_TRUE : AL_FALSE); \
CONS_Debug(DBG_EFX, VAL(AL_##altype##_##alfield) ": %s\n", efx->field ? "TRUE" : "FALSE")
#define APPLY_EFFECT_FVEC3(alEffectType, field, altype, alfield, min, max) \
ALfloat vec3fields##alfield[3]; \
vec3fields##alfield[0] = efx->field.x; \
vec3fields##alfield[1] = efx->field.y; \
vec3fields##alfield[2] = efx->field.z; \
TRY(alEffectType, effect, AL_##altype##_##alfield, vec3fields##alfield); \
CONS_Debug(DBG_EFX, VAL(AL_##altype##_##alfield) ": x=%f y=%f z=%f\n", vec3fields##alfield[0], vec3fields##alfield[1], vec3fields##alfield[2])
static void I_HandleEFXType(efx_t *efx, ALuint effect) static void I_HandleEFXType(efx_t *efx, ALuint effect)
{ {
CONS_Debug(DBG_EFX, "Attempting to Handle EFX type.\n");
switch (efx->type) switch (efx->type)
{ {
case EFFECT_EAXREVERB:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_EAXREVERB);
APPLY_EFFECT(alEffectf, eaxreverb.density, EAXREVERB, DENSITY);
APPLY_EFFECT(alEffectf, eaxreverb.diffusion, EAXREVERB, DIFFUSION);
APPLY_EFFECT(alEffectf, eaxreverb.gain, EAXREVERB, GAIN);
APPLY_EFFECT(alEffectf, eaxreverb.gainhf, EAXREVERB, GAINHF);
APPLY_EFFECT(alEffectf, eaxreverb.gainlf, EAXREVERB, GAINLF);
APPLY_EFFECT(alEffectf, eaxreverb.decay_time, EAXREVERB, DECAY_TIME);
APPLY_EFFECT(alEffectf, eaxreverb.decay_hfratio, EAXREVERB, DECAY_HFRATIO);
APPLY_EFFECT(alEffectf, eaxreverb.decay_lfratio, EAXREVERB, DECAY_LFRATIO);
APPLY_EFFECT(alEffectf, eaxreverb.reflections_gain, EAXREVERB, REFLECTIONS_GAIN);
APPLY_EFFECT(alEffectf, eaxreverb.reflections_delay, EAXREVERB, REFLECTIONS_DELAY);
APPLY_EFFECT_FVEC3(alEffectfv, eaxreverb.reflections_pan, EAXREVERB, REFLECTIONS_PAN, -1.0, 1.0);
APPLY_EFFECT(alEffectf, eaxreverb.late_reverb_gain, EAXREVERB, LATE_REVERB_GAIN);
APPLY_EFFECT(alEffectf, eaxreverb.late_reverb_delay, EAXREVERB, LATE_REVERB_DELAY);
APPLY_EFFECT_FVEC3(alEffectfv, eaxreverb.late_reverb_pan, EAXREVERB, LATE_REVERB_PAN, -1.0, 1.0);
APPLY_EFFECT(alEffectf, eaxreverb.echo_time, EAXREVERB, ECHO_TIME);
APPLY_EFFECT(alEffectf, eaxreverb.echo_depth, EAXREVERB, ECHO_DEPTH);
APPLY_EFFECT(alEffectf, eaxreverb.modulation_time, EAXREVERB, MODULATION_TIME);
APPLY_EFFECT(alEffectf, eaxreverb.modulation_depth, EAXREVERB, MODULATION_DEPTH);
APPLY_EFFECT(alEffectf, eaxreverb.air_absorption_gainhf, EAXREVERB, AIR_ABSORPTION_GAINHF);
APPLY_EFFECT(alEffectf, eaxreverb.hfreference, EAXREVERB, HFREFERENCE);
APPLY_EFFECT(alEffectf, eaxreverb.lfreference, EAXREVERB, LFREFERENCE);
APPLY_EFFECT(alEffectf, eaxreverb.room_rolloff_factor, EAXREVERB, ROOM_ROLLOFF_FACTOR);
APPLY_EFFECT_BOOL(eaxreverb.decay_hflimit, EAXREVERB, DECAY_HFLIMIT);
break;
case EFFECT_REVERB: case EFFECT_REVERB:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
if (efx->var1 != -255) APPLY_EFFECT(alEffectf, reverb.density, REVERB, DENSITY);
TRY(alEffectf, effect, AL_REVERB_DENSITY, efx->var1); APPLY_EFFECT(alEffectf, reverb.diffusion, REVERB, DIFFUSION);
if (efx->var2 != -255) APPLY_EFFECT(alEffectf, reverb.gain, REVERB, GAIN);
TRY(alEffectf, effect, AL_REVERB_DIFFUSION, efx->var2); APPLY_EFFECT(alEffectf, reverb.gainhf, REVERB, GAINHF);
if (efx->var3 != -255) APPLY_EFFECT(alEffectf, reverb.decay_time, REVERB, DECAY_TIME);
TRY(alEffectf, effect, AL_REVERB_GAIN, efx->var3); APPLY_EFFECT(alEffectf, reverb.decay_hfratio, REVERB, DECAY_HFRATIO);
if (efx->var4 != -255) APPLY_EFFECT(alEffectf, reverb.reflections_gain, REVERB, REFLECTIONS_GAIN);
TRY(alEffectf, effect, AL_REVERB_GAINHF, efx->var4); APPLY_EFFECT(alEffectf, reverb.reflections_delay, REVERB, REFLECTIONS_DELAY);
if (efx->var5 != -255) APPLY_EFFECT(alEffectf, reverb.late_reverb_gain, REVERB, LATE_REVERB_GAIN);
TRY(alEffectf, effect, AL_REVERB_DECAY_TIME, efx->var5); APPLY_EFFECT(alEffectf, reverb.late_reverb_delay, REVERB, LATE_REVERB_DELAY);
if (efx->var6 != -255) APPLY_EFFECT(alEffectf, reverb.air_absorption_gainhf, REVERB, AIR_ABSORPTION_GAINHF);
TRY(alEffectf, effect, AL_REVERB_DECAY_HFRATIO, efx->var6); APPLY_EFFECT_BOOL(reverb.decay_hflimit, REVERB, DECAY_HFLIMIT);
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; break;
case EFFECT_CHORUS: case EFFECT_CHORUS:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_CHORUS); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_CHORUS);
if (efx->var1 != -255) APPLY_EFFECT(alEffectf, chorus.waveform, CHORUS, WAVEFORM);
TRY(alEffectf, effect, AL_CHORUS_WAVEFORM, efx->var1); APPLY_EFFECT(alEffecti, chorus.phase, CHORUS, PHASE);
if (efx->var2 != -255) APPLY_EFFECT(alEffectf, chorus.rate, CHORUS, RATE);
TRY(alEffectf, effect, AL_CHORUS_PHASE, efx->var2); APPLY_EFFECT(alEffectf, chorus.depth, CHORUS, DEPTH);
if (efx->var3 != -255) APPLY_EFFECT(alEffectf, chorus.feedback, CHORUS, FEEDBACK);
TRY(alEffectf, effect, AL_CHORUS_RATE, efx->var3); APPLY_EFFECT(alEffectf, chorus.delay, CHORUS, DELAY);
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; break;
case EFFECT_DISTORTION: case EFFECT_DISTORTION:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_DISTORTION); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_DISTORTION);
if (efx->var1 != -255) APPLY_EFFECT(alEffectf, distortion.edge, DISTORTION, EDGE);
TRY(alEffectf, effect, AL_DISTORTION_EDGE, efx->var1); APPLY_EFFECT(alEffectf, distortion.gain, DISTORTION, GAIN);
if (efx->var2 != -255) APPLY_EFFECT(alEffectf, distortion.lowpass_cutoff, DISTORTION, LOWPASS_CUTOFF);
TRY(alEffectf, effect, AL_DISTORTION_GAIN, efx->var2); APPLY_EFFECT(alEffectf, distortion.eqcenter, DISTORTION, EQCENTER);
if (efx->var3 != -255) APPLY_EFFECT(alEffectf, distortion.eqbandwidth, DISTORTION, EQBANDWIDTH);
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; break;
case EFFECT_ECHO: case EFFECT_ECHO:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_ECHO); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_ECHO);
if (efx->var1 != -255) APPLY_EFFECT(alEffectf, echo.delay, ECHO, DELAY);
TRY(alEffectf, effect, AL_ECHO_DELAY, efx->var1); APPLY_EFFECT(alEffectf, echo.lrdelay, ECHO, LRDELAY);
if (efx->var2 != -255) APPLY_EFFECT(alEffectf, echo.damping, ECHO, DAMPING);
TRY(alEffectf, effect, AL_ECHO_LRDELAY, efx->var2); APPLY_EFFECT(alEffectf, echo.feedback, ECHO, FEEDBACK);
if (efx->var3 != -255) APPLY_EFFECT(alEffectf, echo.spread, ECHO, SPREAD);
TRY(alEffectf, effect, AL_ECHO_DAMPING, efx->var3); break;
if (efx->var4 != -255) case EFFECT_FLANGER:
TRY(alEffectf, effect, AL_ECHO_FEEDBACK, efx->var4); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_FLANGER);
if (efx->var5 != -255)
TRY(alEffectf, effect, AL_ECHO_SPREAD, efx->var5); APPLY_EFFECT(alEffectf, flanger.waveform, FLANGER, WAVEFORM);
APPLY_EFFECT(alEffecti, flanger.phase, FLANGER, PHASE);
APPLY_EFFECT(alEffectf, flanger.rate, FLANGER, RATE);
APPLY_EFFECT(alEffectf, flanger.depth, FLANGER, DEPTH);
APPLY_EFFECT(alEffectf, flanger.feedback, FLANGER, FEEDBACK);
APPLY_EFFECT(alEffectf, flanger.delay, FLANGER, DELAY);
break;
case EFFECT_FREQSHIFT:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_FREQUENCY_SHIFTER);
APPLY_EFFECT(alEffectf, freqshift.frequency, FREQUENCY_SHIFTER, FREQUENCY);
APPLY_EFFECT(alEffecti, freqshift.left_direction, FREQUENCY_SHIFTER, LEFT_DIRECTION);
APPLY_EFFECT(alEffecti, freqshift.right_direction, FREQUENCY_SHIFTER, RIGHT_DIRECTION);
break;
case EFFECT_VOCALMORPH:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_VOCAL_MORPHER);
APPLY_EFFECT(alEffecti, vocal_morpher.phonemea, VOCAL_MORPHER, PHONEMEA);
APPLY_EFFECT(alEffecti, vocal_morpher.phonemeb, VOCAL_MORPHER, PHONEMEB);
APPLY_EFFECT(alEffecti, vocal_morpher.phonemea_coarse_tuning, VOCAL_MORPHER, PHONEMEA_COARSE_TUNING);
APPLY_EFFECT(alEffecti, vocal_morpher.phonemeb_coarse_tuning, VOCAL_MORPHER, PHONEMEB_COARSE_TUNING);
APPLY_EFFECT(alEffecti, vocal_morpher.waveform, VOCAL_MORPHER, WAVEFORM);
APPLY_EFFECT(alEffectf, vocal_morpher.rate, VOCAL_MORPHER, RATE);
break; break;
case EFFECT_PITCHSHIFT: case EFFECT_PITCHSHIFT:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_PITCH_SHIFTER);
if (efx->var1 != -255) APPLY_EFFECT(alEffecti, pitchshift.coarse_tune, PITCH_SHIFTER, COARSE_TUNE);
TRY(alEffectf, effect, AL_PITCH_SHIFTER_COARSE_TUNE, efx->var1); APPLY_EFFECT(alEffecti, pitchshift.fine_tune, PITCH_SHIFTER, FINE_TUNE);
if (efx->var2 != -255)
TRY(alEffectf, effect, AL_PITCH_SHIFTER_FINE_TUNE , efx->var2);
break; break;
case EFFECT_RINGMOD: case EFFECT_RINGMOD:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_RING_MODULATOR);
if (efx->var1 != -255) APPLY_EFFECT(alEffectf, ringmod.frequency, RING_MODULATOR, FREQUENCY);
TRY(alEffectf, effect, AL_RING_MODULATOR_FREQUENCY, efx->var1); APPLY_EFFECT(alEffectf, ringmod.highpass_cutoff, RING_MODULATOR, HIGHPASS_CUTOFF);
if (efx->var2 != -255) APPLY_EFFECT(alEffecti, ringmod.waveform, RING_MODULATOR, WAVEFORM);
TRY(alEffectf, effect, AL_RING_MODULATOR_HIGHPASS_CUTOFF, efx->var2); break;
if (efx->var3 != -255) case EFFECT_AUTOWAH:
TRY(alEffectf, effect, AL_RING_MODULATOR_WAVEFORM, efx->var3); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_AUTOWAH);
APPLY_EFFECT(alEffectf, autowah.attack_time, AUTOWAH, ATTACK_TIME);
APPLY_EFFECT(alEffectf, autowah.release_time, AUTOWAH, RELEASE_TIME);
APPLY_EFFECT(alEffectf, autowah.resonance, AUTOWAH, RESONANCE);
APPLY_EFFECT(alEffectf, autowah.peak_gain, AUTOWAH, PEAK_GAIN);
break; break;
case EFFECT_COMPRESSOR: case EFFECT_COMPRESSOR:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_COMPRESSOR);
if (efx->var1 != -255) APPLY_EFFECT(alEffectf, compressor.onoff, COMPRESSOR, ONOFF);
TRY(alEffectf, effect, AL_COMPRESSOR_ONOFF, efx->var1);
break; break;
case EFFECT_EQ: case EFFECT_EQ:
TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER); TRY(alEffecti, effect, AL_EFFECT_TYPE, AL_EFFECT_EQUALIZER);
if (efx->var1 != -255) APPLY_EFFECT(alEffectf, eq.low_gain, EQUALIZER, LOW_GAIN);
TRY(alEffectf, effect, AL_EQUALIZER_LOW_GAIN, efx->var1); APPLY_EFFECT(alEffectf, eq.low_cutoff, EQUALIZER, LOW_CUTOFF);
if (efx->var2 != -255) APPLY_EFFECT(alEffectf, eq.mid1_gain, EQUALIZER, MID1_GAIN);
TRY(alEffectf, effect, AL_EQUALIZER_LOW_CUTOFF, efx->var2); APPLY_EFFECT(alEffectf, eq.mid1_center, EQUALIZER, MID1_CENTER);
if (efx->var3 != -255) APPLY_EFFECT(alEffectf, eq.mid1_width, EQUALIZER, MID1_WIDTH);
TRY(alEffectf, effect, AL_EQUALIZER_MID1_GAIN, efx->var3); APPLY_EFFECT(alEffectf, eq.mid2_gain, EQUALIZER, MID2_GAIN);
if (efx->var4 != -255) APPLY_EFFECT(alEffectf, eq.mid2_center, EQUALIZER, MID2_CENTER);
TRY(alEffectf, effect, AL_EQUALIZER_MID1_CENTER, efx->var4); APPLY_EFFECT(alEffectf, eq.mid2_width, EQUALIZER, MID2_WIDTH);
if (efx->var5 != -255) APPLY_EFFECT(alEffectf, eq.high_gain, EQUALIZER, HIGH_GAIN);
TRY(alEffectf, effect, AL_EQUALIZER_MID1_WIDTH, efx->var5); APPLY_EFFECT(alEffectf, eq.high_cutoff, EQUALIZER, HIGH_CUTOFF);
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; break;
} }
} }
#undef APPLY_EFFECT
#undef APPLY_EFFECT_FVEC3
efx_t *I_CreateEFX(efx_t *efx) efx_t *I_CreateEFX(efx_t *efx)
{ {
LOCKAUDIO; LOCKAUDIO;
@ -2063,24 +2102,32 @@ efx_t *I_CreateEFX(efx_t *efx)
efx_t *efxc = Z_Calloc(sizeof(efx_t), PU_STATIC, NULL); efx_t *efxc = Z_Calloc(sizeof(efx_t), PU_STATIC, NULL);
CONS_Debug(DBG_EFX, "I_CreateEFX: Attempting to allocate new EFX.\n");
if (efxc == NULL) if (efxc == NULL)
I_Error("OpenAL: Ran out of memory generating EFX.\n"); I_Error("OpenAL: Ran out of memory generating EFX.\n");
if (efx != NULL) if (efx != NULL)
{
memcpy(efxc, efx, sizeof(efx_t)); memcpy(efxc, efx, sizeof(efx_t));
CONS_Debug(DBG_EFX, "I_CreateEFX: Given EFX exists, attempt to copy its data over.\n");
}
// Init effects and slots. // Init effects and slots.
TRY(alGenEffects, 1, &efxc->effect); CONS_Debug(DBG_EFX, "I_CreateEFX: Generating Effect and Slot.\n");
TRY(alGenAuxiliaryEffectSlots, 1, &efxc->slot); TRY(alGenEffects, 1, &efxc->al.effect);
TRY(alGenAuxiliaryEffectSlots, 1, &efxc->al.slot);
if (TRY(alIsEffect, efxc->effect) && TRY(alIsAuxiliaryEffectSlot, efxc->slot)) if (TRY(alIsEffect, efxc->al.effect) && TRY(alIsAuxiliaryEffectSlot, efxc->al.slot))
{ {
I_HandleEFXType(efxc, efxc->effect); CONS_Debug(DBG_EFX, "I_CreateEFX: Effect and Slot successfully created.\n");
I_HandleEFXType(efxc, efxc->al.effect);
TRY(alAuxiliaryEffectSloti, efxc->slot, AL_EFFECTSLOT_EFFECT, efxc->effect); TRY(alAuxiliaryEffectSloti, efxc->al.slot, AL_EFFECTSLOT_EFFECT, efxc->al.effect);
return efxc; return efxc;
} }
CONS_Debug(DBG_EFX, "I_CreateEFX: Effect or Slot failed to be created, freeing.\n");
Z_Free(efxc); Z_Free(efxc);
return NULL; return NULL;
@ -2100,10 +2147,7 @@ float I_GetEFXTail(efx_t *efx)
switch(efx->type) switch(efx->type)
{ {
case EFFECT_REVERB: case EFFECT_REVERB:
if (efx->var5 != 255) tailtime = efx->reverb.decay_time;
tailtime = efx->var5;
else
tailtime = 1.49;
break; break;
default: default:
@ -2111,6 +2155,7 @@ float I_GetEFXTail(efx_t *efx)
break; break;
} }
CONS_Debug(DBG_EFX, "I_GetEFXTail: EFX tail is %f aka %f.\n", tailtime, tailtime*TICRATE);
return tailtime*TICRATE; return tailtime*TICRATE;
} }
@ -2121,16 +2166,19 @@ void I_DeleteEFX(efx_t *efx)
if (efx == NULL) if (efx == NULL)
return; return;
if (TRY(alIsEffect, efx->effect)) if (TRY(alIsEffect, efx->al.effect))
{ {
TRY(alDeleteEffects, 1, &efx->effect); CONS_Debug(DBG_EFX, "I_DeleteEFX: Effect exists, attempting to delete.\n");
TRY(alDeleteEffects, 1, &efx->al.effect);
} }
if (TRY(alIsAuxiliaryEffectSlot, efx->slot)) if (TRY(alIsAuxiliaryEffectSlot, efx->al.slot))
{ {
TRY(alDeleteAuxiliaryEffectSlots, 1, &efx->slot); CONS_Debug(DBG_EFX, "I_DeleteEFX: Slot exists, attempting to delete.\n");
TRY(alDeleteAuxiliaryEffectSlots, 1, &efx->al.slot);
} }
CONS_Debug(DBG_EFX, "I_DeleteEFX: Freeing allocated memory.\n");
Z_Free(efx); Z_Free(efx);
} }
@ -2145,27 +2193,36 @@ void I_CreateGlobalEFX(efx_t *efx)
return; return;
// Init effects and slots. // Init effects and slots.
CONS_Debug(DBG_EFX, "I_CreateGlobalEFX: Generating Effect and Slot.\n");
TRY(alGenEffects, 1, &audio.globalefx.effect); TRY(alGenEffects, 1, &audio.globalefx.effect);
TRY(alGenAuxiliaryEffectSlots, 1, &audio.globalefx.slot); TRY(alGenAuxiliaryEffectSlots, 1, &audio.globalefx.slot);
if (TRY(alIsEffect, audio.globalefx.effect) && TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot)) if (TRY(alIsEffect, audio.globalefx.effect) && TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot))
{ {
CONS_Debug(DBG_EFX, "I_CreateGlobalEFX: Effect and Slot successfully created.\n");
I_HandleEFXType(efx, audio.globalefx.effect); I_HandleEFXType(efx, audio.globalefx.effect);
TRY(alAuxiliaryEffectSloti, audio.globalefx.slot, AL_EFFECTSLOT_EFFECT, audio.globalefx.effect); TRY(alAuxiliaryEffectSloti, audio.globalefx.slot, AL_EFFECTSLOT_EFFECT, audio.globalefx.effect);
CONS_Debug(DBG_EFX, "I_CreateGlobalEFX: Global EFX enabled.\n");
audio.globalefx.enabled = true; audio.globalefx.enabled = true;
return; return;
} }
CONS_Debug(DBG_EFX, "I_CreateEFX: Effect or Slot failed to be created.\n");
if (TRY(alIsEffect, audio.globalefx.effect)) if (TRY(alIsEffect, audio.globalefx.effect))
{ {
CONS_Debug(DBG_EFX, "I_CreateGlobalEFX: Effect exists, attempting to delete.\n");
TRY(alDeleteEffects, 1, &audio.globalefx.effect); TRY(alDeleteEffects, 1, &audio.globalefx.effect);
} }
if (TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot)) if (TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot))
{ {
CONS_Debug(DBG_EFX, "I_CreateGlobalEFX: Slot exists, attempting to delete.\n");
TRY(alDeleteAuxiliaryEffectSlots, 1, &audio.globalefx.slot); TRY(alDeleteAuxiliaryEffectSlots, 1, &audio.globalefx.slot);
} }
CONS_Debug(DBG_EFX, "I_CreateGlobalEFX: Global EFX disabled.\n");
audio.globalefx.enabled = false; audio.globalefx.enabled = false;
} }
@ -2178,15 +2235,139 @@ void I_DeleteGlobalEFX(void)
if (TRY(alIsEffect, audio.globalefx.effect)) if (TRY(alIsEffect, audio.globalefx.effect))
{ {
CONS_Debug(DBG_EFX, "I_DeleteGlobalEFX: Effect exists, attempting to delete.\n");
TRY(alDeleteEffects, 1, &audio.globalefx.effect); TRY(alDeleteEffects, 1, &audio.globalefx.effect);
} }
if (TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot)) if (TRY(alIsAuxiliaryEffectSlot, audio.globalefx.slot))
{ {
CONS_Debug(DBG_EFX, "I_DeleteGlobalEFX: Slot exists, attempting to delete.\n");
TRY(alDeleteAuxiliaryEffectSlots, 1, &audio.globalefx.slot); TRY(alDeleteAuxiliaryEffectSlots, 1, &audio.globalefx.slot);
} }
CONS_Debug(DBG_EFX, "I_DeleteGlobalEFX: Global EFX disabled.\n");
audio.globalefx.enabled = false; audio.globalefx.enabled = false;
} }
#define RESET_EFFECT(field, altype, alfield) efx->field = AL_##altype##_DEFAULT_##alfield; \
CONS_Debug(DBG_EFX, VAL(AL_##altype##_##alfield) ": %f\n", (float)efx->field)
#define RESET_EFFECT_FVEC3(field, altype, alfield) efx->field.x = AL_##altype##_DEFAULT_##alfield##_XYZ; \
efx->field.y = AL_##altype##_DEFAULT_##alfield##_XYZ; \
efx->field.z = AL_##altype##_DEFAULT_##alfield##_XYZ; \
CONS_Debug(DBG_EFX, VAL(AL_##altype##_##alfield) ": x=%f y=%f z=%f\n", efx->field.x, efx->field.y, efx->field.z)
void I_InitEFXArray(efx_t *efx)
{
if (efx == NULL)
return;
efx->type = EFFECT_NONE;
CONS_Debug(DBG_EFX, "I_InitEFXArray: Resetting EFX array to defaults.\n");
RESET_EFFECT(eaxreverb.density, EAXREVERB, DENSITY);
RESET_EFFECT(eaxreverb.diffusion, EAXREVERB, DIFFUSION);
RESET_EFFECT(eaxreverb.gain, EAXREVERB, GAIN);
RESET_EFFECT(eaxreverb.gainhf, EAXREVERB, GAINHF);
RESET_EFFECT(eaxreverb.gainlf, EAXREVERB, GAINLF);
RESET_EFFECT(eaxreverb.decay_time, EAXREVERB, DECAY_TIME);
RESET_EFFECT(eaxreverb.decay_hfratio, EAXREVERB, DECAY_HFRATIO);
RESET_EFFECT(eaxreverb.decay_lfratio, EAXREVERB, DECAY_LFRATIO);
RESET_EFFECT(eaxreverb.reflections_gain, EAXREVERB, REFLECTIONS_GAIN);
RESET_EFFECT(eaxreverb.reflections_delay, EAXREVERB, REFLECTIONS_DELAY);
RESET_EFFECT_FVEC3(eaxreverb.reflections_pan, EAXREVERB, REFLECTIONS_PAN);
RESET_EFFECT(eaxreverb.late_reverb_gain, EAXREVERB, LATE_REVERB_GAIN);
RESET_EFFECT(eaxreverb.late_reverb_delay, EAXREVERB, LATE_REVERB_DELAY);
RESET_EFFECT_FVEC3(eaxreverb.late_reverb_pan, EAXREVERB, LATE_REVERB_PAN);
RESET_EFFECT(eaxreverb.echo_time, EAXREVERB, ECHO_TIME);
RESET_EFFECT(eaxreverb.echo_depth, EAXREVERB, ECHO_DEPTH);
RESET_EFFECT(eaxreverb.modulation_time, EAXREVERB, MODULATION_TIME);
RESET_EFFECT(eaxreverb.modulation_depth, EAXREVERB, MODULATION_DEPTH);
RESET_EFFECT(eaxreverb.air_absorption_gainhf, EAXREVERB, AIR_ABSORPTION_GAINHF);
RESET_EFFECT(eaxreverb.hfreference, EAXREVERB, HFREFERENCE);
RESET_EFFECT(eaxreverb.lfreference, EAXREVERB, LFREFERENCE);
RESET_EFFECT(eaxreverb.room_rolloff_factor, EAXREVERB, ROOM_ROLLOFF_FACTOR);
RESET_EFFECT(eaxreverb.decay_hflimit, EAXREVERB, DECAY_HFLIMIT);
RESET_EFFECT(reverb.density, REVERB, DENSITY);
RESET_EFFECT(reverb.diffusion, REVERB, DIFFUSION);
RESET_EFFECT(reverb.gain, REVERB, GAIN);
RESET_EFFECT(reverb.gainhf, REVERB, GAINHF);
RESET_EFFECT(reverb.decay_time, REVERB, DECAY_TIME);
RESET_EFFECT(reverb.decay_hfratio, REVERB, DECAY_HFRATIO);
RESET_EFFECT(reverb.reflections_gain, REVERB, REFLECTIONS_GAIN);
RESET_EFFECT(reverb.reflections_delay, REVERB, REFLECTIONS_DELAY);
RESET_EFFECT(reverb.late_reverb_gain, REVERB, LATE_REVERB_GAIN);
RESET_EFFECT(reverb.late_reverb_delay, REVERB, LATE_REVERB_DELAY);
RESET_EFFECT(reverb.air_absorption_gainhf, REVERB, AIR_ABSORPTION_GAINHF);
RESET_EFFECT(reverb.decay_hflimit, REVERB, DECAY_HFLIMIT);
RESET_EFFECT(chorus.waveform, CHORUS, WAVEFORM);
RESET_EFFECT(chorus.phase, CHORUS, PHASE);
RESET_EFFECT(chorus.rate, CHORUS, RATE);
RESET_EFFECT(chorus.depth, CHORUS, DEPTH);
RESET_EFFECT(chorus.feedback, CHORUS, FEEDBACK);
RESET_EFFECT(chorus.delay, CHORUS, DELAY);
RESET_EFFECT(distortion.edge, DISTORTION, EDGE);
RESET_EFFECT(distortion.gain, DISTORTION, GAIN);
RESET_EFFECT(distortion.lowpass_cutoff, DISTORTION, LOWPASS_CUTOFF);
RESET_EFFECT(distortion.eqcenter, DISTORTION, EQCENTER);
RESET_EFFECT(distortion.eqbandwidth, DISTORTION, EQBANDWIDTH);
RESET_EFFECT(echo.delay, ECHO, DELAY);
RESET_EFFECT(echo.lrdelay, ECHO, LRDELAY);
RESET_EFFECT(echo.damping, ECHO, DAMPING);
RESET_EFFECT(echo.feedback, ECHO, FEEDBACK);
RESET_EFFECT(echo.spread, ECHO, SPREAD);
RESET_EFFECT(flanger.waveform, FLANGER, WAVEFORM);
RESET_EFFECT(flanger.phase, FLANGER, PHASE);
RESET_EFFECT(flanger.rate, FLANGER, RATE);
RESET_EFFECT(flanger.depth, FLANGER, DEPTH);
RESET_EFFECT(flanger.feedback, FLANGER, FEEDBACK);
RESET_EFFECT(flanger.delay, FLANGER, DELAY);
RESET_EFFECT(freqshift.frequency, FREQUENCY_SHIFTER, FREQUENCY);
RESET_EFFECT(freqshift.left_direction, FREQUENCY_SHIFTER, LEFT_DIRECTION);
RESET_EFFECT(freqshift.right_direction, FREQUENCY_SHIFTER, RIGHT_DIRECTION);
RESET_EFFECT(vocal_morpher.phonemea, VOCAL_MORPHER, PHONEMEA);
RESET_EFFECT(vocal_morpher.phonemeb, VOCAL_MORPHER, PHONEMEB);
RESET_EFFECT(vocal_morpher.phonemea_coarse_tuning, VOCAL_MORPHER, PHONEMEA_COARSE_TUNING);
RESET_EFFECT(vocal_morpher.phonemeb_coarse_tuning, VOCAL_MORPHER, PHONEMEB_COARSE_TUNING);
RESET_EFFECT(vocal_morpher.waveform, VOCAL_MORPHER, WAVEFORM);
RESET_EFFECT(vocal_morpher.rate, VOCAL_MORPHER, RATE);
RESET_EFFECT(pitchshift.coarse_tune, PITCH_SHIFTER, COARSE_TUNE);
RESET_EFFECT(pitchshift.fine_tune, PITCH_SHIFTER, FINE_TUNE);
RESET_EFFECT(ringmod.frequency, RING_MODULATOR, FREQUENCY);
RESET_EFFECT(ringmod.highpass_cutoff, RING_MODULATOR, HIGHPASS_CUTOFF);
RESET_EFFECT(ringmod.waveform, RING_MODULATOR, WAVEFORM);
RESET_EFFECT(autowah.attack_time, AUTOWAH, ATTACK_TIME);
RESET_EFFECT(autowah.release_time, AUTOWAH, RELEASE_TIME);
RESET_EFFECT(autowah.resonance, AUTOWAH, RESONANCE);
RESET_EFFECT(autowah.peak_gain, AUTOWAH, PEAK_GAIN);
RESET_EFFECT(compressor.onoff, COMPRESSOR, ONOFF);
RESET_EFFECT(eq.low_gain, EQUALIZER, LOW_GAIN);
RESET_EFFECT(eq.low_cutoff, EQUALIZER, LOW_CUTOFF);
RESET_EFFECT(eq.mid1_gain, EQUALIZER, MID1_GAIN);
RESET_EFFECT(eq.mid1_center, EQUALIZER, MID1_CENTER);
RESET_EFFECT(eq.mid1_width, EQUALIZER, MID1_WIDTH);
RESET_EFFECT(eq.mid2_gain, EQUALIZER, MID2_GAIN);
RESET_EFFECT(eq.mid2_center, EQUALIZER, MID2_CENTER);
RESET_EFFECT(eq.mid2_width, EQUALIZER, MID2_WIDTH);
RESET_EFFECT(eq.high_gain, EQUALIZER, HIGH_GAIN);
RESET_EFFECT(eq.high_cutoff, EQUALIZER, HIGH_CUTOFF);
}
#undef RESET_EFFECT
#undef RESET_EFFECT_FVEC3
#undef VAL
#endif // defined(HAVE_OPENAL) #endif // defined(HAVE_OPENAL)

View file

@ -235,6 +235,7 @@ TYPEDEF (mdllistitem_t);
TYPEDEF (vector2_t); TYPEDEF (vector2_t);
TYPEDEF (f_vector2_t); TYPEDEF (f_vector2_t);
TYPEDEF (vector3_t); TYPEDEF (vector3_t);
TYPEDEF (f_vector3_t);
TYPEDEF (vector4_t); TYPEDEF (vector4_t);
TYPEDEF (matrix_t); TYPEDEF (matrix_t);