Skip to content

Commit 4c4e050

Browse files
committed
console: drop head_wobbler.feed_pcm path and its playback-delay helper
LocalStream's audio path no longer needs to feed a local wobbler with a playback-delay-aware start offset; the daemon's wobbler analyses the same audio that we hand off via push_audio_sample. Remove the "if head_wobbler is not None" block and the now-unused _estimate_pending_playback_seconds helper that only existed to compute that start_delay_s. Drops the matching test test_play_loop_feeds_head_wobbler_with_local_playback_delay in tests/test_console.py.
1 parent c0b2cbf commit 4c4e050

2 files changed

Lines changed: 0 additions & 75 deletions

File tree

src/reachy_mini_conversation_app/console.py

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -65,26 +65,6 @@
6565
)
6666

6767

68-
def _estimate_pending_playback_seconds(robot: ReachyMini) -> float:
69-
"""Best-effort estimate of audio still queued in the local player."""
70-
media = getattr(robot, "media", None)
71-
audio = getattr(media, "audio", None)
72-
if audio is None:
73-
return 0.0
74-
75-
next_pts_ns = getattr(audio, "_playback_next_pts_ns", None)
76-
get_running_time_ns = getattr(audio, "_get_playback_running_time_ns", None)
77-
if next_pts_ns is None or not callable(get_running_time_ns):
78-
return 0.0
79-
80-
try:
81-
pending_ns = int(next_pts_ns) - int(get_running_time_ns())
82-
except Exception:
83-
return 0.0
84-
85-
return max(0.0, pending_ns / 1e9)
86-
87-
8868
class LocalStream:
8969
"""LocalStream using Reachy Mini's recorder/player."""
9070

@@ -622,11 +602,6 @@ async def play_loop(self) -> None:
622602
num_samples,
623603
)
624604

625-
head_wobbler = self.handler.deps.head_wobbler
626-
if head_wobbler is not None:
627-
playback_delay_s = _estimate_pending_playback_seconds(self._robot)
628-
head_wobbler.feed_pcm(audio_data.reshape(1, -1), input_sample_rate, start_delay_s=playback_delay_s)
629-
630605
self._robot.media.push_audio_sample(audio_frame)
631606

632607
else:

tests/test_console.py

Lines changed: 0 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -70,56 +70,6 @@ def test_clear_audio_queue_falls_back_when_backend_is_unknown() -> None:
7070
assert handler.output_queue.empty()
7171

7272

73-
@pytest.mark.asyncio
74-
async def test_play_loop_feeds_head_wobbler_with_local_playback_delay() -> None:
75-
"""Local playback should drive speech wobble using the queued player delay."""
76-
head_wobbler = MagicMock()
77-
chunk = np.array([1, -2, 3, -4], dtype=np.int16)
78-
79-
class Handler:
80-
def __init__(self) -> None:
81-
self.deps = SimpleNamespace(head_wobbler=head_wobbler)
82-
self.output_queue = asyncio.Queue()
83-
self._emitted = False
84-
85-
async def emit(self):
86-
if not self._emitted:
87-
self._emitted = True
88-
return (24000, chunk.copy())
89-
return None
90-
91-
audio = SimpleNamespace(
92-
_playback_next_pts_ns=1_500_000_000,
93-
_get_playback_running_time_ns=lambda: 500_000_000,
94-
)
95-
media = SimpleNamespace(
96-
audio=audio,
97-
backend=MediaBackend.LOCAL,
98-
get_output_audio_samplerate=lambda: 24000,
99-
push_audio_sample=MagicMock(),
100-
)
101-
robot = SimpleNamespace(media=media)
102-
handler = Handler()
103-
stream = LocalStream(handler, robot)
104-
105-
async def stop_soon() -> None:
106-
await asyncio.sleep(0.01)
107-
stream._stop_event.set()
108-
109-
stopper = asyncio.create_task(stop_soon())
110-
try:
111-
await asyncio.wait_for(stream.play_loop(), timeout=1.0)
112-
finally:
113-
await stopper
114-
115-
head_wobbler.feed_pcm.assert_called_once()
116-
args, kwargs = head_wobbler.feed_pcm.call_args
117-
assert np.array_equal(args[0], chunk.reshape(1, -1))
118-
assert args[1] == 24000
119-
assert kwargs["start_delay_s"] == pytest.approx(1.0)
120-
media.push_audio_sample.assert_called_once()
121-
122-
12373
def test_backend_config_persists_gemini_selection_and_status(
12474
tmp_path,
12575
monkeypatch,

0 commit comments

Comments
 (0)