68 lines
2.2 KiB
Python
68 lines
2.2 KiB
Python
"""
|
|
builtin_mic.py — backward-compat shim.
|
|
|
|
The G1 on-board microphone implementation now lives in
|
|
[Voice/audio_io.py](Voice/audio_io.py) where it can be paired with the
|
|
matching BuiltinSpeaker via `AudioIO.from_profile("builtin", ...)` —
|
|
the same structure Sanad uses.
|
|
|
|
This module exists so existing imports (`from Voice.builtin_mic import
|
|
BuiltinMic`) keep working for the non-Gemini voice paths and for
|
|
`API/audio_api.py`. It subclasses the canonical `BuiltinMic` and adds
|
|
`read_seconds()`, which is used by `API/audio_api.record()`.
|
|
|
|
Do not add new code here — extend Voice/audio_io.py instead.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import sys
|
|
import time
|
|
|
|
# When run directly (`python3 Voice/builtin_mic.py`) the parent
|
|
# directory isn't on sys.path, so the `Voice.audio_io` import below
|
|
# would fail. Add it before the import resolves.
|
|
_PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|
if _PROJECT_DIR not in sys.path:
|
|
sys.path.insert(0, _PROJECT_DIR)
|
|
|
|
from Voice.audio_io import BuiltinMic as _BaseBuiltinMic
|
|
|
|
|
|
class BuiltinMic(_BaseBuiltinMic):
|
|
"""G1 on-board mic + `read_seconds()` convenience."""
|
|
|
|
def read_seconds(self, seconds: float) -> bytes:
|
|
"""Capture `seconds` of audio and return as bytes."""
|
|
num_bytes = int(seconds * self.sample_rate * 2)
|
|
out = bytearray()
|
|
chunk_bytes = 1024
|
|
while len(out) < num_bytes:
|
|
out.extend(self.read_chunk(min(chunk_bytes, num_bytes - len(out))))
|
|
return bytes(out)
|
|
|
|
|
|
# Standalone test — capture 3 s and print energy stats
|
|
if __name__ == "__main__":
|
|
import array
|
|
|
|
print("BuiltinMic standalone test — capturing 3 s from G1...")
|
|
mic = BuiltinMic()
|
|
mic.start()
|
|
time.sleep(0.3)
|
|
raw = mic.read_seconds(3.0)
|
|
mic.stop()
|
|
|
|
samples = array.array("h", raw)
|
|
if not samples:
|
|
print(" FAIL — got zero samples")
|
|
else:
|
|
mn = min(samples); mx = max(samples)
|
|
mean_abs = sum(abs(s) for s in samples) / len(samples)
|
|
print(f" samples={len(samples)} min={mn} max={mx} mean|s|={mean_abs:.0f}")
|
|
if mean_abs > 30:
|
|
print(" OK — mic is capturing audio")
|
|
else:
|
|
print(" WARN — signal very low")
|