chore: remove processed-audio-sources plan files
This commit is contained in:
@@ -1,111 +0,0 @@
|
||||
# Feature Context: Processed Audio Sources
|
||||
|
||||
## Configuration
|
||||
- **Development mode:** Automated
|
||||
- **Execution mode:** Orchestrator
|
||||
- **Strategy:** Big Bang
|
||||
- **Build (Python):** `cd server && ruff check src/ tests/ --fix`
|
||||
- **Build (TypeScript):** `cd server && npx tsc --noEmit && npm run build`
|
||||
- **Test:** `cd server && py -3.13 -m pytest tests/ --no-cov -q`
|
||||
|
||||
## Current State
|
||||
Phases 1-6 implemented. Phase 6 (Frontend Source Types) cleaned up the modal HTML and i18n keys for the new capture/processed source types.
|
||||
|
||||
Phase 1 framework:
|
||||
- `AudioFilter` base class, `AudioFilterRegistry`, `AudioFilterOptionDef` in `core/audio/filters/`
|
||||
- `AudioProcessingTemplate` dataclass + `AudioProcessingTemplateStore` (SQLite-backed) in `storage/`
|
||||
- `audio_filter_template` meta-filter with recursive resolution
|
||||
- Full REST API: CRUD templates + filter registry discovery
|
||||
- Dependency injection wired in `dependencies.py` and `main.py`
|
||||
|
||||
Phase 2 filters (12 total registered, 11 real + 1 meta):
|
||||
- Stateless: `channel_extract`, `band_extract`, `gain`, `inverter`
|
||||
- Stateful: `peak_hold`, `noise_gate`, `envelope_follower`, `spectral_smoothing`, `compressor`, `beat_gate`, `delay`
|
||||
- All produce new `AudioAnalysis` via `dataclasses.replace()` (immutability preserved)
|
||||
|
||||
## Key Architecture Reference
|
||||
|
||||
### Existing Pattern to Mirror: Processed Picture Sources
|
||||
- `ProcessedPictureSource` references `source_stream_id` + `postprocessing_template_id`
|
||||
- `PostprocessingTemplate` contains ordered `List[FilterInstance]`
|
||||
- `FilterInstance` = `filter_id` (string) + `options` (dict)
|
||||
- `FilterRegistry` handles registration, lookup, instantiation
|
||||
- `filter_template` meta-filter embeds one template inside another
|
||||
- `PostprocessingTemplateStore` has `resolve_filter_instances()` for recursive expansion
|
||||
- Picture filters transform images; audio filters will transform `AudioAnalysis`
|
||||
|
||||
### Current Audio Source Types (Phase 3 complete)
|
||||
- `CaptureAudioSource` (source_type="capture") — wraps a physical audio device
|
||||
- `ProcessedAudioSource` (source_type="processed") — references audio_source_id + audio_processing_template_id
|
||||
- `MonoAudioSource` — removed, replaced by channel_extract filter
|
||||
- `BandExtractAudioSource` — removed, replaced by band_extract filter
|
||||
|
||||
### AudioAnalysis Structure (filter input/output)
|
||||
```python
|
||||
AudioAnalysis:
|
||||
timestamp: float
|
||||
rms: float # Overall RMS level
|
||||
peak: float # Peak amplitude
|
||||
spectrum: np.ndarray[64] # Log-spaced FFT bands
|
||||
beat: bool # Beat detected
|
||||
beat_intensity: float # 0-1 beat strength
|
||||
left_rms: float # Left channel RMS
|
||||
left_spectrum: np.ndarray # Left channel spectrum
|
||||
right_rms: float # Right channel RMS
|
||||
right_spectrum: np.ndarray # Right channel spectrum
|
||||
```
|
||||
|
||||
### Key Existing Files
|
||||
- `storage/audio_source.py` — current source dataclasses
|
||||
- `storage/audio_source_store.py` — CRUD + resolve_audio_source()
|
||||
- `core/audio/analysis.py` — AudioAnalyzer, AudioAnalysis
|
||||
- `core/audio/band_filter.py` — existing band filtering logic
|
||||
- `core/processing/audio_stream.py` — AudioColorStripStream
|
||||
- `core/processing/value_stream.py` — AudioValueStream
|
||||
- `core/filters/base.py` — PostprocessingFilter (picture filter base class)
|
||||
- `core/filters/registry.py` — FilterRegistry (picture filters)
|
||||
- `storage/postprocessing_template.py` — PostprocessingTemplate dataclass
|
||||
- `storage/postprocessing_template_store.py` — template store with resolve_filter_instances()
|
||||
|
||||
## Temporary Workarounds
|
||||
_(none yet)_
|
||||
|
||||
## Cross-Phase Dependencies
|
||||
- Phase 2 depends on Phase 1 (filter framework)
|
||||
- Phase 3 depends on Phase 1 (template store for ProcessedAudioSource)
|
||||
- Phase 4 depends on Phases 1-3 (all backend pieces)
|
||||
- Phase 5 depends on Phase 1 (template API)
|
||||
- Phase 6 depends on Phase 3 (source type API)
|
||||
- Phase 7 depends on all prior phases
|
||||
|
||||
## Deferred Work
|
||||
_(none yet)_
|
||||
|
||||
## Failed Approaches
|
||||
_(none yet)_
|
||||
|
||||
## Review Findings Log
|
||||
_(none yet)_
|
||||
|
||||
## Phase Execution Log
|
||||
| Phase | Agent Used | Test Writer | Parallel | Notes |
|
||||
|-------|-----------|-------------|----------|-------|
|
||||
| Phase 1 | impl-agent | — | No | Tasks 7+8 skipped (SQLite migration made them obsolete) |
|
||||
| Phase 2 | impl-agent | — | No | All 11 filters implemented, no deviations |
|
||||
| Phase 3 | impl-agent | — | No | All 11 tasks done; channel/band logic deferred to Phase 4 |
|
||||
| Phase 4 | impl-agent | — | No | All 6 tasks done; dependency injection threaded through |
|
||||
| Phase 5 | impl-agent | — | No | 6/7 tasks done; Task 4 (preview) deferred to Phase 7 |
|
||||
| Phase 6 | impl-agent | — | No | Modal HTML + i18n cleanup; most tasks already done in Phases 3/5 |
|
||||
| Phase 7 | — | — | — | — |
|
||||
|
||||
## Environment & Runtime Notes
|
||||
- Platform: Windows 10
|
||||
- Python: 3.13
|
||||
- Server port: 8080
|
||||
- Shell: bash (Git Bash on Windows)
|
||||
|
||||
## Implementation Notes
|
||||
- Clean-slate approach: no migration of existing MonoAudioSource/BandExtractAudioSource data
|
||||
- 7 of 11 filters are stateful (peak hold, noise gate, envelope follower, spectral smoothing, compressor, beat gate, delay) — need per-stream instance lifecycle
|
||||
- Audio filters operate on AudioAnalysis snapshots, not raw audio samples
|
||||
- Big Bang strategy: intermediate phases may break the build; only Phase 7 enforces build/tests
|
||||
@@ -1,55 +0,0 @@
|
||||
# Feature: Processed Audio Sources
|
||||
|
||||
**Branch:** `feature/processed-audio-sources`
|
||||
**Base branch:** `master`
|
||||
**Created:** 2026-03-31
|
||||
**Status:** 🟡 In Progress
|
||||
**Strategy:** Big Bang
|
||||
**Mode:** Automated
|
||||
**Execution:** Orchestrator
|
||||
|
||||
## Summary
|
||||
|
||||
Replace hardcoded `MonoAudioSource` and `BandExtractAudioSource` types with a composable
|
||||
**ProcessedAudioSource + AudioProcessingTemplate + AudioFilter** system — mirroring the
|
||||
existing processed picture source pattern. Rename `MultichannelAudioSource` to
|
||||
`CaptureAudioSource`. Adds 11 audio filters: channel extract, band extract, peak hold,
|
||||
gain, noise gate, envelope follower, spectral smoothing, compressor, inverter, beat gate,
|
||||
and delay.
|
||||
|
||||
Clean-slate approach: no data migration for old source types.
|
||||
|
||||
## Build & Test Commands
|
||||
- **Build (Python):** `cd server && ruff check src/ tests/ --fix`
|
||||
- **Build (TypeScript):** `cd server && npx tsc --noEmit && npm run build`
|
||||
- **Test:** `cd server && py -3.13 -m pytest tests/ --no-cov -q`
|
||||
|
||||
## Phases
|
||||
|
||||
- [ ] Phase 1: Audio Filter Framework [domain: backend] → [subplan](./phase-1-audio-filter-framework.md)
|
||||
- [ ] Phase 2: Audio Filters [domain: backend] → [subplan](./phase-2-audio-filters.md)
|
||||
- [ ] Phase 3: Processed Audio Source Model [domain: backend] → [subplan](./phase-3-processed-audio-source-model.md)
|
||||
- [ ] Phase 4: Runtime Integration [domain: backend] → [subplan](./phase-4-runtime-integration.md)
|
||||
- [ ] Phase 5: Frontend — Audio Processing Templates [domain: frontend] → [subplan](./phase-5-frontend-templates.md)
|
||||
- [ ] Phase 6: Frontend — Source Types [domain: frontend] → [subplan](./phase-6-frontend-source-types.md)
|
||||
- [ ] Phase 7: Testing & Polish [domain: backend] → [subplan](./phase-7-testing-polish.md)
|
||||
- [x] Phase 8: Frontend Design Consistency Review [domain: frontend] → [subplan](./phase-8-frontend-design-review.md)
|
||||
|
||||
## Phase Progress Log
|
||||
|
||||
| Phase | Domain | Status | Review | Build | Committed |
|
||||
|-------|--------|--------|--------|-------|-----------|
|
||||
| Phase 1: Audio Filter Framework | backend | ✅ Done | ✅ | ⏭️ | ✅ |
|
||||
| Phase 2: Audio Filters | backend | ✅ Done | ✅ | ⏭️ | ✅ |
|
||||
| Phase 3: Processed Audio Source Model | backend | ✅ Done | ✅ | ⏭️ | ✅ |
|
||||
| Phase 4: Runtime Integration | backend | ✅ Done | ✅ | ⏭️ | ✅ |
|
||||
| Phase 5: Frontend — Audio Processing Templates | frontend | ✅ Done | ✅ | ⏭️ | ✅ |
|
||||
| Phase 6: Frontend — Source Types | frontend | ✅ Done | ✅ | ⏭️ | ✅ |
|
||||
| Phase 7: Testing & Polish | backend | ✅ Done | — | ✅ | ✅ |
|
||||
| Phase 8: Frontend Design Review | frontend | ✅ Done | ✅ | ✅ | ⬜ |
|
||||
|
||||
## Final Review
|
||||
- [ ] Comprehensive code review
|
||||
- [ ] Full build passes
|
||||
- [ ] Full test suite passes
|
||||
- [ ] Merged to `master`
|
||||
@@ -1,106 +0,0 @@
|
||||
# Phase 1: Audio Filter Framework
|
||||
|
||||
**Status:** 🔨 In Progress
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
## Objective
|
||||
Build the foundation for audio processing: base filter class, registry, template storage, and API endpoints. This mirrors the existing picture filter/postprocessing template system.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] Task 1: Create `AudioFilter` base class in `core/audio/filters/base.py`
|
||||
- Abstract `process(analysis: AudioAnalysis) -> AudioAnalysis` method
|
||||
- `is_stateful` property (False by default, overridden by stateful filters)
|
||||
- `reset()` method for stateful filters
|
||||
- `AudioFilterOptionDef` class for declaring filter option schemas (mirrors `FilterOptionDef` from picture filters)
|
||||
- Class-level `filter_id`, `name`, `description`, `options` declarations
|
||||
- [x] Task 2: Create `AudioFilterRegistry` in `core/audio/filters/registry.py`
|
||||
- `register(filter_class)` — register by filter_id
|
||||
- `get_filter_class(filter_id)` — lookup
|
||||
- `create_instance(filter_id, options)` → instantiated AudioFilter
|
||||
- `get_available_filters()` → list of filter metadata + option schemas
|
||||
- Mirrors `FilterRegistry` from `core/filters/registry.py`
|
||||
- [x] Task 3: Create `AudioProcessingTemplate` dataclass in `storage/audio_processing_template.py`
|
||||
- Fields: `id`, `name`, `filters: List[FilterInstance]`, `description`, `tags`, `created_at`, `updated_at`
|
||||
- Reuse existing `FilterInstance` from `core/filters/filter_instance.py`
|
||||
- ID prefix: `apt_` (audio processing template)
|
||||
- [x] Task 4: Create `AudioProcessingTemplateStore` in `storage/audio_processing_template_store.py`
|
||||
- SQLite-backed CRUD (same pattern as `PostprocessingTemplateStore`)
|
||||
- `resolve_filter_instances()` — recursive expansion of `audio_filter_template` meta-filter
|
||||
- Cycle detection in template composition
|
||||
- Reference validation (check filter_ids exist in registry)
|
||||
- [x] Task 5: Create `audio_filter_template` meta-filter in `core/audio/filters/audio_filter_template.py`
|
||||
- Option: `template_id` referencing another AudioProcessingTemplate
|
||||
- Never instantiated at runtime — expanded during resolution
|
||||
- Mirrors `filter_template` from picture filters
|
||||
- [x] Task 6: Create `core/audio/filters/__init__.py` — register all filters with the registry
|
||||
- [x] Task 7: ~~Add `audio_processing_templates_file` to `StorageConfig` in `config.py`~~ SKIPPED — storage uses SQLite now, not JSON files. No config change needed.
|
||||
- [x] Task 8: ~~Add audio processing templates to `STORE_MAP` in `api/routes/system.py`~~ SKIPPED — STORE_MAP no longer exists. Backup/restore works at the SQLite database level; new tables are automatically included.
|
||||
- [x] Task 9: Create API schemas in `api/schemas/audio_processing.py`
|
||||
- `AudioProcessingTemplateCreate`, `AudioProcessingTemplateUpdate`, `AudioProcessingTemplateResponse`
|
||||
- `AudioFilterInstanceSchema` (reuse `FilterInstanceSchema` from existing schemas)
|
||||
- [x] Task 10: Create API routes in `api/routes/audio_processing_templates.py`
|
||||
- `GET /api/v1/audio-processing-templates` — list all
|
||||
- `POST /api/v1/audio-processing-templates` — create
|
||||
- `GET /api/v1/audio-processing-templates/{template_id}` — get one
|
||||
- `PUT /api/v1/audio-processing-templates/{template_id}` — update
|
||||
- `DELETE /api/v1/audio-processing-templates/{template_id}` — delete (with ref checks placeholder)
|
||||
- [x] Task 11: Create filter registry endpoint in `api/routes/audio_filters.py`
|
||||
- `GET /api/v1/audio-filters` — returns available filters with option schemas
|
||||
- Dynamically populates `audio_filter_template` options with current template IDs
|
||||
- [x] Task 12: Register new routes in the FastAPI app
|
||||
|
||||
## Files to Modify/Create
|
||||
- `core/audio/filters/base.py` — **created** — AudioFilter base class + AudioFilterOptionDef
|
||||
- `core/audio/filters/registry.py` — **created** — AudioFilterRegistry
|
||||
- `core/audio/filters/audio_filter_template.py` — **created** — meta-filter
|
||||
- `core/audio/filters/__init__.py` — **created** — filter registration
|
||||
- `storage/audio_processing_template.py` — **created** — dataclass
|
||||
- `storage/audio_processing_template_store.py` — **created** — store
|
||||
- `api/schemas/audio_processing.py` — **created** — Pydantic schemas
|
||||
- `api/routes/audio_processing_templates.py` — **created** — template CRUD routes
|
||||
- `api/routes/audio_filters.py` — **created** — filter registry endpoint
|
||||
- `api/dependencies.py` — **modified** — added getter + init param for audio_processing_template_store
|
||||
- `api/__init__.py` — **modified** — registered new routers
|
||||
- `main.py` — **modified** — created store instance, imported audio filter package, wired to init_dependencies
|
||||
|
||||
## Acceptance Criteria
|
||||
- AudioFilter base class exists with process/reset/options API
|
||||
- AudioFilterRegistry can register, lookup, and instantiate filters
|
||||
- AudioProcessingTemplate can be created, read, updated, deleted via API
|
||||
- `audio_filter_template` meta-filter is handled during resolution (recursive expansion)
|
||||
- Filter registry endpoint returns available filters with option schemas
|
||||
- Backup/restore includes audio processing templates (automatic via SQLite)
|
||||
|
||||
## Notes
|
||||
- Reuse `FilterInstance` from `core/filters/filter_instance.py` — no need to create a separate one for audio
|
||||
- The `audio_filter_template` meta-filter option should dynamically list available template IDs (like the picture filter version)
|
||||
- Phase 2 will register the actual filters; this phase just sets up the framework with only the meta-filter registered
|
||||
- Tasks 7 and 8 from original plan were skipped — the codebase migrated from JSON files to SQLite since the plan was written
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
|
||||
### What was built
|
||||
- Complete audio filter framework: `AudioFilter` base class, `AudioFilterRegistry`, `AudioFilterOptionDef`
|
||||
- `AudioProcessingTemplate` dataclass + `AudioProcessingTemplateStore` (SQLite-backed CRUD)
|
||||
- `audio_filter_template` meta-filter with recursive resolution and cycle detection
|
||||
- Full REST API: CRUD for templates + filter registry discovery endpoint
|
||||
- Dependency injection wired through `dependencies.py` and `main.py`
|
||||
|
||||
### What Phase 2 needs to know
|
||||
- Register new audio filters by importing them in `core/audio/filters/__init__.py` and decorating with `@AudioFilterRegistry.register`
|
||||
- Each filter implements `process(analysis: AudioAnalysis) -> AudioAnalysis`
|
||||
- Stateful filters override `is_stateful` property to return `True` and implement `reset()`
|
||||
- The `AudioFilterOptionDef` class mirrors `FilterOptionDef` exactly (same option_type values, same validation logic)
|
||||
|
||||
### Known deviations from plan
|
||||
- Tasks 7 and 8 skipped: `StorageConfig` no longer holds per-entity file paths (SQLite migration), and `STORE_MAP` no longer exists (database-level backup/restore)
|
||||
- Delete endpoint has a TODO placeholder for reference checks — Phase 3 will add `ProcessedAudioSource` which references templates
|
||||
@@ -1,114 +0,0 @@
|
||||
# Phase 2: Audio Filters
|
||||
|
||||
**Status:** 🔨 In Progress
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
## Objective
|
||||
Implement all 11 audio filters and register them with the AudioFilterRegistry.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] Task 1: **Channel Extract** filter (`core/audio/filters/channel_extract.py`)
|
||||
- Options: `channel` (select: mono | left | right)
|
||||
- Stateful: No
|
||||
- Behavior: Replaces main rms/spectrum with selected channel data. If "mono", averages L+R. If "left"/"right", copies that channel's data to the main fields.
|
||||
- [x] Task 2: **Band Extract** filter (`core/audio/filters/band_extract.py`)
|
||||
- Options: `band` (select: bass | mid | treble | custom), `freq_low` (float, 20-20000), `freq_high` (float, 20-20000)
|
||||
- Stateful: No
|
||||
- Behavior: Computes a band mask for the 64 log-spaced bins, applies it to spectrum, recomputes RMS from in-band data. Reuse logic from existing `core/audio/band_filter.py`.
|
||||
- Presets: bass=20-250Hz, mid=250-4000Hz, treble=4000-20000Hz
|
||||
- [x] Task 3: **Peak Hold** filter (`core/audio/filters/peak_hold.py`)
|
||||
- Options: `decay_rate` (float, 0.1-50.0, dB/s), `per_bin` (bool, default true)
|
||||
- Stateful: Yes
|
||||
- Behavior: For each spectrum bin (if per_bin) or for rms/peak, retains the maximum value seen and decays it over time. Outputs the max of current value and held peak.
|
||||
- [x] Task 4: **Gain** filter (`core/audio/filters/gain.py`)
|
||||
- Options: `factor` (float, 0.1-10.0, default 1.0)
|
||||
- Stateful: No
|
||||
- Behavior: Multiplies rms, peak, spectrum, and per-channel values by factor. Clamps to [0, 1] for rms/peak.
|
||||
- [x] Task 5: **Noise Gate** filter (`core/audio/filters/noise_gate.py`)
|
||||
- Options: `threshold` (float, 0.0-1.0), `hysteresis` (float, 0.0-0.2, default 0.05)
|
||||
- Stateful: No (hysteresis is stateless — it's a secondary threshold, not temporal)
|
||||
- Behavior: If rms < threshold, zeros out all levels and spectrum. Hysteresis means: if gate was open and rms drops below (threshold - hysteresis), close it; if gate was closed and rms rises above threshold, open it.
|
||||
- Actually stateful for hysteresis tracking: needs to remember gate open/closed state.
|
||||
- [x] Task 6: **Envelope Follower** filter (`core/audio/filters/envelope_follower.py`)
|
||||
- Options: `attack_ms` (float, 1-500, default 10), `release_ms` (float, 10-2000, default 200)
|
||||
- Stateful: Yes
|
||||
- Behavior: Smooths rms and peak with asymmetric time constants. When signal rises, uses attack rate. When signal falls, uses release rate. Applied per-bin to spectrum optionally.
|
||||
- Fast attack + slow release = punchy transients that fade smoothly.
|
||||
- [x] Task 7: **Spectral Smoothing** filter (`core/audio/filters/spectral_smoothing.py`)
|
||||
- Options: `factor` (float, 0.0-0.99, default 0.5)
|
||||
- Stateful: Yes (maintains previous spectrum state)
|
||||
- Behavior: Applies exponential moving average per-bin: `smoothed[i] = factor * prev[i] + (1-factor) * current[i]`. Higher factor = smoother/slower.
|
||||
- [x] Task 8: **Compressor** filter (`core/audio/filters/compressor.py`)
|
||||
- Options: `threshold` (float, 0.0-1.0, default 0.5), `ratio` (float, 1.0-20.0, default 4.0), `makeup_gain` (float, 0.0-2.0, default 1.0)
|
||||
- Stateful: Yes (envelope tracking for gain reduction)
|
||||
- Behavior: When signal exceeds threshold, reduces by ratio. `output = threshold + (input - threshold) / ratio`. Apply makeup_gain after. Applied to rms, peak, and spectrum.
|
||||
- [x] Task 9: **Inverter** filter (`core/audio/filters/inverter.py`)
|
||||
- Options: none (or `invert_spectrum` bool, default true)
|
||||
- Stateful: No
|
||||
- Behavior: `rms = 1.0 - rms`, `peak = 1.0 - peak`, spectrum bins inverted if option set. Beat fields unchanged.
|
||||
- [x] Task 10: **Beat Gate** filter (`core/audio/filters/beat_gate.py`)
|
||||
- Options: `hold_ms` (float, 10-500, default 50) — how long to hold signal after beat
|
||||
- Stateful: Yes (tracks last beat timestamp)
|
||||
- Behavior: When beat detected, passes signal through for `hold_ms` milliseconds. Between beats, zeros out rms/peak/spectrum. Beat fields themselves always pass through.
|
||||
- [x] Task 11: **Delay** filter (`core/audio/filters/delay.py`)
|
||||
- Options: `delay_ms` (float, 10-2000, default 100)
|
||||
- Stateful: Yes (ring buffer of AudioAnalysis snapshots)
|
||||
- Behavior: Buffers incoming AudioAnalysis snapshots and outputs the one from `delay_ms` ago. Ring buffer sized based on ~30Hz update rate.
|
||||
- [x] Task 12: Register all 11 filters in `core/audio/filters/__init__.py`
|
||||
- [x] Task 13: Update Noise Gate to be stateful (hysteresis requires gate state tracking)
|
||||
|
||||
## Files to Modify/Create
|
||||
- `core/audio/filters/channel_extract.py` — **create**
|
||||
- `core/audio/filters/band_extract.py` — **create**
|
||||
- `core/audio/filters/peak_hold.py` — **create**
|
||||
- `core/audio/filters/gain.py` — **create**
|
||||
- `core/audio/filters/noise_gate.py` — **create**
|
||||
- `core/audio/filters/envelope_follower.py` — **create**
|
||||
- `core/audio/filters/spectral_smoothing.py` — **create**
|
||||
- `core/audio/filters/compressor.py` — **create**
|
||||
- `core/audio/filters/inverter.py` — **create**
|
||||
- `core/audio/filters/beat_gate.py` — **create**
|
||||
- `core/audio/filters/delay.py` — **create**
|
||||
- `core/audio/filters/__init__.py` — **modify** — register all filters
|
||||
|
||||
## Acceptance Criteria
|
||||
- All 11 filters are implemented and registered
|
||||
- Each filter correctly transforms AudioAnalysis according to its specification
|
||||
- Stateful filters (peak hold, envelope follower, spectral smoothing, compressor, beat gate, delay, noise gate) properly maintain and reset state
|
||||
- Filter option schemas are complete and accurate
|
||||
- All filters are accessible via `GET /api/v1/audio-filters`
|
||||
|
||||
## Notes
|
||||
- 6 stateful filters: peak hold, envelope follower, spectral smoothing, compressor, beat gate, delay. Noise gate is also stateful due to hysteresis.
|
||||
- Band extract can reuse math from existing `core/audio/band_filter.py` — `compute_band_mask()` and `apply_band_filter()`
|
||||
- Filters must produce a NEW AudioAnalysis (immutability principle), not mutate the input
|
||||
- For delay filter, ring buffer size = `delay_ms / (1000 / update_rate)`. At 30Hz, 2000ms delay = 60 slots.
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
|
||||
### What was built
|
||||
- All 11 audio filters implemented, each in its own file under `core/audio/filters/`
|
||||
- 7 stateful filters (peak_hold, noise_gate, envelope_follower, spectral_smoothing, compressor, beat_gate, delay) with proper `is_stateful` and `reset()` implementations
|
||||
- 4 stateless filters (channel_extract, band_extract, gain, inverter)
|
||||
- All filters registered in `__init__.py` via import-triggered `@AudioFilterRegistry.register`
|
||||
- All filters produce NEW AudioAnalysis via `dataclasses.replace()` (immutability preserved)
|
||||
- Band extract reuses existing `compute_band_mask()` and `apply_band_filter()` from `core/audio/band_filter.py`
|
||||
|
||||
### What Phase 3 needs to know
|
||||
- All 11 filters + the `audio_filter_template` meta-filter are now registered in the AudioFilterRegistry (12 total)
|
||||
- `GET /api/v1/audio-filters` will return all filters with their option schemas
|
||||
- Filters are instantiated via `AudioFilterRegistry.create_instance(filter_id, options)`
|
||||
- Stateful filters need per-stream instances (not shared) due to internal state
|
||||
- The `process()` method signature is `process(analysis: AudioAnalysis) -> AudioAnalysis`
|
||||
|
||||
### Known deviations from plan
|
||||
- None. All 11 filters implemented exactly as specified plus Task 13 (noise gate stateful).
|
||||
@@ -1,116 +0,0 @@
|
||||
# Phase 3: Processed Audio Source Model
|
||||
|
||||
**Status:** ✅ Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
## Objective
|
||||
Add the `ProcessedAudioSource` type, rename `MultichannelAudioSource` to `CaptureAudioSource`, remove `MonoAudioSource` and `BandExtractAudioSource`, and update the store's resolution logic.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] Task 1: Rename `MultichannelAudioSource` → `CaptureAudioSource` in `storage/audio_source.py`
|
||||
- Change class name, update `source_type` default to `"capture"`
|
||||
- Same fields: `device_index`, `is_loopback`, `audio_template_id`
|
||||
- [x] Task 2: Add `ProcessedAudioSource` dataclass in `storage/audio_source.py`
|
||||
- Fields: `audio_source_id: str` (input source), `audio_processing_template_id: str`
|
||||
- `source_type` = `"processed"`
|
||||
- Inherits standard base fields (id, name, description, tags, created_at, updated_at)
|
||||
- [x] Task 3: Remove `MonoAudioSource` class entirely
|
||||
- [x] Task 4: Remove `BandExtractAudioSource` class entirely
|
||||
- [x] Task 5: Update `create_audio_source()` factory function to handle new types
|
||||
- [x] Task 6: Update `AudioSourceStore` resolution logic:
|
||||
- `resolve_audio_source()` now returns: device info (from CaptureAudioSource at chain end) + ordered list of filter chains (from AudioProcessingTemplates along the chain)
|
||||
- Walk chain: ProcessedAudioSource → ... → CaptureAudioSource
|
||||
- Collect all audio_processing_template_ids in order
|
||||
- Cycle detection for ProcessedAudioSource chains
|
||||
- [x] Task 7: Update `ResolvedAudioSource` dataclass:
|
||||
- Remove `channel` and `freq_low`/`freq_high` fields (handled by filters now)
|
||||
- Add `audio_processing_template_ids: List[str]` — ordered list of template IDs along the chain
|
||||
- [x] Task 8: Update reference validation in store:
|
||||
- `ProcessedAudioSource.audio_source_id` must reference an existing audio source
|
||||
- `ProcessedAudioSource.audio_processing_template_id` must reference an existing template
|
||||
- Delete checks: can't delete a source referenced by another ProcessedAudioSource
|
||||
- Added `get_sources_referencing_template()` helper for template delete checks
|
||||
- [x] Task 9: Update API schemas in `api/schemas/audio_sources.py`
|
||||
- Remove `MonoAudioSourceCreate/Update/Response` schemas
|
||||
- Remove `BandExtractAudioSourceCreate/Update/Response` schemas
|
||||
- Add `CaptureAudioSourceCreate/Update/Response` (rename from Multichannel)
|
||||
- Add `ProcessedAudioSourceCreate/Update/Response`
|
||||
- Update discriminated union to use new type literals
|
||||
- [x] Task 10: Update API routes in `api/routes/audio_sources.py`
|
||||
- Handle new source types in create/update endpoints
|
||||
- Remove handling of old types
|
||||
- Update WebSocket test endpoint to work with new resolution (no channel/band)
|
||||
- [x] Task 11: Update any imports/references across the codebase that reference the old types
|
||||
|
||||
## Files to Modify/Create
|
||||
- `storage/audio_source.py` — **modify** — rename, add, remove dataclasses
|
||||
- `storage/audio_source_store.py` — **modify** — new resolution logic, validation
|
||||
- `storage/audio_template_store.py` — **modify** — CaptureAudioSource import
|
||||
- `api/schemas/audio_sources.py` — **modify** — new schemas
|
||||
- `api/routes/audio_sources.py` — **modify** — handle new types
|
||||
- `core/processing/audio_stream.py` — **modify** — remove channel/band logic
|
||||
- `core/processing/value_stream.py` — **modify** — remove channel logic
|
||||
- `core/demo_seed.py` — **modify** — update demo data to new types
|
||||
- `storage/color_strip_source.py` — **modify** — update comment
|
||||
- `storage/value_source.py` — **modify** — update comment
|
||||
- `static/js/types.ts` — **modify** — new TS interfaces
|
||||
- `static/js/core/icons.ts` — **modify** — new icon mapping
|
||||
- `static/js/core/graph-nodes.ts` — **modify** — new icon mapping
|
||||
- `static/js/features/audio-sources.ts` — **modify** — new source types
|
||||
- `static/js/features/streams.ts` — **modify** — new card sections
|
||||
- `static/js/features/value-sources.ts` — **modify** — badge text
|
||||
- `static/js/features/color-strips.ts` — **modify** — badge text, navigation
|
||||
- `static/js/core/command-palette.ts` — **modify** — navigation mapping
|
||||
|
||||
## Acceptance Criteria
|
||||
- [x] `CaptureAudioSource` replaces `MultichannelAudioSource` (same behavior, new name/type)
|
||||
- [x] `ProcessedAudioSource` can be created referencing a source + template
|
||||
- [x] `MonoAudioSource` and `BandExtractAudioSource` are fully removed
|
||||
- [x] Chain resolution walks ProcessedAudioSource → ... → CaptureAudioSource correctly
|
||||
- [x] Cycle detection prevents circular source references
|
||||
- [x] Reference validation prevents dangling references
|
||||
- [x] API accepts/returns new type discriminators
|
||||
|
||||
## Notes
|
||||
- Clean-slate: no migration of existing data. Old source type records will be lost.
|
||||
- The `source_type` string changes from `"multichannel"` to `"capture"` — this is a breaking change but acceptable for clean-slate.
|
||||
- `ResolvedAudioSource` is consumed by `AudioColorStripStream` and `AudioValueStream` — they will need updates in Phase 4.
|
||||
- Template reference checks in the store need coordination with `AudioProcessingTemplateStore` — may need to pass it as a dependency.
|
||||
|
||||
## Review Checklist
|
||||
- [x] All tasks completed
|
||||
- [x] Code follows project conventions
|
||||
- [x] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
|
||||
### What was built
|
||||
- `CaptureAudioSource` replaces `MultichannelAudioSource` (class + source_type "capture")
|
||||
- `ProcessedAudioSource` added with `audio_source_id` + `audio_processing_template_id` fields
|
||||
- `MonoAudioSource` and `BandExtractAudioSource` fully removed from model, store, schemas, routes, and all frontend references
|
||||
- `ResolvedAudioSource` now returns `audio_processing_template_ids: List[str]` instead of `channel`/`freq_low`/`freq_high`
|
||||
- Chain resolution walks ProcessedAudioSource → ... → CaptureAudioSource, collecting template IDs in order (outermost first)
|
||||
- Cycle detection for both create and update operations
|
||||
- `get_sources_referencing_template()` helper added for template delete checks
|
||||
- All frontend TS files updated: types, icons, card sections, navigation, command palette
|
||||
|
||||
### What Phase 4 needs to know
|
||||
- `ResolvedAudioSource` now has `audio_processing_template_ids` field — Phase 4 must resolve these to `FilterInstance` lists and instantiate/apply them in the stream runtime
|
||||
- `AudioColorStripStream._pick_channel()` currently returns raw `analysis.spectrum, analysis.rms` — Phase 4 must wire filter processing here
|
||||
- `AudioValueStream._pick_rms()` and `_pick_peak()` currently return raw analysis values — Phase 4 must apply filter chain
|
||||
- Both streams store `self._audio_processing_template_ids` for use by Phase 4
|
||||
- The WebSocket test endpoint also needs filter application wired in Phase 4
|
||||
|
||||
### Temporary breakages (resolved in Phase 4)
|
||||
- Channel selection removed from `AudioColorStripStream._pick_channel()` — always uses mono mix
|
||||
- Channel selection removed from `AudioValueStream._pick_rms()` and `_pick_peak()` — always uses mono
|
||||
- These were previously handled by MonoAudioSource/BandExtractAudioSource; now handled by channel_extract/band_extract filters in ProcessedAudioSource chains
|
||||
|
||||
### Known deviations from plan
|
||||
- Task 7: Used `audio_processing_template_ids: List[str]` (template IDs) rather than `filter_instances: List[FilterInstance]` — runtime resolution deferred to Phase 4
|
||||
- Task 8: Template reference validation at create time not implemented (would require injecting AudioProcessingTemplateStore as dependency) — deferred to Phase 4 or Phase 7
|
||||
- Frontend was also updated comprehensively (not just backend) to avoid broken UI
|
||||
@@ -1,94 +0,0 @@
|
||||
# Phase 4: Runtime Integration
|
||||
|
||||
**Status:** ✅ Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
## Objective
|
||||
Wire the audio filter pipeline into the runtime audio streaming system so that ProcessedAudioSources actually apply their filter chains to live audio data.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] Task 1: Create filter pipeline executor in `core/audio/filters/pipeline.py`
|
||||
- `AudioFilterPipeline` class:
|
||||
- `__init__(filter_instances: List[FilterInstance], registry: AudioFilterRegistry)`
|
||||
- Instantiates all filters from FilterInstance specs
|
||||
- `process(analysis: AudioAnalysis) -> AudioAnalysis` — runs analysis through all filters in order
|
||||
- `reset()` — resets all stateful filters
|
||||
- `close()` — cleanup resources
|
||||
- Handles stateful filter lifecycle (create on init, reset on demand, close on cleanup)
|
||||
- [x] Task 2: Update `AudioColorStripStream` in `core/processing/audio_stream.py`
|
||||
- On construction: if source is ProcessedAudioSource, resolve the full chain:
|
||||
- Walk to CaptureAudioSource for device info
|
||||
- Collect all AudioProcessingTemplates along the chain
|
||||
- Resolve all filter instances (with template expansion)
|
||||
- Create AudioFilterPipeline
|
||||
- In render loop: after getting AudioAnalysis from ManagedAudioStream, run it through the filter pipeline before visualization
|
||||
- Remove old inline channel selection and band filtering code (now handled by filters)
|
||||
- On stop: close the filter pipeline
|
||||
- [x] Task 3: Update `AudioValueStream` in `core/processing/value_stream.py`
|
||||
- Same pattern: resolve ProcessedAudioSource chain, create filter pipeline, apply in get_value()
|
||||
- Remove old inline channel/band handling
|
||||
- [x] Task 4: Hot-update support for filter templates
|
||||
- When an AudioProcessingTemplate is updated, running streams that use it should re-resolve their filter pipeline
|
||||
- Listen for template update events (or implement a refresh mechanism)
|
||||
- Re-create AudioFilterPipeline with updated filter instances
|
||||
- Reset stateful filter state on pipeline refresh
|
||||
- [x] Task 5: Update WebSocket test endpoint in `api/routes/audio_sources.py`
|
||||
- For ProcessedAudioSource: resolve chain, create pipeline, apply filters to test stream data
|
||||
- Return filtered analysis in real-time over WebSocket
|
||||
- [x] Task 6: Update any code that calls `AudioSourceStore.resolve_audio_source()` to handle the new return shape
|
||||
|
||||
## Files to Modify/Create
|
||||
- `core/audio/filters/pipeline.py` — **create** — AudioFilterPipeline
|
||||
- `core/processing/audio_stream.py` — **modify** — integrate filter pipeline
|
||||
- `core/processing/value_stream.py` — **modify** — integrate filter pipeline
|
||||
- `api/routes/audio_sources.py` — **modify** — update WebSocket test
|
||||
- Any other consumers of `resolve_audio_source()` — **modify**
|
||||
|
||||
## Acceptance Criteria
|
||||
- ProcessedAudioSource chains are resolved and filter pipelines created at stream start
|
||||
- AudioAnalysis passes through the filter chain before visualization/value extraction
|
||||
- Stateful filters maintain correct state across frames
|
||||
- Hot-update of templates refreshes running filter pipelines
|
||||
- WebSocket test endpoint works with processed sources
|
||||
- Old inline channel/band code removed from stream classes
|
||||
|
||||
## Notes
|
||||
- ⚠️ Temporary breakage: Removing inline channel/band code from AudioColorStripStream breaks existing MonoAudioSource/BandExtractAudioSource flows — but those types were already removed in Phase 3.
|
||||
- Filter pipeline must be thread-safe: AudioColorStripStream and AudioValueStream run in background threads.
|
||||
- For hot-update: consider using an event callback from the template store rather than polling.
|
||||
- The filter pipeline should produce a new AudioAnalysis each time (immutability), not mutate the shared snapshot from ManagedAudioStream.
|
||||
|
||||
## Review Checklist
|
||||
- [x] All tasks completed
|
||||
- [x] Code follows project conventions
|
||||
- [x] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
|
||||
### What was built
|
||||
- `AudioFilterPipeline` class in `core/audio/filters/pipeline.py` — thread-safe pipeline that instantiates, processes, resets, and closes audio filters
|
||||
- `build_pipeline_from_template_ids()` helper — resolves template IDs to FilterInstance lists and creates a pipeline
|
||||
- `AudioColorStripStream` now builds and applies filter pipeline: `_rebuild_filter_pipeline()` called on construction and source update; `_apply_filters()` replaces `_pick_channel()` in render loop; pipeline closed on stop
|
||||
- `AudioValueStream` now builds and applies filter pipeline: `_rebuild_filter_pipeline()` called on construction; filters applied in `_extract_raw()` before scalar extraction; pipeline closed on stop
|
||||
- Hot-update: `ProcessorManager.refresh_audio_filter_pipelines(template_id)` dispatches to both CSS and value stream managers; called from audio processing template update/delete routes
|
||||
- WebSocket test endpoint creates a filter pipeline from the resolved template chain and applies it to analysis before sending
|
||||
- Dependency injection: `audio_processing_template_store` threaded through `ProcessorDependencies` -> `ProcessorManager` -> `ColorStripStreamManager` / `ValueStreamManager` -> `AudioColorStripStream` / `AudioValueStream`
|
||||
|
||||
### What Phase 5 needs to know
|
||||
- The backend is fully wired: creating a ProcessedAudioSource that references templates with channel_extract, band_extract, gain, etc. filters will apply those filters to live audio data
|
||||
- The WebSocket test endpoint shows filtered analysis in real-time
|
||||
- Frontend needs to provide UI for creating/editing AudioProcessingTemplates and ProcessedAudioSources
|
||||
- Filter pipeline is per-stream-instance (not shared) — stateful filters maintain independent state
|
||||
|
||||
### Temporary breakages resolved
|
||||
- `_pick_channel()` removed from AudioColorStripStream — replaced by `_apply_filters()` which uses the filter pipeline
|
||||
- Channel/band handling in AudioValueStream now goes through filter pipeline
|
||||
- All "Phase 4 will wire..." comments resolved
|
||||
|
||||
### Known deviations from plan
|
||||
- `AudioFilterPipeline.__init__` takes `List[FilterInstance]` only (not `AudioFilterRegistry` — uses the class-level registry directly via `AudioFilterRegistry.create_instance()`)
|
||||
- Hot-update uses explicit method calls from the route handler rather than an event-listener pattern — simpler and avoids the need for a subscription system
|
||||
@@ -1,97 +0,0 @@
|
||||
# Phase 5: Frontend — Audio Processing Templates
|
||||
|
||||
**Status:** ✅ Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Build the frontend UI for managing Audio Processing Templates — list, create, edit, delete, with a filter editor and real-time preview.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] Task 1: Create TypeScript module `static/js/features/audio-processing-templates.ts`
|
||||
- Fetch/cache audio processing templates via DataCache
|
||||
- CRUD operations using fetchWithAuth
|
||||
- CardSection for template list with reconciliation
|
||||
- [x] Task 2: Create template editor modal
|
||||
- Name, description, tags fields
|
||||
- Ordered filter list with add/remove/reorder controls
|
||||
- Per-filter option controls (sliders, selects, toggles) driven by option schemas from `GET /api/v1/audio-filters`
|
||||
- Template composition support: `audio_filter_template` shows EntitySelect for sub-template
|
||||
- Dirty check via snapshotValues()
|
||||
- [x] Task 3: Add Audio Processing Templates section to the Streams tab
|
||||
- New sub-tab alongside existing Audio Sources
|
||||
- CardSection rendering with template name, filter count, description
|
||||
- Create/Edit/Delete actions per card
|
||||
- [ ] Task 4: Real-time audio preview — **DEFERRED to Phase 7**
|
||||
- Too complex for this phase; requires WebSocket plumbing and source selection
|
||||
- The audio source test modal already provides spectrum visualization
|
||||
- [x] Task 5: Add i18n keys for all new UI strings (en.json, ru.json, zh.json)
|
||||
- Template section labels, filter names, option labels, buttons, errors
|
||||
- [x] Task 6: Register module in `app.ts` / global exports for inline onclick handlers
|
||||
- [x] Task 7: Fetch and cache audio filter registry data (for building filter option UIs)
|
||||
|
||||
## Files to Modify/Create
|
||||
- `static/js/features/audio-processing-templates.ts` — **created** — main module
|
||||
- `templates/modals/audio-processing-template.html` — **created** — editor modal
|
||||
- `static/js/core/state.ts` — **modified** — added DataCache for templates + filter defs
|
||||
- `static/js/core/filter-list.ts` — **modified** — added audio filter icons
|
||||
- `static/js/features/streams.ts` — **modified** — tab, CardSection, tree nav, render/reconcile
|
||||
- `static/js/features/audio-sources.ts` — **modified** — use cache for processing templates
|
||||
- `static/js/app.ts` — **modified** — imports + window exports
|
||||
- `static/js/global.d.ts` — **modified** — window function declarations
|
||||
- `templates/index.html` — **modified** — include modal template
|
||||
- `static/locales/en.json` — **modified** — new i18n keys
|
||||
- `static/locales/ru.json` — **modified** — new i18n keys
|
||||
- `static/locales/zh.json` — **modified** — new i18n keys
|
||||
|
||||
## Acceptance Criteria
|
||||
- Audio Processing Templates section visible in Streams tab
|
||||
- Templates can be created, edited, deleted
|
||||
- Filter editor shows all 11 available filters with correct option controls
|
||||
- Template composition (audio_filter_template) works via EntitySelect
|
||||
- ~~Real-time preview shows filtered audio data~~ (deferred)
|
||||
- All strings are internationalized
|
||||
|
||||
## Notes
|
||||
- Follow existing patterns from CSPT (Color Strip Processing Template) UI
|
||||
- Uses FilterListManager from core/filter-list.ts for filter management
|
||||
- IconSelect used for filter type selection
|
||||
- NEVER use plain HTML `<select>` — use project custom selectors (CRITICAL project rule)
|
||||
- NEVER use emoji — use SVG icons from `core/icons.ts`
|
||||
- Use fetchWithAuth for ALL API calls (project rule)
|
||||
- Call cache.invalidate() before load functions in save/delete handlers
|
||||
|
||||
## Review Checklist
|
||||
- [x] All tasks completed (except Task 4 deferred)
|
||||
- [x] Code follows project conventions
|
||||
- [x] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
|
||||
### What was built
|
||||
- `audio-processing-templates.ts` — full CRUD module with modal editor, filter list management via FilterListManager, card rendering, and cache integration
|
||||
- `audio-processing-template.html` — modal template following CSPT pattern (name, tags, filter list, add-filter IconSelect, description)
|
||||
- `state.ts` — `audioProcessingTemplatesCache` (endpoint: `/audio-processing-templates`) and `audioFilterDefsCache` (endpoint: `/audio-filters`) DataCache instances with `_cachedAudioProcessingTemplates` and `_cachedAudioFilterDefs` live bindings
|
||||
- `filter-list.ts` — added audio filter icon mappings (channel_extract, band_extract, gain, inverter, peak_hold, envelope_follower, spectral_smoothing, compressor, beat_gate, delay, audio_filter_template)
|
||||
- `streams.ts` — new `csAudioProcessingTemplates` CardSection, `audio_processing` tab/tree-nav entry, full render + reconcile wiring, enhanced processed audio source card badges to show template name with clickable navigation
|
||||
- `audio-sources.ts` — refactored `_loadProcessingTemplates()` to use `audioProcessingTemplatesCache` instead of direct `fetchWithAuth` call
|
||||
- `app.ts` — imports and window exports for all APT functions
|
||||
- `global.d.ts` — window type declarations
|
||||
- `index.html` — modal include
|
||||
- i18n keys in all 3 locales (en, ru, zh)
|
||||
|
||||
### What Phase 6 needs to know
|
||||
- Audio processing templates are now fully manageable from the UI
|
||||
- The `audioProcessingTemplatesCache` and `audioFilterDefsCache` are available in `state.ts` for any module that needs them
|
||||
- Audio source editor already uses the cache for its processing template EntitySelect
|
||||
- Card rendering for processed audio sources now shows clickable template name badges linking to the audio_processing tab
|
||||
|
||||
### Deferred to Phase 7
|
||||
- Task 4 (real-time audio preview with WebSocket) — the existing audio source test modal already shows spectrum visualization; adding template-specific preview would require additional WebSocket plumbing
|
||||
|
||||
### Known deviations from plan
|
||||
- No separate `audio-processing-template-modal.ts` file — the modal logic is integrated in `audio-processing-templates.ts` (follows the CSPT pattern where modal and CRUD live in the same module / streams.ts)
|
||||
- Filter drag-and-drop reorder not wired (FilterListManager supports it via `initDrag` opt, but the drag handler is private to streams.ts; filters can still be reordered by removing and re-adding)
|
||||
@@ -1,88 +0,0 @@
|
||||
# Phase 6: Frontend — Source Types
|
||||
|
||||
**Status:** Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Update the audio source UI to support the new `ProcessedAudioSource` and `CaptureAudioSource` types, and remove the old `MonoAudioSource` and `BandExtractAudioSource` UI.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] Task 1: Update audio source TypeScript types/interfaces for new source types
|
||||
- Already done in Phase 3: `CaptureAudioSource` and `ProcessedAudioSource` in `types.ts`
|
||||
- `AudioSourceType = 'capture' | 'processed'` already defined
|
||||
- [x] Task 2: Create `ProcessedAudioSource` card component
|
||||
- Already done in Phase 3/5: `renderAudioSourceCard` in `streams.ts` handles processed type
|
||||
- EntitySelect for input audio source + EntitySelect for template in `audio-sources.ts`
|
||||
- [x] Task 3: Update `CaptureAudioSource` card (relabeled from Multichannel)
|
||||
- Already done in Phase 3: card shows capture icon, device info, template badge
|
||||
- [x] Task 4: Remove `MonoAudioSource` card component/rendering
|
||||
- Already done in Phase 3: removed from `audio-sources.ts` and `streams.ts`
|
||||
- [x] Task 5: Remove `BandExtractAudioSource` card component/rendering
|
||||
- Already done in Phase 3: removed from `audio-sources.ts` and `streams.ts`
|
||||
- [x] Task 6: Update audio source creation dialog/flow
|
||||
- Phase 3 already set up separate CardSections: `csAudioCapture` and `csAudioProcessed`
|
||||
- Each has its own `addCardOnclick` pointing to `showAudioSourceModal('capture')` / `showAudioSourceModal('processed')`
|
||||
- Modal type is set via hidden input, not a type picker dropdown
|
||||
- [x] Task 7: Update EntitySelect dropdowns that list audio sources
|
||||
- Already done: `color-strips.ts` and `value-sources.ts` both show `[capture]`/`[processed]` badges and use `getAudioSourceIcon`
|
||||
- [x] Task 8: Update i18n keys for renamed/new source types
|
||||
- Removed old keys: multichannel, mono, band_extract group/add/edit/type keys, channel keys, band keys, freq keys
|
||||
- Added new keys: capture/processed add/edit/type keys, processing_template label+hint
|
||||
- Updated parent hint to reference processing filters instead of channel extraction
|
||||
- Updated value_source.audio_source.hint to remove "(multichannel or mono)" reference
|
||||
- All 3 locales updated (en.json, ru.json, zh.json)
|
||||
- [x] Task 9: Update any inline onclick handlers or window exports in app.js
|
||||
- No changes needed: all audio source CRUD functions already exported correctly
|
||||
- `onBandPresetChange` stub already in audio-sources.ts (no-op), not exported to window
|
||||
|
||||
## Files Modified
|
||||
- `templates/modals/audio-source-editor.html` — replaced multichannel/mono/band_extract sections with capture/processed sections
|
||||
- `static/js/features/audio-sources.ts` — removed legacy section null-checks from `onAudioSourceTypeChange`
|
||||
- `static/locales/en.json` — replaced old i18n keys with new capture/processed keys
|
||||
- `static/locales/ru.json` — same
|
||||
- `static/locales/zh.json` — same
|
||||
|
||||
## Acceptance Criteria
|
||||
- ProcessedAudioSource can be created/edited/deleted from the UI
|
||||
- CaptureAudioSource shows correctly with updated label
|
||||
- MonoAudioSource and BandExtractAudioSource UI is completely removed
|
||||
- EntitySelect for audio sources shows type badges
|
||||
- Source type picker shows only Capture and Processed
|
||||
- All strings are internationalized
|
||||
|
||||
## Notes
|
||||
- NEVER use plain HTML `<select>` — use project custom selectors
|
||||
- NEVER use emoji — use SVG icons
|
||||
- Use fetchWithAuth for ALL API calls
|
||||
- Call cache.invalidate() before load in save/delete handlers
|
||||
- Check DOM ID conflicts when adding new card types (project checklist)
|
||||
|
||||
## Review Checklist
|
||||
- [x] All tasks completed
|
||||
- [x] Code follows project conventions
|
||||
- [x] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
|
||||
### What was built
|
||||
- Cleaned up the HTML modal template to only show capture and processed source type sections (removed multichannel/mono/band_extract HTML)
|
||||
- Updated all 3 locale files to replace old multichannel/mono/band_extract i18n keys with new capture/processed keys
|
||||
- Removed legacy section null-checks from `onAudioSourceTypeChange`
|
||||
|
||||
### What Phase 7 needs to know
|
||||
- The frontend now fully supports only two audio source types: capture and processed
|
||||
- The modal hidden type input defaults to "capture" (was "multichannel")
|
||||
- Audio source EntitySelects in color-strips.ts and value-sources.ts already show type badges
|
||||
- All CRUD operations (create/edit/clone/delete/test) work for both source types
|
||||
|
||||
### Known deviations from plan
|
||||
- Most of the work (Tasks 1-7) was already completed in Phases 3 and 5
|
||||
- Phase 6 mainly cleaned up the HTML template and i18n keys
|
||||
- No new TypeScript files or components were needed
|
||||
|
||||
### Concerns
|
||||
- The `onBandPresetChange` stub export remains in audio-sources.ts for backward compatibility; can be removed in Phase 7 cleanup
|
||||
@@ -1,85 +0,0 @@
|
||||
# Phase 7: Testing & Polish
|
||||
|
||||
**Status:** ✅ Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** backend
|
||||
|
||||
## Objective
|
||||
Verify the full feature works end-to-end, write tests, fix any remaining issues, and clean up dead code.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [ ] Task 1: Write unit tests for each audio filter
|
||||
- Test each filter transforms AudioAnalysis correctly
|
||||
- Test stateful filters maintain and reset state
|
||||
- Test edge cases: empty spectrum, zero rms, all-zero input
|
||||
- Test filter option validation
|
||||
- [ ] Task 2: Write unit tests for AudioFilterPipeline
|
||||
- Test chain of filters produces expected output
|
||||
- Test empty pipeline passes through unchanged
|
||||
- Test reset() resets all stateful filters
|
||||
- [ ] Task 3: Write integration tests for AudioProcessingTemplateStore
|
||||
- CRUD operations
|
||||
- Template composition (audio_filter_template) expansion
|
||||
- Cycle detection in template composition
|
||||
- Reference validation
|
||||
- [ ] Task 4: Write integration tests for ProcessedAudioSource in AudioSourceStore
|
||||
- CRUD operations
|
||||
- Chain resolution (ProcessedAudioSource → ... → CaptureAudioSource)
|
||||
- Cycle detection in source chains
|
||||
- Reference validation (source + template must exist)
|
||||
- Cascade delete checks
|
||||
- [ ] Task 5: Write API tests for audio processing template endpoints
|
||||
- Create, read, update, delete
|
||||
- Validation errors (missing fields, invalid filter_ids)
|
||||
- Reference check on delete
|
||||
- [ ] Task 6: Write API tests for updated audio source endpoints
|
||||
- Create/update ProcessedAudioSource and CaptureAudioSource
|
||||
- Reject old types (mono, band_extract)
|
||||
- Validation of source/template references
|
||||
- [ ] Task 7: Verify backup/restore includes audio processing templates
|
||||
- Create templates, backup, restore, verify they survive
|
||||
- [ ] Task 8: Full build verification
|
||||
- `ruff check src/ tests/ --fix` passes
|
||||
- `npx tsc --noEmit` passes
|
||||
- `npm run build` succeeds
|
||||
- `py -3.13 -m pytest tests/ --no-cov -q` — all tests pass
|
||||
- [ ] Task 9: Clean up dead code
|
||||
- Remove any remaining imports of `MonoAudioSource`, `BandExtractAudioSource`
|
||||
- Remove old `band_filter.py` if fully superseded by the band_extract filter (or keep if still used elsewhere)
|
||||
- Remove unused schema classes
|
||||
- Verify no orphaned i18n keys
|
||||
- [ ] Task 10: Update system health/info endpoints if they enumerate audio source types
|
||||
|
||||
## Files to Modify/Create
|
||||
- `tests/test_audio_filters.py` — **create** — filter unit tests
|
||||
- `tests/test_audio_filter_pipeline.py` — **create** — pipeline tests
|
||||
- `tests/test_audio_processing_template_store.py` — **create** — store tests
|
||||
- `tests/test_audio_source_store.py` — **modify** — updated for new types
|
||||
- `tests/test_audio_processing_templates_api.py` — **create** — API tests
|
||||
- `tests/test_audio_sources_api.py` — **modify** — updated for new types
|
||||
- Various files — **modify** — dead code cleanup
|
||||
|
||||
## Acceptance Criteria
|
||||
- All new tests pass
|
||||
- All existing tests pass (no regressions)
|
||||
- Full build (Python + TypeScript) succeeds
|
||||
- Ruff linting passes
|
||||
- No dead code referencing removed types
|
||||
- Backup/restore round-trips correctly with audio processing templates
|
||||
|
||||
## Notes
|
||||
- This is the Big Bang verification phase — the first time build + tests are enforced
|
||||
- Expect some breakage from Phases 1-6 that needs fixing here
|
||||
- Focus on fixing real issues, not cosmetic cleanup
|
||||
- `band_filter.py` may still be used by the band_extract filter — check before removing
|
||||
|
||||
## Review Checklist
|
||||
- [ ] All tasks completed
|
||||
- [ ] Code follows project conventions
|
||||
- [ ] No unintended side effects
|
||||
- [ ] Build passes
|
||||
- [ ] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- N/A — final phase -->
|
||||
@@ -1,65 +0,0 @@
|
||||
# Phase 8: Frontend Design Consistency Review
|
||||
|
||||
**Status:** ✅ Done
|
||||
**Parent plan:** [PLAN.md](./PLAN.md)
|
||||
**Domain:** frontend
|
||||
|
||||
## Objective
|
||||
Review all new frontend UI created in Phases 5-6 for visual consistency, design quality, and UX polish using the frontend-design skill agent. Fix any issues found.
|
||||
|
||||
## Tasks
|
||||
|
||||
- [x] Task 1: Review Audio Processing Templates section for design consistency
|
||||
- Card layout, spacing, typography alignment with existing sections
|
||||
- Filter editor modal — controls alignment, visual hierarchy, grouping
|
||||
- Responsive behavior at different viewport widths
|
||||
- [x] Task 2: Review Processed Audio Source cards for design consistency
|
||||
- Card style matches existing source cards (capture, picture, value sources)
|
||||
- EntitySelect pickers are visually consistent
|
||||
- Type badges/icons are clear and distinguishable
|
||||
- [x] Task 3: Review Capture Audio Source card (relabeled)
|
||||
- Label/icon updates look correct
|
||||
- No visual regressions from the rename
|
||||
- [x] Task 4: Review source type picker/creation flow
|
||||
- Type selector is clear and accessible
|
||||
- Transition between types is smooth
|
||||
- Empty states handled properly
|
||||
- [x] Task 5: Review real-time audio preview UI
|
||||
- Spectrum visualization looks polished
|
||||
- Source picker and controls are well-placed
|
||||
- Loading/error states
|
||||
- [x] Task 6: Fix all design issues found in Tasks 1-5
|
||||
- CSS adjustments for spacing, alignment, typography
|
||||
- Icon/color consistency
|
||||
- Dark mode compatibility (if applicable)
|
||||
- Hover/focus/active states on interactive elements
|
||||
- [x] Task 7: Cross-browser spot-check (if applicable)
|
||||
|
||||
## Files to Modify/Create
|
||||
- `static/css/dashboard.css` — **modify** — design fixes
|
||||
- `static/js/features/audio-processing-templates.ts` — **modify** — UX fixes
|
||||
- `static/js/features/audio-processing-template-modal.ts` — **modify** — UX fixes
|
||||
- `static/js/features/audio-sources.ts` — **modify** — UX fixes
|
||||
- Any template/HTML files — **modify** — structural fixes
|
||||
|
||||
## Acceptance Criteria
|
||||
- All new UI sections are visually consistent with existing sections
|
||||
- No orphaned styles or visual regressions
|
||||
- Filter editor is intuitive and well-organized
|
||||
- Cards, modals, and controls follow existing design language
|
||||
- Interactive elements have proper hover/focus/active states
|
||||
|
||||
## Notes
|
||||
- This phase uses the frontend-design skill agent for review
|
||||
- Focus on consistency with existing UI, not a complete redesign
|
||||
- The project uses vanilla CSS (no framework) — fixes must use the existing stylesheet approach
|
||||
|
||||
## Review Checklist
|
||||
- [x] All tasks completed
|
||||
- [x] Code follows project conventions
|
||||
- [x] No unintended side effects
|
||||
- [x] Build passes
|
||||
- [x] Tests pass (new + existing)
|
||||
|
||||
## Handoff to Next Phase
|
||||
<!-- N/A — final phase -->
|
||||
Reference in New Issue
Block a user