docs(02-01): complete synth foundation plan
- Add 02-01-SUMMARY.md documenting config, oscillator, layer implementation
This commit is contained in:
@@ -0,0 +1,87 @@
|
||||
---
|
||||
phase: 02-audio-synthesis-engine
|
||||
plan: "01"
|
||||
subsystem: synth
|
||||
tags: [synthesis, oscillator, EMA, harmonics, audio, go-lame, CGo]
|
||||
dependency_graph:
|
||||
requires: [classify/types.go]
|
||||
provides: [synth/config.go, synth/oscillator.go, synth/layer.go]
|
||||
affects: [synth/mixer.go (Plan 02-02)]
|
||||
tech_stack:
|
||||
added: [github.com/sjzar/go-lame@v0.0.9, gcc, ffprobe]
|
||||
patterns: [phase-accumulator oscillator, EMA amplitude smoothing, additive synthesis, whisper floor]
|
||||
key_files:
|
||||
created:
|
||||
- synth/config.go
|
||||
- synth/oscillator.go
|
||||
- synth/layer.go
|
||||
- synth/config_test.go
|
||||
- synth/oscillator_test.go
|
||||
- synth/layer_test.go
|
||||
modified:
|
||||
- go.mod
|
||||
- go.sum
|
||||
decisions:
|
||||
- "go-lame v0.0.9 added as indirect dependency (no direct usage yet); will be promoted to direct in Plan 02-02 when encoder is wired"
|
||||
- "go-audio/wav intentionally excluded — writing interleaved int16 PCM bytes directly to LameWriter is simpler (per CONTEXT.md Claude's Discretion grant)"
|
||||
- "ClassNTP has only 2 harmonics (not 3) — NTP is a minimal timing signal; 2 harmonics satisfy test requirement and match timbral intent"
|
||||
metrics:
|
||||
duration: "~15 minutes"
|
||||
completed_date: "2026-03-26"
|
||||
tasks_completed: 2
|
||||
files_created: 6
|
||||
files_modified: 2
|
||||
---
|
||||
|
||||
# Phase 02 Plan 01: Synth Foundation — Config, Oscillator, and Layer Summary
|
||||
|
||||
**One-liner:** Phase-accumulator additive oscillator with EMA amplitude smoothing and whisper floor for 11 traffic-class drone layers, tested via TDD.
|
||||
|
||||
## What Was Built
|
||||
|
||||
### synth/config.go
|
||||
Defines the frequency/harmonic/pan configuration table for all 11 traffic classes. Key constants: `SampleRate=44100`, `WhisperFloor=0.03`, `GainPerLayer=1/11`. Each class has a `FreqConfig` with `BaseHz` in 60-800 Hz, 2-3 `HarmonicDef` entries (ratio + amplitude), and a stereo pan position in [-1, 1].
|
||||
|
||||
Frequency assignments follow musical intervals (D-02/D-03): 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=700 Hz, other-UDP=780 Hz. ClassUnknown=437 Hz (detuned 3 Hz below SMTP for perceptible beating, per D-04).
|
||||
|
||||
### synth/oscillator.go
|
||||
Phase-accumulator oscillator. `Advance(harmonics []HarmonicDef) float64` sums weighted sine partials and normalizes by total weight. Phase advances by `freq/sampleRate` per sample with subtraction wrap (`o.phase -= 1.0`), not `math.Mod`, for performance.
|
||||
|
||||
### synth/layer.go
|
||||
`Layer` wraps an oscillator with EMA amplitude dynamics. `UpdateTarget(count, maxCount)` sets target amplitude: unseen layers stay at 0.0; seen layers floor at `WhisperFloor` and scale linearly to 1.0 at max count. `AdvanceSample()` advances the oscillator and the EMA (`currentAmp += alpha * (target - current)`). `EMAAlpha(tau, sr)` computes the per-sample coefficient for a given time constant in seconds.
|
||||
|
||||
### Tests (12 passing)
|
||||
- Config: `TestAllClassesHaveConfig`, `TestFrequenciesInRange`, `TestFrequenciesUnique`, `TestHarmonicsNonEmpty`, `TestPanPositionsInRange`
|
||||
- Oscillator: `TestOscillatorAdvance`, `TestOscillatorPhaseWrap`, `TestOscillatorDistinctFreqs`
|
||||
- Layer: `TestEMAAmplitudeRise`, `TestEMAAmplitudeDecay`, `TestWhisperFloor`, `TestWhisperFloorNotSeenIsZero`
|
||||
|
||||
## Commits
|
||||
|
||||
| Task | Commit | Description |
|
||||
|------|--------|-------------|
|
||||
| 1 — environment setup | dc7aed2 | chore(02-01): install gcc, ffprobe, and go-lame dependency |
|
||||
| 2 — tests (RED) | bb13527 | test(02-01): add failing tests for synth config, oscillator, and layer |
|
||||
| 2 — implementation (GREEN) | 1aaa15d | feat(02-01): implement synth config, oscillator, and layer |
|
||||
|
||||
## Deviations from Plan
|
||||
|
||||
None — plan executed exactly as written.
|
||||
|
||||
## Known Stubs
|
||||
|
||||
None — all config entries are fully wired with real frequency/harmonic/pan values. No placeholder data.
|
||||
|
||||
## Self-Check: PASSED
|
||||
|
||||
- synth/config.go: FOUND
|
||||
- synth/oscillator.go: FOUND
|
||||
- synth/layer.go: FOUND
|
||||
- synth/config_test.go: FOUND
|
||||
- synth/oscillator_test.go: FOUND
|
||||
- synth/layer_test.go: FOUND
|
||||
- Commit dc7aed2: FOUND
|
||||
- Commit bb13527: FOUND
|
||||
- Commit 1aaa15d: FOUND
|
||||
- `go test ./synth/...`: 12 tests PASS
|
||||
- `CGO_ENABLED=1 go build ./...`: PASS
|
||||
- go.mod contains go-lame v0.0.9: VERIFIED
|
||||
Reference in New Issue
Block a user