DSP · Python · Embedded Systems
A mathematical model for synthesizing blue whale B-call vocalizations in Python, based on a pulsed-air production mechanism. Repeating short-duration wavelets — derived from the derivative of a Cauchy-like pulse function — reproduce the fundamental frequency and harmonic overtones of real recorded blue whale calls. The eventual goal is a real-time hardware implementation on a microcontroller with a DAC.
Project Overview
Blue Whale B-Call Vocalizations
Blue whale B calls are tonal harmonic signals typically 10–20 seconds in duration, with a fundamental frequency that steps down between roughly 20 and 16 Hz. For decades, these calls were thought to originate from Helmholtz resonance — air flowing from the lungs into the upper respiratory spaces, with vocalization frequency proportional to the size of the resonating organ.
A 2017 paper by Dziak et al. (Scientific Reports) proposed an alternative: blue whales produce B calls by rapidly opening and closing respiratory valves (principally the U-fold, homologous to vocal folds in terrestrial mammals), generating a series of short-duration pneumatic air pulses. These pulses, taken together, produce the fundamental frequency and overtone structure of the B call — analogous to how repeating seismic or volcanic bursts generate harmonic tremor signals.
This model achieves a cross-correlation coefficient of r = 0.93 against real hydrophone recordings of blue whale B calls at 55 m depth, outperforming sinusoidal resonance models (r = 0.87).
Pulse Wavelet Construction
Each individual wavelet is constructed as the time derivative of a piecewise Cauchy-like function q(t). The asymmetric shape — sharper on the leading edge, slower decay on the trailing side — mimics the rapid valve opening and gradual pressure release of a pneumatic pulse.
Here a is a constant that sets the temporal location of the pulse peak, keeping the duration under one second. In the model, a = 0.005, yielding a pulse wavelet of approximately 0.068 seconds. Taking the derivative P(t) = dq/dt produces the actual waveform shape:
A full synthetic B call is constructed by concatenating 99 repetitions of two back-to-back pulses, then applying a sinusoidal volume envelope (sin 0→π/2 for the attack half, sin π/2→π for the decay half). The final signal is scaled to 16-bit integer range and exported as a WAV file.
Python / NumPy — Waveform & Spectrogram
The plots below show (top) a single 0.068 s pulse wavelet, (middle) the full synthesized waveform with sinusoidal amplitude envelope, and (bottom) the resulting spectrogram. The harmonic structure — a fundamental and evenly spaced overtones — is clearly visible, consistent with real blue whale B call recordings.
whale_script.py
The script below generates the whale song waveform, applies the sinusoidal volume
envelope, plots the single pulse, full waveform, and spectrogram, and writes the
output to a 16-bit WAV file (out.wav).
Planned Roadmap
The Python prototype validates the synthesis algorithm. The next phase is porting it to a microcontroller for real-time audio output via a DAC. Two candidate approaches are under consideration: Direct Digital Synthesis (DDS) using the pulse wavelet as a waveform primitive, or a precomputed lookup table stored in program memory that the MCU steps through at the target sample rate.
Wavelet construction, pulse train assembly, sinusoidal envelope, WAV export, spectrogram validation.
Evaluate STM32 (existing Kalman filter experience) vs RP2040/RP2350 for DAC output and DMA capability.
Compare DDS phase accumulator approach against a precomputed 16-bit LUT in flash. LUT is simpler for fixed-frequency output; DDS enables frequency agility.
Low-pass reconstruction filter after the DAC. Target output: 3.5mm audio jack or small speaker driver at whale-call frequencies (~16–20 Hz fundamental, well within audio band).
Implement inter-pulse interval control so the fundamental frequency can be swept in real time — matching the downward frequency step observed in real B calls.
Primary Source
The pulse model and mathematical framework implemented in this project are drawn directly from the following open-access paper: