Files
Assistant/client/audio.py
T

27 lines
1.0 KiB
Python

"""Audio helpers for the Pi client.
This module is split into two layers:
* Deterministic helpers (no hardware) — `resample_24k_to_16k`. Tested.
* `AudioStreams` — owns the persistent PortAudio InputStream / OutputStream.
Filled in by Task 7. Smoke-tested by `main.py` running on the Pi.
"""
import numpy as np
from scipy.signal import resample_poly
def resample_24k_to_16k(frame: np.ndarray) -> np.ndarray:
"""Downsample a 24 kHz int16 mono frame to 16 kHz int16 mono (2:3 poly).
Input length is preserved as `len(frame) * 2 // 3`. For the 1920-sample
frames produced by our 80 ms blocksize at 24 kHz, this yields 1280 samples
(80 ms at 16 kHz), which is exactly what openwakeword expects.
"""
if frame.dtype != np.int16:
raise TypeError(f"expected int16, got {frame.dtype}")
if frame.size == 0:
raise ValueError("empty input")
floats = frame.astype(np.float32)
resampled = resample_poly(floats, up=2, down=3)
return np.clip(resampled, -32768, 32767).astype(np.int16)