diff --git a/src/common/audio/sound/i_sound.cpp b/src/common/audio/sound/i_sound.cpp index 5f828d98540..d6275a6ca30 100644 --- a/src/common/audio/sound/i_sound.cpp +++ b/src/common/audio/sound/i_sound.cpp @@ -134,6 +134,9 @@ class NullSoundRenderer : public SoundRenderer void SetMusicVolume (float volume) { } + virtual void UpdateMusicParams() + { + } SoundHandle LoadSound(uint8_t *sfxdata, int length) { SoundHandle retval = { NULL }; diff --git a/src/common/audio/sound/i_sound.h b/src/common/audio/sound/i_sound.h index 016098d48b8..8d837f72678 100644 --- a/src/common/audio/sound/i_sound.h +++ b/src/common/audio/sound/i_sound.h @@ -105,6 +105,7 @@ class SoundRenderer virtual bool IsNull() { return false; } virtual void SetSfxVolume (float volume) = 0; virtual void SetMusicVolume (float volume) = 0; + virtual void UpdateMusicParams() = 0; virtual SoundHandle LoadSound(uint8_t *sfxdata, int length) = 0; SoundHandle LoadSoundVoc(uint8_t *sfxdata, int length); virtual SoundHandle LoadSoundRaw(uint8_t *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1) = 0; diff --git a/src/common/audio/sound/oalsound.cpp b/src/common/audio/sound/oalsound.cpp index fd43bcd8933..2c22856f7a5 100644 --- a/src/common/audio/sound/oalsound.cpp +++ b/src/common/audio/sound/oalsound.cpp @@ -60,6 +60,16 @@ CVAR(Bool, snd_waterreverb, true, CVAR_ARCHIVE | CVAR_GLOBALCONFIG) CVAR (String, snd_aldevice, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (Bool, snd_efx, true, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) CVAR (String, snd_alresampler, "Default", CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CVAR (Int, snd_musicmode, 0, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +CUSTOM_CVAR (Float, snd_superstereowidth, 0.6f, CVAR_ARCHIVE|CVAR_GLOBALCONFIG) +{ + if (self > 1.0f) + self = 1.0f; + else if (!(self >= 0.0f)) + self = 0.0f; + else if(GSnd) + GSnd->UpdateMusicParams(); +} #ifdef _WIN32 #define OPENALLIB "openal32.dll" @@ -117,6 +127,14 @@ EXTERN_CVAR (Int, snd_hrtf) #define MAKE_PTRID(x) ((void*)(uintptr_t)(x)) #define GET_PTRID(x) ((uint32_t)(uintptr_t)(x)) +namespace { + +/* Values used by snd_musicmode. */ +enum MusicMode : int { + Normal = 0, + SuperStereo = 1, +}; + static ALenum checkALError(const char *fn, unsigned int ln) { @@ -162,6 +180,8 @@ static ALvoid AL_APIENTRY _wrap_ProcessUpdatesSOFT(void) alcProcessContext(alcGetCurrentContext()); } +} // namespace + class OpenALSoundStream : public SoundStream { @@ -222,6 +242,13 @@ class OpenALSoundStream : public SoundStream alSourcef(Source, AL_SOURCE_RADIUS, 0.f); if(Renderer->AL.SOFT_source_spatialize) alSourcei(Source, AL_SOURCE_SPATIALIZE_SOFT, AL_AUTO_SOFT); + if(Renderer->AL.SOFT_UHJ) + { + const ALenum mode{(*snd_musicmode == MusicMode::SuperStereo) + ? AL_SUPER_STEREO_SOFT : AL_NORMAL_SOFT}; + alSourcei(Source, AL_STEREO_MODE_SOFT, mode); + alSourcef(Source, AL_SUPER_STEREO_WIDTH_SOFT, *snd_superstereowidth); + } alGenBuffers(BufferCount, Buffers); return (getALError() == AL_NO_ERROR); @@ -307,12 +334,14 @@ class OpenALSoundStream : public SoundStream virtual void SetVolume(float vol) { Volume = vol; - UpdateVolume(); + UpdateParams(); } - void UpdateVolume() + void UpdateParams() { alSourcef(Source, AL_GAIN, Renderer->MusicVolume*Volume); + if(Renderer->AL.SOFT_UHJ) + alSourcef(Source, AL_SUPER_STEREO_WIDTH_SOFT, *snd_superstereowidth); getALError(); } @@ -673,6 +702,7 @@ OpenALSoundRenderer::OpenALSoundRenderer() AL.SOFT_source_latency = !!alIsExtensionPresent("AL_SOFT_source_latency"); AL.SOFT_source_resampler = !!alIsExtensionPresent("AL_SOFT_source_resampler"); AL.SOFT_source_spatialize = !!alIsExtensionPresent("AL_SOFT_source_spatialize"); + AL.SOFT_UHJ = !!alIsExtensionPresent("AL_SOFT_UHJ"); // Speed of sound is in units per second. Presuming we want to simulate a // typical speed of sound of 343.3 meters per second, multiply it by the @@ -984,8 +1014,13 @@ void OpenALSoundRenderer::SetSfxVolume(float volume) void OpenALSoundRenderer::SetMusicVolume(float volume) { MusicVolume = volume; + UpdateMusicParams(); +} + +void OpenALSoundRenderer::UpdateMusicParams() +{ for(uint32_t i = 0;i < Streams.Size();++i) - Streams[i]->UpdateVolume(); + Streams[i]->UpdateParams(); } unsigned int OpenALSoundRenderer::GetMSLength(SoundHandle sfx) @@ -1273,6 +1308,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound(SoundHandle sfx, float vol, int alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); else alSourcef(source, AL_PITCH, PITCH(pitch)); + if(AL.SOFT_UHJ) + alSourcei(source, AL_STEREO_MODE_SOFT, AL_NORMAL_SOFT); if(!reuse_chan || reuse_chan->StartTime == 0) { @@ -1441,6 +1478,8 @@ FISoundChannel *OpenALSoundRenderer::StartSound3D(SoundHandle sfx, SoundListener alSourcef(source, AL_PITCH, PITCH(pitch)*PITCH_MULT); else alSourcef(source, AL_PITCH, PITCH(pitch)); + if(AL.SOFT_UHJ) + alSourcei(source, AL_STEREO_MODE_SOFT, AL_NORMAL_SOFT); if(!reuse_chan || reuse_chan->StartTime == 0) { diff --git a/src/common/audio/sound/oalsound.h b/src/common/audio/sound/oalsound.h index 93436f4ecae..bad4e5dc720 100644 --- a/src/common/audio/sound/oalsound.h +++ b/src/common/audio/sound/oalsound.h @@ -23,10 +23,27 @@ #include "alext.h" +#ifndef AL_SOFT_UHJ +#define AL_SOFT_UHJ +#define AL_FORMAT_UHJ2CHN8_SOFT 0x19A2 +#define AL_FORMAT_UHJ2CHN16_SOFT 0x19A3 +#define AL_FORMAT_UHJ2CHN_FLOAT32_SOFT 0x19A4 +#define AL_FORMAT_UHJ3CHN8_SOFT 0x19A5 +#define AL_FORMAT_UHJ3CHN16_SOFT 0x19A6 +#define AL_FORMAT_UHJ3CHN_FLOAT32_SOFT 0x19A7 +#define AL_FORMAT_UHJ4CHN8_SOFT 0x19A8 +#define AL_FORMAT_UHJ4CHN16_SOFT 0x19A9 +#define AL_FORMAT_UHJ4CHN_FLOAT32_SOFT 0x19AA +#define AL_STEREO_MODE_SOFT 0x19B0 +#define AL_NORMAL_SOFT 0x0000 +#define AL_SUPER_STEREO_SOFT 0x0001 +#define AL_SUPER_STEREO_WIDTH_SOFT 0x19B1 +#endif + class OpenALSoundStream; -class OpenALSoundRenderer : public SoundRenderer +class OpenALSoundRenderer final : public SoundRenderer { public: OpenALSoundRenderer(); @@ -34,6 +51,7 @@ class OpenALSoundRenderer : public SoundRenderer virtual void SetSfxVolume(float volume); virtual void SetMusicVolume(float volume); + virtual void UpdateMusicParams(); virtual SoundHandle LoadSound(uint8_t *sfxdata, int length); virtual SoundHandle LoadSoundRaw(uint8_t *sfxdata, int length, int frequency, int channels, int bits, int loopstart, int loopend = -1); virtual void UnloadSound(SoundHandle sfx); @@ -86,20 +104,21 @@ class OpenALSoundRenderer : public SoundRenderer private: struct { - bool EXT_EFX; - bool EXT_disconnect; - bool SOFT_HRTF; - bool SOFT_pause_device; - bool SOFT_output_limiter; + bool EXT_EFX : 1; + bool EXT_disconnect : 1; + bool SOFT_HRTF : 1; + bool SOFT_pause_device : 1; + bool SOFT_output_limiter : 1; } ALC; struct { - bool EXT_source_distance_model; - bool EXT_SOURCE_RADIUS; - bool SOFT_deferred_updates; - bool SOFT_loop_points; - bool SOFT_source_latency; - bool SOFT_source_resampler; - bool SOFT_source_spatialize; + bool EXT_source_distance_model : 1; + bool EXT_SOURCE_RADIUS : 1; + bool SOFT_deferred_updates : 1; + bool SOFT_loop_points : 1; + bool SOFT_source_latency : 1; + bool SOFT_source_resampler : 1; + bool SOFT_source_spatialize : 1; + bool SOFT_UHJ : 1; } AL; // EFX Extension function pointer variables. Loaded after context creation diff --git a/wadsrc/static/menudef.txt b/wadsrc/static/menudef.txt index 252b086cc5d..6a4b25b517a 100644 --- a/wadsrc/static/menudef.txt +++ b/wadsrc/static/menudef.txt @@ -1905,12 +1905,22 @@ OptionString Resamplers } +OptionValue MusicModes +{ + 0, "$OPTVAL_NORMAL" + 1, "$OPTVAL_SUPERSTEREO" +} + + OptionMenu OpenALSoundItems protected { Title "$OPENALMNU_TITLE" Option "$OPENALMNU_PLAYBACKDEVICE", "snd_aldevice", "ALDevices" Option "$OPENALMNU_ENABLEEFX", "snd_efx", "OnOff" Option "$OPENALMNU_RESAMPLER", "snd_alresampler", "ALResamplers" + StaticText " " + Option "$OPENALMNU_MUSICMODE", "snd_musicmode", "MusicModes" + Slider "$OPENALMNU_SUPERSTEREOWIDTH", "snd_superstereowidth", 0, 1, 0.05, 2 }