Source code for sfs.time.drivingfunction

"""Compute time based driving functions for various systems.

.. include:: math-definitions.rst

"""
from __future__ import division
import numpy as np
from numpy.core.umath_tests import inner1d  # element-wise inner product
from .. import defs
from .. import util


[docs]def wfs_25d_plane(x0, n0, n=[0, 1, 0], xref=[0, 0, 0], c=None): r"""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. Notes ----- 2.5D correction factor .. math:: g_0 = \sqrt{2 \pi |x_\mathrm{ref} - x_0|} d using a plane wave as source model .. math:: d_{2.5D}(x_0,t) = h(t) 2 g_0 \scalarprod{n}{n_0} \dirac{t - \frac{1}{c} \scalarprod{n}{x_0}} with wfs(2.5D) prefilter h(t), which is not implemented yet. References ---------- See http://sfstoolbox.org/en/latest/#equation-d.wfs.pw.2.5D """ if c is None: c = defs.c x0 = util.asarray_of_rows(x0) n0 = util.asarray_of_rows(n0) n = util.normalize_vector(n) xref = util.asarray_1d(xref) g0 = np.sqrt(2 * np.pi * np.linalg.norm(xref - x0, axis=1)) delays = inner1d(n, x0) / c weights = 2 * g0 * inner1d(n, n0) return delays, weights
[docs]def wfs_25d_point(x0, n0, xs, xref=[0, 0, 0], c=None): r"""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. 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. Notes ----- 2.5D correction factor .. math:: g_0 = \sqrt{2 \pi |x_\mathrm{ref} - x_0|} d using a point source as source model .. math:: d_{2.5D}(x_0,t) = h(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}} with wfs(2.5D) prefilter h(t), which is not implemented yet. References ---------- See http://sfstoolbox.org/en/latest/#equation-d.wfs.ps.2.5D """ if c is None: c = defs.c x0 = util.asarray_of_rows(x0) n0 = util.asarray_of_rows(n0) xs = util.asarray_1d(xs) xref = util.asarray_1d(xref) g0 = np.sqrt(2 * np.pi * np.linalg.norm(xref - x0, axis=1)) ds = x0 - xs r = np.linalg.norm(ds, axis=1) delays = r/c weights = g0 * inner1d(ds, n0) / (2 * np.pi * r**(3/2)) return delays, weights
[docs]def wfs_25d_focused(x0, n0, xs, xref=[0, 0, 0], c=None): r"""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. 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. Notes ----- 2.5D correction factor .. math:: 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 .. math:: d_{2.5D}(x_0,t) = h(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}} with wfs(2.5D) prefilter h(t), which is not implemented yet. References ---------- See http://sfstoolbox.org/en/latest/#equation-d.wfs.fs.2.5D """ if c is None: c = defs.c x0 = util.asarray_of_rows(x0) n0 = util.asarray_of_rows(n0) xs = util.asarray_1d(xs) xref = util.asarray_1d(xref) ds = x0 - xs r = np.linalg.norm(ds, axis=1) g0 = np.sqrt(np.linalg.norm(xref - x0, axis=1) / (np.linalg.norm(xref - x0, axis=1) + r)) delays = -r/c weights = g0 * inner1d(ds, n0) / (2 * np.pi * r**(3/2)) return delays, weights
[docs]def driving_signals(delays, weights, signal): """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). """ delays = util.asarray_1d(delays) weights = util.asarray_1d(weights) data, samplerate, signal_offset = apply_delays(signal, delays) return util.DelayedSignal(data * weights, samplerate, signal_offset)
[docs]def apply_delays(signal, delays): """Apply delays for every channel. Parameters ---------- 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. delays : (C,) array_like Delay in seconds for each channel (C), negative values allowed. Returns ------- `DelayedSignal` A tuple containing the delayed signals (in a `numpy.ndarray` with shape ``(N, C)``), followed by the sampling rate (in Hertz) and a (possibly negative) time offset (in seconds). """ data, samplerate, initial_offset = util.as_delayed_signal(signal) data = util.asarray_1d(data) delays = util.asarray_1d(delays) delays += initial_offset delays_samples = np.rint(samplerate * delays).astype(int) offset_samples = delays_samples.min() delays_samples -= offset_samples out = np.zeros((delays_samples.max() + len(data), len(delays_samples))) for column, row in enumerate(delays_samples): out[row:row + len(data), column] = data return util.DelayedSignal(out, samplerate, offset_samples / samplerate)