🎵 sound_rs
sound_rs is a fast, Rust-powered audio playback library for Python that I built and maintain — decoding with symphonia, output through cpal, so the same code runs on macOS, Windows and Linux.
🚀 Features
- Formats: WAV, MP3, FLAC, OGG/Vorbis, M4A, AAC — any bit depth, including 24-bit
- NumPy arrays: play 1D mono
(samples,)or 2D(channels, samples)float32 arrays - Resampling: linear interpolation to the device rate, channel folding to the device layout
- Device-native output: the stream is opened in whatever sample format the device wants (f32, i16, u16, ...)
- Non-blocking for others: playback blocks the calling thread but releases the GIL, so other Python threads keep running
- Tone generator:
play_sine_wave(440, 2.0, 44100)
🧠 Installation
pip install sound_rs
💻 Usage
Playback
import sound_rs
sound_rs.play_audio("sound.wav")
sound_rs.play_audio("sound.mp3")
sound_rs.play_audio("sound.flac")
sound_rs.play_audio("sound.m4a")
Inspect a file
sample_rate, channels, duration = sound_rs.get_audio_info("sound.mp3")
sound_rs.is_supported_format("sound.mp3") # probes the header, does not decode
From a NumPy array
import numpy as np
import sound_rs
rate = 44100
t = np.linspace(0, 2.0, rate * 2, endpoint=False, dtype=np.float32)
sound_rs.play_array(np.sin(2 * np.pi * 440 * t), rate) # mono, 1D
sound_rs.play_array(np.stack([left, right]), rate) # 2D, channels first
Background playback
import threading
threading.Thread(target=sound_rs.play_audio, args=("long.mp3",)).start()
Tone generator
sound_rs.play_sine_wave(440.0, 1.0, 44100) # frequency, duration, sample rate
🧩 Benchmark
play_audio is synchronous, so its wall-clock time is dominated by the track's
own duration. The interesting numbers are decode throughput and overhead
(wall clock − audio duration).
python examples/benchmark.py # generated 3s tone: decode + playback
python examples/benchmark.py --compare # + sounddevice / soundfile
python examples/benchmark.py --files a.mp3 b.flac # decode table for real files
Hardware and setup I measured on: Apple M5 Pro, macOS 26.6.2, Python 3.14.7,
release build (lto = "fat", opt-level = 3), 60 s of 44.1 kHz stereo, best of 5
runs, competitor is libsndfile (soundfile 0.14).
| format | size | sound_rs | soundfile | result |
|---|---|---|---|---|
| WAV (PCM 16) | 10.6 MB | 5.6 ms | 7.1 ms | 1.3× faster |
| FLAC | 0.7 MB | 10.2 ms | 26.1 ms | 2.6× faster |
| MP3 | 1.0 MB | 19.6 ms | 16.1 ms | 1.2× slower |
| M4A (AAC) | 1.0 MB | 22.1 ms | unsupported | sound_rs only |
Playback of a 3 s tone, overhead over the track duration:
| wall clock | overhead | |
|---|---|---|
| sound_rs | 3.240 s | +0.239 s |
| sounddevice | 3.234 s | +0.234 s |
Both pay the same cost: opening and closing the audio stream on every call. I want to be straight about the weak spots too: my MP3 decoding is ~20% behind libmpg123, and on uncompressed WAV there is no real race to win — both sides are a memcpy. The playback overhead is the number I intend to fix with a persistent stream, which should bring it down to single-digit milliseconds.
🛠️ Roadmap
| Step | Feature | Description |
|---|---|---|
| ✅ 1 | WAV playback | Core playback |
| ✅ 2 | MP3, FLAC, M4A, AAC, 24-bit | Full symphonia decode path |
| ✅ 3 | NumPy integration | 1D/2D float32 arrays |
| 🔜 4 | Player object |
Persistent stream: pause, resume, seek, volume, position |
| 🔜 5 | Device selection | list_devices(), choose input/output |
| 🔜 6 | Recording | Microphone → array or WAV |
| 🔜 7 | Decode to array | load(path) -> (ndarray, sample_rate) without playing |
🧪 Development
cargo test # resampler and channel conversion
maturin develop --release # build the extension into your venv
python tests/smoke.py # end-to-end decode checks
SOUND_RS_PLAY=1 python tests/smoke.py # also plays (needs an audio device)
python examples/benchmark.py
⚙️ Built With
- 🦀 Rust — performance and safety
- 🔗 PyO3 — Python bridge
- 🧰 Maturin — building and publishing
- 🔊 cpal + symphonia — audio backend and decoders
👨💻 Author
Nurassyl Mussainov Kazakhstan 🇰🇿 Python / Rust Developer
🔗 GitHub: Neksand 📦 PyPI: sound_rs
📜 License
Licensed under the MIT License — free for personal and commercial use.
Metadata
Release files for sound-rs 0.1.6
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| sound_rs-0.1.6.tar.gz | 760.0 kB | Without provenance | Details for sound_rs-0.1.6.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| sound_rs-0.1.6-cp314-cp314-macosx_11_0_arm64.whl | CPython 3.14 | CPython 3.14 | macOS 11.0+ ARM64 | Details for sound_rs-0.1.6-cp314-cp314-macosx_11_0_arm64.whl |
Total release size: 1.5 MB
Release files / sound_rs-0.1.6.tar.gz
| Download URL | sound_rs-0.1.6.tar.gz |
|---|---|
| Size | 760.0 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
98f6cbe39af3f10508eec478c90a8c1c0269436f7b396f66fb5cb9fd7825fdac
|
|
BLAKE2b-256 checksum How to use checksums |
e9cb34c0759e6b5e91bbd5fe5255339225edbb25a55234fb2006a902fd047e62
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Release files / sound_rs-0.1.6-cp314-cp314-macosx_11_0_arm64.whl
| Download URL | sound_rs-0.1.6-cp314-cp314-macosx_11_0_arm64.whl |
|---|---|
| Size | 737.6 kB |
| Tags | CPython 3.14 macOS 11.0+ ARM64 |
|
SHA-256 checksum How to use checksums |
2f87a6b0dfcfc77c994c80dcb79090890cbf1108e9fc61aa3291c1c7492400a7
|
|
BLAKE2b-256 checksum How to use checksums |
5f8a182ef14dc890f4edb27cc1e217ce0bc98374b3fdbed56252e431a58fb732
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/7.0.0 CPython/3.14.7
|
Security for sound-rs 0.1.6
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.