docs(05): capture phase context
This commit is contained in:
@@ -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
|
||||
Reference in New Issue
Block a user