Spatializer phase 1: daisy-spatializer app + KEMAR HRIR pipeline - #68
Merged
Conversation
…o OUT) Second slice of the spatializer (deliverable 3), on the DSP foundation from the previous PR. Places a mono guitar behind-and-left on headphones. - tools/hrir-gen — uv-managed tool that fetches the MIT KEMAR compact HRIR set (Gardner & Martin, MIT Media Lab 1994; publicly redistributable), reads a direction, mirrors right-hemisphere measurements to the left by swapping ears, resamples 44.1→48 kHz (scipy resample_poly 160/147), and joint-normalizes each pair (ILD-preserving). Emits a generated Rust source. It reports the spatial cue of each exported pair as a sanity check; the baked "behind-left" pair reads ITD +19 samples (left ear leads) and ILD +11.2 dB (left louder) — both cues point left, exactly a rear-left image. The .kemar download is cached + gitignored so a firmware build needs no network. - crates/daisy-spatializer — XIP app. In the DMA1_STR1 audio callback: mono (left input) → SampleFifo reblock 48→64 → StereoConvolver(HRIR_L, HRIR_R) fully wet → reblock 64→48 → stereo out. DSP state (convolver + its static scratch, sized by a const twin of required_scratch; three reblock FIFOs) lives in statics owned by the callback, built before start() unmasks the ISR. #[pre_init] sets the MPU + L1 caches + DWT and it recovers the bootloader's CoreClocks (an XIP app can't freeze its own), then brings up the codec via daisy-audio (AK4556/WM8731/PCM3060 auto-detect, or seed3=TAC5242). The measured HRIR — not a pan/delay — is what images behind: the interaural time/level/pinna cues live in the data. - renode/spatializer_xip.robot — boots the renode_test build from QSPI XIP and checks the PC7 heartbeat, proving Reset + pre_init + main (incl. building the ~10 KB convolver into static scratch) run from FLASH. Guards the __ebss / startup-lockup class for this app. Green. Verify: clippy -D warnings on all three feature combos (codec default / seed3 / renode_test) + fmt clean; XIP boot smoke green. Actual on-headphones imaging is HARDWARE-ONLY (needs a real codec + the clock hand-off), pending board time. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
… fmt) The generated hrir_data.rs failed `cargo fmt --check`: the tool emitted the module-level `#![allow(...)]` as one line, but rustfmt reflows a 3-item attribute to multi-line. Emit it pre-formatted so regenerating the data never breaks fmt. No data change (only the attribute layout). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 1 of the binaural spatializer (deliverable 3): a mono guitar patched to the left input is placed behind and to the left on headphones. Builds on the DSP foundation in #67 (this PR is based on that branch; rebase to
mainonce #67 merges).tools/hrir-gen— the HRIR data pipelineuv-managed tool that fetches the MIT KEMAR compact set (Gardner & Martin, MIT Media Lab 1994; publicly redistributable), reads a direction, mirrors right-hemisphere measurements to the left by swapping ears, resamples 44.1→48 kHz (
scipy resample_poly160/147), and joint-normalizes each pair (ILD-preserving). Emits generated Rust (hrir_data.rs). It prints each exported pair's spatial cue as a sanity check:Both cues point left → a rear-left image. The
.kemardownload is cached + gitignored, so a firmware build needs no network.crates/daisy-spatializer— the XIP appIn the DMA1_STR1 audio callback: mono (left in) →
SampleFiforeblock 48→64 →StereoConvolver(HRIR_L, HRIR_R) fully wet → reblock 64→48 → stereo out. DSP state (the convolver + its static scratch sized by aconsttwin ofrequired_scratch, plus three reblock FIFOs) lives in statics owned by the callback, built beforestart()unmasks the ISR.#[pre_init]sets the MPU + L1 caches + DWT; it recovers the bootloader'sCoreClocks(an XIP app can'tfreeze()) and brings up the codec via daisy-audio (AK4556/WM8731/PCM3060 auto-detect, orseed3= TAC5242).Renode
spatializer_xip.robotboots therenode_testbuild from QSPI XIP and checks the PC7 heartbeat — Reset +pre_init+main(incl. building the ~10 KB convolver into static scratch) run from FLASH. Guards the__ebss/startup-lockup class for this app. Green.Verification
-D warningson all three feature combos (codec default /seed3/renode_test) +cargo fmt --checkclean.spatializer_xip.robotgreen (PC7 samples: [0,1,0,1,0,0,1,0]).Status / next
Actual on-headphones imaging is HARDWARE-ONLY (needs a real codec + the clock hand-off), pending board time. Then phases 2–5: the room (externalization via distance/air-absorption/reverb), a second source, live positioning from the Hothouse knobs (HRIR interpolation), and the BRIR/head-tracking stretch.
🤖 Generated with Claude Code