Skip to content

Commit

Permalink
Add in-game custom HRTF selection
Browse files Browse the repository at this point in the history
  • Loading branch information
ceski-1 committed Oct 12, 2024
1 parent 010bc54 commit eb1af8d
Show file tree
Hide file tree
Showing 8 changed files with 196 additions and 12 deletions.
1 change: 1 addition & 0 deletions src/i_oalcommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@
#endif

#define ALFUNC(T, ptr) (ptr = FUNCTION_CAST(T, alGetProcAddress(#ptr)))
#define ALCFUNC(d, T, ptr) (ptr = FUNCTION_CAST(T, alcGetProcAddress(d, #ptr)))

#define DB_TO_GAIN(db) powf(10.0f, (db) / 20.0f)

Expand Down
152 changes: 147 additions & 5 deletions src/i_oalsound.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include <stdlib.h>
#include <string.h>

#include "d_iwad.h"
#include "d_main.h"
#include "i_oalcommon.h"
#include "i_oalequalizer.h"
#include "i_oalsound.h"
Expand All @@ -35,6 +37,8 @@
#include "m_array.h"
#include "m_config.h"
#include "m_fixed.h"
#include "m_io.h"
#include "m_misc.h"
#include "sounds.h"
#include "w_wad.h"
#include "z_zone.h"
Expand All @@ -53,10 +57,13 @@

static int snd_resampler;
static boolean snd_limiter;
static boolean snd_hrtf;
static int snd_hrtf;
static const char *snd_hrtf_dir = "";
static const char *snd_hrtf_string = "";
static int snd_absorption;
static int snd_doppler;

static const char **hrtf_strings = NULL;
static int oal_snd_module;
boolean oal_use_doppler;

Expand Down Expand Up @@ -409,19 +416,26 @@ static void PrintDeviceInfo(ALCdevice *device)
static void GetAttribs(ALCint **attribs)
{
const boolean use_3d = (oal_snd_module == SND_MODULE_3D);
const boolean use_hrtf = (use_3d && snd_hrtf > 0);

if (alcIsExtensionPresent(oal->device, "ALC_SOFT_HRTF") == ALC_TRUE)
{
array_push(*attribs, ALC_HRTF_SOFT);
array_push(*attribs, (use_3d && snd_hrtf) ? ALC_TRUE : ALC_FALSE);
array_push(*attribs, use_hrtf ? ALC_TRUE : ALC_FALSE);

if (use_hrtf)
{
array_push(*attribs, ALC_HRTF_ID_SOFT);
array_push(*attribs, snd_hrtf - 1);
}
}

#ifdef ALC_OUTPUT_MODE_SOFT
if (alcIsExtensionPresent(oal->device, "ALC_SOFT_output_mode") == ALC_TRUE)
{
array_push(*attribs, ALC_OUTPUT_MODE_SOFT);
array_push(*attribs,
use_3d ? (snd_hrtf ? ALC_STEREO_HRTF_SOFT : ALC_ANY_SOFT)
use_3d ? (use_hrtf ? ALC_STEREO_HRTF_SOFT : ALC_ANY_SOFT)
: ALC_STEREO_BASIC_SOFT);
}
#endif
Expand All @@ -439,8 +453,16 @@ static void GetAttribs(ALCint **attribs)

void I_OAL_BindSoundVariables(void)
{
BIND_BOOL_GENERAL(snd_hrtf, false,
"[OpenAL 3D] Headphones mode (0 = No; 1 = Yes)");
BIND_NUM(snd_hrtf, 0, 0, UL, "[OpenAL 3D] Headphones mode menu index");
M_BindStr("snd_hrtf_string", &snd_hrtf_string, "Off", wad_no,
"[OpenAL 3D] Headphones mode menu string");
M_BindStr("snd_hrtf_dir", &snd_hrtf_dir,
#if defined(_WIN32)
"hrtf",
#else
"./hrtf",
#endif
wad_no, "[OpenAL 3D] Headphones mode data directory");
BIND_NUM_GENERAL(snd_resampler, 1, 0, UL,
"Sound resampler (0 = Nearest; 1 = Linear; ...)");
BIND_NUM(snd_absorption, 0, 0, 10,
Expand All @@ -450,6 +472,122 @@ void I_OAL_BindSoundVariables(void)
BIND_BOOL(snd_limiter, false, "Use sound output limiter");
}

boolean I_OAL_3dSound(void)
{
return (oal_snd_module == SND_MODULE_3D);
}

const char **I_OAL_GetHrtfStrings(void)
{
return hrtf_strings;
}

static void UpdatetHrtfMenu(void)
{
if (snd_hrtf < array_size(hrtf_strings))
{
snd_hrtf_string = hrtf_strings[snd_hrtf];
}
else
{
snd_hrtf = 0;
snd_hrtf_string = "Off";
}
}

static void InitHrtfMenu(void)
{
int i;

for (i = 0; i < array_size(hrtf_strings); i++)
{
if (!strcasecmp(hrtf_strings[i], snd_hrtf_string))
{
snd_hrtf = i;
break;
}
}

if (i == array_size(hrtf_strings))
{
snd_hrtf = 0;
snd_hrtf_string = "Off";
}
}

#define NAME_MAX_LENGTH 25

static void InitHrtfStrings(void)
{
if (array_size(hrtf_strings))
{
return;
}

array_push(hrtf_strings, "Off");

if (!oal || !oal->device)
{
return;
}

if (alcIsExtensionPresent(oal->device, "ALC_SOFT_HRTF") != AL_TRUE)
{
return;
}

LPALCGETSTRINGISOFT alcGetStringiSOFT = NULL;
if (ALCFUNC(oal->device, LPALCGETSTRINGISOFT, alcGetStringiSOFT) == NULL)
{
return;
}

ALCint num_hrtf;
alcGetIntegerv(oal->device, ALC_NUM_HRTF_SPECIFIERS_SOFT, 1, &num_hrtf);
if (num_hrtf < 1)
{
return;
}

for (ALCint i = 0; i < num_hrtf; i++)
{
char *name = M_StringDuplicate(
alcGetStringiSOFT(oal->device, ALC_HRTF_SPECIFIER_SOFT, i));

if (strlen(name) > NAME_MAX_LENGTH)
{
name[NAME_MAX_LENGTH] = '\0';
}

array_push(hrtf_strings, name);
}
}

static void SetLocalHrtfPath(const char *orig)
{
if (!orig || orig[0] == '\0')
{
return;
}

#if defined(_WIN32)
M_setenv("ALSOFT_LOCAL_PATH", orig);
#else
char *dir = M_StringDuplicate(orig);

if (dir[0] == '.' && (dir[1] == '.' || dir[1] == '/' || dir[1] == '\0'))
{
// ALSOFT_LOCAL_PATH must be a single path, so use the config path.
char *rel = M_StringJoin(D_DoomPrefDir(), DIR_SEPARATOR_S, dir);
free(dir);
dir = rel;
}

M_setenv("ALSOFT_LOCAL_PATH", dir);
free(dir);
#endif
}

boolean I_OAL_InitSound(int snd_module)
{
ALCint *attribs = NULL;
Expand All @@ -461,6 +599,7 @@ boolean I_OAL_InitSound(int snd_module)
I_OAL_ShutdownSound();
}

SetLocalHrtfPath(snd_hrtf_dir);
oal = calloc(1, sizeof(*oal));
oal->device = alcOpenDevice(NULL);
if (!oal->device)
Expand All @@ -471,6 +610,8 @@ boolean I_OAL_InitSound(int snd_module)
return false;
}

InitHrtfStrings();
InitHrtfMenu();
GetAttribs(&attribs);
oal->context = alcCreateContext(oal->device, attribs);
array_free(attribs);
Expand Down Expand Up @@ -535,6 +676,7 @@ boolean I_OAL_ReinitSound(int snd_module)
return false;
}

UpdatetHrtfMenu();
GetAttribs(&attribs);
result = alcResetDeviceSOFT(oal->device, attribs);
array_free(attribs);
Expand Down
4 changes: 4 additions & 0 deletions src/i_oalsound.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,10 @@ void I_OAL_UpdateListenerParams(const ALfloat *position,

const char **I_OAL_GetResamplerStrings(void);

const char **I_OAL_GetHrtfStrings(void);

boolean I_OAL_3dSound(void);

boolean I_OAL_InitSound(int snd_module);

boolean I_OAL_ReinitSound(int snd_module);
Expand Down
4 changes: 2 additions & 2 deletions src/i_sound.c
Original file line number Diff line number Diff line change
Expand Up @@ -442,7 +442,7 @@ void I_InitSound(void)

I_AtExit(I_ShutdownSound, true);

MN_UpdateAdvancedSoundItems(snd_module != SND_MODULE_3D);
MN_UpdateAdvancedSoundItems();

snd_init = true;

Expand Down Expand Up @@ -520,7 +520,7 @@ void I_SetSoundModule(void)
I_Printf(VB_WARNING, "I_SetSoundModule: Failed to reinitialize sound.");
}

