woodfireind's picture
HOA7 Spatial Field Decoder (hoa64 v0.5.0): 7th-order Ambisonics encode/decode, Wigner-D rotation, DOA analysis, vision fuse, diffusion conditioning
570b87b verified
Raw
History Blame Contribute Delete
2.13 kB
"""Decode HOA-7 coefficients to samples on the sphere."""
from __future__ import annotations
import numpy as np
from .basis import MAX_ORDER, sh_sn3d, sh_sn3d_batch, sphere_grid
def decode_directions(
hoa: np.ndarray,
azimuths: np.ndarray | float,
elevations: np.ndarray | float,
*,
degrees: bool = True,
max_order: int = MAX_ORDER,
) -> np.ndarray:
"""Sample field a · Y(Ω) at given directions.
hoa: (C,) or (C, T)
returns: (...) or (..., T)
"""
a = np.asarray(hoa, dtype=np.float64)
nch = (max_order + 1) ** 2
# Allow shorter coefficient vectors (truncated order) or longer (ignore tail).
if a.ndim == 1:
aa = np.zeros(nch, dtype=np.float64)
n = min(nch, a.shape[0])
aa[:n] = a[:n]
Y = sh_sn3d(azimuths, elevations, degrees=degrees, max_order=max_order)
return np.einsum("...c,c->...", Y[..., :nch], aa)
if a.ndim == 2:
aa = np.zeros((nch, a.shape[1]), dtype=np.float64)
n = min(nch, a.shape[0])
aa[:n] = a[:n, :]
Y = sh_sn3d(azimuths, elevations, degrees=degrees, max_order=max_order)
return np.einsum("...c,ct->...t", Y[..., :nch], aa)
raise ValueError("hoa must be (C,) or (C,T)")
def decode_grid(
hoa: np.ndarray,
n_azi: int = 72,
n_el: int = 36,
*,
degrees: bool = True,
max_order: int = MAX_ORDER,
) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
"""Decode on a product sphere grid.
Returns azi, el, samples with samples shape (n_azi, n_el) or (n_azi, n_el, T).
"""
azi, el, _ = sphere_grid(n_azi, n_el, degrees=degrees)
AA, EE = np.meshgrid(azi, el, indexing="ij")
samp = decode_directions(hoa, AA, EE, degrees=degrees, max_order=max_order)
return azi, el, samp
def beamform(
hoa: np.ndarray,
azimuth: float,
elevation: float,
*,
degrees: bool = True,
max_order: int = MAX_ORDER,
) -> float | np.ndarray:
"""Look / listen toward one direction: scalar (or time series) readout."""
return decode_directions(
hoa, azimuth, elevation, degrees=degrees, max_order=max_order
)