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:
@@ -76,6 +76,13 @@ internal sealed class SenderLane
|
||||
public float TakeMaxPreEncodeStepCrossBuffer() => preEncodeStepProbe.TakeMaxCrossBuffer();
|
||||
public float TakeMaxPreEncodeStepWithinBuffer() => preEncodeStepProbe.TakeMaxWithinBuffer();
|
||||
|
||||
// Loudest absolute sample seen on this lane's pre-encode buffer since the last drain (resets on
|
||||
// read), surfaced on the diag line. ~0 = we are sending silence (mic blocked / muted / wrong
|
||||
// endpoint); a clear non-zero = real audio is reaching the encoder. This is the signal level the
|
||||
// log never had — which is exactly why a "mic sends silence" report couldn't be confirmed from it.
|
||||
private float preEncodePeak;
|
||||
public float TakeMaxPreEncodePeak() { var p = preEncodePeak; preEncodePeak = 0f; return p; }
|
||||
|
||||
// Which render route this lane announces in its format packets. The receiver reads the
|
||||
// Lane byte on the wire and tags the matching SessionPlayout, which makes PlayoutEngine
|
||||
// route the lane's audio to the corresponding per-route IWaveProvider surface (lane
|
||||
@@ -190,6 +197,14 @@ internal sealed class SenderLane
|
||||
// <see cref="preEncodeStepProbe"/> field comment for why this isn't shared with the
|
||||
// other lane in BothIndependent.
|
||||
preEncodeStepProbe.ScanStereo(span);
|
||||
// Capture-level peak alongside the discontinuity probe — the loudest sample about to be sent.
|
||||
var peak = preEncodePeak;
|
||||
for (var s = 0; s < span.Length; s++)
|
||||
{
|
||||
var a = span[s] < 0f ? -span[s] : span[s];
|
||||
if (a > peak) peak = a;
|
||||
}
|
||||
preEncodePeak = peak;
|
||||
|
||||
switch (owner.Codec)
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user