# Phase 2: Audio Synthesis Engine - Context **Gathered:** 2026-03-26 **Status:** Ready for planning ## Phase Boundary Oscillators, EMA amplitude smoothing, multi-layer mixing, stereo panning, and MP3 encoding — all validated against synthetic `WindowSnapshot` inputs. No live traffic flows through this phase. The output is a valid MP3 file produced from fabricated traffic data. ## Implementation Decisions ### Tone mapping - **D-01:** Wide ambient frequency range: 60-800 Hz across 11 traffic classes - **D-02:** Frequencies use musical intervals (harmonic relationships — fifths, octaves, etc.) so layers blend pleasantly - **D-03:** Approximate register assignments: ICMP ~65 Hz (deep bass), DNS ~110 Hz, HTTPS ~175 Hz, HTTP ~220 Hz, SSH ~330 Hz, SMTP ~440 Hz, NTP ~520 Hz, DHCP ~600 Hz, other-TCP/other-UDP ~700-800 Hz - **D-04:** "unknown" traffic gets a dissonant/detuned tone — slightly off-key or beating frequency that audibly signals unclassified traffic, distinct from the harmonious known classes ### Waveform texture - **D-05:** Each drone layer uses fundamental + 2-3 harmonics (not pure sine waves) for warm, pad-like sound - **D-06:** Harmonic ratios vary per traffic class for subtle timbral distinction — e.g., ICMP brighter, HTTPS warmer, SSH buzzier. Each protocol has its own sonic identity beyond just pitch. ### Amplitude dynamics - **D-07:** EMA smoothing with medium responsiveness (1-2 second attack/decay). Traffic changes are audible but smooth — not glacial, not snappy. - **D-08:** Layers never fade to full silence — once a traffic class has been seen, it stays at a fixed whisper floor (~2-5% of max amplitude). Quiet network still has a faint base layer. - **D-09:** Fixed whisper floor (not recency-based decay). Simple and predictable. ### Mixing & output - **D-10:** Fixed equal gain per layer — each of 11 layers gets 1/11 of headroom (~0.09 max amplitude). Sum never exceeds 1.0, no clipping, no dynamic limiter needed. - **D-11:** Stereo output with register-based panning: bass frequencies center, mid frequencies spread left/right, higher frequencies wider. Unknown stays center to stand out. - **D-12:** Panning positions: ICMP center, DNS slight-L, HTTPS slight-R, HTTP center-L, SSH center-R, SMTP mid-L, NTP mid-R, DHCP wide-L, other-TCP wide-R, other-UDP wide-L, unknown center. - **D-13:** 44100 Hz sample rate (CD quality) - **D-14:** 128 kbps MP3 encoding via `sjzar/go-lame` - **D-15:** `-o` flag for output path; defaults to `netsynth-.mp3` when omitted - **D-16:** Empty (zero-packet) input produces a clear error message, not a corrupt or zero-byte MP3 ### Claude's Discretion - Exact Hz values per class (within the 60-800 Hz range, using musical intervals) - Specific harmonic ratios per traffic class (within the "2-3 harmonics" constraint) - Exact EMA alpha/decay constants to achieve the 1-2 second feel - Exact whisper floor percentage (within 2-5% range) - WAV intermediate format usage (per CLAUDE.md recommendation of go-audio/wav) - Stereo panning implementation (constant-power pan law vs linear) ## Canonical References **Downstream agents MUST read these before planning or implementing.** ### Project context - `.planning/PROJECT.md` — Core value, constraints (Go, MP3 output, non-interactive) - `.planning/REQUIREMENTS.md` — SYNTH-01, SYNTH-02, SYNTH-03, OUT-01, OUT-02, OUT-03 ### Prior phase - `.planning/phases/01-capture-and-classification/01-CONTEXT.md` — Phase 1 decisions; `WindowSnapshot` contract defined here - `classify/types.go` — `TrafficClass` constants and `WindowSnapshot` struct (the input contract for synthesis) - `aggregate/window.go` — `Aggregate()` function that produces `WindowSnapshot` on 500ms intervals ### Stack decisions - `.planning/research/STACK.md` — Library recommendations (go-lame, go-audio/wav) - `.planning/research/ARCHITECTURE.md` — Pipeline architecture, component boundaries - `CLAUDE.md` — Technology stack section with `sjzar/go-lame` v0.0.9 usage, `go-audio/wav` for intermediate format ## Existing Code Insights ### Reusable Assets - `classify.TrafficClass` type and constants (`classify/types.go`) — 11 named classes, used as map keys in WindowSnapshot - `classify.AllClasses()` — returns all classes in display order; useful for iterating when setting up oscillator bank - `classify.WindowSnapshot` — the input contract: `Counts map[TrafficClass]int64`, `TotalPackets int64`, `WindowIndex int` - `aggregate.Aggregate()` — produces `chan WindowSnapshot` on 500ms ticks; Phase 2 consumes this channel ### Established Patterns - Channel-based pipeline: capture -> classify -> aggregate -> (synthesis goes here) - `done <-chan struct{}` for shutdown signaling - Buffered channels for stage decoupling (512-buffer capture, 8-buffer aggregate output) - io.Writer injection for testable output (used in aggregate/summary.go) ### Integration Points - Synthesis engine will consume `<-chan classify.WindowSnapshot` from `aggregate.Aggregate()` - MP3 output path comes from Cobra CLI flags (already scaffolded in `cmd/netsynth/main.go`) - Phase 3 wires these together; Phase 2 tests against synthetic/fabricated WindowSnapshot data ## Specific Ideas - Sound should feel like an "ambient synth pad" — warm, layered, organic - Unknown traffic should be immediately recognizable as "something doesn't belong" via its dissonant tone - The stereo field should create a sense of space — not just mono with volume panning - Each protocol should have a sonic identity beyond just pitch (varied harmonic ratios) ## Deferred Ideas None — discussion stayed within phase scope --- *Phase: 02-audio-synthesis-engine* *Context gathered: 2026-03-26*