Skip to content

monitor: one audio status for every sound card, with frames moved and skipped by cause - #690

Open
jamesbraid wants to merge 1 commit into
audio/mace-testsfrom
audio/status
Open

jamesbraid wants to merge 1 commit into
audio/mace-testsfrom
audio/status

Conversation

@jamesbraid

@jamesbraid jamesbraid commented Nov 13, 2026 •

Copy link
Copy Markdown
Collaborator

audio status is now one machine-level monitor command that lists every sound card the machine has (HAL2, MACE audio, RAD1, the Tezro's ICE1724) in one layout, or says No audio device.. It replaces hal2 status, ice1724 status and MACE audio's own audio status.

Per output, each card shows the frames moved on its own clock and the guest rate, and, only when some occurred, the frames its clock made due that it skipped, by cause:

audio: MACE audio
  analog out 1: 128 moved, guest rate 8000 Hz
    skipped: stale 14000, dry 1872, ring full 0
  host: 0 underruns, 0 frames skipped, 0 dropped, queued 19.8 ms, delay 20.0 ms, adjust +0.001%
  host output: <device> at 48000 Hz, 2 channels
  • stale: the card fell behind real time and drops the lost time (HAL2 pacer backlog limit, MACE audio's quarter-second lag, ICE1724 clock jump and steering backlog, RAD1 ring laps it never walks).
  • dry: the guest's ring had nothing (MACE audio empty ring, HAL2 channel reads that returned nothing, RAD1 chain end or DMA failure, dropped once and taken into the channel's own count).
  • ring full: MACE audio's input ring.

The host side is not counted again. It is iris_audio::Stats for the card's outputs: underruns, frames skipped to hold latency, frames dropped on a full ring, queued sound, delay, clock adjustment, device and format. For MACE audio's two DAC voices the host line sums underruns, skipped and dropped, shows the most queued, and takes delay, adjustment and device from the first.

Wiring. New Device::audio_report (default None); the monitor prints every registered card's report. HAL2 reports through the HPC3, MACE audio through the O2 bus, and the Octane and Onyx2 now register RAD1. audio codec stays on MACE audio.

Size: 26 files, +505/-255. Production is not a net deletion: the machine-level dispatch and the skip causes cost more than the status dumps they replace.

Removed: hal2 status with its ISR, DMA, BRES, codec and AES dumps; Hal2State.iar_log and its recording; CodecAState.frames/calls/armed_ch/dry_reads; ice1724 status (converter write counts and unexpected() stay in Stats for snapshots and tests but are no longer shown); MACE audio's status text. Scripts and a clanker note that said hal2 status now say audio status.

Scrutinize

  • "moved" differs by card: MACE audio's DAC moves a frame per clock tick the ring supplied (an empty ring is dry); RAD1's moved no longer includes laps (stale); the ICE1724's is its saved engine count (snapshots and 26 test reads use it), which the report copies into the meter at command time, so there is no second counter. The ICE1724 counts only stale; its failed transfers still count as moved.
  • HAL2 counts codec A only; codec B and the AES channels are not counted. With no host output it still reads the channel without converting it.
  • help lists audio once, and only where a card can answer.
  • ICE1724 counts are as of the last timer pass.
  • Counters are relaxed atomics, once per timer pass or DMA chunk.
  • Ip27Machine::monitor() is a #[cfg(test)] accessor like the existing bridge().

Verified (all on the final head)

  • cargo check --workspace --all-targets, default and --features jitv2.
  • cargo test -p iris --lib -- hal2 mace_audio rad1 ice1724 host_audio host_pcm monitor hpc3 ip32:: ip30_machine ip53 ip27_deskside: 337 pass on Linux.
  • Tests that carry the change: exact report text; HAL2's pacer stall (injected time), dry reads, no-host read and report while codec A plays; MACE audio's stall and empty ring; RAD1's laps and chain end; the ICE1724 clock jump and report; the monitor with two cards, with none, and help listing audio once and only with a card; RAD1 reachable through the Octane and Onyx2 monitors, and "No audio device." on an Origin 2000. Fifteen of them ran 50 times alone and 50 times under four CPU hogs on two pinned CPUs: no failure.
  • Mutations that fail their test: HAL2 dry count removed, Octane RAD1 registration removed, monitor filter_map to find_map, HAL2 no-host conversion forced on, help duplicate-check removed.

Not run: audio status against a booted guest through the telnet monitor, a real sound device, macOS or Windows. No machine has two cards, so the several-cards listing uses two stub devices. The monitor no longer holds its device lock across the socket write; that is covered by review only (a regression test needs a stalled client).

@jamesbraid
jamesbraid added this pull request to stack #693 November 13, 2026 00:11
@jamesbraid
jamesbraid force-pushed the audio/status branch 3 times, most recently from bdbb254 to 7ab605b Compare November 13, 2026 11:20
…nd skipped by cause

Each sound device answered the monitor differently, or not at all:
`hal2 status` (a hundred lines of ISR, DMA, BRES, codec, AES and timer
state plus an indirect-access log), `ice1724 status` (frame counts and
converter write counts), MACE audio's own `audio status` (ring
pointers), and nothing on RAD1 in the Octane and the Onyx2. None said
whether a card's clock was moving, or why sound broke up, in a form
comparable across cards.

