# sfs.td.nfchoa¶

Compute NFC-HOA driving functions.

import matplotlib.pyplot as plt
import numpy as np
import sfs
from scipy.signal import unit_impulse

# Plane wave

# Point source
xs = -1.5, 1.5, 0
rs = np.linalg.norm(xs)  # distance from origin
ts = rs / sfs.default.c  # time-of-arrival at origin

# Impulsive excitation
fs = 44100
signal = unit_impulse(512), fs

# Circular loudspeaker array
N = 32  # number of loudspeakers
array = sfs.array.circular(N, R)

grid = sfs.util.xyz_grid([-2, 2], [-2, 2], 0, spacing=0.02)

def plot(d, selection, secondary_source, t=0):
p = sfs.td.synthesize(d, selection, array, secondary_source, grid=grid,
observation_time=t)
sfs.plot2d.level(p, grid)
sfs.plot2d.loudspeakers(array.x, array.n, selection * array.a, size=0.15)


Functions

 driving_signals_25d(delay, weight, sos, …) Get 2.5-dimensional NFC-HOA driving signals. driving_signals_3d(delay, weight, sos, …) Get 3-dimensional NFC-HOA driving signals. matchedz_zpk(s_zeros, s_poles, s_gain, fs) Matched-z transform of poles and zeros. plane_25d(x0, r0, npw, fs[, max_order, c, s2z]) Virtual plane wave by 2.5-dimensional NFC-HOA. plane_3d(x0, r0, npw, fs[, max_order, c, s2z]) Virtual plane wave by 3-dimensional NFC-HOA. point_25d(x0, r0, xs, fs[, max_order, c, s2z]) Virtual Point source by 2.5-dimensional NFC-HOA. point_3d(x0, r0, xs, fs[, max_order, c, s2z]) Virtual point source by 3-dimensional NFC-HOA.
sfs.td.nfchoa.matchedz_zpk(s_zeros, s_poles, s_gain, fs)[source]

Matched-z transform of poles and zeros.

Parameters: s_zeros (array_like) – Zeros in the Laplace domain. s_poles (array_like) – Poles in the Laplace domain. s_gain (float) – System gain in the Laplace domain. fs (int) – Sampling frequency in Hertz. z_zeros (numpy.ndarray) – Zeros in the z-domain. z_poles (numpy.ndarray) – Poles in the z-domain. z_gain (float) – System gain in the z-domain.
sfs.td.nfchoa.plane_25d(x0, r0, npw, fs, max_order=None, c=None, s2z=<function matchedz_zpk>)[source]

Virtual plane wave by 2.5-dimensional NFC-HOA.

$D(\phi_0, s) = 2\e{\frac{s}{c}r_0} \sum_{m=-M}^{M} (-1)^m \Big(\frac{s}{s-\frac{c}{r_0}\sigma_0}\Big)^\mu \prod_{l=1}^{\nu} \frac{s^2}{(s-\frac{c}{r_0}\sigma_l)^2+(\frac{c}{r_0}\omega_l)^2} \e{\i m(\phi_0 - \phi_\text{pw})}$

The driving function is represented in the Laplace domain, from which the recursive filters are designed. $$\sigma_l + \i\omega_l$$ denotes the complex roots of the reverse Bessel polynomial. The number of second-order sections is $$\nu = \big\lfloor\tfrac{|m|}{2}\big\rfloor$$, whereas the number of first-order section $$\mu$$ is either 0 or 1 for even and odd $$|m|$$, respectively.

Parameters: x0 ((N, 3) array_like) – Sequence of secondary source positions. r0 (float) – Radius of the circular secondary source distribution. npw ((3,) array_like) – Unit vector (propagation direction) of plane wave. fs (int) – Sampling frequency in Hertz. max_order (int, optional) – Ambisonics order. c (float, optional) – Speed of sound in m/s. s2z (callable, optional) – Function transforming s-domain poles and zeros into z-domain, e.g. matchedz_zpk(), scipy.signal.bilinear_zpk(). delay (float) – Overall delay in seconds. weight (float) – Overall weight. sos (list of numpy.ndarray) – Second-order section filters scipy.signal.sosfilt(). phaseshift ((N,) numpy.ndarray) – Phase shift in radians. selection ((N,) numpy.ndarray) – Boolean array containing only True indicating that all secondary source are “active” for NFC-HOA. secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().

Examples

