353c090b42
Replace MultichannelAudioSource with CaptureAudioSource, add ProcessedAudioSource (audio_source_id + audio_processing_template_id), remove MonoAudioSource and BandExtractAudioSource entirely. Update store resolution to walk processed chains collecting template IDs. Update all API schemas, routes, and frontend references.
117 lines
7.5 KiB
Markdown
117 lines
7.5 KiB
Markdown
# 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
|