Skip to main content

Fast audio analysis library with C++ and Python bindings

Project description

libsonare

PyPI npm License

Fast audio analysis library for Python.

Built on a C++ core with zero Python dependencies.

Installation

pip install libsonare

Supported platforms: Linux (x86_64, aarch64), macOS (Apple Silicon).

Quick Start

Audio is the recommended entry point. The top-level libsonare.detect_* / libsonare.analyze functions are thin wrappers around Audio for one-shot calls and are kept for convenience.

Load from a file

import libsonare

audio = libsonare.Audio.from_file("song.mp3")  # or "song.wav"
print(f"BPM: {audio.detect_bpm():.1f}")
print(f"Key: {audio.detect_key().root.name} {audio.detect_key().mode.name}")

result = audio.analyze()  # BPM + key + time signature + beats
print(f"BPM: {result.bpm:.1f}  Key: {result.key.root.name} {result.key.mode.name}")

Load from a numpy array / in-memory samples

from_buffer accepts any 1D float sequence. With numpy, use a mono float32 array (stereo must be downmixed first, e.g. samples.mean(axis=1)).

import numpy as np
import libsonare

sr = 22050
samples = np.asarray(my_mono_float32_signal, dtype=np.float32)

audio = libsonare.Audio.from_buffer(samples, sample_rate=sr)
bpm = audio.detect_bpm()

# Or call the function directly (equivalent shortcut)
bpm = libsonare.detect_bpm(samples, sample_rate=sr)

Mastering

The Python binding exposes the same mastering processors as the C, CLI, Node, and WASM APIs.

import libsonare

names = libsonare.mastering_processor_names()  # e.g. "dynamics.compressor"

compressed = libsonare.mastering_process(
    "dynamics.compressor",
    samples,
    sample_rate=sr,
    params={"thresholdDb": -24.0, "ratio": 1.5},
)

widened = libsonare.mastering_process_stereo(
    "stereo.imager",
    left,
    right,
    sample_rate=sr,
    params={"width": 1.1},
)

pair_names = libsonare.mastering_pair_processor_names()  # e.g. "match.abCrossfade"
crossfaded = libsonare.mastering_pair_process(
    "match.abCrossfade",
    source,
    reference,
    sample_rate=sr,
    params={"mix": 0.25},
)

loudness_json = libsonare.mastering_pair_analyze(
    "match.referenceLoudness",
    source,
    reference,
    sample_rate=sr,
)
mono_compat_json = libsonare.mastering_stereo_analyze(
    "stereo.monoCompatCheck",
    left,
    right,
    sample_rate=sr,
)

Mastering chain

mastering_chain runs the full configurable mastering pipeline (EQ, dynamics, saturation, repair, stereo, loudness, ...). The Python binding accepts flat dot-notation keys for the config dict — addressing any module parameter directly — and an optional on_progress(progress, stage) callback that is invoked after each stage (progress in [0, 1]).

import libsonare

result = libsonare.mastering_chain(
    samples,
    sample_rate=sr,
    config={
        "eq.tilt.tiltDb": 0.5,
        "dynamics.compressor.thresholdDb": -24.0,
        "dynamics.compressor.ratio": 1.5,
        "dynamics.transientShaper.attackGainDb": 2.0,
        "repair.declick.enabled": True,
        "loudness.targetLufs": -14.0,
        "loudness.ceilingDb": -1.0,
    },
    on_progress=lambda p, stage: print(f"[{p * 100:5.1f}%] {stage}"),
)

stereo_result = libsonare.mastering_chain_stereo(
    left, right, sample_rate=sr,
    config={"stereo.imager.width": 1.1, "loudness.targetLufs": -14.0},
)

MasteringChainResult exposes the rendered samples plus loudness telemetry (input_lufs, output_lufs, applied_gain_db, latency_samples).

Mastering presets

Named presets ship sensible defaults for common targets. master_audio applies a preset and lets you override any individual parameter using the same flat dot-notation keys as mastering_chain.

import libsonare

libsonare.mastering_preset_names()
# -> ['pop', 'edm', 'acoustic', 'hipHop', 'aiMusic', 'speech']

result = libsonare.master_audio(
    samples,
    sample_rate=sr,
    preset="aiMusic",
    overrides={
        "loudness.targetLufs": -13.0,
        "dynamics.multibandComp.enabled": True,
    },
)

