Simple, asynchronous audio playback for Python 3.
npx @tessl/cli install tessl/pypi-simpleaudio@1.0.00
# Simpleaudio
1
2
Simple, asynchronous audio playback for Python 3. Provides cross-platform, dependency-free audio playback capability for Python 3 on macOS, Windows, and Linux through a simple object-oriented API.
3
4
## Package Information
5
6
- **Package Name**: simpleaudio
7
- **Language**: Python
8
- **Installation**: `pip install simpleaudio`
9
- **Platforms**: Linux (ALSA), macOS (CoreAudio), Windows (WinMM)
10
11
## Core Imports
12
13
```python
14
import simpleaudio as sa
15
```
16
17
For function checks and testing:
18
19
```python
20
import simpleaudio.functionchecks as fc
21
```
22
23
## Basic Usage
24
25
```python
26
import simpleaudio as sa
27
28
# Load and play a wave file
29
wave_obj = sa.WaveObject.from_wave_file("path/to/file.wav")
30
play_obj = wave_obj.play()
31
play_obj.wait_done() # Wait until playback finishes
32
33
# Play raw audio buffer
34
audio_data = b'\x00\x01' * 44100 # Sample audio data
35
play_obj = sa.play_buffer(audio_data, 2, 2, 44100)
36
play_obj.wait_done()
37
38
# Stop all audio playback
39
sa.stop_all()
40
```
41
42
## Capabilities
43
44
### Wave Object Creation and Playback
45
46
Load audio from files or create from raw data, then control playback.
47
48
```python { .api }
49
class WaveObject:
50
def __init__(self, audio_data, num_channels=2, bytes_per_sample=2, sample_rate=44100):
51
"""
52
Create a WaveObject from raw audio data.
53
54
Args:
55
audio_data (bytes): Raw audio data buffer
56
num_channels (int): Number of audio channels (1=mono, 2=stereo)
57
bytes_per_sample (int): Bytes per audio sample (1, 2, 3, or 4)
58
sample_rate (int): Sample rate in Hz (must be multiple of 11025)
59
"""
60
61
def play(self):
62
"""
63
Start playback of this wave object.
64
65
Returns:
66
PlayObject: Object for controlling this playback instance
67
"""
68
69
@classmethod
70
def from_wave_file(cls, wave_file):
71
"""
72
Load a wave object from a WAV file.
73
74
Args:
75
wave_file (str): Path to WAV file
76
77
Returns:
78
WaveObject: New wave object loaded from file
79
"""
80
81
@classmethod
82
def from_wave_read(cls, wave_read):
83
"""
84
Create a wave object from an open wave.Wave_read object.
85
86
Args:
87
wave_read: Open wave.Wave_read object from wave.open()
88
89
Returns:
90
WaveObject: New wave object from wave reader
91
"""
92
93
def __str__(self):
94
"""
95
String representation showing audio format details.
96
97
Returns:
98
str: Format description (channels, bit depth, sample rate)
99
"""
100
```
101
102
### Playback Control
103
104
Control individual audio playback instances.
105
106
```python { .api }
107
class PlayObject:
108
def __init__(self, play_id):
109
"""
110
Internal constructor for playback control object.
111
112
Args:
113
play_id (int): Internal ID for tracking this playback
114
"""
115
116
def stop(self):
117
"""
118
Stop this specific audio playback.
119
"""
120
121
def wait_done(self):
122
"""
123
Block until this audio playback completes.
124
Polls playback status every 50ms.
125
"""
126
127
def is_playing(self):
128
"""
129
Check if this audio is currently playing.
130
131
Returns:
132
bool: True if still playing, False if stopped or finished
133
"""
134
```
135
136
### Direct Buffer Playback
137
138
Play audio directly from raw buffer data without creating a WaveObject.
139
140
```python { .api }
141
def play_buffer(audio_data, num_channels, bytes_per_sample, sample_rate):
142
"""
143
Play audio from raw buffer data.
144
145
Args:
146
audio_data (bytes): Raw audio data buffer
147
num_channels (int): Number of channels (1 or 2)
148
bytes_per_sample (int): Bytes per sample (1, 2, 3, or 4)
149
sample_rate (int): Sample rate in Hz (must be multiple of 11025)
150
151
Returns:
152
PlayObject: Object for controlling this playback
153
154
Raises:
155
ValueError: Invalid parameters (channels not 1-2, invalid bytes_per_sample,
156
or sample_rate not multiple of 11025)
157
"""
158
```
159
160
### Global Playback Control
161
162
Stop all audio playback at once.
163
164
```python { .api }
165
def stop_all():
166
"""
167
Stop all currently playing audio streams.
168
"""
169
```
170
171
### Function Checks and Testing
172
173
Built-in audio functionality tests for verifying installation and hardware.
174
175
```python { .api }
176
class FunctionCheckBase:
177
@classmethod
178
def run(cls, countdown=3):
179
"""
180
Run this function check with optional countdown.
181
182
Args:
183
countdown (int): Seconds to wait before starting (default: 3)
184
"""
185
186
class LeftRightCheck(FunctionCheckBase):
187
"""Tests stereo playback by playing left channel then right channel."""
188
189
class OverlappingCheck(FunctionCheckBase):
190
"""Tests overlapping playback with three notes spaced half-second apart."""
191
192
class StopCheck(FunctionCheckBase):
193
"""Tests stopping individual playback streams."""
194
195
class StopAllCheck(FunctionCheckBase):
196
"""Tests stopping all playback streams at once."""
197
198
class IsPlayingCheck(FunctionCheckBase):
199
"""Tests the is_playing() method functionality."""
200
201
class WaitDoneCheck(FunctionCheckBase):
202
"""Tests the wait_done() method functionality."""
203
204
def run_all(countdown=0):
205
"""
206
Run all function checks in sequence.
207
208
Args:
209
countdown (int): Seconds to wait before each check (default: 0)
210
"""
211
```
212
213
## Usage Examples
214
215
### Basic Wave File Playback
216
217
```python
218
import simpleaudio as sa
219
220
# Load and play a wave file
221
wave_obj = sa.WaveObject.from_wave_file("audio.wav")
222
play_obj = wave_obj.play()
223
224
# Wait for playback to finish
225
play_obj.wait_done()
226
```
227
228
### Overlapping Audio Streams
229
230
```python
231
import simpleaudio as sa
232
from time import sleep
233
234
# Load multiple audio files
235
wave1 = sa.WaveObject.from_wave_file("note1.wav")
236
wave2 = sa.WaveObject.from_wave_file("note2.wav")
237
wave3 = sa.WaveObject.from_wave_file("note3.wav")
238
239
# Play them with overlapping timing
240
play1 = wave1.play()
241
sleep(0.5)
242
play2 = wave2.play()
243
sleep(0.5)
244
play3 = wave3.play()
245
246
# Wait for all to finish
247
play1.wait_done()
248
play2.wait_done()
249
play3.wait_done()
250
```
251
252
### Raw Buffer Playback
253
254
```python
255
import simpleaudio as sa
256
import numpy as np
257
258
# Generate a sine wave
259
sample_rate = 44100
260
duration = 2.0
261
frequency = 440
262
263
t = np.linspace(0, duration, int(sample_rate * duration), False)
264
sine_wave = np.sin(2 * np.pi * frequency * t)
265
266
# Convert to 16-bit integers
267
audio_data = (sine_wave * 32767).astype(np.int16).tobytes()
268
269
# Play the generated audio
270
play_obj = sa.play_buffer(audio_data, 1, 2, sample_rate)
271
play_obj.wait_done()
272
```
273
274
### Function Testing
275
276
```python
277
import simpleaudio.functionchecks as fc
278
279
# Run a specific test
280
fc.LeftRightCheck.run()
281
282
# Run all tests
283
fc.run_all(countdown=3)
284
```
285
286
## Error Handling
287
288
The package raises `ValueError` exceptions for invalid parameters:
289
290
- **Channels**: Must be 1 (mono) or 2 (stereo)
291
- **Bytes per sample**: Must be 1, 2, 3, or 4
292
- **Sample rate**: Must be a multiple of 11025 Hz (e.g., 11025, 22050, 44100, 88200)
293
294
```python
295
import simpleaudio as sa
296
297
try:
298
# This will raise ValueError - invalid sample rate
299
sa.play_buffer(b'\x00' * 1000, 2, 2, 44101)
300
except ValueError as e:
301
print(f"Invalid parameters: {e}")
302
```
303
304
## Platform-Specific Details
305
306
- **Linux**: Uses ALSA (Advanced Linux Sound Architecture)
307
- **macOS**: Uses CoreAudio framework with minimum macOS 10.6 support
308
- **Windows**: Uses Windows Multimedia API (WinMM)
309
310
The package automatically detects the platform and uses the appropriate audio backend. No platform-specific code is required from the user.