Files
2026-03-26 11:19:39 +01:00

5.7 KiB

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-<timestamp>.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_refs>

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.goTrafficClass constants and WindowSnapshot struct (the input contract for synthesis)
  • aggregate/window.goAggregate() 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

</canonical_refs>

<code_context>

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

</code_context>

## 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