Core concepts
Three dataclasses carry the audio through the pipeline: AudioSource, Unit, and SymbolStream. They are designed so that
every downstream statistic remains tied to the audio it came from.
AudioSource
The result of load_audio(path). Holds:
samples— float32 mono array.sr— current sample rate (Hz).original_sr,original_channels— what was on disk before any downmix or resample.path,source_url,label— provenance.duration_s— convenience.
The contract is: write_wav(p, src.samples, src.sr) always produces a playable file.
Unit
A single acoustic unit returned by detect_units. Holds:
index— position in the detection sequence.start_s,end_s— offsets into the parent waveform.source_samples— the audio for this unit atsrHz.peak_db— peak amplitude at segmentation time.
A Unit is listenable on its own: write_wav(p, u.source_samples, u.sr).
SymbolStream
A categorical sequence aligned 1:1 with its audio units. Holds:
symbols— int array of cluster ids in[0, alphabet_size). No-1sentinels.alphabet_size— number of distinct symbols.units— parallel list of Unit objects.source_sr— sample rate of the parent recording.session_boundaries— list of half-open[start, end)intervals partitioning the sequence.name— short label used in logs and figure filenames.
The constructor validates: symbols are 1-D integer, in range, and session
boundaries (when present) cover [0, N) exactly once.
The round-trip invariant
This is the load-bearing rule of the toolkit. At every stage of processing — raw, bandpassed, segmented, clustered, embedded — there must be a way to get back to playable audio. In code:
- Segmentation returns timestamped offsets and the audio slice (the
Unit). - Clustering attaches labels to feature rows; the caller keeps the
unitsalongside, sounits[i]is the audio for clusterlabels[i]. - Embeddings are computed over Units; the audio lookup is the same parallel list.
The reason: any statistic computed downstream is interpretable only if you can re-listen. A novel "type" that turns out to be a single coughing engine is fixable in two minutes if you can play it.
Pipeline shape
load_audio → bandpass → detect_units → featurise → cluster_features → SymbolStream
| | | | |
AudioSource np.ndarray list[Unit] ClusterResult SymbolStream
(labels_assigned)
From a SymbolStream, downstream primitives compute entropy, mutual information, n-gram perplexity, transition graphs, Hill numbers, and the linguistic-laws tests (Zipf, Menzerath).