Verified findings from a multi-dimension code audit, plus the two install-flow bugs:
- Fix Opus encoder use-after-free on a codec/rate change while streaming (guard swap vs encode).
- Fix "both" single-file recording dropping audio + drifting (drain both directions in lockstep).
- Fix broken clip counter, UPnP teardown on exit, auto-update-restart foreground grant, and a
malformed-Opus-format packet orphaning a playout session forever.
- Post-install relaunch now respects start-minimised; uninstall is path-aware so it won't clear a
different copy's run-at-startup.
- Perf/hygiene: cache AppConfig off UI hot paths, fold per-peer EQ+gain into one pass, deterministic
disposal (tray menu, timers, COM shortcut, Process handles, process meter), ring-buffer overflow
guard, receiver session-lock fix, remote-control allow-list moved onto the UI thread.
- Remove dead code (two IsAsioBackend, SessionPlayout.Reset, IsSameEndpoint, RemSoundUpdater
IDisposable); several stale-doc fixes.
Deferred (not in this release): drift-estimator tweak, peer-discovery pruning, uninstall retry-loop,
encryption nonce. Wire format unchanged (interops v3.3-v5.1). Version -> 5.2.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
* Connectivity tab order: Add peer by IP now sits right after Rename peer (before the Discovered
list), grouped with the connected-peer actions, per Ed's requested order. Dropped the second
section header (only the lock toggle was under it).
* Audio I/O labels: "Set volume for all received audio" → "Master volume for received audio" (the
code never got this rename, only the manual had). Device lists now say "audio": "...for received
audio" and "WASAPI/ASIO audio inputs/outputs to send". Labels + AccessibleNames updated together.
* Add EQ band dialog: the spin/edit boxes now select-all on focus, so a typed value REPLACES what's
there instead of being inserted next to it and reverting (typing 2.5 over 4.0 now works).
* Parametric bands list: Left/Right arrow nudge the selected band's gain by half a dB, live —
up/down still move between bands. NVDA re-reads the band's new dB.
* Recording settings: source list reordered to Both (top, now the default) / Received / Sent;
display order decoupled from the RecordingSource enum. Default RecordingSettings.Source = Both.
* Preferences: Colour theme is now first in the General tab order.
Manual updated. Build clean; --selftest passes; deployed to both test folders. Held for next release.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
The dialog set sourceList.TabIndex=0, so it grabbed initial focus and the user landed partway
down, past the two new toggles. Put the toggles first in tab order (and ordered the containers,
so the top row precedes the grid), and force focus to the split-tracks checkbox on show.
Held for next release.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recording Settings gains two per-profile toggles (Ed's request):
* "Split recording into separate tracks" — each recording becomes a folder with one file per
connected peer (their received audio only) plus one for your own send.
* "Bypass pan and EQ when recording" — record the RAW audio (before pan/EQ) instead of the
shaped audio you hear; applies to single and split.
Engine: a per-peer record tap in SessionPlayout hands each peer's block to the recorder RAW
(before pan/EQ) or SHAPED (after) per the bypass flag; PlayoutEngine propagates the tap to all
sessions (+ inherits on reconnect) and fires OnRecordBlockComplete each render; AudioReceiver
exposes SetPeerRecordTap / OnRecordBlockComplete. AudioRecorder now accepts an explicit path and
exposes ExtensionFor. RecordingController composes one AudioRecorder per track: multi-track =
a recorder per connected peer + a "me" recorder; single-track shaped = the existing mixed tap;
single-track raw (bypass) = sum each peer's raw block per render, flushed on the block boundary.
Naming (Ed's scheme, sortable): <recordings>/<yyyy-MM-dd>/ then, single-track, "<HH-mm-ss>
RemSound recording.<ext>"; multi-track, a folder "<HH-mm-ss> RemSound recording multi track/"
containing "<machine name> <HH-mm-ss>.<ext>" per peer (name or IP) and for your own send.
Known edge (noted): a peer using sender-side BothIndependent (two lanes) records both lanes to
one file in a split recording; single-track bypass sums per render in the Mixed path. Off by
default (both toggles unticked = today's behaviour). Builds clean; pending Ed's hands-on test.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Recording settings dialog
=========================
Promote what were row attributes inside the format-attributes table
into their own dedicated listboxes. Pre-rework each format's
attribute list contained a row per (quality knob × channel mode)
combination — doubling the row count for no real benefit. WAV had
6 rows, MP3 / OGG-Opus had 8, FLAC had 4. Channel mode is now its
own listbox; per-format attribute lists shrink to 3 (WAV), 4
(MP3 / OGG-Opus), 2 (FLAC).
FLAC compression level was previously a hidden RecordingSettings
field locked at the libFLAC default of 5. Now exposed as its own
conditional listbox with all 9 levels (0..8). Visible only when the
selected file format is FLAC; the column collapses to 0% width
otherwise so the dialog reads cleanly as 4 columns for non-FLAC
formats and 5 for FLAC.
Mnemonics:
* Source Alt+S (unchanged)
* File format Alt+F (unchanged)
* Attributes Alt+A (unchanged)
* Compression Alt+L (new, FLAC-only visible)
* Channels Alt+C (new)
* OK Alt+O (unchanged)
* Cancel Alt+N (was Alt+C — moved to free C for Channels)
Record menu mnemonics
=====================
Item mnemonics inside the Record menu reorganised so the keystroke
inside the menu matches the same letter used for Ctrl+R outside it,
and Settings reads naturally:
* Start recording / Stop recording Alt+R (was Alt+S)
* Recording settings Alt+S (was Alt+T)
* Open recordings folder Alt+O (unchanged)
* Change recordings folder Alt+C (unchanged)
UpdateStartStopRecordingMenuLabel keeps the underline on a literal
R in both states ("Sta&rt recording" → "Stop &recording") so the
keystroke does the same job regardless of which label is active.
No version bump — the running version stays at 1.3.0. These changes
will be bundled with the next public release alongside whatever else
is in flight.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
New user-facing features:
* Recording. Dedicated Record menu (Alt+O — moved from Alt+R to
avoid clashing with the Receive audio checkbox), Start/Stop on
Ctrl+R, settings dialog, per-profile source / format / bit-depth /
channel-mode / folder. Three source modes (received only, sent
only, both). Files are crash-resilient — a process crash
mid-recording leaves a playable file containing everything up to
the last header refresh (~5 seconds).
* Four output formats, all functional:
- WAV: 16/24-bit PCM or 32-bit float, custom writer with
periodic RIFF re-patching.
- MP3: LAME 128–320 kbps CBR (via NAudio.Lame).
- OGG-Opus: 96–256 kbps VBR (via Concentus.Oggfile, reusing the
Concentus encoder from the wire path).
- FLAC: 16/24-bit lossless (via CUETools.Codecs.FLAKE — pure
managed, no native DLL).
* Recording start/stop sound cues. record start.wav and
record stop.wav play around the recording transition. Played via
System.Media.SoundPlayer to the default Windows output, separate
from the recording pipeline so a normal recording does not contain
the cue.
* Per-cue Preferences. The old single "Mute connect/disconnect
sounds" checkbox is replaced by a CheckedListBox: Connect /
Disconnect / Recording start / Recording stop. Old profiles with
the legacy MuteConnectionCues=true are honoured on first load via
a migration path in the new Load* helpers.
* Receiver-side drift compensation switched from discrete
single-frame splices to a continuous WdlResampler at a smoothed
rate ratio. SessionPlayout.cs rewrite.
Diagnostics (only active with Enable logs ticked):
* Per-stage discontinuity probes — sender raw capture (per backend,
PushModeWasapi + Asio both wired), sender pre-encode (now per
lane in BothIndependent, fixing a cross-stream artefact), receiver
post-decode, post-ring, post-resampler.
* Wire-level packet sequence tracking on each PCM stream — in-order
/ missed / reordered / duplicated counts in the diag log.
* Clipped-sample delta in the diag log.
* New AudioStepProbe in RemSound.Core with per-channel scan helper.
UI changes:
* Record menu uses Alt+O (Rec&ord). Inside the menu, item mnemonics
unchanged (S / T / O / C).
* Auto-tune interval combo label is mode-aware: "Auto-tune latency
interval" in classic modes, "Auto-tune interval — WASAPI and ASIO"
in BothIndependent. The combo's Enabled state now follows EITHER
lane's auto-tune checkbox (was only the WASAPI one — bug).
Wire format and audio pipeline unchanged from v1.1 — v1.1 and v1.2
peers interoperate.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>