Skip to content

feat: SH-052 - the living soundscape: river, wind loops, creature locomotion#37

Merged
proggeramlug merged 4 commits into
mainfrom
feat/sh-052-living-soundscape
Jul 17, 2026
Merged

feat: SH-052 - the living soundscape: river, wind loops, creature locomotion#37
proggeramlug merged 4 commits into
mainfrom
feat/sh-052-living-soundscape

Conversation

@proggeramlug

@proggeramlug proggeramlug commented Jul 16, 2026

Copy link
Copy Markdown
Contributor

What

"We want 3D sounds for the wind, the river, the animals/spiders crawling closer" — built on engine EN-062 (Bloom-Engine/engine#116, merge that first).

  • River: one looping emitter per water volume, positioned every frame at the closest point of the volume's rectangle to the player — a line source that always stays abreast of you. World-file-driven: move the river in the editor and its sound moves.
  • Wind: the three forest-centroid sources are true loops now (the 15.2 s retrigger hack is deleted), detuned 0.94/1.0/1.07 so the treeline stops sounding like one file. Volume still rides the live wind amplitude.
  • Creature locomotion, two layers:
    • every kind now runs the tyrant's stride accumulator (KIND_STRIDE) and fires positional chitin skitters (light/heavy banks by kind), gated on actually moving;
    • a pool of 4 looping crawl-bed voices follows the nearest moving enemies within 28 m (slot-stable top-k, allocation-free), pitched per kind — the thing you haven't seen is audible closing in between its steps.
  • Assets: 10 new synthesised stand-ins in gen-sfx.ts (river bed+babble, skitter tap-bursts, granular crawl loop), appended after the existing emits so every old file stays byte-identical. ASSET-TODO A7–A9 track real recordings.

Engine-side (from EN-062, free here): equal-power pan, air absorption, rear head-shadow, doppler — and the stereo field is no longer mirrored.

Testing

AITEST probe build (numeric counters, not ears): 351 skitter steps over 50 s of live combat; crawl slots assign/release as enemies move and park (a dretch standing still at 1.5 m goes silent — the moving gate); wind voices 5/6/7, river voice 8; zero errors, no command-ring pressure. Probe reverted; shipped-config build boots clean for 15 s.

https://claude.ai/code/session_015wJLdkwm71jQCAqypaFeNE

Summary by CodeRabbit

  • New Features

    • Added a richer 3D living soundscape with spatial river ambience, pooled creature crawl loops, and per-kind skitter steps.
    • Extended ambience to follow nearby world geometry and enemy motion.
    • Added an in-world audio test mode (orbit/flyby/river) with a live HUD overlay.
  • Bug Fixes

    • Improved wind/leaf rustle behavior to address earlier “white noise” issues; wind is disabled by default for stability.
  • Documentation

    • Updated audio source mappings, soundscape/ticket specs, and loop/synthesis notes for the new assets and deterministic generation.

…omotion

Built on EN-062 live spatial voices:
- River: one looping emitter per water volume, tracking the closest bank
  point to the player every frame. World-file-driven.
- Wind: the three forest sources are true detuned loops now (retrigger
  timer deleted); volume still rides the live wind amplitude.
- Creature locomotion: every kind runs the tyrant's stride accumulator
  (KIND_STRIDE) and fires positional chitin skitters; a pool of 4 looping
  crawl-bed voices follows the nearest moving enemies so the thing you
  haven't seen is audible closing in between its steps.
- 10 new synthesised stand-in assets (gen-sfx.ts, appended after existing
  emits so old files stay byte-identical). ASSET-TODO A7-A9.

Verified via AITEST probe build: 351 skitters over 50s of combat, crawl
slots assign/release correctly, no errors. Probe reverted.

Claude-Session: https://claude.ai/code/session_015wJLdkwm71jQCAqypaFeNE
@coderabbitai

coderabbitai Bot commented Jul 16, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

The change implements the SH-052 living soundscape with generated wind, skitter, and crawl assets; recorded river-loop conversion; runtime river and creature ambience; generalized enemy locomotion audio; and an --audiotest harness for spatialization checks.

Changes

Living soundscape

Layer / File(s) Summary
Audio asset generation and looping
tools/convert-audio.ts, tools/gen-sfx.ts
Adds seamless recorded-loop conversion and generates SH-052 wind, skitter, and crawl assets while removing synthesized river generation.
Runtime ambience voices
src/audio-mix.ts
Adds multi-emitter river playback, disabled wind handling, pooled crawl voices, skitter banks, and per-frame spatial updates.
Enemy locomotion audio wiring
src/enemies.ts, src/director.ts
Adds per-kind stride distances and triggers tyrant steps or skitter sounds for moving enemies.
Audio probe and main-loop integration
src/main.ts, src/audio-mix.ts
Initializes and updates river and creature ambience, adds orbit/flyby/river probe modes, and displays probe status.
Soundscape records and orientation
CLAUDE.md, assets/sounds/SOURCES.md, docs/ASSET-TODO.md, docs/tickets.md
Documents SH-052 behavior, asset provenance, river completion, wind disablement, and synthesized locomotion stand-ins.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant MainLoop
  participant Director
  participant AudioMix
  participant AudioEngine
  participant EnemyState
  MainLoop->>AudioMix: Update river and creature ambience
  EnemyState-->>Director: Moving enemy and stride state
  Director->>AudioMix: Trigger tyrant step or skitterStep
  AudioMix->>AudioEngine: Update emitters and play locomotion sounds
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change by naming SH-052 and the new living soundscape features.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/sh-052-living-soundscape

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

…idth)

