0
# Stream Processing
1
2
Low-level stream classes for advanced audio processing with full control over buffering, callbacks, and real-time operation. These classes provide the foundation for building sophisticated audio applications with precise timing and custom processing workflows.
3
4
## Capabilities
5
6
### NumPy-based Streams
7
8
High-performance audio streams that work directly with NumPy arrays, providing efficient memory management and integration with scientific computing workflows.
9
10
```python { .api }
11
class Stream:
12
"""
13
Bidirectional audio stream for simultaneous input and output.
14
15
Parameters:
16
- samplerate (float, optional): Sample rate in Hz
17
- blocksize (int, optional): Block size for audio processing
18
- device (int or str or tuple, optional): Input/output device specification
19
- channels (int or tuple, optional): Number of channels
20
- dtype (str or numpy.dtype, optional): Data type for audio samples
21
- latency (float or str, optional): Desired latency in seconds or 'low'/'high'
22
- extra_settings (object, optional): Platform-specific settings
23
- callback (function, optional): User callback function for real-time processing
24
- finished_callback (function, optional): Callback when stream finishes
25
- clip_off (bool, optional): Disable clipping of out-of-range samples
26
- dither_off (bool, optional): Disable dithering
27
- never_drop_input (bool, optional): Never drop input samples
28
- prime_output_buffers_using_stream_callback (bool, optional): Prime buffers with callback
29
"""
30
31
def start(self): ...
32
def stop(self, ignore_errors=True): ...
33
def abort(self, ignore_errors=True): ...
34
def close(self, ignore_errors=True): ...
35
def read(self, frames): ...
36
def write(self, data): ...
37
38
@property
39
def read_available(self): ...
40
@property
41
def write_available(self): ...
42
@property
43
def active(self): ...
44
@property
45
def stopped(self): ...
46
@property
47
def closed(self): ...
48
@property
49
def samplerate(self): ...
50
@property
51
def blocksize(self): ...
52
@property
53
def device(self): ...
54
@property
55
def channels(self): ...
56
@property
57
def dtype(self): ...
58
@property
59
def samplesize(self): ...
60
@property
61
def latency(self): ...
62
@property
63
def time(self): ...
64
@property
65
def cpu_load(self): ...
66
67
class InputStream:
68
"""
69
Input-only audio stream with NumPy arrays.
70
71
Parameters: Same as Stream class
72
"""
73
74
def start(self): ...
75
def stop(self, ignore_errors=True): ...
76
def abort(self, ignore_errors=True): ...
77
def close(self, ignore_errors=True): ...
78
def read(self, frames): ...
79
80
@property
81
def read_available(self): ...
82
@property
83
def active(self): ...
84
@property
85
def stopped(self): ...
86
@property
87
def closed(self): ...
88
@property
89
def samplerate(self): ...
90
@property
91
def blocksize(self): ...
92
@property
93
def device(self): ...
94
@property
95
def channels(self): ...
96
@property
97
def dtype(self): ...
98
@property
99
def samplesize(self): ...
100
@property
101
def latency(self): ...
102
@property
103
def time(self): ...
104
@property
105
def cpu_load(self): ...
106
107
class OutputStream:
108
"""
109
Output-only audio stream with NumPy arrays.
110
111
Parameters: Same as Stream class
112
"""
113
114
def start(self): ...
115
def stop(self, ignore_errors=True): ...
116
def abort(self, ignore_errors=True): ...
117
def close(self, ignore_errors=True): ...
118
def write(self, data): ...
119
120
@property
121
def write_available(self): ...
122
@property
123
def active(self): ...
124
@property
125
def stopped(self): ...
126
@property
127
def closed(self): ...
128
@property
129
def samplerate(self): ...
130
@property
131
def blocksize(self): ...
132
@property
133
def device(self): ...
134
@property
135
def channels(self): ...
136
@property
137
def dtype(self): ...
138
@property
139
def samplesize(self): ...
140
@property
141
def latency(self): ...
142
@property
143
def time(self): ...
144
@property
145
def cpu_load(self): ...
146
```
147
148
### Raw Buffer Streams
149
150
Buffer-based audio streams that work with Python buffer objects when NumPy is not available or when direct memory control is needed.
151
152
```python { .api }
153
class RawStream:
154
"""
155
Bidirectional raw audio stream using Python buffer objects.
156
157
Parameters: Same as Stream class
158
"""
159
160
def start(self): ...
161
def stop(self, ignore_errors=True): ...
162
def abort(self, ignore_errors=True): ...
163
def close(self, ignore_errors=True): ...
164
def read(self, frames): ...
165
def write(self, data): ...
166
167
@property
168
def read_available(self): ...
169
@property
170
def write_available(self): ...
171
@property
172
def active(self): ...
173
@property
174
def stopped(self): ...
175
@property
176
def closed(self): ...
177
@property
178
def samplerate(self): ...
179
@property
180
def blocksize(self): ...
181
@property
182
def device(self): ...
183
@property
184
def channels(self): ...
185
@property
186
def dtype(self): ...
187
@property
188
def samplesize(self): ...
189
@property
190
def latency(self): ...
191
@property
192
def time(self): ...
193
@property
194
def cpu_load(self): ...
195
196
class RawInputStream:
197
"""
198
Input-only raw audio stream using Python buffer objects.
199
200
Parameters: Same as Stream class
201
"""
202
203
def start(self): ...
204
def stop(self): ...
205
def close(self): ...
206
def read(self, frames): ...
207
def read_available(self): ...
208
209
@property
210
def active(self): ...
211
@property
212
def stopped(self): ...
213
@property
214
def closed(self): ...
215
@property
216
def samplerate(self): ...
217
@property
218
def blocksize(self): ...
219
@property
220
def latency(self): ...
221
@property
222
def cpu_load(self): ...
223
224
class RawOutputStream:
225
"""
226
Output-only raw audio stream using Python buffer objects.
227
228
Parameters: Same as Stream class
229
"""
230
231
def start(self): ...
232
def stop(self): ...
233
def close(self): ...
234
def write(self, data): ...
235
def write_available(self): ...
236
237
@property
238
def active(self): ...
239
@property
240
def stopped(self): ...
241
@property
242
def closed(self): ...
243
@property
244
def samplerate(self): ...
245
@property
246
def blocksize(self): ...
247
@property
248
def latency(self): ...
249
@property
250
def cpu_load(self): ...
251
```
252
253
## Usage Examples
254
255
### Basic Stream Recording
256
257
```python
258
import sounddevice as sd
259
import numpy as np
260
261
# Create and configure input stream
262
with sd.InputStream(samplerate=44100, channels=2, blocksize=1024) as stream:
263
print("Recording... Press Ctrl+C to stop")
264
try:
265
while True:
266
# Read audio data
267
data, overflowed = stream.read(1024)
268
if overflowed:
269
print("Input overflow detected!")
270
271
# Process audio data here
272
# For example, calculate RMS level
273
rms = np.sqrt(np.mean(data**2))
274
print(f"RMS level: {rms:.4f}")
275
276
except KeyboardInterrupt:
277
print("Recording stopped")
278
```
279
280
### Real-time Audio Processing with Callbacks
281
282
```python
283
import sounddevice as sd
284
import numpy as np
285
286
# Global variable to store processed audio
287
processed_audio = []
288
289
def audio_callback(indata, outdata, frames, time, status):
290
"""Real-time audio processing callback."""
291
if status:
292
print(f"Stream status: {status}")
293
294
# Apply simple gain and highpass filter
295
gain = 0.5
296
processed = indata * gain
297
298
# Simple high-pass filter (remove DC offset)
299
if hasattr(audio_callback, 'prev_sample'):
300
processed = processed - audio_callback.prev_sample * 0.95
301
audio_callback.prev_sample = processed[-1] if len(processed) > 0 else 0
302
303
# Copy processed audio to output
304
outdata[:] = processed
305
processed_audio.append(processed.copy())
306
307
# Create bidirectional stream with callback
308
with sd.Stream(callback=audio_callback, channels=2, samplerate=44100):
309
print("Real-time processing active. Press Enter to stop.")
310
input()
311
312
print(f"Processed {len(processed_audio)} blocks of audio")
313
```
314
315
### Custom Stream Configuration
316
317
```python
318
import sounddevice as sd
319
import numpy as np
320
321
# Configure stream for specific device and low latency
322
device_info = sd.query_devices()
323
print("Available devices:")
324
for i, device in enumerate(device_info):
325
print(f" {i}: {device['name']}")
326
327
# Select specific input and output devices
328
input_device = 1 # Replace with desired input device index
329
output_device = 2 # Replace with desired output device index
330
331
# Create stream with custom configuration
332
stream = sd.Stream(
333
device=(input_device, output_device),
334
samplerate=48000,
335
channels=(1, 2), # 1 input channel, 2 output channels
336
dtype=np.float32,
337
latency='low',
338
blocksize=512
339
)
340
341
with stream:
342
print(f"Stream info:")
343
print(f" Sample rate: {stream.samplerate}")
344
print(f" Block size: {stream.blocksize}")
345
print(f" Latency: {stream.latency}")
346
print(f" CPU load: {stream.cpu_load}")
347
348
# Record some audio
349
recording = []
350
for _ in range(100): # Record 100 blocks
351
data, overflowed = stream.read(512)
352
recording.append(data)
353
354
# Convert to single array
355
recording = np.concatenate(recording, axis=0)
356
print(f"Recorded {len(recording)} samples")
357
358
# Play back with processing
359
for block in np.array_split(recording, 100):
360
# Duplicate mono input to stereo output
361
stereo_block = np.column_stack([block, block])
362
stream.write(stereo_block)
363
```
364
365
### Using Raw Streams (without NumPy)
366
367
```python
368
import sounddevice as sd
369
import array
370
371
# Create raw input stream for systems without NumPy
372
with sd.RawInputStream(samplerate=44100, channels=1, dtype='int16') as stream:
373
print("Recording raw audio...")
374
375
# Read raw audio data
376
raw_data, overflowed = stream.read(4410) # 0.1 seconds at 44100 Hz
377
378
# Convert to Python array for processing
379
audio_array = array.array('h') # 'h' for signed short (int16)
380
audio_array.frombytes(raw_data)
381
382
print(f"Recorded {len(audio_array)} samples")
383
print(f"Sample values: {audio_array[:10]}...") # First 10 samples
384
```
385
386
### Stream Context Management
387
388
```python
389
import sounddevice as sd
390
import numpy as np
391
392
# Streams automatically start and stop with context manager
393
def process_audio_file(input_file, output_file):
394
# This example assumes you have audio data loaded
395
# In practice, you'd load from a file using scipy.io.wavfile or similar
396
397
with sd.OutputStream(samplerate=44100, channels=2) as output_stream:
398
with sd.InputStream(samplerate=44100, channels=1) as input_stream:
399
400
print("Streams started automatically")
401
402
# Process audio in chunks
403
chunk_size = 1024
404
while True:
405
try:
406
# Read from input
407
input_data, _ = input_stream.read(chunk_size)
408
409
# Process (e.g., convert mono to stereo)
410
stereo_data = np.column_stack([input_data, input_data])
411
412
# Write to output
413
output_stream.write(stereo_data)
414
415
except KeyboardInterrupt:
416
break
417
418
print("Streams stopped automatically")
419
```
420
421
## Callback Function Signature
422
423
Audio callback functions must follow this signature:
424
425
```python { .api }
426
def callback(indata, outdata, frames, time, status):
427
"""
428
Audio processing callback function.
429
430
Parameters:
431
- indata (numpy.ndarray): Input audio data
432
- outdata (numpy.ndarray): Output audio buffer to fill
433
- frames (int): Number of frames in this callback
434
- time (object): Time information for this callback
435
- status (CallbackFlags): Status flags indicating stream conditions
436
437
Returns:
438
None (modify outdata in-place)
439
440
Raises:
441
CallbackStop: To stop the stream
442
CallbackAbort: To abort the stream
443
"""
444
```
445
446
## Stream Properties
447
448
All stream classes provide these properties:
449
450
- `active`: Whether the stream is currently active
451
- `stopped`: Whether the stream has been stopped
452
- `closed`: Whether the stream has been closed
453
- `samplerate`: Actual sample rate of the stream
454
- `blocksize`: Actual block size used by the stream
455
- `latency`: Actual latency of the stream (input, output)
456
- `cpu_load`: Current CPU load of the stream (0.0 to 1.0)