v5 pre-release: multi-track drift fix, more self-tests, logging, CLI, version bump
Multi-track recording drift fix (Ed's question — can the separate tracks drift over an hour?): * Root: FlushPeerTracks skipped a peer that produced no samples in a render block, so a peer that went quiet long enough for its session to be pruned (>4 s idle) would have its track fall behind and desync. Now every peer track is padded to a full render block each cycle (silence when the peer produced nothing), so all peer tracks stay sample-locked to the single render clock — they can't drift apart however long the recording runs, and all end the same length. Same padding for the single-file bypass path. OnRecordBlockComplete now carries the block's float count. (The peer tracks are already resampled to the render clock per peer, so this makes peer-to-peer sync exact; your own "me" track is capture-clocked — same soundcard for capture+playback = same clock = no drift, different interfaces can drift slightly.) * Self-test: two new steps — "Per-peer shaping DSP" (PeerDspChain unity/master-off/volume/parametric + ParametricToPeaking) and "v5 settings and shaping round-trip" (AppConfig defaults, NamedPeers, MainTabOrder, parametric PeerShaping, recording default = Both). * Logging (gated by the logging checkbox): master shaping switch, EQ-mode change, parametric band add/delete, peer rename/clear/delete, and the applied Appearance settings after Preferences close. * CLI: --list-profiles and --list-named-peers (read-only), in --help. * Version bumped to 5.0; About-box changelog, RELEASE_NOTES.md and README updated for v5. Build clean; --selftest passes. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
fcc3cdc793
commit
aeca24ae17
@@ -206,7 +206,7 @@ public sealed class AudioReceiver : IDisposable
|
||||
|
||||
/// <summary>Fired once per rendered block, right after <see cref="OnReceivedSamples"/> — the block
|
||||
/// boundary a single-file bypass recording uses to flush its per-peer sum.</summary>
|
||||
public Action? OnRecordBlockComplete
|
||||
public Action<int>? OnRecordBlockComplete
|
||||
{
|
||||
get => playoutEngine.OnRecordBlockComplete;
|
||||
set => playoutEngine.OnRecordBlockComplete = value;
|
||||
|
||||
@@ -170,8 +170,10 @@ internal sealed class PlayoutEngine : IWaveProvider
|
||||
}
|
||||
|
||||
/// <summary>Fired once per rendered block, right after the mixed received tap — the block boundary a
|
||||
/// single-file "bypass" recording uses to flush its per-peer sum.</summary>
|
||||
public Action? OnRecordBlockComplete { get; set; }
|
||||
/// split / "bypass" recording uses to flush its per-peer sum. The argument is the block's interleaved
|
||||
/// float count (frames × channels), so the recorder can pad any peer that produced nothing this block
|
||||
/// with silence and keep every track sample-locked to the render clock.</summary>
|
||||
public Action<int>? OnRecordBlockComplete { get; set; }
|
||||
|
||||
public WaveFormat WaveFormat { get; } = WaveFormat.CreateIeeeFloatWaveFormat(MixSampleRate, MixChannels);
|
||||
|
||||
@@ -822,7 +824,7 @@ internal sealed class PlayoutEngine : IWaveProvider
|
||||
// BothIndependent; without the tag both ended up in one recorder ring, doubling the
|
||||
// file's effective sample rate).
|
||||
DispatchReceivedSamples(mixBuf.AsMemory(0, outFloats), route);
|
||||
OnRecordBlockComplete?.Invoke();
|
||||
OnRecordBlockComplete?.Invoke(outFloats);
|
||||
|
||||
Buffer.BlockCopy(mixBuf, 0, buffer, offset, outFloats * sizeof(float));
|
||||
return count;
|
||||
@@ -899,7 +901,7 @@ internal sealed class PlayoutEngine : IWaveProvider
|
||||
// wasapi-slot ring (canonical single-lane slot in classic modes), so this fires
|
||||
// exactly once per real-time second.
|
||||
DispatchReceivedSamples(mixBuf.AsMemory(0, outFloats), RenderRoute.Mixed);
|
||||
OnRecordBlockComplete?.Invoke();
|
||||
OnRecordBlockComplete?.Invoke(outFloats);
|
||||
|
||||
Buffer.BlockCopy(mixBuf, 0, buffer, offset, outFloats * sizeof(float));
|
||||
return count;
|
||||
|
||||
Reference in New Issue
Block a user