Audio Subsystem Audit (M44)

VerifiedCaution

Deep audit of the M44 audio subsystem (kira backend, spatial sub-tracks, reverb send, streaming music) and its engine callers, orchestrated across task agents.

Sby Skills Guide Bot
DevelopmentAdvanced
11/7/2026
Claude Code
#code-audit#rust#audio#game-engine#kira

Recommended for

Automated summary

Audits the M44 audio subsystem (kira backend, spatial sub-tracks, reverb send, underwater filter, voice and streaming music) along with the engine systems that are its only callers, producing deduplicated findings per dimension.

Strengths

  • Orchestrates one Task agent per dimension (max 3 concurrent) on top of a shared delta-first scoping and finding-format protocol.
  • Draws explicit handoff boundaries with neighbouring audits (water state to physics, ordering to ECS/concurrency) so findings are not duplicated.
  • Clearly separates shipped from not-yet-shipped features and cites the open issues (#3816, #3086, #5526, #5464, #5912…) behind each gap.
  • Grounds verification in concrete references: the lib.rs module docstring, docs/feature-matrix.md, and the crate's test and fuzz files.

Limitations

  • Tightly bound to one specific repository (paths, component names, issue numbers), so it is hard to reuse as-is elsewhere.
  • Relies on companion files (_audit-common.md, _audit-severity.md) that are missing from the supplied SKILL.md, and the text cuts off mid-sentence on issue #3086.
  • Feature status is dated 2026-10-20 and must be re-verified on every run.
When to use it

Use it when you need a deep review of the audio crate and its engine call sites, for example before a release or after changing audio code.

When not to use it

Do not use it for a different subsystem or repository, or when the shared audit protocol and expected crate layout are not present.

Security analysis

Caution
Quality score84/100

The skill is a read/verify-oriented audit workflow: git/grep inspection, targeted cargo test runs, subagent fan-out, and a report written into the repo. Its only destructive action is deleting its own /tmp scratch directory, and nothing sends data out or touches secrets. It is rated caution rather than safe because it drives an execution-capable toolchain (cargo test, ignored/device test lane, shell, 3 concurrent subagents) and mutates the working tree, so a reviewer should expect real command execution against a local repository.

Findings
  • •Executes shell commands: `mkdir -p /tmp/audit/audio`, `cargo test -p byroredux-audio`, `git log`, `git grep` — cargo test compiles and runs arbitrary repository code, and the skill instructs re-running the suite with `-- --ignored` (device-gated/FFN-data lifecycle tests), expanding the executed surface.
  • •Destructive command present but tightly scoped: `rm -rf /tmp/audit/audio` at merge time. Low blast radius, but a literal `rm -rf` on a path variable is a pattern worth hardening (quote/validate the path).
  • •Spawns up to 3 concurrent Task subagents with open read access to the repo and tooling, then writes output into `docs/audits/AUDIT_AUDIO_<TODAY>.md`, mutating the working tree without an explicit confirmation step.
  • •Depends on reading sibling instruction files (`.claude/commands/_audit-common.md`, `_audit-severity.md`) whose contents are not shown here; a modified/compromised common protocol file would silently steer this audit.
  • •Recommends a follow-on command (`/audit-publish`) as the final step, chaining execution beyond the audited scope.
  • •No network fetches, credential access, exfiltration, obfuscated payloads, or safety-disabling instructions found; no prompt-injection attempts detected in the skill body.
  • •Directs the agent to execute repository build/test binaries (`cargo test -p byroredux-audio`, `cargo test -p byroredux -- audio dialogue_voice`, and `-- --ignored` device-gated lanes), i.e. compiling and running arbitrary in-repo code, plus `git log`/`git grep` shell invocations. Legitimate for an audit skill, but it is real code execution with no declared allowed-tools.
  • •Contains a scoped destructive command: `mkdir -p /tmp/audit/audio` ... `rm -rf /tmp/audit/audio`. The path is narrow and self-owned, but an agent that mis-substitutes the variable could widen the blast radius; the cleanup should be quoted/guarded.
  • •Describes a bridge that pipes untrusted game-asset WMA payloads through an external `ffmpeg` process (crates/audio/src/fuz.rs). Not an instruction to the auditor, but the audited surface parses attacker-controllable binary containers via a third-party binary — worth noting as a risk the skill is asking the agent to reason about.
  • •No prompt-injection, exfiltration, credential access, obfuscated payload, or safety-disabling instruction found in the content; the document reads as genuine internal audit runbook material.
How this analysis is made

Examples

Deep spatial audio audit
Run the M44 audio audit at deep depth, focusing on the kira backend and the spatial sub-tracks.
Reverb and underwater paths
Audit the reverb send, reverb zones and the underwater filter at shallow depth and report findings in the shared format.
Engine callers check
Check the engine-side callers of the audio crate — footsteps, water audio, REGN ambient music and voice — for stale or missing API usage.

description: "Deep audit of the M44 audio subsystem — kira backend, spatial sub-tracks, listener/unit seam, reverb send, underwater filter, streaming music — plus its engine callers (footsteps, water audio, reverb zones, REGN ambient music)" argument-hint: "--focus <dimensions> --depth shallow|deep"

Audio Subsystem Audit (M44)

Read .claude/commands/_audit-common.md (delta-first scoping, dedup, finding format) and _audit-severity.md for shared protocol.

Audits crates/audio/ (kira 0.12, default-features = false with an explicit feature list in the workspace Cargo.toml — cpal, wav+pcm, ogg+vorbis, mp3, flac; 0.12 split container from codec features, so dropping a codec silently stops decoding (mp3 now carries Oblivion voice); src/lib.rs + src/tests.rs + src/fuz.rs, the .fuz/xWMA container reader and ffmpeg bridge) and the engine systems that are the ONLY callers of its API. Orchestrator; one Task agent per dimension (max 3 concurrent). Verify the shipped surface against the lib.rs module docstring and docs/feature-matrix.md (Audio); if lib.rs splits, re-derive each dimension's paths first.

Scope

  • Crate: AudioWorld (Option<AudioManager> resource; headless() is the no-device constructor), AudioListener / AudioEmitter / OneShotSound components, Attenuation, audio_system, SoundCache, VoiceSoundCache, load_*sound*, with_start_delay.
  • Engine side: byroredux/src/systems/audio.rs (footstep_system, impact_audio_system, reverb_zone_system, water_audio_system), the combat-feedback sound half of byroredux/src/systems/combat_anim.rs (play_oneshot_cached; take/animation half is /audit-gameplay), byroredux/src/systems/dialogue_voice.rs (voice consumer), byroredux/src/systems/scripted_sound.rs (script Sound.Play), SoundCache / VoiceSoundCache boot inserts (boot/world.rs) + telemetry (ownership_sample.rs), the footstep / impact / water-audio resources in byroredux/src/components/audio.rs (FootstepConfig, ImpactConfig, WaterAudioConfig) and RegionAmbientRes in byroredux/src/components/environment.rs, byroredux/src/asset_provider/{audio,texture}.rs (dispatch_region_ambient_music, SoundArchiveProvider, sound_is_folder, try_load_default_footstep), wired from cell_loader/load.rs and scene::apply_cell_region_ambient.
  • Handoffs: water state (SubmersionState, splash/ripple production) is /audit-physics Dim 5; stage/lock shape is /audit-ecs / /audit-concurrency (report audio-specific ordering only).

Not shipped as of 2026-10-20 (re-verify against docs/feature-matrix.md; audit the mechanism that will carry them): FOOT/IPDS/IPCT records → per-material footstep and clutter-impact content (the Wave-4 mechanism is live — Havok surface_material u32 → FootstepConfig/ImpactConfig surface_sounds — but both maps and ImpactConfig::default_sound ship empty, so impact_audio_system is a production no-op and footsteps always take the default), CELL-level MUSC routing (default_music/music_type_form are parsed; every construction site still hardcodes music_type_form: None), per-cell acoustics beyond binary interior/exterior reverb, occlusion, REGN incidental/ambient-loop selection (#3301 open). Dialogue voice now covers every voiced title (Dim 5): Oblivion's race/sex .mp3 (#5526 fa7591ca2, through kira's mp3 feature) and Skyrim+ .fuz (FUZE + raw .lip + RIFF xWMA, not XMA2 — #5464 1c69389b7; crates/audio/src/fuz.rs parses it and bridges the WMA payload through the host's OPTIONAL ffmpeg to a hand-headed WAV, since no workspace decoder reads WMA — no ffmpeg ⇒ subtitle estimate, #5912 acd577a79). Known-open (verified 2026-10-20): #3816 (MUSC/MUST/MSET/RDMD decode: REGN music_form never resolves as a SOUN on any supported game, so the dispatch mechanism is live and tested but plays nothing in production; audit the mechanism, cite #3816 for the gap). #3086 (entity-path spatial position frozen at dispatch) is closed (b4f08089b): sync_emitter_positions now follows the source GlobalTransform (Dim 1) — a frozen position is a regression. #4146 (reverb-zone ordering comment drift) is closed — a third drift is a regression. #5432 is closed (40b77828b): AudioWorld::stop_sounds_for (#5410) now has production callers through dialogue_voice::stop_line_voice — topic change, conversation close and speaker death cut the line (Dim 1/5); a new line-ending path that skips it is the regression. #5148 is closed (7208af67c): combat.status reports per-kind request counts (CombatSoundRequests: swing / impact / death_voice, counted only when play_oneshot_cached actually requested a one-shot) and the Skyrim P2 gate requires >= 1 impact + >= 1 death-voice, so oneshots_requested is no longer the gate's only signal. #4743 is closed (519bb02c4): impact one-shots queue per HitEvent ahead of the Dead / active-take branches (mid-stagger hits and the killing blow sound) and the swing sound rides the marked aggressor's own attack take; pinned by a_hit_during_an_active_take_still_sounds beside the existing killing-blow / aggressor-swing tests.

Parameters

--focus <dims> (default all 5) · --depth shallow|deep (deep traces per-frame data flow + lifecycle). Extra field: Dimension: Spatial Dispatch & Listener | Send Graph (Reverb + Underwater) | Music & SoundCache | Manager & ECS Lifecycle | Engine Consumers.

Phase 1: Setup

  1. mkdir -p /tmp/audit/audio; dedup per _audit-common.md; read the latest docs/audits/AUDIT_AUDIO_*.md (date D = delta baseline). A re-flag of a closed finding is a regression claim: check its guard is gone before reporting.
  2. cargo test -p byroredux-audio and cargo test -p byroredux -- audio dialogue_voice; record counts. The lifecycle guards are #[ignore]d (need an audio device, some FNV data): looping_emitter_survives_natural_duration_and_stops_on_emitter_remove, non_looping_emitter_stops_on_emitter_remove_regression_858, play_music_looping_survives_track_end, play_music_drives_streaming_playback_on_real_ogg, emitter_position_follows_the_source_entity_regression_3086, anchored_voice_follows_survives_prune_and_stops, plus the playback/decode trio play_oneshot_queue_drives_real_playback, audio_system_full_lifecycle_on_real_fnv_sound, real_fnv_sounds_decode_through_kira. Despawn truncation, follow, anchored-voice stop and music looping are unguarded in the default lane: run -- --ignored or say so.

Phase 2: Dimensions

Dim 1: Spatial Dispatch, Listener & the Unit Seam

Paths: crates/audio/src/lib.rs (dispatch_new_oneshots, drain_pending_oneshots, build_spatial_track, prune_stopped_sounds, sync_listener_pose, sync_emitter_positions, bu_to_audio_space, linear_volume_to_db, ActiveSound, SoundSource, play_oneshot_following, stop_sounds_for) First step: git log --since=D -- crates/audio/src/lib.rs Guards (default lane): tests.rs::{every_kira_position_site_goes_through_the_unit_seam, emitter_at_max_distance_in_bu_lands_on_max_distance_in_audio_space, drain_pending_oneshots_drains_in_place_instead_of_stranding_capacity, play_oneshot_queue_caps_at_max_pending_when_active, oneshot_marker_is_consumed_on_both_dispatch_failure_arms, with_start_delay_sets_the_start_time_and_shares_frames, play_oneshot_following_drops_on_inactive_audio, stop_sounds_for_is_a_no_op_on_a_headless_world}; #[ignore]d device-gated emitter_position_follows_the_source_entity_regression_3086 (#3086) and anchored_voice_follows_survives_prune_and_stops (#5410).

  • Two dispatch paths stay observably equivalent: entity path (OneShotSound+AudioEmitter → per-emitter SpatialTrackHandle, SoundSource::Emitter, marker removed, AudioEmitter kept) and queue path (PendingOneShot, never loops: play_oneshot → SoundSource::Detached, or play_oneshot_following → SoundSource::Anchored(entity), #5410 d1a7ee8c6). Both early-return without a listener id and build their sub-track through the one build_spatial_track (distance window, reverb send, underwater filter, kira sub-track; each loop keeps only its play tail and error policy, #5738 eac602644) — a loop that hand-builds the chain again is the regression. stop_sounds_for(entity, fade_ms) fades every playing Emitter/Anchored sound of the entity and drops its queued segments; its production caller is dialogue_voice::stop_line_voice (150 ms fade; apply_selection, end_open_conversation, reconcile_dead_actor, and ahead of each ObScript Say line in scripted_line_voice_system; #5432). The entity path has NO engine producer — spawn_oneshot_at is test/tooling-only, so its dispatch is exercised by tests.rs alone (#5612 81207d34d).
  • ActiveSound::track is held for its Drop side effect AND carries the #3086 position pushes (renamed from _track; the track must still be kept alive): it must land in active_sounds before the helper returns. Arc<StaticSoundData> is shared, never deep-cloned; volume applies via (*sound).clone().volume(db).
  • oneshots_requested is a monotonic count of play_oneshot / play_oneshot_following calls including headless discards (incremented before the manager gate; read by combat.status in commands/view.rs for device-less smoke gates) — it proves a request, never audible playback.
  • Producer queue caps at 256 (in both play_oneshot* entry points, each with its own MAX_PENDING) with O(1) pop_front and drops up front when the manager is None; the manager-active gate precedes the drain; a drain of more than 32 warns once per tick (footstep tempo gone wrong). linear_volume_to_db is the single dB conversion (floor SILENCE_DB -60).
  • Entity path reads post-propagation GlobalTransform, not Transform. World is Bethesda units (70/m), kira is metres: bu_to_audio_space is the only seam, applied to the listener pose and both dispatch paths; Attenuation is authored in metres (min <= max, RangeInclusive) and callers must never pre-scale by 70. A missed site is silent (inaudible past ~43 cm, no log); every_kira_position_site_goes_through_the_unit_seam scans the listener sites, both dispatch paths and (since #5411, bb31c5fb3) the follow site, with a negative on raw set_position.
  • Emitter follow (#3086, b4f08089b): sync_emitter_positions (pass 2, after the listener sync) pushes the sub-track of every ActiveSound whose SoundSource::followed_entity() is set (Emitter and Anchored) to its source's current GlobalTransform through the same bu_to_audio_space; change-gated on ActiveSound::last_position (seeded at dispatch on both paths) so a stationary emitter costs one compare and zero kira commands; Detached queue sounds and music are never touched; a despawned/transform-less entity is skipped (prune owns Emitter on emitter removal and Anchored on GlobalTransform loss — orphaned_anchored_entity, #5678 74d841165 — and stop_sounds_for owns the explicit Anchored stop). AudioWorld::emitter_position_updates() is the observable (kira has no position readback). The behaviour guards are #[ignore]d (device) — trace the code in the default lane.
  • Listener: created lazily on the first frame an AudioListener has a resolved GlobalTransform; the handle is sticky (never cleared on despawn: kira listener capacity is 8, a clear/re-add loop exhausts it); a failed add_listener retries next frame; multi-listener warns once and uses the first. Pose uses Tween::default() (smooth follow); orientation is already renderer-space (no second Z-up conversion). Output: /tmp/audit/audio/dim_1.md

Dim 2: Send Graph: Reverb Send & Underwater Filter

Paths: crates/audio/src/lib.rs (AudioWorld::new, apply_reverb_send, reverb_send_gate_open, set_reverb_send_db, apply_underwater_filter, update_underwater_filters, set_underwater) First step: git log --since=D -- crates/audio/src/lib.rs (send/filter regions) Guards: tests.rs::{reverb_send_defaults_to_silent, reverb_send_gate_matches_silence_db_boundary, above_water_filter_state_is_a_dry_bypass, above_water_cutoff_never_reaches_the_kira_clamp_ceiling, both_dispatch_paths_build_the_filter_through_one_call_site}.

  • One global reverb send is created in AudioWorld::new from REVERB_FEEDBACK/REVERB_DAMPING/REVERB_STEREO_WIDTH (0.85/0.6/1.0). They have no recorded provenance and are not kira's defaults: flag the doc gap, never invent a rationale. reverb_send: None never cascades into an unwrap().
  • Send opt-in is build-time only (with_send at track construction, gated is_finite() && > -60 dB) and both paths use the shared helper. Default level NEG_INFINITY (dry). Playing sounds keep their construction-time level: the documented "next-dispatch knob" contract, not a bug — kira 0.12's SpatialTrackHandle::set_send could retarget an existing route, but the engine does not, and a track built while the send was muted has no route at all (doc corrected #5677 b0b9bc987; a live fader needs every track routed at SILENCE_DB from construction).
  • Every spatial sub-track carries a low-pass built by ONE shared apply_underwater_filter; update_underwater_filters retargets live tracks when the listener's submersion changes. Above water is a genuine bypass via Mix::DRY (a default FilterBuilder is fully wet and colours the signal); the parked 20 kHz cutoff stays below kira's Nyquist clamp (beyond it the filter degenerates rather than turning transparent). set_underwater is written each frame by water_audio_system (Dim 5), before audio_system. Output: /tmp/audit/audio/dim_2.md

Dim 3: Streaming Music & SoundCache

Paths: crates/audio/src/lib.rs (play_music, stop_music, is_music_active, load_streaming_sound_from_*, SoundCache, VoiceSoundCache) First step: git log --since=D -- crates/audio/src/lib.rs Guards: tests.rs::{play_music_no_op_when_inactive, sound_cache_hits_are_case_insensitive_and_share_arc, sound_cache_get_or_load_invokes_loader_only_on_miss, sound_cache_clear_drops_entries_and_bytes_estimate_tracks_pcm_size, voice_cache_evicts_lru_under_byte_budget, voice_cache_negatives_are_capped_and_counted}.

  • Single music slot: play_music(streaming_sound, volume, fade_in_secs, looping) (4 parameters, looping since #3775; re-verify the arity before citing) crossfades any existing handle. Music routes through the main track, never a spatial sub-track. It uses StreamingSoundData (from_cursor/from_file), never StaticSoundData (full PCM decode = OOM on long tracks).
  • stop_music fades for fade_out_secs.max(0.0) then drops the handle (an instant stop clicks); is_music_active goes false the moment stop_music returns (the slot is cleared while kira renders the fade tail): documented, so a caller must not read it as "audibly occupied".
  • SoundCache keys lowercase once per entry point (sound_archive_path also drops a Data\ game-root prefix that Skyrim.esm's pull-chain descriptors author); clear() never invalidates Arcs held by live ActiveSounds. It is live since 2026-09-27: inserted at boot (boot/world.rs), sampled by ownership_sample.rs (len() + bytes_estimate()), and its consumer is combat_anim.rs::play_oneshot_cached (three fixed combat paths; voice moved to VoiceSoundCache), which M47.2's scripted_sound_system now also calls with script-chosen SNDR files — an open-ended key set landing on SoundCache, the shape this section calls the finding (every distinct file stays resident, no eviction). Footstep/splash loaders still bypass it into FootstepConfig/WaterAudioConfig. The map is Option<Arc<_>>: None is a negative-cache entry (loader returned no bytes, or decode failed) that get_or_load never re-probes and len()/bytes_estimate() exclude — so a sound missing at first use stays missing until clear(), which nothing in production calls (check whether the --sounds-bsa set can change at runtime). Still no eviction: a consumer keyed on open-ended paths (FOOT, REGN, per-NPC SFX) that lands on SoundCache is the finding.
  • VoiceSoundCache (#5382, 8410ad1e5) is the open-ended-key cache, used only by dialogue voice: same get_or_load contract, LRU-evicted past DEFAULT_BUDGET_BYTES (64 MiB; the just-inserted entry is never its own victim), negatives capped at VOICE_NEGATIVE_CAP (4096; the set clears and re-probes past it) and counted (negative_len). Telemetry reports voice_cache_{entries,bytes,negatives} through ownership_sample.rs; the save registry allowlists it. A new open-ended consumer belongs here (or in its own bounded cache), not in SoundCache. Output: /tmp/audit/audio/dim_3.md

Dim 4: Manager, ECS Lifecycle & Schedule

Paths: crates/audio/src/lib.rs (struct, AudioWorld::new/headless, audio_system, prune_stopped_sounds), byroredux/src/boot/schedule/late.rs, byroredux/src/cell_loader/{load,unload}.rs First step: git log --since=D -- crates/audio/src/lib.rs byroredux/src/boot/schedule/late.rs Guards: tests.rs::{audio_world_constructs_without_panic_on_any_environment, explicit_headless_world_discards_playback_without_retaining_sound, manager_capacities_exceed_kira_defaults}; scheduler_access_tests.rs::{footstep_runs_after_camera_follow_in_late, reverb_zone_is_parallel_and_audio_is_exclusive_in_late}.

  • Graceful degradation: AudioManager::new failure leaves manager = None; every public API gates on it with no unwrap(); headless/CI boot must succeed (report as PASS/FAIL in the summary). AudioWorld::headless() never contacts a device; tests use it, not the device-dependent default().
  • SUB_TRACK_CAPACITY (512) and SEND_TRACK_CAPACITY (32) exceed kira's defaults and are applied in new().
  • Field-drop order (single source of truth): active_sounds → pending_oneshots → (oneshots_requested) → music → reverb_send → reverb_send_db → listener → manager, then the trailing multi_listener_warned / underwater flags and the emitter_position_updates counter. A reorder that moves manager up asserts in kira's Drop. AudioWorld::new() is boot-only, never on cell transition or resize.
  • Schedule (all Stage::Late): audio_system is an exclusive registered after footstep_system (exclusive, pinned to Late by #4185's test) and water_audio_system (exclusive, after submersion_system); reverb_zone_system is a parallel registration, and the parallel batch finishing before any exclusive (not registration order) is what sets the send level before new tracks are built. audio_system body order: sync_listener_pose → sync_emitter_positions → update_underwater_filters → drain_pending_oneshots → dispatch_new_oneshots → prune_stopped_sounds. The conversation voice producer (Late npc_dialogue_selection_system) registers AFTER audio_system, so a line's segments dispatch on the next frame — one frame of latency, not a loss; the ObScript Say producer scripted_line_voice_system is Update, so its segments dispatch the same frame.
  • Despawn truncation: only SoundSource::Emitter entries are emitter-coupled (emitter_coupled()): an entity that loses AudioEmitter gets a tweened stop() over ActiveSound.unload_fade_ms (10 ms default, looping and not); stop_issued debounces (and is set by stop_sounds_for too); retain drops only on Stopped. Detached runs to natural end; Anchored survives SFX emitter churn on the same NPC by design and stops via stop_sounds_for (topic change, close, death, #5432) or, for a speaker despawned mid-line (cell unload), through the prune sweep's tweened stop once the followed entity has no GlobalTransform (#5678 74d841165; the anchored_voice_follows_survives_prune_and_stops lifecycle test is #[ignore]d, the orphan selection is pinned default-lane by only_transformless_anchored_sources_are_prune_orphans). Guards are #[ignore]d (Phase 1): trace the code.
  • Cross-cell continuity: dispatch_region_ambient_music runs only when music_form changed (both cell_loader/load.rs paths and scene::apply_cell_region_ambient compare against the prior RegionAmbientRes); an unconditional redispatch audibly restarts the track on every connected-cell crossing. A future CELL-level MUSC caller needs its own gate. Output: /tmp/audit/audio/dim_4.md

Dim 5: Engine-Side Consumers

Paths: byroredux/src/systems/{audio,dialogue_voice,scripted_sound}.rs, crates/audio/src/fuz.rs, byroredux/src/components/{audio,environment}.rs (footstep/impact/water-audio/region resources), byroredux/src/asset_provider/{audio,texture}.rs, byroredux/src/scene.rs First step: git log --since=D -- byroredux/src/systems/audio.rs byroredux/src/systems/dialogue_voice.rs byroredux/src/asset_provider/audio.rs Guards (systems/audio.rs tests): first_tick_seeds_last_position_without_firing, stride_threshold_is_bethesda_units_not_metres, walking_for_one_second_fires_a_walking_cadence_not_one_per_frame, single_large_jump_fires_one_footstep_only, water_splash_event_reaches_audio_dispatcher, interior_to_exterior_transition_resets_send_to_dry, the #5146 trio orbiting_camera_with_stationary_body_fires_nothing / swimming_body_is_silent_and_exit_does_not_replay_the_swim_distance / airborne_body_is_silent_and_landing_does_not_replay_the_air_distance, plus the no_*_is_safe_noop pair. Highest-yield dimension in the 2026-08/09 reports.

  • Callers: footstep_system, impact_audio_system (Late exclusive registered right after footstep_system: drains PhysicsWorld::take_contact_force_events — the started force crossings, below ImpactConfig::min_force_magnitude skipped — and plays one {1.0, 24.0} m one-shot per impact at PhysicsWorld::contact_event_position — the deepest solver contact, not the body-origin midpoint (a static ghost / exterior terrain tile parks its body at the placement or world origin, so the midpoint played 300 m impacts at ~150 m, #5675 0d8ea5d6e); material = resolve_impact_material (collider 1's non-zero, else collider 2's, else 0 while either handle lives, #5549); impact_sounds_to_play skips only an unmapped impact, never breaks the frame, #5554; the whole system returns early with no default_sound and no surface_sounds, and first syncs the physics subscription to that verdict — set_contact_force_events_enabled(has_sound), so with no content dynamic colliders carry no force-event flag at all (#5711 e3a4d5e18; /audit-physics Dim 2)), water_audio_system and combat_anim.rs::play_oneshot_cached (PostUpdate, enqueued before Late audio_system) are live play_oneshot callers, with systems/scripted_sound.rs::scripted_sound_system (Update exclusive, M47.2 5046c7af8/f093e7393: drains PendingSoundPlays, resolves the SNDR/SOUN through index.sounds, skips looping descriptors, takes multi-ANAM variants in turn, positions at the source's GlobalTransform and plays through play_oneshot_cached — note this puts script-authored, open-ended sound paths on the unbounded SoundCache, Dim 3) and byroredux/src/systems/dialogue_voice.rs as further callers (#5367 Phase V: per-line voice — FO3/FNV .ogg, Oblivion race/sex .mp3 #5526, Skyrim+ .fuz through byroredux_audio::fuz + optional ffmpeg #5912 — from apply_selection and the Update scripted_line_voice_system (ObScript Say/SayTo, whose resolved duration times SayToDone), through play_oneshot_following, anchored to the speaker and skipped when it has no GlobalTransform (#5410) and cut by stop_line_voice on topic change / close / speaker death (#5432); segments chained via byroredux_audio::with_start_delay, each named by its authored response_number; Attenuation::default(), volume 1.0; gated on AudioWorld::is_active before any archive work; decoded through VoiceSoundCache with the provider read inside the loader (#5382/#5383); file name and owning plugin per docs/engine/dialogue-trees.md (#5393/#5395, 5b68792b7; .ogg/.fuz names truncate only when quest + topic exceed 25 characters, one candidate, #5521; Oblivion's are untruncated); missing voice is a silent fallback to the subtitle estimate); reverb_zone_system the only set_reverb_send_db caller, dispatch_region_ambient_music the only play_music/stop_music caller. Re-grep for any new caller (git grep -n 'play_oneshot\|play_music\|set_underwater\|stop_sounds_for\|take_contact_force_events' -- byroredux/src) and audit it.
  • Footsteps: XZ-only stride accumulation against FootstepEmitter.stride_threshold, authored in Bethesda units (0.75 * BETHESDA_UNITS_PER_METER), compared to GlobalTransform deltas with no conversion at the compare site; reset to 0 on fire (subtract-remainder multiplies footsteps on a teleport); first tick seeds last_position and fires nothing. Attenuation {0.5, 12.0} in metres (no pre-scaling by 70, no widening). The FootstepScratch Vec (capacity 32) is restored on the success and the AudioWorld-absent path; no component lock is held across play_oneshot and the scratch lock drops before AudioWorld is taken. The player-body gate (CharacterController grounded flag + body handle) is resolved as an owned (body, gated) pair BEFORE any GlobalTransform/FootstepEmitter/scratch guard (#5305, 6915fe783: taking it inside closed three lock-order cycles) — a per-entity get back inside that scope is the regression. Every missing resource is a silent no-op (no per-frame log). Opt-in is component-driven. Surface selection (Wave 4): each trigger resolves its material at footstep cadence through PhysicsWorld::surface_material_under, which takes a MANDATORY excluded_body (the player's RapierHandles.body, else the capsule centre self-hits at toi 0 and every player step reads material 0, #5545 3909778eb); select_footstep_sound is a pure function of a FootstepConfig.surface_sounds snapshot cloned once, after the no-trigger early return and BEFORE the AudioWorld guard (no AudioWorld → FootstepConfig lock edge, #5556 ac710964e); the Access row declares the PhysicsWorld/RapierHandles reads (scheduler_access_tests.rs::footstep_declares_its_physics_reads). Material keys are u32 end to end (Skyrim's are CRC32s; 0 is STONE on Oblivion/FO3/FNV and the value of every unauthored body, #5542). Which entity walks (#5146, ccc743160; #5348 a9def9cb9): character mode adds an emitter on the player body, and only the stand-in camera emitter — the ActiveCamera entity while PlayerMode is Character, resolved once from those two resources (skipped_camera) — is re-seeded, never accumulated (the 180 BU third-person boom turned mouse-look into footsteps); every other emitter (a future per-NPC/FOOT one) walks, and FlyCam steps with the camera whether booted --fly or toggled. The body accumulates only while CharacterController.is_grounded; the gate is !is_grounded ALONE since #5347 (7068c16d3) because resolve_ground_contact never grounds a swimmer (character::tests::a_swimmer_is_never_grounded) — if swimming ever stops clearing is_grounded, an explicit swim operand plus a test holding it true through the swim leg must come back. Gated frames re-seed so a landing or water exit never replays as a burst. A FlyCam toggle leaves the frozen body silent while the camera steps (pinned in #5348). With no PhysicsWorld each stride trigger still keeps one surface result and takes the default sound instead of truncating the loop (#5714 77eea4311). The Access row (boot/schedule/late.rs) declares the PlayerEntity/PlayerMode/ActiveCamera/CharacterController reads and still lists a WaterContact read the system no longer takes (harmless over-declaration since #5347).
  • Water audio: water_audio_system writes AudioWorld::set_underwater from the active camera's SubmersionState.head_submerged every frame (before the config early-return), then plays SplashEvent one-shots (range 1-24 m) and, when no splash fired, one cooldown-limited RippleEvent (per-surface cooldown, 0.45 damping). The range and the 0.45 factor are uncited (no authored SOUN range): note as unsourced, never invent one. WaterAudioConfig.splash_sound is None without an archive (valid headless state); try_load_default_footstep and try_load_default_water_splash (asset_provider/texture.rs) no-op cleanly when the arg or archive is absent.
  • Combat feedback sounds (play_oneshot_cached): registered outside the BYRO_NO_AI_LOCOMOTION block since #4709 (70d9896fb) — a move back inside silently mutes them; hardcoded Skyrim paths per docs/engine/p2-combat-anim-sound-fixture.md, each request counted per kind in CombatSoundRequests (swing / impact / death_voice; incremented only when the one-shot was actually requested, surfaced by combat.status, #5148 7208af67c), attenuation {0.5, 24.0} m (uncited, like the water range); lookup goes through SoundCache::get_or_load whose loader reads SoundArchiveProvider while the SoundCache write guard is held (resource-in-resource nesting). Dialogue voice uses the same cache → provider order on VoiceSoundCache (#5383, 080b35f35; the old provider → cache order closed a lock-order cycle with this path); dialogue_voice.rs::voice_and_combat_sound_paths_share_one_cache_provider_order drives both consumers in one process — a third consumer taking the provider first is the regression. Headless / archive-less paths skip silently.
  • reverb_zone_system: -12 dB interior / NEG_INFINITY exterior; the transition is bit-equality gated (to_bits), no-ops without CellLightingRes (pre-load) or AudioWorld (headless).
  • dispatch_region_ambient_music: stops outstanding playback on every failure layer (no provider, no --sounds-bsa, unresolved FormID, folder FNAM, archive miss, decode failure, music_form: None) because what is audible belonged to the previous directive; the authored-but-unresolved log fires once per process (std::sync::Once); looping threads from sound_loops (SOUN Loop bit) into play_music. SounRecord::sound_path is a file or a trailing-separator folder (about half of FNV's FNAM-bearing records): sound_is_folder fails closed before any archive lookup, and any future resolve_sound_path consumer must gate on it (variant selection is an unmade policy, so no "extract any file under this folder" fallback exists).
  • Archive precedence: SoundArchiveProvider::extract iterates .rev() (last-listed wins, as mesh/texture/material; FNV's Fallout - Sound.bsa + Update.bsa overlap with differing bytes): forward iteration is the regression. ScriptProvider is the deliberate first-wins exception. Output: /tmp/audit/audio/dim_5.md

Phase 3: Merge

Combine /tmp/audit/audio/dim_*.md into docs/audits/AUDIT_AUDIO_<TODAY>.md (header per _audit-common.md Report finalization): Executive Summary (severity counts, headless-boot PASS/FAIL), Lifecycle Invariant Matrix (field-drop order, sticky listener, despawn truncation, schedule order: verified or drifted), Findings (deduplicated), Future-Phase Readiness (FOOT, MUSC/MUST/MSET, occlusion). Then rm -rf /tmp/audit/audio; suggest /audit-publish docs/audits/AUDIT_AUDIO_<TODAY>.md (labels audio, plus game:* when one title's sound data is the cause).

From the file to a first result

The download contains exactly the content displayed on this page. This copy may differ from the latest version in the source repository.

View the source and supporting files

This download contains SKILL.md only. Any scripts, references, templates and dependencies are not included. Get the required files from the source, preserving their directory structure, before continuing.

1. Download the file

Download SKILL.md

From the root of a test project, save the file as .skill-downloads/audio-subsystem-audit-m44-mvhm5m25/SKILL.md, or use the command below. This folder is for inspecting the skill before installation.

Command for macOS/Linux or WSL: requires a POSIX shell and curl. On Windows without WSL, use the download button and create the folder manually.

mkdir -p '.skill-downloads/audio-subsystem-audit-m44-mvhm5m25' && curl --fail --show-error --location 'https://skills-guides.com/api/skills/audio-subsystem-audit-m44-mvhm5m25/download' --output '.skill-downloads/audio-subsystem-audit-m44-mvhm5m25/SKILL.md.part' && mv '.skill-downloads/audio-subsystem-audit-m44-mvhm5m25/SKILL.md.part' '.skill-downloads/audio-subsystem-audit-m44-mvhm5m25/SKILL.md'

2. Check prerequisites

Read SKILL.md before using it. If it references scripts or external services, inspect them and prepare the required access in your test environment.

No recognized prerequisites section in this file. This does not mean it is self-contained: libraries, tools and access requirements may be mentioned elsewhere in the content or source repository.

The platforms on this page are catalog indications. The paths below follow tool documentation; they do not prove this skill has been run in those tools. No minimum tool version is confirmed for this listing.

3. Load the skill

This file does not provide a usable name/description header for this native procedure. It remains available to download and inspect; use the manual method below.

Manual method or another tool: attach SKILL.md to a conversation, or open it in an agent that can read files. Include any required supporting resources. No universal folder is recognized by every tool.

4. Try a first task

Use a short, synthetic input: an API endpoint, a small document or an interface brief. In a new conversation, attach the file or give the agent its path, then adapt this request:

Read .skill-downloads/audio-subsystem-audit-m44-mvhm5m25/SKILL.md and apply its instructions to this example: [describe a test input]. Identify any missing files, dependencies or access. Produce the result requested by the skill without inventing data or running unreviewed scripts.

Expected result: output matching the skill instructions, or a precise list of missing prerequisites. A read confirmation alone does not validate a first use. If an external resource is unavailable, that path remains untested.

Related skills