Skip to main content

Lightweight full-featured audio playback in Python, built on Miniaudio

Project description

SoundObj

A modern Python wrapper for the miniaudio library, providing high-level audio playback and 3D spatialization capabilities.

Another audio library? Why?

It's a reasonable question.

The short version is that I couldn't find one that did what I wanted.

As of mid-2025, you either get a specialized set of features (playsound), a bloated installation that does way more than sound (pyglet/pygame/etc), licensing restrictions (bass/sound_lib), EOL/lack of support (Libaudioverse/Synthizer), data sciency stuff, or low-level interfaces (PyAudio/PyMiniaudio).

To be clear, I'm not knocking any of these libraries. I have used all of them once or twice, and have code in both pybass and sound_lib. At the time of writing, they are admitedly far more battle tested. In fact, I am likely to use them again and encourage you to do the same if they better serve your use case.

That said, I wanted something portable, permissive, and that just works with an API that is familiar or that someone could pick up and immediately start hacking on.

Features

  • Truly simple audio playback
  • Support for WAV, MP3, FLAC, OGG Vorbis, Opus, and everything else miniaudio is able to work with
  • Adjust volume, pitch, pan, and spatial properties during playback
  • Full support for positional audio, distance attenuation, and Doppler effects
  • Stream audio directly from HTTP/FTP(s) URLs, including live streams
  • Clean property-based Python interface
  • Support for multiple 3D audio listeners
  • Customizable engine settings for different use cases
  • Easy to extend, assuming you know a little bit of C and feel comfortable adding FFI declarations

Installation

Prerequisites

  • Python 3.13+
  • cffi library
  • vcpkg (included as submodule in vcpkg/ directory)
  • miniaudio library (pulled in by vcpkg)
  • curl (pulled in by vcpkg), used for URL streams

Build Instructions

  1. Clone the repository with submodules:
git clone --recursive https://github.com/cartertemm/soundobj.git
cd soundobj

Or if you already have a clone of the repository:

cd soundobj
git submodule update --init --recursive
  1. Install Python dependencies:
pip install cffi
  1. Build the FFI wrapper (will automatically handle VCPKG):
python build_ffi.py

Testing

After building the FFI wrapper, run the test suite with:

pytest tests/

Tests that require a real audio device are skipped automatically on headless machines. No additional dependencies beyond pytest are needed.

Roadmap

  • Upload to PyPI
  • Memory streams
  • A more comprehensive environment for managing multiple sounds simultaniously
  • More demos/examples
  • Optional support for HRTF, now that Steam Audio has been made open-source and is licensed under Apache-2.0. This wouldn't be included by default but would be an optional dependency for those who need it.

How you can help

Test, test, test. If you get weird behavior, open an issue and tell me about it. If you are willing and able, hack on one of these features.

Quick Start

Most things should be pretty self explanatory, as this library is a high-level API over the already high-level ma_engine API. If not, the Miniaudio programming manual is a good starting point. It explains concepts like the coordinate system, positioning in 3D space, attenuation, etc.

One-line audio playback

Just want a quick sound or earcon to play and don't care about anything else?

import soundobj
soundobj.play_sound("path/to/audio.wav") # Sound is already playing! It will automatically close when complete and you do not have any control over the sound after this point.

Basic Audio Playback with controls

import soundobj

# Create a sound object and load an audio file
snd = soundobj.Sound(source="path/to/audio.wav")
snd.play()  # Play the sound
snd.looping = True  # Enable looping
snd.volume = 0.8
snd.pitch = 1.2
# Wait a bit
snd.stop()

Streaming audio from a URL

Pass any http:// or https:// URL as the source and it works the same as a local file. This includes both regular audio files and live streams (e.g. internet radio) where the duration isn't known in advance.

import soundobj

snd = soundobj.Sound(source="https://example.com/audio.mp3")
snd.play()

# Or an internet radio stream
radio = soundobj.Sound(source="https://stream.example.com/live")
radio.play()
radio.volume = 0.5

3D Spatial Audio

import soundobj
from soundobj import AttenuationModel, PositioningMode