delay, weight, sos, phaseshift, selection, secondary_source = \
sfs.td.nfchoa.plane_25d(array.x, R, npw, fs)
d = sfs.td.nfchoa.driving_signals_25d(
delay, weight, sos, phaseshift, signal)
plot(d, selection, secondary_source)

sfs.td.nfchoa.point_25d(x0, r0, xs, fs, max_order=None, c=None, s2z=<function matchedz_zpk>)[source]

Virtual Point source by 2.5-dimensional NFC-HOA.

$D(\phi_0, s) = \frac{1}{2\pi r_\text{s}} \e{\frac{s}{c}(r_0-r_\text{s})} \sum_{m=-M}^{M} \Big(\frac{s-\frac{c}{r_\text{s}}\sigma_0}{s-\frac{c}{r_0}\sigma_0}\Big)^\mu \prod_{l=1}^{\nu} \frac{(s-\frac{c}{r_\text{s}}\sigma_l)^2-(\frac{c}{r_\text{s}}\omega_l)^2} {(s-\frac{c}{r_0}\sigma_l)^2+(\frac{c}{r_0}\omega_l)^2} \e{\i m(\phi_0 - \phi_\text{s})}$

The driving function is represented in the Laplace domain, from which the recursive filters are designed. $$\sigma_l + \i\omega_l$$ denotes the complex roots of the reverse Bessel polynomial. The number of second-order sections is $$\nu = \big\lfloor\tfrac{|m|}{2}\big\rfloor$$, whereas the number of first-order section $$\mu$$ is either 0 or 1 for even and odd $$|m|$$, respectively.

Parameters: x0 ((N, 3) array_like) – Sequence of secondary source positions. r0 (float) – Radius of the circular secondary source distribution. xs ((3,) array_like) – Virtual source position. fs (int) – Sampling frequency in Hertz. max_order (int, optional) – Ambisonics order. c (float, optional) – Speed of sound in m/s. s2z (callable, optional) – Function transforming s-domain poles and zeros into z-domain, e.g. matchedz_zpk(), scipy.signal.bilinear_zpk(). delay (float) – Overall delay in seconds. weight (float) – Overall weight. sos (list of numpy.ndarray) – Second-order section filters scipy.signal.sosfilt(). phaseshift ((N,) numpy.ndarray) – Phase shift in radians. selection ((N,) numpy.ndarray) – Boolean array containing only True indicating that all secondary source are “active” for NFC-HOA. secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().

Examples

delay, weight, sos, phaseshift, selection, secondary_source = \
sfs.td.nfchoa.point_25d(array.x, R, xs, fs)
d = sfs.td.nfchoa.driving_signals_25d(
delay, weight, sos, phaseshift, signal)
plot(d, selection, secondary_source, t=ts)

sfs.td.nfchoa.plane_3d(x0, r0, npw, fs, max_order=None, c=None, s2z=<function matchedz_zpk>)[source]

Virtual plane wave by 3-dimensional NFC-HOA.

$D(\phi_0, s) = \frac{\e{\frac{s}{c}r_0}}{r_0} \sum_{n=0}^{N} (-1)^n (2n+1) P_{n}(\cos\Theta) \Big(\frac{s}{s-\frac{c}{r_0}\sigma_0}\Big)^\mu \prod_{l=1}^{\nu} \frac{s^2}{(s-\frac{c}{r_0}\sigma_l)^2+(\frac{c}{r_0}\omega_l)^2}$

The driving function is represented in the Laplace domain, from which the recursive filters are designed. $$\sigma_l + \i\omega_l$$ denotes the complex roots of the reverse Bessel polynomial. The number of second-order sections is $$\nu = \big\lfloor\tfrac{|m|}{2}\big\rfloor$$, whereas the number of first-order section $$\mu$$ is either 0 or 1 for even and odd $$|m|$$, respectively. $$P_{n}(\cdot)$$ denotes the Legendre polynomial of degree $$n$$, and $$\Theta$$ the angle between $$(\theta, \phi)$$ and $$(\theta_\text{pw}, \phi_\text{pw})$$.

