peachy / tests /test_console_audio.py
stephenslee's picture
Publish Peachy v0.1.0 for Reachy Mini Control
8a652b8 verified
Raw History Blame Contribute Delete
2.09 kB
from __future__ import annotations
import asyncio
from types import SimpleNamespace
from unittest.mock import MagicMock
import numpy as np
import pytest
from peachy.console import LocalStream
class _Handler:
def __init__(self, output: tuple[int, np.ndarray]) -> None:
self.output = output
self.output_queue: asyncio.Queue[object] = asyncio.Queue()
self.last_activity_time = 0.0
def set_activity_observer(self, _observer: object) -> None:
pass
async def emit(self) -> tuple[int, np.ndarray]:
return self.output
@pytest.mark.asyncio
@pytest.mark.parametrize(("provider_rate", "source_samples"), [(16_000, 160), (24_000, 240)])
async def test_play_loop_resamples_provider_audio_to_robot_rate(
provider_rate: int,
source_samples: int,
) -> None:
pushed: list[np.ndarray] = []
media = SimpleNamespace(
audio=None,
get_output_audio_samplerate=lambda: 48_000,
push_audio_sample=lambda frame: pushed.append(np.asarray(frame)),
)
stream = LocalStream(
_Handler((provider_rate, np.ones((1, source_samples), dtype=np.int16))),
SimpleNamespace(media=media),
)
media.push_audio_sample = lambda frame: (
pushed.append(np.asarray(frame)),
stream._stop_event.set(),
)
await stream.play_loop()
assert len(pushed) == 1
assert pushed[0].dtype == np.float32
assert pushed[0].shape == (480,)
@pytest.mark.asyncio
async def test_play_loop_uses_the_rate_from_each_tuple() -> None:
media = SimpleNamespace(
audio=None,
get_output_audio_samplerate=MagicMock(return_value=24_000),
push_audio_sample=MagicMock(),
)
stream = LocalStream(
_Handler((48_000, np.ones(480, dtype=np.int16))),
SimpleNamespace(media=media),
)
media.push_audio_sample.side_effect = lambda _frame: stream._stop_event.set()
await stream.play_loop()
pushed = media.push_audio_sample.call_args.args[0]
assert pushed.shape == (240,)
media.get_output_audio_samplerate.assert_called_once_with()