'The water sounds fake' - it did; synthetic babble always does. river_loop
is now a 32s seamless cut of a real Vermont babbling brook (Bolt Immersive
Creek, Sonniss GDC 2024 - same license line as splash1.wav):

- convert-audio.ts grew startAt + loopFade (equal-power tail-over-head
  cross-fade, chunk-aware WAV patching). The window at 49s was picked by
  scanning for minimum RMS+brightness variance; the seam verified
  numerically (wrap delta 0.034 vs body max 0.31, no clipping).
- Each water volume now runs a detuned emitter TRIO (main at the closest
  bank point + flankers +/-8m up/downstream at 0.96/1.05) so the water has
  audible extent instead of reading as a point speaker.
- gen-sfx.ts no longer emits a river (it would clobber the recording);
  the seed-stream shift regenerated skitter*/crawl_loop (equivalent
  variants, committed here).

Claude-Session: https://claude.ai/code/session_015wJLdkwm71jQCAqypaFeNE
@proggeramlug

Copy link
Copy Markdown
Contributor Author

SH-052b pushed: the river is a real creek recording now. river_loop.wav = 32 s seamless cut of Bolt's Immersive Creek babbling brook (Sonniss GDC 2024, same license line as splash1.wav) — the cut is scripted in convert-audio.ts (startAt/loopFade), the window was chosen by RMS+brightness variance scan, and the loop seam is verified numerically (wrap delta 0.034 vs body max 0.31). Each water volume also runs a detuned emitter trio now (main at the closest bank point + flankers ±8 m up/downstream at 0.96/1.05) so the water has audible width instead of reading as a point speaker. gen-sfx no longer emits a river; the seed-stream shift regenerated the skitter/crawl variants in the same commit.

@proggeramlug

Copy link
Copy Markdown
Contributor Author

SH-052c pushed — the remaining "white noise" was the wind bed, two causes: (1) the synth asset was a fixed bandpass × volume LFO — a static spectrum is what the ear files under white noise; (2) SH-052 had removed the authored 40 m window, so the engine's long rolloff tail spread that hiss over the whole arena. Fixed both: the generator now moves the spectrum with the gust (dark bough murmur in lulls → bright leaf-sizzle in gusts + flutter grains, measured brightness-vs-level r=0.95 across the loop, was ~0) and the game re-applies the authored window (full <27 m of the treeline, silent past 45 m). Open field is quiet again; near the trees it breathes instead of hissing. Real canopy recording still tracked as ASSET-TODO A3.