Parameters: x0 ((N, 3) array_like) – Sequence of secondary source positions. r0 (float) – Radius of the spherical secondary source distribution. npw ((3,) array_like) – Unit vector (propagation direction) of plane wave. fs (int) – Sampling frequency in Hertz. max_order (int, optional) – Ambisonics order. c (float, optional) – Speed of sound in m/s. s2z (callable, optional) – Function transforming s-domain poles and zeros into z-domain, e.g. matchedz_zpk(), scipy.signal.bilinear_zpk(). delay (float) – Overall delay in seconds. weight (float) – Overall weight. sos (list of numpy.ndarray) – Second-order section filters scipy.signal.sosfilt(). phaseshift ((N,) numpy.ndarray) – Phase shift in radians. selection ((N,) numpy.ndarray) – Boolean array containing only True indicating that all secondary source are “active” for NFC-HOA. secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().
sfs.td.nfchoa.point_3d(x0, r0, xs, fs, max_order=None, c=None, s2z=<function matchedz_zpk>)[source]

Virtual point source by 3-dimensional NFC-HOA.

$D(\phi_0, s) = \frac{\e{\frac{s}{c}(r_0-r_\text{s})}}{4 \pi r_0 r_\text{s}} \sum_{n=0}^{N} (2n+1) P_{n}(\cos\Theta) \Big(\frac{s-\frac{c}{r_\text{s}}\sigma_0}{s-\frac{c}{r_0}\sigma_0}\Big)^\mu \prod_{l=1}^{\nu} \frac{(s-\frac{c}{r_\text{s}}\sigma_l)^2-(\frac{c}{r_\text{s}}\omega_l)^2} {(s-\frac{c}{r_0}\sigma_l)^2+(\frac{c}{r_0}\omega_l)^2}$

The driving function is represented in the Laplace domain, from which the recursive filters are designed. $$\sigma_l + \i\omega_l$$ denotes the complex roots of the reverse Bessel polynomial. The number of second-order sections is $$\nu = \big\lfloor\tfrac{|m|}{2}\big\rfloor$$, whereas the number of first-order section $$\mu$$ is either 0 or 1 for even and odd $$|m|$$, respectively. $$P_{n}(\cdot)$$ denotes the Legendre polynomial of degree $$n$$, and $$\Theta$$ the angle between $$(\theta, \phi)$$ and $$(\theta_\text{s}, \phi_\text{s})$$.

Parameters: x0 ((N, 3) array_like) – Sequence of secondary source positions. r0 (float) – Radius of the spherial secondary source distribution. xs ((3,) array_like) – Virtual source position. fs (int) – Sampling frequency in Hertz. max_order (int, optional) – Ambisonics order. c (float, optional) – Speed of sound in m/s. s2z (callable, optional) – Function transforming s-domain poles and zeros into z-domain, e.g. matchedz_zpk(), scipy.signal.bilinear_zpk(). delay (float) – Overall delay in seconds. weight (float) – Overall weight. sos (list of numpy.ndarray) – Second-order section filters scipy.signal.sosfilt(). phaseshift ((N,) numpy.ndarray) – Phase shift in radians. selection ((N,) numpy.ndarray) – Boolean array containing only True indicating that all secondary source are “active” for NFC-HOA. secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().
sfs.td.nfchoa.driving_signals_25d(delay, weight, sos, phaseshift, signal)[source]

Get 2.5-dimensional NFC-HOA driving signals.

Parameters: delay (float) – Overall delay in seconds. weight (float) – Overall weight. sos (list of array_like) – Second-order section filters scipy.signal.sosfilt(). phaseshift ((N,) array_like) – Phase shift in radians. signal ((L,) array_like + float) – Excitation signal consisting of (mono) audio data and a sampling rate (in Hertz). A DelayedSignal object can also be used. DelayedSignal – A tuple containing the delayed signals (in a numpy.ndarray with shape (L, N)), followed by the sampling rate (in Hertz) and a (possibly negative) time offset (in seconds).
sfs.td.nfchoa.driving_signals_3d(delay, weight, sos, phaseshift, signal)[source]

Get 3-dimensional NFC-HOA driving signals.

Parameters: delay (float) – Overall delay in seconds. weight (float) – Overall weight. sos (list of array_like) – Second-order section filters scipy.signal.sosfilt(). phaseshift ((N,) array_like) – Phase shift in radians. signal ((L,) array_like + float) – Excitation signal consisting of (mono) audio data and a sampling rate (in Hertz). A DelayedSignal object can also be used. DelayedSignal – A tuple containing the delayed signals (in a numpy.ndarray with shape (L, N)), followed by the sampling rate (in Hertz) and a (possibly negative) time offset (in seconds).