Added reverb sound effect

Enabled by default, can be disabled via s_reverb 0. Also by default
picks preset automatically out of 7 presets based on surrounding
size, this function can be disabled via s_reverb_preset_autopick 0.
Presets can be set manually via s_reverb_preset (0-113).

Cherrypick of ac7be51e94
This commit is contained in:
SkacikPL 2019-06-22 23:16:28 +02:00 committed by Denis Pauk
parent 66f1bc9a33
commit 93812df488
5 changed files with 439 additions and 1 deletions

View file

@ -178,6 +178,9 @@ extern cvar_t* s_underwater_gain_hf;
extern cvar_t* s_doppler;
extern cvar_t* s_occlusion;
extern cvar_t* s_occlusion_strength;
extern cvar_t* s_reverb_preset;
extern cvar_t* s_reverb_preset_autopick;
extern cvar_t* s_reverb;
extern cvar_t* s_ps_sorting;
/*

View file

@ -33,6 +33,7 @@
#include <AL/al.h>
#include <AL/efx.h>
#include "AL/efx-presets.h"
/* Function pointers used to tie
* the qal API to the OpenAL API */
@ -113,6 +114,14 @@ extern LPALGENFILTERS qalGenFilters;
extern LPALFILTERI qalFilteri;
extern LPALFILTERF qalFilterf;
extern LPALDELETEFILTERS qalDeleteFilters;
extern LPALGENEFFECTS qalGenEffects;
extern LPALEFFECTF qalEffectf;
extern LPALEFFECTI qalEffecti;
extern LPALEFFECTFV qalEffectfv;
extern LPALAUXILIARYEFFECTSLOTI qalAuxiliaryEffectSloti;
extern LPALGENAUXILIARYEFFECTSLOTS qalGenAuxiliaryEffectSlots;
extern LPALDELETEAUXILIARYEFFECTSLOTS qalDeleteAuxiliaryEffectSlots;
extern LPALDELETEEFFECTS qalDeleteEffects;
/*
* Gives information over the OpenAL

View file

@ -59,6 +59,8 @@ static ALuint s_srcnums[MAX_CHANNELS - 1];
static ALuint streamSource;
static int s_framecount;
static ALuint underwaterFilter;
static ALuint ReverbEffect;
static ALuint ReverbEffectSlot;
/* ----------------------------------------------------------------- */
@ -238,6 +240,334 @@ AL_DeleteSfx(sfx_t *s)
/* ----------------------------------------------------------------- */
static EFXEAXREVERBPROPERTIES ReverbPresets[113] = {
EFX_REVERB_PRESET_GENERIC,
EFX_REVERB_PRESET_PADDEDCELL,
EFX_REVERB_PRESET_ROOM,
EFX_REVERB_PRESET_BATHROOM,
EFX_REVERB_PRESET_LIVINGROOM,
EFX_REVERB_PRESET_STONEROOM,
EFX_REVERB_PRESET_AUDITORIUM,
EFX_REVERB_PRESET_CONCERTHALL,
EFX_REVERB_PRESET_CAVE,
EFX_REVERB_PRESET_ARENA,
EFX_REVERB_PRESET_HANGAR,
EFX_REVERB_PRESET_CARPETEDHALLWAY,
EFX_REVERB_PRESET_HALLWAY,
EFX_REVERB_PRESET_STONECORRIDOR,
EFX_REVERB_PRESET_ALLEY,
EFX_REVERB_PRESET_FOREST,
EFX_REVERB_PRESET_CITY,
EFX_REVERB_PRESET_MOUNTAINS,
EFX_REVERB_PRESET_QUARRY,
EFX_REVERB_PRESET_PLAIN,
EFX_REVERB_PRESET_PARKINGLOT,
EFX_REVERB_PRESET_SEWERPIPE,
EFX_REVERB_PRESET_UNDERWATER,
EFX_REVERB_PRESET_DRUGGED,
EFX_REVERB_PRESET_DIZZY,
EFX_REVERB_PRESET_PSYCHOTIC,
EFX_REVERB_PRESET_CASTLE_SMALLROOM,
EFX_REVERB_PRESET_CASTLE_SHORTPASSAGE,
EFX_REVERB_PRESET_CASTLE_MEDIUMROOM,
EFX_REVERB_PRESET_CASTLE_LARGEROOM,
EFX_REVERB_PRESET_CASTLE_LONGPASSAGE,
EFX_REVERB_PRESET_CASTLE_HALL,
EFX_REVERB_PRESET_CASTLE_CUPBOARD,
EFX_REVERB_PRESET_CASTLE_COURTYARD,
EFX_REVERB_PRESET_CASTLE_ALCOVE,
EFX_REVERB_PRESET_FACTORY_SMALLROOM,
EFX_REVERB_PRESET_FACTORY_SHORTPASSAGE,
EFX_REVERB_PRESET_FACTORY_MEDIUMROOM,
EFX_REVERB_PRESET_FACTORY_LARGEROOM,
EFX_REVERB_PRESET_FACTORY_LONGPASSAGE,
EFX_REVERB_PRESET_FACTORY_HALL,
EFX_REVERB_PRESET_FACTORY_CUPBOARD,
EFX_REVERB_PRESET_FACTORY_COURTYARD,
EFX_REVERB_PRESET_FACTORY_ALCOVE,
EFX_REVERB_PRESET_ICEPALACE_SMALLROOM,
EFX_REVERB_PRESET_ICEPALACE_SHORTPASSAGE,
EFX_REVERB_PRESET_ICEPALACE_MEDIUMROOM,
EFX_REVERB_PRESET_ICEPALACE_LARGEROOM,
EFX_REVERB_PRESET_ICEPALACE_LONGPASSAGE,
EFX_REVERB_PRESET_ICEPALACE_HALL,
EFX_REVERB_PRESET_ICEPALACE_CUPBOARD,
EFX_REVERB_PRESET_ICEPALACE_COURTYARD,
EFX_REVERB_PRESET_ICEPALACE_ALCOVE,
EFX_REVERB_PRESET_SPACESTATION_SMALLROOM,
EFX_REVERB_PRESET_SPACESTATION_SHORTPASSAGE,
EFX_REVERB_PRESET_SPACESTATION_MEDIUMROOM,
EFX_REVERB_PRESET_SPACESTATION_LARGEROOM,
EFX_REVERB_PRESET_SPACESTATION_LONGPASSAGE,
EFX_REVERB_PRESET_SPACESTATION_HALL,
EFX_REVERB_PRESET_SPACESTATION_CUPBOARD,
EFX_REVERB_PRESET_SPACESTATION_ALCOVE,
EFX_REVERB_PRESET_WOODEN_SMALLROOM,
EFX_REVERB_PRESET_WOODEN_SHORTPASSAGE,
EFX_REVERB_PRESET_WOODEN_MEDIUMROOM,
EFX_REVERB_PRESET_WOODEN_LARGEROOM,
EFX_REVERB_PRESET_WOODEN_LONGPASSAGE,
EFX_REVERB_PRESET_WOODEN_HALL,
EFX_REVERB_PRESET_WOODEN_CUPBOARD,
EFX_REVERB_PRESET_WOODEN_COURTYARD,
EFX_REVERB_PRESET_WOODEN_ALCOVE,
EFX_REVERB_PRESET_SPORT_EMPTYSTADIUM,
EFX_REVERB_PRESET_SPORT_SQUASHCOURT,
EFX_REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL,
EFX_REVERB_PRESET_SPORT_LARGESWIMMINGPOOL,
EFX_REVERB_PRESET_SPORT_GYMNASIUM,
EFX_REVERB_PRESET_SPORT_FULLSTADIUM,
EFX_REVERB_PRESET_SPORT_STADIUMTANNOY,
EFX_REVERB_PRESET_PREFAB_WORKSHOP,
EFX_REVERB_PRESET_PREFAB_SCHOOLROOM,
EFX_REVERB_PRESET_PREFAB_PRACTISEROOM,
EFX_REVERB_PRESET_PREFAB_OUTHOUSE,
EFX_REVERB_PRESET_PREFAB_CARAVAN,
EFX_REVERB_PRESET_DOME_TOMB,
EFX_REVERB_PRESET_PIPE_SMALL,
EFX_REVERB_PRESET_DOME_SAINTPAULS,
EFX_REVERB_PRESET_PIPE_LONGTHIN,
EFX_REVERB_PRESET_PIPE_LARGE,
EFX_REVERB_PRESET_PIPE_RESONANT,
EFX_REVERB_PRESET_OUTDOORS_BACKYARD,
EFX_REVERB_PRESET_OUTDOORS_ROLLINGPLAINS,
EFX_REVERB_PRESET_OUTDOORS_DEEPCANYON,
EFX_REVERB_PRESET_OUTDOORS_CREEK,
EFX_REVERB_PRESET_OUTDOORS_VALLEY,
EFX_REVERB_PRESET_MOOD_HEAVEN,
EFX_REVERB_PRESET_MOOD_HELL,
EFX_REVERB_PRESET_MOOD_MEMORY,
EFX_REVERB_PRESET_DRIVING_COMMENTATOR,
EFX_REVERB_PRESET_DRIVING_PITGARAGE,
EFX_REVERB_PRESET_DRIVING_INCAR_RACER,
EFX_REVERB_PRESET_DRIVING_INCAR_SPORTS,
EFX_REVERB_PRESET_DRIVING_INCAR_LUXURY,
EFX_REVERB_PRESET_DRIVING_FULLGRANDSTAND,
EFX_REVERB_PRESET_DRIVING_EMPTYGRANDSTAND,
EFX_REVERB_PRESET_DRIVING_TUNNEL,
EFX_REVERB_PRESET_CITY_STREETS,
EFX_REVERB_PRESET_CITY_SUBWAY,
EFX_REVERB_PRESET_CITY_MUSEUM,
EFX_REVERB_PRESET_CITY_LIBRARY,
EFX_REVERB_PRESET_CITY_UNDERPASS,
EFX_REVERB_PRESET_CITY_ABANDONED,
EFX_REVERB_PRESET_DUSTYROOM,
EFX_REVERB_PRESET_CHAPEL,
EFX_REVERB_PRESET_SMALLWATERROOM
};
static char ReverbPresetsNames[113][31] = {
"GENERIC",
"PADDEDCELL",
"ROOM",
"BATHROOM",
"LIVINGROOM",
"STONEROOM",
"AUDITORIUM",
"CONCERTHALL",
"CAVE",
"ARENA",
"HANGAR",
"CARPETEDHALLWAY",
"HALLWAY",
"STONECORRIDOR",
"ALLEY",
"FOREST",
"CITY",
"MOUNTAINS",
"QUARRY",
"PLAIN",
"PARKINGLOT",
"SEWERPIPE",
"UNDERWATER",
"DRUGGED",
"DIZZY",
"PSYCHOTIC",
"CASTLE_SMALLROOM",
"CASTLE_SHORTPASSAGE",
"CASTLE_MEDIUMROOM",
"CASTLE_LARGEROOM",
"CASTLE_LONGPASSAGE",
"CASTLE_HALL",
"CASTLE_CUPBOARD",
"CASTLE_COURTYARD",
"CASTLE_ALCOVE",
"FACTORY_SMALLROOM",
"FACTORY_SHORTPASSAGE",
"FACTORY_MEDIUMROOM",
"FACTORY_LARGEROOM",
"FACTORY_LONGPASSAGE",
"FACTORY_HALL",
"FACTORY_CUPBOARD",
"FACTORY_COURTYARD",
"FACTORY_ALCOVE",
"ICEPALACE_SMALLROOM",
"ICEPALACE_SHORTPASSAGE",
"ICEPALACE_MEDIUMROOM",
"ICEPALACE_LARGEROOM",
"ICEPALACE_LONGPASSAGE",
"ICEPALACE_HALL",
"ICEPALACE_CUPBOARD",
"ICEPALACE_COURTYARD",
"ICEPALACE_ALCOVE",
"SPACESTATION_SMALLROOM",
"SPACESTATION_SHORTPASSAGE",
"SPACESTATION_MEDIUMROOM",
"SPACESTATION_LARGEROOM",
"SPACESTATION_LONGPASSAGE",
"SPACESTATION_HALL",
"SPACESTATION_CUPBOARD",
"SPACESTATION_ALCOVE",
"WOODEN_SMALLROOM",
"WOODEN_SHORTPASSAGE",
"WOODEN_MEDIUMROOM",
"WOODEN_LARGEROOM",
"WOODEN_LONGPASSAGE",
"WOODEN_HALL",
"WOODEN_CUPBOARD",
"WOODEN_COURTYARD",
"WOODEN_ALCOVE",
"SPORT_EMPTYSTADIUM",
"SPORT_SQUASHCOURT",
"SPORT_SMALLSWIMMINGPOOL",
"SPORT_LARGESWIMMINGPOOL",
"SPORT_GYMNASIUM",
"SPORT_FULLSTADIUM",
"SPORT_STADIUMTANNOY",
"PREFAB_WORKSHOP",
"PREFAB_SCHOOLROOM",
"PREFAB_PRACTISEROOM",
"PREFAB_OUTHOUSE",
"PREFAB_CARAVAN",
"DOME_TOMB",
"PIPE_SMALL",
"DOME_SAINTPAULS",
"PIPE_LONGTHIN",
"PIPE_LARGE",
"PIPE_RESONANT",
"OUTDOORS_BACKYARD",
"OUTDOORS_ROLLINGPLAINS",
"OUTDOORS_DEEPCANYON",
"OUTDOORS_CREEK",
"OUTDOORS_VALLEY",
"MOOD_HEAVEN",
"MOOD_HELL",
"MOOD_MEMORY",
"DRIVING_COMMENTATOR",
"DRIVING_PITGARAGE",
"DRIVING_INCAR_RACER",
"DRIVING_INCAR_SPORTS",
"DRIVING_INCAR_LUXURY",
"DRIVING_FULLGRANDSTAND",
"DRIVING_EMPTYGRANDSTAND",
"DRIVING_TUNNEL",
"CITY_STREETS",
"CITY_SUBWAY",
"CITY_MUSEUM",
"CITY_LIBRARY",
"CITY_UNDERPASS",
"CITY_ABANDONED",
"DUSTYROOM",
"CHAPEL",
"SMALLWATERROOM"
};
static void
SetReverb(int index, int concalled)
{
EFXEAXREVERBPROPERTIES reverb = ReverbPresets[index];
if(concalled)
Com_Printf("Reverb set to: %s\n", ReverbPresetsNames[index]);
qalEffectf(ReverbEffect, AL_REVERB_DENSITY, reverb.flDensity);
qalEffectf(ReverbEffect, AL_REVERB_DIFFUSION, reverb.flDiffusion);
qalEffectf(ReverbEffect, AL_REVERB_GAIN, reverb.flGain);
qalEffectf(ReverbEffect, AL_REVERB_GAINHF, reverb.flGainHF);
qalEffectf(ReverbEffect, AL_REVERB_DECAY_TIME, reverb.flDecayTime);
qalEffectf(ReverbEffect, AL_REVERB_DECAY_HFRATIO, reverb.flDecayHFRatio);
qalEffectf(ReverbEffect, AL_REVERB_REFLECTIONS_GAIN, reverb.flReflectionsGain);
qalEffectf(ReverbEffect, AL_REVERB_REFLECTIONS_DELAY, reverb.flReflectionsDelay);
qalEffectf(ReverbEffect, AL_REVERB_LATE_REVERB_GAIN, reverb.flLateReverbGain);
qalEffectf(ReverbEffect, AL_REVERB_LATE_REVERB_DELAY, reverb.flLateReverbDelay);
qalEffectf(ReverbEffect, AL_REVERB_AIR_ABSORPTION_GAINHF, reverb.flAirAbsorptionGainHF);
qalEffectf(ReverbEffect, AL_REVERB_ROOM_ROLLOFF_FACTOR, reverb.flRoomRolloffFactor);
qalEffecti(ReverbEffect, AL_REVERB_DECAY_HFLIMIT, reverb.iDecayHFLimit);
qalAuxiliaryEffectSloti(ReverbEffectSlot, AL_EFFECTSLOT_EFFECT, ReverbEffect);
}
/*
* Apply Reverb effect
*/
static void
UpdateReverb(void)
{
vec3_t mins = { 0, 0, 0 }, maxs = { 0, 0, 0 };
vec3_t forward = { 1000000, 0, 0 };
vec3_t backward = { -1000000, 0, 0 };
vec3_t left = { 0, 1000000, 0 };
vec3_t right = { 0, -1000000, 0 };
vec3_t up = { 0, 0, 1000000 };
trace_t trace1;
trace_t trace2;
trace_t trace3;
trace_t trace4;
trace_t trace5;
vec3_t length1;
vec3_t length2;
vec3_t length3;
vec3_t length4;
vec3_t length5;
float dist1;
float dist2;
float dist3;
float dist4;
float dist5;
float average;
if (ReverbEffect == 0)
return;
trace1 = CM_BoxTrace(listener_origin, up, mins, maxs, 0, MASK_PLAYERSOLID);
trace2 = CM_BoxTrace(listener_origin, forward, mins, maxs, 0, MASK_PLAYERSOLID);
trace3 = CM_BoxTrace(listener_origin, backward, mins, maxs, 0, MASK_PLAYERSOLID);
trace4 = CM_BoxTrace(listener_origin, left, mins, maxs, 0, MASK_PLAYERSOLID);
trace5 = CM_BoxTrace(listener_origin, right, mins, maxs, 0, MASK_PLAYERSOLID);
VectorSubtract(trace1.endpos, listener_origin, length1);
VectorSubtract(trace2.endpos, listener_origin, length2);
VectorSubtract(trace3.endpos, listener_origin, length3);
VectorSubtract(trace4.endpos, listener_origin, length4);
VectorSubtract(trace5.endpos, listener_origin, length5);
dist1 = VectorLength(length1);
dist2 = VectorLength(length2);
dist3 = VectorLength(length3);
dist4 = VectorLength(length4);
dist5 = VectorLength(length5);
average = (dist1 + dist2 + dist3 + dist4 + dist5) / 5;
if (average < 60)
SetReverb(21, 0);
if (average > 60 && average < 90)
SetReverb(36, 0);
if (average > 90 && average < 200)
SetReverb(0, 0);
if (average > 200 && average < 400)
SetReverb(37, 0);
if (average > 400 && average < 600)
SetReverb(38, 0);
if (average > 600)
SetReverb(75, 0);
}
/*
* Performance stereo spatialization
* of a channel in the frontends
@ -274,7 +604,7 @@ AL_Spatialize(channel_t *ch)
qalSource3f(ch->srcnum, AL_VELOCITY, AL_UnpackVector(velocity));
}
if (s_occlusion->value)
if (s_occlusion->value && underwaterFilter != 0)
{
trace_t trace;
vec3_t mins = { 0, 0, 0 }, maxs = { 0, 0, 0 };
@ -295,6 +625,8 @@ AL_Spatialize(channel_t *ch)
qalSourcef(ch->srcnum, AL_GAIN, min(max(final, 0), 1));
VectorCopy(trace.endpos, origin);
if (!snd_is_underwater)
qalSourcei(ch->srcnum, AL_DIRECT_FILTER, underwaterFilter);
}
@ -303,6 +635,20 @@ AL_Spatialize(channel_t *ch)
if (!snd_is_underwater)
qalSourcei(ch->srcnum, AL_DIRECT_FILTER, 0) ;
}
if(!snd_is_underwater && s_reverb_preset_autopick->value && s_reverb->value)
{
UpdateReverb();
}
if(s_reverb->value && ReverbEffect != 0)
{
qalSource3i(ch->srcnum, AL_AUXILIARY_SEND_FILTER, ReverbEffectSlot, 0, AL_FILTER_NULL);
}
else
{
qalSource3i(ch->srcnum, AL_AUXILIARY_SEND_FILTER, 0, 0, AL_FILTER_NULL);
}
}
return;
@ -614,6 +960,30 @@ AL_UnqueueRawSamples()
AL_StreamDie();
}
static void
AL_UpdateReverb()
{
if (!s_reverb_preset->modified)
{
return;
}
s_reverb_preset->modified = false;
if (s_reverb_preset_autopick->value)
{
Com_Printf("This will not have effect while s_reverb_preset_autopick is 1!");
return;
}
if (s_reverb_preset->value < 0)
s_reverb_preset->value = 0;
if (s_reverb_preset->value > 112)
s_reverb_preset->value = 112;
SetReverb(s_reverb_preset->value, 1);
}
static void
AL_UpdateUnderwater()
{
@ -754,6 +1124,7 @@ AL_Update(void)
AL_IssuePlaysounds();
AL_UpdateUnderwater();
AL_UpdateReverb();
}
/* ----------------------------------------------------------------- */
@ -778,6 +1149,7 @@ AL_Underwater()
for (i = 0; i < s_numchannels; i++)
{
qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, underwaterFilter);
SetReverb(22, 0);
}
}
@ -801,6 +1173,7 @@ AL_Overwater()
for (i = 0; i < s_numchannels; i++)
{
qalSourcei(s_srcnums[i], AL_DIRECT_FILTER, AL_FILTER_NULL);
SetReverb(s_reverb_preset->value, 0);
}
}
@ -856,6 +1229,27 @@ AL_InitUnderwaterFilter()
s_underwater_gain_hf->modified = true;
}
static void
AL_InitReverbEffect(void)
{
if (!(qalGenEffects && qalEffecti && qalEffectf && qalDeleteEffects &&qalGenAuxiliaryEffectSlots && qalAuxiliaryEffectSloti))
return;
ReverbEffect = 0;
qalGenEffects(1, &ReverbEffect);
if (qalGetError() != AL_NO_ERROR)
{
Com_Printf("Couldn't generate an OpenAL effect!\n");
return;
}
ReverbEffectSlot = 0;
qalGenAuxiliaryEffectSlots(1, &ReverbEffectSlot);
qalEffecti(ReverbEffect, AL_EFFECT_TYPE, AL_EFFECT_REVERB);
SetReverb(s_reverb_preset->value, 0);
}
/*
* Initializes the OpenAL backend
*/
@ -913,6 +1307,7 @@ AL_Init(void)
s_numchannels = i;
AL_InitStreamSource();
AL_InitUnderwaterFilter();
AL_InitReverbEffect();
Com_Printf("Number of OpenAL sources: %d\n\n", s_numchannels);
@ -936,6 +1331,7 @@ AL_Shutdown(void)
qalDeleteSources(1, &streamSource);
qalDeleteFilters(1, &underwaterFilter);
qalDeleteEffects(1, &ReverbEffect);
if (s_numchannels)
{

View file

@ -148,6 +148,14 @@ LPALGENFILTERS qalGenFilters;
LPALFILTERI qalFilteri;
LPALFILTERF qalFilterf;
LPALDELETEFILTERS qalDeleteFilters;
LPALGENEFFECTS qalGenEffects;
LPALEFFECTF qalEffectf;
LPALEFFECTI qalEffecti;
LPALEFFECTFV qalEffectfv;
LPALAUXILIARYEFFECTSLOTI qalAuxiliaryEffectSloti;
LPALGENAUXILIARYEFFECTSLOTS qalGenAuxiliaryEffectSlots;
LPALDELETEAUXILIARYEFFECTSLOTS qalDeleteAuxiliaryEffectSlots;
LPALDELETEEFFECTS qalDeleteEffects;
/*
* Gives information over the OpenAL
@ -552,11 +560,27 @@ QAL_Init()
qalFilteri = qalGetProcAddress("alFilteri");
qalFilterf = qalGetProcAddress("alFilterf");
qalDeleteFilters = qalGetProcAddress("alDeleteFilters");
qalAuxiliaryEffectSloti = qalGetProcAddress("alAuxiliaryEffectSloti");
qalGenEffects = qalGetProcAddress("alGenEffects");
qalGenAuxiliaryEffectSlots = qalGetProcAddress("alGenAuxiliaryEffectSlots");
qalEffectf = qalGetProcAddress("alEffectf");
qalEffecti = qalGetProcAddress("alEffecti");
qalEffectfv = qalGetProcAddress("alEffectfv");
qalDeleteAuxiliaryEffectSlots = qalGetProcAddress("alDeleteAuxiliaryEffectSlots");
qalDeleteEffects = qalGetProcAddress("alDeleteEffects");
} else {
qalGenFilters = NULL;
qalFilteri = NULL;
qalFilterf = NULL;
qalDeleteFilters = NULL;
qalAuxiliaryEffectSloti = NULL;
qalGenEffects = NULL;
qalGenAuxiliaryEffectSlots = NULL;
qalEffectf = NULL;
qalEffecti = NULL;
qalEffectfv = NULL;
qalDeleteAuxiliaryEffectSlots = NULL;
qalDeleteEffects = NULL;
}
Com_Printf("ok\n");

View file

@ -74,6 +74,9 @@ cvar_t* s_underwater_gain_hf;
cvar_t* s_doppler;
cvar_t* s_occlusion;
cvar_t* s_occlusion_strength;
cvar_t* s_reverb_preset;
cvar_t* s_reverb_preset_autopick;
cvar_t* s_reverb;
cvar_t* s_ps_sorting;
channel_t channels[MAX_CHANNELS];
@ -1555,6 +1558,9 @@ S_Init(void)
s_doppler = Cvar_Get("s_doppler", "0", CVAR_ARCHIVE);
s_occlusion = Cvar_Get("s_occlusion", "0", CVAR_ARCHIVE);
s_occlusion_strength = Cvar_Get("s_occlusion_strength", "0", CVAR_ARCHIVE);
s_reverb_preset = Cvar_Get("s_reverb_preset", "0", CVAR_ARCHIVE);
s_reverb = Cvar_Get("s_reverb", "1", CVAR_ARCHIVE);
s_reverb_preset_autopick = Cvar_Get("s_reverb_preset_autopick", "1", CVAR_ARCHIVE);
s_ps_sorting = Cvar_Get("s_ps_sorting", "1", CVAR_ARCHIVE);
Cmd_AddCommand("play", S_Play);