docs(05): capture phase context

This commit is contained in:
2026-03-26 17:11:11 +01:00
parent 8cb5120666
commit 7ced25ae70
2 changed files with 144 additions and 0 deletions
@@ -0,0 +1,86 @@
# Phase 5: Waveform Types and Bank Decoupling - Context
**Gathered:** 2026-03-26
**Status:** Ready for planning
<domain>
## Phase Boundary
Extend the synthesis oscillator to support four waveform types (sine, square, sawtooth, triangle) using bandlimited additive synthesis, and decouple the OscillatorBank from the hardcoded `ClassFreqConfigs` global and `classify.AllClasses()` iteration — making it accept an injected config map instead.
</domain>
<decisions>
## Implementation Decisions
### Waveform Presets
- **D-01:** Use bandlimited additive synthesis with 8-12 partials per waveform type. Square wave uses odd harmonics (1,3,5,...,11), sawtooth uses all harmonics (1-12), triangle uses odd harmonics with 1/n^2 amplitude rolloff. This is the standard approach for aliasing-free waveform generation.
- **D-02:** Add a `WaveformType` enum to `FreqConfig` (`Sine`, `Square`, `Sawtooth`, `Triangle`). When waveform is set, generate the `[]HarmonicDef` from the preset formula. When waveform is unset/custom, use the existing hand-tuned `Harmonics` array.
### Built-in Harmonics Migration
- **D-03:** (Claude's Discretion) Decide whether built-in classes keep their hand-tuned HarmonicDef arrays or migrate to waveform presets. Recommended approach: keep existing harmonics as-is for v1.0 classes (preserves sound character), default them to `WaveformType = ""` (custom). Waveform presets only take effect when explicitly set via config in Phase 6.
### GainPerLayer Scaling
- **D-04:** Fix GainPerLayer now in Phase 5 — compute dynamically as `1.0 / float64(len(layers))` inside `NewBank` instead of using the hardcoded `NumLayers=14` constant. This establishes the correct foundation before Phase 7 adds dynamic class counts.
### Bank Decoupling
- **D-05:** (Claude's Discretion) Change `NewBank` to accept a `map[classify.TrafficClass]FreqConfig` parameter instead of reading the `ClassFreqConfigs` global. This is the injection seam that Phase 6 will use to pass merged config. The existing `ClassFreqConfigs` var remains as the default map.
</decisions>
<canonical_refs>
## Canonical References
**Downstream agents MUST read these before planning or implementing.**
### Synthesis Architecture
- `synth/oscillator.go` — Current sine-only Oscillator with phase accumulator and `Advance([]HarmonicDef)`
- `synth/config.go``FreqConfig`, `HarmonicDef`, `ClassFreqConfigs` global, constants (`SampleRate`, `NumLayers`, `GainPerLayer`)
- `synth/bank.go``NewBank(tau)` iterates `classify.AllClasses()` and reads `ClassFreqConfigs` global
- `synth/layer.go``Layer` with EMA smoothing, uses `FreqConfig` from config.go
### Research
- `.planning/research/ARCHITECTURE.md` — Integration points and build order for v1.1
- `.planning/research/PITFALLS.md` — Pitfall A3 (aliasing) and A6 (bank class mismatch)
No external specs — requirements fully captured in decisions above.
</canonical_refs>
<code_context>
## Existing Code Insights
### Reusable Assets
- `Oscillator.Advance([]HarmonicDef)` — Already supports additive synthesis via harmonic series. Waveform presets just need different `[]HarmonicDef` arrays, not a new oscillator type.
- `FreqConfig` struct — Has `BaseHz`, `Harmonics`, `Pan`. Adding `WaveformType` field is backward-compatible.
### Established Patterns
- Phase accumulator in `Oscillator` wraps at 1.0 — all harmonic ratios are integer multiples of the fundamental.
- `Layer` delegates to `Oscillator.Advance()` — waveform change is transparent to the layer.
- `ClassFreqConfigs` is a package-level `var` (not `const`) — can be replaced by parameter injection without breaking existing tests.
### Integration Points
- `NewBank(tau)``NewBank(tau, configs map[TrafficClass]FreqConfig)` — single signature change
- `bank.RenderWindow()` iterates `classify.AllClasses()` — must iterate `b.layers` map keys instead
- `encode.RunSynthesis` calls `NewBank(1.0)` — will need to pass config map (Phase 6 concern, but seam established here)
</code_context>
<specifics>
## Specific Ideas
No specific requirements — standard bandlimited synthesis approach with 8-12 partials as user requested.
</specifics>
<deferred>
## Deferred Ideas
None — discussion stayed within phase scope.
</deferred>
---
*Phase: 05-waveform-types-and-bank-decoupling*
*Context gathered: 2026-03-26*
@@ -0,0 +1,58 @@
# Phase 5: Waveform Types and Bank Decoupling - Discussion Log
> **Audit trail only.** Do not use as input to planning, research, or execution agents.
> Decisions are captured in CONTEXT.md — this log preserves the alternatives considered.
**Date:** 2026-03-26
**Phase:** 05-waveform-types-and-bank-decoupling
**Areas discussed:** Waveform presets, GainPerLayer scaling
---
## Waveform presets
### Harmonic richness
| Option | Description | Selected |
|--------|-------------|----------|
| Bandlimited (8-12 partials) | Accurate waveform shapes, no aliasing. Standard for quality synthesis. | ✓ |
| Lightweight (4-6 partials) | Recognizably different but softer/rounder. Less CPU. | |
| You decide | Claude picks based on Nyquist and ambient use case | |
**User's choice:** Bandlimited (8-12 partials)
**Notes:** None
### Built-in class harmonics
| Option | Description | Selected |
|--------|-------------|----------|
| Keep current harmonics | Built-in classes retain hand-tuned arrays. Waveform presets only via config. | |
| Migrate to sine preset | Switch to pure fundamental. Simpler but loses v1.0 character. | |
| You decide | Claude picks best approach for preserving v1.0 sound | ✓ |
**User's choice:** You decide (Claude's Discretion)
**Notes:** None
---
## GainPerLayer scaling
| Option | Description | Selected |
|--------|-------------|----------|
| Fix now in Phase 5 | Compute dynamically as 1/len(layers). Clean foundation for Phase 7. | ✓ |
| Defer to Phase 7 | Keep NumLayers=14 constant. Fix when user classes land. | |
| You decide | Claude picks timing based on complexity | |
**User's choice:** Fix now in Phase 5
**Notes:** None
---
## Claude's Discretion
- Built-in class harmonics migration strategy (D-03)
- Bank config injection API design (D-05)
## Deferred Ideas
None