Volume/pan/EQ tab overhaul: one master switch, peer checklist, 16-band parametric EQ

Reworks the per-peer shaping tab (held for next release):

 * Renamed the tab to "Volume, pan and EQ for peers"; the Preferences toggle now defaults ON.
 * Collapsed the two master switches (Enable EQ / Enable pan) into ONE: "Enable volume, pan and
   EQ for all peers" (Alt+E). Volume now obeys it too. PeerDspChain.Build takes a single enabled
   flag; Profile.EnableAllPeerShaping replaces the two bools (old ones kept for load-migration).
 * Peer picker is now a CheckedListBox: ticking a peer shapes them (per-peer bypass via new
   PeerShaping.Enabled, default true); the focused row is the one the controls edit. Effective
   shaping = master switch AND that peer's tick. Letter-nav suppressed so keys never toggle a tick.
 * Three EQ modes, renamed: "3 band simple EQ", "12 band advanced graphic EQ", and the new
   "16 band parametric EQ" (PeerEqMode.Parametric16Band).
 * Parametric EQ: up to 16 user bands, each a boost/cut across a start->end range (PeerShaping
   .ParametricBands; ParametricToPeaking maps range -> peaking centre+Q, shared by DSP and curve).
   Add band dialog (spin-or-type, numeric-only, live preview, OK/Escape); Bands list sorted
   bass->treble reading "X Hz to Y Hz, plus/minus N dB"; Delete key / Delete button, multi-select.
   Set peer EQ to default clears the parametric list too.
 * dB now spoken as words ("plus 3 dB" / "minus 6 dB" / "flat") on the graphic sliders and the
   parametric list, since NVDA users typically have punctuation off and never hear a "+".
 * New unbound machine-wide global shortcut "Toggle volume, pan and EQ for all peers" (not stored
   in any profile) via the hotkey controller + settings store.
 * Renamed the Inputs/outputs "Set volume for all received audio" to "Master receive volume".
 * Added EqCurveControl: a purely-visual EQ response graph (not focusable, invisible to NVDA).
 * Full manual sweep (readme.html + regenerated MANUAL.md).

Build clean; --selftest passes. Deployed to both test folders. Held for next release.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-07-07 23:21:18 +01:00
co-authored by Claude Opus 4.8
parent eaae76d015
commit 033edd776f
102 changed files with 4658 additions and 135 deletions
+65
View File
@@ -0,0 +1,65 @@
# deploy-test.ps1 - Ed's test-deploy. proj\remsound\default sounds is the AUTHORITATIVE sound master.
#
# As of 2026-06-13 the shipped DEFAULT cue sounds live in a "default sounds\" folder next to the exe
# (AppConfig.SoundsDirectory) - they're part of the install, not per-user state, so an update (or a
# republish) always overwrites them and a tweaked default always lands. The user's OWN custom sounds
# are NOT here: they're explicit file paths set via the Preferences "Browse" picker, kept in the
# user's own location, which nothing here touches.
#
# Every run of THIS script force-copies the ENTIRE source "default sounds\" folder over BOTH test
# locations' copies, overwriting every file regardless of timestamp/size (/IS /IT). Ed can tweak any
# number of sounds, with any timestamps, without telling anyone which changed - the next deploy
# always takes them all. (A running app reads each WAV fresh on every play, so a sound tweak even
# takes effect live, no restart needed.) Binaries + program files go out too, skipped automatically
# if RemSound is open and has them locked.
#
# Run: powershell -ExecutionPolicy Bypass -File deploy-test.ps1
$ErrorActionPreference = 'Stop'
$repo = $PSScriptRoot
$proj = Join-Path $repo 'src\RemSound.App\RemSound.App.csproj'
$srcSounds = Join-Path $repo 'default sounds'
$publish = Join-Path $repo 'publish'
# The TWO test run-locations. Each has its own 'default sounds\' copy that must be kept current.
$runLocations = @($publish, 'D:\Dropbox\remsound')
function Invoke-Robocopy([string[]]$rcArgs) {
& robocopy @rcArgs /NFL /NDL /NJH /NJS /NP /R:3 /W:1 | Out-Null
if ($LASTEXITCODE -ge 8) { throw "robocopy failed ($LASTEXITCODE): $($rcArgs -join ' ')" }
}
$soundOnly = @(Get-Process RemSound -ErrorAction SilentlyContinue).Count -gt 0
if ($soundOnly) {
Write-Host "RemSound is running - refreshing SOUNDS only (binaries are locked; close RemSound to update them)." -ForegroundColor Yellow
}
else {
Write-Host "Publishing (Release) -> $publish ..." -ForegroundColor Cyan
& dotnet publish $proj -c Release -o $publish --nologo -v q
if ($LASTEXITCODE -ne 0) { throw "dotnet publish failed ($LASTEXITCODE)" }
}
foreach ($loc in $runLocations) {
# Binaries: publish\ already has them from the publish above; copy them to the other location(s).
if (-not $soundOnly -and $loc -ne $publish) {
Write-Host "Deploying program + binaries -> $loc (preserving user settings/logs) ..." -ForegroundColor Cyan
Invoke-Robocopy @($publish, $loc, '/E') # no /MIR: never delete the user's settings/logs/profiles
}
# THE point of this script: the whole source 'default sounds' folder, force-copied over THIS
# location's copy, every time. /IS = copy even files robocopy thinks are identical; /IT = copy
# "tweaked" files. No /XO (don't skip on timestamp) and no /MIR (don't delete files).
$locSounds = Join-Path $loc 'default sounds'
Write-Host "Force-syncing 'default sounds' -> $locSounds (source wins, every time) ..." -ForegroundColor Cyan
New-Item -ItemType Directory -Path $locSounds -Force | Out-Null
Invoke-Robocopy @($srcSounds, $locSounds, '*.wav', '/IS', '/IT')
# One-time tidy: drop the orphaned pre-2026-06-13 program 'sounds\' folder and the defunct old
# per-user sounds folder if they're lingering from before the move (the running app also deletes
# the per-user one on launch). Idempotent - a no-op once gone.
foreach ($orphan in @((Join-Path $loc 'sounds'), (Join-Path $loc 'user settings and logs\sounds'))) {
if (Test-Path -LiteralPath $orphan) { Remove-Item -LiteralPath $orphan -Recurse -Force -ErrorAction SilentlyContinue }
}
}
$count = @(Get-ChildItem $srcSounds -Filter *.wav).Count
Write-Host "Done. $count default sounds force-synced to BOTH test locations. Tweak away - the next run always takes them all." -ForegroundColor Green