fix(dock): meters beat on their own 20 Hz clock, and TRAX silence is diagnosed
Reported: TRAX plays audibly but no ladder registers anywhere. Two distinct faults, one of them mine: 1. The meter readouts were refreshed only from the MIC's level callback. With a silent or absent mic there is no tick, so a playing TRAX never updated its ladder — the level was measured, the UI simply never asked for it. Meters now have a 20 Hz DispatcherTimer of their own. 2. If the player's own meter still reads 0 while playing, the samples are not reaching the device (or metering is not attached). That now writes ONE line to startup.log after 2s — so the next report says which side is broken instead of another round of guessing. Note: TRAX rides the desktop loopback, so once the mix captures it the GAME ladder should move too; if it does not, the loopback endpoint and the music's output device differ.
This commit is contained in:
@@ -13,6 +13,49 @@ namespace ytLive.ViewModels;
|
||||
|
||||
public partial class MainViewModel
|
||||
{
|
||||
private readonly DispatcherTimer _meterTimer;
|
||||
private int _traxSilentTicks;
|
||||
private bool _traxSilenceLogged;
|
||||
|
||||
/// <summary>The dock's heartbeat: every meter readout is refreshed here, 20 times a second,
|
||||
/// from whatever the audio threads last measured.</summary>
|
||||
private void TickMeters()
|
||||
{
|
||||
OnPropertyChanged(nameof(MicMeterFraction));
|
||||
OnPropertyChanged(nameof(MeterFillWidth));
|
||||
OnPropertyChanged(nameof(MeterBrush));
|
||||
OnPropertyChanged(nameof(GameMeterFraction));
|
||||
OnPropertyChanged(nameof(GameMeterFillWidth));
|
||||
OnPropertyChanged(nameof(GameMeterBrush));
|
||||
OnPropertyChanged(nameof(TraxMeterFraction));
|
||||
RaiseMasterReadouts();
|
||||
UpdateDuckState();
|
||||
CheckTraxSilence();
|
||||
}
|
||||
|
||||
/// <summary>One honest diagnostic: "playing" with a flat player meter means the samples never
|
||||
/// reached the device (or the metering was not attached). Logged once per playback, so the next
|
||||
/// run says which side is broken instead of another round of guessing.</summary>
|
||||
private void CheckTraxSilence()
|
||||
{
|
||||
if (!IsMusicPlaying)
|
||||
{
|
||||
_traxSilentTicks = 0;
|
||||
_traxSilenceLogged = false;
|
||||
return;
|
||||
}
|
||||
if (_musicPlayer.Level > 0f)
|
||||
{
|
||||
_traxSilentTicks = 0;
|
||||
_traxSilenceLogged = false;
|
||||
return;
|
||||
}
|
||||
if (++_traxSilentTicks < 40 || _traxSilenceLogged) return; // 2s at 20 Hz
|
||||
_traxSilenceLogged = true;
|
||||
AppLog.Write("TRAX: playing but the player meter reads 0 — the output device is silent or " +
|
||||
"the metering stream is not attached (the dock's ladder has nothing to show)");
|
||||
}
|
||||
|
||||
private readonly DispatcherTimer _volumeFlashTimer;
|
||||
private readonly DispatcherTimer _gameVolumeFlashTimer;
|
||||
private double _audioLevel;
|
||||
|
||||
Reference in New Issue
Block a user