# 02 — Audio-Topologie (PipeWire)
Herzstück: virtueller Misch-Bus **`callmix`** (Null-Sink). Alles, was aufgenommen werden soll, wird per
Loopback dorthin geroutet; der Monitor von `callmix` wird als echte Quelle **`callrec_mix`** („CallRecMix“)
re-mappt — die wählt die Web-GUI als Aufnahmequelle.
## Gesamtgraph
```mermaid
flowchart LR
PCIN["PC-Audio (Capture des UAC2-Gadgets)
alsa_input.platform-fc000000.usb"]
MIC["Headset-Mikrofon H390
alsa_input.usb-Logi...mono-fallback"]
HS["Headset-Hörer H390
alsa_output.usb-Logi...analog-stereo"]
GADGET["Gadget-Sink (Board→PC)
alsa_output.platform-fc000000.usb"]
GATE["micgate
LADSPA Noise-Gate
(swh gate_1410, Thr −45 dB)"]
MIX[("callmix
Null-Sink")]
CRMIX["callrec_mix ('CallRecMix')
remap von callmix.monitor"]
APP["Aime-App
Aufnahme"]
PCIN -- "cr_pc2hs (100%)" --> HS
PCIN -- "cr_pc2mix (60% ≈ −13 dB)" --> MIX
MIC -- "cr_mic2pc (65%)" --> GATE
GATE --> GADGET
GATE -- "pw-link (gegatet, 2026-07-17)" --> MIX
MIX -.->|"monitor"| CRMIX --> APP
```
Drei Loopbacks (per `media.name`-Tag identifizierbar) + ein statischer `pw-link`; Gains setzt
`si_vol()` im Setup-Skript `/opt/callrec/aime-usb-audio-setup.sh`:
| Route | Weg | Gain | Zweck |
|---|---|---|---|
| `cr_pc2hs` | PC → Headset | 100 % | Nutzer hört PC/Teams |
| `cr_pc2mix` | PC → callmix | **60 % (≈ −13 dB)** | Gegenseite in die Aufnahme (clip-sicher) |
| `cr_mic2pc` | Mikro → micgate → Gadget | 65 % | Gegenseite hört den Nutzer (gegatet) |
| `pw-link micgate.out → callmix` | GEGATETES Mikro → callmix | unity | Eigene Stimme in die Aufnahme |
| ~~`cr_mic2mix`~~ | ~~Mikro → callmix direkt~~ | — | **ENTFERNT 2026-07-17** (nur noch Fallback ohne Gate): der offene Mikro-Pfad legte die Gegenseite ZWEIMAL in den Mix — digital + ~80 ms später als Muschel-Bleed (Cepstral-Peak 79–80 ms, #71) → Hall auf der Gegenseite + Diarization verschmolz zwei entfernte Sprecher |
## Warum Noise-Gate (micgate)?
Teams-Gegenseite hörte sich selbst verzögert (Selbst-Echo). Nachgewiesen: **akustisches Übersprechen ins
Mikrofon** (nicht elektrisch, nicht Ohrmuschel — Mute-Tests), und Teams-AGC renormalisiert jede Pegelabsenkung.
Lösung: LADSPA-Gate im Mikro→PC-Pfad schließt in Sprechpausen → Gegenseite bekommt Stille → kein Echo.
AEC wurde getestet und **verworfen** (Knistern, kein Nutzen).
```mermaid
flowchart LR
M["Mikrofon
HW-Gain fest Stufe 12 (+1,4 dB)"] --> G{"Pegel > −45 dB?"}
G -- "ja (Sprache)" --> OPEN["Gate offen → Signal zum PC"]
G -- "nein (Pause)" --> CLOSED["Gate zu → Stille zum PC
= kein Selbst-Echo"]
```
**Gotchas (teuer bezahlt):**
- Filter-Chain ist ein **Core-Modul**, kein Pulse-Modul → nicht per `pactl load-module`, sondern Drop-in
`filter-chain.conf.d/micgate.conf` + eigener Dienst `aime-micgate.service`.
- PipeWire liefert einen eigenen preset-aktivierten `filter-chain.service` mit → **doppeltes** micgate →
`systemctl --user mask filter-chain.service`.
- Mikro-HW-Gain **nur** über `pactl set-source-volume $HSMIC 62%` setzen (= HW-Stufe 12). `amixer` direkt
wird von WirePlumber überschrieben; 100 % = +11 dB → Grundrauschen öffnet das Gate wieder.
- 2-Mono-Node-Stereo-Graph im Filter-Chain = kein Audio → 1 Mono-Node verwenden.
- `pkill -f "pipewire -c filter-chain.conf"` killt die eigene SSH-Session (exit 128) → `setsid` nutzen.
## Merksätze
- **PC-Audio = die Quelle `alsa_input.platform-fc000000.usb...`**, NICHT deren `.monitor` (der ist stumm —
hat einmal eine Stunde gekostet). Quellen vor Verwendung mit `parecord` + `ffmpeg astats` auf Signal prüfen.
- Die GUI filtert alle `*.monitor`-Quellen aus → deshalb der Remap auf `callrec_mix`.
- Gain-Staging ist clip-kritisch: Übersteuerung (0 dBFS) hat einmal die Diarization-Embeddings zerstört
→ 14 „Sprecher“ bei einem 2-Personen-Gespräch (Aufnahme #41, bleibt dauerhaft geclippt).
## Persistenz
| Einheit | Aufgabe |
|---|---|
| `aime-usb-audio.service` (user) | baut die komplette Topologie beim Boot (`aime-usb-audio-setup.sh`); wartet auf micgate, Fallback direkt auf Gadget-Sink |
| `aime-micgate.service` (user, enabled) | startet die micgate-Filter-Chain |
| `aime-volume-headset.service` (user) | Windows-Volume-Bridge (UAC2 numid=7 → Headset-Sink) |
| `aime-headset-keys.service` (root) | H390-Inline-Tasten → Lautstärke |
| alte `aime-audio-out` / `aime-volume` | ES8323-Ära, **disabled** |
Kaltstart 2× verifiziert: Topologie, Gate, Volume-Bridge und WLAN kommen ohne Eingriff hoch.