# Create an engine with custom configuration
config = soundobj.EngineConfig(
    channels=2,
    sampleRate=44100,
    listenerCount=1
)
engine = soundobj.Engine(config)
# Create a 3D positioned sound and enable spacialization
sound = soundobj.Sound(engine, "footsteps.wav")
sound.spatialization_enabled = True

# Position the sound in 3D space
sound.position = (5.0, 0.0, 10.0)  # (x, y, z)
sound.direction = (0.0, 0.0, -1.0)  # facing negative Z
# Configure distance attenuation
sound.attenuation_model = AttenuationModel.INVERSE
sound.min_distance = 1.0
sound.max_distance = 100.0
sound.rolloff = 2.0

# Set up velocity for Doppler effect
sound.velocity = (-2.0, 0.0, 0.0)  # moving left

# Configure sound cone for directional audio
sound.cone = (0.5, 1.0, 0.3)  # (inner_angle, outer_angle, outer_gain)
sound.play()

Engine and Listener Management

import soundobj

engine = soundobj.Engine()

# Get engine information
print(f"Channels: {engine.channels}")
print(f"Sample Rate: {engine.sample_rate}")
print(f"Listeners: {engine.listener_count}")

# Configure listener position and orientation
engine.set_listener_position(0, 0.0, 0.0, 0.0)  # listener at origin
engine.set_listener_direction(0, 0.0, 0.0, 1.0)  # facing positive Z
engine.set_listener_velocity(0, 1.0, 0.0, 0.0)   # moving right

# Set world up vector (for 3D orientation)
engine.set_listener_world_up(0, 0.0, 1.0, 0.0)   # Y is up

# Enable/disable listeners
engine.set_listener_enabled(0, True)

API Reference

Classes

Engine

The main audio engine that manages playback and 3D audio processing globally. A default global engine is created automatically at import, so most code can start with Sound directly and only instantiate Engine when custom configuration is needed.

Properties:

  • volume: Master volume (0.0 to 1.0+)
  • channels: Number of output channels (read-only)
  • sample_rate: Audio sample rate in Hz (read-only)
  • time_in_milliseconds: Current engine time (read-only)
  • listener_count: Number of 3D listeners (read-only)

Methods:

  • start(): Start the audio engine
  • stop(): Stop the audio engine
  • play_sound(file_path, group=None): Play a sound file directly
  • find_closest_listener(x, y, z): Find nearest listener to position
  • set_listener_position(index, x, y, z): Set listener position
  • get_listener_position(index): Get listener position
  • set_listener_direction(index, x, y, z): Set listener orientation
  • get_listener_direction(index): Get listener orientation

Sound

Represents an individual audio sound with full control over playback and 3D properties.

Basic Properties:

  • volume: Sound volume (0.0 to 1.0+)
  • pitch: Playback speed/pitch multiplier (1.0 = normal)
  • pan: Stereo pan (-1.0 = left, 0.0 = center, 1.0 = right)
  • looping: Enable/disable looping playback
  • is_playing: Check if currently playing (read-only)
  • length_in_seconds: Audio duration (read-only)
  • position_in_seconds: Current playback position (get/set)

3D Spatial Properties:

  • position: 3D position as (x, y, z) tuple
  • direction: Direction vector as (x, y, z) tuple
  • velocity: Velocity vector for Doppler effect
  • spatialization_enabled: Enable/disable 3D audio processing
  • attenuation_model: Distance attenuation model (enum or string)
  • positioning: Positioning mode (enum or string)

Distance and Attenuation:

  • rolloff: Distance attenuation rolloff factor
  • min_distance: Minimum distance for attenuation
  • max_distance: Maximum distance for attenuation
  • min_gain: Minimum volume level
  • max_gain: Maximum volume level

Advanced 3D Properties:

  • cone: Directional audio cone as (inner_angle, outer_angle, outer_gain)
  • doppler_factor: Doppler effect intensity (1.0 = normal)
  • directional_attenuation_factor: Directional volume reduction
  • direction_to_listener: Vector pointing to listener (read-only)
  • pinned_listener_index: Pin sound to specific listener
  • listener_index: Current listener index (read-only)

Methods:

  • load(source, stream=True): Load audio from a file path, URL, or bytes; auto-detects the source type
  • load_from_file(filename, stream=True): Load from file
  • load_from_url(url, stream=True): Load from an HTTP/HTTPS URL; works for both regular files and live streams
  • load_from_memory(data, stream=True): Load from memory (not implemented, raises NotImplementedError)
  • play(): Start playback
  • pause(): Pause playback
  • stop(): Stop playback
  • fade_in(duration_ms, start_volume=0.0, end_volume=1.0): Fade in effect
  • fade_out(duration_ms, end_volume=0.0): Fade out effect

EngineConfig

Configuration options for engine initialization.

Attributes:

  • listenerCount: Number of 3D listeners (default: 0 = auto)
  • channels: Output channels (default: 0 = auto)
  • sampleRate: Sample rate in Hz (default: 0 = auto)
  • periodSizeInFrames: Period size in frames (default: 0 = auto)
  • periodSizeInMilliseconds: Period size in ms (default: 0 = auto)
  • noAutoStart: Don't auto-start engine (default: False)
  • noDevice: Initialize without audio device (default: False)

Global functions

play_sound

play_sound(path, group = None) -> bool

Plays what miniaudio calls an inline sound. They're meant for convenience as it takes only one line of code to get one playing and you don't have to manage keeping it alive. The sacrifice however is that you get 0 control over the sound once it starts playing. Returns True if the sound played successfully, False otherwise.

The group parameter will allow you to attach such a sound to a ma_sound_group thus giving you volume/positioning control, keep it set at None for now (WIP at this time).

Enums

AttenuationModel

Distance-based volume attenuation models:

  • NONE: No distance attenuation
  • INVERSE: Realistic inverse distance attenuation
  • LINEAR: Linear distance attenuation
  • EXPONENTIAL: Exponential distance attenuation

PositioningMode

Sound positioning modes:

  • ABSOLUTE: Position in world coordinates
  • RELATIVE: Position relative to listener

Exceptions

MiniAudioError

Raised when miniaudio operations fail (engine initialization, file loading, etc.).

Licensing

This module is both released under the MIT and into the public domain. Choose which ever you prefer.

MIT

Copyright (c) 2025 Carter Temm

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Public Domain

This is free and unencumbered software released into the public domain.

Anyone is free to copy, modify, publish, use, compile, sell, or distribute this software, either in source code form or as a compiled binary, for any purpose, commercial or non-commercial, and by any means.

In jurisdictions that recognize copyright laws, the author or authors of this software dedicate any and all copyright interest in the software to the public domain. We make this dedication for the benefit of the public at large and to the detriment of our heirs and successors. We intend this dedication to be an overt act of relinquishment in perpetuity of all present and future rights to this software under copyright law.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

Acknowledgments

  • miniaudio by David Reid - The excellent underlying audio library
  • CFFI - For the Python/C integration. If I had to use ctypes I probably wouldn't have bothered.

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.

soundobj-0.3.0-cp314-cp314-win_amd64.whl (827.9 kB view details)

Uploaded CPython 3.14Windows x86-64

soundobj-0.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.14manylinux: glibc 2.17+ x86-64

soundobj-0.3.0-cp314-cp314-macosx_11_0_arm64.whl (3.9 MB view details)

Uploaded CPython 3.14macOS 11.0+ ARM64

soundobj-0.3.0-cp313-cp313-win_amd64.whl (802.4 kB view details)

Uploaded CPython 3.13Windows x86-64

soundobj-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (5.0 MB view details)

Uploaded CPython 3.13manylinux: glibc 2.17+ x86-64

soundobj-0.3.0-cp313-cp313-macosx_11_0_arm64.whl (3.9 MB view details)

Uploaded CPython 3.13macOS 11.0+ ARM64

File details

Details for the file soundobj-0.3.0-cp314-cp314-win_amd64.whl.

File metadata

  • Download URL: soundobj-0.3.0-cp314-cp314-win_amd64.whl
  • Upload date:
  • Size: 827.9 kB
  • Tags: CPython 3.14, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for soundobj-0.3.0-cp314-cp314-win_amd64.whl
