sfs.td.wfs

Compute WFS driving functions.

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

# Plane wave
npw = sfs.util.direction_vector(np.radians(-45))

# 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

# Focused source
xf = -0.5, 0.5, 0
nf = sfs.util.direction_vector(np.radians(-45))  # normal vector
rf = np.linalg.norm(xf)  # distance from origin
tf = rf / 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
R = 1.5  # radius
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(delays, weights, signal)

Get driving signals per secondary source.

focused_25d(x0, n0, xs, ns[, xref, c])

Point source by 2.5-dimensional WFS.

plane_25d(x0, n0[, n, xref, c])

Plane wave model by 2.5-dimensional WFS.

point_25d(x0, n0, xs[, xref, c])

Driving function for 2.5-dimensional WFS of a virtual point source.

point_25d_legacy(x0, n0, xs[, xref, c])

Driving function for 2.5-dimensional WFS of a virtual point source.

sfs.td.wfs.plane_25d(x0, n0, n=[0, 1, 0], xref=[0, 0, 0], c=None)[source]

Plane wave model by 2.5-dimensional WFS.

Parameters
  • x0 ((N, 3) array_like) – Sequence of secondary source positions.

  • n0 ((N, 3) array_like) – Sequence of secondary source orientations.

  • n ((3,) array_like, optional) – Normal vector (propagation direction) of synthesized plane wave.

  • xref ((3,) array_like, optional) – Reference position

  • c (float, optional) – Speed of sound

Returns

  • delays ((N,) numpy.ndarray) – Delays of secondary sources in seconds.

  • weights ((N,) numpy.ndarray) – Weights of secondary sources.

  • selection ((N,) numpy.ndarray) – Boolean array containing True or False depending on whether the corresponding secondary source is “active” or not.

  • secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().

Notes

2.5D correction factor

\[g_0 = \sqrt{2 \pi |x_\mathrm{ref} - x_0|}\]

d using a plane wave as source model

\[d_{2.5D}(x_0,t) = 2 g_0 \scalarprod{n}{n_0} \dirac{t - \frac{1}{c} \scalarprod{n}{x_0}} \ast_t h(t)\]

with wfs(2.5D) prefilter h(t), which is not implemented yet.

See https://sfs.rtfd.io/d_wfs/#equation-td-wfs-plane-25d

Examples

delays, weights, selection, secondary_source = \
    sfs.td.wfs.plane_25d(array.x, array.n, npw)
d = sfs.td.wfs.driving_signals(delays, weights, signal)
plot(d, selection, secondary_source)
_images/sfs-td-wfs-2.svg
sfs.td.wfs.point_25d(x0, n0, xs, xref=[0, 0, 0], c=None)[source]

Driving function for 2.5-dimensional WFS of a virtual point source.

Changed in version 0.6.1: see notes, old handling of point_25d() is now point_25d_legacy()

Parameters
  • x0 ((N, 3) array_like) – Sequence of secondary source positions.

  • n0 ((N, 3) array_like) – Sequence of secondary source orientations.

  • xs ((3,) array_like) – Virtual source position.

  • xref ((N, 3) array_like or (3,) array_like) – Contour xref(x0) for amplitude correct synthesis, reference point xref.

  • c (float, optional) – Speed of sound

Returns

  • delays ((N,) numpy.ndarray) – Delays of secondary sources in seconds.

  • weights ((N,) numpy.ndarray) – Weights of secondary sources.

  • selection ((N,) numpy.ndarray) – Boolean array containing True or False depending on whether the corresponding secondary source is “active” or not.

  • secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().

Notes

Eq. (2.138) in [Sch16]:

\[d_{2.5D}(x_0, x_{ref}, t) = \sqrt{8\pi} \frac{\scalarprod{(x_0 - x_s)}{n_0}}{|x_0 - x_s|} \sqrt{\frac{|x_0 - x_s||x_0 - x_{ref}|}{|x_0 - x_s|+|x_0 - x_{ref}|}} \cdot \frac{\dirac{t - \frac{|x_0 - x_s|}{c}}}{4\pi |x_0 - x_s|} \ast_t h(t)\]
\[h(t) = F^{-1}(\sqrt{\frac{j \omega}{c}})\]

with wfs(2.5D) prefilter h(t), which is not implemented yet.

point_25d() derives WFS from 3D to 2.5D via the stationary phase approximation approach (i.e. the Delft approach). The theoretical link of point_25d() and point_25d_legacy() was introduced as unified WFS framework in [FFSS17].

Examples

delays, weights, selection, secondary_source = \
    sfs.td.wfs.point_25d(array.x, array.n, xs)
d = sfs.td.wfs.driving_signals(delays, weights, signal)
plot(d, selection, secondary_source, t=ts)
_images/sfs-td-wfs-3.svg
sfs.td.wfs.point_25d_legacy(x0, n0, xs, xref=[0, 0, 0], c=None)[source]

