#!/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()