Algorithm Hash digest
SHA256 fdb475c9da65ea2d60ad0830e23b2ee75dc81376876fb2ea5bbf8feb6524c873
MD5 d5e6be5c4dab88fb144ef4374e8dd714
BLAKE2b-256 156edc668946f8265c3bbc1d6d021ca67c210f0345267c48ddde4b180b1cfd43

See more details on using hashes here.

Provenance

The following attestation bundles were made for soundobj-0.3.0-cp314-cp314-win_amd64.whl:

Publisher: build.yml on cartertemm/soundobj

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

File details

Details for the file soundobj-0.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl.

File metadata

File hashes

Hashes for soundobj-0.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl
Algorithm Hash digest
SHA256 e9aff0cc87f59be3d1878ce4863e0d9805cc82fb9971de91a52584755900100c
MD5 2bcc4207128d79e3a3feffdff314eb34
BLAKE2b-256 56927e2556c61f1f2ec63716930871834cc27be22a03c723f42d14bfe2fadf39

See more details on using hashes here.

Provenance

The following attestation bundles were made for soundobj-0.3.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl:

Publisher: build.yml on cartertemm/soundobj

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

File details

Details for the file soundobj-0.3.0-cp314-cp314-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for soundobj-0.3.0-cp314-cp314-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 3b5311ffd9929cd482b16cbba39b0355188f8dd69e9d9ad868d94a2b4d194864
MD5 2e1b922e3cc9c267f50a980928718f10
BLAKE2b-256 e98a34796a526fc4194e106245b2d7c3d60a76460d4ac8ede0f9b33e55023d97

See more details on using hashes here.

Provenance

The following attestation bundles were made for soundobj-0.3.0-cp314-cp314-macosx_11_0_arm64.whl:

Publisher: build.yml on cartertemm/soundobj

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

File details

Details for the file soundobj-0.3.0-cp313-cp313-win_amd64.whl.

File metadata

  • Download URL: soundobj-0.3.0-cp313-cp313-win_amd64.whl
  • Upload date:
  • Size: 802.4 kB
  • Tags: CPython 3.13, Windows x86-64
  • Uploaded using Trusted Publishing? Yes
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for soundobj-0.3.0-cp313-cp313-win_amd64.whl
Algorithm Hash digest
SHA256 018d048a8fafd902fea2e15f9e20a9d11d664fe2e9a0c5999d2618c6de126968
MD5 969bf55dd34f06e2585225e2c65d5e52
BLAKE2b-256 4427dcedf6f84ef650ebf29811b2e567ea4003871eaaded3e0ba4802d88b72da

See more details on using hashes here.

Provenance

The following attestation bundles were made for soundobj-0.3.0-cp313-cp313-win_amd64.whl:

Publisher: build.yml on cartertemm/soundobj

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

File details

Details for the file soundobj-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl.

File metadata

File hashes

Hashes for soundobj-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
Algorithm Hash digest
SHA256 8490a531ae61cac87e8c9fa054ccc2ff65c0c75cbc4d460812ed4e0c27ebf82c
MD5 7b725d5dcfef845e1c9e1bfce00d379a
BLAKE2b-256 d4805d4f0efcceacbc42c1c016401a4d3adef4c6495b575a160f14fb398ec757

See more details on using hashes here.

Provenance

The following attestation bundles were made for soundobj-0.3.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl:

Publisher: build.yml on cartertemm/soundobj

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

File details

Details for the file soundobj-0.3.0-cp313-cp313-macosx_11_0_arm64.whl.

File metadata

File hashes

Hashes for soundobj-0.3.0-cp313-cp313-macosx_11_0_arm64.whl
Algorithm Hash digest
SHA256 6b4ea8d380b3bfc99dbbd883bb792a6b96471f12ae1f0eec2be35c9f6c6538ee
MD5 1c03f8eb77e5a1c64f5107ea6b332bef
BLAKE2b-256 06304c308db3555ba1baaa789872e5cb3104e0f3355072f5a1203685759596e8

See more details on using hashes here.

Provenance

The following attestation bundles were made for soundobj-0.3.0-cp313-cp313-macosx_11_0_arm64.whl:

Publisher: build.yml on cartertemm/soundobj

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