or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

configuration.mdconvenience-functions.mddevice-management.mdindex.mdstream-processing.mdutilities.md

stream-processing.mddocs/

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)