Two causes: the synth wind was a FIXED bandpass x volume LFO (a static
spectrum is what the ear calls white noise), and SH-052 had dropped the
authored 40m window so the engine's long inverse-model tail spread that
hiss over the whole arena.

- gen-sfx wind v2: spectrum rides the gust (bough murmur in lulls ->
  leaf sizzle in gusts, brightness ~ gust^1.8, measured r=0.95), leaf
  flutter grains only in strong gusts, slow seeded wander, 24s loop.
  Seam verified (delta 0.23 vs body max 0.53), no clipping.
- updateWindAmbience: authored window restored on top of engine rolloff
  (full <27m, silent >45m). Engine keeps pan/absorption/close-range.

Skitter/crawl regenerated (shared seed stream, same contract as before).

Claude-Session: https://claude.ai/code/session_015wJLdkwm71jQCAqypaFeNE

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@assets/sounds/SOURCES.md`:
- Around line 58-67: Update the synthesized-asset listing in SOURCES.md to
remove river_loop.wav from that section, preserving its recorded-loop
classification and 32-second duration from the existing source definitions.
Correct ambient_wind.wav’s listed duration from 16 seconds to 24 seconds,
leaving the other asset entries unchanged.

In `@src/director.ts`:
- Around line 779-780: Base movement audio on post-resolution displacement: in
src/director.ts lines 779-780, update the enStepPhase accumulation to use the
final realized nx/nz displacement rather than requested vx/vz; in
src/audio-mix.ts lines 465-470, use the corrected realized velocity for crawl
eligibility and loudness.

In `@src/main.ts`:
- Around line 1993-1994: Update the updateCreatureLoops method and its call site
in the gameplay loop to accept the current playing state. When inactive, clear
all pooled crawl-voice assignments and volumes, and skip movement-based updates;
preserve the existing behavior while playing.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: bede531b-93d6-42b7-b24e-9bbaba621251

📥 Commits

Reviewing files that changed from the base of the PR and between 5200fd2 and 348ab0f.

⛔ Files ignored due to path filters (11)
  • assets/sounds/ambient_wind.wav is excluded by !**/*.wav
  • assets/sounds/crawl_loop.wav is excluded by !**/*.wav
  • assets/sounds/river_loop.wav is excluded by !**/*.wav
  • assets/sounds/skitter_heavy1.wav is excluded by !**/*.wav
  • assets/sounds/skitter_heavy2.wav is excluded by !**/*.wav
  • assets/sounds/skitter_heavy3.wav is excluded by !**/*.wav
  • assets/sounds/skitter_heavy4.wav is excluded by !**/*.wav
  • assets/sounds/skitter_light1.wav is excluded by !**/*.wav
  • assets/sounds/skitter_light2.wav is excluded by !**/*.wav
  • assets/sounds/skitter_light3.wav is excluded by !**/*.wav
  • assets/sounds/skitter_light4.wav is excluded by !**/*.wav
📒 Files selected for processing (10)
  • CLAUDE.md
  • assets/sounds/SOURCES.md
  • docs/ASSET-TODO.md
  • docs/tickets.md
  • src/audio-mix.ts
  • src/director.ts
  • src/enemies.ts
  • src/main.ts
  • tools/convert-audio.ts
  • tools/gen-sfx.ts

Comment thread assets/sounds/SOURCES.md
Comment on lines +58 to +67
Deterministic (seeded), so re-running the tool reproduces byte-identical
files. See docs/ASSET-TODO.md A1/A2/A3/A5/A6/A7/A8/A9 for the intended real
replacements.

`step_grass{1-4}.wav`, `step_dirt{1-4}.wav`, `step_heavy1.wav`,
`reload_start.wav`, `reload_end.wav`, `ui_move.wav`, `ui_select.wav`,
`{rifle,blaster,chain,cannon}_tail.wav`, `ambient_wind.wav` (16 s seamless
loop), and the SH-052 set: `river_loop.wav` (14 s seamless),
`skitter_light{1-4}.wav`, `skitter_heavy{1-4}.wav`, `crawl_loop.wav`
(3.5 s seamless).

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Correct the synthesized-asset provenance and durations.

This section incorrectly labels river_loop.wav as a 14-second synthesized asset despite Line 49 and tools/convert-audio.ts defining it as a 32-second recorded loop. It also lists the rebuilt wind loop as 16 seconds instead of 24 seconds. This makes the licensing/provenance record internally inconsistent.

Proposed documentation fix
-`{rifle,blaster,chain,cannon}_tail.wav`, `ambient_wind.wav` (16 s seamless
-loop), and the SH-052 set: `river_loop.wav` (14 s seamless),
-`skitter_light{1-4}.wav`, `skitter_heavy{1-4}.wav`, `crawl_loop.wav`
-(3.5 s seamless).
+`{rifle,blaster,chain,cannon}_tail.wav`, `ambient_wind.wav` (24 s seamless
+loop), and the SH-052 synthesized set: `skitter_light{1-4}.wav`,
+`skitter_heavy{1-4}.wav`, `crawl_loop.wav` (3.5 s seamless).
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
Deterministic (seeded), so re-running the tool reproduces byte-identical
files. See docs/ASSET-TODO.md A1/A2/A3/A5/A6/A7/A8/A9 for the intended real
replacements.
`step_grass{1-4}.wav`, `step_dirt{1-4}.wav`, `step_heavy1.wav`,
`reload_start.wav`, `reload_end.wav`, `ui_move.wav`, `ui_select.wav`,
`{rifle,blaster,chain,cannon}_tail.wav`, `ambient_wind.wav` (16 s seamless
loop), and the SH-052 set: `river_loop.wav` (14 s seamless),
`skitter_light{1-4}.wav`, `skitter_heavy{1-4}.wav`, `crawl_loop.wav`
(3.5 s seamless).
Deterministic (seeded), so re-running the tool reproduces byte-identical
files. See docs/ASSET-TODO.md A1/A2/A3/A5/A6/A7/A8/A9 for the intended real
replacements.
`step_grass{1-4}.wav`, `step_dirt{1-4}.wav`, `step_heavy1.wav`,
`reload_start.wav`, `reload_end.wav`, `ui_move.wav`, `ui_select.wav`,
`{rifle,blaster,chain,cannon}_tail.wav`, `ambient_wind.wav` (24 s seamless
loop), and the SH-052 synthesized set: `skitter_light{1-4}.wav`,
`skitter_heavy{1-4}.wav`, `crawl_loop.wav` (3.5 s seamless).
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@assets/sounds/SOURCES.md` around lines 58 - 67, Update the synthesized-asset
listing in SOURCES.md to remove river_loop.wav from that section, preserving its
recorded-loop classification and 32-second duration from the existing source
definitions. Correct ambient_wind.wav’s listed duration from 16 seconds to 24
seconds, leaving the other asset entries unchanged.

