# 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
