Flip decision 12: the tablet owns aux, not the Orin

The earlier decision assumed the Orin would be the media source. It is not —
the tablet is the music player and that role is staying put, so it holds the
aux cable regardless. Giving the Orin its own aux line would have added a
second permanent cable rather than freeing the display unit.

TTS therefore crosses the boundary as discrete utterances over the reliable
channel rather than a real-time stream, and ducking moves to Android audio
focus, which handles cross-application ducking natively.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013kj58Jugkic783b8ZrtTVZ
This commit is contained in:
2026-09-04 13:57:40 +09:00
parent fa49976efd
commit 1d24d90c36
2 changed files with 45 additions and 17 deletions
+1 -1
View File
@@ -279,7 +279,7 @@ rewriting the document.
| 9 | Nav guidance published on the bus; route requests over HTTP via `telemetry-gw` | **Proposed** | 2026-09-03 |
| 10 | Map artifacts delivered by `rsync` over LAN only; Valhalla tiles kept as a directory, not a tar | Accepted | 2026-09-03 |
| 11 | Boot ordering is capture-first: acquisition reaches ready before serving or voice | Accepted | 2026-09-03 |
| 12 | The Orin owns the car's aux input; the display unit carries no permanent cable | Accepted | 2026-09-03 |
| 12 | The **tablet** owns the car's aux input; TTS crosses as discrete utterances, not a stream | Accepted | 2026-09-04 |
| 13 | Reasoning stays in the cloud — a local LLM does not fit beside the voice stack | Accepted | 2026-09-03 |
| 14 | Recordings are bounded with rotation | Accepted | 2026-09-04 |
| 15 | Boundary is two simplex channels — lossy stream down, acknowledged request/response up | Accepted | 2026-09-03 |
+44 -16
View File
@@ -122,26 +122,54 @@ have run. Two properties matter more than the specific size:
## Audio
The Orin owns the car's single aux input, via a USB DAC.
The **tablet** owns the car's single aux input. It is the music player, and that
role is not moving to the Orin.
```
GPT-SoVITS (TTS) ──┐
├──▶ PipeWire mixer ──▶ USB DAC ──▶ aux in
A2DP sink ─────────┘ │
(media from the tablet) └── ducking: media drops under TTS
tablet: media (Spotify etc.) ──┐
├──▶ Android mixer ──▶ aux in
Orin: GPT-SoVITS (TTS) ──────┘
└── utterances sent over the reliable boundary channel
mic ──▶ Whisper (ASR)
Orin: mic ──▶ Whisper (ASR) stays local, never crosses
```
Three reasons the aux cable belongs here rather than on the tablet:
The tablet is the media source, so it holds the aux cable whatever is decided
about speech. Giving the Orin its own aux line would not free the display unit —
it would add a second permanent cable to the car and leave the first one in place.
- **The aux cable should belong to the fixed unit.** The display is meant to be
removable; anything holding a permanent cable to the car is not removable.
- **Ducking becomes a local policy** on one box instead of coordination between
two. Without it the assistant talks over the music.
- **The direction works.** Linux is a capable A2DP *sink*, so the tablet can send
media here. The reverse — this box as an A2DP source into an Android sink — is
not viable, since stock Android builds generally do not enable A2DP sink.
### TTS crosses as utterances, not as a stream
Unplug the tablet and the car keeps audio and voice. The Orin depends on the
display unit for nothing.
An utterance is short, finite, and fully synthesised before it is needed. So it
ships as a **discrete object over the reliable channel**, not as a real-time audio
stream: no jitter buffer, no underrun handling, no clock synchronisation, and a
dropped packet is a retry rather than an audible gap.
The cost is that speech begins only once synthesis *and* transfer complete. For a
car assistant that is fine — nothing here is lip-synced. If streaming TTS is ever
wanted, so that speech starts before synthesis finishes, this is the decision to
revisit.
### Ducking is the tablet's job
Android's `AUDIOFOCUS_GAIN_TRANSIENT_MAY_DUCK` ducks other applications' audio —
Spotify included — for the duration of a request, then restores it. This is the
mechanism every navigation app already uses, and it is less work than the PipeWire
policy it replaces. Cross-application ducking is a solved problem on the tablet
and would have been a bespoke one on the Orin.
### The microphone stays on the Orin
Whisper runs on the Orin, so its input does too. Audio *in* on one box and audio
*out* on the other is asymmetric on purpose: each side does the simple thing, and
a microphone has no reason to reach the head unit.
### Degrade when there is no sink
With no tablet connected the Orin can still hear — the mic is local — but cannot
speak. The voice stack expires or drops pending utterances rather than queueing
them unboundedly or blocking on a sink that may never arrive.
The consequence to accept: **unplug the tablet and the car has no voice.** That is
tolerable because unplugging it also removes the music, so the tablet was already
load-bearing for audio. Speech does not make it more so.