fix(audio): game meter scales by GameAudioVolume — meter/stream/headphones all follow the one knob
Creator report 2026-09-01: with the desktop slider dragged to 20%, the game bar's
meter stayed pegged yellow/red. Root cause: the mic meter's formula (level x volume)
was cloned to the game bar WITHOUT the x-volume factor, and the clone inherited a
false premise — that WASAPI loopback capture tracks the endpoint volume. Tonight's
observation disproves it (the tap is pre-endpoint-volume), so both the meter (display)
and the mix (AudioGainProvider.LoopbackGain, fixed in 5ead064) must scale it themselves.
ai.md's two 'loopback scales with the slider' sentences corrected in the same pass.
Test seam: VolumePushOverride (internal static, mirrors LayoutPathOverride pattern) so
the test never hijacks the machine's real volume. GameMeterHonestyTests (RealApp +
temp DB): unity -> hot/red, 20% -> ~1/5 width/green, push observed.
This commit is contained in:
@@ -234,8 +234,18 @@ public partial class MainViewModel
|
||||
};
|
||||
// ─── Game audio bar (desktop/game): always visible — a mirror of the mic bar
|
||||
// ─── (meter + mute + volume). Desktop/game audio is automatic (WASAPI loopback). ───
|
||||
// Test seam (mirrors LayoutPathOverride/RegistrarOverride): the volume slider is
|
||||
// stream-honest AND speaker-honest — the real path writes the Windows endpoint.
|
||||
// Tests must never hijack the machine's actual volume, so they swap the push out.
|
||||
internal static Action<double>? VolumePushOverride;
|
||||
|
||||
private static void PushSystemVolume(double volume)
|
||||
{
|
||||
if (VolumePushOverride is { } push)
|
||||
{
|
||||
push(volume);
|
||||
return;
|
||||
}
|
||||
try
|
||||
{
|
||||
using var enumerator = new MMDeviceEnumerator();
|
||||
@@ -262,8 +272,11 @@ public partial class MainViewModel
|
||||
|
||||
/// <summary>Displayed game meter level: 0 while muted; the volume position
|
||||
/// while the slider is dragged (or briefly after an unmute flash); otherwise
|
||||
/// the realtime live level scaled by volume.</summary>
|
||||
private double GameMeterLevel => GameMuted ? 0 : _gameVolumeAdjusting || _gameVolumeFlash ? GameAudioVolume : Math.Min(1, AudioLevelMeter.ToDisplay((float)GameAudioLevel));
|
||||
/// the realtime live level scaled by volume — the WASAPI loopback tap is
|
||||
/// PRE-endpoint-volume (creator's 20%-volume/pegged-meter observation,
|
||||
/// 2026-09-01), so the meter must multiply by GameAudioVolume itself, exactly
|
||||
/// like the stream gain does (the mic formula always did; the clone dropped it).</summary>
|
||||
private double GameMeterLevel => GameMuted ? 0 : _gameVolumeAdjusting || _gameVolumeFlash ? GameAudioVolume : Math.Min(1, AudioLevelMeter.ToDisplay((float)GameAudioLevel) * GameAudioVolume);
|
||||
|
||||
public double GameMeterFillWidth => GameMeterLevel * 288;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user