Release v3.7: device-change smoothing, auto-tune spike rejection, wider mic detector, forensic logging

Coalesce capture-engine rebuilds (CompositeCaptureBackend): a swap-triggering
source change now arms a 250ms debounce timer and re-arms on each further
change, so a flap or quick reconfiguration produces ONE rebuild to the final
state instead of a burst (Andre's 16:40 four-rebuilds-in-33s crackle). In-place
updates still apply immediately; a pending rebuild whose target flaps back is
cancelled.

Auto-tune (TickRoute) now keys off the SECOND-highest arrival-gap/render-gap
second in the lookback window instead of the single worst, so a lone ~1s
OS/driver stall no longer balloons the buffer to the 200ms cap (the 16:51
trim burst); sustained jitter still reacts at full speed. Logs both gap-max
(true peak) and gap-used (value acted on).

Mic-privacy detector widened: also catches a per-app Deny aimed at this exe
under ConsentStore\microphone\NonPackaged\<exe>, the HKLM NonPackaged gate,
and the Group-Policy/MDM force-deny (AppPrivacy LetAppsAccessMicrophone=2) —
the block shapes that silence WASAPI capture while ASIO sails past, and that
the old three-value check missed.

Forensic instrumentation so the next log proves what happened: capPeak=
(loudest pre-encode sample, per lane, on the diag line), mic-privacy verdict
logged at startup, ui: capture tick/untick events, and device-event: lines for
Windows endpoint changes.

Docs: mic-privacy + auto-tune sections updated in readme.html, MANUAL.md
regenerated, About-box changelog and RELEASE_NOTES for v3.7.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-06-10 22:44:55 +01:00
co-authored by Claude Fable 5
parent 55bdcde0af
commit 9e247112cb
9 changed files with 213 additions and 51 deletions
+9
View File
@@ -179,6 +179,15 @@ public sealed class AudioSender : IDisposable
public float TakeMaxPreEncodeStepWasapiLane() => defaultLane.TakeMaxPreEncodeStep();
public float TakeMaxPreEncodeStepAsioLane() => asioLane.TakeMaxPreEncodeStep();
/// <summary>Loudest absolute pre-encode sample across both lanes since the last call (resets on
/// read). ~0 means we're sending silence; surfaced on the diag line as capPeak.</summary>
public float TakeMaxSenderPreEncodePeak()
{
var a = defaultLane.TakeMaxPreEncodePeak();
var b = asioLane.TakeMaxPreEncodePeak();
return a > b ? a : b;
}
// Cross-buffer (boundary) and within-buffer (content) split — see AudioStepProbe for the
// diagnostic distinction. Used by the per-second diag logger to emit two extra columns so
// an offline log inspection can tell a real audio transient apart from a buffer-boundary