Comment thread src/director.ts
Comment on lines 779 to 780
const spd = Math.sqrt(vx * vx + vz * vz);
enStepPhase[i] = enStepPhase[i] + spd * dt;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Base movement audio on post-resolution displacement.

Both systems treat requested steering velocity as realized movement, although collision and navigation resolution may cancel or redirect it.

  • src/director.ts#L779-L780: accumulate enStepPhase from the final nx/nz displacement.
  • src/audio-mix.ts#L465-L470: use the corrected realized velocity for crawl eligibility and loudness.
📍 Affects 2 files
  • src/director.ts#L779-L780 (this comment)
  • src/audio-mix.ts#L465-L470
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/director.ts` around lines 779 - 780, Base movement audio on
post-resolution displacement: in src/director.ts lines 779-780, update the
enStepPhase accumulation to use the final realized nx/nz displacement rather
than requested vx/vz; in src/audio-mix.ts lines 465-470, use the corrected
realized velocity for crawl eligibility and loudness.

Comment thread src/main.ts Outdated
Comment on lines +1993 to +1994
MIX.updateRiverAmbience(pp.x, pp.z);
MIX.updateCreatureLoops(pp.x, pp.z);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

Mute pooled crawl voices when gameplay stops.

When playing becomes false, enemy movement state is no longer updated, while persistent crawl voices can retain living enemies and stale velocity. Pass the active state into updateCreatureLoops and clear all assignments and volumes when inactive.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@src/main.ts` around lines 1993 - 1994, Update the updateCreatureLoops method
and its call site in the gameplay loop to accept the current playing state. When
inactive, clear all pooled crawl-voice assignments and volumes, and skip
movement-based updates; preserve the existing behavior while playing.

