"""Submodules for broadband sound fields.
.. autosummary::
:toctree:
source
wfs
nfchoa
"""
import numpy as _np
from . import source
from .. import array as _array
from .. import util as _util
[docs]def synthesize(signals, weights, ssd, secondary_source_function, **kwargs):
"""Compute sound field for an array of secondary sources.
Parameters
----------
signals : (N, C) array_like + float
Driving signals consisting of audio data (C channels) and a
sampling rate (in Hertz).
A `DelayedSignal` object can also be used.
weights : (C,) array_like
Additional weights applied during integration, e.g. source
selection and tapering.
ssd : sequence of between 1 and 3 array_like objects
Positions (shape ``(C, 3)``), normal vectors (shape ``(C, 3)``)
and weights (shape ``(C,)``) of secondary sources.
A `SecondarySourceDistribution` can also be used.
secondary_source_function : callable
A function that generates the sound field of a secondary source.
This signature is expected::
secondary_source_function(
position, normal_vector, **kwargs) -> numpy.ndarray
**kwargs
All keyword arguments are forwarded to *secondary_source_function*.
This is typically used to pass the *observation_time* and *grid*
arguments.
Returns
-------
numpy.ndarray
Sound pressure at grid positions.
"""
ssd = _array.as_secondary_source_distribution(ssd)
data, samplerate, signal_offset = _util.as_delayed_signal(signals)
weights = _util.asarray_1d(weights)
channels = data.T
if not (len(ssd.x) == len(ssd.n) == len(ssd.a) == len(channels) ==
len(weights)):
raise ValueError("Length mismatch")
p = 0
for x, n, a, channel, weight in zip(ssd.x, ssd.n, ssd.a,
channels, weights):
if weight != 0:
signal = channel, samplerate, signal_offset
p += a * weight * secondary_source_function(x, n, signal, **kwargs)
return p
[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)
[docs]def secondary_source_point(c):
"""Create a point source for use in `sfs.td.synthesize()`."""
def secondary_source(position, _, signal, observation_time, grid):
return source.point(position, signal, observation_time, grid, c=c)
return secondary_source
from . import nfchoa
from . import wfs