Skip to main content

Bispectral features for audio: modal estimation, librosa-style API

Project description

bispectrosa

Bispectral features for audio.

PyPI Python 3.10-3.14 CI License MIT

InstallQuick startWhat it computesReconstructionArchitectureDocsCite

The bispectrum B(f₁, f₂) = ⟨X(f₁) X(f₂) X*(f₁+f₂)⟩ is the third-order spectrum: the correlation between the frequency components at f₁, f₂, and f₁+f₂, a part of the signal the power spectrum cannot see. bispectrosa turns it into a practical audio feature: one call, waveform in, a few dozen bispectral coefficients per frame out.

The API follows librosa conventions (waveform in, feature out, time as the last axis).

Install

pip install "bispectrosa[audio]"      # audio front-end (pulls in librosa)
pip install "bispectrosa[audio,viz]"  # + plotting

The generic core imports with only numpy and scipy; librosa is needed only for the audio layer.

Quick start

import numpy as np, bispectrosa as bs

y = np.random.default_rng(0).standard_normal(16000).astype(np.float32)

B = bs.mel_bispectrogram(y, sr=16000)   # (49, n_frames) at degree 12
v = bs.time_pool(B)                     # (49,) utterance-level vector

The signature follows librosa: y is positional, everything else is keyword-only (sr, degree, n_fft, hop_length, n_mels, fmin, fmax, window, center, ...). Defaults are tuned for speech (sr=16000, n_fft=400, hop_length=160, n_mels=80), not librosa's music defaults, so set them explicitly for other domains. Coefficients come out time-last, so librosa post-processing composes directly, e.g. librosa.feature.delta(B) for delta features.

To compute the STFT once and share it across features, pass S= (the complex STFT, since the bispectrum needs phase) instead of y:

X = bs.stft(y)                          # one transform
B = bs.mel_bispectrogram(S=X, sr=16000) # third-order feature
M = bs.mel_spectrogram(S=X, sr=16000)            # second-order companion

What it computes: bispectrum modal coefficients

The power spectrum treats every frequency separately: it carries no information about how components relate to one another. The bispectrum is the correlation between three components at once, those at f₁, f₂, and f₁+f₂: it averages to zero when they fluctuate independently and survives when they are correlated (nonlinearity). Harmonic structure, timbre, and source nonlinearities live there, invisible to second-order features.

Computed directly, the bispectrum is a large, noisy 2-D matrix per frame (raw_bispectrum, kept as the reference estimator). The main feature mel_bispectrogram uses a modal estimator instead, borrowed from cosmology, where the same compression problem appears: expand the bispectrum on a small basis of smooth functions built from mel-binned modes, and keep the coefficients β; 49 numbers per frame at the default degree, signed-log compressed like a log-mel spectrogram. The full derivation is in docs/theory.md.

Standard bispectrum reconstruction

The coefficients determine a best least-squares fit of the bispectrum by the basis; rebuilding it shows what the basis captures.

import numpy as np, bispectrosa as bs
from bispectrosa import bispectrum

Xstft = bs.stft(y)
F = Xstft.shape[0]
degree = 7
pairs = bs.modal_index_pairs(degree)
modes = bs.legendre_modes(np.linspace(-1, 1, F), degree)

beta = bispectrum.project_bispectrum(Xstft, pairs, modes)
gram = bs.modal_gram_matrix(pairs, modes)
x, _, B = bispectrum.reconstruct_bispectrum(beta, pairs, modes, gram=gram, return_full=True)
# x is a normalized [-1, 1] axis: here x = -1 is 0 Hz and x = +1 is sr / 2

Architecture

The generic math is separated from the audio choices, so the core (bispectrum.py) can be reused for other domains:

module role
bispectrum generic core (numpy/scipy only): the full and modal estimators (raw_bispectrum, ModalBispectrum), Legendre modes, pair kernels, Gram matrix, reconstruction. Knows nothing about sr, Hz, or mel.
filters audio layer: lays the 1-D modes on a frequency grid (Slaney mel, or custom triangular filterbanks) and builds the ModalBispectrum the core consumes.
feature front door: mel_bispectrogram, mel_spectrogram, mel_bin_bispectrum, stft, time_pool.
display bispectrum plotting.

Documentation

  • docs/theory.md: the bispectrum and the modal estimator, from definition to the fast form the code computes.
  • API reference: the numpydoc docstrings (help(bs.mel_bispectrogram), or any IDE hover).
  • examples/intro.ipynb: the guided tour, from a controlled phase-coupled signal to real recordings: the feature, the raw grid, reconstruction, and cost.
  • examples/animate_bispectrum.py: the per-frame bispectrum as a movie.

Development

uv sync --group dev     # install with dev dependencies
uv run pytest -q        # run the test suite
uv run ruff check .     # lint
uv run ruff format .    # format

Feature outputs are frozen bit-for-bit by tests/test_regression.py; see CHANGELOG.md for the release history.

Citing

If you use bispectrosa in your research, please cite it; see CITATION.cff.

License

MIT © 2026 Gabriel Jung. See LICENSE.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

bispectrosa-0.1.0.tar.gz (207.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

bispectrosa-0.1.0-py3-none-any.whl (36.7 kB view details)

Uploaded Python 3

File details

Details for the file bispectrosa-0.1.0.tar.gz.

File metadata

  • Download URL: bispectrosa-0.1.0.tar.gz
  • Upload date:
  • Size: 207.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for bispectrosa-0.1.0.tar.gz
Algorithm Hash digest
SHA256 11ab4f2e3c6e6df21660863a6eae47ff1385c365b7d63ffb8b57cc0313c82b73
MD5 b43d6496f1c68fb4cf061d8bd3681b68
BLAKE2b-256 e2b74564c86b860fbbb16b18de716934411ab79166e45d8e0dbfcc3ef888c7e5

See more details on using hashes here.

Provenance

The following attestation bundles were made for bispectrosa-0.1.0.tar.gz:

Publisher: release.yml on gabriel-jung/bispectrosa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

File details

Details for the file bispectrosa-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: bispectrosa-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 36.7 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.14

File hashes

Hashes for bispectrosa-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 f96044813611466a86c06612a3755769e4fc64f3e70eddb999ce713843d1d2fb
MD5 3594fc230a4758342cfd6e135c8c153e
BLAKE2b-256 0573479a9d4fc0240ce727261d50743a523c2e65e6e8472471918b10e97139a1

See more details on using hashes here.

Provenance

The following attestation bundles were made for bispectrosa-0.1.0-py3-none-any.whl:

Publisher: release.yml on gabriel-jung/bispectrosa

Attestations: Values shown here reflect the state when the release was signed and may no longer be current.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page