signals#

Implements signal generators for the simulation of acoustic sources.

Inheritance diagram of acoular.signals

SignalGenerator

ABC for a simple one-channel signal generator.

PeriodicSignalGenerator

Abstract base class for periodic signal generators.

NoiseGenerator

Abstract base class for noise signal generators.

WNoiseGenerator

White noise signal generator.

PNoiseGenerator

Generate pink noise signal.

FiltWNoiseGenerator

Generate filtered white noise using an AR, MA, or ARMA process.

SineGenerator

Generate a sine signal.

GenericSignalGenerator

Generate signals from a SamplesGenerator or derived object.

class acoular.signals.SignalGenerator#

Bases: ABCHasStrictTraits

ABC for a simple one-channel signal generator.

This ABC defines the common interface and attributes for all signal generator implementations. It provides a template for generating one-channel signals with specified amplitude, sampling frequency, and duration. Subclasses should implement the core functionality, including signal generation and computation of the internal identifier.

See also

scipy.signal.resample()

Used for resampling signals in the usignal() method.

Notes

This class should not be instantiated directly. Instead, use a subclass that implements the required methods for signal generation.

sample_freq = Float(1.0, desc='sampling frequency')#

Sampling frequency of the signal in Hz. Default is 1.0.

num_samples = CInt#

The number of samples to generate for the signal.

digest = Property(depends_on=['sample_freq', 'num_samples'])#

A unique checksum identifier based on the object properties. (read-only)

abstractmethod signal()#

Generate and return the signal.

This method must be implemented by subclasses to provide the generated signal as a 1D array of samples.

usignal(factor)#

Resample the signal at a higher sampling frequency.

This method uses Fourier transform-based resampling to deliver the signal at a sampling frequency that is a multiple of the original sample_freq. The resampled signal has a length of factor * num_samples.

Parameters:
factorint

The resampling factor. Defines how many times larger the new sampling frequency is compared to the original sample_freq.

Returns:
numpy.ndarray

The resampled signal as a 1D array of floats.

Notes

This method relies on the scipy.signal.resample() function for resampling.

Examples

Resample a signal by a factor of 4:

>>> from acoular import SineGenerator  # Class extending SignalGenerator
>>> sg = SineGenerator(sample_freq=100.0, num_samples=1000)
>>> resampled_signal = sg.usignal(4)
>>> len(resampled_signal)
4000
class acoular.signals.PeriodicSignalGenerator#

Bases: SignalGenerator

Abstract base class for periodic signal generators.

The PeriodicSignalGenerator class defines the common interface for all SignalGenerator-derived classes with periodic signals. This class may be used as a base for class handling periodic signals that can be characterized by their frequency, phase and amplitude.

It should not be used directly as it contains no real functionality.

See also

SineGenerator

Generate a sine signal.

freq = Float(1000.0, desc='Frequency')#

The frequency of the signal. Default is 1000.0.

phase = Float(0.0, desc='Phase')#

The phase of the signal (in radians). Default is 0.0.

amplitude = Float(1.0)#

The amplitude of the signal. Default is 1.0.

digest = Property(depends_on=['amplitude', 'num_samples', 'sample_freq', 'freq', 'phase'])#

Internal identifier based on generator properties. (read-only)

abstractmethod signal()#

Deliver the signal.

class acoular.signals.NoiseGenerator#

Bases: SignalGenerator

Abstract base class for noise signal generators.

The NoiseGenerator class defines the common interface for all SignalGenerator classes with noise signals. This class may be used as a base for class handling noise signals that can be characterized by their RMS amplitude.

It should not be used directly as it contains no real functionality.

See also

PNoiseGenerator

For pink noise generation.

WNoiseGenerator

For pink white generation.

UncorrelatedNoiseSource

For per-channel noise generation.

rms = Float(1.0, desc='rms amplitude')#

Root mean square (RMS) amplitude of the signal. For a point source, this corresponds to the RMS amplitude at a distance of 1 meter. Default is 1.0.

seed = Int(0, desc='random seed value')#

Seed for random number generator. Default is 0. This parameter should be set differently for different instances to guarantee statistically independent (non-correlated) outputs.

digest = Property(depends_on=['rms', 'seed', 'sample_freq', 'num_samples'])#

Internal identifier based on generator properties. (read-only)

abstractmethod signal()#

Generate and deliver the periodic signal.

class acoular.signals.WNoiseGenerator#

Bases: NoiseGenerator

White noise signal generator.

This class generates white noise signals with a specified root mean square (RMS) amplitude, number of samples, and sampling frequency. The white noise is generated using a random number generator initialized with a user-defined seed for reproducibility.

See also

numpy.random.RandomState.standard_normal

Used here to generate normally distributed noise.

PNoiseGenerator

For pink noise generation.

UncorrelatedNoiseSource

For per-channel noise generation.

Examples

Generate white noise with an RMS amplitude of 1.0 and 0.5:

>>> from acoular import WNoiseGenerator
>>> from numpy import mean
>>>
>>> # White noise with RMS of 1.0
>>> gen1 = WNoiseGenerator(rms=1.0, num_samples=1000, seed=42)
>>> signal1 = gen1.signal()
>>>
>>> # White noise with RMS of 0.5
>>> gen2 = WNoiseGenerator(rms=0.5, num_samples=1000, seed=24)
>>> signal2 = gen2.signal()
>>>
>>> mean(signal1) > mean(signal2)
np.True_

Ensure different outputs with different seeds:

>>> gen1 = WNoiseGenerator(num_samples=3, seed=42)
>>> gen2 = WNoiseGenerator(num_samples=3, seed=73)
>>> gen1.signal() == gen2.signal()
array([False, False, False])
signal()#

Generate and deliver the white noise signal.

The signal is created using a Gaussian distribution with mean 0 and variance 1, scaled by the RMS amplitude of the object.

Returns:
numpy.ndarray

A 1D array of floats containing the generated white noise signal. The length of the array is equal to num_samples.

class acoular.signals.PNoiseGenerator#

Bases: NoiseGenerator

Generate pink noise signal.

The PNoiseGenerator class generates pink noise signals, which exhibit a \(1/f\) power spectral density. Pink noise is characterized by equal energy per octave, making it useful in various applications such as audio testing, sound synthesis, and environmental noise simulations.

The pink noise simulation is based on the Voss-McCartney algorithm, which iteratively adds noise with increasing wavelength to achieve the desired \(1/f\) characteristic.

See also

WNoiseGenerator

For white noise generation.

UncorrelatedNoiseSource

For per-channel noise generation.

References

depth = Int(16, desc='octave depth')#

“Octave depth” of the pink noise generation. Higher values result in a better approximation of the \(1/f\) spectrum at low frequencies but increase computation time. The maximum allowable value depends on the number of samples. Default is 16.

digest = Property(depends_on=['rms', 'seed', 'sample_freq', 'num_samples', 'depth'])#

A unique checksum identifier based on the object properties. (read-only)

signal()#

Generate and deliver the pink noise signal.

The signal is computed using the Voss-McCartney algorithm, which generates noise with a \(1/f\) power spectral density. The method ensures that the output has the desired RMS amplitude and spectrum.

Returns:
numpy.ndarray

A 1D array of floats containing the generated pink noise signal. The length of the array is equal to num_samples.

Notes

  • The “depth” parameter controls the number of octaves included in the pink noise simulation. If the specified depth exceeds the maximum possible value based on the number of samples, it is automatically adjusted, and a warning is printed.

  • The output signal is scaled to have the same overall level as white noise by dividing the result by np.sqrt(depth + 1.5).

class acoular.signals.FiltWNoiseGenerator#

Bases: WNoiseGenerator

Generate filtered white noise using an AR, MA, or ARMA process.

  • AR: autoregressive (ar)

  • MA: moving-average (ma)

  • ARMA: autoregressive moving-average

This class extends the WNoiseGenerator class to apply a digital filter to white noise, producing a signal with specific characteristics based on the provided filter coefficients. The desired filter is defined using the autoregressive coefficients (ar) and moving-average coefficients (ma).

The filter is implemented as a series of second-order sections (sos) for numerical stability, especially at high filter orders.

See also

WNoiseGenerator

For white noise generation.

Notes

  • The output signal is adjusted for the group delay introduced by the filter, ensuring proper alignment of the filtered signal.

  • The RMS value specified in the rms attribute corresponds to the original white noise signal and not the filtered output.

Examples

Generate filtered white noise using AR and MA coefficients:

>>> import acoular as ac
>>> import numpy as np
>>>
>>> # Define AR and MA coefficients
>>> ar = np.array([1.0, -0.5])
>>> ma = np.array([0.5, 0.5])
>>>
>>> # Create generator
>>> gen = ac.FiltWNoiseGenerator(
...     rms=1.0,
...     seed=42,
...     sample_freq=1000,
...     num_samples=10000,
...     ar=ar,
...     ma=ma,
... )
>>>
>>> # Generate signal
>>> signal = gen.signal()
>>> print(signal[:10])  # Print the first 10 samples
[0.24835708 0.30340346 0.40641385 1.28856612 1.2887213  0.41021549
 0.87764567 1.61214661 0.95505348 0.51406957]
ar = CArray(value=np.array([]), dtype=float, desc='autoregressive coefficients (coefficients of the denominator)')#

A numpy.ndarray of autoregressive coefficients (denominator). Default is [], which results in no AR filtering (i.e., all-pole filter is [1.0]).

ma = CArray(value=np.array([]), dtype=float, desc='moving-average coefficients (coefficients of the numerator)')#

A numpy.ndarray of moving-average coefficients (numerator). Default is [], which results in no MA filtering (i.e., all-zero filter is [1.0]).

digest = Property(depends_on=['rms', 'seed', 'sample_freq', 'num_samples', 'ar', 'ma'])#

A unique checksum identifier based on the object properties. (read-only)

handle_empty_coefficients(coefficients)#

Handle empty filter coefficient arrays by returning a default value.

This method ensures that both the autoregressive (ar) and moving-average (ma) coefficients are non-empty before filtering. If a coefficient array is empty, it is replaced with a default array containing a single value of 1.0.

Parameters:
coefficientsnumpy.ndarray

Array of filter coefficients to check.

Returns:
numpy.ndarray

The original array if it is non-empty, or a default array containing [1.0] if the input array is empty.

signal()#

Generate and return the filtered white noise signal.

This method creates a white noise signal with the specified RMS value and seed, then filters it using the autoregressive (ar) and moving-average (ma) coefficients. The filtering process compensates for group delay introduced by the filter.

Returns:
numpy.ndarray of floats

An array representing the filtered white noise signal. The length of the returned array is equal to the number of samples.

class acoular.signals.SineGenerator#

Bases: PeriodicSignalGenerator

Generate a sine signal.

The SineGenerator class extends the PeriodicSignalGenerator class and generates a sinusoidal signal based on specified amplitude, frequency, and phase.

This generator is commonly used for creating test signals in signal processing, acoustics, and control systems.

The signal is defined as

\[s(t) = A \sin(2 \pi f t + \phi)\]
where:

See also

PeriodicSignalGenerator

Base class for periodic signal generators.

Examples

Generate a sine wave signal:

>>> import acoular as ac
>>>
>>> gen = ac.SineGenerator(
...     amplitude=2.0,
...     freq=50.0,
...     phase=0.0,
...     num_samples=1000,
...     sample_freq=1000,
... )
>>> signal = gen.signal()
>>> signal[:5]  # The first 5 samples
array([0.        , 0.61803399, 1.1755705 , 1.61803399, 1.90211303])

Generate a sine wave with a phase shift (arguably a cosine wave):

>>> import numpy as np
>>>
>>> gen = ac.SineGenerator(
...     amplitude=1.0,
...     freq=100.0,
...     phase=np.pi / 2,
...     num_samples=500,
...     sample_freq=2000,
... )
>>> signal = gen.signal()
>>> signal[:5]  # The first 5 samples
array([1.        , 0.95105652, 0.80901699, 0.58778525, 0.30901699])
digest = Property(depends_on=['num_samples', 'sample_freq', 'amplitude', 'freq', 'phase'])#

A unique checksum identifier based on the object properties. (read-only)

signal()#

Generate and return the sine wave signal.

The method computes the sine wave based on the specified amplitude, frequency, and phase. The time values are determined by the sampling frequency and the number of samples.

Returns:
numpy.ndarray of floats

A 1D array representing the sine wave signal. The length of the array is equal to num_samples.

Notes

The generator supports high-frequency and high-resolution signals, limited by the Nyquist criterion.

class acoular.signals.GenericSignalGenerator#

Bases: SignalGenerator

Generate signals from a SamplesGenerator or derived object.

The GenericSignalGenerator class enables the integration of arbitrary signals into Acoular processing chains. The signal is fetched from a specified data source and optionally scaled by an amplitude factor. It supports looping the signal to match the desired number of samples and can handle signals with multiple channels (only the first channel is used).

Common use cases include:
  • Injecting custom or pre-recorded signals from HDF5 files.

  • Creating signals using the TimeSamples class.

  • Generating a continuous or repeated signal for simulations.

Notes

If the signal source has more than one channel, only channel 0 is used.

Examples

Inject a random signal into a processing chain:

>>> import acoular as ac
>>> import numpy as np
>>>
>>> data = np.random.rand(1000, 1)
>>> ts = ac.TimeSamples(data=data, sample_freq=51200)
>>> sig = ac.GenericSignalGenerator(source=ts)
>>> output_signal = sig.signal()
source = Instance(SamplesGenerator)#

The data source from which the signal is fetched. This can be any object derived from SamplesGenerator.

amplitude = Float(1.0)#

Scaling factor applied to the generated signal. Defaults to 1.0.

sample_freq = Delegate('source')#

Sampling frequency of the output signal, as provided by the source object.

num_samples = Property()#

The number of samples to generate. Default is the number of samples available in the source (source.num_samples). If set explicitly, it can exceed the source length, in which case the signal will loop if loop_signal is True.

loop_signal = Bool(True)#

If True (default), the signal is repeated to meet the requested num_samples. If False, the signal stops once the source data is exhausted.

digest = Property( #

A unique checksum identifier based on the object properties. (read-only)

signal()#

Deliver the signal from the specified source.

Returns:
numpy.array of floats

The resulting signal, scaled by the amplitude attribute, with a length matching num_samples.

Warning

A warning is raised if the source has more than one channel.