Single biggest change: added the Concentus.Native NuGet package. Concentus
2.0+ auto-detects native libopus at runtime and routes encode calls
through it; encoder state lives on the C side and is reused across calls
rather than `new`ing ~15 working buffers per call (Concentus issue #22,
open since 2018). Measured on the desktop test at 15:36:55 — Opus 10 ms
allocation rate dropped from 4,625 KB/s to 108 KB/s, a 97.7% reduction.
Process CPU dropped from 4.7% to 1.6% in the same config. Audio is bit-
for-bit identical (it's literally the same encoder, just better
packaged). `OpusEncoderState.cs` itself unchanged on the call site.
Diagnostic / measurement layer (gated on Enable-logs, zero cost when off):
* ProcessSelfMeter: CPU%, managed heap MB, working set MB, allocation
rate per second, GC counts per generation
* Per-thread work-time counters: captureMs / sendMs / recvMs / renderMs
expressed as milliseconds of CPU consumed by each audio thread per
second
* Inter-packet arrival gap measured at the user-space UDP socket
(rxNetGapMs) — pinpoints whether arrival jitter is in the network or
our own dispatch path
Small efficiency wins (each one was small but cumulative):
* deviceRefreshTimer interval 1s -> 3s (item 4)
* WaitHandle array allocations eliminated in MixingEngine.MixLoop and
MultiOutputPlayout.ProduceLoop (item 6)
* MultiOutputPlayout caches its output-buffer snapshot and only rebuilds
on SetOutputDevices, instead of rebuilding every 10 ms (item 7)
* HeartbeatService reuses an outbound ping byte[] instead of allocating
per send (item 14)
* PeerDiscoveryService caches broadcast addresses and invalidates on
Windows' NetworkChange event instead of walking all NICs every 1.5 s
(item 16)
Legacy / dead-code removal:
* KeepAlive packet's implementation (struct, enums, writer, reader, size
constant) — all dead since HeartbeatService landed 2026-05-06. Kept
the RemPacketType.KeepAlive enum value and silent-drop dispatch for
wire compat with any pre-2026-05-06 build still in the wild (item 30)
* driftDropFramesTotal / driftRepeatFramesTotal fields and accessors —
Phase-2 splice corrector relics, never incremented since Phase-4
resampler design landed; backed five always-zero diag log columns
(items 34 + 35)
* DriftAccumulator (always returned 0) — same shape, removed alongside
the driftAcc= column (item 35)
* TakeMaxFanOutCacheBytes / Ms + fanCacheMs column — FanOutSource was
retired in May (item 36)
Project documentation:
* RemSoundefficiency.md added as the canonical record of the efficiency
analysis, every item's status, and the measured wins from this round
* Honest item-by-item review of the original 50-item list — several
items I had sized optimistically in the original analysis turned out
to be already-done (item 20), already-optimal (item 22), or below
the meter floor (items 9, 15, 17, 25). Recorded so future passes
don't re-investigate.
Wire format and audio pipeline unchanged from v1.5 onward — v1.5 through
v2.2 peers interoperate.
Three reliability fixes. Wire format and audio pipeline unchanged from
v1.4 / v1.5 — all interoperate.
Peer address recovery:
* When a tracked peer goes Unreachable (its resolved address — often a
stale DNS / Pi-hole record, or a peer that rebooted onto a new IP) but
the same peer is still heartbeat-pinging us from a different address,
RemSound now adopts the live address instead of transmitting to a dead
one. HeartbeatService records untracked ping sources; MainForm's
TryAdoptLiveHeartbeatAddress (1 Hz) re-points the sender, heartbeat
tracking and receiver allow-list. Conservative: fires only on the
unambiguous one-unreachable-and-one-source case, private-range (RFC1918)
addresses only so a relay can't hijack the sender, 10 s cooldown.
Reconnect crash:
* Fixed IndexOutOfRangeException in MainForm.SyncConnectedList. A churny
peer-list rebuild (peer reboot) left SelectedIndex pointing past the
rebuilt item array; the 1 Hz status timer read SelectedItem and crashed
the app. New SafeSelectedItem bounds-checks the index; applied to all
three timer-driven sync methods. The status tick is also wrapped in
try/catch so a transient WinForms hiccup logs instead of crashing.
Long-run memory / CPU leak:
* A receiver left running for hours grew to gigabytes and climbing CPU.
Decoder sessions orphaned by peer reconnects were not reaped — every
reconnect mints a fresh (endpoint, streamId) key, and PruneIdleSessions
silently skipped sessions whose PlayoutEngine lookup missed. Rewrote it
to reap on each session's own LastWriteUtc (no cross-dictionary lookup),
added a hard MaxLiveSessions cap as a backstop, and a "stream sessions
live: N" diagnostic line. Bounds both memory and render-thread CPU.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>