# math_wave Color Strip Source — Implementation Plan ## Overview A new CSS type that generates LED colors from configurable mathematical wave functions. Each LED position gets a wave value based on spatial position and time, mapped to a color via a gradient palette. Supports multiple superimposed wave layers, sync clocks, and bindable parameters. ## Requirements - Waveform types: sine, triangle, sawtooth, square - Parameters per wave layer: waveform, frequency, amplitude, phase, offset - Global parameters: speed (bindable), gradient_id (color mapping) - Wave superposition: list of wave layers combined additively - Spatial dimension: wave value depends on LED position (0.0-1.0) + time - Sync clock integration for time parameter - Color mapping: combined wave output (0.0-1.0) mapped through a gradient ## Phase 1: Storage Model **File: `server/src/wled_controller/storage/color_strip_source.py`** - Add `MathWaveColorStripSource` dataclass after `GameEventColorStripSource` - Fields: - `waves: list` — default `[{"waveform": "sine", "frequency": 1.0, "amplitude": 1.0, "phase": 0.0, "offset": 0.0}]` - `speed: BindableFloat` — default 1.0 - `gradient_id: Optional[str]` — references Gradient entity - Implement `to_dict`, `from_dict`, `create_from_kwargs`, `apply_update` (follow `CandlelightColorStripSource` pattern) - Valid waveforms: `{"sine", "triangle", "sawtooth", "square"}` - Add `"math_wave": MathWaveColorStripSource` to `_SOURCE_TYPE_MAP` ## Phase 2: Stream Implementation **File: `server/src/wled_controller/core/processing/math_wave_stream.py`** (new) - Class `MathWaveColorStripStream(ColorStripStream)` following `CandlelightColorStripStream` pattern - Key methods: `__init__`, `_update_from_source`, `configure`, `start`, `stop`, `get_latest_colors`, `update_source`, `set_clock`, `set_gradient_store` - Animation loop (`_animate_loop`): - Get `t` from clock (if set) or wall clock - For each LED at normalized position `p = i / (N-1)`: - Sum all wave layers: `sum += amplitude * waveform(2*pi*frequency*(p + speed*t) + phase) + offset` - Clamp result to [0.0, 1.0] - Map per-LED values to RGB via gradient LUT - Waveform functions (vectorized with numpy): - `sine`: `0.5 + 0.5 * np.sin(x)` - `triangle`: `2.0 * np.abs(np.mod(x / (2*pi), 1.0) - 0.5)` - `sawtooth`: `np.mod(x / (2*pi), 1.0)` - `square`: `(np.sin(x) >= 0).astype(float)` - Double-buffering pattern (same as candlelight) - Use `self.resolve("speed", self._speed)` for bindable speed - Gradient resolution via `set_gradient_store` pattern ## Phase 3: API Integration **File: `server/src/wled_controller/api/schemas/color_strip_sources.py`** - Add `MathWaveCSSResponse`, `MathWaveCSSCreate`, `MathWaveCSSUpdate` - Add to `ColorStripSourceResponse`, `ColorStripSourceCreate`, `ColorStripSourceUpdate` unions **File: `server/src/wled_controller/core/processing/color_strip_stream_manager.py`** - Import `MathWaveColorStripStream` - Add `"math_wave": MathWaveColorStripStream` to `_SIMPLE_STREAM_MAP` - Existing `set_gradient_store` and `_inject_clock` injection handles it automatically ## Phase 4: Frontend **File: `server/src/wled_controller/static/js/types.ts`** - Add `'math_wave'` to `CSSSourceType` union **File: `server/src/wled_controller/static/js/core/icons.ts`** - Add `math_wave: _svg(P.activity)` to `_colorStripTypeIcons` **File: `server/src/wled_controller/templates/modals/css-editor.html`** - Add `