`audio status` is now one machine-level command. The monitor asks every
registered device for `Device::audio_report`, prints every card's report
(several at once if a machine has them) and answers `No audio device.`
on a machine with none. HAL2 reports through the HPC3, MACE audio through
the O2 bus, the Octane and Onyx2 now register RAD1, and the Tezro's
ICE1724 was already registered.

Each card's report has the same layout. Per output it shows the frames
moved on the card's own clock and the guest rate (`off` while idle), and,
only when some occurred, the frames the clock made due that were skipped,
by cause:

  stale      the card fell behind real time and drops the lost time:
             HAL2's pacer backlog limit, MACE audio's quarter-second lag,
             the ICE1724's clock jump and steering backlog (dropped time
             converted to frames by truncation, so exact to under a frame
             per event), RAD1's ring laps it never walks
  dry        the guest's ring had nothing: MACE audio's empty output ring,
             HAL2's channel reads that returned nothing, RAD1's chain end
             or DMA failure (dropped once and taken into the channel's own
             count so they are not owed again)
  ring full  MACE audio's input ring

What "moved" means differs by card and is not changed here: MACE audio
moves a frame per DAC clock tick the guest's ring supplied, RAD1's moved
count no longer includes the laps (they are stale), and the ICE1724's is
its saved engine count, which the report reads rather than keeping a
second counter (the ICE1724 counts only stale; its failed transfers still
count as moved). HAL2 counts codec A only, the one output that plays to
the host; codec B and the AES channels are not counted (it still reads
the channel with no host output, without converting it).

The host side is not counted again: the report prints what iris-audio's
stream already keeps for the card's outputs (`Stats`): underruns, guest
frames skipped to hold latency, frames dropped on a full ring, queued
sound, device delay, clock adjustment, and the device and its format.
For MACE audio's two DAC voices the host line sums underruns, skipped and
dropped frames, shows the most queued, and takes delay, adjustment and
device from the first.

Removed: `hal2 status` and with it the HAL2 ISR, DMA, BRES, codec and AES
dumps, the indirect-access log (`iar_log`) and the codec A counters only
it printed (`CodecAState.frames`, `calls`, `armed_ch`, `dry_reads`);
`ice1724 status` (its converter write counts and unexpected-access count
stay in `Stats` for snapshots and tests but are no longer shown); MACE
audio's status text (`audio codec` stays). Scripts that asked for
`hal2 status` now ask for `audio status`.

Counters are relaxed atomics added once per timer pass or DMA chunk, at
the site that already computes the frames. Counts are this run's, in the
card's own frames. Overall the change is +468/-255 by file path: source
files, with their inline test modules, +422/-226; separate tests.rs files
+28/-17; docs and scripts +18/-12.
@jamesbraid
jamesbraid removed this pull request from stack #693 November 14, 2026 14:15
@jamesbraid jamesbraid changed the title monitor: one audio status for every audio card, from shared counters monitor: one audio status for every sound card, with frames moved and skipped by cause Nov 14, 2026
@jamesbraid
jamesbraid added this pull request to stack #737 November 14, 2026 14:16
@jamesbraid
jamesbraid removed this pull request from stack #737 November 14, 2026 20:52
@jamesbraid
jamesbraid changed the base branch from main to audio/mace-tests November 14, 2026 20:52
@jamesbraid
jamesbraid added this pull request to stack #741 November 14, 2026 20:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant