bluepebble.signal

Signal-generation namespaces for source, ambient, and signal-effects modelling.

Signal package public API.

class bluepebble.signal.Signal(duration_s, sampling_rate_hz)[source]

Shared sampling parameter contract for all signal and noise models.

Signal is the public unified root of the signal hierarchy. All concrete signal types — Biological, Anthropogenic, and RandomSignal — inherit from it as siblings.

This class carries only the shared duration_s / sampling_rate_hz parameter contract and the derived num_samples property. Each branch defines its own generation interface independently.

Parameters:
  • duration_s (float) – Duration of the signal in seconds.

  • sampling_rate_hz (int) – Sampling rate in Hertz.

duration_s: float

Duration of the signal in seconds

sampling_rate_hz: int

Sampling rate in Hertz

property num_samples: int

Calculate the number of samples based on duration and sampling rate.

Returns:

The number of samples in the signal snapshot.

Return type:

int

class bluepebble.signal.BiologicalSignal(duration_s, sampling_rate_hz)[source]

Abstract base class for biological marine acoustic signals.

Provides the per-timestep generation interface used by DiscretePassiveSonarArraySimulator. Subclasses implement _generate_base_signal() to produce a raw source waveform; generate() handles padding / truncation and frequency-domain propagation automatically.

Parameters:
  • duration_s (float)

  • sampling_rate_hz (int)

get_source_waveform(source)[source]

Return the full-duration source waveform for this signal model.

Delegates to _prepare_waveform().

Parameters:

source (State) – Source state passed to the underlying waveform generator.

Returns:

Full-duration source waveform as complex128, padded or truncated to exactly num_samples.

Return type:

ComplexArray

generate(source, sensor_delays_s, tloss_db, propagation_time_s)[source]

Generate the signal, apply attenuation, and propagate it to a sensor array.

Parameters:
  • source (State) – The source state.

  • sensor_delays_s (ArrayLike) – Relative time delay for each sensor in seconds.

  • tloss_db (ArrayLike | float) – Transmission loss in dB to the array origin.

  • propagation_time_s (float) – Propagation time from source to origin in seconds.

Returns:

Complex signal matrix with shape (num_sensors, num_samples).

Return type:

ComplexArray

class bluepebble.signal.RandomSignal(duration_s, sampling_rate_hz, amplitude_upa, seed=None)[source]

Abstract base class for stochastic signal generation models.

These models generate random signals that can be applied either as spatially distributed signals across the entire sensor array, or as part of a localized source’s radiated signature. The base class is agnostic to the deployment mode—subclasses implement the signal generation, and the simulator determines spatial distribution.

Parameters:
  • amplitude_upa (float) – The signal amplitude (e.g., in µPa).

  • duration_s (float) – Duration of the signal in seconds.

  • sampling_rate_hz (int) – Sampling rate in Hertz.

  • seed (int or None, optional) – Seed for the random number generator. When None (default), defers to the global seed set by bluepebble.set_seed() if called, otherwise non-deterministic. Provide an integer for a reproducible independent stream.

amplitude_upa: float

The signal amplitude (e.g., in µPa)

seed: int | None

Seed for the random number generator. None defers to the global seed set by bluepebble.set_seed() if called, otherwise gives non-deterministic output; an explicit integer always produces a reproducible independent stream.

abstractmethod generate(num_sensors=1, num_samples=None)[source]

Generate a signal array. This must be implemented by subclasses.

Parameters:
  • num_sensors (int, optional) – The number of sensors in the array. Defaults to 1.

  • num_samples (int or None, optional) – Number of samples to generate. Defaults to self.num_samples when None.

Returns:

Signal matrix of shape (num_sensors, num_samples).

Return type:

ComplexArray

class bluepebble.signal.WhiteNoiseSignal(duration_s, sampling_rate_hz, amplitude_upa, seed=None)[source]

Generates complex white Gaussian noise with a flat power spectrum.

