Skip to content

Audio round 2: looping engine audio (racing3d/car3d) + native loop-retune fix#33

Open
doodlewind wants to merge 1 commit into
mainfrom
feat/audio-round2
Open

Audio round 2: looping engine audio (racing3d/car3d) + native loop-retune fix#33
doodlewind wants to merge 1 commit into
mainfrom
feat/audio-round2

Conversation

@doodlewind

Copy link
Copy Markdown
Owner

Round 2 of the audio self-iteration — exercises + verifies the loop path (loop/stopLoopSND_OP_SET_LOOP) that round 1 (#30) built but never used. All existing visual goldens stay byte-identical (audio is invisible; no HUD added).

What

  • racing3d / car3d: speed-modulated engine loopSoundBank.loop('engine', {pitch ~ speed}), retuned only when the quantized pitch changes, stopLoop at rest. No visual HUD → RGBA/.dc3d goldens unchanged.
  • audio.ts flush(): SET_LOOP now emitted only on a real wire delta (on/off, gain, or pitch-while-on) — held throttle at saturated pitch emits nothing; stopLoop emits exactly one gain==0; idle-from-boot emits nothing. Fixes per-frame ring spam (found in review).
  • runtime/src/audio.rs — native loop-retune fix: round 1's re-parameterize branch dropped c.pitch, so a running loop was stuck at its start pitch (the engine wouldn't modulate). Now recomputes the Q16 phase step from base_freq × pitch without resetting phase (retunes, no click).
  • dodge: one-shot SFX (coin pickup / collision), no HUD.
  • golden.ts: new racing3d/car3d/dodge .snd.json event goldens asserting SET_LOOP-on (pitch 156→410), OFF (gain==0), and dodge coin TRIGGER.

Verification (re-run by me)

  • Headless: typecheck clean; bun run test green — 24 golden (same count), every prior .rgbz/.dc3d byte-identical (git diff goldens/ empty); new event goldens prove the loop path (SET_LOOP-on ×112, pitch 156→410 + OFF; dodge TRIGGER×1).
  • Native PSP (built + booted): racing3d EBOOT compiles with the loop-retune fix; PPSSPP boot under auto-accelerate — pspjs_audio thread scheduled, sceAudioSRCChReserve + 627× OutputBlocking in 16s (DAC fed), the SET_LOOP retune branch runs, no crash, 60 fps.
  • ⚠️ Audible pitch-modulation pending a human listen (web bun run serve / device).

Not auto-merging — ear-check the engine pitch sweep, then I'll merge + continue (round 3: music loops, more games).

🤖 Generated with Claude Code

…tune fix

Exercises + verifies the loop path (loop/stopLoop -> SND_OP_SET_LOOP) that round 1
built but never used. All EXISTING visual goldens byte-identical (no HUD added).

- racing3d.js / car3d.js: speed-modulated engine loop via SoundBank.loop('engine',
  {pitch ~ speed}); retuned only when the quantized pitch changes; stopLoop at rest.
  No visual HUD -> RGBA/.dc3d goldens unchanged.
- audio.ts flush(): SET_LOOP now emitted ONLY on a real wire delta (on/off, gain, or
  pitch-while-on) — a held throttle at saturated pitch emits nothing; stopLoop emits
  exactly one gain==0; idle-from-boot emits nothing. Fixes per-frame ring spam.
- runtime/src/audio.rs: NATIVE loop-retune fix — the re-parameterize branch dropped
  c.pitch (a running loop was stuck at its start pitch). Now recomputes the Q16 phase
  step from base_freq×pitch WITHOUT resetting phase (retunes, no click).
- dodge.js: one-shot SFX (coin.pickup / collision.impact), no HUD.
- golden.ts: new racing3d/car3d/dodge .snd.json event goldens asserting SET_LOOP-on
  (pitch 156->410) + OFF (gain==0) + dodge coin TRIGGER.

Verified: bun run test green (24 golden, same count, all prior visual goldens
byte-identical; loop event goldens prove the path); typecheck clean. Native: racing3d
EBOOT compiles + boots in PPSSPP — pspjs_audio thread scheduled, DAC fed (627x
OutputBlocking/16s under auto-accel), SET_LOOP retune branch runs, no crash, 60fps.
Audible pitch-modulation pending a human listen.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
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