HOA7 Spatial Field Decoder (hoa64 v0.5.0): 7th-order Ambisonics encode/decode, Wigner-D rotation, DOA analysis, vision fuse, diffusion conditioning
570b87b verified | #!/usr/bin/env python3 | |
| """Phase 1 demo: multi-source scene → Ambix WAV → JSON spatial report for AIs.""" | |
| from __future__ import annotations | |
| import json | |
| import sys | |
| import tempfile | |
| from pathlib import Path | |
| sys.path.insert(0, str(Path(__file__).resolve().parents[1])) | |
| from hoa64.audio_io import write_wav | |
| from hoa64.report import report_from_ambix_wav, report_from_scene | |
| from hoa64.stream import SourceSpec, encode_scene | |
| from hoa64.synth import envelope_adsr, tone | |
| def main() -> None: | |
| sr = 48000 | |
| dur = 0.6 | |
| n = int(sr * dur) | |
| env = envelope_adsr(n, sr, attack=0.02, release=0.08) | |
| sources = [ | |
| SourceSpec(0.0, 0.0, tone(440, dur, sr, amplitude=0.45) * env, "front_A4"), | |
| SourceSpec(90.0, 10.0, tone(554.37, dur, sr, amplitude=0.3) * env, "left_C#5"), | |
| SourceSpec(-120.0, -5.0, tone(659.25, dur, sr, amplitude=0.2) * env, "backright_E5"), | |
| ] | |
| print("=== Synthetic multi-source scene ===") | |
| for s in sources: | |
| print(f" {s.label}: az={s.azimuth_deg}° el={s.elevation_deg}°") | |
| rep = report_from_scene(sources, sr, max_order=3) | |
| print("\n" + rep.one_liner()) | |
| print(f"sources_hint: {json.dumps(rep.sources_hint, indent=2)}") | |
| if rep.bands: | |
| print("bands (first 3):") | |
| for b in rep.bands[:3]: | |
| print( | |
| f" {b['band_hz']}: DOA ({b['doa_az_deg']:.1f},{b['doa_el_deg']:.1f}) " | |
| f"E={b['energy']:.3g}" | |
| ) | |
| out_dir = Path(tempfile.mkdtemp(prefix="hoa64_p1_")) | |
| wav_path = out_dir / "scene_ambix4.wav" | |
| json_path = out_dir / "spatial_report.json" | |
| hoa = encode_scene(sources, max_order=3) | |
| write_wav(wav_path, hoa[:4], sr) | |
| rep.save(json_path) | |
| # Reload as Ambix and re-analyze | |
| rep2 = report_from_ambix_wav(wav_path, max_order=1) | |
| print(f"\nFrom written Ambix WAV: {rep2.one_liner()}") | |
| print(f"\nArtifacts:\n {wav_path}\n {json_path}") | |
| print("\nPhase 1: audio path + JSON report for other models — live.") | |
| if __name__ == "__main__": | |
| main() | |