Parameters:
  • amplitude_upa (float) – The signal amplitude (e.g., in µPa).

  • duration_s (float) – Duration of the signal in seconds.

  • sampling_rate_hz (int) – Sampling rate in Hertz.

  • seed (int | None)

generate(num_sensors=1, num_samples=None)[source]

Generate a complex white Gaussian noise array.

Parameters:
  • num_sensors (int, optional) – The number of sensors in the array. Defaults to 1.

  • num_samples (int or None, optional) – Number of samples to generate. Defaults to self.num_samples when None.

Returns:

Complex white-noise matrix of shape (num_sensors, num_samples).

Return type:

ComplexArray

class bluepebble.signal.ColouredNoiseSignal(duration_s, sampling_rate_hz, amplitude_upa, spectral_exponent, seed=None)[source]

Generates complex coloured noise using FFT filtering.

This class generates noise with a power spectral density proportional to 1/f^alpha.

Parameters:
  • spectral_exponent (float) – The power-law exponent for the noise spectrum (e.g., -1 for pink noise, -2 for red/brownian noise).

  • amplitude_upa (float) – The signal amplitude (e.g., in µPa).

  • duration_s (float) – Duration of the signal in seconds.

  • sampling_rate_hz (int) – Sampling rate in Hertz.

  • seed (int | None)

spectral_exponent: float

The power-law exponent for the noise spectrum (e.g., -1 for pink noise, -2 for red/brownian noise).

generate(num_sensors=1, num_samples=None)[source]

Generate a complex coloured noise array.

Parameters:
  • num_sensors (int, optional) – The number of sensors in the array. Defaults to 1.

  • num_samples (int or None, optional) – Number of samples to generate. Defaults to self.num_samples when None.

Returns:

Complex coloured-noise matrix of shape (num_sensors, num_samples), normalised to the specified amplitude.

Return type:

ComplexArray

class bluepebble.signal.AnthropogenicSignal(duration_s, sampling_rate_hz, frame_len=1024, hop_factor=4, window_type='hann')[source]

Base class for STFT-first anthropogenic signal models.

Lifecycle

These models generate their full-duration source waveform once and cache it as an STFT matrix for frequency-domain propagation by ContinuousPassiveSonarArraySimulator.

The expected call sequence for a single simulation run is:

  1. Call compute_stft() once with the source state to build and cache the STFT.

  2. Pass the model to the simulator, which reads the cached STFT via get_stft() for each frame.

To reuse the same model instance across multiple simulation runs (e.g. with a different source state or after changing signal parameters), call reset() before the next compute_stft() call. Calling compute_stft() a second time without resetting raises RuntimeError.

frame_len: int

STFT frame length in samples

hop_factor: int

Hop factor (hop = frame_len // hop_factor)

window_type: str

Window type for STFT

compute_stft(source)[source]

Compute and cache STFT outputs for the source signal.

This method may only be called once per simulation run. If the cache is already populated, RuntimeError is raised — call reset() first to clear it before recomputing.

Parameters:

source (State) – Source state used by concrete implementations to build the waveform.

Returns:

Cached STFT tuple (stft, frequencies_hz, hop_samples, window).

Return type:

CachedStftResult

Raises:

RuntimeError – If compute_stft() has already been called on this instance. Call reset() to clear the cache before recomputing.

get_stft()[source]

Return cached STFT data.

Returns:

Cached STFT tuple (stft, frequencies_hz, hop_samples, window).

Return type:

CachedStftResult

Raises:

RuntimeError – If compute_stft() has not been called yet.

get_source_signal()[source]

Return the cached full-duration source signal.

Returns:

Cached source waveform.

Return type:

ComplexArray

Raises:

RuntimeError – If compute_stft() has not been called yet.

get_source_waveform(source)[source]

Return the cached source waveform, computing it on first call.

If the cache is already populated but source is not the same object that was passed to compute_stft(), a UserWarning is raised. This guards against stale-cache bugs in multi-source simulations where the same model instance is accidentally reused across different targets. Call reset() then compute_stft() to update the cache.

Parameters:

source (State) – Source state used to generate the waveform if not yet cached.

Returns:

Full-duration source waveform.

Return type:

ComplexArray

stft_geometry()[source]

Return STFT geometry derived purely from signal model properties.

Returns:

(num_freq_bins, frequencies_hz, hop, window, num_frames). No source State is required.

Return type:

tuple of (int, FloatArray, int, FloatArray, int)

reset()[source]

Clear the cached STFT and source-signal state.

Call this before reusing a signal model instance across multiple simulation runs, or after changing signal parameters, so that the next call to compute_stft() generates a fresh waveform and STFT.

This method is safe to call even if compute_stft() has never been called — it is a no-op in that case.

Subclasses that maintain additional caches (e.g. noise realisations in SyntheticSignal) override this method and call super().reset() to ensure all state is cleared.

Return type:

None

Parameters:
  • duration_s (float)

  • sampling_rate_hz (int)

  • frame_len (int)

  • hop_factor (int)

  • window_type (str)

class bluepebble.signal.SyntheticAnthropogenicSignal(duration_s, sampling_rate_hz, frame_len=1024, hop_factor=4, window_type='hann', tonal_bandwidth_hz=2.0, noise_amplitude_upa=0.0, noise_spectral_exponent=-1.0, noise_freq_range_hz=(20.0, 200.0), noise_variance=1.0, tonal_noise_is_constant=False, use_powerlaw_noise=False, noise_is_constant=True, seed=None)[source]

Generates ship signals with broadband tonals and coloured noise.

This signal model combines: 1. Broadband tonals with finite bandwidth 2. Wideband coloured noise 3. STFT-based frequency-domain processing for efficient propagation

Parameters:
  • frame_len (int, optional) – STFT frame length in samples (power of 2 recommended). Default is 1024.

  • hop_factor (int, optional) – Hop factor, where hop size = frame_len // hop_factor. Default is 4.

  • window_type (str, optional) – Window type for STFT (e.g., ‘hann’). Default is ‘hann’.

  • tonal_bandwidth_hz (float, optional) – Bandwidth of each tonal component in Hz. Creates realistic spectral spreading around nominal frequencies. Default is 2.0.

  • noise_amplitude_upa (float, optional) – RMS amplitude of background noise in µPa. Set to 0.0 to disable noise. Default is 0.0.

  • noise_spectral_exponent (float, optional) – Spectral shape exponent for coloured noise. -1.0 is pink noise (1/f), -2.0 is red/brownian noise (1/f^2), and 0.0 is white. Default is -1.0.

  • noise_freq_range_hz (tuple, optional) – Tuple of (min_freq, max_freq) for noise generation. Default is (20.0, 200.0), covering typical machinery noise ranges.

  • noise_variance (float, optional) – Variance multiplier applied to all generated white noise before any bandlimiting or normalisation (default 1.0). This controls the base random field variance.

  • tonal_noise_is_constant (bool, optional) – If True, reuse the same band-limited tonal noise across calls; phase and amplitude are still applied per call. Default is False.

  • use_powerlaw_noise (bool, optional) – If True, build broadband noise deterministically from the power-law spectrum (no random white-noise seed). Default is False.

  • noise_is_constant (bool, optional) – If True, use same noise realization for all signal generations (constant scalar over time). If False, generate new random noise each time. Default is True.

  • seed (int or None, optional) – Seed for the random number generator. When None (default), defers to the global seed set by bluepebble.set_seed() if called, otherwise non-deterministic. Provide an integer for a reproducible independent stream.

  • duration_s (float)

  • sampling_rate_hz (int)

Examples

Merchant vessel with propeller tonals and machinery noise:

>>> signal_model = SyntheticAnthropogenicSignal(
...     duration_s=60.0,
...     sampling_rate_hz=500.0,
...     frame_len=500,
...     hop_factor=4,
...     tonal_bandwidth_hz=3.0,  # Broader tonals
...     noise_amplitude_upa=10**(50/20),  # 50 dB re 1 µPa background
...     noise_spectral_exponent=-1.0,  # Pink noise
...     noise_freq_range_hz=(30.0, 150.0)
... )
tonal_bandwidth_hz: float

Bandwidth of each tonal component (Hz)

noise_amplitude_upa: float

RMS amplitude of background noise (µPa)

noise_spectral_exponent: float

Spectral shape exponent (-1=pink, -2=red/brownian, 0=white)

noise_freq_range_hz: tuple[float, float]

Frequency range for noise (Hz)

noise_variance: float

Variance multiplier for generated white noise before shaping; std = sqrt(variance).

tonal_noise_is_constant: bool

If True, reuse the same band-limited tonal noise across calls; phase and amplitude are still applied per call.

use_powerlaw_noise: bool

If True, build broadband noise deterministically from the power-law spectrum (no random white-noise seed).

noise_is_constant: bool

If True, use same noise realization across calls; if False, generate new noise each time

seed: int | None

Seed for the random number generator. None defers to the global seed set by bluepebble.set_seed() if called, otherwise gives non-deterministic output; an explicit integer always produces a reproducible independent stream.

reset()[source]

Clear cached STFT and source signal data.

Call this when starting a new simulation with different source parameters.

Return type:

None

class bluepebble.signal.RecordedAnthropogenicSignal(duration_s, sampling_rate_hz, wav_path, frame_len=1024, hop_factor=4, window_type='hann', segment_start_s=0.0, segment_duration_s=0.0, duration_match_mode='tile', level_db_re_1upa=85.0)[source]

Generates broadband source signals from measured WAV recordings.

This signal model loads a measured waveform from disk, resamples it to the simulator sampling rate, matches the requested simulation duration, scales to a target RMS level in dB re 1 µPa, and then computes/caches an STFT for frequency-domain propagation.

Parameters:
  • wav_path (str) – Path to the measured WAV file.

  • frame_len (int, optional) – STFT frame length in samples. Default is 1024.

  • hop_factor (int, optional) – Hop factor, where hop size = frame_len // hop_factor. Default is 4.

  • window_type (str, optional) – STFT window type. Default is “hann”.

  • segment_start_s (float, optional) – Start time (seconds) within the WAV to extract. Default is 0.0.

  • segment_duration_s (float, optional) – Duration (seconds) to extract before duration matching. If <= 0, uses to the end of file.

  • duration_match_mode (str, optional) – Method to match requested duration when audio is shorter than required. Supported values: “tile”, “zero_pad”. Default is “tile”.

  • level_db_re_1upa (float, optional) – Target RMS level of the source signal in dB re 1 µPa. Default is 85.0.

  • duration_s (float)

  • sampling_rate_hz (int)

wav_path: str

Path to measured WAV recording

segment_start_s: float

Segment start time in WAV (seconds)

segment_duration_s: float

Segment duration in WAV (seconds); <=0 uses to end of recording

duration_match_mode: str

Duration matching mode when audio is short: “tile” or “zero_pad”

level_db_re_1upa: float

Target RMS source level in dB re 1 µPa

bluepebble.signal.compute_stft(signal, frame_len, hop_factor=4, window='hann')[source]

Compute Short-Time Fourier Transform of a signal.

Uses overlap-add method matching BroadbandArrayProcessor implementation.

Parameters:
  • signal (ArrayLike) – Input time-domain signal (complex or real).

  • frame_len (int) – STFT frame length in samples (power of 2 recommended).

  • hop_factor (int, optional) – Hop size = frame_len // hop_factor (4 gives 75% overlap).

  • window (WindowType, optional) – Window type (‘hann’, ‘hamming’, ‘blackman’).

Returns:

Tuple containing:
stftComplexArray

STFT matrix of shape (num_frames, num_freq_bins).

frequenciesFloatArray

Frequency array for the bins.

hopint

Hop size in samples.

window_arrayFloatArray

The window array used.

Return type:

StftResult

bluepebble.signal.inverse_stft(stft, frame_len, hop, window)[source]

Reconstruct time-domain signal from STFT using overlap-add.

Matches BroadbandArrayProcessor._inverse_stft() implementation.

Parameters:
  • stft (ArrayLike) – STFT matrix of shape (num_frames, num_freq_bins).

  • frame_len (int) – STFT frame length in samples.

  • hop (int) – Hop size in samples.

  • window (ArrayLike) – Window array used in forward STFT.

Returns:

Reconstructed time-domain signal.

Return type:

ComplexArray

bluepebble.signal.apply_fade_in(signal, fade_samples)[source]

Apply smooth cosine-taper fade-in to signal arrival.

Uses a raised cosine (Tukey) window for smooth signal arrival, matching the BroadbandArrayProcessor implementation.

Parameters:
  • signal (ArrayLike) – Input signal.

  • fade_samples (int) – Number of samples for fade-in duration.

Returns:

Signal with fade-in applied.

Return type:

SignalArray

bluepebble.signal.apply_fade_out(signal, fade_samples)[source]

Apply smooth cosine-taper fade-out to the end of a signal.

Uses the same raised-cosine profile as apply_fade_in(), reversed so the signal transitions smoothly from 1 to 0 over fade_samples.

Parameters:
  • signal (ArrayLike) – Input signal.

  • fade_samples (int) – Number of samples for fade-out duration.

Returns:

Signal with fade-out applied.

Return type:

SignalArray

bluepebble.signal.effects

Post-processing effects that can be applied to synthesised sensor signals.

Signal post-processing effects.

This module provides Effect subclasses that can be applied to complex sensor-signal arrays after synthesis but before beamforming or output. Each effect operates independently on each sensor channel.

Current implementations:

  • Reverb — convolutional reverb via a synthetic exponentially-decaying impulse response, controlled by duration_s and wet_dry_mix.

class bluepebble.signal.effects.Effect[source]

A base class for all signal post-processing effects.

abstractmethod apply(signals, sampling_rate_hz)[source]

Apply the effect to the signal. Must be implemented by subclasses.

Parameters:
  • signals (ndarray[tuple[Any, ...], dtype[complex128]])

  • sampling_rate_hz (int)

Return type:

ndarray[tuple[Any, …], dtype[complex128]]

class bluepebble.signal.effects.Reverb(duration_s=1.0, wet_dry_mix=0.3, seed=None)[source]

Applies a simple convolutional reverb effect to the signal.

Parameters:
  • duration_s (float)

  • wet_dry_mix (float)

  • seed (int | None)

duration_s: float

The decay time of the reverb tail in seconds.

wet_dry_mix: float

Mix between wet (reverb) and dry signal (0=dry, 1=wet).

seed: int | None

Seed for the impulse-response RNG. None defers to the global seed set by bluepebble.set_seed() (different reproducible tail per call) or gives a non-deterministic tail if no global seed is set; an explicit integer produces the same tail for the same duration_s and sampling_rate_hz across calls and runs.

apply(signals, sampling_rate_hz)[source]

Apply a simple convolutional reverb effect to the signal.

Parameters:
  • signals (ComplexArray) – An array of complex signals with shape (num_sensors, num_samples).

  • sampling_rate_hz (int) – The sampling rate in Hertz.

Returns:

An array of complex signals with the reverb effect applied, with shape (num_sensors, num_samples).

Return type:

ComplexArray

Raises:

ValueError – If duration_s is not positive or wet_dry_mix is not in [0, 1].