…the 3D

Wind: two rebuilds could not make a spectral-only always-on synth bed stop
reading as white noise, so it is LEFT OUT - sfxWind=NO_SOUND, every wind
path early-returns as for a missing file. System stays live and dormant;
one line re-enables it when a real canopy recording lands (ASSET-TODO A3).
River/footsteps/creatures/reverb untouched.

--audiotest orbit|flyby|river: a deterministic way to HEAR the
spatialisation instead of inferring it from combat.
- orbit: a broadband voice circles the listener at 6m (pan + rear cue)
- flyby: it flies through you at ~14 m/s (doppler + front/back)
- river: free-walk, river-only, dist-to-bank on the HUD
Waves suppressed in all modes; orbit/flyby silence the river so the probe
is the single source; river mode skips the probe. Top-centre HUD readout.
Dormant unless --audiotest is passed. Verified: voice live, orbit angle
advancing, all modes + normal path boot clean.

Claude-Session: https://claude.ai/code/session_015wJLdkwm71jQCAqypaFeNE
@proggeramlug

Copy link
Copy Markdown
Contributor Author

SH-052d pushed — two things:

Wind is left out. Two rebuilds couldn't stop a spectral-only, always-on synth bed from reading as white noise (you heard it both times — that's the ground truth). So sfxWind = NO_SOUND and every wind path early-returns exactly as for a missing file. The whole system — three world-driven emitters, wind-amplitude coupling, distance window — stays live and dormant; it's a one-line re-enable the moment a real canopy recording lands (ASSET-TODO A3). River, footsteps, creatures, reverb are untouched.

--audiotest orbit|flyby|river — a deterministic way to hear the spatialization instead of inferring it from a firefight:

  • orbit — a broadband voice circles your head at 6 m: sweeps L → behind (darker, rear cue) → R → front, and the pan tracks the camera when you turn.
  • flyby — it flies through you at ~14 m/s: doppler up on approach, down past you, front/back timbre flip.
  • river — free-walk, river as the only source, distance-to-nearest-bank on the HUD.

Waves off in all modes; orbit/flyby mute the river so the probe is the single source; river mode skips the probe. Top-centre HUD readout. Dormant unless the flag is passed.

@proggeramlug
proggeramlug merged commit d6b5666 into main Jul 17, 2026
1 check was pending

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
docs/tickets.md (1)

1721-1747: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Mark the superseded SH-052 claims as historical.

The earlier SH-052 summary still says river_loop is synthesized and reports active wind voices, while these follow-ups establish that the river is now recorded and wind is dormant. Label the original bullets as “as initially shipped” or update them so the ticket has one unambiguous current-state description.

