# Audio Device Stability Policy

This document defines conservative audio-device lifecycle rules for the future
playback troubleshooting tool. It is a design constraint, not an implementation.

## Problem Statement

The application is meant to troubleshoot difficult playback paths, including
USB DACs and ASIO drivers. Some devices can behave poorly around stream stop,
idle, USB suspend, sample-rate changes, reset, or rapid close/reopen cycles.
The product must avoid making those conditions worse.

The user specifically called out XMOS-based USB audio devices as a risk class.
This policy treats XMOS, USB Audio Class 2, vendor ASIO drivers, DoP, and native
DSD paths as conservative lifecycle targets.

## Design Principles

- Device lifecycle transitions are part of the test and must be logged.
- Opening a device, starting a stream, stopping a stream, resetting a stream,
  changing format, and releasing a device are high-risk operations.
- Avoid rapid release/reinitialize loops.
- Prefer one initialization per selected backend/device/format/buffer profile.
- Prefer graceful drain and silent keep-alive over abrupt stop/reset.
- Do not change global Windows power-management or USB selective-suspend
  settings automatically.
- Recovery must be bounded. Reacquire attempts should have cooldowns and should
  stop after a configured retry limit.

## Required Device States

Future implementation should model device lifecycle explicitly:

- `Discovered`: Device was enumerated but not opened.
- `Reserved`: API-specific device object or driver was opened.
- `Prepared`: Buffers and format were accepted.
- `RunningSignal`: Test signal is being rendered.
- `RunningSilence`: Valid silence is being rendered to keep the stream alive.
- `Draining`: Signal stopped; queued frames are being allowed to finish.
- `HeldOpen`: Device remains initialized but not actively playing a test signal.
- `Releasing`: Graceful release is in progress.
- `Released`: Application no longer owns the device.
- `Faulted`: Device, driver, or stream returned an unrecovered error.

Every transition should include timestamp, backend, device ID, format, buffer
settings, and API result code.

## Hold-Open And Free Modes

The GUI should eventually expose these lifecycle choices:

- `Keep warm after stop`: keep the stream or driver initialized and feed valid
  silence after the 1 kHz signal stops. This should be the conservative default
  for unstable USB DAC or ASIO troubleshooting.
- `Hold initialized`: keep the device initialized but not actively submitting
  signal data if the backend supports this safely.
- `Release after drain`: drain queued frames, wait a cooldown interval, then
  release the device.
- `Immediate release`: manual diagnostic option only; not the default.

Important constraint:

- A fully released device is no longer controlled by the application. The app
  cannot guarantee that Windows, the USB stack, hub, firmware, or vendor driver
  will keep it awake. To avoid "device coma" during a troubleshooting session,
  the default should be keep-warm/hold-open, not fully free.

## Backend-Specific Rules

### WASAPI

- Use `IAudioClient::Initialize` once per selected stream profile.
- Log requested and actual buffer size through `GetBufferSize`.
- Log padding through `GetCurrentPadding`.
- Register session-disconnect notifications when available.
- Treat `AUDCLNT_E_DEVICE_INVALIDATED`, `AUDCLNT_E_RESOURCES_INVALIDATED`, and
  `AUDCLNT_E_SERVICE_NOT_RUNNING` as lifecycle events, not generic failures.
- For event-driven exclusive mode, ensure event handles are set before release.
- On invalidation, release interfaces once, wait a cooldown, then attempt bounded
  reacquire of the same selected endpoint unless the user chose default-device
  follow mode.

### ASIO

- Avoid repeated `ASIOExit` / driver unload cycles during a single session.
- Query and log buffer size min/max/preferred/granularity before creating
  buffers.
- Keep buffers running with valid silence when keep-warm is enabled.
- Log callbacks including `sampleRateDidChange`, reset/resync requests, and
  output-ready support.
- Treat native DSD sample-type support as driver-specific.
- Do not open the vendor ASIO control panel automatically.

### MME

- Prepare buffers once per selected stream profile.
- Prefer draining queued `waveOut` buffers over abrupt reset.
- Keep enough prepared headers queued to avoid starvation.
- Use reset only as an explicit diagnostic or fault-recovery action.

### DirectSound

- Restore lost buffers conservatively.
- Avoid changing cooperative level during a test session.
- Log play cursor, write cursor, lock/unlock results, and restore events.

### Kernel Streaming

- Treat filter handles, pin creation, pin state changes, allocator/framing
  negotiation, and stream writes as high-risk operations.
- Discovery and format probing must not start a pin stream.
- Require an explicit selected KS filter and render/sink pin before creating a
  pin instance.
- Avoid automatic pin recreate loops, repeated state cycling, and rapid
  format changes.
- Prefer valid silence keep-warm or held pin state over full close/reopen when
  the selected device is being diagnosed.
- Log filter path, pin ID, dataflow/communication, requested data format,
  accepted format/data range, allocator/framing fields where available,
  stream state changes, IOCTL/Win32 error codes, and audio-thread scheduling
  state.

### DoP And Native DSD

- Keep-alive silence must be format-correct:
  - PCM silence for PCM paths.
  - Valid DoP frames with correct marker alternation for DoP paths.
  - Valid DSD silence/idle pattern for native DSD paths.
- Never replace DSD keep-alive with arbitrary PCM silence on a DSD path.

## GUI Controls Required Later

- Hold mode: keep warm, hold initialized, release after drain, immediate release.
- Cooldown before release.
- Cooldown before reacquire.
- Maximum reacquire attempts.
- Keep-alive silence duration or indefinite toggle.
- Keep-alive level/pattern display.
- Disable rapid format cycling.
- Log lifecycle transitions.
- Warn when fully releasing a known-problem device profile.

## References

- Microsoft WASAPI stream management:
  https://learn.microsoft.com/en-us/windows/win32/coreaudio/stream-management
- Microsoft `IAudioClient::Initialize`:
  https://learn.microsoft.com/en-us/windows/win32/api/audioclient/nf-audioclient-iaudioclient-initialize
- Microsoft recovering from `AUDCLNT_E_DEVICE_INVALIDATED`:
  https://learn.microsoft.com/en-us/windows/win32/coreaudio/recovering-from-an-invalid-device-error
- Microsoft USB selective suspend:
  https://learn.microsoft.com/en-us/windows-hardware/drivers/usbcon/usb-selective-suspend
