summaryrefslogtreecommitdiff
path: root/stacks/crdop/docs/AUDIO-ARCHITECTURE.md
blob: 63202531e2c9cd5127992e9c0773c0f0b3f835b1 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
# CRDOP audio architecture — kernel ALSA only

**CRDOP** = stack acronym for **MAX25-SoftModem** (device id `soft-crdop`).

MAX25-SoftModem (CRDOP) talks to the radio **through the sound hardware directly**. There is **no PulseAudio**, **no PipeWire default route**, and **no desktop sound server** in the path.

## Stack layers

```
┌─────────────┐   M25/1 TCP    ┌──────────────┐   host TCP   ┌─────────────┐
│  max25d     │ ◄────────────► │ CRDOP modem  │ ◄──────────► │ max25-      │
│  (stack)    │                │ (DSP/AX.25)  │              │ terminal    │
└─────────────┘                └──────┬───────┘              └─────────────┘
                                      │
                              MAX25 sound-proxy
                              (buffer, timing, duplex)
                                      │
                                      ▼
                              libasound (userspace)
                                      │
                                      ▼
                              Linux kernel ALSA
                              (/dev/snd/*, drivers)
                                      │
                                      ▼
                              Sound hardware (USB/PCI codec)
                                      │
                                      ▼
                              Radio interface (line / acoustic)
```

| Layer | Role | Allowed |
|-------|------|---------|
| **max25d** | Device lifecycle, `CrdopTcpBackend`, no audio I/O | — |
| **CRDOP modem** | AFSK encode/decode, AX.25 framing, duplex policy | — |
| **MAX25 sound-proxy** | **Only** audio shim between modem and ALSA — period size, xrun recovery, hw params, PTT timing hooks | MAX25-owned |
| **ALSA userspace** | `snd_pcm_*` on **`hw:` / `plughw:`** devices | Direct libasound |
| **Kernel ALSA** | Driver, DMA, card registry | Required |
| **PulseAudio / PipeWire** | — | **Forbidden** in production path |

The sound-proxy is **not** a second network hop — it is the in-process (or co-process) module that owns ALSA opens and keeps modem timing off the desktop audio stack.

## Why no PulseAudio

PulseAudio and PipeWire insert mixing, resampling, and variable latency between applications and the kernel. CRDOP must:

- Reproduce **exact mark/space frequencies** on playback
- Sample capture with **stable phase** for demodulation
- Meet **tighter deadlines** as baud rises toward 19200

A userspace mixer breaks those guarantees. Operators must bind **card and device explicitly** (`hw:Card,Device` or tested `plughw:`).

## Operator setup

1. Identify hardware: `arecord -l` and `aplay -l` (kernel cards, not `pulse` pseudo-devices).
2. Set INI `[audio] capture` and `playback` to **hardware ALSA names**.
3. Ensure no session steals the device (`pasuspender` / stop PulseAudio on dedicated hosts).
4. Verify loopback before on-air traffic.

Example INI:

```ini
[audio]
backend = alsa-kernel
no_pulse = yes
capture = hw:1,0
playback = hw:1,0
```

Dedicated packet-radio hosts: prefer **single-purpose Linux** without a desktop sound daemon, or `PULSE_SERVER=` / `PIPEWIRE_RUNTIME_DIR=` unset for the `crdop` service unit.

## Development (Eigenentwicklung)

Native CRDOP will implement the sound-proxy in-tree (`include/crdop/sound_proxy.h`). Legacy optional vendor builds used `ALSASound.c` with the same rule: **open ALSA devices directly**.

## See also

- [SOFTMODEM.md](SOFTMODEM.md) — product scope, baud, duplex
- [CONFIG.md](CONFIG.md) — INI keys
- [BUILD.md](BUILD.md) — `libasound2-dev` dependency
git clone -b <branch> https://cgit.mode42.com/<repo>.git
git clone -b <branch> git://cgit.mode42.com/<repo>.git

info@mode42.com