Driving function for 2.5-dimensional WFS of a virtual point source.

New in version 0.6.1: point_25d() was renamed to point_25d_legacy() (and a new function with the name point_25d() was introduced). See notes below for further details.

Parameters
  • x0 ((N, 3) array_like) – Sequence of secondary source positions.

  • n0 ((N, 3) array_like) – Sequence of secondary source orientations.

  • xs ((3,) array_like) – Virtual source position.

  • xref ((3,) array_like, optional) – Reference position

  • c (float, optional) – Speed of sound

Returns

  • delays ((N,) numpy.ndarray) – Delays of secondary sources in seconds.

  • weights ((N,) numpy.ndarray) – Weights of secondary sources.

  • selection ((N,) numpy.ndarray) – Boolean array containing True or False depending on whether the corresponding secondary source is “active” or not.

  • secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().

Notes

2.5D correction factor

\[g_0 = \sqrt{2 \pi |x_\mathrm{ref} - x_0|}\]

d using a point source as source model

\[d_{2.5D}(x_0,t) = \frac{g_0 \scalarprod{(x_0 - x_s)}{n_0}} {2\pi |x_0 - x_s|^{3/2}} \dirac{t - \frac{|x_0 - x_s|}{c}} \ast_t h(t)\]

with wfs(2.5D) prefilter h(t), which is not implemented yet.

See https://sfs.rtfd.io/d_wfs/#equation-td-wfs-point-25d

point_25d_legacy() derives 2.5D WFS from the 2D Neumann-Rayleigh integral (i.e. the approach by Rabenstein & Spors), cf. [SRA08]. The theoretical link of point_25d() and point_25d_legacy() was introduced as unified WFS framework in [FFSS17].

Examples

delays, weights, selection, secondary_source = \
    sfs.td.wfs.point_25d(array.x, array.n, xs)
d = sfs.td.wfs.driving_signals(delays, weights, signal)
plot(d, selection, secondary_source, t=ts)
_images/sfs-td-wfs-4.svg
sfs.td.wfs.focused_25d(x0, n0, xs, ns, xref=[0, 0, 0], c=None)[source]

Point source by 2.5-dimensional WFS.

Parameters
  • x0 ((N, 3) array_like) – Sequence of secondary source positions.

  • n0 ((N, 3) array_like) – Sequence of secondary source orientations.

  • xs ((3,) array_like) – Virtual source position.

  • ns ((3,) array_like) – Normal vector (propagation direction) of focused source. This is used for secondary source selection, see sfs.util.source_selection_focused().

  • xref ((3,) array_like, optional) – Reference position

  • c (float, optional) – Speed of sound

Returns

  • delays ((N,) numpy.ndarray) – Delays of secondary sources in seconds.

  • weights ((N,) numpy.ndarray) – Weights of secondary sources.

  • selection ((N,) numpy.ndarray) – Boolean array containing True or False depending on whether the corresponding secondary source is “active” or not.

  • secondary_source_function (callable) – A function that can be used to create the sound field of a single secondary source. See sfs.td.synthesize().

Notes

2.5D correction factor

\[g_0 = \sqrt{\frac{|x_\mathrm{ref} - x_0|} {|x_0-x_s| + |x_\mathrm{ref}-x_0|}}\]

d using a point source as source model

\[d_{2.5D}(x_0,t) = \frac{g_0 \scalarprod{(x_0 - x_s)}{n_0}} {|x_0 - x_s|^{3/2}} \dirac{t + \frac{|x_0 - x_s|}{c}} \ast_t h(t)\]

with wfs(2.5D) prefilter h(t), which is not implemented yet.

See https://sfs.rtfd.io/d_wfs/#equation-td-wfs-focused-25d

Examples

delays, weights, selection, secondary_source = \
    sfs.td.wfs.focused_25d(array.x, array.n, xf, nf)
d = sfs.td.wfs.driving_signals(delays, weights, signal)
plot(d, selection, secondary_source, t=tf)
_images/sfs-td-wfs-5.svg
sfs.td.wfs.driving_signals(delays, weights, signal)[source]

Get driving signals per secondary source.

Returned signals are the delayed and weighted mono input signal (with N samples) per channel (C).

Parameters
  • delays ((C,) array_like) – Delay in seconds for each channel, negative values allowed.

  • weights ((C,) array_like) – Amplitude weighting factor for each channel.

  • signal ((N,) array_like + float) – Excitation signal consisting of (mono) audio data and a sampling rate (in Hertz). A DelayedSignal object can also be used.

Returns

DelayedSignal – A tuple containing the driving signals (in a numpy.ndarray with shape (N, C)), followed by the sampling rate (in Hertz) and a (possibly negative) time offset (in seconds).