"""PCM helpers for Bonvoice media (from test_bonvoice/audio_utils.py).""" import audioop import wave from pathlib import Path TARGET_RATE = 8000 CHUNK_SIZE = 320 def wav_to_pcm8000_mono(path: str | Path) -> bytes: path = Path(path) with wave.open(str(path), "rb") as wf: channels = wf.getnchannels() sample_width = wf.getsampwidth() frame_rate = wf.getframerate() pcm = wf.readframes(wf.getnframes()) if sample_width != 2: raise ValueError(f"Expected 16-bit audio, got {sample_width * 8}-bit") if channels == 2: pcm = audioop.tomono(pcm, 2, 0.5, 0.5) elif channels != 1: raise ValueError(f"Unsupported channel count: {channels}") if frame_rate != TARGET_RATE: pcm, _ = audioop.ratecv(pcm, 2, 1, frame_rate, TARGET_RATE, None) return pcm def chunk_pcm(pcm: bytes, chunk_size: int = CHUNK_SIZE) -> list[bytes]: chunks: list[bytes] = [] for i in range(0, len(pcm), chunk_size): chunk = pcm[i : i + chunk_size] if len(chunk) < chunk_size: chunk = chunk + b"\x00" * (chunk_size - len(chunk)) chunks.append(chunk) return chunks