docs(02-03): complete MP3 encoder and output flag plan
- Create 02-03-SUMMARY.md with TDD flow documentation - Update STATE.md: advance to last plan, 100% progress, add decisions - Update ROADMAP.md: phase 02 complete (3/3 plans) - Mark requirements OUT-01, OUT-02, OUT-03 complete
This commit is contained in:
@@ -31,9 +31,9 @@ Requirements for initial release. Each maps to roadmap phases.
|
||||
|
||||
### Output
|
||||
|
||||
- [ ] **OUT-01**: User can specify output file path via `-o` flag (defaults to `netsynth-<timestamp>.mp3`)
|
||||
- [ ] **OUT-02**: Output is encoded as a valid MP3 file
|
||||
- [ ] **OUT-03**: Empty captures (zero packets) produce a clear error instead of a corrupt file
|
||||
- [x] **OUT-01**: User can specify output file path via `-o` flag (defaults to `netsynth-<timestamp>.mp3`)
|
||||
- [x] **OUT-02**: Output is encoded as a valid MP3 file
|
||||
- [x] **OUT-03**: Empty captures (zero packets) produce a clear error instead of a corrupt file
|
||||
|
||||
## v2 Requirements
|
||||
|
||||
@@ -79,9 +79,9 @@ Which phases cover which requirements. Updated during roadmap creation.
|
||||
| SYNTH-01 | Phase 2 | Complete |
|
||||
| SYNTH-02 | Phase 2 | Complete |
|
||||
| SYNTH-03 | Phase 2 | Complete |
|
||||
| OUT-01 | Phase 2 | Pending |
|
||||
| OUT-02 | Phase 2 | Pending |
|
||||
| OUT-03 | Phase 2 | Pending |
|
||||
| OUT-01 | Phase 2 | Complete |
|
||||
| OUT-02 | Phase 2 | Complete |
|
||||
| OUT-03 | Phase 2 | Complete |
|
||||
|
||||
**Coverage:**
|
||||
- v1 requirements: 16 total
|
||||
|
||||
@@ -13,7 +13,7 @@ NetSynth is built in four phases ordered by technical risk. Phase 1 validates th
|
||||
Decimal phases appear between their surrounding integers in numeric order.
|
||||
|
||||
- [x] **Phase 1: Capture and Classification** - Live packet capture, protocol identification, and CLI scaffolding — no audio yet (completed 2026-03-25)
|
||||
- [ ] **Phase 2: Audio Synthesis Engine** - Oscillators, EMA amplitude smoothing, mixing, and MP3 encoding against synthetic inputs
|
||||
- [x] **Phase 2: Audio Synthesis Engine** - Oscillators, EMA amplitude smoothing, mixing, and MP3 encoding against synthetic inputs (completed 2026-03-26)
|
||||
- [ ] **Phase 3: Pipeline Integration and MVP** - Wire capture into synthesis, Ctrl+C with valid MP3 output, auto-clustering of unknown traffic
|
||||
- [ ] **Phase 4: Power User Features** - BPF capture filter, offline pcap file input
|
||||
|
||||
@@ -47,12 +47,12 @@ Plans:
|
||||
3. Drone layer amplitude rises and falls with traffic volume over time — sustained traffic sounds louder, quiet periods fade
|
||||
4. User can specify output path via `-o` flag; it defaults to `netsynth-<timestamp>.mp3` when omitted
|
||||
5. An empty (zero-packet) input produces a clear error message instead of a corrupt or zero-byte MP3
|
||||
**Plans:** 2/3 plans executed
|
||||
**Plans:** 3/3 plans complete
|
||||
|
||||
Plans:
|
||||
- [x] 02-01-PLAN.md — Environment setup (gcc, ffprobe, go-lame), synth config table, oscillator, EMA layer with tests
|
||||
- [x] 02-02-PLAN.md — Stereo mixer (constant-power panning), OscillatorBank multi-layer rendering with tests
|
||||
- [ ] 02-03-PLAN.md — MP3 encoder package, zero-packet guard, -o CLI flag, ffprobe integration test
|
||||
- [x] 02-03-PLAN.md — MP3 encoder package, zero-packet guard, -o CLI flag, ffprobe integration test
|
||||
|
||||
### Phase 3: Pipeline Integration and MVP
|
||||
**Goal**: Live capture flows end-to-end into audio synthesis — the complete v1 MVP: run, capture, Ctrl+C, get an MP3
|
||||
@@ -82,6 +82,6 @@ Phases execute in numeric order: 1 → 2 → 3 → 4
|
||||
| Phase | Plans Complete | Status | Completed |
|
||||
|-------|----------------|--------|-----------|
|
||||
| 1. Capture and Classification | 4/4 | Complete | 2026-03-25 |
|
||||
| 2. Audio Synthesis Engine | 2/3 | In Progress| |
|
||||
| 2. Audio Synthesis Engine | 3/3 | Complete | 2026-03-26 |
|
||||
| 3. Pipeline Integration and MVP | 0/? | Not started | - |
|
||||
| 4. Power User Features | 0/? | Not started | - |
|
||||
|
||||
+10
-7
@@ -2,14 +2,14 @@
|
||||
gsd_state_version: 1.0
|
||||
milestone: v1.0
|
||||
milestone_name: milestone
|
||||
status: Ready to execute
|
||||
stopped_at: "Completed 02-02: OscillatorBank and stereo mixer"
|
||||
last_updated: "2026-03-26T11:04:17.995Z"
|
||||
status: Phase complete — ready for verification
|
||||
stopped_at: "Completed 02-03: MP3 encoder and CLI output flag"
|
||||
last_updated: "2026-03-26T11:09:30.198Z"
|
||||
progress:
|
||||
total_phases: 4
|
||||
completed_phases: 1
|
||||
completed_phases: 2
|
||||
total_plans: 7
|
||||
completed_plans: 6
|
||||
completed_plans: 7
|
||||
---
|
||||
|
||||
# Project State
|
||||
@@ -52,6 +52,7 @@ Plan: 3 of 3
|
||||
| Phase 01-capture-and-classification P04 | 15min | 2 tasks | 2 files |
|
||||
| Phase 02 P01 | 15min | 2 tasks | 8 files |
|
||||
| Phase 02 P02 | 10min | 2 tasks | 4 files |
|
||||
| Phase 02 P03 | 3min | 2 tasks | 3 files |
|
||||
|
||||
## Accumulated Context
|
||||
|
||||
@@ -79,6 +80,8 @@ Recent decisions affecting current work:
|
||||
- [Phase 02]: go-audio/wav excluded — writing PCM bytes directly to LameWriter is simpler (per Claude's Discretion grant in CONTEXT.md)
|
||||
- [Phase 02]: GainPerLayer applied in bank.go during mixing to ensure 11 max layers sum to 1.0 (D-10)
|
||||
- [Phase 02]: int16 conversion uses float * 32767 to avoid positive overflow at exactly +1.0
|
||||
- [Phase 02]: RunSynthesis takes snapshot slice (not channel) enabling zero-packet guard before file creation
|
||||
- [Phase 02]: EncodeMP3 and RunSynthesis are separate functions for independent testability
|
||||
|
||||
### Pending Todos
|
||||
|
||||
@@ -92,6 +95,6 @@ None yet.
|
||||
|
||||
## Session Continuity
|
||||
|
||||
Last session: 2026-03-26T11:04:17.988Z
|
||||
Stopped at: Completed 02-02: OscillatorBank and stereo mixer
|
||||
Last session: 2026-03-26T11:09:30.191Z
|
||||
Stopped at: Completed 02-03: MP3 encoder and CLI output flag
|
||||
Resume file: None
|
||||
|
||||
@@ -0,0 +1,100 @@
|
||||
---
|
||||
phase: 02-audio-synthesis-engine
|
||||
plan: 03
|
||||
subsystem: encode
|
||||
tags: [mp3, encoding, go-lame, cli, output-flag, tdd]
|
||||
dependency_graph:
|
||||
requires: [02-01, 02-02]
|
||||
provides: [encode/mp3.go, encode/mp3_test.go, cmd/netsynth/-o-flag]
|
||||
affects: [cmd/netsynth/main.go]
|
||||
tech_stack:
|
||||
added: [github.com/sjzar/go-lame (used directly)]
|
||||
patterns: [go-lame LameWriter API, zero-packet guard before file creation, TDD red-green workflow]
|
||||
key_files:
|
||||
created:
|
||||
- encode/mp3.go
|
||||
- encode/mp3_test.go
|
||||
modified:
|
||||
- cmd/netsynth/main.go
|
||||
decisions:
|
||||
- "EncodeMP3 and RunSynthesis separated into distinct functions to enable independent testing of raw-frame encoding vs full pipeline"
|
||||
- "RunSynthesis takes []classify.WindowSnapshot slice (not channel) — caller collects from channel enabling zero-packet check before file creation"
|
||||
- "Zero-packet guard checks totalPackets BEFORE os.Create to ensure no empty file is left on disk"
|
||||
- "Snapshot accumulator uses _ = collectedSnapshots to suppress unused variable error without importing encode package prematurely"
|
||||
metrics:
|
||||
duration: 3min
|
||||
completed: 2026-03-26
|
||||
tasks_completed: 2
|
||||
files_created: 2
|
||||
files_modified: 1
|
||||
---
|
||||
|
||||
# Phase 2 Plan 3: MP3 Encoder and Output Flag Summary
|
||||
|
||||
**One-liner:** MP3 encoder via go-lame (44100 Hz, 128 kbps) with ffprobe-validated tests, zero-packet guard, and -o CLI flag with timestamp default.
|
||||
|
||||
## What Was Built
|
||||
|
||||
### Task 1: MP3 encoder package (TDD)
|
||||
|
||||
**encode/mp3.go** implements two functions:
|
||||
|
||||
- `EncodeMP3(outputPath string, frames [][2]float64, sampleRate int) error` — Creates an MP3 file from stereo PCM frames using go-lame's LameWriter. Sets 44100 Hz input/output sample rate, 128 kbps bitrate, stereo (2 channels), quality 5. Calls `InitParams()` after all `Set*` calls (required by go-lame API). Writes all PCM bytes in a single call.
|
||||
|
||||
- `RunSynthesis(snapshots []classify.WindowSnapshot, outputPath string) error` — Orchestrates the full pipeline: checks total packet count (zero-packet guard before file creation), creates `OscillatorBank` with tau=1.0, renders each snapshot via `bank.RenderWindow`, concatenates all frames, and calls `EncodeMP3`.
|
||||
|
||||
**encode/mp3_test.go** implements three tests, all ffprobe-validated:
|
||||
- `TestMP3Valid` — 3 synthetic snapshots (ICMP=50+DNS=30, HTTPS=200, SSH=10+HTTP=80) through full pipeline; ffprobe confirms MP3 format, duration > 0
|
||||
- `TestZeroPacketError` — empty slice and zero-count snapshots return error containing "no packets"; output file does not exist on disk
|
||||
- `TestEncodeMP3DirectBytes` — 44100 frames of 440 Hz sine wave encoded directly; ffprobe confirms MP3 output
|
||||
|
||||
### Task 2: -o output flag and snapshot accumulator stub
|
||||
|
||||
**cmd/netsynth/main.go** additions:
|
||||
- `var outputPath string` package-level var
|
||||
- `-o`/`--output` Cobra flag with descriptive help text
|
||||
- Timestamp default resolution: `netsynth-<20060102-150405>.mp3` format when flag omitted
|
||||
- Snapshot accumulator loop collects `[]classify.WindowSnapshot` alongside existing totals accumulation
|
||||
- `TODO(phase-3)` comment marking the synthesis integration point
|
||||
|
||||
## Test Results
|
||||
|
||||
```
|
||||
ok github.com/netsynth/netsynth/aggregate 0.145s
|
||||
ok github.com/netsynth/netsynth/capture 0.009s
|
||||
ok github.com/netsynth/netsynth/classify 0.007s
|
||||
ok github.com/netsynth/netsynth/cmd/netsynth 0.021s
|
||||
ok github.com/netsynth/netsynth/encode 0.283s
|
||||
ok github.com/netsynth/netsynth/synth 0.680s
|
||||
```
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Commits
|
||||
|
||||
| Hash | Type | Description |
|
||||
|------|------|-------------|
|
||||
| ed3a562 | test | Add failing tests for MP3 encoder and RunSynthesis (RED) |
|
||||
| f221963 | feat | Implement MP3 encoder package with RunSynthesis orchestrator (GREEN) |
|
||||
| a65dfcd | feat | Wire -o output flag and snapshot accumulator stub into CLI |
|
||||
|
||||
## Phase 2 Completion
|
||||
|
||||
This plan completes Phase 2 (audio-synthesis-engine). The full synthesis chain is now validated end-to-end:
|
||||
|
||||
```
|
||||
WindowSnapshot -> OscillatorBank.RenderWindow -> [][2]float64 -> StereoFramesToInt16Bytes -> go-lame LameWriter -> MP3 file
|
||||
```
|
||||
|
||||
Phase 3 will wire `encode.RunSynthesis(collectedSnapshots, outputPath)` into the live capture pipeline.
|
||||
|
||||
## Self-Check
|
||||
|
||||
Files created/modified:
|
||||
- encode/mp3.go: EXISTS
|
||||
- encode/mp3_test.go: EXISTS
|
||||
- cmd/netsynth/main.go: MODIFIED
|
||||
|
||||
Commits verified: ed3a562, f221963, a65dfcd
|
||||
Reference in New Issue
Block a user