MN_UpdateAdvancedSoundItems(snd_module != SND_MODULE_3D);
MN_UpdateAdvancedSoundItems();
}

midiplayertype_t I_MidiPlayerType(void)
Expand Down
26 changes: 26 additions & 0 deletions src/m_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -383,3 +383,29 @@ char *M_getenv(const char *name)
return getenv(name);
#endif
}

// Doesn't overwrite an existing environment variable. See env_vars.
int M_setenv(const char *name, const char *value)
{
#ifdef _WIN32
if (!name || !value || M_getenv(name) != NULL)
{
return -1;
}

char *pair = M_StringJoin(name, "=", value);
wchar_t *wpair = ConvertUtf8ToWide(pair);
free(pair);

if (!wpair)
{
return -1;
}

const int ret = _wputenv(wpair);
free(wpair);
return ret;
#else
return setenv(name, value, 0);
#endif
}
1 change: 1 addition & 0 deletions src/m_io.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ int M_open(const char *filename, int oflag);
int M_access(const char *path, int mode);
void M_MakeDirectory(const char *dir);
char *M_getenv(const char *name);
int M_setenv(const char *name, const char *value);

#ifdef _WIN32
char *M_ConvertWideToUtf8(const wchar_t *wstr);
Expand Down
2 changes: 1 addition & 1 deletion src/mn_menu.h
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ void MN_UpdateMouseLook(void);
void MN_UpdatePadLook(void);
void MN_UpdateAllGamepadItems(void);
void MN_UpdateEqualizerItems(void);
void MN_UpdateAdvancedSoundItems(boolean toggle);
void MN_UpdateAdvancedSoundItems(void);
void MN_ResetTimeScale(void);
void MN_SetHUFontKerning(void);
void MN_DisableVoxelsRenderingItem(void);
Expand Down
18 changes: 14 additions & 4 deletions src/mn_setup.c
Original file line number Diff line number Diff line change
Expand Up @@ -337,6 +337,7 @@ enum
str_gamma,
str_sound_module,
str_resampler,
str_hrtf,
str_equalizer_preset,
str_midi_complevel,
str_midi_reset_type,
Expand Down Expand Up @@ -2562,8 +2563,8 @@ static setup_menu_t gen_settings2[] = {
{"Sound Module", S_CHOICE, CNTR_X, M_SPC, {"snd_module"},
.strings_id = str_sound_module, .action = SetSoundModule},

{"Headphones Mode", S_ONOFF, CNTR_X, M_SPC, {"snd_hrtf"},
.action = SetSoundModule},
{"Headphones Mode", S_CHOICE | S_ACTION, CNTR_X, M_SPC, {"snd_hrtf"},
.strings_id = str_hrtf, .action = SetSoundModule},

{"Pitch-Shifting", S_ONOFF, CNTR_X, M_SPC, {"pitched_sounds"}},

Expand Down Expand Up @@ -2596,6 +2597,12 @@ static const char **GetResamplerStrings(void)
return strings;
}

static const char **GetHrtfStrings(void)
{
MN_UpdateAdvancedSoundItems();
return I_OAL_GetHrtfStrings();
}

static const char *midi_complevel_strings[] = {
"Vanilla", "Standard", "Full"
};
Expand Down Expand Up @@ -3369,9 +3376,10 @@ void MN_UpdateDynamicResolutionItem(void)
"dynamic_resolution");
}

void MN_UpdateAdvancedSoundItems(boolean toggle)
void MN_UpdateAdvancedSoundItems(void)
{
DisableItem(toggle, gen_settings2, "snd_hrtf");
const boolean condition = (!I_OAL_3dSound() || !I_OAL_GetHrtfStrings());
DisableItem(condition, gen_settings2, "snd_hrtf");
}

void MN_UpdateFpsLimitItem(void)
Expand Down Expand Up @@ -4833,6 +4841,7 @@ static const char **selectstrings[] = {
gamma_strings,
sound_module_strings,
NULL, // str_resampler
NULL, // str_hrtf
equalizer_preset_strings,
midi_complevel_strings,
midi_reset_type_strings,
Expand Down Expand Up @@ -4889,6 +4898,7 @@ void MN_InitMenuStrings(void)
selectstrings[str_gyro_sens] = GetGyroSensitivityStrings();
selectstrings[str_gyro_accel] = GetGyroAccelStrings();
selectstrings[str_resampler] = GetResamplerStrings();
selectstrings[str_hrtf] = GetHrtfStrings();
}

void MN_SetupResetMenu(void)
Expand Down

0 comments on commit eb1af8d

Please sign in to comment.