File size: 2,022 Bytes
570b87b | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 | #!/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()
|