# Audio shortcut
audio = libsonare.Audio.from_file("song.wav")
pop_mastered = audio.master_audio("pop")

Streaming mastering chain

StreamingMasteringChain runs the same pipeline block-by-block for real-time or chunked workflows. The constructor takes the same flat dot-notation config as mastering_chain; non-streamable stages (repair.denoise, loudness) cause the constructor to raise, so omit those keys for streaming use. The object is also a context manager.

import libsonare

with libsonare.StreamingMasteringChain({
    "eq.tilt.tiltDb": 0.5,
    "dynamics.compressor.thresholdDb": -20.0,
    "dynamics.transientShaper.attackGainDb": 1.5,
}) as chain:
    chain.prepare(sample_rate=48000, max_block_size=512, num_channels=1)
    print(chain.stage_names())
    print(f"latency = {chain.latency_samples()} samples")

    out_block = chain.process_mono([0.0] * 512)
    # Stereo:
    # chain.prepare(48000, 512, 2)
    # out_l, out_r = chain.process_stereo(left_block, right_block)
    chain.reset()

Library version

import libsonare
libsonare.__version__   # e.g. "1.0.4"  (preferred — matches importlib.metadata)
libsonare.version()     # native library version string

Supported audio formats

Format Default build With FFmpeg support
WAV (PCM 16/24/32, float32) yes yes
MP3 yes yes
M4A / AAC / FLAC / OGG / Opus / WMA / ... no yes

If Audio.from_file() is given an unsupported format you will see a clear error such as:

RuntimeError: Unsupported audio format: '.m4a'. Supported: WAV, MP3.
Rebuild with -DSONARE_WITH_FFMPEG=ON for M4A/AAC/FLAC/OGG,
or convert via: ffmpeg -i "song.m4a" output.wav

The PyPI wheels are pinned to SONARE_WITH_FFMPEG=OFF so the distributed wheel never silently links against the build host's FFmpeg. From-source builds default to AUTO detection via pkg-config: if FFmpeg dev libraries are present they are enabled, otherwise WAV/MP3 only.

To enable FFmpeg-backed decoding when building from source:

