We mute the mic while Companion is talking. On purpose.
Why CareOS uses a half-duplex gate instead of software AEC on Companion — and why turn-based feels right at the bedside.
Companion has a speaker and a microphone an inch apart in the same enclosure. When the speaker plays a TTS line, the mic hears it loud and clear. If we sent that audio back to CareOS as if it were the resident, the model would end up arguing with itself.
The textbook fix is acoustic echo cancellation — model the speaker-to-mic path with an adaptive filter and subtract it from the captured signal. It works beautifully on a laptop. On a small MCU with a few hundred KB of RAM and no dedicated DSP, it does not.
Why AEC is hard on this hardware
Two things make software AEC unforgiving. First, the adaptive filter — usually NLMS or a frequency-domain variant — needs hundreds of taps to model a real room's reverb, and it has to converge fast enough that the first syllable of a response is already clean. Second, double-talk detection: when the resident speaks over Companion, the filter must freeze adaptation, or it learns the resident's voice as echo and starts cancelling them. Getting double-talk wrong is worse than no AEC at all.
Half-duplex, with a small post-roll
So we do the honest thing. A gate driven by the TTS playback state mutes mic capture while Companion is speaking, plus a short post-roll — long enough for the speaker membrane and room tail to decay before we open the mic again. The cost is real: you cannot interrupt Companion mid-sentence the way you can interrupt a person. The benefit is that nothing the resident hears is ever an echo of Companion, and nothing CareOS receives is ever Companion talking to itself.
For a bedside companion this tradeoff lands well. It is not a phone call. The cadence is naturally turn-based — a question, a pause, an answer — and the gate makes that cadence feel deliberate instead of glitchy. When Companion finishes speaking, the mic opens, and the next thing it hears is the resident.