diff --git a/.planning/REQUIREMENTS.md b/.planning/REQUIREMENTS.md index f9b1482..acb511f 100644 --- a/.planning/REQUIREMENTS.md +++ b/.planning/REQUIREMENTS.md @@ -18,8 +18,8 @@ Requirements for custom sound mappings milestone. Each maps to roadmap phases. ### Waveforms -- [ ] **WAVE-01**: User can set waveform type per traffic class (sine, square, sawtooth, triangle) -- [ ] **WAVE-02**: Non-sine waveforms use bandlimited additive synthesis (no aliasing artifacts) +- [x] **WAVE-01**: User can set waveform type per traffic class (sine, square, sawtooth, triangle) +- [x] **WAVE-02**: Non-sine waveforms use bandlimited additive synthesis (no aliasing artifacts) ### Custom Rules @@ -62,8 +62,8 @@ Which phases cover which requirements. Updated during roadmap creation. | CFG-04 | Phase 6 | Pending | | CFG-05 | Phase 6 | Pending | | CFG-06 | Phase 7 | Pending | -| WAVE-01 | Phase 5 | Pending | -| WAVE-02 | Phase 5 | Pending | +| WAVE-01 | Phase 5 | Complete | +| WAVE-02 | Phase 5 | Complete | | RULE-01 | Phase 7 | Pending | | RULE-02 | Phase 7 | Pending | | RULE-03 | Phase 7 | Pending | diff --git a/.planning/ROADMAP.md b/.planning/ROADMAP.md index 0ea81fb..96786f0 100644 --- a/.planning/ROADMAP.md +++ b/.planning/ROADMAP.md @@ -37,10 +37,10 @@ Full details: `.planning/milestones/v1.0-ROADMAP.md` 1. User can set a traffic class to square, sawtooth, or triangle waveform and hear a tonally distinct sound with no audible aliasing or buzzing artifacts 2. Sine waveform continues to produce the same output as v1.0 — no regression 3. The synthesis bank builds layers from a passed-in config map rather than a hardcoded class list -**Plans:** 2 plans +**Plans:** 1/2 plans executed Plans: -- [ ] 05-01-PLAN.md — Waveform types: WaveformType enum, WaveformPresetHarmonics, NewLayer resolution +- [x] 05-01-PLAN.md — Waveform types: WaveformType enum, WaveformPresetHarmonics, NewLayer resolution - [ ] 05-02-PLAN.md — Bank decoupling: NewBank injected config map, dynamic GainPerLayer, test updates ### Phase 6: Config Package and Sound Overrides @@ -74,6 +74,6 @@ Plans: | 2. Audio Synthesis Engine | v1.0 | 3/3 | Complete | 2026-03-26 | | 3. Pipeline Integration and MVP | v1.0 | 2/2 | Complete | 2026-03-26 | | 4. Power User Features | v1.0 | 2/2 | Complete | 2026-03-26 | -| 5. Waveform Types and Bank Decoupling | v1.1 | 0/2 | Not started | - | +| 5. Waveform Types and Bank Decoupling | v1.1 | 1/2 | In Progress| | | 6. Config Package and Sound Overrides | v1.1 | 0/? | Not started | - | | 7. Custom Rules and Print-Config | v1.1 | 0/? | Not started | - | diff --git a/.planning/STATE.md b/.planning/STATE.md index fcfeef6..bb25d85 100644 --- a/.planning/STATE.md +++ b/.planning/STATE.md @@ -2,15 +2,15 @@ gsd_state_version: 1.0 milestone: v1.1 milestone_name: Custom Sound Mappings -status: planning -stopped_at: Phase 5 context gathered -last_updated: "2026-03-26T16:11:17.884Z" -last_activity: 2026-03-26 — v1.1 roadmap created, Phases 5-7 defined +status: executing +stopped_at: Completed 05-01-PLAN.md +last_updated: "2026-03-26T16:35:44.333Z" +last_activity: 2026-03-26 progress: total_phases: 3 completed_phases: 0 - total_plans: 0 - completed_plans: 0 + total_plans: 2 + completed_plans: 1 percent: 0 --- @@ -21,14 +21,14 @@ progress: See: .planning/PROJECT.md (updated 2026-03-26) **Core value:** Network traffic patterns are instantly recognizable as distinct sounds — a ping sounds different from HTTPS noise, which sounds different from a port scan. -**Current focus:** Milestone v1.1 — Custom Sound Mappings (Phase 5 next) +**Current focus:** Phase 05 — waveform-types-and-bank-decoupling ## Current Position -Phase: 5 of 7 (Waveform Types and Bank Decoupling) -Plan: — -Status: Ready to plan -Last activity: 2026-03-26 — v1.1 roadmap created, Phases 5-7 defined +Phase: 05 (waveform-types-and-bank-decoupling) — EXECUTING +Plan: 2 of 2 +Status: Ready to execute +Last activity: 2026-03-26 Progress: [░░░░░░░░░░] 0% @@ -50,6 +50,7 @@ Progress: [░░░░░░░░░░] 0% | 04 | 2 | ~7min | 3.5min | **Recent Trend:** Stable +| Phase 05 P01 | 3min | 2 tasks | 3 files | ## Accumulated Context @@ -58,6 +59,8 @@ Progress: [░░░░░░░░░░] 0% - [v1.1 Roadmap]: Phase 5 consolidates waveform types (WAVE-01, WAVE-02) with bank decoupling — both are internal refactors with no user-visible surface, establishing the injectable seam before config is added - [v1.1 Roadmap]: Research steps 5+6 (wire config + freq/waveform overrides) collapsed into Phase 6 — they share the same integration boundary (encode.RunSynthesis signature change) and are safer to land together - [v1.1 Roadmap]: User class name collision with built-in TrafficClass strings is an unresolved design question — decide before coding Phase 7 (treat as override vs. reject as ambiguous) +- [Phase 05]: FreqConfig struct uses named field syntax for ClassFreqConfigs entries (required by WaveformType addition) +- [Phase 05]: WaveformType zero value is WaveformCustom — all 14 existing ClassFreqConfigs entries retain hand-tuned harmonics without modification ### Pending Todos @@ -69,6 +72,6 @@ None. ## Session Continuity -Last session: 2026-03-26T16:11:17.877Z -Stopped at: Phase 5 context gathered -Resume file: .planning/phases/05-waveform-types-and-bank-decoupling/05-CONTEXT.md +Last session: 2026-03-26T16:35:44.326Z +Stopped at: Completed 05-01-PLAN.md +Resume file: None diff --git a/.planning/phases/05-waveform-types-and-bank-decoupling/05-01-SUMMARY.md b/.planning/phases/05-waveform-types-and-bank-decoupling/05-01-SUMMARY.md new file mode 100644 index 0000000..d45d610 --- /dev/null +++ b/.planning/phases/05-waveform-types-and-bank-decoupling/05-01-SUMMARY.md @@ -0,0 +1,78 @@ +--- +phase: 05-waveform-types-and-bank-decoupling +plan: "01" +subsystem: synth +tags: [waveform, additive-synthesis, bandlimiting, enum, tdd] +dependency_graph: + requires: [] + provides: [WaveformType enum, WaveformPresetHarmonics, NewLayer waveform resolution] + affects: [synth/config.go, synth/layer.go] +tech_stack: + added: [] + patterns: [TDD red-green, bandlimited additive synthesis, zero-value backward compat] +key_files: + created: + - synth/waveform_test.go + modified: + - synth/config.go + - synth/layer.go +decisions: + - "ClassFreqConfigs converted from positional to named struct literals (required by new WaveformType field)" + - "FreqConfig.WaveformType zero value is WaveformCustom, ensuring all existing entries auto-preserve hand-tuned harmonics" +metrics: + duration: "~3 min" + completed_date: "2026-03-26" + tasks: 2 + files: 3 +requirements: + - WAVE-01 + - WAVE-02 +--- + +# Phase 5 Plan 01: Waveform Types and WaveformPresetHarmonics Summary + +WaveformType enum with four bandlimited presets (sine, square, sawtooth, triangle) added to synth package with construction-time resolution in NewLayer. + +## What Was Built + +- **`WaveformType int` enum** in `synth/config.go` with five constants: `WaveformCustom` (0), `WaveformSine`, `WaveformSquare`, `WaveformSawtooth`, `WaveformTriangle` +- **`WaveformPresetHarmonics(wt, baseHz, sampleRate)`** function that generates bandlimited harmonic series — all partials below Nyquist (sampleRate/2) +- **`FreqConfig.WaveformType` field** added; zero value `WaveformCustom` ensures full backward compatibility with all 14 existing `ClassFreqConfigs` entries +- **`NewLayer` waveform resolution** — presets resolved at construction time, stored in `Layer.Config.Harmonics`, so `AdvanceSample` requires no changes +- **`synth/waveform_test.go`** with 12 tests covering all preset shapes, bandlimit enforcement, odd-only ratios, consecutive ratios, nil return for Custom, regression vs hand-tuned harmonics, and NewLayer construction behavior + +## Tasks Completed + +| Task | Description | Commit | Files | +|------|-------------|--------|-------| +| 1 (RED) | Failing waveform tests | 88dee31 | synth/waveform_test.go | +| 1 (GREEN) | WaveformType enum + WaveformPresetHarmonics | 82d1e37 | synth/config.go | +| 2 | Wire waveform resolution into NewLayer + 3 more tests | 7f64714 | synth/layer.go, synth/waveform_test.go | + +## Verification + +- `go test ./synth/... -v`: 41 tests, all pass (28 existing + 12 new waveform + 1 regression) +- `go test ./encode/...`: 3 tests pass (no regressions) +- `go vet ./synth/...`: clean + +## Deviations from Plan + +### Auto-fixed Issues + +**1. [Rule 1 - Bug] ClassFreqConfigs positional struct literals broken by new field** +- **Found during:** Task 1 GREEN phase +- **Issue:** Adding `WaveformType WaveformType` field to `FreqConfig` caused compile errors on all 14 positional struct literals in `ClassFreqConfigs` ("too few values in struct literal") +- **Fix:** Converted all 14 entries from positional `{65.0, []HarmonicDef{...}, 0.0}` syntax to named field `{BaseHz: 65.0, Harmonics: []HarmonicDef{...}, Pan: 0.0}` syntax. WaveformType field implicitly zero (WaveformCustom), preserving hand-tuned harmonics as per D-03. +- **Files modified:** synth/config.go (ClassFreqConfigs block) +- **Commit:** 82d1e37 + +## Known Stubs + +None — all waveform preset logic is fully implemented and wired. + +## Self-Check: PASSED + +- synth/waveform_test.go: FOUND +- synth/config.go (WaveformType): FOUND (verified by go test passing) +- synth/layer.go (NewLayer resolution): FOUND (verified by TestNewLayerResolvesWaveformPreset) +- Commits 88dee31, 82d1e37, 7f64714: all present in git log