git clone https://github.com/libraz/libsonare
cd libsonare
SONARE_FFMPEG=1 bash bindings/python/build_wheel.sh   # require FFmpeg
# or
SONARE_FFMPEG=AUTO bash bindings/python/build_wheel.sh # detect via pkg-config
pip install bindings/python/dist/*.whl

This links against the system FFmpeg shared libraries (LGPL by default), so ensure they are installed (e.g. brew install ffmpeg, apt install libavformat-dev libavcodec-dev libavutil-dev libswresample-dev).

Function vs Audio method

Both APIs return the same results. Use whichever is more convenient:

# Functional (good for ad-hoc numpy work)
bpm = libsonare.detect_bpm(samples, sample_rate=22050)        # -> float
key = libsonare.detect_key(samples, sample_rate=22050)        # -> Key(root, mode, confidence)
result = libsonare.analyze(samples, sample_rate=22050)        # -> AnalysisResult

# Audio class (recommended for files, multiple operations on the same audio)
audio = libsonare.Audio.from_file("song.wav")
bpm = audio.detect_bpm()
key = audio.detect_key()
result = audio.analyze()

Audio caches the decoded samples and is the only way to load files, so it is the recommended entry point when you do more than a single computation on the same signal.

Input format expectations

API dtype shape range
Audio.from_buffer(samples, sample_rate=...) float32 (float64 also accepted) 1D mono nominally [-1.0, 1.0]
Audio.from_memory(data) bytes of an encoded WAV / MP3 / (FFmpeg) file
Audio.from_file(path) path to an encoded audio file
libsonare.detect_bpm(samples, sample_rate=...) etc. float32 (float64 also accepted) 1D mono nominally [-1.0, 1.0]

Stereo input is not downmixed automatically when passed as samples — downmix yourself (e.g. samples.mean(axis=1, dtype=np.float32)). File loaders downmix to mono internally.

CLI

sonare analyze song.mp3
# > Estimated BPM : 161.00 BPM  (conf 75.0%)
# > Estimated Key : C major  (conf 100.0%)

sonare bpm song.mp3 --json       # {"bpm": 161.0}
sonare key song.mp3              # Key: C major (confidence: 100.0%)
sonare spectral song.mp3         # Spectral features table
sonare pitch song.mp3            # Pitch tracking (pYIN)
sonare mel song.mp3              # Mel spectrogram shape
sonare chroma song.mp3           # Chromagram with visualization

sonare mastering song.wav -o mastered.wav --target-lufs -14
sonare mastering-processor song.wav --processor dynamics.compressor --params thresholdDb=-24,ratio=1.5
sonare mastering-pair-processor source.wav --reference reference.wav --processor match.abCrossfade
sonare mastering-pair-analyze source.wav --reference reference.wav --analysis match.referenceLoudness
sonare mastering-stereo-analyze left.wav --reference right.wav --analysis stereo.monoCompatCheck

Features

  • Detection: BPM (float), key (Key(root, mode, confidence)), beats (list[float] seconds), onsets (list[float] seconds)
  • Analysis: Full music analysis (AnalysisResult with BPM, key, time signature, beat times)
  • Effects: HPSS, pitch shift, time stretch, normalize, trim
  • Features: STFT, mel spectrogram, MFCC, chroma, spectral features, pitch tracking (YIN / pYIN with voicing probabilities)
  • Conversions: Hz / mel / MIDI / note, frames / time
  • I/O: Load WAV / MP3 (and M4A/AAC/FLAC/OGG when built with FFmpeg), resample

librosa-compatible defaults

Parameter Default
Sample rate 22050 Hz
n_fft 2048
hop_length 512
n_mels 128
fmin / fmax 0.0 / sr/2

Also available

npm install @libraz/libsonare  # JavaScript / TypeScript (WASM)

License

Apache-2.0

Project details


Download files

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

Source Distributions

No source distribution files available for this release.See tutorial on generating distribution archives.

Built Distributions

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

libsonare-1.1.0-py3-none-manylinux_2_17_x86_64.whl (1.1 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ x86-64

libsonare-1.1.0-py3-none-manylinux_2_17_aarch64.whl (1.0 MB view details)

Uploaded Python 3manylinux: glibc 2.17+ ARM64

libsonare-1.1.0-py3-none-macosx_11_0_arm64.whl (835.1 kB view details)

Uploaded Python 3macOS 11.0+ ARM64

File details

Details for the file libsonare-1.1.0-py3-none-manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for libsonare-1.1.0-py3-none-manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 e8c66457d423ddb5eb852becca8b4caed0785196acf115538dcface3a448938a
MD5 7bbec56b9900c7984761b65cf46d3c58
BLAKE2b-256 1d3dc4562880ed28743fa2269f15fb5c1b4fc37cc348badcd86c3c45ba8640d0

See more details on using hashes here.

Provenance

The following attestation bundles were made for libsonare-1.1.0-py3-none-manylinux_2_17_x86_64.whl:

Publisher: publish.yml on libraz/libsonare

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

File details

Details for the file libsonare-1.1.0-py3-none-manylinux_2_17_aarch64.whl.

File metadata

File hashes

Hashes for libsonare-1.1.0-py3-none-manylinux_2_17_aarch64.whl
Algorithm Hash digest
SHA256 afaff68f7ae7ceb20c741783b36ab49d5f972fb506c6128c3dbfd66ce05b10d8
MD5 1463fd6a7a9b6319e1656224e14bc7fb
BLAKE2b-256 973fa54e5b6cf4553b77edf5da6f238738888322b6b6c370734538f39cca83f7

See more details on using hashes here.

Provenance

The following attestation bundles were made for libsonare-1.1.0-py3-none-manylinux_2_17_aarch64.whl:

Publisher: publish.yml on libraz/libsonare

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

File details

Details for the file libsonare-1.1.0-py3-none-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for libsonare-1.1.0-py3-none-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 e2ff1c3dc29b21abf02ddb9ed561519b460500381046ca9090787967a0df030f
MD5 aa955ced2eada682499808e229cf0d47
BLAKE2b-256 82327dcd544df0b8a806a392595bd8226881bd50f38dfdd1ac265c85eb4897f0

See more details on using hashes here.

Provenance

The following attestation bundles were made for libsonare-1.1.0-py3-none-macosx_11_0_arm64.whl:

Publisher: publish.yml on libraz/libsonare

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