Add priority mode + always-on network packet priority

Priority mode (per-profile toggle, Audio profile tab, Alt+U):
- Bundled PROCESS_POWER_THROTTLING_STATE with EXECUTION_SPEED and
  IGNORE_TIMER_RESOLUTION flags (keeps CPU at full clock + 1 ms quantum
  pinned regardless of OS idle decisions)
- PowerSetRequest(EXECUTION_REQUIRED) + SetThreadExecutionState so the
  system can't decide we're idle and downclock
- timeBeginPeriod(1) for 1 ms scheduler quantum
- ProcessPriorityClass.High, ProcessMemoryPriority normal, working-set
  minimum locked via SetProcessWorkingSetSizeEx(HARDWS_MIN_ENABLE)
- Fully reversed on toggle-off and on form close
- Off by default (battery cost on laptops); explicit opt-in per profile

MMCSS thread priority on hot threads bumped from High to Critical
(network listener, mix loop, render thread) — always on.

Network packet priority (always on, no toggle):
- qWAVE flow on the outbound UDP socket at QOS_TRAFFIC_TYPE_VOICE with
  QOS_NON_ADAPTIVE_FLOW (Voice priority, DSCP 46/EF, WMM Voice on Wi-Fi)
- Silent fallback if qwave.dll missing or QoS service disabled
- Sender + receiver kernel UDP buffers bumped to 1 MB each (was
  256 KB send / 512 KB receive) for resilience against ~30 ms stalls

Bug fix: PreferencesDialog logging toggle no longer flags the profile
as dirty. Logging is a machine-local AppConfig setting; the spurious
ChangedAnyProfileSetting flag was triggering the unsaved-changes prompt
on exit after toggling logs alone.

Manual updated: new "Use CPU and Windows performance settings in high
priority mode (Alt+U)" subsection on the Audio profile tab, new
"Network packet priority (qWAVE / Voice / WMM)" subsection in the
network chapter, Alt+U row added to keyboard-shortcuts table.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Ednunp
2026-05-14 11:21:58 +01:00
co-authored by Claude Opus 4.7
parent 146e76c6e6
commit 768875cebb
10 changed files with 731 additions and 14 deletions
+5 -1
View File
@@ -45,7 +45,11 @@ internal sealed class NetworkListener : IDisposable
cts = new CancellationTokenSource();
socket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
socket.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
socket.ReceiveBufferSize = 512 * 1024;
// 1 MB kernel receive buffer — large enough to ride out ~30 ms of audio-thread or GC
// stall at typical PCM-stereo bitrates before the kernel starts dropping inbound
// datagrams. Cheap on modern Windows; the old 512 KB cap was below what the receive
// thread can saturate during a long-tail GC pause.
socket.ReceiveBufferSize = 1024 * 1024;
socket.Bind(new IPEndPoint(IPAddress.Any, udpPort));
var startedSocket = socket;