add zebrad: pulseaudio→websocket introspector for chat.html
single C file (~620 LOC), no third-party deps beyond libpulse.
closes a receive loop for web/chat.html: a browser tab cannot read
another tab's PulseAudio state, so each peer runs zebrad locally
to forward decoded frames to ws://127.0.0.1:7777.
components inline:
* SHA-1 (RFC 3174) + base64 encode — for the WebSocket handshake;
verified against the canonical RFC 6455 example
(key dGhlIHNhbXBsZSBub25jZQ== → accept s3pPLMBiTxaQ9kYGzzhZRbK+xOo=)
* CRC-32 (IEEE 802.3) — verifies DATA + HELLO frame payloads
* UART symbol decoder with adaptive threshold:
running peak with 2-second half-life decay, threshold = 50% of peak,
falling-edge start detect, sample at 1.5..8.5 × sps from edge
* frame assembler: magic-sync ZB, type dispatch OFFER/READY/DATA/HELLO,
overflow + corrupt-length guards, resync on bad checksum
* embedded WebSocket server: TCP listener on 127.0.0.1:7777,
handshake responder, binary frames only (opcode 0x82), no masking
(server→client), any inbound data closes the client (browser
auto-reconnects); max 16 concurrent clients
* pulseaudio: pa_mainloop integration, record stream on @DEFAULT_MONITOR@
by default, PA_SAMPLE_FLOAT32LE mono @ 8 kHz, 10 ms fragsize, peak
energy extracted from |abs(sample)|
adaptive baud: starts at ZEBRA_BAUD_HANDSHAKE (50). On valid READY frame
locks in negotiated baud from payload. Matches the chat.html send path.
binds 127.0.0.1 only — never reachable from the LAN, even though the
chat.html page itself may be served over HTTPS from a public domain.
smoke tested: PA connect + stream ready + WS handshake (RFC example
verified) + clean shutdown. -Wall -Wextra clean.
Makefile: zebrad now part of `make all`; clean target updated.
README: new section documenting it.
This commit is contained in:
parent
5d76d713a6
commit
c8a755513f
3 changed files with 719 additions and 4 deletions
25
README.md
25
README.md
|
|
@ -41,7 +41,7 @@ early with a clear message.
|
|||
|
||||
## Targets
|
||||
|
||||
### `make all` — five binaries
|
||||
### `make all` — six binaries
|
||||
|
||||
| Binary | Source | Role |
|
||||
|-----------|----------------|------|
|
||||
|
|
@ -50,6 +50,7 @@ early with a clear message.
|
|||
| `chat` | `src/chat.c` | bidirectional tx+rx, line-based chat UI |
|
||||
| `bt` | `src/bt.c` | "battle toads" dual-channel stereo UART (2× throughput) |
|
||||
| `carrier` | `src/carrier.c`| publishes a silent PA sink so volume reads have something to read |
|
||||
| `zebrad` | `src/zebrad.c` | PA→WS introspector for `web/chat.html` |
|
||||
|
||||
All link against `libpulse`, `librt`, and `libpthread`. Headers come from
|
||||
`include/zebra.h` (protocol constants) and `include/modem.h` (inline encode/
|
||||
|
|
@ -107,6 +108,28 @@ the blog and serves `web/` on port 8765 for local preview.
|
|||
The chat UI (`web/chat.html`) is plain static HTML and works directly under
|
||||
`make serve` — open `http://127.0.0.1:8765/chat.html`.
|
||||
|
||||
### `make zebrad` — PulseAudio → WebSocket introspector
|
||||
|
||||
`web/chat.html` modulates audio output via Web Audio `GainNode` (mic stays off).
|
||||
A browser tab cannot read another tab's PA state, so to close the receive
|
||||
loop each peer runs `zebrad`. Decoded frames are forwarded over a local
|
||||
WebSocket; `chat.html` auto-connects to `ws://127.0.0.1:7777`.
|
||||
|
||||
```bash
|
||||
make zebrad
|
||||
./zebrad --verbose # default: @DEFAULT_MONITOR@, port 7777
|
||||
./zebrad --source <name> --port 7777
|
||||
```
|
||||
|
||||
Single C file, no third-party deps beyond `libpulse`. Embedded WebSocket
|
||||
server: SHA-1 + base64 inline, server→client binary frames only (RFC 6455
|
||||
opcode 0x82); any inbound data closes the socket (browser auto-reconnects).
|
||||
Bound to `127.0.0.1` only — never accessible from the LAN.
|
||||
|
||||
Adaptive baud: starts at `ZEBRA_BAUD_HANDSHAKE` (50), watches for a `READY`
|
||||
frame, locks in the negotiated rate from its payload. Peak tracker has
|
||||
2-second half-life decay so threshold adapts to room volume.
|
||||
|
||||
### `make clean`
|
||||
|
||||
Removes:
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue