diff --git a/engine/MUNGA_L4/L4AUDRND.cpp b/engine/MUNGA_L4/L4AUDRND.cpp index 8e3415b..a1b5a71 100644 --- a/engine/MUNGA_L4/L4AUDRND.cpp +++ b/engine/MUNGA_L4/L4AUDRND.cpp @@ -383,9 +383,22 @@ void ALCcontext *context = alcCreateContext(device,NULL); alcMakeContextCurrent(context); // Master volume: AL_GAIN on the listener scales EVERY source. Default 0.6 - // (the raw samples are hot); override with BT_AUDIO_VOLUME=<0.0..1.0+>. + // (the raw samples are hot). Priority: BT_AUDIO_VOLUME env > + // content\volume.cfg (written by the runtime -/+ keys, issue #26) > 0.6. float masterVol = 0.6f; + { + FILE *cfg = fopen("volume.cfg", "rt"); + if (cfg != NULL) + { + float f = -1.0f; + if (fscanf(cfg, "%f", &f) == 1 && f >= 0.0f && f <= 1.5f) + masterVol = f; + fclose(cfg); + } + } if (const char *v = getenv("BT_AUDIO_VOLUME")) { float f = (float)atof(v); if (f >= 0.0f) masterVol = f; } + extern float gBTMasterVolume; + gBTMasterVolume = masterVol; alListenerf(AL_GAIN, masterVol); if (getenv("BT_AUDIO_LOG")) DEBUG_STREAM << "[audio] OpenAL device OPENED + context current; master gain=" << masterVol << "\n" << std::flush; // (task #50, AUDIO_FIDELITY F9/F11) EFX bridge: the authored lowpass @@ -1442,3 +1455,31 @@ void L4AudioRenderer::ReleaseSourceSet(SourceSet &sourceSet) #if defined(TRACE_AUDIO_RENDERER_DORMANT_SOURCES) BitTrace Audio_Renderer_Dormant_Sources("Audio Renderer Dormant Sources"); #endif + +// +//############################################################################# +// Master-volume runtime control (issue #26, 2026-07-23). The pod had a +// physical volume knob on the operator side; desktop players had NO way to +// duck the (hot) game audio under voice chat short of the Windows mixer. +// The -/= keys step the OpenAL listener gain (the master scale for every +// source); the value persists in content\volume.cfg (CWD) and reloads at +// the next boot (BT_AUDIO_VOLUME env still wins when set). +//############################################################################# +// +float gBTMasterVolume = 0.6f; + +void BTAudioMasterVolumeStep(int direction) +{ + gBTMasterVolume += (direction > 0) ? 0.05f : -0.05f; + if (gBTMasterVolume < 0.0f) gBTMasterVolume = 0.0f; + if (gBTMasterVolume > 1.5f) gBTMasterVolume = 1.5f; + alListenerf(AL_GAIN, gBTMasterVolume); + FILE *cfg = fopen("volume.cfg", "wt"); + if (cfg != NULL) + { + fprintf(cfg, "%.2f\n", gBTMasterVolume); + fclose(cfg); + } + DEBUG_STREAM << "[audio] master volume " + << (int)(gBTMasterVolume * 100.0f + 0.5f) << "%" << std::endl << std::flush; +} diff --git a/game/reconstructed/mech4.cpp b/game/reconstructed/mech4.cpp index 12cc607..7aee087 100644 --- a/game/reconstructed/mech4.cpp +++ b/game/reconstructed/mech4.cpp @@ -2746,6 +2746,24 @@ void // task #12: Generator1-4 actions assign the selected weapon // to Generator A..D; Reconnect toggles Manual/Auto. gBTGenSelKey = gBTInput.genSel; + // issue #26: -/= step the master volume (edge-detected; + // VK_OEM_MINUS/VK_OEM_PLUS, focus-guarded like all polls). + { + extern void BTAudioMasterVolumeStep(int direction); + static int sVolDn = 0, sVolUp = 0; + unsigned long fgpid = 0; + if (GetForegroundWindow() != 0) + GetWindowThreadProcessId(GetForegroundWindow(), &fgpid); + int focused_vol = (fgpid == GetCurrentProcessId()); + int dn = focused_vol + && (GetAsyncKeyState(VK_OEM_MINUS) & 0x8000) != 0; + int up = focused_vol + && (GetAsyncKeyState(VK_OEM_PLUS) & 0x8000) != 0; + if (dn && !sVolDn) BTAudioMasterVolumeStep(-1); + if (up && !sVolUp) BTAudioMasterVolumeStep(+1); + sVolDn = dn; + sVolUp = up; + } // task #13: the Valve action cycles the coolant valve. gBTValveKey = gBTInput.valve; // Gitea #7: the Flush action HELD = the coolant MFD's diff --git a/players/README.txt b/players/README.txt index 0bcae9c..259a179 100644 --- a/players/README.txt +++ b/players/README.txt @@ -41,6 +41,7 @@ CONTROLS (keyboard): 1 or Space ........... main trigger 2 ............. middle thumb 3 or Ctrl ............ upper thumb (missiles) 4 ............ pinky V view | B look-behind | M control mode | N schematic | J/K/L MFD pages + - / = ................ game volume down/up (saved between sessions) G (hold) + fire key .. regroup a weapon onto that trigger -- or hold a weapon panel's red PROGRAM button with the mouse and tap a fire key; the joystick diagram on the panel shows the binding live.