Also applies to: 1777-1805

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/tickets.md` around lines 1721 - 1747, Update the superseded SH-052
sections in docs/tickets.md, including the related content around the second
referenced range, to clearly label claims about synthesized river audio and
active wind voices as “as initially shipped” or revise them to the current
recorded-river and dormant-wind state. Ensure the ticket presents one
unambiguous current-state description while preserving historical details where
appropriate.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@docs/ASSET-TODO.md`:
- Line 27: Update the status legend in docs/ASSET-TODO.md to define 🔴 as the
status used for intentionally left-out or unavailable assets, matching the
meaning assigned to A3. Keep the existing 🔵, 🟡, and ✅ definitions unchanged.

---

Outside diff comments:
In `@docs/tickets.md`:
- Around line 1721-1747: Update the superseded SH-052 sections in
docs/tickets.md, including the related content around the second referenced
range, to clearly label claims about synthesized river audio and active wind
voices as “as initially shipped” or revise them to the current recorded-river
and dormant-wind state. Ensure the ticket presents one unambiguous current-state
description while preserving historical details where appropriate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 00d9b1a6-5936-4116-b439-7b0909e7e9ca

📥 Commits

Reviewing files that changed from the base of the PR and between 348ab0f and 48bf9da.

📒 Files selected for processing (4)
  • docs/ASSET-TODO.md
  • docs/tickets.md
  • src/audio-mix.ts
  • src/main.ts

Comment thread docs/ASSET-TODO.md
| A1 | Footstep SFX — grass ×4, dirt ×4, heavy ×1 | 🟡 | **Synthesised stand-ins shipped** (`bun tools/gen-sfx.ts`). A step is an *impact* plus a *scuff*: grass is nearly all scuff (bright, grainy), dirt is mostly impact (low thud + grit), the tyrant footfall is a 48 Hz body with debris on top. They are audible and they sit right in the mix — but they are synthesis, not recordings. Replace with the Sonniss GDC bundle (a documented source in `SOURCES.md`) as a straight file drop: same names, no code change. |
| A2 | Weapon tail layers — rifle, blaster, chaingun, cannon | 🟡 | **Synthesised stand-ins shipped.** The "BOOM" half of crack-BOOM: band-limited decaying noise + a low body, routed to the reverb send by the mixer. Cannon runs 2.4 s and is still audible when the next shot lands. Real recordings would be better; the *system* is no longer silent. |
| A3 | Wind / leaf-rustle ambience loop | 🟡 | **Synthesised stand-in shipped** (16 s, seamless — the tail is cross-faded over the head). SH-001 is now wired: three 3D sources placed on the forest's own centroids (computed from the world file, so moving the trees in the editor moves the sound), volume from distance **and from the live wind amplitude**, so the rustle swells with the same vector that bends the grass. |
| A3 | Wind / leaf-rustle ambience loop | 🔴 | **LEFT OUT for now (SH-052d).** Two rebuilds (SH-052c moved the spectrum with the gust, r=0.95) still could not make synthesis pass as a spectral-only, always-on ambience — the user heard white noise, and they were right. The whole wind SYSTEM stays live and DORMANT: `audio-mix.ts` forces `sfxWind = NO_SOUND`, so every wind path early-returns exactly as for a missing file; the three world-driven emitters, the wind-amplitude coupling and the 45 m window are all intact. Re-enable in ONE line (restore the `optional('assets/sounds/ambient_wind.wav', …)` call) the moment a real recording lands — steady broadleaf canopy, no birds, no mic buffet, cut to a seamless loop with convert-audio's `loopFade`. The synth asset + generator are kept for that A/B. Sonniss 1of9 has no usable wind; check 2–9 or a CC0 source. |

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Define the new 🔴 status in the legend.

The legend only defines 🔵, 🟡, and ✅, so readers cannot determine what the newly introduced red A3 status means. Add 🔴 to the legend or use an existing status with equivalent semantics.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/ASSET-TODO.md` at line 27, Update the status legend in
docs/ASSET-TODO.md to define 🔴 as the status used for intentionally left-out or
unavailable assets, matching the meaning assigned to A3. Keep the existing 🔵,
🟡, and ✅ definitions unchanged.

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