main 0a644dbb07d9 cached
271 files
4.5 MB
1.2M tokens
1337 symbols
1 requests
Download .txt
Showing preview only (4,766K chars total). Download the full file or copy to clipboard to get everything.
Repository: nomadkaraoke/python-audio-separator
Branch: main
Commit: 0a644dbb07d9
Files: 271
Total size: 4.5 MB

Directory structure:
gitextract_b_sdr3ak/

├── .claude/
│   └── plans/
│       └── gha-gpu-runner.plan.md
├── .cursor/
│   ├── commands/
│   │   ├── analyze.md
│   │   ├── clarify.md
│   │   ├── constitution.md
│   │   ├── implement.md
│   │   ├── plan.md
│   │   ├── specify.md
│   │   └── tasks.md
│   └── rules/
│       └── specify-rules.mdc
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── BUG_REPORT.yml
│   │   └── FEATURE_REQUEST.yml
│   ├── prompts/
│   │   ├── analyze.prompt.md
│   │   ├── clarify.prompt.md
│   │   ├── constitution.prompt.md
│   │   ├── implement.prompt.md
│   │   ├── plan.prompt.md
│   │   ├── specify.prompt.md
│   │   └── tasks.prompt.md
│   └── workflows/
│       ├── deploy-to-cloudrun.yml
│       ├── deploy-to-modal.yml
│       ├── github-sponsors.yml
│       ├── publish-to-docker.yml
│       ├── publish-to-pypi.yml
│       ├── run-integration-tests.yaml
│       └── run-unit-tests.yaml
├── .gitignore
├── .specify/
│   ├── memory/
│   │   └── constitution.md
│   ├── scripts/
│   │   └── bash/
│   │       ├── check-prerequisites.sh
│   │       ├── common.sh
│   │       ├── create-new-feature.sh
│   │       ├── setup-plan.sh
│   │       └── update-agent-context.sh
│   └── templates/
│       ├── agent-file-template.md
│       ├── plan-template.md
│       ├── spec-template.md
│       └── tasks-template.md
├── Dockerfile.cloudrun
├── Dockerfile.cpu
├── Dockerfile.cuda11
├── Dockerfile.cuda12
├── Dockerfile.runpod-cuda11
├── Dockerfile.runpod-cuda12
├── LICENSE
├── README.md
├── TODO.md
├── audio_separator/
│   ├── __init__.py
│   ├── ensemble_presets.json
│   ├── model-data.json
│   ├── models-scores.json
│   ├── models.json
│   ├── remote/
│   │   ├── README.md
│   │   ├── __init__.py
│   │   ├── api_client.py
│   │   ├── cli.py
│   │   ├── deploy_cloudrun.py
│   │   ├── deploy_modal.py
│   │   ├── job_store.py
│   │   ├── output_store.py
│   │   └── requirements.txt
│   ├── separator/
│   │   ├── __init__.py
│   │   ├── architectures/
│   │   │   ├── __init__.py
│   │   │   ├── demucs_separator.py
│   │   │   ├── mdx_separator.py
│   │   │   ├── mdxc_separator.py
│   │   │   └── vr_separator.py
│   │   ├── audio_chunking.py
│   │   ├── common_separator.py
│   │   ├── ensembler.py
│   │   ├── roformer/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── bs_roformer_config.py
│   │   │   ├── bs_roformer_validator.py
│   │   │   ├── configuration_normalizer.py
│   │   │   ├── mel_band_roformer_config.py
│   │   │   ├── mel_band_roformer_validator.py
│   │   │   ├── model_configuration.py
│   │   │   ├── model_loading_result.py
│   │   │   ├── parameter_validation_error.py
│   │   │   ├── parameter_validator.py
│   │   │   └── roformer_loader.py
│   │   ├── separator.py
│   │   └── uvr_lib_v5/
│   │       ├── __init__.py
│   │       ├── demucs/
│   │       │   ├── __init__.py
│   │       │   ├── __main__.py
│   │       │   ├── apply.py
│   │       │   ├── demucs.py
│   │       │   ├── filtering.py
│   │       │   ├── hdemucs.py
│   │       │   ├── htdemucs.py
│   │       │   ├── model.py
│   │       │   ├── model_v2.py
│   │       │   ├── pretrained.py
│   │       │   ├── repo.py
│   │       │   ├── spec.py
│   │       │   ├── states.py
│   │       │   ├── tasnet.py
│   │       │   ├── tasnet_v2.py
│   │       │   ├── transformer.py
│   │       │   └── utils.py
│   │       ├── mdxnet.py
│   │       ├── mixer.ckpt
│   │       ├── modules.py
│   │       ├── playsound.py
│   │       ├── pyrb.py
│   │       ├── results.py
│   │       ├── roformer/
│   │       │   ├── attend.py
│   │       │   ├── bs_roformer.py
│   │       │   └── mel_band_roformer.py
│   │       ├── spec_utils.py
│   │       ├── stft.py
│   │       ├── tfc_tdf_v3.py
│   │       └── vr_network/
│   │           ├── __init__.py
│   │           ├── layers.py
│   │           ├── layers_new.py
│   │           ├── model_param_init.py
│   │           ├── modelparams/
│   │           │   ├── 1band_sr16000_hl512.json
│   │           │   ├── 1band_sr32000_hl512.json
│   │           │   ├── 1band_sr33075_hl384.json
│   │           │   ├── 1band_sr44100_hl1024.json
│   │           │   ├── 1band_sr44100_hl256.json
│   │           │   ├── 1band_sr44100_hl512.json
│   │           │   ├── 1band_sr44100_hl512_cut.json
│   │           │   ├── 1band_sr44100_hl512_nf1024.json
│   │           │   ├── 2band_32000.json
│   │           │   ├── 2band_44100_lofi.json
│   │           │   ├── 2band_48000.json
│   │           │   ├── 3band_44100.json
│   │           │   ├── 3band_44100_mid.json
│   │           │   ├── 3band_44100_msb2.json
│   │           │   ├── 4band_44100.json
│   │           │   ├── 4band_44100_mid.json
│   │           │   ├── 4band_44100_msb.json
│   │           │   ├── 4band_44100_msb2.json
│   │           │   ├── 4band_44100_reverse.json
│   │           │   ├── 4band_44100_sw.json
│   │           │   ├── 4band_v2.json
│   │           │   ├── 4band_v2_sn.json
│   │           │   ├── 4band_v3.json
│   │           │   ├── 4band_v3_sn.json
│   │           │   ├── 4band_v4_ms_fullband.json
│   │           │   └── ensemble.json
│   │           ├── nets.py
│   │           └── nets_new.py
│   └── utils/
│       ├── __init__.py
│       └── cli.py
├── cloudbuild.yaml
├── docs/
│   ├── BIT_DEPTH_IMPLEMENTATION_SUMMARY.md
│   ├── BIT_DEPTH_PRESERVATION.md
│   ├── CI-GPU-RUNNERS.md
│   ├── archive/
│   │   └── 2026-03-22-modal-to-gcp-migration-plan.md
│   ├── deton24-audio-separation-info-2026-03-15.md
│   └── deton24-model-mapping-and-ensemble-guide.md
├── environment.yml
├── pyproject.toml
├── pytest.ini
├── scripts/
│   └── download_preset_models.py
├── specs/
│   ├── 001-update-roformer-implementation/
│   │   ├── 001-update-roformer-implementation.md
│   │   ├── contracts/
│   │   │   ├── fallback_loader_interface.py
│   │   │   ├── parameter_validator_interface.py
│   │   │   └── roformer_loader_interface.py
│   │   ├── data-model.md
│   │   ├── plan.md
│   │   ├── post-implementation-issues.md
│   │   ├── quickstart.md
│   │   ├── research.md
│   │   └── tasks.md
│   └── main/
│       └── plan.md
├── tests/
│   ├── README.md
│   ├── TODO.txt
│   ├── contract/
│   │   ├── test_parameter_validator_interface.py
│   │   └── test_roformer_loader_interface.py
│   ├── inputs/
│   │   ├── clocks_piano.flac
│   │   ├── fallen24bit20s.flac
│   │   ├── levee_drums.flac
│   │   ├── mardy20s.flac
│   │   ├── mardy20s_(Instrumental)_mel_band_roformer_karaoke_aufr33_viperx_sdr_10.flac
│   │   ├── mardy20s_(Vocals)_mel_band_roformer_karaoke_aufr33_viperx_sdr_10.flac
│   │   ├── only_time_reverb.flac
│   │   ├── reference/
│   │   │   ├── ref_clocks_piano_bass_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_drums_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_instrumental.flac
│   │   │   ├── ref_clocks_piano_instrumental_karaoke.flac
│   │   │   ├── ref_clocks_piano_other_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_vocals.flac
│   │   │   ├── ref_clocks_piano_vocals_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_vocals_karaoke.flac
│   │   │   ├── ref_levee_drums_bass_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_crash_drumsep.flac
│   │   │   ├── ref_levee_drums_drums_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_hh_drumsep.flac
│   │   │   ├── ref_levee_drums_instrumental.flac
│   │   │   ├── ref_levee_drums_instrumental_karaoke.flac
│   │   │   ├── ref_levee_drums_instrumental_preset_vocal_balanced.flac
│   │   │   ├── ref_levee_drums_kick_drumsep.flac
│   │   │   ├── ref_levee_drums_other_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_ride_drumsep.flac
│   │   │   ├── ref_levee_drums_snare_drumsep.flac
│   │   │   ├── ref_levee_drums_toms_drumsep.flac
│   │   │   ├── ref_levee_drums_vocals.flac
│   │   │   ├── ref_levee_drums_vocals_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_vocals_karaoke.flac
│   │   │   ├── ref_levee_drums_vocals_preset_vocal_balanced.flac
│   │   │   ├── ref_only_time_reverb_instrumental.flac
│   │   │   ├── ref_only_time_reverb_vocals.flac
│   │   │   ├── ref_only_time_reverb_vocals_noreverb.flac
│   │   │   ├── ref_only_time_reverb_vocals_reverb.flac
│   │   │   ├── ref_sing_sing_sing_brass_instrumental.flac
│   │   │   ├── ref_sing_sing_sing_brass_no_woodwinds.flac
│   │   │   ├── ref_sing_sing_sing_brass_vocals.flac
│   │   │   ├── ref_sing_sing_sing_brass_woodwinds.flac
│   │   │   ├── ref_under_pressure_harmonies_backing_vocals.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental_karaoke.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental_preset_karaoke.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental_preset_vocal_balanced.flac
│   │   │   ├── ref_under_pressure_harmonies_lead_vocals.flac
│   │   │   ├── ref_under_pressure_harmonies_vocals.flac
│   │   │   ├── ref_under_pressure_harmonies_vocals_karaoke.flac
│   │   │   ├── ref_under_pressure_harmonies_vocals_preset_karaoke.flac
│   │   │   └── ref_under_pressure_harmonies_vocals_preset_vocal_balanced.flac
│   │   ├── sing_sing_sing_brass.flac
│   │   └── under_pressure_harmonies.flac
│   ├── integration/
│   │   ├── README.md
│   │   ├── generate_multi_stem_references.py
│   │   ├── generate_reference_images.py
│   │   ├── generate_reference_images_24bit.py
│   │   ├── generate_reference_images_ensemble.py
│   │   ├── requirements.txt
│   │   ├── test_24bit_preservation.py
│   │   ├── test_cli_integration.py
│   │   ├── test_ensemble_integration.py
│   │   ├── test_ensemble_meaningful.py
│   │   ├── test_multi_stem_verification.py
│   │   ├── test_remote_api_integration.py
│   │   ├── test_roformer_audio_quality.py
│   │   ├── test_roformer_backward_compatibility.py
│   │   ├── test_roformer_config_validation.py
│   │   ├── test_roformer_e2e.py
│   │   ├── test_roformer_fallback_mechanism.py
│   │   ├── test_roformer_model_switching.py
│   │   ├── test_roformer_new_parameters.py
│   │   └── test_separator_output_integration.py
│   ├── model-metrics/
│   │   └── test-all-models.py
│   ├── regression/
│   │   ├── test_all_models_stem_verification.py
│   │   └── test_roformer_size_mismatch.py
│   ├── remote/
│   │   └── README.md
│   ├── reproduce_ensemble_bug.py
│   ├── unit/
│   │   ├── test_audio_chunking.py
│   │   ├── test_bit_depth_detection.py
│   │   ├── test_bit_depth_writing.py
│   │   ├── test_cli.py
│   │   ├── test_configuration_normalizer.py
│   │   ├── test_deploy_cloudrun_async.py
│   │   ├── test_ensemble_presets.py
│   │   ├── test_ensembler.py
│   │   ├── test_job_store.py
│   │   ├── test_mdxc_roformer_chunking.py
│   │   ├── test_model_configuration.py
│   │   ├── test_output_store.py
│   │   ├── test_parameter_validator.py
│   │   ├── test_remote_api_client.py
│   │   ├── test_remote_cli.py
│   │   ├── test_separator_chunking.py
│   │   ├── test_separator_detection.py
│   │   ├── test_stem_naming.py
│   │   └── test_stft.py
│   ├── utils.py
│   └── utils_audio_verification.py
└── tools/
    ├── calculate-model-hashes.py
    └── sync-to-github.py

================================================
FILE CONTENTS
================================================

================================================
FILE: .claude/plans/gha-gpu-runner.plan.md
================================================
# Plan: GCP GPU Runner for Integration Tests

**Created:** 2026-03-16
**Branch:** feat/gha-gpu-runner
**Status:** Implemented (pending `pulumi up` and PR merge)

## Overview

The python-audio-separator integration tests currently run on a CPU-only self-hosted
GHA runner (`e2-standard-4`, 4 vCPU, 16GB RAM). With the new ensemble tests and
multi-stem verification tests, CI takes 30+ minutes because each model separation runs
on CPU. A GPU runner would reduce this to ~5 minutes.

## Current State

### Existing runner infrastructure
- **Location:** `karaoke-gen/infrastructure/compute/github_runners.py` (Pulumi)
- **Runners:** 3× `e2-standard-4` (general) + 1× `e2-standard-8` (Docker builds)
- **Labels:** `self-hosted`, `Linux`, `X64`, `gcp`, `large-disk`
- **Region:** `us-central1-a`
- **Models:** Pre-cached at `/opt/audio-separator-models` on runner startup
- **Org-level:** Runners are registered to `nomadkaraoke` org, available to all repos
- **NAT:** All runners use Cloud NAT (no external IPs)

### Current integration test workflow
- File: `.github/workflows/run-integration-tests.yaml`
- Runs on: `self-hosted` (picks up any org runner)
- Tests: `poetry run pytest -sv --cov=audio_separator tests/integration`
- Installs: `poetry install -E cpu`
- Problem: All model inference on CPU → very slow for Roformer/Demucs models

## Requirements

- [x] GCE VM with NVIDIA GPU (T4 is cheapest, sufficient for inference)
- [x] CUDA drivers + PyTorch GPU support pre-installed
- [x] Models pre-cached on persistent disk (same as existing runners)
- [x] Labeled `gpu` so workflow can target it specifically
- [x] Cost-effective — only runs when needed (on-demand, not always-on)
- [x] Integration test workflow updated to use `gpu` label
- [x] Install `poetry install -E gpu` (onnxruntime-gpu) instead of `-E cpu`

## Technical Approach

### Option A: Dedicated GPU VM (simplest)

Add a new GPU runner VM to the existing Pulumi infrastructure. Use an `n1-standard-4`
with 1× NVIDIA T4 GPU. Cost: ~$0.35/hr on-demand, ~$0.11/hr spot.

**Pros:** Simple, fits existing patterns, fast startup (VM already running)
**Cons:** Always-on cost if not managed; or slow cold-start if managed

### Option B: Spot GPU VM with startup/shutdown management

Same as A but use spot pricing and the existing runner_manager Cloud Function to
start/stop based on CI demand.

**Pros:** 70% cheaper ($0.11/hr), fits existing management pattern
**Cons:** Spot can be preempted mid-test (rare for short jobs); cold start ~2-3 min

### Option C: Use a cloud GPU service (Modal, Lambda Labs, etc.)

Run the integration tests on a cloud GPU service rather than self-hosted.

**Pros:** No infrastructure to manage, pay-per-second
**Cons:** More complex CI integration, different from existing patterns

### Recommendation: Option B (Spot GPU VM)

The integration test takes <10 minutes on GPU, so spot preemption risk is low.
Cold start is acceptable since it's triggered by PR events. Cost: ~$0.02 per CI run.

## Implementation Steps

### 1. Pulumi infrastructure (in karaoke-gen repo)

1. [x] Add `GITHUB_GPU_RUNNER` machine type to `config.py`: `n1-standard-4` + 1× T4
2. [x] Add `GPU_RUNNER_LABELS` to `config.py`: `"self-hosted,linux,x64,gcp,gpu"`
3. [x] Create GPU runner VM in `github_runners.py`:
   - `n1-standard-4` (4 vCPU, 15GB RAM)
   - 1× NVIDIA T4 GPU (`nvidia-tesla-t4`)
   - `guest_accelerators` config
   - `on_host_maintenance: "TERMINATE"` (required for GPU VMs)
   - Same NAT/networking as existing runners
4. [x] Create GPU startup script (`github_runner_gpu.sh`):
   - Install NVIDIA drivers via CUDA repo (cuda-drivers + cuda-toolkit-12-4)
   - Install CUDA toolkit
   - Verify GPU: `nvidia-smi`
   - Pre-download models to `/opt/audio-separator-models`
   - Register as GHA runner with `gpu` label
5. [x] Add spot scheduling for cost optimization
6. [ ] Run `pulumi up` to create the VM

### 2. Workflow update (in python-audio-separator repo)

7. [x] Update `run-integration-tests.yaml`:
   - Change `runs-on: self-hosted` to `runs-on: [self-hosted, gpu]`
   - Change `poetry install -E cpu` to `poetry install -E gpu`
   - Add `nvidia-smi` verification step
   - Add 30-minute timeout
8. [ ] Add fallback: if no GPU runner available, fall back to CPU with longer timeout
   - Deferred: not needed initially, the runner_manager auto-starts the GPU VM on demand

### 3. Startup script details

The GPU startup script needs to:
```bash
# Install NVIDIA drivers (for Debian 12)
sudo apt-get update
sudo apt-get install -y linux-headers-$(uname -r) nvidia-driver-535

# Verify GPU
nvidia-smi

# Install CUDA (for PyTorch)
# PyTorch bundles its own CUDA, so we mainly need the driver

# Pre-download models
pip install audio-separator[gpu]
python -c "
from audio_separator.separator import Separator
sep = Separator(model_file_dir='/opt/audio-separator-models')
# Download all models used in integration tests
models = [
    'model_bs_roformer_ep_317_sdr_12.9755.ckpt',
    'mel_band_roformer_karaoke_aufr33_viperx_sdr_10.1956.ckpt',
    'MGM_MAIN_v4.pth',
    'UVR-MDX-NET-Inst_HQ_4.onnx',
    'kuielab_b_vocals.onnx',
    '2_HP-UVR.pth',
    'htdemucs_6s.yaml',
    'htdemucs_ft.yaml',
    # Ensemble preset models
    'bs_roformer_vocals_resurrection_unwa.ckpt',
    'melband_roformer_big_beta6x.ckpt',
    'bs_roformer_vocals_revive_v2_unwa.ckpt',
    'mel_band_roformer_kim_ft2_bleedless_unwa.ckpt',
    'bs_roformer_vocals_revive_v3e_unwa.ckpt',
    'mel_band_roformer_vocals_becruily.ckpt',
    'mel_band_roformer_vocals_fv4_gabox.ckpt',
    'mel_band_roformer_instrumental_fv7z_gabox.ckpt',
    'bs_roformer_instrumental_resurrection_unwa.ckpt',
    'melband_roformer_inst_v1e_plus.ckpt',
    'mel_band_roformer_instrumental_becruily.ckpt',
    'mel_band_roformer_instrumental_instv8_gabox.ckpt',
    'UVR-MDX-NET-Inst_HQ_5.onnx',
    'mel_band_roformer_karaoke_gabox_v2.ckpt',
    'mel_band_roformer_karaoke_becruily.ckpt',
    # Multi-stem test models
    '17_HP-Wind_Inst-UVR.pth',
    'MDX23C-DrumSep-aufr33-jarredou.ckpt',
    'dereverb_mel_band_roformer_anvuew_sdr_19.1729.ckpt',
]
for m in models:
    sep.download_model_and_data(m)
"
```

## Cost Estimate

| Config | Hourly | Per CI run (~10 min) | Monthly (est. 100 runs) |
|--------|--------|---------------------|-------------------------|
| n1-standard-4 + T4 (on-demand) | $0.61 | $0.10 | $10 |
| n1-standard-4 + T4 (spot) | $0.19 | $0.03 | $3 |
| Current CPU (e2-standard-4) | $0.13 | $0.07 | $7 |

Spot GPU is actually cheaper per-run than current CPU because GPU tests finish 5× faster.

## Files to Create/Modify

| File | Repo | Action |
|------|------|--------|
| `infrastructure/config.py` | karaoke-gen | Add GPU machine type + labels |
| `infrastructure/compute/github_runners.py` | karaoke-gen | Add GPU runner VM |
| `infrastructure/compute/startup_scripts/github_runner_gpu.sh` | karaoke-gen | GPU-specific startup |
| `.github/workflows/run-integration-tests.yaml` | python-audio-separator | Target GPU runner |

## Open Questions

- [x] Should the GPU runner be spot or on-demand? → **Spot** ($0.19/hr, ~$3/mo)
- [x] Should we keep the CPU fallback for when GPU runner is unavailable? → **Deferred** (runner_manager auto-starts VM)
- [x] Should the runner startup script install NVIDIA drivers from scratch each boot,
      or use a pre-built GCP Deep Learning VM image? → **From scratch** (idempotent, matches existing pattern)
- [x] Zone availability: T4 GPUs may not be available in us-central1-a → **Available** in all us-central1 zones (a, b, c, f)

## Rollback Plan

The GPU runner is additive infrastructure. If it fails:
1. Change workflow back to `runs-on: self-hosted` (CPU)
2. Destroy the GPU VM via `pulumi destroy` targeting just that resource


================================================
FILE: .cursor/commands/analyze.md
================================================
---
description: Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and tasks.md after task generation.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

Goal: Identify inconsistencies, duplications, ambiguities, and underspecified items across the three core artifacts (`spec.md`, `plan.md`, `tasks.md`) before implementation. This command MUST run only after `/tasks` has successfully produced a complete `tasks.md`.

STRICTLY READ-ONLY: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up editing commands would be invoked manually).

Constitution Authority: The project constitution (`.specify/memory/constitution.md`) is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit constitution update outside `/analyze`.

Execution steps:

1. Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` once from repo root and parse JSON for FEATURE_DIR and AVAILABLE_DOCS. Derive absolute paths:
   - SPEC = FEATURE_DIR/spec.md
   - PLAN = FEATURE_DIR/plan.md
   - TASKS = FEATURE_DIR/tasks.md
   Abort with an error message if any required file is missing (instruct the user to run missing prerequisite command).

2. Load artifacts:
   - Parse spec.md sections: Overview/Context, Functional Requirements, Non-Functional Requirements, User Stories, Edge Cases (if present).
   - Parse plan.md: Architecture/stack choices, Data Model references, Phases, Technical constraints.
   - Parse tasks.md: Task IDs, descriptions, phase grouping, parallel markers [P], referenced file paths.
   - Load constitution `.specify/memory/constitution.md` for principle validation.

3. Build internal semantic models:
   - Requirements inventory: Each functional + non-functional requirement with a stable key (derive slug based on imperative phrase; e.g., "User can upload file" -> `user-can-upload-file`).
   - User story/action inventory.
   - Task coverage mapping: Map each task to one or more requirements or stories (inference by keyword / explicit reference patterns like IDs or key phrases).
   - Constitution rule set: Extract principle names and any MUST/SHOULD normative statements.

4. Detection passes:
   A. Duplication detection:
      - Identify near-duplicate requirements. Mark lower-quality phrasing for consolidation.
   B. Ambiguity detection:
      - Flag vague adjectives (fast, scalable, secure, intuitive, robust) lacking measurable criteria.
      - Flag unresolved placeholders (TODO, TKTK, ???, <placeholder>, etc.).
   C. Underspecification:
      - Requirements with verbs but missing object or measurable outcome.
      - User stories missing acceptance criteria alignment.
      - Tasks referencing files or components not defined in spec/plan.
   D. Constitution alignment:
      - Any requirement or plan element conflicting with a MUST principle.
      - Missing mandated sections or quality gates from constitution.
   E. Coverage gaps:
      - Requirements with zero associated tasks.
      - Tasks with no mapped requirement/story.
      - Non-functional requirements not reflected in tasks (e.g., performance, security).
   F. Inconsistency:
      - Terminology drift (same concept named differently across files).
      - Data entities referenced in plan but absent in spec (or vice versa).
      - Task ordering contradictions (e.g., integration tasks before foundational setup tasks without dependency note).
      - Conflicting requirements (e.g., one requires to use Next.js while other says to use Vue as the framework).

5. Severity assignment heuristic:
   - CRITICAL: Violates constitution MUST, missing core spec artifact, or requirement with zero coverage that blocks baseline functionality.
   - HIGH: Duplicate or conflicting requirement, ambiguous security/performance attribute, untestable acceptance criterion.
   - MEDIUM: Terminology drift, missing non-functional task coverage, underspecified edge case.
   - LOW: Style/wording improvements, minor redundancy not affecting execution order.

6. Produce a Markdown report (no file writes) with sections:

   ### Specification Analysis Report
   | ID | Category | Severity | Location(s) | Summary | Recommendation |
   |----|----------|----------|-------------|---------|----------------|
   | A1 | Duplication | HIGH | spec.md:L120-134 | Two similar requirements ... | Merge phrasing; keep clearer version |
   (Add one row per finding; generate stable IDs prefixed by category initial.)

   Additional subsections:
   - Coverage Summary Table:
     | Requirement Key | Has Task? | Task IDs | Notes |
   - Constitution Alignment Issues (if any)
   - Unmapped Tasks (if any)
   - Metrics:
     * Total Requirements
     * Total Tasks
     * Coverage % (requirements with >=1 task)
     * Ambiguity Count
     * Duplication Count
     * Critical Issues Count

7. At end of report, output a concise Next Actions block:
   - If CRITICAL issues exist: Recommend resolving before `/implement`.
   - If only LOW/MEDIUM: User may proceed, but provide improvement suggestions.
   - Provide explicit command suggestions: e.g., "Run /specify with refinement", "Run /plan to adjust architecture", "Manually edit tasks.md to add coverage for 'performance-metrics'".

8. Ask the user: "Would you like me to suggest concrete remediation edits for the top N issues?" (Do NOT apply them automatically.)

Behavior rules:
- NEVER modify files.
- NEVER hallucinate missing sections—if absent, report them.
- KEEP findings deterministic: if rerun without changes, produce consistent IDs and counts.
- LIMIT total findings in the main table to 50; aggregate remainder in a summarized overflow note.
- If zero issues found, emit a success report with coverage statistics and proceed recommendation.

Context: $ARGUMENTS


================================================
FILE: .cursor/commands/clarify.md
================================================
---
description: Identify underspecified areas in the current feature spec by asking up to 5 highly targeted clarification questions and encoding answers back into the spec.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

Goal: Detect and reduce ambiguity or missing decision points in the active feature specification and record the clarifications directly in the spec file.

Note: This clarification workflow is expected to run (and be completed) BEFORE invoking `/plan`. If the user explicitly states they are skipping clarification (e.g., exploratory spike), you may proceed, but must warn that downstream rework risk increases.

Execution steps:

1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode / `-Json -PathsOnly`). Parse minimal JSON payload fields:
   - `FEATURE_DIR`
   - `FEATURE_SPEC`
   - (Optionally capture `IMPL_PLAN`, `TASKS` for future chained flows.)
   - If JSON parsing fails, abort and instruct user to re-run `/specify` or verify feature branch environment.

2. Load the current spec file. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked).

   Functional Scope & Behavior:
   - Core user goals & success criteria
   - Explicit out-of-scope declarations
   - User roles / personas differentiation

   Domain & Data Model:
   - Entities, attributes, relationships
   - Identity & uniqueness rules
   - Lifecycle/state transitions
   - Data volume / scale assumptions

   Interaction & UX Flow:
   - Critical user journeys / sequences
   - Error/empty/loading states
   - Accessibility or localization notes

   Non-Functional Quality Attributes:
   - Performance (latency, throughput targets)
   - Scalability (horizontal/vertical, limits)
   - Reliability & availability (uptime, recovery expectations)
   - Observability (logging, metrics, tracing signals)
   - Security & privacy (authN/Z, data protection, threat assumptions)
   - Compliance / regulatory constraints (if any)

   Integration & External Dependencies:
   - External services/APIs and failure modes
   - Data import/export formats
   - Protocol/versioning assumptions

   Edge Cases & Failure Handling:
   - Negative scenarios
   - Rate limiting / throttling
   - Conflict resolution (e.g., concurrent edits)

   Constraints & Tradeoffs:
   - Technical constraints (language, storage, hosting)
   - Explicit tradeoffs or rejected alternatives

   Terminology & Consistency:
   - Canonical glossary terms
   - Avoided synonyms / deprecated terms

   Completion Signals:
   - Acceptance criteria testability
   - Measurable Definition of Done style indicators

   Misc / Placeholders:
   - TODO markers / unresolved decisions
   - Ambiguous adjectives ("robust", "intuitive") lacking quantification

   For each category with Partial or Missing status, add a candidate question opportunity unless:
   - Clarification would not materially change implementation or validation strategy
   - Information is better deferred to planning phase (note internally)

3. Generate (internally) a prioritized queue of candidate clarification questions (maximum 5). Do NOT output them all at once. Apply these constraints:
    - Maximum of 5 total questions across the whole session.
    - Each question must be answerable with EITHER:
       * A short multiple‑choice selection (2–5 distinct, mutually exclusive options), OR
       * A one-word / short‑phrase answer (explicitly constrain: "Answer in <=5 words").
   - Only include questions whose answers materially impact architecture, data modeling, task decomposition, test design, UX behavior, operational readiness, or compliance validation.
   - Ensure category coverage balance: attempt to cover the highest impact unresolved categories first; avoid asking two low-impact questions when a single high-impact area (e.g., security posture) is unresolved.
   - Exclude questions already answered, trivial stylistic preferences, or plan-level execution details (unless blocking correctness).
   - Favor clarifications that reduce downstream rework risk or prevent misaligned acceptance tests.
   - If more than 5 categories remain unresolved, select the top 5 by (Impact * Uncertainty) heuristic.

4. Sequential questioning loop (interactive):
    - Present EXACTLY ONE question at a time.
    - For multiple‑choice questions render options as a Markdown table:

       | Option | Description |
       |--------|-------------|
       | A | <Option A description> |
       | B | <Option B description> |
       | C | <Option C description> | (add D/E as needed up to 5)
       | Short | Provide a different short answer (<=5 words) | (Include only if free-form alternative is appropriate)

    - For short‑answer style (no meaningful discrete options), output a single line after the question: `Format: Short answer (<=5 words)`.
    - After the user answers:
       * Validate the answer maps to one option or fits the <=5 word constraint.
       * If ambiguous, ask for a quick disambiguation (count still belongs to same question; do not advance).
       * Once satisfactory, record it in working memory (do not yet write to disk) and move to the next queued question.
    - Stop asking further questions when:
       * All critical ambiguities resolved early (remaining queued items become unnecessary), OR
       * User signals completion ("done", "good", "no more"), OR
       * You reach 5 asked questions.
    - Never reveal future queued questions in advance.
    - If no valid questions exist at start, immediately report no critical ambiguities.

5. Integration after EACH accepted answer (incremental update approach):
    - Maintain in-memory representation of the spec (loaded once at start) plus the raw file contents.
    - For the first integrated answer in this session:
       * Ensure a `## Clarifications` section exists (create it just after the highest-level contextual/overview section per the spec template if missing).
       * Under it, create (if not present) a `### Session YYYY-MM-DD` subheading for today.
    - Append a bullet line immediately after acceptance: `- Q: <question> → A: <final answer>`.
    - Then immediately apply the clarification to the most appropriate section(s):
       * Functional ambiguity → Update or add a bullet in Functional Requirements.
       * User interaction / actor distinction → Update User Stories or Actors subsection (if present) with clarified role, constraint, or scenario.
       * Data shape / entities → Update Data Model (add fields, types, relationships) preserving ordering; note added constraints succinctly.
       * Non-functional constraint → Add/modify measurable criteria in Non-Functional / Quality Attributes section (convert vague adjective to metric or explicit target).
       * Edge case / negative flow → Add a new bullet under Edge Cases / Error Handling (or create such subsection if template provides placeholder for it).
       * Terminology conflict → Normalize term across spec; retain original only if necessary by adding `(formerly referred to as "X")` once.
    - If the clarification invalidates an earlier ambiguous statement, replace that statement instead of duplicating; leave no obsolete contradictory text.
    - Save the spec file AFTER each integration to minimize risk of context loss (atomic overwrite).
    - Preserve formatting: do not reorder unrelated sections; keep heading hierarchy intact.
    - Keep each inserted clarification minimal and testable (avoid narrative drift).

6. Validation (performed after EACH write plus final pass):
   - Clarifications session contains exactly one bullet per accepted answer (no duplicates).
   - Total asked (accepted) questions ≤ 5.
   - Updated sections contain no lingering vague placeholders the new answer was meant to resolve.
   - No contradictory earlier statement remains (scan for now-invalid alternative choices removed).
   - Markdown structure valid; only allowed new headings: `## Clarifications`, `### Session YYYY-MM-DD`.
   - Terminology consistency: same canonical term used across all updated sections.

7. Write the updated spec back to `FEATURE_SPEC`.

8. Report completion (after questioning loop ends or early termination):
   - Number of questions asked & answered.
   - Path to updated spec.
   - Sections touched (list names).
   - Coverage summary table listing each taxonomy category with Status: Resolved (was Partial/Missing and addressed), Deferred (exceeds question quota or better suited for planning), Clear (already sufficient), Outstanding (still Partial/Missing but low impact).
   - If any Outstanding or Deferred remain, recommend whether to proceed to `/plan` or run `/clarify` again later post-plan.
   - Suggested next command.

Behavior rules:
- If no meaningful ambiguities found (or all potential questions would be low-impact), respond: "No critical ambiguities detected worth formal clarification." and suggest proceeding.
- If spec file missing, instruct user to run `/specify` first (do not create a new spec here).
- Never exceed 5 total asked questions (clarification retries for a single question do not count as new questions).
- Avoid speculative tech stack questions unless the absence blocks functional clarity.
- Respect user early termination signals ("stop", "done", "proceed").
 - If no questions asked due to full coverage, output a compact coverage summary (all categories Clear) then suggest advancing.
 - If quota reached with unresolved high-impact categories remaining, explicitly flag them under Deferred with rationale.

Context for prioritization: $ARGUMENTS


================================================
FILE: .cursor/commands/constitution.md
================================================
---
description: Create or update the project constitution from interactive or provided principle inputs, ensuring all dependent templates stay in sync.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

You are updating the project constitution at `.specify/memory/constitution.md`. This file is a TEMPLATE containing placeholder tokens in square brackets (e.g. `[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`). Your job is to (a) collect/derive concrete values, (b) fill the template precisely, and (c) propagate any amendments across dependent artifacts.

Follow this execution flow:

1. Load the existing constitution template at `.specify/memory/constitution.md`.
   - Identify every placeholder token of the form `[ALL_CAPS_IDENTIFIER]`.
   **IMPORTANT**: The user might require less or more principles than the ones used in the template. If a number is specified, respect that - follow the general template. You will update the doc accordingly.

2. Collect/derive values for placeholders:
   - If user input (conversation) supplies a value, use it.
   - Otherwise infer from existing repo context (README, docs, prior constitution versions if embedded).
   - For governance dates: `RATIFICATION_DATE` is the original adoption date (if unknown ask or mark TODO), `LAST_AMENDED_DATE` is today if changes are made, otherwise keep previous.
   - `CONSTITUTION_VERSION` must increment according to semantic versioning rules:
     * MAJOR: Backward incompatible governance/principle removals or redefinitions.
     * MINOR: New principle/section added or materially expanded guidance.
     * PATCH: Clarifications, wording, typo fixes, non-semantic refinements.
   - If version bump type ambiguous, propose reasoning before finalizing.

3. Draft the updated constitution content:
   - Replace every placeholder with concrete text (no bracketed tokens left except intentionally retained template slots that the project has chosen not to define yet—explicitly justify any left).
   - Preserve heading hierarchy and comments can be removed once replaced unless they still add clarifying guidance.
   - Ensure each Principle section: succinct name line, paragraph (or bullet list) capturing non‑negotiable rules, explicit rationale if not obvious.
   - Ensure Governance section lists amendment procedure, versioning policy, and compliance review expectations.

4. Consistency propagation checklist (convert prior checklist into active validations):
   - Read `.specify/templates/plan-template.md` and ensure any "Constitution Check" or rules align with updated principles.
   - Read `.specify/templates/spec-template.md` for scope/requirements alignment—update if constitution adds/removes mandatory sections or constraints.
   - Read `.specify/templates/tasks-template.md` and ensure task categorization reflects new or removed principle-driven task types (e.g., observability, versioning, testing discipline).
   - Read each command file in `.specify/templates/commands/*.md` (including this one) to verify no outdated references (agent-specific names like CLAUDE only) remain when generic guidance is required.
   - Read any runtime guidance docs (e.g., `README.md`, `docs/quickstart.md`, or agent-specific guidance files if present). Update references to principles changed.

5. Produce a Sync Impact Report (prepend as an HTML comment at top of the constitution file after update):
   - Version change: old → new
   - List of modified principles (old title → new title if renamed)
   - Added sections
   - Removed sections
   - Templates requiring updates (✅ updated / ⚠ pending) with file paths
   - Follow-up TODOs if any placeholders intentionally deferred.

6. Validation before final output:
   - No remaining unexplained bracket tokens.
   - Version line matches report.
   - Dates ISO format YYYY-MM-DD.
   - Principles are declarative, testable, and free of vague language ("should" → replace with MUST/SHOULD rationale where appropriate).

7. Write the completed constitution back to `.specify/memory/constitution.md` (overwrite).

8. Output a final summary to the user with:
   - New version and bump rationale.
   - Any files flagged for manual follow-up.
   - Suggested commit message (e.g., `docs: amend constitution to vX.Y.Z (principle additions + governance update)`).

Formatting & Style Requirements:
- Use Markdown headings exactly as in the template (do not demote/promote levels).
- Wrap long rationale lines to keep readability (<100 chars ideally) but do not hard enforce with awkward breaks.
- Keep a single blank line between sections.
- Avoid trailing whitespace.

If the user supplies partial updates (e.g., only one principle revision), still perform validation and version decision steps.

If critical info missing (e.g., ratification date truly unknown), insert `TODO(<FIELD_NAME>): explanation` and include in the Sync Impact Report under deferred items.

Do not create a new template; always operate on the existing `.specify/memory/constitution.md` file.


================================================
FILE: .cursor/commands/implement.md
================================================
---
description: Execute the implementation plan by processing and executing all tasks defined in tasks.md
---

The user input can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

1. Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.

2. Load and analyze the implementation context:
   - **REQUIRED**: Read tasks.md for the complete task list and execution plan
   - **REQUIRED**: Read plan.md for tech stack, architecture, and file structure
   - **IF EXISTS**: Read data-model.md for entities and relationships
   - **IF EXISTS**: Read contracts/ for API specifications and test requirements
   - **IF EXISTS**: Read research.md for technical decisions and constraints
   - **IF EXISTS**: Read quickstart.md for integration scenarios

3. Parse tasks.md structure and extract:
   - **Task phases**: Setup, Tests, Core, Integration, Polish
   - **Task dependencies**: Sequential vs parallel execution rules
   - **Task details**: ID, description, file paths, parallel markers [P]
   - **Execution flow**: Order and dependency requirements

4. Execute implementation following the task plan:
   - **Phase-by-phase execution**: Complete each phase before moving to the next
   - **Respect dependencies**: Run sequential tasks in order, parallel tasks [P] can run together  
   - **Follow TDD approach**: Execute test tasks before their corresponding implementation tasks
   - **File-based coordination**: Tasks affecting the same files must run sequentially
   - **Validation checkpoints**: Verify each phase completion before proceeding

5. Implementation execution rules:
   - **Setup first**: Initialize project structure, dependencies, configuration
   - **Tests before code**: If you need to write tests for contracts, entities, and integration scenarios
   - **Core development**: Implement models, services, CLI commands, endpoints
   - **Integration work**: Database connections, middleware, logging, external services
   - **Polish and validation**: Unit tests, performance optimization, documentation

6. Progress tracking and error handling:
   - Report progress after each completed task
   - Halt execution if any non-parallel task fails
   - For parallel tasks [P], continue with successful tasks, report failed ones
   - Provide clear error messages with context for debugging
   - Suggest next steps if implementation cannot proceed
   - **IMPORTANT** For completed tasks, make sure to mark the task off as [X] in the tasks file.

7. Completion validation:
   - Verify all required tasks are completed
   - Check that implemented features match the original specification
   - Validate that tests pass and coverage meets requirements
   - Confirm the implementation follows the technical plan
   - Report final status with summary of completed work

Note: This command assumes a complete task breakdown exists in tasks.md. If tasks are incomplete or missing, suggest running `/tasks` first to regenerate the task list.


================================================
FILE: .cursor/commands/plan.md
================================================
---
description: Execute the implementation planning workflow using the plan template to generate design artifacts.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

Given the implementation details provided as an argument, do this:

1. Run `.specify/scripts/bash/setup-plan.sh --json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute.
   - BEFORE proceeding, inspect FEATURE_SPEC for a `## Clarifications` section with at least one `Session` subheading. If missing or clearly ambiguous areas remain (vague adjectives, unresolved critical choices), PAUSE and instruct the user to run `/clarify` first to reduce rework. Only continue if: (a) Clarifications exist OR (b) an explicit user override is provided (e.g., "proceed without clarification"). Do not attempt to fabricate clarifications yourself.
2. Read and analyze the feature specification to understand:
   - The feature requirements and user stories
   - Functional and non-functional requirements
   - Success criteria and acceptance criteria
   - Any technical constraints or dependencies mentioned

3. Read the constitution at `.specify/memory/constitution.md` to understand constitutional requirements.

4. Execute the implementation plan template:
   - Load `.specify/templates/plan-template.md` (already copied to IMPL_PLAN path)
   - Set Input path to FEATURE_SPEC
   - Run the Execution Flow (main) function steps 1-9
   - The template is self-contained and executable
   - Follow error handling and gate checks as specified
   - Let the template guide artifact generation in $SPECS_DIR:
     * Phase 0 generates research.md
     * Phase 1 generates data-model.md, contracts/, quickstart.md
     * Phase 2 generates tasks.md
   - Incorporate user-provided details from arguments into Technical Context: $ARGUMENTS
   - Update Progress Tracking as you complete each phase

5. Verify execution completed:
   - Check Progress Tracking shows all phases complete
   - Ensure all required artifacts were generated
   - Confirm no ERROR states in execution

6. Report results with branch name, file paths, and generated artifacts.

Use absolute paths with the repository root for all file operations to avoid path issues.


================================================
FILE: .cursor/commands/specify.md
================================================
---
description: Create or update the feature specification from a natural language feature description.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

The text the user typed after `/specify` in the triggering message **is** the feature description. Assume you always have it available in this conversation even if `$ARGUMENTS` appears literally below. Do not ask the user to repeat it unless they provided an empty command.

Given that feature description, do this:

1. Run the script `.specify/scripts/bash/create-new-feature.sh --json "$ARGUMENTS"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute.
  **IMPORTANT** You must only ever run this script once. The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for.
2. Load `.specify/templates/spec-template.md` to understand required sections.
3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
4. Report completion with branch name, spec file path, and readiness for the next phase.

Note: The script creates and checks out the new branch and initializes the spec file before writing.


================================================
FILE: .cursor/commands/tasks.md
================================================
---
description: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

1. Run `.specify/scripts/bash/check-prerequisites.sh --json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.
2. Load and analyze available design documents:
   - Always read plan.md for tech stack and libraries
   - IF EXISTS: Read data-model.md for entities
   - IF EXISTS: Read contracts/ for API endpoints
   - IF EXISTS: Read research.md for technical decisions
   - IF EXISTS: Read quickstart.md for test scenarios

   Note: Not all projects have all documents. For example:
   - CLI tools might not have contracts/
   - Simple libraries might not need data-model.md
   - Generate tasks based on what's available

3. Generate tasks following the template:
   - Use `.specify/templates/tasks-template.md` as the base
   - Replace example tasks with actual tasks based on:
     * **Setup tasks**: Project init, dependencies, linting
     * **Test tasks [P]**: One per contract, one per integration scenario
     * **Core tasks**: One per entity, service, CLI command, endpoint
     * **Integration tasks**: DB connections, middleware, logging
     * **Polish tasks [P]**: Unit tests, performance, docs

4. Task generation rules:
   - Each contract file → contract test task marked [P]
   - Each entity in data-model → model creation task marked [P]
   - Each endpoint → implementation task (not parallel if shared files)
   - Each user story → integration test marked [P]
   - Different files = can be parallel [P]
   - Same file = sequential (no [P])

5. Order tasks by dependencies:
   - Setup before everything
   - Tests before implementation (TDD)
   - Models before services
   - Services before endpoints
   - Core before integration
   - Everything before polish

6. Include parallel execution examples:
   - Group [P] tasks that can run together
   - Show actual Task agent commands

7. Create FEATURE_DIR/tasks.md with:
   - Correct feature name from implementation plan
   - Numbered tasks (T001, T002, etc.)
   - Clear file paths for each task
   - Dependency notes
   - Parallel execution guidance

Context for task generation: $ARGUMENTS

The tasks.md should be immediately executable - each task must be specific enough that an LLM can complete it without additional context.


================================================
FILE: .cursor/rules/specify-rules.mdc
================================================
# python-audio-separator Development Guidelines

Auto-generated from all feature plans. Last updated: 2025-09-25

## Active Technologies
- Python 3.11+ + PyTorch, librosa, soundfile, numpy, onnxruntime (001-update-roformer-implementation)

## Project Structure
```
src/
tests/
```

## Commands
cd src [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES][ONLY COMMANDS FOR ACTIVE TECHNOLOGIES] pytest [ONLY COMMANDS FOR ACTIVE TECHNOLOGIES][ONLY COMMANDS FOR ACTIVE TECHNOLOGIES] ruff check .

## Code Style
Python 3.11+: Follow standard conventions

## Recent Changes
- 001-update-roformer-implementation: Added Python 3.11+ + PyTorch, librosa, soundfile, numpy, onnxruntime

<!-- MANUAL ADDITIONS START -->
<!-- MANUAL ADDITIONS END -->

================================================
FILE: .github/FUNDING.yml
================================================
github: beveradb

================================================
FILE: .github/ISSUE_TEMPLATE/BUG_REPORT.yml
================================================
name: Bug report
description: Report a problem you encountered
title: "[Bug]: "
labels: ["bug"]
body:
  - type: textarea
    id: bug-description
    attributes:
      label: Describe the bug
      description: Please provide a concise description of the bug.
      placeholder: Bug description
    validations:
      required: true
  - type: checkboxes
    attributes:
      label: Have you searched for existing issues?  🔎
      description: Please search to see if there is already an issue for the problem you encountered.
      options:
        - label: I have searched and found no existing issues.
          required: true
  - type: markdown
    attributes:
      value: "---"
  - type: textarea
    id: screenshots
    attributes:
      label: Screenshots or Videos
      description: Add screenshots, gifs, or videos to help explain your problem.
      placeholder: Upload screenshots, gifs, and videos here.
    validations:
      required: false
  - type: textarea
    id: logs
    attributes:
      label: Logs
      description: Please include the full stack trace of the errors you encounter.
      render: shell
  - type: markdown
    attributes:
      value: "---"
  - type: textarea
    id: system-info
    attributes:
      label: System Info
      description: Provide information about your system.
      value: |
        Operating System: 
        Python version: 
        Other...
      render: shell
    validations:
      required: true
  - type: textarea
    id: additional
    attributes:
      label: Additional Information
      description: Add any other useful information about the problem here.
      placeholder: Is there any additional helpful information you can share?
    validations:
      required: false


================================================
FILE: .github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml
================================================
name: Feature request
description: Suggest an idea for this project
title: "[Feature]: "
labels: ["enhancement", "feature"]
body:
  - type: textarea
    id: description
    attributes:
      label: Description
      description: Clearly and concisely describe what you would like to change, add, or implement.
      placeholder: Tell us your idea.
    validations:
      required: true


================================================
FILE: .github/prompts/analyze.prompt.md
================================================
---
description: Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and tasks.md after task generation.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

Goal: Identify inconsistencies, duplications, ambiguities, and underspecified items across the three core artifacts (`spec.md`, `plan.md`, `tasks.md`) before implementation. This command MUST run only after `/tasks` has successfully produced a complete `tasks.md`.

STRICTLY READ-ONLY: Do **not** modify any files. Output a structured analysis report. Offer an optional remediation plan (user must explicitly approve before any follow-up editing commands would be invoked manually).

Constitution Authority: The project constitution (`.specify/memory/constitution.md`) is **non-negotiable** within this analysis scope. Constitution conflicts are automatically CRITICAL and require adjustment of the spec, plan, or tasks—not dilution, reinterpretation, or silent ignoring of the principle. If a principle itself needs to change, that must occur in a separate, explicit constitution update outside `/analyze`.

Execution steps:

1. Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` once from repo root and parse JSON for FEATURE_DIR and AVAILABLE_DOCS. Derive absolute paths:
   - SPEC = FEATURE_DIR/spec.md
   - PLAN = FEATURE_DIR/plan.md
   - TASKS = FEATURE_DIR/tasks.md
   Abort with an error message if any required file is missing (instruct the user to run missing prerequisite command).

2. Load artifacts:
   - Parse spec.md sections: Overview/Context, Functional Requirements, Non-Functional Requirements, User Stories, Edge Cases (if present).
   - Parse plan.md: Architecture/stack choices, Data Model references, Phases, Technical constraints.
   - Parse tasks.md: Task IDs, descriptions, phase grouping, parallel markers [P], referenced file paths.
   - Load constitution `.specify/memory/constitution.md` for principle validation.

3. Build internal semantic models:
   - Requirements inventory: Each functional + non-functional requirement with a stable key (derive slug based on imperative phrase; e.g., "User can upload file" -> `user-can-upload-file`).
   - User story/action inventory.
   - Task coverage mapping: Map each task to one or more requirements or stories (inference by keyword / explicit reference patterns like IDs or key phrases).
   - Constitution rule set: Extract principle names and any MUST/SHOULD normative statements.

4. Detection passes:
   A. Duplication detection:
      - Identify near-duplicate requirements. Mark lower-quality phrasing for consolidation.
   B. Ambiguity detection:
      - Flag vague adjectives (fast, scalable, secure, intuitive, robust) lacking measurable criteria.
      - Flag unresolved placeholders (TODO, TKTK, ???, <placeholder>, etc.).
   C. Underspecification:
      - Requirements with verbs but missing object or measurable outcome.
      - User stories missing acceptance criteria alignment.
      - Tasks referencing files or components not defined in spec/plan.
   D. Constitution alignment:
      - Any requirement or plan element conflicting with a MUST principle.
      - Missing mandated sections or quality gates from constitution.
   E. Coverage gaps:
      - Requirements with zero associated tasks.
      - Tasks with no mapped requirement/story.
      - Non-functional requirements not reflected in tasks (e.g., performance, security).
   F. Inconsistency:
      - Terminology drift (same concept named differently across files).
      - Data entities referenced in plan but absent in spec (or vice versa).
      - Task ordering contradictions (e.g., integration tasks before foundational setup tasks without dependency note).
      - Conflicting requirements (e.g., one requires to use Next.js while other says to use Vue as the framework).

5. Severity assignment heuristic:
   - CRITICAL: Violates constitution MUST, missing core spec artifact, or requirement with zero coverage that blocks baseline functionality.
   - HIGH: Duplicate or conflicting requirement, ambiguous security/performance attribute, untestable acceptance criterion.
   - MEDIUM: Terminology drift, missing non-functional task coverage, underspecified edge case.
   - LOW: Style/wording improvements, minor redundancy not affecting execution order.

6. Produce a Markdown report (no file writes) with sections:

   ### Specification Analysis Report
   | ID | Category | Severity | Location(s) | Summary | Recommendation |
   |----|----------|----------|-------------|---------|----------------|
   | A1 | Duplication | HIGH | spec.md:L120-134 | Two similar requirements ... | Merge phrasing; keep clearer version |
   (Add one row per finding; generate stable IDs prefixed by category initial.)

   Additional subsections:
   - Coverage Summary Table:
     | Requirement Key | Has Task? | Task IDs | Notes |
   - Constitution Alignment Issues (if any)
   - Unmapped Tasks (if any)
   - Metrics:
     * Total Requirements
     * Total Tasks
     * Coverage % (requirements with >=1 task)
     * Ambiguity Count
     * Duplication Count
     * Critical Issues Count

7. At end of report, output a concise Next Actions block:
   - If CRITICAL issues exist: Recommend resolving before `/implement`.
   - If only LOW/MEDIUM: User may proceed, but provide improvement suggestions.
   - Provide explicit command suggestions: e.g., "Run /specify with refinement", "Run /plan to adjust architecture", "Manually edit tasks.md to add coverage for 'performance-metrics'".

8. Ask the user: "Would you like me to suggest concrete remediation edits for the top N issues?" (Do NOT apply them automatically.)

Behavior rules:
- NEVER modify files.
- NEVER hallucinate missing sections—if absent, report them.
- KEEP findings deterministic: if rerun without changes, produce consistent IDs and counts.
- LIMIT total findings in the main table to 50; aggregate remainder in a summarized overflow note.
- If zero issues found, emit a success report with coverage statistics and proceed recommendation.

Context: $ARGUMENTS


================================================
FILE: .github/prompts/clarify.prompt.md
================================================
---
description: Identify underspecified areas in the current feature spec by asking up to 5 highly targeted clarification questions and encoding answers back into the spec.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

Goal: Detect and reduce ambiguity or missing decision points in the active feature specification and record the clarifications directly in the spec file.

Note: This clarification workflow is expected to run (and be completed) BEFORE invoking `/plan`. If the user explicitly states they are skipping clarification (e.g., exploratory spike), you may proceed, but must warn that downstream rework risk increases.

Execution steps:

1. Run `.specify/scripts/bash/check-prerequisites.sh --json --paths-only` from repo root **once** (combined `--json --paths-only` mode / `-Json -PathsOnly`). Parse minimal JSON payload fields:
   - `FEATURE_DIR`
   - `FEATURE_SPEC`
   - (Optionally capture `IMPL_PLAN`, `TASKS` for future chained flows.)
   - If JSON parsing fails, abort and instruct user to re-run `/specify` or verify feature branch environment.

2. Load the current spec file. Perform a structured ambiguity & coverage scan using this taxonomy. For each category, mark status: Clear / Partial / Missing. Produce an internal coverage map used for prioritization (do not output raw map unless no questions will be asked).

   Functional Scope & Behavior:
   - Core user goals & success criteria
   - Explicit out-of-scope declarations
   - User roles / personas differentiation

   Domain & Data Model:
   - Entities, attributes, relationships
   - Identity & uniqueness rules
   - Lifecycle/state transitions
   - Data volume / scale assumptions

   Interaction & UX Flow:
   - Critical user journeys / sequences
   - Error/empty/loading states
   - Accessibility or localization notes

   Non-Functional Quality Attributes:
   - Performance (latency, throughput targets)
   - Scalability (horizontal/vertical, limits)
   - Reliability & availability (uptime, recovery expectations)
   - Observability (logging, metrics, tracing signals)
   - Security & privacy (authN/Z, data protection, threat assumptions)
   - Compliance / regulatory constraints (if any)

   Integration & External Dependencies:
   - External services/APIs and failure modes
   - Data import/export formats
   - Protocol/versioning assumptions

   Edge Cases & Failure Handling:
   - Negative scenarios
   - Rate limiting / throttling
   - Conflict resolution (e.g., concurrent edits)

   Constraints & Tradeoffs:
   - Technical constraints (language, storage, hosting)
   - Explicit tradeoffs or rejected alternatives

   Terminology & Consistency:
   - Canonical glossary terms
   - Avoided synonyms / deprecated terms

   Completion Signals:
   - Acceptance criteria testability
   - Measurable Definition of Done style indicators

   Misc / Placeholders:
   - TODO markers / unresolved decisions
   - Ambiguous adjectives ("robust", "intuitive") lacking quantification

   For each category with Partial or Missing status, add a candidate question opportunity unless:
   - Clarification would not materially change implementation or validation strategy
   - Information is better deferred to planning phase (note internally)

3. Generate (internally) a prioritized queue of candidate clarification questions (maximum 5). Do NOT output them all at once. Apply these constraints:
    - Maximum of 5 total questions across the whole session.
    - Each question must be answerable with EITHER:
       * A short multiple‑choice selection (2–5 distinct, mutually exclusive options), OR
       * A one-word / short‑phrase answer (explicitly constrain: "Answer in <=5 words").
   - Only include questions whose answers materially impact architecture, data modeling, task decomposition, test design, UX behavior, operational readiness, or compliance validation.
   - Ensure category coverage balance: attempt to cover the highest impact unresolved categories first; avoid asking two low-impact questions when a single high-impact area (e.g., security posture) is unresolved.
   - Exclude questions already answered, trivial stylistic preferences, or plan-level execution details (unless blocking correctness).
   - Favor clarifications that reduce downstream rework risk or prevent misaligned acceptance tests.
   - If more than 5 categories remain unresolved, select the top 5 by (Impact * Uncertainty) heuristic.

4. Sequential questioning loop (interactive):
    - Present EXACTLY ONE question at a time.
    - For multiple‑choice questions render options as a Markdown table:

       | Option | Description |
       |--------|-------------|
       | A | <Option A description> |
       | B | <Option B description> |
       | C | <Option C description> | (add D/E as needed up to 5)
       | Short | Provide a different short answer (<=5 words) | (Include only if free-form alternative is appropriate)

    - For short‑answer style (no meaningful discrete options), output a single line after the question: `Format: Short answer (<=5 words)`.
    - After the user answers:
       * Validate the answer maps to one option or fits the <=5 word constraint.
       * If ambiguous, ask for a quick disambiguation (count still belongs to same question; do not advance).
       * Once satisfactory, record it in working memory (do not yet write to disk) and move to the next queued question.
    - Stop asking further questions when:
       * All critical ambiguities resolved early (remaining queued items become unnecessary), OR
       * User signals completion ("done", "good", "no more"), OR
       * You reach 5 asked questions.
    - Never reveal future queued questions in advance.
    - If no valid questions exist at start, immediately report no critical ambiguities.

5. Integration after EACH accepted answer (incremental update approach):
    - Maintain in-memory representation of the spec (loaded once at start) plus the raw file contents.
    - For the first integrated answer in this session:
       * Ensure a `## Clarifications` section exists (create it just after the highest-level contextual/overview section per the spec template if missing).
       * Under it, create (if not present) a `### Session YYYY-MM-DD` subheading for today.
    - Append a bullet line immediately after acceptance: `- Q: <question> → A: <final answer>`.
    - Then immediately apply the clarification to the most appropriate section(s):
       * Functional ambiguity → Update or add a bullet in Functional Requirements.
       * User interaction / actor distinction → Update User Stories or Actors subsection (if present) with clarified role, constraint, or scenario.
       * Data shape / entities → Update Data Model (add fields, types, relationships) preserving ordering; note added constraints succinctly.
       * Non-functional constraint → Add/modify measurable criteria in Non-Functional / Quality Attributes section (convert vague adjective to metric or explicit target).
       * Edge case / negative flow → Add a new bullet under Edge Cases / Error Handling (or create such subsection if template provides placeholder for it).
       * Terminology conflict → Normalize term across spec; retain original only if necessary by adding `(formerly referred to as "X")` once.
    - If the clarification invalidates an earlier ambiguous statement, replace that statement instead of duplicating; leave no obsolete contradictory text.
    - Save the spec file AFTER each integration to minimize risk of context loss (atomic overwrite).
    - Preserve formatting: do not reorder unrelated sections; keep heading hierarchy intact.
    - Keep each inserted clarification minimal and testable (avoid narrative drift).

6. Validation (performed after EACH write plus final pass):
   - Clarifications session contains exactly one bullet per accepted answer (no duplicates).
   - Total asked (accepted) questions ≤ 5.
   - Updated sections contain no lingering vague placeholders the new answer was meant to resolve.
   - No contradictory earlier statement remains (scan for now-invalid alternative choices removed).
   - Markdown structure valid; only allowed new headings: `## Clarifications`, `### Session YYYY-MM-DD`.
   - Terminology consistency: same canonical term used across all updated sections.

7. Write the updated spec back to `FEATURE_SPEC`.

8. Report completion (after questioning loop ends or early termination):
   - Number of questions asked & answered.
   - Path to updated spec.
   - Sections touched (list names).
   - Coverage summary table listing each taxonomy category with Status: Resolved (was Partial/Missing and addressed), Deferred (exceeds question quota or better suited for planning), Clear (already sufficient), Outstanding (still Partial/Missing but low impact).
   - If any Outstanding or Deferred remain, recommend whether to proceed to `/plan` or run `/clarify` again later post-plan.
   - Suggested next command.

Behavior rules:
- If no meaningful ambiguities found (or all potential questions would be low-impact), respond: "No critical ambiguities detected worth formal clarification." and suggest proceeding.
- If spec file missing, instruct user to run `/specify` first (do not create a new spec here).
- Never exceed 5 total asked questions (clarification retries for a single question do not count as new questions).
- Avoid speculative tech stack questions unless the absence blocks functional clarity.
- Respect user early termination signals ("stop", "done", "proceed").
 - If no questions asked due to full coverage, output a compact coverage summary (all categories Clear) then suggest advancing.
 - If quota reached with unresolved high-impact categories remaining, explicitly flag them under Deferred with rationale.

Context for prioritization: $ARGUMENTS


================================================
FILE: .github/prompts/constitution.prompt.md
================================================
---
description: Create or update the project constitution from interactive or provided principle inputs, ensuring all dependent templates stay in sync.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

You are updating the project constitution at `.specify/memory/constitution.md`. This file is a TEMPLATE containing placeholder tokens in square brackets (e.g. `[PROJECT_NAME]`, `[PRINCIPLE_1_NAME]`). Your job is to (a) collect/derive concrete values, (b) fill the template precisely, and (c) propagate any amendments across dependent artifacts.

Follow this execution flow:

1. Load the existing constitution template at `.specify/memory/constitution.md`.
   - Identify every placeholder token of the form `[ALL_CAPS_IDENTIFIER]`.
   **IMPORTANT**: The user might require less or more principles than the ones used in the template. If a number is specified, respect that - follow the general template. You will update the doc accordingly.

2. Collect/derive values for placeholders:
   - If user input (conversation) supplies a value, use it.
   - Otherwise infer from existing repo context (README, docs, prior constitution versions if embedded).
   - For governance dates: `RATIFICATION_DATE` is the original adoption date (if unknown ask or mark TODO), `LAST_AMENDED_DATE` is today if changes are made, otherwise keep previous.
   - `CONSTITUTION_VERSION` must increment according to semantic versioning rules:
     * MAJOR: Backward incompatible governance/principle removals or redefinitions.
     * MINOR: New principle/section added or materially expanded guidance.
     * PATCH: Clarifications, wording, typo fixes, non-semantic refinements.
   - If version bump type ambiguous, propose reasoning before finalizing.

3. Draft the updated constitution content:
   - Replace every placeholder with concrete text (no bracketed tokens left except intentionally retained template slots that the project has chosen not to define yet—explicitly justify any left).
   - Preserve heading hierarchy and comments can be removed once replaced unless they still add clarifying guidance.
   - Ensure each Principle section: succinct name line, paragraph (or bullet list) capturing non‑negotiable rules, explicit rationale if not obvious.
   - Ensure Governance section lists amendment procedure, versioning policy, and compliance review expectations.

4. Consistency propagation checklist (convert prior checklist into active validations):
   - Read `.specify/templates/plan-template.md` and ensure any "Constitution Check" or rules align with updated principles.
   - Read `.specify/templates/spec-template.md` for scope/requirements alignment—update if constitution adds/removes mandatory sections or constraints.
   - Read `.specify/templates/tasks-template.md` and ensure task categorization reflects new or removed principle-driven task types (e.g., observability, versioning, testing discipline).
   - Read each command file in `.specify/templates/commands/*.md` (including this one) to verify no outdated references (agent-specific names like CLAUDE only) remain when generic guidance is required.
   - Read any runtime guidance docs (e.g., `README.md`, `docs/quickstart.md`, or agent-specific guidance files if present). Update references to principles changed.

5. Produce a Sync Impact Report (prepend as an HTML comment at top of the constitution file after update):
   - Version change: old → new
   - List of modified principles (old title → new title if renamed)
   - Added sections
   - Removed sections
   - Templates requiring updates (✅ updated / ⚠ pending) with file paths
   - Follow-up TODOs if any placeholders intentionally deferred.

6. Validation before final output:
   - No remaining unexplained bracket tokens.
   - Version line matches report.
   - Dates ISO format YYYY-MM-DD.
   - Principles are declarative, testable, and free of vague language ("should" → replace with MUST/SHOULD rationale where appropriate).

7. Write the completed constitution back to `.specify/memory/constitution.md` (overwrite).

8. Output a final summary to the user with:
   - New version and bump rationale.
   - Any files flagged for manual follow-up.
   - Suggested commit message (e.g., `docs: amend constitution to vX.Y.Z (principle additions + governance update)`).

Formatting & Style Requirements:
- Use Markdown headings exactly as in the template (do not demote/promote levels).
- Wrap long rationale lines to keep readability (<100 chars ideally) but do not hard enforce with awkward breaks.
- Keep a single blank line between sections.
- Avoid trailing whitespace.

If the user supplies partial updates (e.g., only one principle revision), still perform validation and version decision steps.

If critical info missing (e.g., ratification date truly unknown), insert `TODO(<FIELD_NAME>): explanation` and include in the Sync Impact Report under deferred items.

Do not create a new template; always operate on the existing `.specify/memory/constitution.md` file.


================================================
FILE: .github/prompts/implement.prompt.md
================================================
---
description: Execute the implementation plan by processing and executing all tasks defined in tasks.md
---

The user input can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

1. Run `.specify/scripts/bash/check-prerequisites.sh --json --require-tasks --include-tasks` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.

2. Load and analyze the implementation context:
   - **REQUIRED**: Read tasks.md for the complete task list and execution plan
   - **REQUIRED**: Read plan.md for tech stack, architecture, and file structure
   - **IF EXISTS**: Read data-model.md for entities and relationships
   - **IF EXISTS**: Read contracts/ for API specifications and test requirements
   - **IF EXISTS**: Read research.md for technical decisions and constraints
   - **IF EXISTS**: Read quickstart.md for integration scenarios

3. Parse tasks.md structure and extract:
   - **Task phases**: Setup, Tests, Core, Integration, Polish
   - **Task dependencies**: Sequential vs parallel execution rules
   - **Task details**: ID, description, file paths, parallel markers [P]
   - **Execution flow**: Order and dependency requirements

4. Execute implementation following the task plan:
   - **Phase-by-phase execution**: Complete each phase before moving to the next
   - **Respect dependencies**: Run sequential tasks in order, parallel tasks [P] can run together  
   - **Follow TDD approach**: Execute test tasks before their corresponding implementation tasks
   - **File-based coordination**: Tasks affecting the same files must run sequentially
   - **Validation checkpoints**: Verify each phase completion before proceeding

5. Implementation execution rules:
   - **Setup first**: Initialize project structure, dependencies, configuration
   - **Tests before code**: If you need to write tests for contracts, entities, and integration scenarios
   - **Core development**: Implement models, services, CLI commands, endpoints
   - **Integration work**: Database connections, middleware, logging, external services
   - **Polish and validation**: Unit tests, performance optimization, documentation

6. Progress tracking and error handling:
   - Report progress after each completed task
   - Halt execution if any non-parallel task fails
   - For parallel tasks [P], continue with successful tasks, report failed ones
   - Provide clear error messages with context for debugging
   - Suggest next steps if implementation cannot proceed
   - **IMPORTANT** For completed tasks, make sure to mark the task off as [X] in the tasks file.

7. Completion validation:
   - Verify all required tasks are completed
   - Check that implemented features match the original specification
   - Validate that tests pass and coverage meets requirements
   - Confirm the implementation follows the technical plan
   - Report final status with summary of completed work

Note: This command assumes a complete task breakdown exists in tasks.md. If tasks are incomplete or missing, suggest running `/tasks` first to regenerate the task list.


================================================
FILE: .github/prompts/plan.prompt.md
================================================
---
description: Execute the implementation planning workflow using the plan template to generate design artifacts.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

Given the implementation details provided as an argument, do this:

1. Run `.specify/scripts/bash/setup-plan.sh --json` from the repo root and parse JSON for FEATURE_SPEC, IMPL_PLAN, SPECS_DIR, BRANCH. All future file paths must be absolute.
   - BEFORE proceeding, inspect FEATURE_SPEC for a `## Clarifications` section with at least one `Session` subheading. If missing or clearly ambiguous areas remain (vague adjectives, unresolved critical choices), PAUSE and instruct the user to run `/clarify` first to reduce rework. Only continue if: (a) Clarifications exist OR (b) an explicit user override is provided (e.g., "proceed without clarification"). Do not attempt to fabricate clarifications yourself.
2. Read and analyze the feature specification to understand:
   - The feature requirements and user stories
   - Functional and non-functional requirements
   - Success criteria and acceptance criteria
   - Any technical constraints or dependencies mentioned

3. Read the constitution at `.specify/memory/constitution.md` to understand constitutional requirements.

4. Execute the implementation plan template:
   - Load `.specify/templates/plan-template.md` (already copied to IMPL_PLAN path)
   - Set Input path to FEATURE_SPEC
   - Run the Execution Flow (main) function steps 1-9
   - The template is self-contained and executable
   - Follow error handling and gate checks as specified
   - Let the template guide artifact generation in $SPECS_DIR:
     * Phase 0 generates research.md
     * Phase 1 generates data-model.md, contracts/, quickstart.md
     * Phase 2 generates tasks.md
   - Incorporate user-provided details from arguments into Technical Context: $ARGUMENTS
   - Update Progress Tracking as you complete each phase

5. Verify execution completed:
   - Check Progress Tracking shows all phases complete
   - Ensure all required artifacts were generated
   - Confirm no ERROR states in execution

6. Report results with branch name, file paths, and generated artifacts.

Use absolute paths with the repository root for all file operations to avoid path issues.


================================================
FILE: .github/prompts/specify.prompt.md
================================================
---
description: Create or update the feature specification from a natural language feature description.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

The text the user typed after `/specify` in the triggering message **is** the feature description. Assume you always have it available in this conversation even if `$ARGUMENTS` appears literally below. Do not ask the user to repeat it unless they provided an empty command.

Given that feature description, do this:

1. Run the script `.specify/scripts/bash/create-new-feature.sh --json "$ARGUMENTS"` from repo root and parse its JSON output for BRANCH_NAME and SPEC_FILE. All file paths must be absolute.
  **IMPORTANT** You must only ever run this script once. The JSON is provided in the terminal as output - always refer to it to get the actual content you're looking for.
2. Load `.specify/templates/spec-template.md` to understand required sections.
3. Write the specification to SPEC_FILE using the template structure, replacing placeholders with concrete details derived from the feature description (arguments) while preserving section order and headings.
4. Report completion with branch name, spec file path, and readiness for the next phase.

Note: The script creates and checks out the new branch and initializes the spec file before writing.


================================================
FILE: .github/prompts/tasks.prompt.md
================================================
---
description: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts.
---

The user input to you can be provided directly by the agent or as a command argument - you **MUST** consider it before proceeding with the prompt (if not empty).

User input:

$ARGUMENTS

1. Run `.specify/scripts/bash/check-prerequisites.sh --json` from repo root and parse FEATURE_DIR and AVAILABLE_DOCS list. All paths must be absolute.
2. Load and analyze available design documents:
   - Always read plan.md for tech stack and libraries
   - IF EXISTS: Read data-model.md for entities
   - IF EXISTS: Read contracts/ for API endpoints
   - IF EXISTS: Read research.md for technical decisions
   - IF EXISTS: Read quickstart.md for test scenarios

   Note: Not all projects have all documents. For example:
   - CLI tools might not have contracts/
   - Simple libraries might not need data-model.md
   - Generate tasks based on what's available

3. Generate tasks following the template:
   - Use `.specify/templates/tasks-template.md` as the base
   - Replace example tasks with actual tasks based on:
     * **Setup tasks**: Project init, dependencies, linting
     * **Test tasks [P]**: One per contract, one per integration scenario
     * **Core tasks**: One per entity, service, CLI command, endpoint
     * **Integration tasks**: DB connections, middleware, logging
     * **Polish tasks [P]**: Unit tests, performance, docs

4. Task generation rules:
   - Each contract file → contract test task marked [P]
   - Each entity in data-model → model creation task marked [P]
   - Each endpoint → implementation task (not parallel if shared files)
   - Each user story → integration test marked [P]
   - Different files = can be parallel [P]
   - Same file = sequential (no [P])

5. Order tasks by dependencies:
   - Setup before everything
   - Tests before implementation (TDD)
   - Models before services
   - Services before endpoints
   - Core before integration
   - Everything before polish

6. Include parallel execution examples:
   - Group [P] tasks that can run together
   - Show actual Task agent commands

7. Create FEATURE_DIR/tasks.md with:
   - Correct feature name from implementation plan
   - Numbered tasks (T001, T002, etc.)
   - Clear file paths for each task
   - Dependency notes
   - Parallel execution guidance

Context for task generation: $ARGUMENTS

The tasks.md should be immediately executable - each task must be specific enough that an LLM can complete it without additional context.


================================================
FILE: .github/workflows/deploy-to-cloudrun.yml
================================================
name: Deploy to Cloud Run

on:
  # Deploy when a new PyPI release is published
  workflow_run:
    workflows: ["Publish to PyPI"]
    types: [completed]

  # Deploy on changes to Dockerfile or Cloud Run server
  push:
    branches: [main]
    paths:
      - "Dockerfile.cloudrun"
      - "audio_separator/remote/deploy_cloudrun.py"
      - "audio_separator/ensemble_presets.json"
      - "cloudbuild.yaml"

  # Manual deployment
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    # Only run on successful PyPI publish (or push/manual triggers)
    if: ${{ github.event_name != 'workflow_run' || github.event.workflow_run.conclusion == 'success' }}

    permissions:
      contents: read
      id-token: write  # Required for Workload Identity Federation

    steps:
      - name: Checkout code
        uses: actions/checkout@v4

      - name: Authenticate to Google Cloud
        uses: google-github-actions/auth@v2
        with:
          workload_identity_provider: ${{ secrets.GCP_WORKLOAD_IDENTITY_PROVIDER }}
          service_account: ${{ secrets.GCP_SERVICE_ACCOUNT }}

      - name: Set up Cloud SDK
        uses: google-github-actions/setup-gcloud@v2

      # Use Cloud Build for the Docker build — it has native x86 with enough
      # RAM to load ML models during the build (baking models into the image).
      - name: Build and push via Cloud Build
        run: |
          gcloud builds submit \
            --config cloudbuild.yaml \
            --region=us-east4 \
            --project=nomadkaraoke \
            --substitutions=SHORT_SHA=${GITHUB_SHA::8}

      - name: Deploy to Cloud Run
        run: |
          gcloud run services update audio-separator \
            --image="us-east4-docker.pkg.dev/nomadkaraoke/audio-separator/api:${GITHUB_SHA::8}" \
            --region=us-east4 \
            --project=nomadkaraoke \
            --quiet


================================================
FILE: .github/workflows/deploy-to-modal.yml
================================================
name: deploy-to-modal

on:
  # Deploy after PyPI publish (when new version is available)
  workflow_run:
    workflows: ["publish-to-pypi"]
    types:
      - completed
  # Also deploy on direct changes to Modal deployment files
  push:
    branches:
      - main
    paths:
      - 'audio_separator/remote/deploy_modal.py'
  # Manual trigger
  workflow_dispatch:

jobs:
  deploy-modal:
    # Only run if publish-to-pypi succeeded (or if triggered directly)
    if: |
      github.event_name == 'workflow_dispatch' ||
      github.event_name == 'push' ||
      (github.event_name == 'workflow_run' && github.event.workflow_run.conclusion == 'success')
    runs-on: ubuntu-latest

    steps:
      - name: Checkout repository
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.12'

      - name: Install Modal CLI and dependencies
        run: |
          pip install modal
          # Install dependencies needed to parse deploy_modal.py
          pip install fastapi filetype python-multipart

      - name: Deploy to Modal
        env:
          MODAL_TOKEN_ID: ${{ secrets.MODAL_TOKEN_ID }}
          MODAL_TOKEN_SECRET: ${{ secrets.MODAL_TOKEN_SECRET }}
        run: |
          modal deploy audio_separator/remote/deploy_modal.py

      - name: Verify deployment
        run: |
          sleep 10  # Wait for container to be ready
          VERSION=$(curl -s https://nomadkaraoke--audio-separator-api.modal.run/health | jq -r '.version')
          echo "Deployed version: $VERSION"


================================================
FILE: .github/workflows/github-sponsors.yml
================================================
name: Generate Sponsors README
on:
  workflow_dispatch:
  schedule:
    - cron: 30 15 * * 0-6
permissions:
  contents: write
jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - name: Checkout 🛎️
        uses: actions/checkout@v4

      - name: Generate Sponsors 💖
        uses: JamesIves/github-sponsors-readme-action@v1
        with:
          token: ${{ secrets.SPONSORS_WORKFLOW_PAT }}
          file: 'README.md'

      - name: Deploy to GitHub Pages 🚀
        uses: JamesIves/github-pages-deploy-action@v4
        with:
          branch: main
          folder: '.'


================================================
FILE: .github/workflows/publish-to-docker.yml
================================================
name: publish-to-docker

on:
  push:
    branches:
      - main
    paths:
      - pyproject.toml
      - Dockerfile.cpu
      - Dockerfile.gpu
      - Dockerfile.runpod
  workflow_dispatch:

jobs:
  build-and-push-docker:
    runs-on: ubuntu-latest
    steps:
      - name: Delete huge unnecessary tools folder
        run: rm -rf /opt/hostedtoolcache

      - name: Checkout
        uses: actions/checkout@v4

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.x'

      - name: Install TOML
        run: pip install toml

      - name: Get version from pyproject.toml
        run: |
          VERSION=$(python -c "import toml; print(toml.load('pyproject.toml')['tool']['poetry']['version'])")
          echo "VERSION=$VERSION" >> $GITHUB_ENV

      - name: Set up QEMU
        uses: docker/setup-qemu-action@v3

      - name: Set up Docker Buildx
        uses: docker/setup-buildx-action@v3

      - name: Login to Docker Hub
        uses: docker/login-action@v3
        with:
          username: ${{ secrets.DOCKERHUB_USERNAME }}
          password: ${{ secrets.DOCKERHUB_TOKEN }}

      - name: Build and push Docker image for CPU
        if: ${{ github.ref == 'refs/heads/main' }}
        uses: docker/build-push-action@v5
        with:
          file: Dockerfile.cpu
          context: .
          platforms: linux/amd64,linux/arm64
          push: true
          tags: |
            beveradb/audio-separator:cpu-${{ env.VERSION }}
            beveradb/audio-separator:cpu
            beveradb/audio-separator:latest

      - name: Build and push Docker image for CUDA 11 GPU
        if: ${{ github.ref == 'refs/heads/main' }}
        uses: docker/build-push-action@v5
        with:
          file: Dockerfile.cuda11
          context: .
          platforms: linux/amd64
          push: true
          tags: |
            beveradb/audio-separator:gpu-${{ env.VERSION }}
            beveradb/audio-separator:gpu

      - name: Build and push Docker image for CUDA 12 GPU
        if: ${{ github.ref == 'refs/heads/main' }}
        uses: docker/build-push-action@v5
        with:
          file: Dockerfile.cuda12
          context: .
          platforms: linux/amd64
          push: true
          tags: |
            beveradb/audio-separator:cuda12-${{ env.VERSION }}
            beveradb/audio-separator:cuda12

      # Deliberately commented out because Github CI can't build this runpod image due to disk space limits
      # Instead, I build this (17GB) image locally and push it to Docker Hub manually.
      # - name: Build and push Docker image for Runpod
      #   if: ${{ github.ref == 'refs/heads/main' }}
      #   uses: docker/build-push-action@v5
      #   with:
      #     file: Dockerfile.runpod
      #     context: .
      #     platforms: linux/amd64
      #     push: true
      #     tags: |
      #       beveradb/audio-separator:runpod-${{ env.VERSION }}
      #       beveradb/audio-separator:runpod


================================================
FILE: .github/workflows/publish-to-pypi.yml
================================================
name: publish-to-pypi

on:
  push:
    branches:
      - main
    paths:
      - pyproject.toml
  workflow_dispatch:

jobs:
  # Auto-publish when version is increased
  publish-pypi:
    # Only publish on `main` branch
    if: github.ref == 'refs/heads/main'
    runs-on: ubuntu-latest
    permissions: # Don't forget permissions
      contents: write

    steps:
      - uses: etils-actions/pypi-auto-publish@v1
        with:
          pypi-token: ${{ secrets.PYPI_API_TOKEN }}
          gh-token: ${{ secrets.GITHUB_TOKEN }}
          parse-changelog: false


================================================
FILE: .github/workflows/run-integration-tests.yaml
================================================
name: run-integration-tests

on:
  pull_request:

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      should_run: ${{ steps.filter.outputs.code }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            code:
              - 'audio_separator/**'
              - 'tests/**'
              - 'pyproject.toml'
              - 'poetry.lock'
              - '.github/workflows/run-integration-tests.yaml'

  # ── Integration test jobs (parallel across 3 GPU runners) ──────────
  #
  # Balanced to ~7 min each so all 3 finish around the same time.
  #
  #   ensemble-presets (~8 min): test_ensemble_integration (heaviest single file)
  #   core-models      (~7 min): test_24bit + test_cli + test_separator_output + roformer tests
  #   stems-and-quality (~6 min): test_ensemble_meaningful + test_multi_stem + test_remote_api

  ensemble-presets:
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: [self-hosted, gpu]
    timeout-minutes: 15
    env:
      AUDIO_SEPARATOR_MODEL_DIR: /opt/audio-separator-models
    steps:
      - uses: actions/checkout@v4
      - name: Verify GPU availability
        run: nvidia-smi --query-gpu=driver_version,name,memory.total --format=csv,noheader
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
      - name: Install pipx and poetry
        run: |
          python -m pip install --user pipx && python -m pipx ensurepath
          python -m pipx install poetry
          echo "$HOME/.local/bin" >> $GITHUB_PATH
      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y ffmpeg libsamplerate0 libsamplerate-dev
      - name: Set up Python with cache
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
          cache: poetry
      - name: Install Poetry dependencies (GPU)
        run: poetry install -E gpu
      - name: Verify pre-cached models
        run: |
          MODEL_COUNT=$(ls -1 $AUDIO_SEPARATOR_MODEL_DIR | wc -l)
          echo "Pre-cached models: $MODEL_COUNT"
          if [ "$MODEL_COUNT" -lt 10 ]; then
            echo "::warning::Expected at least 10 pre-cached model files, found $MODEL_COUNT"
          fi
      - name: "Run: ensemble preset tests (~8 min)"
        run: poetry run pytest -sv tests/integration/test_ensemble_integration.py
      - name: Upload test artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: ensemble-presets-results
          path: |
            *.flac
            tests/*.flac

  core-models:
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: [self-hosted, gpu]
    timeout-minutes: 15
    env:
      AUDIO_SEPARATOR_MODEL_DIR: /opt/audio-separator-models
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
      - name: Install pipx and poetry
        run: |
          python -m pip install --user pipx && python -m pipx ensurepath
          python -m pipx install poetry
          echo "$HOME/.local/bin" >> $GITHUB_PATH
      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y ffmpeg libsamplerate0 libsamplerate-dev
      - name: Set up Python with cache
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
          cache: poetry
      - name: Install Poetry dependencies (GPU)
        run: poetry install -E gpu
      - name: "Run: 24-bit, CLI, output, and roformer tests (~7 min)"
        run: |
          poetry run pytest -sv \
            tests/integration/test_24bit_preservation.py \
            tests/integration/test_cli_integration.py \
            tests/integration/test_separator_output_integration.py \
            tests/integration/test_roformer_audio_quality.py \
            tests/integration/test_roformer_backward_compatibility.py \
            tests/integration/test_roformer_config_validation.py \
            tests/integration/test_roformer_e2e.py \
            tests/integration/test_roformer_fallback_mechanism.py \
            tests/integration/test_roformer_model_switching.py \
            tests/integration/test_roformer_new_parameters.py
      - name: Upload test artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: core-models-results
          path: |
            *.flac
            tests/*.flac

  stems-and-quality:
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: [self-hosted, gpu]
    timeout-minutes: 15
    env:
      AUDIO_SEPARATOR_MODEL_DIR: /opt/audio-separator-models
    steps:
      - uses: actions/checkout@v4
      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
      - name: Install pipx and poetry
        run: |
          python -m pip install --user pipx && python -m pipx ensurepath
          python -m pipx install poetry
          echo "$HOME/.local/bin" >> $GITHUB_PATH
      - name: Install system dependencies
        run: sudo apt-get update && sudo apt-get install -y ffmpeg libsamplerate0 libsamplerate-dev
      - name: Set up Python with cache
        uses: actions/setup-python@v5
        with:
          python-version: '3.13'
          cache: poetry
      - name: Install Poetry dependencies (GPU)
        run: poetry install -E gpu
      - name: "Run: ensemble quality, multi-stem, and remote API tests (~6 min)"
        run: |
          poetry run pytest -sv \
            tests/integration/test_ensemble_meaningful.py \
            tests/integration/test_multi_stem_verification.py \
            tests/integration/test_remote_api_integration.py
      - name: Upload test artifacts
        if: always()
        uses: actions/upload-artifact@v4
        with:
          name: stems-and-quality-results
          path: |
            *.flac
            tests/*.flac

  # ── Gate job for branch protection ────────────────────────────────

  integration-test:
    needs: [changes, ensemble-presets, core-models, stems-and-quality]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Check test results
        run: |
          if [[ "${{ needs.changes.outputs.should_run }}" != "true" ]]; then
            echo "Tests skipped - no code changes detected"
            exit 0
          fi

          echo "ensemble-presets:   ${{ needs.ensemble-presets.result }}"
          echo "core-models:        ${{ needs.core-models.result }}"
          echo "stems-and-quality:  ${{ needs.stems-and-quality.result }}"

          if [[ "${{ needs.ensemble-presets.result }}" == "failure" ]] || \
             [[ "${{ needs.core-models.result }}" == "failure" ]] || \
             [[ "${{ needs.stems-and-quality.result }}" == "failure" ]]; then
            echo "Integration tests failed"
            exit 1
          fi
          echo "All integration tests passed"


================================================
FILE: .github/workflows/run-unit-tests.yaml
================================================
name: run-unit-tests

on:
  pull_request:

jobs:
  changes:
    runs-on: ubuntu-latest
    outputs:
      should_run: ${{ steps.filter.outputs.code }}
    steps:
      - uses: actions/checkout@v4
      - uses: dorny/paths-filter@v3
        id: filter
        with:
          filters: |
            code:
              - 'audio_separator/**'
              - 'tests/**'
              - 'pyproject.toml'
              - 'poetry.lock'

  test-ubuntu:
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: ubuntu-latest

    strategy:
      matrix:
        python-version: ['3.10', '3.11', '3.12', '3.13']

    steps:
      - name: Free disk space
        uses: jlumbroso/free-disk-space@main
        with:
          tool-cache: false
          android: true
          dotnet: true
          haskell: true
          large-packages: false
          docker-images: true
          swap-storage: true

      - name: Checkout project
        uses: actions/checkout@v4

      - name: Install poetry
        run: pipx install poetry

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          cache: poetry # caching dependencies from poetry.lock

      - name: Install Poetry dependencies (CPU)
        run: poetry install -E cpu

      - name: Run unit tests with coverage
        run: poetry run pytest tests/unit

  test-macos:
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: macos-latest

    strategy:
      matrix:
        python-version: ['3.10', '3.11', '3.12', '3.13']

    steps:
      - name: Checkout project
        uses: actions/checkout@v4

      - name: Install poetry
        run: pipx install poetry

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          cache: poetry # caching dependencies from poetry.lock

      - name: Install Poetry dependencies (CPU)
        run: poetry install -E cpu

      - name: Run unit tests with coverage
        run: |
          poetry run pytest tests/unit

  test-windows:
    needs: changes
    if: needs.changes.outputs.should_run == 'true'
    runs-on: windows-latest

    strategy:
      matrix:
        python-version: ['3.10', '3.11', '3.12', '3.13']

    steps:
      - name: Checkout project
        uses: actions/checkout@v4

      - name: Install poetry
        run: pipx install poetry

      - name: Set up Python
        uses: actions/setup-python@v5
        with:
          python-version: ${{ matrix.python-version }}
          cache: poetry # caching dependencies from poetry.lock

      - name: Install Poetry dependencies (CPU)
        run: poetry install -E cpu

      - name: Run unit tests with coverage
        run: poetry run pytest tests/unit

  # Gate job for branch protection - always reports a status
  unit-tests:
    needs: [changes, test-ubuntu, test-macos, test-windows]
    if: always()
    runs-on: ubuntu-latest
    steps:
      - name: Check test results
        run: |
          if [[ "${{ needs.changes.outputs.should_run }}" != "true" ]]; then
            echo "Tests skipped - no code changes detected"
            exit 0
          fi
          if [[ "${{ needs.test-ubuntu.result }}" == "failure" ]] || \
             [[ "${{ needs.test-macos.result }}" == "failure" ]] || \
             [[ "${{ needs.test-windows.result }}" == "failure" ]]; then
            echo "Some tests failed"
            exit 1
          fi
          echo "All tests passed"


================================================
FILE: .gitignore
================================================
# Andrew env
.DS_Store
.vscode

# Andrew functional adds
/tracks/
/lyrics/
/.cache/
*.onnx
*.pth
*.wav
/*.flac
*.mp3
tests/model-metrics/results
tests/model-metrics/datasets
temp_images

# Byte-compiled / optimized / DLL files
__pycache__/
*.py[cod]
*$py.class

# C extensions
*.so

# Distribution / packaging
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
share/python-wheels/
*.egg-info/
.installed.cfg
*.egg
MANIFEST

# PyInstaller
#  Usually these files are written by a python script from a template
#  before PyInstaller builds the exe, so as to inject date/other infos into it.
*.manifest
*.spec

# Installer logs
pip-log.txt
pip-delete-this-directory.txt

# Unit test / coverage reports
htmlcov/
.tox/
.nox/
.coverage
.coverage.*
.cache
nosetests.xml
coverage.xml
*.cover
*.py,cover
.hypothesis/
.pytest_cache/
cover/

# Translations
*.mo
*.pot

# Django stuff:
*.log
local_settings.py
db.sqlite3
db.sqlite3-journal

# Flask stuff:
instance/
.webassets-cache

# Scrapy stuff:
.scrapy

# Sphinx documentation
docs/_build/

# PyBuilder
.pybuilder/
target/

# Jupyter Notebook
.ipynb_checkpoints

# IPython
profile_default/
ipython_config.py

# pyenv
#   For a library or package, you might want to ignore these files since the code is
#   intended to run in multiple environments; otherwise, check them in:
# .python-version

# pipenv
#   According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
#   However, in case of collaboration, if having platform-specific dependencies or dependencies
#   having no cross-platform support, pipenv may install dependencies that don't work, or not
#   install all needed dependencies.
#Pipfile.lock

# poetry
#   Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
#   This is especially recommended for binary packages to ensure reproducibility, and is more
#   commonly ignored for libraries.
#   https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
#poetry.lock

# pdm
#   Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
#pdm.lock
#   pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
#   in version control.
#   https://pdm.fming.dev/#use-with-ide
.pdm.toml

# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
__pypackages__/

# Celery stuff
celerybeat-schedule
celerybeat.pid

# SageMath parsed files
*.sage.py

# Environments
.env
.venv
env/
venv/
ENV/
env.bak/
venv.bak/

# Spyder project settings
.spyderproject
.spyproject

# Rope project settings
.ropeproject

# mkdocs documentation
/site

# mypy
.mypy_cache/
.dmypy.json
dmypy.json

# Pyre type checker
.pyre/

# pytype static type analyzer
.pytype/

# Cython debug symbols
cython_debug/

# PyCharm
#  JetBrains specific template is maintained in a separate JetBrains.gitignore that can
#  be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
#  and can be added to the global gitignore or merged into this file.  For a more nuclear
#  option (not recommended) you can uncomment the following to ignore the entire idea folder.
#.idea/


================================================
FILE: .specify/memory/constitution.md
================================================
<!--
Sync Impact Report:
Version change: Initial → 1.0.0
Modified principles: All (new constitution)
Added sections: Core Principles, Performance Standards, Quality Assurance
Removed sections: None (template placeholders)
Templates requiring updates:
- ✅ plan-template.md (Constitution Check section updated)
- ✅ spec-template.md (aligned with principles)
- ✅ tasks-template.md (TDD enforcement aligned)
- ✅ agent-file-template.md (no changes needed)
Follow-up TODOs: None
-->

# Audio Separator Constitution

## Core Principles

### I. Library-First Architecture
The `Separator` class MUST be the primary interface for all audio separation functionality. CLI and remote API are thin wrappers around the library. Libraries MUST be self-contained, independently testable, and documented with clear separation of concerns between architectures (MDX, VR, Demucs, MDXC).

**Rationale**: This ensures the core functionality can be integrated into other projects while maintaining a consistent API across all interfaces.

### II. Multi-Interface Consistency
Every core feature MUST be accessible via three interfaces: Python API, CLI, and Remote API. Parameter names and behavior MUST be identical across all interfaces. All interfaces MUST support the same model architectures and processing options.

**Rationale**: Users should have consistent experience regardless of how they access the functionality, enabling seamless transition between local and remote processing.

### III. Test-First Development (NON-NEGOTIABLE)
TDD is mandatory: Tests written → Tests fail → Implementation → Tests pass. All new features MUST include unit tests, integration tests with audio validation (SSIM comparison), and CLI tests. No code merges without passing tests.

**Rationale**: Audio processing requires precision and consistency. Automated testing with perceptual validation ensures output quality remains stable across changes.

### IV. Performance & Resource Efficiency
Hardware acceleration MUST be supported (CUDA, CoreML, DirectML). Memory usage MUST be optimized for large audio files through streaming and batch processing. Processing parameters MUST be tunable for different hardware capabilities.

**Rationale**: Audio separation is computationally intensive. Efficient resource usage enables processing of longer files and broader hardware compatibility.

### V. Model Architecture Separation
Each model architecture (MDX, VR, Demucs, MDXC) MUST be implemented in separate modules inheriting from `CommonSeparator`. Loading one architecture MUST NOT load code from others. Architecture-specific parameters MUST be isolated and documented.

**Rationale**: This prevents conflicts between different model types and keeps memory usage minimal by loading only required components.

## Performance Standards

All audio processing operations MUST meet these requirements:
- **Memory efficiency**: Support files larger than available RAM through streaming
- **GPU utilization**: Automatically detect and utilize available hardware acceleration
- **Batch processing**: Support processing multiple files without model reloading
- **Output consistency**: Identical inputs MUST produce identical outputs (deterministic)

## Quality Assurance

### Testing Requirements
- **Unit tests**: All core classes and functions
- **Integration tests**: End-to-end audio processing with SSIM validation
- **Performance tests**: Memory usage and processing speed benchmarks
- **Cross-platform tests**: Windows, macOS, Linux compatibility

### Audio Validation
Output quality MUST be validated using:
- Waveform and spectrogram image comparison (SSIM ≥ 0.95)
- Reference audio files for each supported model architecture
- Automated regression testing on model output changes

## Governance

This constitution supersedes all other development practices. All pull requests MUST verify compliance with these principles. Any deviation MUST be explicitly justified and documented.

**Amendment Process**: Changes require documentation of impact, approval from maintainers, and migration plan for affected code.

**Compliance Review**: All features undergo constitutional compliance check during planning phase and post-implementation validation.

**Version**: 1.0.0 | **Ratified**: 2025-09-25 | **Last Amended**: 2025-09-25

================================================
FILE: .specify/scripts/bash/check-prerequisites.sh
================================================
#!/usr/bin/env bash

# Consolidated prerequisite checking script
#
# This script provides unified prerequisite checking for Spec-Driven Development workflow.
# It replaces the functionality previously spread across multiple scripts.
#
# Usage: ./check-prerequisites.sh [OPTIONS]
#
# OPTIONS:
#   --json              Output in JSON format
#   --require-tasks     Require tasks.md to exist (for implementation phase)
#   --include-tasks     Include tasks.md in AVAILABLE_DOCS list
#   --paths-only        Only output path variables (no validation)
#   --help, -h          Show help message
#
# OUTPUTS:
#   JSON mode: {"FEATURE_DIR":"...", "AVAILABLE_DOCS":["..."]}
#   Text mode: FEATURE_DIR:... \n AVAILABLE_DOCS: \n ✓/✗ file.md
#   Paths only: REPO_ROOT: ... \n BRANCH: ... \n FEATURE_DIR: ... etc.

set -e

# Parse command line arguments
JSON_MODE=false
REQUIRE_TASKS=false
INCLUDE_TASKS=false
PATHS_ONLY=false

for arg in "$@"; do
    case "$arg" in
        --json)
            JSON_MODE=true
            ;;
        --require-tasks)
            REQUIRE_TASKS=true
            ;;
        --include-tasks)
            INCLUDE_TASKS=true
            ;;
        --paths-only)
            PATHS_ONLY=true
            ;;
        --help|-h)
            cat << 'EOF'
Usage: check-prerequisites.sh [OPTIONS]

Consolidated prerequisite checking for Spec-Driven Development workflow.

OPTIONS:
  --json              Output in JSON format
  --require-tasks     Require tasks.md to exist (for implementation phase)
  --include-tasks     Include tasks.md in AVAILABLE_DOCS list
  --paths-only        Only output path variables (no prerequisite validation)
  --help, -h          Show this help message

EXAMPLES:
  # Check task prerequisites (plan.md required)
  ./check-prerequisites.sh --json
  
  # Check implementation prerequisites (plan.md + tasks.md required)
  ./check-prerequisites.sh --json --require-tasks --include-tasks
  
  # Get feature paths only (no validation)
  ./check-prerequisites.sh --paths-only
  
EOF
            exit 0
            ;;
        *)
            echo "ERROR: Unknown option '$arg'. Use --help for usage information." >&2
            exit 1
            ;;
    esac
done

# Source common functions
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Get feature paths and validate branch
eval $(get_feature_paths)
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1

# If paths-only mode, output paths and exit (support JSON + paths-only combined)
if $PATHS_ONLY; then
    if $JSON_MODE; then
        # Minimal JSON paths payload (no validation performed)
        printf '{"REPO_ROOT":"%s","BRANCH":"%s","FEATURE_DIR":"%s","FEATURE_SPEC":"%s","IMPL_PLAN":"%s","TASKS":"%s"}\n' \
            "$REPO_ROOT" "$CURRENT_BRANCH" "$FEATURE_DIR" "$FEATURE_SPEC" "$IMPL_PLAN" "$TASKS"
    else
        echo "REPO_ROOT: $REPO_ROOT"
        echo "BRANCH: $CURRENT_BRANCH"
        echo "FEATURE_DIR: $FEATURE_DIR"
        echo "FEATURE_SPEC: $FEATURE_SPEC"
        echo "IMPL_PLAN: $IMPL_PLAN"
        echo "TASKS: $TASKS"
    fi
    exit 0
fi

# Validate required directories and files
if [[ ! -d "$FEATURE_DIR" ]]; then
    echo "ERROR: Feature directory not found: $FEATURE_DIR" >&2
    echo "Run /specify first to create the feature structure." >&2
    exit 1
fi

if [[ ! -f "$IMPL_PLAN" ]]; then
    echo "ERROR: plan.md not found in $FEATURE_DIR" >&2
    echo "Run /plan first to create the implementation plan." >&2
    exit 1
fi

# Check for tasks.md if required
if $REQUIRE_TASKS && [[ ! -f "$TASKS" ]]; then
    echo "ERROR: tasks.md not found in $FEATURE_DIR" >&2
    echo "Run /tasks first to create the task list." >&2
    exit 1
fi

# Build list of available documents
docs=()

# Always check these optional docs
[[ -f "$RESEARCH" ]] && docs+=("research.md")
[[ -f "$DATA_MODEL" ]] && docs+=("data-model.md")

# Check contracts directory (only if it exists and has files)
if [[ -d "$CONTRACTS_DIR" ]] && [[ -n "$(ls -A "$CONTRACTS_DIR" 2>/dev/null)" ]]; then
    docs+=("contracts/")
fi

[[ -f "$QUICKSTART" ]] && docs+=("quickstart.md")

# Include tasks.md if requested and it exists
if $INCLUDE_TASKS && [[ -f "$TASKS" ]]; then
    docs+=("tasks.md")
fi

# Output results
if $JSON_MODE; then
    # Build JSON array of documents
    if [[ ${#docs[@]} -eq 0 ]]; then
        json_docs="[]"
    else
        json_docs=$(printf '"%s",' "${docs[@]}")
        json_docs="[${json_docs%,}]"
    fi
    
    printf '{"FEATURE_DIR":"%s","AVAILABLE_DOCS":%s}\n' "$FEATURE_DIR" "$json_docs"
else
    # Text output
    echo "FEATURE_DIR:$FEATURE_DIR"
    echo "AVAILABLE_DOCS:"
    
    # Show status of each potential document
    check_file "$RESEARCH" "research.md"
    check_file "$DATA_MODEL" "data-model.md"
    check_dir "$CONTRACTS_DIR" "contracts/"
    check_file "$QUICKSTART" "quickstart.md"
    
    if $INCLUDE_TASKS; then
        check_file "$TASKS" "tasks.md"
    fi
fi

================================================
FILE: .specify/scripts/bash/common.sh
================================================
#!/usr/bin/env bash
# Common functions and variables for all scripts

# Get repository root, with fallback for non-git repositories
get_repo_root() {
    if git rev-parse --show-toplevel >/dev/null 2>&1; then
        git rev-parse --show-toplevel
    else
        # Fall back to script location for non-git repos
        local script_dir="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
        (cd "$script_dir/../../.." && pwd)
    fi
}

# Get current branch, with fallback for non-git repositories
get_current_branch() {
    # First check if SPECIFY_FEATURE environment variable is set
    if [[ -n "${SPECIFY_FEATURE:-}" ]]; then
        echo "$SPECIFY_FEATURE"
        return
    fi
    
    # Then check git if available
    if git rev-parse --abbrev-ref HEAD >/dev/null 2>&1; then
        git rev-parse --abbrev-ref HEAD
        return
    fi
    
    # For non-git repos, try to find the latest feature directory
    local repo_root=$(get_repo_root)
    local specs_dir="$repo_root/specs"
    
    if [[ -d "$specs_dir" ]]; then
        local latest_feature=""
        local highest=0
        
        for dir in "$specs_dir"/*; do
            if [[ -d "$dir" ]]; then
                local dirname=$(basename "$dir")
                if [[ "$dirname" =~ ^([0-9]{3})- ]]; then
                    local number=${BASH_REMATCH[1]}
                    number=$((10#$number))
                    if [[ "$number" -gt "$highest" ]]; then
                        highest=$number
                        latest_feature=$dirname
                    fi
                fi
            fi
        done
        
        if [[ -n "$latest_feature" ]]; then
            echo "$latest_feature"
            return
        fi
    fi
    
    echo "main"  # Final fallback
}

# Check if we have git available
has_git() {
    git rev-parse --show-toplevel >/dev/null 2>&1
}

check_feature_branch() {
    local branch="$1"
    local has_git_repo="$2"
    
    # For non-git repos, we can't enforce branch naming but still provide output
    if [[ "$has_git_repo" != "true" ]]; then
        echo "[specify] Warning: Git repository not detected; skipped branch validation" >&2
        return 0
    fi
    
    if [[ ! "$branch" =~ ^[0-9]{3}- ]]; then
        echo "ERROR: Not on a feature branch. Current branch: $branch" >&2
        echo "Feature branches should be named like: 001-feature-name" >&2
        return 1
    fi
    
    return 0
}

get_feature_dir() { echo "$1/specs/$2"; }

get_feature_paths() {
    local repo_root=$(get_repo_root)
    local current_branch=$(get_current_branch)
    local has_git_repo="false"
    
    if has_git; then
        has_git_repo="true"
    fi
    
    local feature_dir=$(get_feature_dir "$repo_root" "$current_branch")
    
    cat <<EOF
REPO_ROOT='$repo_root'
CURRENT_BRANCH='$current_branch'
HAS_GIT='$has_git_repo'
FEATURE_DIR='$feature_dir'
FEATURE_SPEC='$feature_dir/spec.md'
IMPL_PLAN='$feature_dir/plan.md'
TASKS='$feature_dir/tasks.md'
RESEARCH='$feature_dir/research.md'
DATA_MODEL='$feature_dir/data-model.md'
QUICKSTART='$feature_dir/quickstart.md'
CONTRACTS_DIR='$feature_dir/contracts'
EOF
}

check_file() { [[ -f "$1" ]] && echo "  ✓ $2" || echo "  ✗ $2"; }
check_dir() { [[ -d "$1" && -n $(ls -A "$1" 2>/dev/null) ]] && echo "  ✓ $2" || echo "  ✗ $2"; }


================================================
FILE: .specify/scripts/bash/create-new-feature.sh
================================================
#!/usr/bin/env bash

set -e

JSON_MODE=false
ARGS=()
for arg in "$@"; do
    case "$arg" in
        --json) JSON_MODE=true ;;
        --help|-h) echo "Usage: $0 [--json] <feature_description>"; exit 0 ;;
        *) ARGS+=("$arg") ;;
    esac
done

FEATURE_DESCRIPTION="${ARGS[*]}"
if [ -z "$FEATURE_DESCRIPTION" ]; then
    echo "Usage: $0 [--json] <feature_description>" >&2
    exit 1
fi

# Function to find the repository root by searching for existing project markers
find_repo_root() {
    local dir="$1"
    while [ "$dir" != "/" ]; do
        if [ -d "$dir/.git" ] || [ -d "$dir/.specify" ]; then
            echo "$dir"
            return 0
        fi
        dir="$(dirname "$dir")"
    done
    return 1
}

# Resolve repository root. Prefer git information when available, but fall back
# to searching for repository markers so the workflow still functions in repositories that
# were initialised with --no-git.
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

if git rev-parse --show-toplevel >/dev/null 2>&1; then
    REPO_ROOT=$(git rev-parse --show-toplevel)
    HAS_GIT=true
else
    REPO_ROOT="$(find_repo_root "$SCRIPT_DIR")"
    if [ -z "$REPO_ROOT" ]; then
        echo "Error: Could not determine repository root. Please run this script from within the repository." >&2
        exit 1
    fi
    HAS_GIT=false
fi

cd "$REPO_ROOT"

SPECS_DIR="$REPO_ROOT/specs"
mkdir -p "$SPECS_DIR"

HIGHEST=0
if [ -d "$SPECS_DIR" ]; then
    for dir in "$SPECS_DIR"/*; do
        [ -d "$dir" ] || continue
        dirname=$(basename "$dir")
        number=$(echo "$dirname" | grep -o '^[0-9]\+' || echo "0")
        number=$((10#$number))
        if [ "$number" -gt "$HIGHEST" ]; then HIGHEST=$number; fi
    done
fi

NEXT=$((HIGHEST + 1))
FEATURE_NUM=$(printf "%03d" "$NEXT")

BRANCH_NAME=$(echo "$FEATURE_DESCRIPTION" | tr '[:upper:]' '[:lower:]' | sed 's/[^a-z0-9]/-/g' | sed 's/-\+/-/g' | sed 's/^-//' | sed 's/-$//')
WORDS=$(echo "$BRANCH_NAME" | tr '-' '\n' | grep -v '^$' | head -3 | tr '\n' '-' | sed 's/-$//')
BRANCH_NAME="${FEATURE_NUM}-${WORDS}"

if [ "$HAS_GIT" = true ]; then
    git checkout -b "$BRANCH_NAME"
else
    >&2 echo "[specify] Warning: Git repository not detected; skipped branch creation for $BRANCH_NAME"
fi

FEATURE_DIR="$SPECS_DIR/$BRANCH_NAME"
mkdir -p "$FEATURE_DIR"

TEMPLATE="$REPO_ROOT/.specify/templates/spec-template.md"
SPEC_FILE="$FEATURE_DIR/spec.md"
if [ -f "$TEMPLATE" ]; then cp "$TEMPLATE" "$SPEC_FILE"; else touch "$SPEC_FILE"; fi

# Set the SPECIFY_FEATURE environment variable for the current session
export SPECIFY_FEATURE="$BRANCH_NAME"

if $JSON_MODE; then
    printf '{"BRANCH_NAME":"%s","SPEC_FILE":"%s","FEATURE_NUM":"%s"}\n' "$BRANCH_NAME" "$SPEC_FILE" "$FEATURE_NUM"
else
    echo "BRANCH_NAME: $BRANCH_NAME"
    echo "SPEC_FILE: $SPEC_FILE"
    echo "FEATURE_NUM: $FEATURE_NUM"
    echo "SPECIFY_FEATURE environment variable set to: $BRANCH_NAME"
fi


================================================
FILE: .specify/scripts/bash/setup-plan.sh
================================================
#!/usr/bin/env bash

set -e

# Parse command line arguments
JSON_MODE=false
ARGS=()

for arg in "$@"; do
    case "$arg" in
        --json) 
            JSON_MODE=true 
            ;;
        --help|-h) 
            echo "Usage: $0 [--json]"
            echo "  --json    Output results in JSON format"
            echo "  --help    Show this help message"
            exit 0 
            ;;
        *) 
            ARGS+=("$arg") 
            ;;
    esac
done

# Get script directory and load common functions
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Get all paths and variables from common functions
eval $(get_feature_paths)

# Check if we're on a proper feature branch (only for git repos)
check_feature_branch "$CURRENT_BRANCH" "$HAS_GIT" || exit 1

# Ensure the feature directory exists
mkdir -p "$FEATURE_DIR"

# Copy plan template if it exists
TEMPLATE="$REPO_ROOT/.specify/templates/plan-template.md"
if [[ -f "$TEMPLATE" ]]; then
    cp "$TEMPLATE" "$IMPL_PLAN"
    echo "Copied plan template to $IMPL_PLAN"
else
    echo "Warning: Plan template not found at $TEMPLATE"
    # Create a basic plan file if template doesn't exist
    touch "$IMPL_PLAN"
fi

# Output results
if $JSON_MODE; then
    printf '{"FEATURE_SPEC":"%s","IMPL_PLAN":"%s","SPECS_DIR":"%s","BRANCH":"%s","HAS_GIT":"%s"}\n' \
        "$FEATURE_SPEC" "$IMPL_PLAN" "$FEATURE_DIR" "$CURRENT_BRANCH" "$HAS_GIT"
else
    echo "FEATURE_SPEC: $FEATURE_SPEC"
    echo "IMPL_PLAN: $IMPL_PLAN" 
    echo "SPECS_DIR: $FEATURE_DIR"
    echo "BRANCH: $CURRENT_BRANCH"
    echo "HAS_GIT: $HAS_GIT"
fi


================================================
FILE: .specify/scripts/bash/update-agent-context.sh
================================================
#!/usr/bin/env bash

# Update agent context files with information from plan.md
#
# This script maintains AI agent context files by parsing feature specifications 
# and updating agent-specific configuration files with project information.
#
# MAIN FUNCTIONS:
# 1. Environment Validation
#    - Verifies git repository structure and branch information
#    - Checks for required plan.md files and templates
#    - Validates file permissions and accessibility
#
# 2. Plan Data Extraction
#    - Parses plan.md files to extract project metadata
#    - Identifies language/version, frameworks, databases, and project types
#    - Handles missing or incomplete specification data gracefully
#
# 3. Agent File Management
#    - Creates new agent context files from templates when needed
#    - Updates existing agent files with new project information
#    - Preserves manual additions and custom configurations
#    - Supports multiple AI agent formats and directory structures
#
# 4. Content Generation
#    - Generates language-specific build/test commands
#    - Creates appropriate project directory structures
#    - Updates technology stacks and recent changes sections
#    - Maintains consistent formatting and timestamps
#
# 5. Multi-Agent Support
#    - Handles agent-specific file paths and naming conventions
#    - Supports: Claude, Gemini, Copilot, Cursor, Qwen, opencode, Codex, Windsurf
#    - Can update single agents or all existing agent files
#    - Creates default Claude file if no agent files exist
#
# Usage: ./update-agent-context.sh [agent_type]
# Agent types: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf
# Leave empty to update all existing agent files

set -e

# Enable strict error handling
set -u
set -o pipefail

#==============================================================================
# Configuration and Global Variables
#==============================================================================

# Get script directory and load common functions
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Get all paths and variables from common functions
eval $(get_feature_paths)

NEW_PLAN="$IMPL_PLAN"  # Alias for compatibility with existing code
AGENT_TYPE="${1:-}"

# Agent-specific file paths  
CLAUDE_FILE="$REPO_ROOT/CLAUDE.md"
GEMINI_FILE="$REPO_ROOT/GEMINI.md"
COPILOT_FILE="$REPO_ROOT/.github/copilot-instructions.md"
CURSOR_FILE="$REPO_ROOT/.cursor/rules/specify-rules.mdc"
QWEN_FILE="$REPO_ROOT/QWEN.md"
AGENTS_FILE="$REPO_ROOT/AGENTS.md"
WINDSURF_FILE="$REPO_ROOT/.windsurf/rules/specify-rules.md"
KILOCODE_FILE="$REPO_ROOT/.kilocode/rules/specify-rules.md"
AUGGIE_FILE="$REPO_ROOT/.augment/rules/specify-rules.md"
ROO_FILE="$REPO_ROOT/.roo/rules/specify-rules.md"

# Template file
TEMPLATE_FILE="$REPO_ROOT/.specify/templates/agent-file-template.md"

# Global variables for parsed plan data
NEW_LANG=""
NEW_FRAMEWORK=""
NEW_DB=""
NEW_PROJECT_TYPE=""

#==============================================================================
# Utility Functions
#==============================================================================

log_info() {
    echo "INFO: $1"
}

log_success() {
    echo "✓ $1"
}

log_error() {
    echo "ERROR: $1" >&2
}

log_warning() {
    echo "WARNING: $1" >&2
}

# Cleanup function for temporary files
cleanup() {
    local exit_code=$?
    rm -f /tmp/agent_update_*_$$
    rm -f /tmp/manual_additions_$$
    exit $exit_code
}

# Set up cleanup trap
trap cleanup EXIT INT TERM

#==============================================================================
# Validation Functions
#==============================================================================

validate_environment() {
    # Check if we have a current branch/feature (git or non-git)
    if [[ -z "$CURRENT_BRANCH" ]]; then
        log_error "Unable to determine current feature"
        if [[ "$HAS_GIT" == "true" ]]; then
            log_info "Make sure you're on a feature branch"
        else
            log_info "Set SPECIFY_FEATURE environment variable or create a feature first"
        fi
        exit 1
    fi
    
    # Check if plan.md exists
    if [[ ! -f "$NEW_PLAN" ]]; then
        log_error "No plan.md found at $NEW_PLAN"
        log_info "Make sure you're working on a feature with a corresponding spec directory"
        if [[ "$HAS_GIT" != "true" ]]; then
            log_info "Use: export SPECIFY_FEATURE=your-feature-name or create a new feature first"
        fi
        exit 1
    fi
    
    # Check if template exists (needed for new files)
    if [[ ! -f "$TEMPLATE_FILE" ]]; then
        log_warning "Template file not found at $TEMPLATE_FILE"
        log_warning "Creating new agent files will fail"
    fi
}

#==============================================================================
# Plan Parsing Functions
#==============================================================================

extract_plan_field() {
    local field_pattern="$1"
    local plan_file="$2"
    
    grep "^\*\*${field_pattern}\*\*: " "$plan_file" 2>/dev/null | \
        head -1 | \
        sed "s|^\*\*${field_pattern}\*\*: ||" | \
        sed 's/^[ \t]*//;s/[ \t]*$//' | \
        grep -v "NEEDS CLARIFICATION" | \
        grep -v "^N/A$" || echo ""
}

parse_plan_data() {
    local plan_file="$1"
    
    if [[ ! -f "$plan_file" ]]; then
        log_error "Plan file not found: $plan_file"
        return 1
    fi
    
    if [[ ! -r "$plan_file" ]]; then
        log_error "Plan file is not readable: $plan_file"
        return 1
    fi
    
    log_info "Parsing plan data from $plan_file"
    
    NEW_LANG=$(extract_plan_field "Language/Version" "$plan_file")
    NEW_FRAMEWORK=$(extract_plan_field "Primary Dependencies" "$plan_file")
    NEW_DB=$(extract_plan_field "Storage" "$plan_file")
    NEW_PROJECT_TYPE=$(extract_plan_field "Project Type" "$plan_file")
    
    # Log what we found
    if [[ -n "$NEW_LANG" ]]; then
        log_info "Found language: $NEW_LANG"
    else
        log_warning "No language information found in plan"
    fi
    
    if [[ -n "$NEW_FRAMEWORK" ]]; then
        log_info "Found framework: $NEW_FRAMEWORK"
    fi
    
    if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
        log_info "Found database: $NEW_DB"
    fi
    
    if [[ -n "$NEW_PROJECT_TYPE" ]]; then
        log_info "Found project type: $NEW_PROJECT_TYPE"
    fi
}

format_technology_stack() {
    local lang="$1"
    local framework="$2"
    local parts=()
    
    # Add non-empty parts
    [[ -n "$lang" && "$lang" != "NEEDS CLARIFICATION" ]] && parts+=("$lang")
    [[ -n "$framework" && "$framework" != "NEEDS CLARIFICATION" && "$framework" != "N/A" ]] && parts+=("$framework")
    
    # Join with proper formatting
    if [[ ${#parts[@]} -eq 0 ]]; then
        echo ""
    elif [[ ${#parts[@]} -eq 1 ]]; then
        echo "${parts[0]}"
    else
        # Join multiple parts with " + "
        local result="${parts[0]}"
        for ((i=1; i<${#parts[@]}; i++)); do
            result="$result + ${parts[i]}"
        done
        echo "$result"
    fi
}

#==============================================================================
# Template and Content Generation Functions
#==============================================================================

get_project_structure() {
    local project_type="$1"
    
    if [[ "$project_type" == *"web"* ]]; then
        echo "backend/\\nfrontend/\\ntests/"
    else
        echo "src/\\ntests/"
    fi
}

get_commands_for_language() {
    local lang="$1"
    
    case "$lang" in
        *"Python"*)
            echo "cd src && pytest && ruff check ."
            ;;
        *"Rust"*)
            echo "cargo test && cargo clippy"
            ;;
        *"JavaScript"*|*"TypeScript"*)
            echo "npm test && npm run lint"
            ;;
        *)
            echo "# Add commands for $lang"
            ;;
    esac
}

get_language_conventions() {
    local lang="$1"
    echo "$lang: Follow standard conventions"
}

create_new_agent_file() {
    local target_file="$1"
    local temp_file="$2"
    local project_name="$3"
    local current_date="$4"
    
    if [[ ! -f "$TEMPLATE_FILE" ]]; then
        log_error "Template not found at $TEMPLATE_FILE"
        return 1
    fi
    
    if [[ ! -r "$TEMPLATE_FILE" ]]; then
        log_error "Template file is not readable: $TEMPLATE_FILE"
        return 1
    fi
    
    log_info "Creating new agent context file from template..."
    
    if ! cp "$TEMPLATE_FILE" "$temp_file"; then
        log_error "Failed to copy template file"
        return 1
    fi
    
    # Replace template placeholders
    local project_structure
    project_structure=$(get_project_structure "$NEW_PROJECT_TYPE")
    
    local commands
    commands=$(get_commands_for_language "$NEW_LANG")
    
    local language_conventions
    language_conventions=$(get_language_conventions "$NEW_LANG")
    
    # Perform substitutions with error checking using safer approach
    # Escape special characters for sed by using a different delimiter or escaping
    local escaped_lang=$(printf '%s\n' "$NEW_LANG" | sed 's/[\[\.*^$()+{}|]/\\&/g')
    local escaped_framework=$(printf '%s\n' "$NEW_FRAMEWORK" | sed 's/[\[\.*^$()+{}|]/\\&/g')
    local escaped_branch=$(printf '%s\n' "$CURRENT_BRANCH" | sed 's/[\[\.*^$()+{}|]/\\&/g')
    
    # Build technology stack and recent change strings conditionally
    local tech_stack
    if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
        tech_stack="- $escaped_lang + $escaped_framework ($escaped_branch)"
    elif [[ -n "$escaped_lang" ]]; then
        tech_stack="- $escaped_lang ($escaped_branch)"
    elif [[ -n "$escaped_framework" ]]; then
        tech_stack="- $escaped_framework ($escaped_branch)"
    else
        tech_stack="- ($escaped_branch)"
    fi

    local recent_change
    if [[ -n "$escaped_lang" && -n "$escaped_framework" ]]; then
        recent_change="- $escaped_branch: Added $escaped_lang + $escaped_framework"
    elif [[ -n "$escaped_lang" ]]; then
        recent_change="- $escaped_branch: Added $escaped_lang"
    elif [[ -n "$escaped_framework" ]]; then
        recent_change="- $escaped_branch: Added $escaped_framework"
    else
        recent_change="- $escaped_branch: Added"
    fi

    local substitutions=(
        "s|\[PROJECT NAME\]|$project_name|"
        "s|\[DATE\]|$current_date|"
        "s|\[EXTRACTED FROM ALL PLAN.MD FILES\]|$tech_stack|"
        "s|\[ACTUAL STRUCTURE FROM PLANS\]|$project_structure|g"
        "s|\[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES\]|$commands|"
        "s|\[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE\]|$language_conventions|"
        "s|\[LAST 3 FEATURES AND WHAT THEY ADDED\]|$recent_change|"
    )
    
    for substitution in "${substitutions[@]}"; do
        if ! sed -i.bak -e "$substitution" "$temp_file"; then
            log_error "Failed to perform substitution: $substitution"
            rm -f "$temp_file" "$temp_file.bak"
            return 1
        fi
    done
    
    # Convert \n sequences to actual newlines
    newline=$(printf '\n')
    sed -i.bak2 "s/\\\\n/${newline}/g" "$temp_file"
    
    # Clean up backup files
    rm -f "$temp_file.bak" "$temp_file.bak2"
    
    return 0
}




update_existing_agent_file() {
    local target_file="$1"
    local current_date="$2"
    
    log_info "Updating existing agent context file..."
    
    # Use a single temporary file for atomic update
    local temp_file
    temp_file=$(mktemp) || {
        log_error "Failed to create temporary file"
        return 1
    }
    
    # Process the file in one pass
    local tech_stack=$(format_technology_stack "$NEW_LANG" "$NEW_FRAMEWORK")
    local new_tech_entries=()
    local new_change_entry=""
    
    # Prepare new technology entries
    if [[ -n "$tech_stack" ]] && ! grep -q "$tech_stack" "$target_file"; then
        new_tech_entries+=("- $tech_stack ($CURRENT_BRANCH)")
    fi
    
    if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]] && ! grep -q "$NEW_DB" "$target_file"; then
        new_tech_entries+=("- $NEW_DB ($CURRENT_BRANCH)")
    fi
    
    # Prepare new change entry
    if [[ -n "$tech_stack" ]]; then
        new_change_entry="- $CURRENT_BRANCH: Added $tech_stack"
    elif [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]] && [[ "$NEW_DB" != "NEEDS CLARIFICATION" ]]; then
        new_change_entry="- $CURRENT_BRANCH: Added $NEW_DB"
    fi
    
    # Process file line by line
    local in_tech_section=false
    local in_changes_section=false
    local tech_entries_added=false
    local changes_entries_added=false
    local existing_changes_count=0
    
    while IFS= read -r line || [[ -n "$line" ]]; do
        # Handle Active Technologies section
        if [[ "$line" == "## Active Technologies" ]]; then
            echo "$line" >> "$temp_file"
            in_tech_section=true
            continue
        elif [[ $in_tech_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
            # Add new tech entries before closing the section
            if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
                printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
                tech_entries_added=true
            fi
            echo "$line" >> "$temp_file"
            in_tech_section=false
            continue
        elif [[ $in_tech_section == true ]] && [[ -z "$line" ]]; then
            # Add new tech entries before empty line in tech section
            if [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
                printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
                tech_entries_added=true
            fi
            echo "$line" >> "$temp_file"
            continue
        fi
        
        # Handle Recent Changes section
        if [[ "$line" == "## Recent Changes" ]]; then
            echo "$line" >> "$temp_file"
            # Add new change entry right after the heading
            if [[ -n "$new_change_entry" ]]; then
                echo "$new_change_entry" >> "$temp_file"
            fi
            in_changes_section=true
            changes_entries_added=true
            continue
        elif [[ $in_changes_section == true ]] && [[ "$line" =~ ^##[[:space:]] ]]; then
            echo "$line" >> "$temp_file"
            in_changes_section=false
            continue
        elif [[ $in_changes_section == true ]] && [[ "$line" == "- "* ]]; then
            # Keep only first 2 existing changes
            if [[ $existing_changes_count -lt 2 ]]; then
                echo "$line" >> "$temp_file"
                ((existing_changes_count++))
            fi
            continue
        fi
        
        # Update timestamp
        if [[ "$line" =~ \*\*Last\ updated\*\*:.*[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9] ]]; then
            echo "$line" | sed "s/[0-9][0-9][0-9][0-9]-[0-9][0-9]-[0-9][0-9]/$current_date/" >> "$temp_file"
        else
            echo "$line" >> "$temp_file"
        fi
    done < "$target_file"
    
    # Post-loop check: if we're still in the Active Technologies section and haven't added new entries
    if [[ $in_tech_section == true ]] && [[ $tech_entries_added == false ]] && [[ ${#new_tech_entries[@]} -gt 0 ]]; then
        printf '%s\n' "${new_tech_entries[@]}" >> "$temp_file"
    fi
    
    # Move temp file to target atomically
    if ! mv "$temp_file" "$target_file"; then
        log_error "Failed to update target file"
        rm -f "$temp_file"
        return 1
    fi
    
    return 0
}
#==============================================================================
# Main Agent File Update Function
#==============================================================================

update_agent_file() {
    local target_file="$1"
    local agent_name="$2"
    
    if [[ -z "$target_file" ]] || [[ -z "$agent_name" ]]; then
        log_error "update_agent_file requires target_file and agent_name parameters"
        return 1
    fi
    
    log_info "Updating $agent_name context file: $target_file"
    
    local project_name
    project_name=$(basename "$REPO_ROOT")
    local current_date
    current_date=$(date +%Y-%m-%d)
    
    # Create directory if it doesn't exist
    local target_dir
    target_dir=$(dirname "$target_file")
    if [[ ! -d "$target_dir" ]]; then
        if ! mkdir -p "$target_dir"; then
            log_error "Failed to create directory: $target_dir"
            return 1
        fi
    fi
    
    if [[ ! -f "$target_file" ]]; then
        # Create new file from template
        local temp_file
        temp_file=$(mktemp) || {
            log_error "Failed to create temporary file"
            return 1
        }
        
        if create_new_agent_file "$target_file" "$temp_file" "$project_name" "$current_date"; then
            if mv "$temp_file" "$target_file"; then
                log_success "Created new $agent_name context file"
            else
                log_error "Failed to move temporary file to $target_file"
                rm -f "$temp_file"
                return 1
            fi
        else
            log_error "Failed to create new agent file"
            rm -f "$temp_file"
            return 1
        fi
    else
        # Update existing file
        if [[ ! -r "$target_file" ]]; then
            log_error "Cannot read existing file: $target_file"
            return 1
        fi
        
        if [[ ! -w "$target_file" ]]; then
            log_error "Cannot write to existing file: $target_file"
            return 1
        fi
        
        if update_existing_agent_file "$target_file" "$current_date"; then
            log_success "Updated existing $agent_name context file"
        else
            log_error "Failed to update existing agent file"
            return 1
        fi
    fi
    
    return 0
}

#==============================================================================
# Agent Selection and Processing
#==============================================================================

update_specific_agent() {
    local agent_type="$1"
    
    case "$agent_type" in
        claude)
            update_agent_file "$CLAUDE_FILE" "Claude Code"
            ;;
        gemini)
            update_agent_file "$GEMINI_FILE" "Gemini CLI"
            ;;
        copilot)
            update_agent_file "$COPILOT_FILE" "GitHub Copilot"
            ;;
        cursor)
            update_agent_file "$CURSOR_FILE" "Cursor IDE"
            ;;
        qwen)
            update_agent_file "$QWEN_FILE" "Qwen Code"
            ;;
        opencode)
            update_agent_file "$AGENTS_FILE" "opencode"
            ;;
        codex)
            update_agent_file "$AGENTS_FILE" "Codex CLI"
            ;;
        windsurf)
            update_agent_file "$WINDSURF_FILE" "Windsurf"
            ;;
        kilocode)
            update_agent_file "$KILOCODE_FILE" "Kilo Code"
            ;;
        auggie)
            update_agent_file "$AUGGIE_FILE" "Auggie CLI"
            ;;
        roo)
            update_agent_file "$ROO_FILE" "Roo Code"
            ;;
        *)
            log_error "Unknown agent type '$agent_type'"
            log_error "Expected: claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo"
            exit 1
            ;;
    esac
}

update_all_existing_agents() {
    local found_agent=false
    
    # Check each possible agent file and update if it exists
    if [[ -f "$CLAUDE_FILE" ]]; then
        update_agent_file "$CLAUDE_FILE" "Claude Code"
        found_agent=true
    fi
    
    if [[ -f "$GEMINI_FILE" ]]; then
        update_agent_file "$GEMINI_FILE" "Gemini CLI"
        found_agent=true
    fi
    
    if [[ -f "$COPILOT_FILE" ]]; then
        update_agent_file "$COPILOT_FILE" "GitHub Copilot"
        found_agent=true
    fi
    
    if [[ -f "$CURSOR_FILE" ]]; then
        update_agent_file "$CURSOR_FILE" "Cursor IDE"
        found_agent=true
    fi
    
    if [[ -f "$QWEN_FILE" ]]; then
        update_agent_file "$QWEN_FILE" "Qwen Code"
        found_agent=true
    fi
    
    if [[ -f "$AGENTS_FILE" ]]; then
        update_agent_file "$AGENTS_FILE" "Codex/opencode"
        found_agent=true
    fi
    
    if [[ -f "$WINDSURF_FILE" ]]; then
        update_agent_file "$WINDSURF_FILE" "Windsurf"
        found_agent=true
    fi
    
    if [[ -f "$KILOCODE_FILE" ]]; then
        update_agent_file "$KILOCODE_FILE" "Kilo Code"
        found_agent=true
    fi

    if [[ -f "$AUGGIE_FILE" ]]; then
        update_agent_file "$AUGGIE_FILE" "Auggie CLI"
        found_agent=true
    fi
    
    if [[ -f "$ROO_FILE" ]]; then
        update_agent_file "$ROO_FILE" "Roo Code"
        found_agent=true
    fi
    
    # If no agent files exist, create a default Claude file
    if [[ "$found_agent" == false ]]; then
        log_info "No existing agent files found, creating default Claude file..."
        update_agent_file "$CLAUDE_FILE" "Claude Code"
    fi
}
print_summary() {
    echo
    log_info "Summary of changes:"
    
    if [[ -n "$NEW_LANG" ]]; then
        echo "  - Added language: $NEW_LANG"
    fi
    
    if [[ -n "$NEW_FRAMEWORK" ]]; then
        echo "  - Added framework: $NEW_FRAMEWORK"
    fi
    
    if [[ -n "$NEW_DB" ]] && [[ "$NEW_DB" != "N/A" ]]; then
        echo "  - Added database: $NEW_DB"
    fi
    
    echo
    log_info "Usage: $0 [claude|gemini|copilot|cursor|qwen|opencode|codex|windsurf|kilocode|auggie|roo]"
}

#==============================================================================
# Main Execution
#==============================================================================

main() {
    # Validate environment before proceeding
    validate_environment
    
    log_info "=== Updating agent context files for feature $CURRENT_BRANCH ==="
    
    # Parse the plan file to extract project information
    if ! parse_plan_data "$NEW_PLAN"; then
        log_error "Failed to parse plan data"
        exit 1
    fi
    
    # Process based on agent type argument
    local success=true
    
    if [[ -z "$AGENT_TYPE" ]]; then
        # No specific agent provided - update all existing agent files
        log_info "No agent specified, updating all existing agent files..."
        if ! update_all_existing_agents; then
            success=false
        fi
    else
        # Specific agent provided - update only that agent
        log_info "Updating specific agent: $AGENT_TYPE"
        if ! update_specific_agent "$AGENT_TYPE"; then
            success=false
        fi
    fi
    
    # Print summary
    print_summary
    
    if [[ "$success" == true ]]; then
        log_success "Agent context update completed successfully"
        exit 0
    else
        log_error "Agent context update completed with errors"
        exit 1
    fi
}

# Execute main function if script is run directly
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    main "$@"
fi


================================================
FILE: .specify/templates/agent-file-template.md
================================================
# [PROJECT NAME] Development Guidelines

Auto-generated from all feature plans. Last updated: [DATE]

## Active Technologies
[EXTRACTED FROM ALL PLAN.MD FILES]

## Project Structure
```
[ACTUAL STRUCTURE FROM PLANS]
```

## Commands
[ONLY COMMANDS FOR ACTIVE TECHNOLOGIES]

## Code Style
[LANGUAGE-SPECIFIC, ONLY FOR LANGUAGES IN USE]

## Recent Changes
[LAST 3 FEATURES AND WHAT THEY ADDED]

<!-- MANUAL ADDITIONS START -->
<!-- MANUAL ADDITIONS END -->

================================================
FILE: .specify/templates/plan-template.md
================================================

# Implementation Plan: [FEATURE]

**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]
**Input**: Feature specification from `/specs/[###-feature-name]/spec.md`

## Execution Flow (/plan command scope)
```
1. Load feature spec from Input path
   → If not found: ERROR "No feature spec at {path}"
2. Fill Technical Context (scan for NEEDS CLARIFICATION)
   → Detect Project Type from context (web=frontend+backend, mobile=app+api)
   → Set Structure Decision based on project type
3. Fill the Constitution Check section based on the content of the constitution document.
4. Evaluate Constitution Check section below
   → If violations exist: Document in Complexity Tracking
   → If no justification possible: ERROR "Simplify approach first"
   → Update Progress Tracking: Initial Constitution Check
5. Execute Phase 0 → research.md
   → If NEEDS CLARIFICATION remain: ERROR "Resolve unknowns"
6. Execute Phase 1 → contracts, data-model.md, quickstart.md, agent-specific template file (e.g., `CLAUDE.md` for Claude Code, `.github/copilot-instructions.md` for GitHub Copilot, `GEMINI.md` for Gemini CLI, `QWEN.md` for Qwen Code or `AGENTS.md` for opencode).
7. Re-evaluate Constitution Check section
   → If new violations: Refactor design, return to Phase 1
   → Update Progress Tracking: Post-Design Constitution Check
8. Plan Phase 2 → Describe task generation approach (DO NOT create tasks.md)
9. STOP - Ready for /tasks command
```

**IMPORTANT**: The /plan command STOPS at step 7. Phases 2-4 are executed by other commands:
- Phase 2: /tasks command creates tasks.md
- Phase 3-4: Implementation execution (manual or via tools)

## Summary
[Extract from feature spec: primary requirement + technical approach from research]

## Technical Context
**Language/Version**: [e.g., Python 3.11, Swift 5.9, Rust 1.75 or NEEDS CLARIFICATION]  
**Primary Dependencies**: [e.g., FastAPI, UIKit, LLVM or NEEDS CLARIFICATION]  
**Storage**: [if applicable, e.g., PostgreSQL, CoreData, files or N/A]  
**Testing**: [e.g., pytest, XCTest, cargo test or NEEDS CLARIFICATION]  
**Target Platform**: [e.g., Linux server, iOS 15+, WASM or NEEDS CLARIFICATION]
**Project Type**: [single/web/mobile - determines source structure]  
**Performance Goals**: [domain-specific, e.g., 1000 req/s, 10k lines/sec, 60 fps or NEEDS CLARIFICATION]  
**Constraints**: [domain-specific, e.g., <200ms p95, <100MB memory, offline-capable or NEEDS CLARIFICATION]  
**Scale/Scope**: [domain-specific, e.g., 10k users, 1M LOC, 50 screens or NEEDS CLARIFICATION]

## Constitution Check
*GATE: Must pass before Phase 0 research. Re-check after Phase 1 design.*

### I. Library-First Architecture
- [ ] Core functionality implemented in `Separator` class or similar library pattern
- [ ] CLI/Remote API are thin wrappers, not containing business logic
- [ ] Clear separation between model architectures (MDX, VR, Demucs, MDXC)

### II. Multi-Interface Consistency  
- [ ] Feature accessible via Python API, CLI, and Remote API (if applicable)
- [ ] Parameter names identical across all interfaces
- [ ] Same model architectures supported across interfaces

### III. Test-First Development (NON-NEGOTIABLE)
- [ ] Tests written before implementation
- [ ] Unit tests for all core functionality
- [ ] Integration tests with audio validation (SSIM comparison)
- [ ] CLI tests for all exposed functionality

### IV. Performance & Resource Efficiency
- [ ] Hardware acceleration support considered (CUDA, CoreML, DirectML)
- [ ] Memory optimization for large files (streaming/batch processing)
- [ ] Tunable parameters for different hardware capabilities

### V. Model Architecture Separation
- [ ] Each architecture in separate modules
- [ ] Inherits from `CommonSeparator` pattern
- [ ] Architecture-specific parameters isolated
- [ ] Loading one architecture doesn't load others

## Project Structure

### Documentation (this feature)
```
specs/[###-feature]/
├── plan.md              # This file (/plan command output)
├── research.md          # Phase 0 output (/plan command)
├── data-model.md        # Phase 1 output (/plan command)
├── quickstart.md        # Phase 1 output (/plan command)
├── contracts/           # Phase 1 output (/plan command)
└── tasks.md             # Phase 2 output (/tasks command - NOT created by /plan)
```

### Source Code (repository root)
```
# Option 1: Single project (DEFAULT)
src/
├── models/
├── services/
├── cli/
└── lib/

tests/
├── contract/
├── integration/
└── unit/

# Option 2: Web application (when "frontend" + "backend" detected)
backend/
├── src/
│   ├── models/
│   ├── services/
│   └── api/
└── tests/

frontend/
├── src/
│   ├── components/
│   ├── pages/
│   └── services/
└── tests/

# Option 3: Mobile + API (when "iOS/Android" detected)
api/
└── [same as backend above]

ios/ or android/
└── [platform-specific structure]
```

**Structure Decision**: [DEFAULT to Option 1 unless Technical Context indicates web/mobile app]

## Phase 0: Outline & Research
1. **Extract unknowns from Technical Context** above:
   - For each NEEDS CLARIFICATION → research task
   - For each dependency → best practices task
   - For each integration → patterns task

2. **Generate and dispatch research agents**:
   ```
   For each unknown in Technical Context:
     Task: "Research {unknown} for {feature context}"
   For each technology choice:
     Task: "Find best practices for {tech} in {domain}"
   ```

3. **Consolidate findings** in `research.md` using format:
   - Decision: [what was chosen]
   - Rationale: [why chosen]
   - Alternatives considered: [what else evaluated]

**Output**: research.md with all NEEDS CLARIFICATION resolved

## Phase 1: Design & Contracts
*Prerequisites: research.md complete*

1. **Extract entities from feature spec** → `data-model.md`:
   - Entity name, fields, relationships
   - Validation rules from requirements
   - State transitions if applicable

2. **Generate API contracts** from functional requirements:
   - For each user action → endpoint
   - Use standard REST/GraphQL patterns
   - Output OpenAPI/GraphQL schema to `/contracts/`

3. **Generate contract tests** from contracts:
   - One test file per endpoint
   - Assert request/response schemas
   - Tests must fail (no implementation yet)

4. **Extract test scenarios** from user stories:
   - Each story → integration test scenario
   - Quickstart test = story validation steps

5. **Update agent file incrementally** (O(1) operation):
   - Run `.specify/scripts/bash/update-agent-context.sh cursor`
     **IMPORTANT**: Execute it exactly as specified above. Do not add or remove any arguments.
   - If exists: Add only NEW tech from current plan
   - Preserve manual additions between markers
   - Update recent changes (keep last 3)
   - Keep under 150 lines for token efficiency
   - Output to repository root

**Output**: data-model.md, /contracts/*, failing tests, quickstart.md, agent-specific file

## Phase 2: Task Planning Approach
*This section describes what the /tasks command will do - DO NOT execute during /plan*

**Task Generation Strategy**:
- Load `.specify/templates/tasks-template.md` as base
- Generate tasks from Phase 1 design docs (contracts, data model, quickstart)
- Each contract → contract test task [P]
- Each entity → model creation task [P] 
- Each user story → integration test task
- Implementation tasks to make tests pass

**Ordering Strategy**:
- TDD order: Tests before implementation 
- Dependency order: Models before services before UI
- Mark [P] for parallel execution (independent files)

**Estimated Output**: 25-30 numbered, ordered tasks in tasks.md

**IMPORTANT**: This phase is executed by the /tasks command, NOT by /plan

## Phase 3+: Future Implementation
*These phases are beyond the scope of the /plan command*

**Phase 3**: Task execution (/tasks command creates tasks.md)  
**Phase 4**: Implementation (execute tasks.md following constitutional principles)  
**Phase 5**: Validation (run tests, execute quickstart.md, performance validation)

## Complexity Tracking
*Fill ONLY if Constitution Check has violations that must be justified*

| Violation | Why Needed | Simpler Alternative Rejected Because |
|-----------|------------|-------------------------------------|
| [e.g., 4th project] | [current need] | [why 3 projects insufficient] |
| [e.g., Repository pattern] | [specific problem] | [why direct DB access insufficient] |


## Progress Tracking
*This checklist is updated during execution flow*

**Phase Status**:
- [ ] Phase 0: Research complete (/plan command)
- [ ] Phase 1: Design complete (/plan command)
- [ ] Phase 2: Task planning complete (/plan command - describe approach only)
- [ ] Phase 3: Tasks generated (/tasks command)
- [ ] Phase 4: Implementation complete
- [ ] Phase 5: Validation passed

**Gate Status**:
- [ ] Initial Constitution Check: PASS
- [ ] Post-Design Constitution Check: PASS
- [ ] All NEEDS CLARIFICATION resolved
- [ ] Complexity deviations documented

---
*Based on Constitution v1.0.0 - See `.specify/memory/constitution.md`*


================================================
FILE: .specify/templates/spec-template.md
================================================
# Feature Specification: [FEATURE NAME]

**Feature Branch**: `[###-feature-name]`  
**Created**: [DATE]  
**Status**: Draft  
**Input**: User description: "$ARGUMENTS"

## Execution Flow (main)
```
1. Parse user description from Input
   → If empty: ERROR "No feature description provided"
2. Extract key concepts from description
   → Identify: actors, actions, data, constraints
3. For each unclear aspect:
   → Mark with [NEEDS CLARIFICATION: specific question]
4. Fill User Scenarios & Testing section
   → If no clear user flow: ERROR "Cannot determine user scenarios"
5. Generate Functional Requirements
   → Each requirement must be testable
   → Mark ambiguous requirements
6. Identify Key Entities (if data involved)
7. Run Review Checklist
   → If any [NEEDS CLARIFICATION]: WARN "Spec has uncertainties"
   → If implementation details found: ERROR "Remove tech details"
8. Return: SUCCESS (spec ready for planning)
```

---

## ⚡ Quick Guidelines
- ✅ Focus on WHAT users need and WHY
- ❌ Avoid HOW to implement (no tech stack, APIs, code structure)
- 👥 Written for business stakeholders, not developers

### Section Requirements
- **Mandatory sections**: Must be completed for every feature
- **Optional sections**: Include only when relevant to the feature
- When a section doesn't apply, remove it entirely (don't leave as "N/A")

### For AI Generation
When creating this spec from a user prompt:
1. **Mark all ambiguities**: Use [NEEDS CLARIFICATION: specific question] for any assumption you'd need to make
2. **Don't guess**: If the prompt doesn't specify something (e.g., "login system" without auth method), mark it
3. **Think like a tester**: Every vague requirement should fail the "testable and unambiguous" checklist item
4. **Common underspecified areas**:
   - User types and permissions
   - Data retention/deletion policies  
   - Performance targets and scale
   - Error handling behaviors
   - Integration requirements
   - Security/compliance needs

---

## User Scenarios & Testing *(mandatory)*

### Primary User Story
[Describe the main user journey in plain language]

### Acceptance Scenarios
1. **Given** [initial state], **When** [action], **Then** [expected outcome]
2. **Given** [initial state], **When** [action], **Then** [expected outcome]

### Edge Cases
- What happens when [boundary condition]?
- How does system handle [error scenario]?

## Requirements *(mandatory)*

### Functional Requirements
- **FR-001**: System MUST [specific capability, e.g., "allow users to create accounts"]
- **FR-002**: System MUST [specific capability, e.g., "validate email addresses"]  
- **FR-003**: Users MUST be able to [key interaction, e.g., "reset their password"]
- **FR-004**: System MUST [data requirement, e.g., "persist user preferences"]
- **FR-005**: System MUST [behavior, e.g., "log all security events"]

*Example of marking unclear requirements:*
- **FR-006**: System MUST authenticate users via [NEEDS CLARIFICATION: auth method not specified - email/password, SSO, OAuth?]
- **FR-007**: System MUST retain user data for [NEEDS CLARIFICATION: retention period not specified]

### Key Entities *(include if feature involves data)*
- **[Entity 1]**: [What it represents, key attributes without implementation]
- **[Entity 2]**: [What it represents, relationships to other entities]

---

## Review & Acceptance Checklist
*GATE: Automated checks run during main() execution*

### Content Quality
- [ ] No implementation details (languages, frameworks, APIs)
- [ ] Focused on user value and business needs
- [ ] Written for non-technical stakeholders
- [ ] All mandatory sections completed

### Requirement Completeness
- [ ] No [NEEDS CLARIFICATION] markers remain
- [ ] Requirements are testable and unambiguous  
- [ ] Success criteria are measurable
- [ ] Scope is clearly bounded
- [ ] Dependencies and assumptions identified

---

## Execution Status
*Updated by main() during processing*

- [ ] User description parsed
- [ ] Key concepts extracted
- [ ] Ambiguities marked
- [ ] User scenarios defined
- [ ] Requirements generated
- [ ] Entities identified
- [ ] Review checklist passed

---


================================================
FILE: .specify/templates/tasks-template.md
================================================
# Tasks: [FEATURE NAME]

**Input**: Design documents from `/specs/[###-feature-name]/`
**Prerequisites**: plan.md (required), research.md, data-model.md, contracts/

## Execution Flow (main)
```
1. Load plan.md from feature directory
   → If not found: ERROR "No implementation plan found"
   → Extract: tech stack, libraries, structure
2. Load optional design documents:
   → data-model.md: Extract entities → model tasks
   → contracts/: Each file → contract test task
   → research.md: Extract decisions → setup tasks
3. Generate tasks by category:
   → Setup: project init, dependencies, linting
   → Tests: contract tests, integration tests
   → Core: models, services, CLI commands
   → Integration: DB, middleware, logging
   → Polish: unit tests, performance, docs
4. Apply task rules:
   → Different files = mark [P] for parallel
   → Same file = sequential (no [P])
   → Tests before implementation (TDD)
5. Number tasks sequentially (T001, T002...)
6. Generate dependency graph
7. Create parallel execution examples
8. Validate task completeness:
   → All contracts have tests?
   → All entities have models?
   → All endpoints implemented?
9. Return: SUCCESS (tasks ready for execution)
```

## Format: `[ID] [P?] Description`
- **[P]**: Can run in parallel (different files, no dependencies)
- Include exact file paths in descriptions

## Path Conventions
- **Single project**: `src/`, `tests/` at repository root
- **Web app**: `backend/src/`, `frontend/src/`
- **Mobile**: `api/src/`, `ios/src/` or `android/src/`
- Paths shown below assume single project - adjust based on plan.md structure

## Phase 3.1: Setup
- [ ] T001 Create project structure per implementation plan
- [ ] T002 Initialize [language] project with [framework] dependencies
- [ ] T003 [P] Configure linting and formatting tools

## Phase 3.2: Tests First (TDD) ⚠️ MUST COMPLETE BEFORE 3.3
**CRITICAL: These tests MUST be written and MUST FAIL before ANY implementation**
- [ ] T004 [P] Contract test POST /api/users in tests/contract/test_users_post.py
- [ ] T005 [P] Contract test GET /api/users/{id} in tests/contract/test_users_get.py
- [ ] T006 [P] Integration test user registration in tests/integration/test_registration.py
- [ ] T007 [P] Integration test auth flow in tests/integration/test_auth.py

## Phase 3.3: Core Implementation (ONLY after tests are failing)
- [ ] T008 [P] User model in src/models/user.py
- [ ] T009 [P] UserService CRUD in src/services/user_service.py
- [ ] T010 [P] CLI --create-user in src/cli/user_commands.py
- [ ] T011 POST /api/users endpoint
- [ ] T012 GET /api/users/{id} endpoint
- [ ] T013 Input validation
- [ ] T014 Error handling and logging

## Phase 3.4: Integration
- [ ] T015 Connect UserService to DB
- [ ] T016 Auth middleware
- [ ] T017 Request/response logging
- [ ] T018 CORS and security headers

## Phase 3.5: Polish
- [ ] T019 [P] Unit tests for validation in tests/unit/test_validation.py
- [ ] T020 Performance tests (<200ms)
- [ ] T021 [P] Update docs/api.md
- [ ] T022 Remove duplication
- [ ] T023 Run manual-testing.md

## Dependencies
- Tests (T004-T007) before implementation (T008-T014)
- T008 blocks T009, T015
- T016 blocks T018
- Implementation before polish (T019-T023)

## Parallel Example
```
# Launch T004-T007 together:
Task: "Contract test POST /api/users in tests/contract/test_users_post.py"
Task: "Contract test GET /api/users/{id} in tests/contract/test_users_get.py"
Task: "Integration test registration in tests/integration/test_registration.py"
Task: "Integration test auth in tests/integration/test_auth.py"
```

## Notes
- [P] tasks = different files, no dependencies
- Verify tests fail before implementing
- Commit after each task
- Avoid: vague tasks, same file conflicts

## Task Generation Rules
*Applied during main() execution*

1. **From Contracts**:
   - Each contract file → contract test task [P]
   - Each endpoint → implementation task
   
2. **From Data Model**:
   - Each entity → model creation task [P]
   - Relationships → service layer tasks
   
3. **From User Stories**:
   - Each story → integration test [P]
   - Quickstart scenarios → validation tasks

4. **Ordering**:
   - Setup → Tests → Models → Services → Endpoints → Polish
   - Dependencies block parallel execution

## Validation Checklist
*GATE: Checked by main() before returning*

- [ ] All contracts have corresponding tests
- [ ] All entities have model tasks
- [ ] All tests come before implementation
- [ ] Parallel tasks truly independent
- [ ] Each task specifies exact file path
- [ ] No task modifies same file as another [P] task

================================================
FILE: Dockerfile.cloudrun
================================================
# Audio Separator API - Cloud Run GPU Deployment
# Optimized for NVIDIA L4 GPU on Google Cloud Run
#
# Models are baked into the image for zero cold-start latency.
# To update models, rebuild the image.
#
# Build: docker build -f Dockerfile.cloudrun -t audio-separator-cloudrun .
# Run:   docker run --gpus all -p 8080:8080 audio-separator-cloudrun

FROM nvidia/cuda:12.6.3-runtime-ubuntu22.04

# Prevent interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive

# Install Python 3.12 from deadsnakes PPA (onnxruntime-gpu requires >= 3.11)
# and system dependencies
RUN apt-get update && apt-get install -y --no-install-recommends \
    software-properties-common \
    && add-apt-repository -y ppa:deadsnakes/ppa \
    && apt-get update && apt-get install -y --no-install-recommends \
    # Python 3.12
    python3.12 \
    python3.12-dev \
    python3.12-venv \
    # FFmpeg
    ffmpeg \
    # Audio libraries
    libsndfile1 \
    libsndfile1-dev \
    libsox-dev \
    sox \
    libportaudio2 \
    portaudio19-dev \
    libasound2-dev \
    libpulse-dev \
    libjack-dev \
    libsamplerate0 \
    libsamplerate0-dev \
    # Build tools (for compiling Python packages with C extensions)
    build-essential \
    gcc \
    g++ \
    pkg-config \
    # Utilities
    curl \
    && rm -rf /var/lib/apt/lists/* \
    && python3.12 --version && ffmpeg -version

# Set Python 3.12 as default and install pip
RUN update-alternatives --install /usr/bin/python3 python3 /usr/bin/python3.12 1 \
    && update-alternatives --install /usr/bin/python python /usr/bin/python3.12 1 \
    && curl -sS https://bootstrap.pypa.io/get-pip.py | python3.12 \
    && python3 -m pip install --no-cache-dir --upgrade pip setuptools wheel

# Install audio-separator with GPU support and API dependencies
COPY . /tmp/audio-separator-src
RUN cd /tmp/audio-separator-src \
    && pip install --no-cache-dir ".[gpu]" \
    && pip install --no-cache-dir \
        "fastapi>=0.104.0" \
        "uvicorn[standard]>=0.24.0" \
        "python-multipart>=0.0.6" \
        "filetype>=1.2.0" \
        "google-cloud-storage>=2.0.0" \
        "google-cloud-firestore>=2.0.0" \
    && rm -rf /tmp/audio-separator-src

# Set up CUDA library paths
RUN echo '/usr/local/cuda/lib64' >> /etc/ld.so.conf.d/cuda.conf && ldconfig

# Environment configuration
ENV MODEL_DIR=/models \
    STORAGE_DIR=/tmp/storage \
    PORT=8080 \
    LD_LIBRARY_PATH=/usr/local/cuda/lib64:$LD_LIBRARY_PATH \
    PATH=/usr/local/cuda/bin:$PATH \
    PYTHONUNBUFFERED=1

# Create directories
RUN mkdir -p /models /tmp/storage/outputs

# Bake ensemble preset models into the image.
# These are the models used by the default presets (instrumental_clean + karaoke).
# Total: ~1-1.5 GB. This eliminates cold-start model download time.
COPY scripts/download_preset_models.py /tmp/download_preset_models.py
RUN python3 /tmp/download_preset_models.py && rm /tmp/download_preset_models.py && ls -lh /models/

# Expose Cloud Run default port
EXPOSE 8080

# Health check for container orchestration
HEALTHCHECK --interval=30s --timeout=10s --start-period=30s --retries=3 \
    CMD curl -f http://localhost:8080/health || exit 1

# Run the API server
CMD ["python3", "-m", "audio_separator.remote.deploy_cloudrun"]


================================================
FILE: Dockerfile.cpu
================================================
# Use an official Python runtime as a parent image
FROM python:3.12-slim

# Set the working directory in the container
WORKDIR /workdir

# Install necessary packages
RUN apt-get update && apt-get install -y ffmpeg build-essential

RUN python -m pip install --upgrade pip

RUN --mount=type=cache,target=/root/.cache \
    pip install "audio-separator[cpu]"

# Run audio-separator when the container launches
ENTRYPOINT ["audio-separator"]


================================================
FILE: Dockerfile.cuda11
================================================
# Use an official Python runtime as a parent image
FROM nvidia/cuda:11.8.0-base-ubuntu22.04

# Set the working directory in the container
WORKDIR /workdir

RUN apt-get update && apt-get install -y \
    ffmpeg \
    build-essential \
    python3 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade pip

# Install the GPU version of audio-separator, which installs the CUDA 11 compatible version of ONNXRuntime
# (the default CUDA version for ORT is 11.8, see https://onnxruntime.ai/docs/install/ for more info)
RUN --mount=type=cache,target=/root/.cache \
    pip3 install "audio-separator[gpu]"

# Run audio-separator when the container launches
ENTRYPOINT ["audio-separator"]


================================================
FILE: Dockerfile.cuda12
================================================
# Use the latest CUDA 12 runtime as base image
FROM nvidia/cuda:12.3.1-devel-ubuntu22.04

# Set the working directory in the container
WORKDIR /workdir

RUN apt-get update && apt-get install -y \
    ffmpeg \
    build-essential \
    python3 \
    python3-pip \
    && rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade pip

# Install the CUDA 12 compatible version of ONNXRuntime (the default CUDA version for ORT is still 11.8 so they've provided a separate package index)
# See https://onnxruntime.ai/docs/install/
RUN pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/

# Install audio-separator without any specific onnxruntime (onnxruntime should already be satisfied by the above)
RUN --mount=type=cache,target=/root/.cache \
    pip3 install "audio-separator"

# Run audio-separator when the container launches
ENTRYPOINT ["audio-separator"]


================================================
FILE: Dockerfile.runpod-cuda11
================================================
# Runpod Base image: https://github.com/runpod/containers/blob/main/official-templates/base/Dockerfile
FROM runpod/base:0.5.0-cuda11.8.0

RUN apt-get update && apt-get install -y \
    ffmpeg \
    && rm -rf /var/lib/apt/lists/*

RUN python3 -m pip install --upgrade pip

# Install the CUDA 11 compatible version of ONNXRuntime (The default CUDA version for ORT is 11.8)
# See https://onnxruntime.ai/docs/install/
RUN pip install onnxruntime-gpu

# Install audio-separator without any specific onnxruntime (onnxruntime should already be satisfied by the above)
RUN --mount=type=cache,target=/root/.cache \
    pip3 install "audio-separator"


================================================
FILE: Dockerfile.runpod-cuda12
================================================
# Runpod Base image: https://github.com/runpod/containers/blob/main/official-templates/base/Dockerfile
FROM runpod/base:0.6.2-cuda12.1.0

RUN wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2204/x86_64/cuda-keyring_1.1-1_all.deb
RUN dpkg -i cuda-keyring_1.1-1_all.deb

RUN apt-get update && apt-get upgrade -y

RUN apt-get install -y \
    ffmpeg \
    cuda-toolkit \
    cudnn9-cuda-12

RUN python3 -m pip install --upgrade pip

# Install the CUDA 12 compatible version of ONNXRuntime (the default CUDA version for ORT is still 11.8 so they've provided a separate package index)
# See https://onnxruntime.ai/docs/install/
RUN pip install onnxruntime-gpu --extra-index-url https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/onnxruntime-cuda-12/pypi/simple/

# Install audio-separator without any specific onnxruntime (onnxruntime should already be satisfied by the above)
RUN --mount=type=cache,target=/root/.cache \
    pip3 install "audio-separator"


================================================
FILE: LICENSE
================================================
MIT License

Copyright (c) 2023 karaokenerds

Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.


================================================
FILE: README.md
================================================
<div align="center">

# 🎶 Audio Separator 🎶

[![PyPI version](https://badge.fury.io/py/audio-separator.svg)](https://badge.fury.io/py/audio-separator)
[![Conda Version](https://img.shields.io/conda/vn/conda-forge/audio-separator.svg)](https://anaconda.org/conda-forge/audio-separator)
[![Docker pulls](https://img.shields.io/docker/pulls/beveradb/audio-separator.svg)](https://hub.docker.com/r/beveradb/audio-separator/tags)
[![codecov](https://codecov.io/gh/karaokenerds/python-audio-separator/graph/badge.svg?token=N7YK4ET5JP)](https://codecov.io/gh/karaokenerds/python-audio-separator)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/drive/1gSlmSmna7f7fH6OjsiMEDLl-aJ9kGPkY?usp=sharing)
[![Open In Huggingface](https://huggingface.co/datasets/huggingface/badges/resolve/main/open-in-hf-spaces-sm.svg)](https://huggingface.co/spaces/nomadkaraoke/audio-separator)

</div>

**Summary:** Easy to use audio stem separation from the command line or as a dependency in your own Python project, using the amazing MDX-Net, VR Arch, Demucs and MDXC models available in UVR by @Anjok07 & @aufr33.

Audio Separator is a Python package that allows you to separate an audio file into various stems, using models trained by @Anjok07 for use with [Ultimate Vocal Remover](https://github.com/Anjok07/ultimatevocalremovergui).

The simplest (and probably most used) use case for this package is to separate an audio file into two stems, Instrumental and Vocals, which can be very useful for producing karaoke videos! However, the models available in UVR can separate audio into many more stems, such as Drums, Bass, Piano, and Guitar, and perform other audio processing tasks, such as denoising or removing echo/reverb.

<details>
<summary align="center"><b>Table of Contents</div></b></summary>

- [🎶 Audio Separator 🎶](#-audio-separator-)
  - [Features](#features)
  - [Installation 🛠️](#installation-%EF%B8%8F)
    - [🐳 Docker](#-docker)
    - [🎮 Nvidia GPU with CUDA or 🧪 Google Colab](#-nvidia-gpu-with-cuda-or--google-colab)
    - [ Apple Silicon, macOS Sonoma+ with M1 or newer CPU (CoreML acceleration)](#-apple-silicon-macos-sonoma-with-m1-or-newer-cpu-coreml-acceleration)
    - [🐢 No hardware acceleration, CPU only](#-no-hardware-acceleration-cpu-only)
    - [🎥 FFmpeg dependency](#-ffmpeg-dependency)
  - [GPU / CUDA specific installation steps with Pip](#gpu--cuda-specific-installation-steps-with-pip)
    - [Multiple CUDA library versions may be needed](#multiple-cuda-library-versions-may-be-needed)
  - [Usage 🚀](#usage-)
    - [Command Line Interface (CLI)](#command-line-interface-cli)
    - [Listing and Filtering Available Models](#listing-and-filtering-available-models)
      - [Filtering Models](#filtering-models)
      - [Limiting Results](#limiting-results)
      - [JSON Output](#json-output)
    - [Full command-line interface options](#full-command-line-interface-options)
    - [As a Dependency in a Python Project](#as-a-dependency-in-a-python-project)
      - [Batch processing and processing with multiple models](#batch-processing-and-processing-with-multiple-models)
      - [Renaming Stems](#renaming-stems)
  - [Parameters for the Separator class](#parameters-for-the-separator-class)
  - [Remote API Usage 🌐](#remote-api-usage-)
  - [Requirements 📋](#requirements-)
  - [Developing Locally](#developing-locally)
    - [Prerequisites](#prerequisites)
    - [Clone the Repository](#clone-the-repository)
    - [Create and activate the Conda Environment](#create-and-activate-the-conda-environment)
    - [Install Dependencies](#install-dependencies)
    - [Running the Command-Line Interface Locally](#running-the-command-line-interface-locally)
    - [Deactivate the Virtual Environment](#deactivate-the-virtual-environment)
    - [Building the Package](#building-the-package)
  - [Contributing 🤝](#contributing-)
  - [License 📄](#license-)
  - [Credits 🙏](#credits-)
  - [Contact 💌](#contact-)
  - [Thanks to all contributors for their efforts](#thanks-to-all-contributors-for-their-efforts)
</details>

---

## Features

- Separate audio into multiple stems, e.g. instrumental and vocals.
- Supports all common audio formats (WAV, MP3, FLAC, M4A, etc.)
- Ability to inference using a pre-trained model in PTH or ONNX format.
- CLI support for easy use in scripts and batch processing.
- Python API for integration into other projects.

## Installation 🛠️

### 🐳 Docker

If you're able to use docker, you don't actually need to _install_ anything - there are [images published on Docker Hub](https://hub.docker.com/r/beveradb/audio-separator/tags) for GPU (CUDA) and CPU inferencing, for both `amd64` and `arm64` platforms.

You probably want to volume-mount a folder containing whatever file you want to separate, which can then also be used as the output folder.

For instance, if your current directory has the file `input.wav`, you could execute `audio-separator` as shown below (see [usage](#usage-) section for more details):

```sh
docker run -it -v `pwd`:/workdir beveradb/audio-separator input.wav
```

If you're using a machine with a GPU, you'll want to use the GPU specific image and pass in the GPU device to the container, like this:

```sh
docker run -it --gpus all -v `pwd`:/workdir beveradb/audio-separator:gpu input.wav
```

If the GPU isn't being detected, make sure your docker runtime environment is passing through the GPU correctly - there are [various guides](https://www.celantur.com/blog/run-cuda-in-docker-on-linux/) online to help with that.

### 🎮 Nvidia GPU with CUDA or 🧪 Google Colab

**Supported CUDA Versions:** 11.8 and 12.2

💬 If successfully configured, you should see this log message when running `audio-separator --env_info`:
 `ONNXruntime has CUDAExecutionProvider available, enabling acceleration`

Conda:
```sh
conda install pytorch=*=*cuda* onnxruntime=*=*cuda* audio-separator -c pytorch -c conda-forge
```

Pip:
```sh
pip install "audio-separator[gpu]"
```

Docker:
```sh
beveradb/audio-separator:gpu
```

###  Apple Silicon, macOS Sonoma+ with M1 or newer CPU (CoreML acceleration)

💬 If successfully configured, you should see this log message when running `audio-separator --env_info`:
 `ONNXruntime has CoreMLExecutionProvider available, enabling acceleration`

Pip:
```sh
pip install "audio-separator[cpu]"
```

### 🐢 No hardware acceleration, CPU only

Conda:
```sh
conda install audio-separator -c pytorch -c conda-forge
```

Pip:
```sh
pip install "audio-separator[cpu]"
```

Docker:
```sh
beveradb/audio-separator
```

### 🎥 FFmpeg dependency

💬 To test if `audio-separator` has been successfully configured to use FFmpeg, run `audio-separator --env_info`. The log will show `FFmpeg installed`.

If you installed `audio-separator` using `conda` or `docker`, FFmpeg should already be available in your environment.

You may need to separately install FFmpeg. It should be easy to install on most platforms, e.g.:

🐧 Debian/Ubuntu:
```sh
apt-get update; apt-get install -y ffmpeg
```

 macOS:
```sh
brew update; brew install ffmpeg
```

## GPU / CUDA specific installation steps with Pip

In theory, all you should need to do to get `audio-separator` working with a GPU is install it with the `[gpu]` extra as above.

However, sometimes getting both PyTorch and ONNX Runtime working with CUDA support can be a bit tricky so it may not work that easily.

You may need to reinstall both packages directly, allowing pip to calculate the right versions for your platform, for example:

- `pip uninstall torch onnxruntime`
- `pip cache purge`
- `pip install --force-reinstall torch torchvision torchaudio`
- `pip install --force-reinstall onnxruntime-gpu`

I generally recommend installing the latest version of PyTorch for your environment using the command recommended by the wizard here:
<https://pytorch.org/get-started/locally/>

### Multiple CUDA library versions may be needed

Depending on your CUDA version and environment, you may need to install specific version(s) of CUDA libraries for ONNX Runtime to use your GPU.

🧪 Google Colab, for example, now uses CUDA 12 by default, but ONNX Runtime still needs CUDA 11 libraries to work.

If you see the error `Failed to load library` or `cannot open shared object file` when you run `audio-separator`, this is likely the issue.

You can install the CUDA 11 libraries _alongside_ CUDA 12 like so:
```sh
apt update; apt install nvidia-cuda-toolkit
```

If you encounter the following messages when running on Google Colab or in another environment:
```
[E:onnxruntime:Default, provider_bridge_ort.cc:1862 TryGetProviderInfo_CUDA] /onnxruntime_src/onnxruntime/core/session/provider_bridge_ort.cc:1539 onnxruntime::Provider& onnxruntime::ProviderLibrary::Get() [ONNXRuntimeError] : 1 : FAIL : Failed to load library libonnxruntime_providers_cuda.so with error: libcudnn_adv.so.9: cannot open shared object file: No such file or directory

[W:onnxruntime:Default, onnxruntime_pybind_state.cc:993 CreateExecutionProviderInstance] Failed to create CUDAExecutionProvider. Require cuDNN 9.* and CUDA 12.*. Please install all dependencies as mentioned in the GPU requirements page (https://onnxruntime.ai/docs/execution-providers/CUDA-ExecutionProvider.html#requirements), make sure they're in the PATH, and that your GPU is supported.
```
You can resolve this by running the following command:
```sh
python -m pip install ort-nightly-gpu --index-url=https://aiinfra.pkgs.visualstudio.com/PublicPackages/_packaging/ort-cuda-12-nightly/pypi/simple/
```

> Note: if anyone knows how to make this cleaner so we can support both different platform-specific dependencies for hardware acceleration without a separate installation process for each, please let me know or raise a PR!

## Usage 🚀

### Command Line Interface (CLI)

You can use Audio Separator via the command line, for example:

```sh
audio-separator /path/to/your/input/audio.wav --model_filename model_bs_roformer_ep_317_sdr_12.9755.ckpt
```

This command will download the specified model file, process the `audio.wav` input audio and generate two new files in the current directory, one containing vocals and one containing instrumental.

**Note:** You do not need to download any files yourself - audio-separator does that automatically for you!

To see a list of supported models, run `audio-separator --list_models`

Any file listed in the list models output can be specified (with file extension) with the model_filename parameter (e.g. `--model_filename UVR_MDXNET_KARA_2.onnx`) and it will be automatically downloaded to the `--model_file_dir` (default: `/tmp/audio-separator-models/`) folder on first usage.

### Listing and Filtering Available Models

You can view all available models using the `--list_models` (or `-l`) flag:

```sh
audio-separator --list_models
```

The output shows a table with the following columns:
- Model Filename: The filename to use with `--model_filename`
- Arch: The model architecture (MDX, MDXC, Demucs, etc.)
- Output Stems (SDR): The stems this model can separate, with Signal-to-Distortion Ratio scores where available
- Friendly Name: A human-readable name describing the model

#### Filtering Models

You can filter and sort the model list by stem type using `--list_filter`. For example, to find models that can separate drums:

```sh
audio-separator -l --list_filter=drums
```

Example output:
```
-----------------------------------------------------------------------------------------------------------------------------------
Model Filename        Arch    Output Stems (SDR)                                            Friendly Name
-----------------------------------------------------------------------------------------------------------------------------------
htdemucs_ft.yaml      Demucs  vocals (10.8), drums (10.1), bass (11.9), other               Demucs v4: htdemucs_ft
hdemucs_mmi.yaml      Demucs  vocals (10.3), drums (9.7), bass (12.0), other                Demucs v4: hdemucs_mmi
htdemucs.yaml         Demucs  vocals (10.0), drums (9.4), bass (11.3), other                Demucs v4: htdemucs
htdemucs_6s.yaml      Demucs  vocals (9.7), drums (8.5), bass (10.0), guitar, piano, other  Demucs v4: htdemucs_6s
```

#### Limiting Results

You can limit the number of results shown using `--list_limit`. This is useful for finding the best performing models for a particular stem. For example, to see the top 5 vocal separation models:

```sh
audio-separator -l --list_filter=vocals --list_limit=5
```

Example output:
```
--------------------------------------------------------------------------------------------------------------------------------------------------------------
Model Filename                             Arch  Output Stems (SDR)                   Friendly Name
--------------------------------------------------------------------------------------------------------------------------------------------------------------
model_bs_roformer_ep_317_sdr_12.9755.ckpt  MDXC  vocals* (12.9), instrumental (17.0)  Roformer Model: BS-Roformer-Viperx-1297
model_bs_roformer_ep_368_sdr_12.9628.ckpt  MDXC  vocals* (12.9), instrumental (17.0)  Roformer Model: BS-Roformer-Viperx-1296
vocals_mel_band_roformer.ckpt              MDXC  vocals* (12.6), other                Roformer Model: MelBand Roformer | Vocals by Kimberley Jensen
melband_roformer_big_beta4.ckpt            MDXC  vocals* (12.5), other                Roformer Model: MelBand Roformer Kim | Big Beta 4 FT by unwa
mel_band_roformer_kim_ft_unwa.ckpt         MDXC  vocals* (12.4), other                Roformer Model: MelBand Roformer Kim | FT by unwa
```

#### JSON Output

For programmatic use, you can output the model list in JSON format:

```sh
audio-separator -l --list_format=json
```

### Processing Large Files

For very long audio files (>1 hour), you may encounter out-of-memory errors. The `--chunk_duration` option automatically splits large files into smaller chunks, processes them separately, and merges the results:

```sh
# Process an 8-hour podcast in 10-minute chunks
audio-separator long_podcast.wav --chunk_duration 600

# Adjust chunk size based on available memory
audio-separator very_long_audio.wav --chunk_duration 300  # 5-minute chunks
```

#### How It Works

1. **Split**: The input file is split into fixed-duration chunks (e.g., 10 minutes)
2. **Process**: Each chunk is processed separately, reducing peak memory usage
3. **Merge**: The results are merged back together with simple concatenation

The chunking feature supports all model types:
- **2-stem models** (e.g., MDX): Vocals + Instrumental
- **4-stem models** (e.g., Demucs): Drums, Bass, Other, Vocals
- **6-stem models** (e.g., Demucs 6s): Bass, Drums, Other, Vocals, Guitar, Piano

#### Benefits

- **Prevents OOM errors**: Process files of any length without running out of memory
- **Predictable memory usage**: Memory usage stays bounded regardless of file length
- **No quality loss**: Each chunk is fully processed with the selected model
- **Multi-stem support**: Works seamlessly with 2, 4, and 6-stem models

#### Recommendations

- **Files > 1 hour**: Use `--chunk_duration 600` (10 minutes)
- **Limited memory systems**: Use smaller chunks (300-600 seconds)
- **Ample memory**: You may not need chunking at all

#### Note on Audio Quality

Chunks are concatenated without crossfading, which may result in minor artifacts at chunk boundaries in rare cases. For most use cases, these are not noticeable. The simple concatenation approach keeps processing time minimal while solving out-of-memory issues.

### Ensembling Multiple Models

You can combine the results of multiple models to improve separation quality. This will run each model and then combine their outputs using a specified algorithm.

#### CLI Usage

Use `-m` for the primary model and `--extra_models` for additional models. You can also specify the ensemble algorithm using `--ensemble_algorithm`.

```sh
# Ensemble two models using the default 'avg_wave' algorithm
audio-separator audio.wav -m model1.ckpt --extra_models model2.onnx

# Ensemble multiple models using a specific algorithm
audio-separator audio.wav -m model1.ckpt --extra_models model2.onnx model3.ckpt --ensemble_algorithm max_fft

# With custom weights (must match the number of models)
audio-separator audio.wav -m model1.ckpt --extra_models model2.onnx --ensemble_weights 2.0 1.0
```

#### Python API Usage

```python
from audio_separator.separator import Separator

# Initialize the Separator class with custom parameters
separator = Separator(
    output_dir='output',
    ensemble_algorithm='avg_wave'
)

# List of models to ensemble
# Note: These models will be downloaded automatically if not present
models = [
    'UVR-MDX-NET-Inst_HQ_3.onnx',
    'UVR_MDXNET_KARA_2.onnx'
]

# Specify multiple models for ensembling
separator.load_model(model_filename=models)

# Perform separation
output_files = separator.separate('audio.wav')
```

#### Supported Ensemble Algorithms
- `avg_wave`: Weighted average of waveforms (default)
- `median_wave`: Median of waveforms
- `min_wave`: Minimum of waveforms
- `max_wave`: Maximum of waveforms
- `avg_fft`: Weighted average of spectrograms
- `median_fft`: Median of spectrograms
- `min_fft`: Minimum of spectrograms
- `max_fft`: Maximum of spectrograms
- `uvr_max_spec`: UVR-based maximum spectrogram ensemble
- `uvr_min_spec`: UVR-based minimum spectrogram ensemble
- `ensemble_wav`: UVR-based least noisy chunk ensemble

#### Ensemble Presets

Instead of specifying models and algorithms manually, you can use curated presets based on community-tested combinations:

```sh
# List available presets
audio-separator --list_presets

# Use a preset (models and algorithm are configured automatically)
audio-separator audio.wav --ensemble_preset vocal_balanced

# Override a preset's algorithm
audio-separator audio.wav --ensemble_preset vocal_balanced --ensemble_algorithm max_fft
```

**Python API:**
```python
separator = Separator(output_dir='output', ensemble_preset='vocal_balanced')
separator.load_model()  # Uses preset's models automatically
output_files = separator.separate('audio.wav')
```

Available presets:

| Preset | Use Case | Models | Algorithm |
|--------|----------|--------|-----------|
| `instrumental_clean` | Cleanest instrumentals, minimal vocal bleed | 2 | `uvr_max_spec` |
| `instrumental_full` | Maximum instrument preservation | 2 | `uvr_max_spec` |
| `instrumental_balanced` | Good noise/fullness balance | 2 | `uvr_max_spec` |
| `instrumental_low_resource` | Fast, low VRAM | 2 | `avg_fft` |
| `vocal_balanced` | Best overall vocal quality | 2 | `avg_fft` |
| `vocal_clean` | Minimal instrument bleed | 2 | `min_fft` |
| `vocal_full` | Maximum vocal capture | 2 | `max_fft` |
| `vocal_rvc` | Optimized for RVC/AI training | 2 | `avg_wave` |
| `karaoke` | Lead vocal removal | 3 | `avg_wave` |

Presets are defined in `audio_separator/ensemble_presets.json` — contributions welcome via PR!

### Full command-line interface options

```sh
usage: audio-separator [-h] [-v] [-d] [-e] [-l] [--log_level LOG_LEVEL] [--list_filter LIST_FILTER] [--list_limit LIST_LIMIT] [--list_format {pretty,json}] [-m MODEL_FILENAME] [--output_format OUTPUT_FORMAT]
                       [--output_bitrate OUTPUT_BITRATE] [--output_dir OUTPUT_DIR] [--model_file_dir MODEL_FILE_DIR] [--download_model_only] [--invert_spect] [--normalization NORMALIZATION]
                       [--amplification AMPLIFICATION] [--single_stem SINGLE_STEM] [--sample_rate SAMPLE_RATE] [--use_soundfile] [--use_autocast] [--custom_output_names CUSTOM_OUTPUT_NAMES]
                       [--mdx_segment_size MDX_SEGMENT_SIZE] [--mdx_overlap MDX_OVERLAP] [--mdx_batch_size MDX_BATCH_SIZE] [--mdx_hop_length MDX_HOP_LENGTH] [--mdx_enable_denoise] [--vr_batch_size VR_BATCH_SIZE]
                       [--vr_window_size VR_WINDOW_SIZE] [--vr_aggression VR_AGGRESSION] [--vr_enable_tta] [--vr_high_end_process] [--vr_enable_post_process]
                       [--vr_post_process_threshold VR_POST_PROCESS_THRESHOLD] [--demucs_segment_size DEMUCS_SEGMENT_SIZE] [--demucs_shifts DEMUCS_SHIFTS] [--demucs_overlap DEMUCS_OVERLAP]
                       [--demucs_segments_enabled DEMUCS_SEGMENTS_ENABLED] [--mdxc_segment_size MDXC_SEGMENT_SIZE] [--mdxc_override_model_segment_size] [--mdxc_overlap MDXC_OVERLAP]
                       [--mdxc_batch_size MDXC_BATCH_SIZE] [--mdxc_pitch_shift MDXC_PITCH_SHIFT]
                       [audio_files ...]

Separate audio file into different stems.

positional arguments:
  audio_files                                            The audio file paths or directory to separate, in any common format.

options:
  -h, --help                                             show this help message and exit

Info and Debugging:
  -v, --version                                          Show the program's version number and exit.
  -d, --debug                                            Enable debug logging, equivalent to --log_level=debug.
  -e, --env_info                                         Print environment information and exit.
  -l, --list_models                                      List all supported models and exit. Use --list_filter to filter/sort the list and --list_limit to show only top N results.
  --log_level LOG_LEVEL                                  Log level, e.g. info, debug, warning (default: info).
  --list_filter LIST_FILTER                              Filter and sort the model list by 'name', 'filename', or any stem e.g. vocals, instrumental, drums
  --list_limit LIST_LIMIT                                Limit the number of models shown
  --list_format {pretty,json}                            Format for listing models: 'pretty' for formatted output, 'json' for raw JSON dump

Separation I/O Params:
  -m MODEL_FILENAME, --model_filename MODEL_FILENAME     Model to use for separation (default: model_bs_roformer_ep_317_sdr_12.9755.yaml). Example: -m 2_HP-UVR.pth
  --output_format OUTPUT_FORMAT                          Output format for separated files, any common format (default: FLAC). Example: --output_format=MP3
  --output_bitrate OUTPUT_BITRATE                        Output bitrate for separated files, any ffmpeg-compatible bitrate (default: None). Example: --output_bitrate=320k
  --output_dir OUTPUT_DIR                                Directory to write output files (default: <current dir>). Example: --output_dir=/app/separated
  --model_file_dir MODEL_FILE_DIR                        Model files directory (default: /tmp/audio-separator-models/). Example: --model_file_dir=/app/models
  --download_model_only                                  Download a single model file only, without performing separation.

Common Separation Parameters:
  --invert_spect                                         Invert secondary stem using spectrogram (default: False). Example: --invert_spect
  --normalization NORMALIZATION                          Max peak amplitude to normalize input and output audio to (default: 0.9). Example: --normalization=0.7
  --amplification AMPLIFICATION                          Min peak amplitude to amplify input and output audio to (default: 0.0). Example: --amplification=0.4
  --single_stem SINGLE_STEM                              Output only single stem, e.g. Instrumental, Vocals, Drums, Bass, Guitar, Piano, Other. Example: --single_stem=Instrumental
  --sample_rate SAMPLE_RATE                              Modify the sample rate of the output audio (default: 44100). Example: --sample_rate=44100
  --use_soundfile                                        Use soundfile to write audio output (default: False). Example: --use_soundfile
  --use_autocast                                         Use PyTorch autocast for faster inference (default: False). Do not use for CPU inference. Example: --use_autocast
  --custom_output_names CUSTOM_OUTPUT_NAMES              Custom names for all output files in JSON format (default: None). Example: --custom_output_names='{"Vocals": "vocals_output", "Drums": "drums_output"}'

MDX Architecture Parameters:
  --mdx_segment_size MDX_SEGMENT_SIZE                    Larger consumes more resources, but may give better results (default: 256). Example: --mdx_segment_size=256
  --mdx_overlap MDX_OVERLAP                              Amount of overlap between prediction windows, 0.001-0.999. Higher is better but slower (default: 0.25). Example: --mdx_overlap=0.25
  --mdx_batch_size MDX_BATCH_SIZE                        Larger consumes more RAM but may process slightly faster (default: 1). Example: --mdx_batch_size=4
  --mdx_hop_length MDX_HOP_LENGTH                        Usually called stride in neural networks, only change if you know what you're doing (default: 1024). Example: --mdx_hop_length=1024
  --mdx_enable_denoise                                   Enable denoising during separation (default: False). Example: --mdx_enable_denoise

VR Architecture Parameters:
  --vr_batch_size VR_BATCH_SIZE                          Number of batches to process at a time. Higher = more RAM, slightly faster processing (default: 1). Example: --vr_batch_size=16
  --vr_window_size VR_WINDOW_SIZE                        Balance quality and speed. 1024 = fast but lower, 320 = slower but better quality. (default: 512). Example: --vr_window_size=320
  --vr_aggression VR_AGGRESSION                          Intensity of primary stem extraction, -100 - 100. Typically, 5 for vocals & instrumentals (default: 5). Example: --vr_aggression=2
  --vr_enable_tta                                        Enable Test-Time-Augmentation; slow but improves quality (default: False). Example: --vr_enable_tta
  --vr_high_end_process                                  Mirror the missing frequency range of the output (default: False). Example: --vr_high_end_process
  --vr_enable_post_process                               Identify leftover artifacts within vocal output; may improve separation for some songs (default: False). Example: --vr_enable_post_process
  --vr_post_process_threshold VR_POST_PROCESS_THRESHOLD  Threshold for post_process feature: 0.1-0.3 (default: 0.2). Example: --vr_post_process_threshold=0.1

Demucs Architecture Parameters:
  --demucs_segment_size DEMUCS_SEGMENT_SIZE              Size of segments into which the audio is split, 1-100. Higher = slower but better quality (default: Default). Example: --demucs_segment_size=256
  --demucs_shifts DEMUCS_SHIFTS                          Number of predictions with random shifts, higher = slower but better quality (default: 2). Example: --demucs_shifts=4
  --demucs_overlap DEMUCS_OVERLAP                        Overlap between prediction windows, 0.001-0.999. Higher = slower but better quality (default: 0.25). Example: --demucs_overlap=0.25
  --demucs_segments_enabled DEMUCS_SEGMENTS_ENABLED      Enable segment-wise processing (default: True). Example: --demucs_segments_enabled=False

MDXC Architecture Parameters:
  --mdxc_segment_size MDXC_SEGMENT_SIZE                  Larger consumes more resources, but may give better results (default: 256). Example: --mdxc_segment_size=256
  --mdxc_override_model_segment_size                     Override model default segment size instead of using the model default value. Example: --mdxc_override_model_segment_size
  --mdxc_overlap MDXC_OVERLAP                            Amount of overlap between prediction windows, 2-50. Higher is better but slower (default: 8). Example: --mdxc_overlap=8
  --mdxc_batch_size MDXC_BATCH_SIZE                      Larger consumes more RAM but may process slightly faster (default: 1). Example: --mdxc_batch_size=4
  --mdxc_pitch_shift MDXC_PITCH_SHIFT                    Shift audio pitch by a number of semitones while processing. May improve output for deep/high vocals. (default: 0). Example: --mdxc_pitch_shift=2
```

### As a Dependency in a Python Project

You can use Audio Separator in your own Python project. Here's a minimal example using the default two stem (Instrumental and Vocals) model:

```python
from audio_separator.separator import Separator

# Initialize the Separator class (with optional configuration properties, below)
separator = Separator()

# Load a machine learning model (if unspecified, defaults to 'model_mel_band_roformer_ep_3005_sdr_11.4360.ckpt')
separator.load_model()

# Perform the separation on specific audio files without reloading the model
output_files = separator.separate('audio1.wav')

print(f"Separation complete! Output file(s): {' '.join(output_files)}")
```

#### Batch processing and processing with multiple models

You can process multiple files without reloading the model to save time and memory.

You only need to load a model when choosing or changing models. See example below:

```python
from audio_separator.separator import Separator

# Initialize the Separator class (with optional configuration properties, below)
separator = Separator()

# Load a model
separator.load_model(model_filename='model_bs_roformer_ep_317_sdr_12.9755.ckpt')

# Separate multiple audio files without reloading the model
output_files = separator.separate(['audio1.wav', 'audio2.wav', 'audio3.wav'])

# Load a different model
separator.load_model(model_filename='UVR_MDXNET_KARA_2.onnx')

# Separate the same files with the new model
output_files = separator.separate(['audio1.wav', 'audio2.wav', 'audio3.wav'])
```

You can also specify the path to a folder containing audio files instead of listing the full paths to each of them:
```python
from audio_separator.separator import Separator

# Initialize the Separator class (with optional configuration properties, below)
separator = Separator()

# Load a model
separator.load_model(model_filename='model_bs_roformer_ep_317_sdr_12.9755.ckpt')

# Separate all audio files located in a folder
output_files = separator.separate('path/to/audio_directory')
```

#### Renaming Stems

You can rename the output files by specifying the desired names. For example:
```python
output_names = {
    "Vocals": "vocals_output",
    "Instrumental": "instrumental_output",
}
output_files = separator.separate('audio1.wav', output_names)
```
In this case, the output file names will be: `vocals_output.wav` and `instrumental_output.wav`.

You can also rename specific stems:

- To rename the Vocals stem:
  ```python
  output_names = {
      "Vocals": "vocals_output",
  }
  output_files = separator.separate('audio1.wav', output_names)
  ```
  > The output files will be named: `vocals_output.wav` and `audio1_(Instrumental)_model_mel_band_roformer_ep_3005_sdr_11.wav`
- To rename the Instrumental stem:
  ```python
  output_names = {
      "Instrumental": "instrumental_output",
  }
  output_files = separator.separate('audio1.wav', output_names)
  ```
  > The output files will be named: `audio1_(Vocals)_model_mel_band_roformer_ep_3005_sdr_11.wav` and `instrumental_output.wav`
- List of stems for Demucs models:
  - htdemucs_6s.yaml
    ```python
    output_names = {
        "Vocals": "vocals_output",
        "Drums": "drums_output",
        "Bass": "bass_output",
        "Other": "other_output",
        "Guitar": "guitar_output",
        "Piano": "piano_output",
    }
    ```
  - Other Demucs models
    ```python
    output_names = {
        "Vocals": "vocals_output",
        "Drums": "drums_output",
        "Bass": "bass_output",
        "Other": "other_output",
    }
    ```

## Parameters for the Separator class

- **`log_level`:** (Optional) Logging level, e.g., INFO, DEBUG, WARNING. `Default: logging.INFO`
- **`log_formatter`:** (Optional) The log format. Default: None, which falls back to '%(asctime)s - %(levelname)s - %(module)s - %(message)s'
- **`model_file_dir`:** (Optional) Directory to cache model files in. `Default: /tmp/audio-separator-models/`
- **`output_dir`:** (Optional) Directory where the separated files will be saved. If not specified, uses the current directory.
- **`output_format`:** (Optional) Format to encode output files, any common format (WAV, MP3, FLAC, M4A, etc.). `Default: WAV`
- **`normalization_threshold`:** (Optional) The amount by which the amplitude of the output audio will be multiplied. `Default: 0.9`
- **`amplification_threshold`:** (Optional) The minimum amplitude level at which the waveform will be amplified. If the peak amplitude of the audio is below this threshold, the waveform will be scaled up to meet it. `Default: 0.0`
- **`output_single_stem`:** (Optional) Output only a single stem, such as 'Instrumental' and 'Vocals'. `Default: None`
- **`invert_using_spec`:** (Optional) Flag to invert using spectrogram. `Default: False`
- **`sample_rate`:** (Optional) Set the sample rate of the output audio. `Default: 44100`
- **`use_soundfile`:** (Optional) Use soundfile for output writing, can solve OOM issues, especially on longer audio.
- **`use_autocast`:** (Optional) Flag to use PyTorch autocast for faster inference. Do not use for CPU inference. `Default: False`
- **`mdx_params`:** (Optional) MDX Architecture Specific Attributes & Defaults. `Default: {"hop_length": 1024, "segment_size": 256, "overlap": 0.25, "batch_size": 1, "enable_denoise": False}`
- **`vr_params`:** (Optional) VR Architecture Specific Attributes & Defaults. `Default: {"batch_size": 1, "window_size": 512, "aggression": 5, "enable_tta": False, "enable_post_process": False, "post_process_threshold": 0.2, "high_end_process": False}`
- **`demucs_params`:** (Optional) Demucs Architecture Specific Attributes & Default
Download .txt
gitextract_b_sdr3ak/

├── .claude/
│   └── plans/
│       └── gha-gpu-runner.plan.md
├── .cursor/
│   ├── commands/
│   │   ├── analyze.md
│   │   ├── clarify.md
│   │   ├── constitution.md
│   │   ├── implement.md
│   │   ├── plan.md
│   │   ├── specify.md
│   │   └── tasks.md
│   └── rules/
│       └── specify-rules.mdc
├── .github/
│   ├── FUNDING.yml
│   ├── ISSUE_TEMPLATE/
│   │   ├── BUG_REPORT.yml
│   │   └── FEATURE_REQUEST.yml
│   ├── prompts/
│   │   ├── analyze.prompt.md
│   │   ├── clarify.prompt.md
│   │   ├── constitution.prompt.md
│   │   ├── implement.prompt.md
│   │   ├── plan.prompt.md
│   │   ├── specify.prompt.md
│   │   └── tasks.prompt.md
│   └── workflows/
│       ├── deploy-to-cloudrun.yml
│       ├── deploy-to-modal.yml
│       ├── github-sponsors.yml
│       ├── publish-to-docker.yml
│       ├── publish-to-pypi.yml
│       ├── run-integration-tests.yaml
│       └── run-unit-tests.yaml
├── .gitignore
├── .specify/
│   ├── memory/
│   │   └── constitution.md
│   ├── scripts/
│   │   └── bash/
│   │       ├── check-prerequisites.sh
│   │       ├── common.sh
│   │       ├── create-new-feature.sh
│   │       ├── setup-plan.sh
│   │       └── update-agent-context.sh
│   └── templates/
│       ├── agent-file-template.md
│       ├── plan-template.md
│       ├── spec-template.md
│       └── tasks-template.md
├── Dockerfile.cloudrun
├── Dockerfile.cpu
├── Dockerfile.cuda11
├── Dockerfile.cuda12
├── Dockerfile.runpod-cuda11
├── Dockerfile.runpod-cuda12
├── LICENSE
├── README.md
├── TODO.md
├── audio_separator/
│   ├── __init__.py
│   ├── ensemble_presets.json
│   ├── model-data.json
│   ├── models-scores.json
│   ├── models.json
│   ├── remote/
│   │   ├── README.md
│   │   ├── __init__.py
│   │   ├── api_client.py
│   │   ├── cli.py
│   │   ├── deploy_cloudrun.py
│   │   ├── deploy_modal.py
│   │   ├── job_store.py
│   │   ├── output_store.py
│   │   └── requirements.txt
│   ├── separator/
│   │   ├── __init__.py
│   │   ├── architectures/
│   │   │   ├── __init__.py
│   │   │   ├── demucs_separator.py
│   │   │   ├── mdx_separator.py
│   │   │   ├── mdxc_separator.py
│   │   │   └── vr_separator.py
│   │   ├── audio_chunking.py
│   │   ├── common_separator.py
│   │   ├── ensembler.py
│   │   ├── roformer/
│   │   │   ├── README.md
│   │   │   ├── __init__.py
│   │   │   ├── bs_roformer_config.py
│   │   │   ├── bs_roformer_validator.py
│   │   │   ├── configuration_normalizer.py
│   │   │   ├── mel_band_roformer_config.py
│   │   │   ├── mel_band_roformer_validator.py
│   │   │   ├── model_configuration.py
│   │   │   ├── model_loading_result.py
│   │   │   ├── parameter_validation_error.py
│   │   │   ├── parameter_validator.py
│   │   │   └── roformer_loader.py
│   │   ├── separator.py
│   │   └── uvr_lib_v5/
│   │       ├── __init__.py
│   │       ├── demucs/
│   │       │   ├── __init__.py
│   │       │   ├── __main__.py
│   │       │   ├── apply.py
│   │       │   ├── demucs.py
│   │       │   ├── filtering.py
│   │       │   ├── hdemucs.py
│   │       │   ├── htdemucs.py
│   │       │   ├── model.py
│   │       │   ├── model_v2.py
│   │       │   ├── pretrained.py
│   │       │   ├── repo.py
│   │       │   ├── spec.py
│   │       │   ├── states.py
│   │       │   ├── tasnet.py
│   │       │   ├── tasnet_v2.py
│   │       │   ├── transformer.py
│   │       │   └── utils.py
│   │       ├── mdxnet.py
│   │       ├── mixer.ckpt
│   │       ├── modules.py
│   │       ├── playsound.py
│   │       ├── pyrb.py
│   │       ├── results.py
│   │       ├── roformer/
│   │       │   ├── attend.py
│   │       │   ├── bs_roformer.py
│   │       │   └── mel_band_roformer.py
│   │       ├── spec_utils.py
│   │       ├── stft.py
│   │       ├── tfc_tdf_v3.py
│   │       └── vr_network/
│   │           ├── __init__.py
│   │           ├── layers.py
│   │           ├── layers_new.py
│   │           ├── model_param_init.py
│   │           ├── modelparams/
│   │           │   ├── 1band_sr16000_hl512.json
│   │           │   ├── 1band_sr32000_hl512.json
│   │           │   ├── 1band_sr33075_hl384.json
│   │           │   ├── 1band_sr44100_hl1024.json
│   │           │   ├── 1band_sr44100_hl256.json
│   │           │   ├── 1band_sr44100_hl512.json
│   │           │   ├── 1band_sr44100_hl512_cut.json
│   │           │   ├── 1band_sr44100_hl512_nf1024.json
│   │           │   ├── 2band_32000.json
│   │           │   ├── 2band_44100_lofi.json
│   │           │   ├── 2band_48000.json
│   │           │   ├── 3band_44100.json
│   │           │   ├── 3band_44100_mid.json
│   │           │   ├── 3band_44100_msb2.json
│   │           │   ├── 4band_44100.json
│   │           │   ├── 4band_44100_mid.json
│   │           │   ├── 4band_44100_msb.json
│   │           │   ├── 4band_44100_msb2.json
│   │           │   ├── 4band_44100_reverse.json
│   │           │   ├── 4band_44100_sw.json
│   │           │   ├── 4band_v2.json
│   │           │   ├── 4band_v2_sn.json
│   │           │   ├── 4band_v3.json
│   │           │   ├── 4band_v3_sn.json
│   │           │   ├── 4band_v4_ms_fullband.json
│   │           │   └── ensemble.json
│   │           ├── nets.py
│   │           └── nets_new.py
│   └── utils/
│       ├── __init__.py
│       └── cli.py
├── cloudbuild.yaml
├── docs/
│   ├── BIT_DEPTH_IMPLEMENTATION_SUMMARY.md
│   ├── BIT_DEPTH_PRESERVATION.md
│   ├── CI-GPU-RUNNERS.md
│   ├── archive/
│   │   └── 2026-03-22-modal-to-gcp-migration-plan.md
│   ├── deton24-audio-separation-info-2026-03-15.md
│   └── deton24-model-mapping-and-ensemble-guide.md
├── environment.yml
├── pyproject.toml
├── pytest.ini
├── scripts/
│   └── download_preset_models.py
├── specs/
│   ├── 001-update-roformer-implementation/
│   │   ├── 001-update-roformer-implementation.md
│   │   ├── contracts/
│   │   │   ├── fallback_loader_interface.py
│   │   │   ├── parameter_validator_interface.py
│   │   │   └── roformer_loader_interface.py
│   │   ├── data-model.md
│   │   ├── plan.md
│   │   ├── post-implementation-issues.md
│   │   ├── quickstart.md
│   │   ├── research.md
│   │   └── tasks.md
│   └── main/
│       └── plan.md
├── tests/
│   ├── README.md
│   ├── TODO.txt
│   ├── contract/
│   │   ├── test_parameter_validator_interface.py
│   │   └── test_roformer_loader_interface.py
│   ├── inputs/
│   │   ├── clocks_piano.flac
│   │   ├── fallen24bit20s.flac
│   │   ├── levee_drums.flac
│   │   ├── mardy20s.flac
│   │   ├── mardy20s_(Instrumental)_mel_band_roformer_karaoke_aufr33_viperx_sdr_10.flac
│   │   ├── mardy20s_(Vocals)_mel_band_roformer_karaoke_aufr33_viperx_sdr_10.flac
│   │   ├── only_time_reverb.flac
│   │   ├── reference/
│   │   │   ├── ref_clocks_piano_bass_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_drums_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_instrumental.flac
│   │   │   ├── ref_clocks_piano_instrumental_karaoke.flac
│   │   │   ├── ref_clocks_piano_other_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_vocals.flac
│   │   │   ├── ref_clocks_piano_vocals_htdemucs_ft.flac
│   │   │   ├── ref_clocks_piano_vocals_karaoke.flac
│   │   │   ├── ref_levee_drums_bass_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_crash_drumsep.flac
│   │   │   ├── ref_levee_drums_drums_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_hh_drumsep.flac
│   │   │   ├── ref_levee_drums_instrumental.flac
│   │   │   ├── ref_levee_drums_instrumental_karaoke.flac
│   │   │   ├── ref_levee_drums_instrumental_preset_vocal_balanced.flac
│   │   │   ├── ref_levee_drums_kick_drumsep.flac
│   │   │   ├── ref_levee_drums_other_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_ride_drumsep.flac
│   │   │   ├── ref_levee_drums_snare_drumsep.flac
│   │   │   ├── ref_levee_drums_toms_drumsep.flac
│   │   │   ├── ref_levee_drums_vocals.flac
│   │   │   ├── ref_levee_drums_vocals_htdemucs_ft.flac
│   │   │   ├── ref_levee_drums_vocals_karaoke.flac
│   │   │   ├── ref_levee_drums_vocals_preset_vocal_balanced.flac
│   │   │   ├── ref_only_time_reverb_instrumental.flac
│   │   │   ├── ref_only_time_reverb_vocals.flac
│   │   │   ├── ref_only_time_reverb_vocals_noreverb.flac
│   │   │   ├── ref_only_time_reverb_vocals_reverb.flac
│   │   │   ├── ref_sing_sing_sing_brass_instrumental.flac
│   │   │   ├── ref_sing_sing_sing_brass_no_woodwinds.flac
│   │   │   ├── ref_sing_sing_sing_brass_vocals.flac
│   │   │   ├── ref_sing_sing_sing_brass_woodwinds.flac
│   │   │   ├── ref_under_pressure_harmonies_backing_vocals.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental_karaoke.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental_preset_karaoke.flac
│   │   │   ├── ref_under_pressure_harmonies_instrumental_preset_vocal_balanced.flac
│   │   │   ├── ref_under_pressure_harmonies_lead_vocals.flac
│   │   │   ├── ref_under_pressure_harmonies_vocals.flac
│   │   │   ├── ref_under_pressure_harmonies_vocals_karaoke.flac
│   │   │   ├── ref_under_pressure_harmonies_vocals_preset_karaoke.flac
│   │   │   └── ref_under_pressure_harmonies_vocals_preset_vocal_balanced.flac
│   │   ├── sing_sing_sing_brass.flac
│   │   └── under_pressure_harmonies.flac
│   ├── integration/
│   │   ├── README.md
│   │   ├── generate_multi_stem_references.py
│   │   ├── generate_reference_images.py
│   │   ├── generate_reference_images_24bit.py
│   │   ├── generate_reference_images_ensemble.py
│   │   ├── requirements.txt
│   │   ├── test_24bit_preservation.py
│   │   ├── test_cli_integration.py
│   │   ├── test_ensemble_integration.py
│   │   ├── test_ensemble_meaningful.py
│   │   ├── test_multi_stem_verification.py
│   │   ├── test_remote_api_integration.py
│   │   ├── test_roformer_audio_quality.py
│   │   ├── test_roformer_backward_compatibility.py
│   │   ├── test_roformer_config_validation.py
│   │   ├── test_roformer_e2e.py
│   │   ├── test_roformer_fallback_mechanism.py
│   │   ├── test_roformer_model_switching.py
│   │   ├── test_roformer_new_parameters.py
│   │   └── test_separator_output_integration.py
│   ├── model-metrics/
│   │   └── test-all-models.py
│   ├── regression/
│   │   ├── test_all_models_stem_verification.py
│   │   └── test_roformer_size_mismatch.py
│   ├── remote/
│   │   └── README.md
│   ├── reproduce_ensemble_bug.py
│   ├── unit/
│   │   ├── test_audio_chunking.py
│   │   ├── test_bit_depth_detection.py
│   │   ├── test_bit_depth_writing.py
│   │   ├── test_cli.py
│   │   ├── test_configuration_normalizer.py
│   │   ├── test_deploy_cloudrun_async.py
│   │   ├── test_ensemble_presets.py
│   │   ├── test_ensembler.py
│   │   ├── test_job_store.py
│   │   ├── test_mdxc_roformer_chunking.py
│   │   ├── test_model_configuration.py
│   │   ├── test_output_store.py
│   │   ├── test_parameter_validator.py
│   │   ├── test_remote_api_client.py
│   │   ├── test_remote_cli.py
│   │   ├── test_separator_chunking.py
│   │   ├── test_separator_detection.py
│   │   ├── test_stem_naming.py
│   │   └── test_stft.py
│   ├── utils.py
│   └── utils_audio_verification.py
└── tools/
    ├── calculate-model-hashes.py
    └── sync-to-github.py
Download .txt
SYMBOL INDEX (1337 symbols across 107 files)

FILE: audio_separator/remote/api_client.py
  class AudioSeparatorAPIClient (line 22) | class AudioSeparatorAPIClient:
    method __init__ (line 25) | def __init__(self, api_url: str, logger: logging.Logger):
    method separate_audio (line 30) | def separate_audio(
    method separate_audio_and_wait (line 172) | def separate_audio_and_wait(
    method get_job_status (line 401) | def get_job_status(self, task_id: str) -> dict:
    method download_file (line 411) | def download_file(self, task_id: str, filename: str, output_path: Opti...
    method download_file_by_hash (line 452) | def download_file_by_hash(self, task_id: str, file_hash: str, filename...
    method _log_server_version_on_error (line 492) | def _log_server_version_on_error(self):
    method list_models (line 500) | def list_models(self, format_type: str = "pretty", filter_by: Optional...
    method get_server_version (line 521) | def get_server_version(self) -> str:

FILE: audio_separator/remote/cli.py
  function main (line 13) | def main():
  function handle_separate_command (line 162) | def handle_separate_command(args, api_client: AudioSeparatorAPIClient, l...
  function handle_status_command (line 232) | def handle_status_command(args, api_client: AudioSeparatorAPIClient, log...
  function handle_models_command (line 259) | def handle_models_command(args, api_client: AudioSeparatorAPIClient, log...
  function handle_download_command (line 273) | def handle_download_command(args, api_client: AudioSeparatorAPIClient, l...
  function poll_for_completion (line 285) | def poll_for_completion(task_id: str, api_client: AudioSeparatorAPIClien...
  function download_files (line 323) | def download_files(task_id: str, files: list, api_client: AudioSeparator...

FILE: audio_separator/remote/deploy_cloudrun.py
  function get_job_store (line 66) | def get_job_store():
  function get_output_store (line 76) | def get_output_store():
  function generate_file_hash (line 86) | def generate_file_hash(filename: str) -> str:
  function download_from_gcs (line 91) | def download_from_gcs(gcs_uri: str) -> tuple[bytes, str]:
  function download_models_from_gcs (line 128) | def download_models_from_gcs():
  function separate_audio_sync (line 168) | def separate_audio_sync(
  class PrettyJSONResponse (line 387) | class PrettyJSONResponse(StarletteResponse):
    method render (line 390) | def render(self, content: typing.Any) -> bytes:
  function separate_audio (line 404) | async def separate_audio(
  function get_job_status (line 562) | async def get_job_status(task_id: str) -> dict:
  function download_file (line 576) | async def download_file(task_id: str, file_hash: str) -> Response:
  function get_available_models (line 610) | async def get_available_models() -> PrettyJSONResponse:
  function get_simplified_models_list (line 620) | async def get_simplified_models_list(filter_sort_by: str = None) -> Plai...
  function list_presets (line 649) | async def list_presets() -> PrettyJSONResponse:
  function health_check (line 659) | async def health_check() -> dict:
  function root (line 671) | async def root() -> dict:
  function startup_event (line 698) | async def startup_event():

FILE: audio_separator/remote/deploy_modal.py
  function generate_file_hash (line 49) | def generate_file_hash(filename: str) -> str:
  class PrettyJSONResponse (line 143) | class PrettyJSONResponse(StarletteResponse):
    method render (line 148) | def render(self, content: typing.Any) -> bytes:
  function separate_audio_function (line 153) | def separate_audio_function(
  function get_job_status_function (line 382) | def get_job_status_function(task_id: str) -> dict:
  function get_file_function (line 401) | def get_file_function(task_id: str, filename: str) -> bytes:
  function get_file_by_hash_function (line 415) | def get_file_by_hash_function(task_id: str, file_hash: str) -> tuple[byt...
  function list_available_models (line 490) | def list_available_models() -> dict:
  function get_simplified_models (line 513) | def get_simplified_models(filter_sort_by: str = None) -> dict:
  function separate_audio (line 540) | async def separate_audio(
  function get_job_status (line 694) | async def get_job_status(task_id: str) -> dict:
  function download_file (line 706) | async def download_file(task_id: str, file_hash: str) -> Response:
  function get_available_models (line 738) | async def get_available_models() -> PrettyJSONResponse:
  function get_simplified_models_list (line 749) | async def get_simplified_models_list(filter_sort_by: str = None) -> Plai...
  function health_check (line 781) | async def health_check() -> dict:
  function root (line 789) | async def root() -> dict:
  function api (line 830) | def api() -> FastAPI:

FILE: audio_separator/remote/job_store.py
  class FirestoreJobStore (line 14) | class FirestoreJobStore:
    method __init__ (line 20) | def __init__(self, project: str = "nomadkaraoke"):
    method set (line 27) | def set(self, task_id: str, data: dict) -> None:
    method get (line 34) | def get(self, task_id: str) -> Optional[dict]:
    method update (line 41) | def update(self, task_id: str, fields: dict) -> None:
    method delete (line 46) | def delete(self, task_id: str) -> None:
    method __contains__ (line 50) | def __contains__(self, task_id: str) -> bool:
    method cleanup_old_jobs (line 55) | def cleanup_old_jobs(self, max_age_seconds: int = 3600) -> int:

FILE: audio_separator/remote/output_store.py
  class GCSOutputStore (line 11) | class GCSOutputStore:
    method __init__ (line 14) | def __init__(self, bucket_name: str = "nomadkaraoke-audio-separator-ou...
    method upload_task_outputs (line 20) | def upload_task_outputs(self, task_id: str, local_dir: str) -> list[str]:
    method get_file_bytes (line 37) | def get_file_bytes(self, task_id: str, filename: str) -> bytes:
    method download_file (line 43) | def download_file(self, task_id: str, filename: str, local_path: str) ...
    method delete_task_outputs (line 50) | def delete_task_outputs(self, task_id: str) -> int:

FILE: audio_separator/separator/architectures/demucs_separator.py
  class DemucsSeparator (line 26) | class DemucsSeparator(CommonSeparator):
    method __init__ (line 32) | def __init__(self, common_config, arch_config):
    method separate (line 83) | def separate(self, audio_file_path, custom_output_names=None):
    method demix_demucs (line 162) | def demix_demucs(self, mix):

FILE: audio_separator/separator/architectures/mdx_separator.py
  class MDXSeparator (line 16) | class MDXSeparator(CommonSeparator):
    method __init__ (line 22) | def __init__(self, common_config, arch_config):
    method load_model (line 108) | def load_model(self):
    method separate (line 135) | def separate(self, audio_file_path, custom_output_names=None):
    method initialize_model_settings (line 205) | def initialize_model_settings(self):
    method initialize_mix (line 230) | def initialize_mix(self, mix, is_ckpt=False):
    method demix (line 293) | def demix(self, mix, is_match_mix=False):
    method run_model (line 414) | def run_model(self, mix, is_match_mix=False):

FILE: audio_separator/separator/architectures/mdxc_separator.py
  class MDXCSeparator (line 16) | class MDXCSeparator(CommonSeparator):
    method __init__ (line 22) | def __init__(self, common_config, arch_config):
    method load_model (line 76) | def load_model(self):
    method separate (line 118) | def separate(self, audio_file_path, custom_output_names=None):
    method pitch_fix (line 230) | def pitch_fix(self, source, sr_pitched, orig_mix):
    method overlap_add (line 246) | def overlap_add(self, result, x, weights, start, length):
    method demix (line 257) | def demix(self, mix: np.ndarray) -> dict:

FILE: audio_separator/separator/architectures/vr_separator.py
  class VRSeparator (line 21) | class VRSeparator(CommonSeparator):
    method __init__ (line 27) | def __init__(self, common_config, arch_config: dict):
    method separate (line 113) | def separate(self, audio_file_path, custom_output_names=None):
    method loading_mix (line 255) | def loading_mix(self):
    method inference_vr (line 295) | def inference_vr(self, X_spec, device, aggressiveness):
    method spec_to_wav (line 368) | def spec_to_wav(self, spec):
  function rerun_mp3 (line 379) | def rerun_mp3(audio_file, sample_rate=44100):

FILE: audio_separator/separator/audio_chunking.py
  class AudioChunker (line 9) | class AudioChunker:
    method __init__ (line 25) | def __init__(self, chunk_duration_seconds: float, logger: logging.Logg...
    method split_audio (line 36) | def split_audio(self, input_path: str, output_dir: str) -> List[str]:
    method merge_chunks (line 87) | def merge_chunks(self, chunk_paths: List[str], output_path: str) -> str:
    method should_chunk (line 131) | def should_chunk(self, audio_duration_seconds: float) -> bool:

FILE: audio_separator/separator/common_separator.py
  class CommonSeparator (line 15) | class CommonSeparator:
    method __init__ (line 57) | def __init__(self, config):
    method secondary_stem (line 148) | def secondary_stem(self, primary_stem: str):
    method separate (line 159) | def separate(self, audio_file_path):
    method final_process (line 165) | def final_process(self, stem_path, source, stem_name):
    method cached_sources_clear (line 174) | def cached_sources_clear(self):
    method cached_source_callback (line 184) | def cached_source_callback(self, model_architecture, model_name=None):
    method cached_model_source_holder (line 210) | def cached_model_source_holder(self, model_architecture, sources, mode...
    method prepare_mix (line 217) | def prepare_mix(self, mix):
    method write_audio (line 284) | def write_audio(self, stem_path: str, stem_source):
    method write_audio_pydub (line 303) | def write_audio_pydub(self, stem_path: str, stem_source):
    method write_audio_soundfile (line 391) | def write_audio_soundfile(self, stem_path: str, stem_source):
    method clear_gpu_cache (line 453) | def clear_gpu_cache(self):
    method clear_file_specific_paths (line 466) | def clear_file_specific_paths(self):
    method sanitize_filename (line 481) | def sanitize_filename(self, filename):
    method get_stem_output_path (line 490) | def get_stem_output_path(self, stem_name, custom_output_names):
    method _detect_roformer_model (line 509) | def _detect_roformer_model(self):
    method _initialize_roformer_loader (line 533) | def _initialize_roformer_loader(self):
    method get_roformer_loading_stats (line 545) | def get_roformer_loading_stats(self):
    method validate_roformer_config (line 556) | def validate_roformer_config(self, config, model_type):

FILE: audio_separator/separator/ensembler.py
  class Ensembler (line 6) | class Ensembler:
    method __init__ (line 7) | def __init__(self, logger, algorithm="avg_wave", weights=None):
    method ensemble (line 12) | def ensemble(self, waveforms):
    method _lambda_max (line 76) | def _lambda_max(self, arr, axis=None, key=None, keepdims=False):
    method _lambda_min (line 87) | def _lambda_min(self, arr, axis=None, key=None, keepdims=False):
    method _stft (line 98) | def _stft(self, wave, nfft=2048, hl=1024):
    method _istft (line 111) | def _istft(self, spec, hl=1024, length=None, original_channels=None):
    method _ensemble_fft (line 126) | def _ensemble_fft(self, waveforms, weights):
    method _ensemble_uvr (line 153) | def _ensemble_uvr(self, waveforms, uvr_algorithm):

FILE: audio_separator/separator/roformer/bs_roformer_config.py
  class BSRoformerConfig (line 12) | class BSRoformerConfig(ModelConfiguration):
    method __post_init__ (line 26) | def __post_init__(self):
    method _validate_bs_roformer_parameters (line 31) | def _validate_bs_roformer_parameters(self):
    method get_total_frequency_bins (line 48) | def get_total_frequency_bins(self) -> int:
    method validate_against_stft_config (line 52) | def validate_against_stft_config(self, n_fft: int) -> bool:
    method get_stft_compatibility_info (line 67) | def get_stft_compatibility_info(self, n_fft: int) -> Dict[str, Any]:
    method get_model_type (line 88) | def get_model_type(self) -> RoformerType:
    method get_bs_roformer_kwargs (line 92) | def get_bs_roformer_kwargs(self) -> Dict[str, Any]:
    method from_model_config (line 107) | def from_model_config(cls, config_dict: Dict[str, Any]) -> 'BSRoformer...
    method suggest_stft_n_fft (line 125) | def suggest_stft_n_fft(self) -> int:
    method get_parameter_summary (line 136) | def get_parameter_summary(self) -> str:
    method __repr__ (line 142) | def __repr__(self) -> str:

FILE: audio_separator/separator/roformer/bs_roformer_validator.py
  class BSRoformerValidator (line 10) | class BSRoformerValidator(ParameterValidator):
    method validate_freqs_per_bands (line 23) | def validate_freqs_per_bands(self, config: Dict[str, Any]) -> List[Val...
    method validate_stft_compatibility (line 106) | def validate_stft_compatibility(self, config: Dict[str, Any]) -> List[...
    method validate_mask_estimator_config (line 141) | def validate_mask_estimator_config(self, config: Dict[str, Any]) -> Li...
    method validate_all (line 178) | def validate_all(self, config: Dict[str, Any], model_type: str = "bs_r...
    method get_parameter_defaults (line 199) | def get_parameter_defaults(self, model_type: str = "bs_roformer") -> D...

FILE: audio_separator/separator/roformer/configuration_normalizer.py
  class ConfigurationNormalizer (line 18) | class ConfigurationNormalizer:
    method __init__ (line 26) | def __init__(self):
    method normalize_config (line 32) | def normalize_config(self,
    method _normalize_structure (line 73) | def _normalize_structure(self, config: Dict[str, Any], model_type: str...
    method _normalize_parameter_names (line 98) | def _normalize_parameter_names(self, config: Dict[str, Any]) -> Dict[s...
    method _normalize_parameter_values (line 143) | def _normalize_parameter_values(self, config: Dict[str, Any], model_ty...
    method _normalize_single_value (line 155) | def _normalize_single_value(self, key: str, value: Any, model_type: st...
    method _apply_defaults (line 213) | def _apply_defaults(self, config: Dict[str, Any], model_type: str) -> ...
    method _validate_config (line 225) | def _validate_config(self, config: Dict[str, Any], model_type: str) ->...
    method detect_model_type (line 237) | def detect_model_type(self, config: Dict[str, Any]) -> Optional[str]:
    method normalize_from_file_path (line 269) | def normalize_from_file_path(self,

FILE: audio_separator/separator/roformer/mel_band_roformer_config.py
  class MelBandRoformerConfig (line 12) | class MelBandRoformerConfig(ModelConfiguration):
    method __post_init__ (line 28) | def __post_init__(self):
    method _validate_mel_band_roformer_parameters (line 33) | def _validate_mel_band_roformer_parameters(self):
    method get_effective_fmax (line 57) | def get_effective_fmax(self) -> float:
    method get_frequency_range (line 61) | def get_frequency_range(self) -> tuple[float, float]:
    method validate_sample_rate (line 65) | def validate_sample_rate(self, sample_rate: int) -> bool:
    method get_mel_scale_info (line 82) | def get_mel_scale_info(self) -> Dict[str, Any]:
    method _estimate_bands_per_octave (line 99) | def _estimate_bands_per_octave(self) -> float:
    method get_model_type (line 110) | def get_model_type(self) -> RoformerType:
    method get_mel_band_roformer_kwargs (line 114) | def get_mel_band_roformer_kwargs(self) -> Dict[str, Any]:
    method from_model_config (line 132) | def from_model_config(cls, config_dict: Dict[str, Any]) -> 'MelBandRof...
    method suggest_optimal_bands (line 150) | def suggest_optimal_bands(self, target_frequency_resolution: float = 5...
    method get_parameter_summary (line 167) | def get_parameter_summary(self) -> str:
    method __repr__ (line 173) | def __repr__(self) -> str:

FILE: audio_separator/separator/roformer/mel_band_roformer_validator.py
  class MelBandRoformerValidator (line 10) | class MelBandRoformerValidator(ParameterValidator):
    method validate_num_bands (line 33) | def validate_num_bands(self, config: Dict[str, Any]) -> List[Validatio...
    method validate_sample_rate_compatibility (line 104) | def validate_sample_rate_compatibility(self, config: Dict[str, Any]) -...
    method validate_mel_scale_config (line 162) | def validate_mel_scale_config(self, config: Dict[str, Any]) -> List[Va...
    method validate_all (line 247) | def validate_all(self, config: Dict[str, Any], model_type: str = "mel_...
    method get_parameter_defaults (line 268) | def get_parameter_defaults(self, model_type: str = "mel_band_roformer"...

FILE: audio_separator/separator/roformer/model_configuration.py
  class RoformerType (line 11) | class RoformerType(Enum):
  class ModelConfiguration (line 18) | class ModelConfiguration:
    method __post_init__ (line 59) | def __post_init__(self):
    method _validate_basic_parameters (line 64) | def _validate_basic_parameters(self):
    method _validate_parameter_ranges (line 78) | def _validate_parameter_ranges(self):
    method to_dict (line 95) | def to_dict(self) -> Dict[str, Any]:
    method from_dict (line 105) | def from_dict(cls, config_dict: Dict[str, Any]) -> 'ModelConfiguration':
    method get_transformer_kwargs (line 123) | def get_transformer_kwargs(self) -> Dict[str, Any]:
    method has_new_parameters (line 137) | def has_new_parameters(self) -> bool:
    method get_parameter_summary (line 147) | def get_parameter_summary(self) -> str:
    method __repr__ (line 155) | def __repr__(self) -> str:

FILE: audio_separator/separator/roformer/model_loading_result.py
  class ImplementationVersion (line 11) | class ImplementationVersion(Enum):
  class ModelLoadingResult (line 19) | class ModelLoadingResult:
    method __post_init__ (line 39) | def __post_init__(self):
    method add_warning (line 50) | def add_warning(self, warning: str):
    method add_model_info (line 55) | def add_model_info(self, key: str, value: Any):
    method get_summary (line 59) | def get_summary(self) -> str:
    method is_fallback_used (line 72) | def is_fallback_used(self) -> bool:
    method is_new_implementation_used (line 76) | def is_new_implementation_used(self) -> bool:
    method has_warnings (line 80) | def has_warnings(self) -> bool:
    method get_model_parameters_count (line 84) | def get_model_parameters_count(self) -> Optional[int]:
    method get_model_size_mb (line 98) | def get_model_size_mb(self) -> Optional[float]:
    method to_dict (line 107) | def to_dict(self) -> Dict[str, Any]:
    method success_result (line 122) | def success_result(
    method failure_result (line 150) | def failure_result(
    method fallback_success_result (line 175) | def fallback_success_result(
    method __str__ (line 204) | def __str__(self) -> str:
    method __repr__ (line 208) | def __repr__(self) -> str:

FILE: audio_separator/separator/roformer/parameter_validation_error.py
  class ParameterValidationError (line 9) | class ParameterValidationError(Exception):
    method __init__ (line 17) | def __init__(
    method _create_error_message (line 45) | def _create_error_message(self) -> str:
    method get_error_details (line 61) | def get_error_details(self) -> dict:
    method missing_parameter (line 74) | def missing_parameter(cls, parameter_name: str, parameter_type: str, c...
    method wrong_type (line 95) | def wrong_type(cls, parameter_name: str, expected_type: str, actual_va...
    method out_of_range (line 117) | def out_of_range(cls, parameter_name: str, valid_range: str, actual_va...
    method incompatible_parameters (line 139) | def incompatible_parameters(cls, parameter_names: list, issue_descript...
    method invalid_normalization (line 162) | def invalid_normalization(cls, norm_value: Any, supported_norms: list,...
    method __repr__ (line 183) | def __repr__(self) -> str:

FILE: audio_separator/separator/roformer/parameter_validator.py
  class ValidationSeverity (line 36) | class ValidationSeverity(Enum):
  class ValidationIssue (line 42) | class ValidationIssue:
  class ParameterValidatorInterface (line 50) | class ParameterValidatorInterface:
  class ParameterValidator (line 57) | class ParameterValidator(ParameterValidatorInterface):
    method validate_required_parameters (line 115) | def validate_required_parameters(self, config: Dict[str, Any], model_t...
    method validate_parameter_types (line 144) | def validate_parameter_types(self, config: Dict[str, Any]) -> List[Val...
    method validate_parameter_ranges (line 173) | def validate_parameter_ranges(self, config: Dict[str, Any]) -> List[Va...
    method validate_parameter_compatibility (line 202) | def validate_parameter_compatibility(self, config: Dict[str, Any]) -> ...
    method validate_normalization_config (line 260) | def validate_normalization_config(self, norm_config: Any) -> List[Vali...
    method get_parameter_defaults (line 297) | def get_parameter_defaults(self, model_type: str) -> Dict[str, Any]:
    method apply_parameter_defaults (line 339) | def apply_parameter_defaults(self, config: Dict[str, Any], model_type:...
    method _is_correct_type (line 356) | def _is_correct_type(self, value: Any, expected_type: Union[type, Tupl...
    method _get_type_name (line 362) | def _get_type_name(self, expected_type: Union[type, Tuple[type, ...]])...
    method _get_expected_type_description (line 368) | def _get_expected_type_description(self, param_name: str) -> str:
    method validate_all (line 374) | def validate_all(self, config: Dict[str, Any], model_type: str) -> Lis...
    method validate_and_raise (line 398) | def validate_and_raise(self, config: Dict[str, Any], model_type: str) ...

FILE: audio_separator/separator/roformer/roformer_loader.py
  class RoformerLoader (line 13) | class RoformerLoader:
    method __init__ (line 16) | def __init__(self):
    method load_model (line 23) | def load_model(self,
    method validate_configuration (line 68) | def validate_configuration(self, config: Dict[str, Any], model_type: s...
    method _load_with_new_implementation (line 82) | def _load_with_new_implementation(self,
    method _create_bs_roformer (line 123) | def _create_bs_roformer(self, config: Dict[str, Any]):
    method _create_mel_band_roformer (line 153) | def _create_mel_band_roformer(self, config: Dict[str, Any]):
    method _load_with_legacy_implementation (line 197) | def _load_with_legacy_implementation(self,
    method get_loading_stats (line 237) | def get_loading_stats(self) -> Dict[str, int]:
    method reset_loading_stats (line 240) | def reset_loading_stats(self) -> None:
    method detect_model_type (line 246) | def detect_model_type(self, model_path: str) -> str:
    method get_default_configuration (line 257) | def get_default_configuration(self, model_type: str) -> Dict[str, Any]:

FILE: audio_separator/separator/separator.py
  class Separator (line 52) | class Separator:
    method __init__ (line 108) | def __init__(
    method _load_ensemble_preset (line 265) | def _load_ensemble_preset(self, preset_name):
    method list_ensemble_presets (line 304) | def list_ensemble_presets(self):
    method setup_accelerated_inferencing_device (line 317) | def setup_accelerated_inferencing_device(self):
    method get_system_info (line 326) | def get_system_info(self):
    method check_ffmpeg_installed (line 344) | def check_ffmpeg_installed(self):
    method log_onnxruntime_packages (line 359) | def log_onnxruntime_packages(self):
    method setup_torch_device (line 377) | def setup_torch_device(self, system_info):
    method configure_cuda (line 404) | def configure_cuda(self, ort_providers):
    method configure_mps (line 416) | def configure_mps(self, ort_providers):
    method configure_dml (line 431) | def configure_dml(self, ort_providers):
    method get_package_distribution (line 446) | def get_package_distribution(self, package_name):
    method get_model_hash (line 456) | def get_model_hash(self, model_path):
    method download_file_if_not_exists (line 491) | def download_file_if_not_exists(self, url, output_path):
    method list_supported_model_files (line 515) | def list_supported_model_files(self):
    method print_uvr_vip_message (line 685) | def print_uvr_vip_message(self):
    method download_model_files (line 693) | def download_model_files(self, model_filename):
    method load_model_data_from_yaml (line 758) | def load_model_data_from_yaml(self, yaml_config_filename):
    method load_model_data_using_hash (line 779) | def load_model_data_using_hash(self, model_path):
    method load_model (line 830) | def load_model(self, model_filename="model_bs_roformer_ep_317_sdr_12.9...
    method separate (line 935) | def separate(self, audio_file_path, custom_output_names=None):
    method _separate_file (line 991) | def _separate_file(self, audio_file_path, custom_output_names=None):
    method _process_with_chunking (line 1047) | def _process_with_chunking(self, audio_file_path, custom_output_names=...
    method download_model_and_data (line 1158) | def download_model_and_data(self, model_filename):
    method get_simplified_model_list (line 1178) | def get_simplified_model_list(self, filter_sort_by: Optional[str] = No...
    method _separate_ensemble (line 1242) | def _separate_ensemble(self, audio_file_path, custom_output_names=None):

FILE: audio_separator/separator/uvr_lib_v5/demucs/__main__.py
  class SavedState (line 30) | class SavedState:
  function main (line 37) | def main():

FILE: audio_separator/separator/uvr_lib_v5/demucs/apply.py
  class BagOfModels (line 28) | class BagOfModels(nn.Module):
    method __init__ (line 29) | def __init__(self, models: tp.List[Model], weights: tp.Optional[tp.Lis...
    method forward (line 67) | def forward(self, x):
  class TensorChunk (line 71) | class TensorChunk:
    method __init__ (line 72) | def __init__(self, tensor, offset=0, length=None):
    method shape (line 92) | def shape(self):
    method padded (line 97) | def padded(self, target_length):
  function tensor_chunk (line 116) | def tensor_chunk(tensor_or_chunk):
  function apply_model (line 124) | def apply_model(model, mix, shifts=1, split=True, overlap=0.25, transiti...
  function demucs_segments (line 263) | def demucs_segments(demucs_segment, demucs_model):

FILE: audio_separator/separator/uvr_lib_v5/demucs/demucs.py
  class BLSTM (line 19) | class BLSTM(nn.Module):
    method __init__ (line 26) | def __init__(self, dim, layers=1, max_steps=None, skip=False):
    method forward (line 34) | def forward(self, x):
  function rescale_conv (line 70) | def rescale_conv(conv, reference):
  function rescale_module (line 79) | def rescale_module(module, reference):
  class LayerScale (line 85) | class LayerScale(nn.Module):
    method __init__ (line 90) | def __init__(self, channels: int, init: float = 0):
    method forward (line 95) | def forward(self, x):
  class DConv (line 99) | class DConv(nn.Module):
    method __init__ (line 107) | def __init__(self, channels: int, compress: float = 4, depth: int = 2,...
    method forward (line 165) | def forward(self, x):
  class LocalState (line 171) | class LocalState(nn.Module):
    method __init__ (line 178) | def __init__(self, channels: int, heads: int = 4, nfreqs: int = 0, nde...
    method forward (line 197) | def forward(self, x):
  class Demucs (line 234) | class Demucs(nn.Module):
    method __init__ (line 236) | def __init__(
    method valid_length (line 382) | def valid_length(self, length):
    method forward (line 405) | def forward(self, mix):
    method load_state_dict (line 444) | def load_state_dict(self, state, strict=True):

FILE: audio_separator/separator/uvr_lib_v5/demucs/filtering.py
  function atan2 (line 8) | def atan2(y, x):
  function _norm (line 36) | def _norm(x: torch.Tensor) -> torch.Tensor:
  function _mul_add (line 49) | def _mul_add(a: torch.Tensor, b: torch.Tensor, out: Optional[torch.Tenso...
  function _mul (line 68) | def _mul(a: torch.Tensor, b: torch.Tensor, out: Optional[torch.Tensor] =...
  function _inv (line 85) | def _inv(z: torch.Tensor, out: Optional[torch.Tensor] = None) -> torch.T...
  function _conj (line 97) | def _conj(z, out: Optional[torch.Tensor] = None) -> torch.Tensor:
  function _invert (line 108) | def _invert(M: torch.Tensor, out: Optional[torch.Tensor] = None) -> torc...
  function expectation_maximization (line 153) | def expectation_maximization(y: torch.Tensor, x: torch.Tensor, iteration...
  function wiener (line 312) | def wiener(targets_spectrograms: torch.Tensor, mix_stft: torch.Tensor, i...
  function _covariance (line 434) | def _covariance(y_j):

FILE: audio_separator/separator/uvr_lib_v5/demucs/hdemucs.py
  function pad1d (line 21) | def pad1d(x: torch.Tensor, paddings: tp.Tuple[int, int], mode: str = "co...
  class ScaledEmbedding (line 41) | class ScaledEmbedding(nn.Module):
    method __init__ (line 47) | def __init__(self, num_embeddings: int, embedding_dim: int, scale: flo...
    method weight (line 59) | def weight(self):
    method forward (line 62) | def forward(self, x):
  class HEncLayer (line 67) | class HEncLayer(nn.Module):
    method __init__ (line 68) | def __init__(self, chin, chout, kernel_size=8, stride=4, norm_groups=1...
    method forward (line 119) | def forward(self, x, inject=None):
  class MultiWrap (line 156) | class MultiWrap(nn.Module):
    method __init__ (line 166) | def __init__(self, layer, split_ratios):
    method forward (line 192) | def forward(self, x, skip=None, length=None):
  class HDecLayer (line 252) | class HDecLayer(nn.Module):
    method __init__ (line 253) | def __init__(
    method forward (line 299) | def forward(self, x, skip, length):
  class HDemucs (line 333) | class HDemucs(nn.Module):
    method __init__ (line 362) | def __init__(
    method _spec (line 574) | def _spec(self, x):
    method _ispec (line 601) | def _ispec(self, z, length=None, scale=0):
    method _magnitude (line 620) | def _magnitude(self, z):
    method _mask (line 631) | def _mask(self, z, m):
    method _wiener (line 648) | def _wiener(self, mag_out, mix_stft, niters):
    method forward (line 674) | def forward(self, mix):

FILE: audio_separator/separator/uvr_lib_v5/demucs/htdemucs.py
  class HTDemucs (line 27) | class HTDemucs(nn.Module):
    method __init__ (line 56) | def __init__(
    method _spec (line 383) | def _spec(self, x):
    method _ispec (line 405) | def _ispec(self, z, length=None, scale=0):
    method _magnitude (line 415) | def _magnitude(self, z):
    method _mask (line 426) | def _mask(self, z, m):
    method _wiener (line 443) | def _wiener(self, mag_out, mix_stft, niters):
    method valid_length (line 469) | def valid_length(self, length: int):
    method forward (line 483) | def forward(self, mix):

FILE: audio_separator/separator/uvr_lib_v5/demucs/model.py
  class BLSTM (line 15) | class BLSTM(nn.Module):
    method __init__ (line 16) | def __init__(self, dim, layers=1):
    method forward (line 21) | def forward(self, x):
  function rescale_conv (line 29) | def rescale_conv(conv, reference):
  function rescale_module (line 37) | def rescale_module(module, reference):
  function upsample (line 43) | def upsample(x, stride):
  function downsample (line 54) | def downsample(x, stride):
  class Demucs (line 61) | class Demucs(nn.Module):
    method __init__ (line 63) | def __init__(
    method valid_length (line 154) | def valid_length(self, length):
    method forward (line 182) | def forward(self, mix):

FILE: audio_separator/separator/uvr_lib_v5/demucs/model_v2.py
  class BLSTM (line 16) | class BLSTM(nn.Module):
    method __init__ (line 17) | def __init__(self, dim, layers=1):
    method forward (line 22) | def forward(self, x):
  function rescale_conv (line 30) | def rescale_conv(conv, reference):
  function rescale_module (line 38) | def rescale_module(module, reference):
  function auto_load_demucs_model_v2 (line 44) | def auto_load_demucs_model_v2(sources, demucs_model_name):
  class Demucs (line 61) | class Demucs(nn.Module):
    method __init__ (line 63) | def __init__(
    method valid_length (line 165) | def valid_length(self, length):
    method forward (line 191) | def forward(self, mix):

FILE: audio_separator/separator/uvr_lib_v5/demucs/pretrained.py
  function demucs_unittest (line 34) | def demucs_unittest():
  function add_model_flags (line 39) | def add_model_flags(parser):
  function _parse_remote_files (line 46) | def _parse_remote_files(remote_file_list) -> tp.Dict[str, str]:
  function get_model (line 62) | def get_model(name: str, repo: tp.Optional[Path] = None):
  function get_model_from_args (line 84) | def get_model_from_args(args):
  function get_url (line 107) | def get_url(name):
  function is_pretrained (line 112) | def is_pretrained(name):
  function load_pretrained (line 116) | def load_pretrained(name):
  function _load_state (line 135) | def _load_state(name, model, quantizer=None):
  function demucs_unittest (line 143) | def demucs_unittest(pretrained=True):
  function demucs (line 150) | def demucs(pretrained=True, extra=False, quantized=False, hq=False, chan...
  function tasnet (line 172) | def tasnet(pretrained=True, extra=False):

FILE: audio_separator/separator/uvr_lib_v5/demucs/repo.py
  class ModelLoadingError (line 25) | class ModelLoadingError(RuntimeError):
  function check_checksum (line 29) | def check_checksum(path: Path, checksum: str):
  class ModelOnlyRepo (line 42) | class ModelOnlyRepo:
    method has_model (line 45) | def has_model(self, sig: str) -> bool:
    method get_model (line 48) | def get_model(self, sig: str) -> Model:
  class RemoteRepo (line 52) | class RemoteRepo(ModelOnlyRepo):
    method __init__ (line 53) | def __init__(self, models: tp.Dict[str, str]):
    method has_model (line 56) | def has_model(self, sig: str) -> bool:
    method get_model (line 59) | def get_model(self, sig: str) -> Model:
  class LocalRepo (line 68) | class LocalRepo(ModelOnlyRepo):
    method __init__ (line 69) | def __init__(self, root: Path):
    method scan (line 73) | def scan(self):
    method has_model (line 88) | def has_model(self, sig: str) -> bool:
    method get_model (line 91) | def get_model(self, sig: str) -> Model:
  class BagOnlyRepo (line 101) | class BagOnlyRepo:
    method __init__ (line 106) | def __init__(self, root: Path, model_repo: ModelOnlyRepo):
    method scan (line 111) | def scan(self):
    method has_model (line 117) | def has_model(self, name: str) -> bool:
    method get_model (line 120) | def get_model(self, name: str) -> BagOfModels:
  class AnyModelRepo (line 133) | class AnyModelRepo:
    method __init__ (line 134) | def __init__(self, model_repo: ModelOnlyRepo, bag_repo: BagOnlyRepo):
    method has_model (line 138) | def has_model(self, name_or_sig: str) -> bool:
    method get_model (line 141) | def get_model(self, name_or_sig: str) -> AnyModel:

FILE: audio_separator/separator/uvr_lib_v5/demucs/spec.py
  function spectro (line 11) | def spectro(x, n_fft=512, hop_length=None, pad=0):
  function ispectro (line 25) | def ispectro(z, hop_length=None, length=None, pad=0):

FILE: audio_separator/separator/uvr_lib_v5/demucs/states.py
  function get_quantizer (line 22) | def get_quantizer(model, args, optimizer=None):
  function load_model (line 34) | def load_model(path_or_package, strict=False):
  function get_state (line 67) | def get_state(model, quantizer, half=False):
  function set_state (line 80) | def set_state(model, state, quantizer=None):
  function save_with_checksum (line 92) | def save_with_checksum(content, path):
  function copy_state (line 103) | def copy_state(state):
  function swap_state (line 108) | def swap_state(model, state):
  function capture_init (line 125) | def capture_init(init):

FILE: audio_separator/separator/uvr_lib_v5/demucs/tasnet.py
  function overlap_and_add (line 44) | def overlap_and_add(signal, frame_step):
  class ConvTasNet (line 66) | class ConvTasNet(nn.Module):
    method __init__ (line 68) | def __init__(self, N=256, L=20, B=256, H=512, P=3, X=8, R=4, C=4, audi...
    method valid_length (line 100) | def valid_length(self, length):
    method forward (line 103) | def forward(self, mixture):
  class Encoder (line 121) | class Encoder(nn.Module):
    method __init__ (line 124) | def __init__(self, L, N, audio_channels):
    method forward (line 132) | def forward(self, mixture):
  class Decoder (line 143) | class Decoder(nn.Module):
    method __init__ (line 144) | def __init__(self, N, L, audio_channels):
    method forward (line 152) | def forward(self, mixture_w, est_mask):
  class TemporalConvNet (line 171) | class TemporalConvNet(nn.Module):
    method __init__ (line 172) | def __init__(self, N, B, H, P, X, R, C, norm_type="gLN", causal=False,...
    method forward (line 210) | def forward(self, mixture_w):
  class TemporalBlock (line 230) | class TemporalBlock(nn.Module):
    method __init__ (line 231) | def __init__(self, in_channels, out_channels, kernel_size, stride, pad...
    method forward (line 242) | def forward(self, x):
  class DepthwiseSeparableConv (line 256) | class DepthwiseSeparableConv(nn.Module):
    method __init__ (line 257) | def __init__(self, in_channels, out_channels, kernel_size, stride, pad...
    method forward (line 274) | def forward(self, x):
  class Chomp1d (line 284) | class Chomp1d(nn.Module):
    method __init__ (line 287) | def __init__(self, chomp_size):
    method forward (line 291) | def forward(self, x):
  function chose_norm (line 301) | def chose_norm(norm_type, channel_size):
  class ChannelwiseLayerNorm (line 318) | class ChannelwiseLayerNorm(nn.Module):
    method __init__ (line 321) | def __init__(self, channel_size):
    method reset_parameters (line 327) | def reset_parameters(self):
    method forward (line 331) | def forward(self, y):
  class GlobalLayerNorm (line 344) | class GlobalLayerNorm(nn.Module):
    method __init__ (line 347) | def __init__(self, channel_size):
    method reset_parameters (line 353) | def reset_parameters(self):
    method forward (line 357) | def forward(self, y):

FILE: audio_separator/separator/uvr_lib_v5/demucs/tasnet_v2.py
  function overlap_and_add (line 44) | def overlap_and_add(signal, frame_step):
  class ConvTasNet (line 66) | class ConvTasNet(nn.Module):
    method __init__ (line 68) | def __init__(self, sources, N=256, L=20, B=256, H=512, P=3, X=8, R=4, ...
    method valid_length (line 103) | def valid_length(self, length):
    method forward (line 106) | def forward(self, mixture):
  class Encoder (line 124) | class Encoder(nn.Module):
    method __init__ (line 127) | def __init__(self, L, N, audio_channels):
    method forward (line 135) | def forward(self, mixture):
  class Decoder (line 146) | class Decoder(nn.Module):
    method __init__ (line 147) | def __init__(self, N, L, audio_channels):
    method forward (line 155) | def forward(self, mixture_w, est_mask):
  class TemporalConvNet (line 174) | class TemporalConvNet(nn.Module):
    method __init__ (line 175) | def __init__(self, N, B, H, P, X, R, C, norm_type="gLN", causal=False,...
    method forward (line 213) | def forward(self, mixture_w):
  class TemporalBlock (line 233) | class TemporalBlock(nn.Module):
    method __init__ (line 234) | def __init__(self, in_channels, out_channels, kernel_size, stride, pad...
    method forward (line 245) | def forward(self, x):
  class DepthwiseSeparableConv (line 259) | class DepthwiseSeparableConv(nn.Module):
    method __init__ (line 260) | def __init__(self, in_channels, out_channels, kernel_size, stride, pad...
    method forward (line 277) | def forward(self, x):
  class Chomp1d (line 287) | class Chomp1d(nn.Module):
    method __init__ (line 290) | def __init__(self, chomp_size):
    method forward (line 294) | def forward(self, x):
  function chose_norm (line 304) | def chose_norm(norm_type, channel_size):
  class ChannelwiseLayerNorm (line 321) | class ChannelwiseLayerNorm(nn.Module):
    method __init__ (line 324) | def __init__(self, channel_size):
    method reset_parameters (line 330) | def reset_parameters(self):
    method forward (line 334) | def forward(self, y):
  class GlobalLayerNorm (line 347) | class GlobalLayerNorm(nn.Module):
    method __init__ (line 350) | def __init__(self, channel_size):
    method reset_parameters (line 356) | def reset_parameters(self):
    method forward (line 360) | def forward(self, y):

FILE: audio_separator/separator/uvr_lib_v5/demucs/transformer.py
  function create_sin_embedding (line 19) | def create_sin_embedding(length: int, dim: int, shift: int = 0, device="...
  function create_2d_sin_embedding (line 29) | def create_2d_sin_embedding(d_model, height, width, device="cpu", max_pe...
  function create_sin_embedding_cape (line 52) | def create_sin_embedding_cape(
  function get_causal_mask (line 85) | def get_causal_mask(length):
  function get_elementary_mask (line 90) | def get_elementary_mask(T1, T2, mask_type, sparse_attn_window, global_wi...
  function get_mask (line 129) | def get_mask(T1, T2, mask_type, sparse_attn_window, global_window, mask_...
  class ScaledEmbedding (line 146) | class ScaledEmbedding(nn.Module):
    method __init__ (line 147) | def __init__(self, num_embeddings: int, embedding_dim: int, scale: flo...
    method weight (line 154) | def weight(self):
    method forward (line 157) | def forward(self, x):
  class LayerScale (line 161) | class LayerScale(nn.Module):
    method __init__ (line 166) | def __init__(self, channels: int, init: float = 0, channel_last=False):
    method forward (line 176) | def forward(self, x):
  class MyGroupNorm (line 183) | class MyGroupNorm(nn.GroupNorm):
    method __init__ (line 184) | def __init__(self, *args, **kwargs):
    method forward (line 187) | def forward(self, x):
  class MyTransformerEncoderLayer (line 196) | class MyTransformerEncoderLayer(nn.TransformerEncoderLayer):
    method __init__ (line 197) | def __init__(
    method forward (line 257) | def forward(self, src, src_mask=None, src_key_padding_mask=None):
  class CrossTransformerEncoderLayer (line 285) | class CrossTransformerEncoderLayer(nn.Module):
    method __init__ (line 286) | def __init__(
    method forward (line 364) | def forward(self, q, k, mask=None):
    method _ca_block (line 394) | def _ca_block(self, q, k, attn_mask=None):
    method _ff_block (line 399) | def _ff_block(self, x):
    method _get_activation_fn (line 403) | def _get_activation_fn(self, activation):
  class CrossTransformerEncoder (line 415) | class CrossTransformerEncoder(nn.Module):
    method __init__ (line 416) | def __init__(
    method forward (line 529) | def forward(self, x, xt):
    method _get_pos_embedding (line 557) | def _get_pos_embedding(self, T, B, C, device):
    method make_optim_group (line 584) | def make_optim_group(self):
  class MultiheadAttention (line 594) | class MultiheadAttention(nn.Module):
    method __init__ (line 595) | def __init__(self, embed_dim, num_heads, dropout=0.0, bias=True, add_b...
    method forward (line 608) | def forward(self, query, key, value, key_padding_mask=None, need_weigh...
  function scaled_query_key_softmax (line 639) | def scaled_query_key_softmax(q, k, att_mask):
  function scaled_dot_product_attention (line 648) | def scaled_dot_product_attention(q, k, v, att_mask, dropout):
  function _compute_buckets (line 655) | def _compute_buckets(x, R):
  function dynamic_sparse_attention (line 663) | def dynamic_sparse_attention(query, key, value, sparsity, infer_sparsity...

FILE: audio_separator/separator/uvr_lib_v5/demucs/utils.py
  function unfold (line 35) | def unfold(a, kernel_size, stride):
  function center_trim (line 53) | def center_trim(tensor: torch.Tensor, reference: tp.Union[torch.Tensor, ...
  function pull_metric (line 72) | def pull_metric(history: tp.List[dict], name: str):
  function EMA (line 82) | def EMA(beta: float = 1):
  function sizeof_fmt (line 104) | def sizeof_fmt(num: float, suffix: str = "B"):
  function temp_filenames (line 117) | def temp_filenames(count: int, delete=True):
  function average_metric (line 129) | def average_metric(metric, count=1.0):
  function free_port (line 139) | def free_port(host="", low=20000, high=40000):
  function sizeof_fmt (line 157) | def sizeof_fmt(num, suffix="B"):
  function human_seconds (line 169) | def human_seconds(seconds, display=".2f"):
  class TensorChunk (line 185) | class TensorChunk:
    method __init__ (line 186) | def __init__(self, tensor, offset=0, length=None):
    method shape (line 202) | def shape(self):
    method padded (line 207) | def padded(self, target_length):
  function tensor_chunk (line 226) | def tensor_chunk(tensor_or_chunk):
  function apply_model_v1 (line 234) | def apply_model_v1(model, mix, shifts=None, split=False, progress=False,...
  function apply_model_v2 (line 295) | def apply_model_v2(model, mix, shifts=None, split=False, overlap=0.25, t...
  function temp_filenames (line 374) | def temp_filenames(count, delete=True):
  function get_quantizer (line 386) | def get_quantizer(model, args, optimizer=None):
  function load_model (line 397) | def load_model(path, strict=False):
  function get_state (line 425) | def get_state(model, quantizer):
  function set_state (line 436) | def set_state(model, quantizer, state):
  function save_state (line 447) | def save_state(state, path):
  function save_model (line 456) | def save_model(model, quantizer, training_args, path):
  function capture_init (line 467) | def capture_init(init):
  class DummyPoolExecutor (line 476) | class DummyPoolExecutor:
    class DummyResult (line 477) | class DummyResult:
      method __init__ (line 478) | def __init__(self, func, *args, **kwargs):
      method result (line 483) | def result(self):
    method __init__ (line 486) | def __init__(self, workers=0):
    method submit (line 489) | def submit(self, func, *args, **kwargs):
    method __enter__ (line 492) | def __enter__(self):
    method __exit__ (line 495) | def __exit__(self, exc_type, exc_value, exc_tb):

FILE: audio_separator/separator/uvr_lib_v5/mdxnet.py
  class AbstractMDXNet (line 8) | class AbstractMDXNet(LightningModule):
    method __init__ (line 9) | def __init__(self, target_name, lr, optimizer, dim_c, dim_f, dim_t, n_...
    method get_optimizer (line 23) | def get_optimizer(self):
  class ConvTDFNet (line 30) | class ConvTDFNet(AbstractMDXNet):
    method __init__ (line 31) | def __init__(self, target_name, lr, optimizer, dim_c, dim_f, dim_t, n_...
    method forward (line 97) | def forward(self, x):
  class Mixer (line 122) | class Mixer(nn.Module):
    method __init__ (line 123) | def __init__(self, device, mixer_path):
    method forward (line 133) | def forward(self, x):

FILE: audio_separator/separator/uvr_lib_v5/modules.py
  class TFC (line 5) | class TFC(nn.Module):
    method __init__ (line 6) | def __init__(self, c, l, k, norm):
    method forward (line 19) | def forward(self, x):
  class DenseTFC (line 25) | class DenseTFC(nn.Module):
    method __init__ (line 26) | def __init__(self, c, l, k, norm):
    method forward (line 39) | def forward(self, x):
  class TFC_TDF (line 45) | class TFC_TDF(nn.Module):
    method __init__ (line 46) | def __init__(self, c, l, f, k, bn, dense=False, bias=True, norm=nn.Bat...
    method forward (line 71) | def forward(self, x):

FILE: audio_separator/separator/uvr_lib_v5/playsound.py
  class PlaysoundException (line 4) | class PlaysoundException(Exception):
  function _canonicalizePath (line 7) | def _canonicalizePath(path):
  function _playsoundWin (line 19) | def _playsoundWin(sound, block = True):
  function _handlePathOSX (line 65) | def _handlePathOSX(sound):
  function _playsoundOSX (line 88) | def _playsoundOSX(sound, block = True):
  function _playsoundNix (line 128) | def _playsoundNix(sound, block = True):
  function _playsoundAnotherPython (line 177) | def _playsoundAnotherPython(otherPython, sound, block = True, macOS = Fa...
  function play (line 240) | def play(audio_filepath):

FILE: audio_separator/separator/uvr_lib_v5/pyrb.py
  function __rubberband (line 23) | def __rubberband(y, sr, **kwargs):
  function time_stretch (line 68) | def time_stretch(y, sr, rate, rbargs=None):
  function pitch_shift (line 82) | def pitch_shift(y, sr, n_steps, rbargs=None):

FILE: audio_separator/separator/uvr_lib_v5/results.py
  class Result (line 25) | class Result:
    method __init__ (line 26) | def __init__(
  function pcm16 (line 41) | def pcm16(file: str) -> Result:
  function pcm24 (line 44) | def pcm24(file: str) -> Result:
  function save_audiofile (line 47) | def save_audiofile(file: str, wav_set="PCM_16") -> Result:

FILE: audio_separator/separator/uvr_lib_v5/roformer/attend.py
  function exists (line 18) | def exists(val):
  function once (line 22) | def once(fn):
  class Attend (line 41) | class Attend(nn.Module):
    method __init__ (line 42) | def __init__(self, dropout=0.0, flash=False):
    method flash_attn (line 66) | def flash_attn(self, q, k, v):
    method forward (line 83) | def forward(self, q, k, v):

FILE: audio_separator/separator/uvr_lib_v5/roformer/bs_roformer.py
  function exists (line 21) | def exists(val):
  function default (line 25) | def default(v, d):
  function pack_one (line 29) | def pack_one(t, pattern):
  function unpack_one (line 33) | def unpack_one(t, ps, pattern):
  function l2norm (line 40) | def l2norm(t):
  class RMSNorm (line 44) | class RMSNorm(Module):
    method __init__ (line 45) | def __init__(self, dim):
    method forward (line 50) | def forward(self, x):
  class FeedForward (line 58) | class FeedForward(Module):
    method __init__ (line 59) | def __init__(self, dim, mult=4, dropout=0.0):
    method forward (line 64) | def forward(self, x):
  class Attention (line 68) | class Attention(Module):
    method __init__ (line 69) | def __init__(self, dim, heads=8, dim_head=64, dropout=0.0, rotary_embe...
    method forward (line 86) | def forward(self, x):
  class LinearAttention (line 104) | class LinearAttention(Module):
    method __init__ (line 110) | def __init__(self, *, dim, dim_head=32, heads=8, scale=8, flash=False,...
    method forward (line 123) | def forward(self, x):
  class Transformer (line 136) | class Transformer(Module):
    method __init__ (line 137) | def __init__(self, *, dim, depth, dim_head=64, heads=8, attn_dropout=0...
    method forward (line 151) | def forward(self, x):
  class BandSplit (line 163) | class BandSplit(Module):
    method __init__ (line 165) | def __init__(self, dim, dim_inputs: Tuple[int, ...]):
    method forward (line 175) | def forward(self, x):
  function MLP (line 186) | def MLP(dim_in, dim_out, dim_hidden=None, depth=1, activation=nn.Tanh):
  class MaskEstimator (line 205) | class MaskEstimator(Module):
    method __init__ (line 207) | def __init__(self, dim, dim_inputs: Tuple[int, ...], depth, mlp_expans...
    method forward (line 220) | def forward(self, x):
  class BSRoformer (line 300) | class BSRoformer(Module):
    method __init__ (line 303) | def __init__(
    method forward (line 418) | def forward(self, raw_audio, target=None, return_loss_breakdown=False):

FILE: audio_separator/separator/uvr_lib_v5/roformer/mel_band_roformer.py
  function exists (line 20) | def exists(val):
  function default (line 24) | def default(v, d):
  function pack_one (line 28) | def pack_one(t, pattern):
  function unpack_one (line 32) | def unpack_one(t, ps, pattern):
  function pad_at_dim (line 36) | def pad_at_dim(t, pad, dim=-1, value=0.0):
  class RMSNorm (line 42) | class RMSNorm(Module):
    method __init__ (line 43) | def __init__(self, dim):
    method forward (line 48) | def forward(self, x):
  class FeedForward (line 53) | class FeedForward(Module):
    method __init__ (line 54) | def __init__(self, dim, mult=4, dropout=0.0):
    method forward (line 59) | def forward(self, x):
  class Attention (line 63) | class Attention(Module):
    method __init__ (line 64) | def __init__(self, dim, heads=8, dim_head=64, dropout=0.0, rotary_embe...
    method forward (line 81) | def forward(self, x):
  class Transformer (line 99) | class Transformer(Module):
    method __init__ (line 100) | def __init__(self, *, dim, depth, dim_head=64, heads=8, attn_dropout=0...
    method forward (line 113) | def forward(self, x):
  class BandSplit (line 122) | class BandSplit(Module):
    method __init__ (line 124) | def __init__(self, dim, dim_inputs: Tuple[int, ...]):
    method forward (line 134) | def forward(self, x):
  function MLP (line 145) | def MLP(dim_in, dim_out, dim_hidden=None, depth=1, activation=nn.Tanh):
  class MaskEstimator (line 164) | class MaskEstimator(Module):
    method __init__ (line 166) | def __init__(self, dim, dim_inputs: Tuple[int, ...], depth, mlp_expans...
    method forward (line 179) | def forward(self, x):
  class MelBandRoformer (line 191) | class MelBandRoformer(Module):
    method __init__ (line 194) | def __init__(
    method forward (line 327) | def forward(self, raw_audio, target=None, return_loss_breakdown=False):

FILE: audio_separator/separator/uvr_lib_v5/spec_utils.py
  function crop_center (line 50) | def crop_center(h1, h2):
  function preprocess (line 74) | def preprocess(X_spec):
  function make_padding (line 85) | def make_padding(width, cropsize, offset):
  function normalize (line 99) | def normalize(wave, max_peak=1.0, min_peak=None):
  function auto_transpose (line 118) | def auto_transpose(audio_array: np.ndarray):
  function write_array_to_mem (line 135) | def write_array_to_mem(audio_data, subtype):
  function spectrogram_to_image (line 145) | def spectrogram_to_image(spec, mode="magnitude"):
  function reduce_vocal_aggressively (line 169) | def reduce_vocal_aggressively(X, y, softmask):
  function merge_artifacts (line 180) | def merge_artifacts(y_mask, thres=0.01, min_range=64, fade_size=32):
  function align_wave_head_and_tail (line 226) | def align_wave_head_and_tail(a, b):
  function convert_channels (line 232) | def convert_channels(spec, mp, band):
  function combine_spectrograms (line 250) | def combine_spectrograms(specs, mp, is_v51_model=False):
  function wave_to_spectrogram (line 282) | def wave_to_spectrogram(wave, hop_length, n_fft, mp, band, is_v51_model=...
  function spectrogram_to_wave (line 315) | def spectrogram_to_wave(spec, hop_length=1024, mp={}, band=0, is_v51_mod...
  function cmb_spectrogram_to_wave (line 341) | def cmb_spectrogram_to_wave(spec_m, mp, extra_bins_h=None, extra_bins=No...
  function get_lp_filter_mask (line 398) | def get_lp_filter_mask(n_bins, bin_start, bin_stop):
  function get_hp_filter_mask (line 404) | def get_hp_filter_mask(n_bins, bin_start, bin_stop):
  function fft_lp_filter (line 410) | def fft_lp_filter(spec, bin_start, bin_stop):
  function fft_hp_filter (line 421) | def fft_hp_filter(spec, bin_start, bin_stop):
  function spectrogram_to_wave_old (line 432) | def spectrogram_to_wave_old(spec, hop_length=1024):
  function wave_to_spectrogram_old (line 446) | def wave_to_spectrogram_old(wave, hop_length, n_fft):
  function mirroring (line 458) | def mirroring(a, spec_m, input_high_end, mp):
  function adjust_aggr (line 472) | def adjust_aggr(mask, is_non_accom_stem, aggressiveness):
  function stft (line 495) | def stft(wave, nfft, hl):
  function istft (line 505) | def istft(spec, hl):
  function spec_effects (line 515) | def spec_effects(wave, algorithm="Default", value=None):
  function spectrogram_to_wave_no_mp (line 538) | def spectrogram_to_wave_no_mp(spec, n_fft=2048, hop_length=1024):
  function wave_to_spectrogram_no_mp (line 547) | def wave_to_spectrogram_no_mp(wave):
  function invert_audio (line 557) | def invert_audio(specs, invert_p=True):
  function invert_stem (line 575) | def invert_stem(mixture, stem):
  function ensembling (line 583) | def ensembling(a, inputs, is_wavs=False):
  function ensemble_for_align (line 611) | def ensemble_for_align(waves):
  function ensemble_inputs (line 625) | def ensemble_inputs(audio_input, algorithm, is_normalization, wav_type_s...
  function to_shape (line 654) | def to_shape(x, target_shape):
  function to_shape_minimize (line 664) | def to_shape_minimize(x: np.ndarray, target_shape):
  function detect_leading_silence (line 675) | def detect_leading_silence(audio, sr, silence_threshold=0.007, frame_len...
  function adjust_leading_silence (line 699) | def adjust_leading_silence(target_audio, reference_audio, silence_thresh...
  function match_array_shapes (line 752) | def match_array_shapes(array_1: np.ndarray, array_2: np.ndarray, is_swap...
  function match_mono_array_shapes (line 772) | def match_mono_array_shapes(array_1: np.ndarray, array_2: np.ndarray):
  function change_pitch_semitones (line 783) | def change_pitch_semitones(y, sr, semitone_shift):
  function augment_audio (line 793) | def augment_audio(export_path, audio_file, rate, is_normalization, wav_t...
  function average_audio (line 821) | def average_audio(audio):
  function average_dual_sources (line 847) | def average_dual_sources(wav_1, wav_2, value):
  function reshape_sources (line 859) | def reshape_sources(wav_1: np.ndarray, wav_2: np.ndarray):
  function reshape_sources_ref (line 874) | def reshape_sources_ref(wav_1_shape, wav_2: np.ndarray):
  function combine_arrarys (line 882) | def combine_arrarys(audio_sources, is_swap=False):
  function combine_audio (line 892) | def combine_audio(paths: list, audio_file_base=None, wav_type_set="FLOAT...
  function reduce_mix_bv (line 900) | def reduce_mix_bv(inst_source, voc_source, reduction_rate=0.9):
  function organize_inputs (line 909) | def organize_inputs(inputs):
  function check_if_phase_inverted (line 925) | def check_if_phase_inverted(wav1, wav2, is_mono=False):
  function align_audio (line 937) | def align_audio(
  function phase_shift_hilbert (line 1114) | def phase_shift_hilbert(signal, degree):
  function get_phase_shifted_tracks (line 1119) | def get_phase_shifted_tracks(track, phase_shift):
  function time_correction (line 1134) | def time_correction(mix: np.ndarray, instrumental: np.ndarray, seconds_l...
  function ensemble_wav (line 1245) | def ensemble_wav(waveforms, split_size=240):
  function ensemble_wav_min (line 1269) | def ensemble_wav_min(waveforms):
  function align_audio_test (line 1283) | def align_audio_test(wav1, wav2, sr1=44100):
  function load_audio (line 1314) | def load_audio(audio_file):
  function rerun_mp3 (line 1323) | def rerun_mp3(audio_file):

FILE: audio_separator/separator/uvr_lib_v5/stft.py
  class STFT (line 4) | class STFT:
    method __init__ (line 11) | def __init__(self, logger, n_fft, hop_length, dim_f, device):
    method __call__ (line 20) | def __call__(self, input_tensor):
    method pad_frequency_dimension (line 58) | def pad_frequency_dimension(self, input_tensor, batch_dimensions, chan...
    method calculate_inverse_dimensions (line 70) | def calculate_inverse_dimensions(self, input_tensor):
    method prepare_for_istft (line 80) | def prepare_for_istft(self, padded_tensor, batch_dimensions, channel_d...
    method inverse (line 99) | def inverse(self, input_tensor):

FILE: audio_separator/separator/uvr_lib_v5/tfc_tdf_v3.py
  class STFT (line 5) | class STFT:
    method __init__ (line 6) | def __init__(self, n_fft, hop_length, dim_f, device):
    method __call__ (line 13) | def __call__(self, x):
    method inverse (line 32) | def inverse(self, x):
  function get_norm (line 55) | def get_norm(norm_type):
  function get_act (line 72) | def get_act(act_type):
  class Upscale (line 84) | class Upscale(nn.Module):
    method __init__ (line 85) | def __init__(self, in_c, out_c, scale, norm, act):
    method forward (line 93) | def forward(self, x):
  class Downscale (line 97) | class Downscale(nn.Module):
    method __init__ (line 98) | def __init__(self, in_c, out_c, scale, norm, act):
    method forward (line 106) | def forward(self, x):
  class TFC_TDF (line 110) | class TFC_TDF(nn.Module):
    method __init__ (line 111) | def __init__(self, in_c, c, l, f, bn, norm, act):
    method forward (line 141) | def forward(self, x):
  class TFC_TDF_net (line 151) | class TFC_TDF_net(nn.Module):
    method __init__ (line 152) | def __init__(self, config, device):
    method cac2cws (line 216) | def cac2cws(self, x):
    method cws2cac (line 223) | def cws2cac(self, x):
    method forward (line 230) | def forward(self, x):

FILE: audio_separator/separator/uvr_lib_v5/vr_network/layers.py
  class Conv2DBNActiv (line 8) | class Conv2DBNActiv(nn.Module):
    method __init__ (line 29) | def __init__(self, nin, nout, ksize=3, stride=1, pad=1, dilation=1, ac...
    method __call__ (line 36) | def __call__(self, input_tensor):
  class SeperableConv2DBNActiv (line 42) | class SeperableConv2DBNActiv(nn.Module):
    method __init__ (line 66) | def __init__(self, nin, nout, ksize=3, stride=1, pad=1, dilation=1, ac...
    method __call__ (line 95) | def __call__(self, input_tensor):
  class Encoder (line 102) | class Encoder(nn.Module):
    method __init__ (line 122) | def __init__(self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.Leaky...
    method __call__ (line 135) | def __call__(self, input_tensor):
  class Decoder (line 148) | class Decoder(nn.Module):
    method __init__ (line 168) | def __init__(self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.ReLU,...
    method __call__ (line 177) | def __call__(self, input_tensor, skip=None):
  class ASPPModule (line 196) | class ASPPModule(nn.Module):
    method __init__ (line 213) | def __init__(self, nn_architecture, nin, nout, dilations=(4, 8, 16), a...
    method forward (line 260) | def forward(self, input_tensor):

FILE: audio_separator/separator/uvr_lib_v5/vr_network/layers_new.py
  class Conv2DBNActiv (line 8) | class Conv2DBNActiv(nn.Module):
    method __init__ (line 16) | def __init__(self, nin, nout, ksize=3, stride=1, pad=1, dilation=1, ac...
    method __call__ (line 22) | def __call__(self, input_tensor):
  class Encoder (line 27) | class Encoder(nn.Module):
    method __init__ (line 34) | def __init__(self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.Leaky...
    method __call__ (line 42) | def __call__(self, input_tensor):
  class Decoder (line 50) | class Decoder(nn.Module):
    method __init__ (line 57) | def __init__(self, nin, nout, ksize=3, stride=1, pad=1, activ=nn.ReLU,...
    method __call__ (line 64) | def __call__(self, input_tensor, skip=None):
  class ASPPModule (line 81) | class ASPPModule(nn.Module):
    method __init__ (line 88) | def __init__(self, nin, nout, dilations=(4, 8, 12), activ=nn.ReLU, dro...
    method forward (line 100) | def forward(self, input_tensor):
  class LSTMModule (line 118) | class LSTMModule(nn.Module):
    method __init__ (line 125) | def __init__(self, nin_conv, nin_lstm, nout_lstm):
    method forward (line 136) | def forward(self, input_tensor):

FILE: audio_separator/separator/uvr_lib_v5/vr_network/model_param_init.py
  function int_keys (line 15) | def int_keys(d):
  class ModelParameters (line 44) | class ModelParameters(object):
    method __init__ (line 52) | def __init__(self, config_path=""):

FILE: audio_separator/separator/uvr_lib_v5/vr_network/nets.py
  class BaseASPPNet (line 8) | class BaseASPPNet(nn.Module):
    method __init__ (line 18) | def __init__(self, nn_architecture, nin, ch, dilations=(4, 8, 16)):
    method __call__ (line 42) | def __call__(self, input_tensor):
  function determine_model_capacity (line 67) | def determine_model_capacity(n_fft_bins, nn_architecture):
  class CascadedASPPNet (line 96) | class CascadedASPPNet(nn.Module):
    method __init__ (line 105) | def __init__(self, n_fft, model_capacity_data, nn_architecture):
    method forward (line 129) | def forward(self, input_tensor):
    method predict_mask (line 166) | def predict_mask(self, input_tensor):

FILE: audio_separator/separator/uvr_lib_v5/vr_network/nets_new.py
  class BaseNet (line 7) | class BaseNet(nn.Module):
    method __init__ (line 15) | def __init__(self, nin, nout, nin_lstm, nout_lstm, dilations=((4, 2), ...
    method __call__ (line 36) | def __call__(self, input_tensor):
  class CascadedNet (line 58) | class CascadedNet(nn.Module):
    method __init__ (line 65) | def __init__(self, n_fft, nn_arch_size=51000, nout=32, nout_lstm=128):
    method forward (line 91) | def forward(self, input_tensor):
    method predict_mask (line 140) | def predict_mask(self, input_tensor):
    method predict (line 151) | def predict(self, input_tensor):

FILE: audio_separator/utils/cli.py
  function main (line 10) | def main():

FILE: specs/001-update-roformer-implementation/contracts/fallback_loader_interface.py
  class ModelLoadingResult (line 11) | class ModelLoadingResult:
  class FallbackLoaderInterface (line 23) | class FallbackLoaderInterface(ABC):
    method try_new_implementation (line 32) | def try_new_implementation(self,
    method try_legacy_implementation (line 50) | def try_legacy_implementation(self,

FILE: specs/001-update-roformer-implementation/contracts/parameter_validator_interface.py
  class ValidationSeverity (line 12) | class ValidationSeverity(Enum):
  class ValidationIssue (line 20) | class ValidationIssue:
  class ParameterValidatorInterface (line 30) | class ParameterValidatorInterface(ABC):
    method validate_required_parameters (line 34) | def validate_required_parameters(self, config: Dict[str, Any], model_t...
    method validate_parameter_types (line 48) | def validate_parameter_types(self, config: Dict[str, Any]) -> List[Val...
    method validate_parameter_ranges (line 61) | def validate_parameter_ranges(self, config: Dict[str, Any]) -> List[Va...
    method validate_parameter_compatibility (line 74) | def validate_parameter_compatibility(self, config: Dict[str, Any]) -> ...
    method validate_normalization_config (line 87) | def validate_normalization_config(self, norm_config: Any) -> List[Vali...
    method get_parameter_defaults (line 100) | def get_parameter_defaults(self, model_type: str) -> Dict[str, Any]:
    method apply_parameter_defaults (line 113) | def apply_parameter_defaults(self, config: Dict[str, Any], model_type:...
  class BSRoformerValidatorInterface (line 127) | class BSRoformerValidatorInterface(ABC):
    method validate_freqs_per_bands (line 131) | def validate_freqs_per_bands(self, freqs_per_bands: Tuple[int, ...], s...
    method calculate_expected_freqs (line 145) | def calculate_expected_freqs(self, stft_n_fft: int) -> int:
  class MelBandRoformerValidatorInterface (line 158) | class MelBandRoformerValidatorInterface(ABC):
    method validate_num_bands (line 162) | def validate_num_bands(self, num_bands: int, sample_rate: int) -> List...
    method validate_sample_rate (line 176) | def validate_sample_rate(self, sample_rate: int) -> List[ValidationIss...
  class ConfigurationNormalizerInterface (line 189) | class ConfigurationNormalizerInterface(ABC):
    method normalize_config_format (line 193) | def normalize_config_format(self, raw_config: Any) -> Dict[str, Any]:
    method map_legacy_parameters (line 206) | def map_legacy_parameters(self, config: Dict[str, Any]) -> Dict[str, A...
    method extract_nested_config (line 219) | def extract_nested_config(self, config: Any, path: str) -> Any:

FILE: specs/001-update-roformer-implementation/contracts/roformer_loader_interface.py
  class RoformerType (line 12) | class RoformerType(Enum):
  class ImplementationVersion (line 18) | class ImplementationVersion(Enum):
  class ModelLoadingResult (line 26) | class ModelLoadingResult:
    method __post_init__ (line 34) | def __post_init__(self):
  class ModelConfiguration (line 40) | class ModelConfiguration:
  class ParameterValidationError (line 72) | class ParameterValidationError(Exception):
    method __init__ (line 75) | def __init__(self, parameter_name: str, expected_type: str, actual_val...
  class RoformerLoaderInterface (line 89) | class RoformerLoaderInterface(ABC):
    method load_model (line 93) | def load_model(self, model_path: str, config: Optional[Dict[str, Any]]...
    method validate_configuration (line 111) | def validate_configuration(self, config: ModelConfiguration, model_typ...
    method detect_model_type (line 125) | def detect_model_type(self, model_path: str) -> RoformerType:
    method get_default_configuration (line 141) | def get_default_configuration(self, model_type: RoformerType) -> Model...
  class RoformerModelInterface (line 154) | class RoformerModelInterface(ABC):
    method separate_audio (line 158) | def separate_audio(self, audio_data: Any, **kwargs) -> Any:
    method get_model_info (line 172) | def get_model_info(self) -> Dict[str, Any]:
    method cleanup (line 182) | def cleanup(self) -> None:
  class FallbackLoaderInterface (line 187) | class FallbackLoaderInterface(ABC):
    method try_new_implementation (line 191) | def try_new_implementation(self, model_path: str, config: ModelConfigu...
    method try_old_implementation (line 205) | def try_old_implementation(self, model_path: str, config: ModelConfigu...
    method should_fallback (line 219) | def should_fallback(self, error: Exception) -> bool:

FILE: tests/contract/test_parameter_validator_interface.py
  class TestParameterValidatorInterface (line 38) | class TestParameterValidatorInterface:
    method test_validate_required_parameters_contract (line 41) | def test_validate_required_parameters_contract(self):
    method test_validate_parameter_types_contract (line 74) | def test_validate_parameter_types_contract(self):
    method test_validate_parameter_ranges_contract (line 98) | def test_validate_parameter_ranges_contract(self):
    method test_validate_parameter_compatibility_contract (line 122) | def test_validate_parameter_compatibility_contract(self):
    method test_validate_normalization_config_contract (line 145) | def test_validate_normalization_config_contract(self):
    method test_get_parameter_defaults_contract (line 172) | def test_get_parameter_defaults_contract(self):
    method test_apply_parameter_defaults_contract (line 193) | def test_apply_parameter_defaults_contract(self):
  class TestBSRoformerValidatorInterface (line 217) | class TestBSRoformerValidatorInterface:
    method test_validate_freqs_per_bands_contract (line 220) | def test_validate_freqs_per_bands_contract(self):
    method test_calculate_expected_freqs_contract (line 244) | def test_calculate_expected_freqs_contract(self):
  class TestMelBandRoformerValidatorInterface (line 257) | class TestMelBandRoformerValidatorInterface:
    method test_validate_num_bands_contract (line 260) | def test_validate_num_bands_contract(self):
    method test_validate_sample_rate_contract (line 286) | def test_validate_sample_rate_contract(self):
  class TestConfigurationNormalizerInterface (line 298) | class TestConfigurationNormalizerInterface:
    method test_normalize_config_format_contract (line 301) | def test_normalize_config_format_contract(self):
    method test_map_legacy_parameters_contract (line 317) | def test_map_legacy_parameters_contract(self):
    method test_extract_nested_config_contract (line 332) | def test_extract_nested_config_contract(self):

FILE: tests/contract/test_roformer_loader_interface.py
  class TestRoformerLoaderInterface (line 39) | class TestRoformerLoaderInterface:
    method test_load_model_success_contract (line 42) | def test_load_model_success_contract(self):
    method test_load_model_failure_contract (line 70) | def test_load_model_failure_contract(self):
    method test_load_model_parameter_validation_error (line 94) | def test_load_model_parameter_validation_error(self):
    method test_validate_configuration_contract (line 116) | def test_validate_configuration_contract(self):
    method test_detect_model_type_contract (line 137) | def test_detect_model_type_contract(self):
    method test_get_default_configuration_contract (line 157) | def test_get_default_configuration_contract(self):

FILE: tests/integration/generate_multi_stem_references.py
  function run_model (line 40) | def run_model(model, input_file, output_dir):
  function find_stem_file (line 47) | def find_stem_file(output_files, stem_name, output_dir):
  function main (line 60) | def main():

FILE: tests/integration/generate_reference_images.py
  function main (line 18) | def main():

FILE: tests/integration/generate_reference_images_24bit.py
  function main (line 29) | def main():

FILE: tests/integration/generate_reference_images_ensemble.py
  function main (line 32) | def main():

FILE: tests/integration/test_24bit_preservation.py
  function fixture_input_file_24bit (line 21) | def fixture_input_file_24bit():
  function fixture_reference_dir (line 27) | def fixture_reference_dir():
  function fixture_cleanup_output_files (line 33) | def fixture_cleanup_output_files():
  function get_audio_bit_depth (line 45) | def get_audio_bit_depth(file_path):
  function run_separation_test_24bit (line 60) | def run_separation_test_24bit(model, audio_path, expected_files):
  function validate_audio_output (line 97) | def validate_audio_output(output_file, reference_dir, waveform_threshold...
  function test_24bit_model_separation (line 188) | def test_24bit_model_separation(model, expected_files, input_file_24bit,...

FILE: tests/integration/test_cli_integration.py
  function fixture_input_file (line 12) | def fixture_input_file():
  function fixture_reference_dir (line 18) | def fixture_reference_dir():
  function fixture_cleanup_output_files (line 24) | def fixture_cleanup_output_files():
  function run_separation_test (line 39) | def run_separation_test(model, audio_path, expected_files):
  function validate_audio_output (line 61) | def validate_audio_output(output_file, reference_dir, waveform_threshold...
  function test_model_separation (line 154) | def test_model_separation(model, expected_files, input_file, reference_d...

FILE: tests/integration/test_ensemble_integration.py
  function fixture_input_file (line 22) | def fixture_input_file():
  function fixture_reference_dir (line 28) | def fixture_reference_dir():
  function fixture_temp_output_dir (line 34) | def fixture_temp_output_dir():
  function fixture_audio_references (line 42) | def fixture_audio_references():
  function validate_audio_output (line 48) | def validate_audio_output(output_file, reference_dir, waveform_threshold...
  function test_ensemble_preset (line 130) | def test_ensemble_preset(preset, expected_files, input_file, reference_d...

FILE: tests/integration/test_ensemble_meaningful.py
  function correlate (line 30) | def correlate(file_a, file_b, sr=44100):
  function rms (line 38) | def rms(file_path, sr=44100):
  function run_separation (line 44) | def run_separation(model, input_file, output_dir):
  function run_preset (line 52) | def run_preset(preset, input_file, output_dir):
  function find_stem (line 60) | def find_stem(output_files, stem_name, output_dir):
  function test_vocal_ensemble_matches_best_single_model (line 84) | def test_vocal_ensemble_matches_best_single_model(input_file, ref_prefix...
  function test_karaoke_ensemble_extracts_lead_only (line 126) | def test_karaoke_ensemble_extracts_lead_only(tmp_path):
  function test_karaoke_on_vocals_produces_lead_backing_split (line 170) | def test_karaoke_on_vocals_produces_lead_backing_split(tmp_path):

FILE: tests/integration/test_multi_stem_verification.py
  function correlate (line 48) | def correlate(file_a, file_b, sr=44100):
  function run_separation (line 64) | def run_separation(model, input_file, output_dir):
  function find_stem (line 72) | def find_stem(output_files, stem_name, output_dir):
  function test_vocal_instrumental_separation (line 100) | def test_vocal_instrumental_separation(input_file, ref_prefix, tmp_path):
  function test_four_stem_separation (line 137) | def test_four_stem_separation(input_file, ref_prefix, tmp_path):
  function test_drumsep_pipeline (line 159) | def test_drumsep_pipeline(tmp_path):
  function test_karaoke_separation (line 199) | def test_karaoke_separation(input_file, ref_prefix, tmp_path):
  function test_wind_instrument_extraction (line 234) | def test_wind_instrument_extraction(tmp_path):
  function test_dereverb_pipeline (line 257) | def test_dereverb_pipeline(tmp_path):

FILE: tests/integration/test_remote_api_integration.py
  class MockAPIHandler (line 18) | class MockAPIHandler(BaseHTTPRequestHandler):
    method log_message (line 29) | def log_message(self, format, *args):
    method do_GET (line 33) | def do_GET(self):
    method do_POST (line 95) | def do_POST(self):
    method _simulate_processing (line 125) | def _simulate_processing(self, task_id):
    method _format_models_as_text (line 147) | def _format_models_as_text(self, models):
    method send_json_response (line 171) | def send_json_response(self, data, status=200):
  function mock_http_server (line 181) | def mock_http_server():
  function api_client (line 199) | def api_client(mock_http_server):
  function test_audio_file (line 206) | def test_audio_file():
  class TestRemoteAPIIntegration (line 214) | class TestRemoteAPIIntegration:
    method test_server_health_check (line 217) | def test_server_health_check(self, api_client):
    method test_list_models_pretty_format (line 222) | def test_list_models_pretty_format(self, api_client):
    method test_list_models_json_format (line 234) | def test_list_models_json_format(self, api_client):
    method test_list_models_with_filter (line 245) | def test_list_models_with_filter(self, api_client):
    method test_separate_audio_submission (line 256) | def test_separate_audio_submission(self, api_client, test_audio_file):
    method test_separate_audio_with_custom_parameters (line 269) | def test_separate_audio_with_custom_parameters(self, api_client, test_...
    method test_job_status_polling (line 284) | def test_job_status_polling(self, api_client, test_audio_file):
    method test_file_download (line 316) | def test_file_download(self, api_client, test_audio_file):
    method test_separate_audio_and_wait_success (line 351) | def test_separate_audio_and_wait_success(self, api_client, test_audio_...
    method test_separate_audio_and_wait_no_download (line 368) | def test_separate_audio_and_wait_no_download(self, api_client, test_au...
    method test_job_status_not_found (line 376) | def test_job_status_not_found(self, api_client):
    method test_download_file_not_found (line 383) | def test_download_file_not_found(self, api_client):
    method test_multiple_concurrent_jobs (line 388) | def test_multiple_concurrent_jobs(self, api_client, test_audio_file):
    method test_separate_audio_with_multiple_models (line 416) | def test_separate_audio_with_multiple_models(self, api_client, test_au...
  class TestRemoteCLIIntegration (line 428) | class TestRemoteCLIIntegration:
    method test_cli_separate_command_integration (line 432) | def test_cli_separate_command_integration(self, mock_client_class, tes...
  class TestRemoteAPIEndToEnd (line 500) | class TestRemoteAPIEndToEnd:
    method test_end_to_end_workflow (line 503) | def test_end_to_end_workflow(self, api_client):
    method test_error_handling_workflow (line 555) | def test_error_handling_workflow(self, api_client):

FILE: tests/integration/test_roformer_audio_quality.py
  class TestRoformerAudioQuality (line 19) | class TestRoformerAudioQuality:
    method reference_audio_file (line 23) | def reference_audio_file(self):
    method test_bs_roformer_audio_quality_regression (line 40) | def test_bs_roformer_audio_quality_regression(self, reference_audio_fi...
    method test_mel_band_roformer_audio_quality_validation (line 67) | def test_mel_band_roformer_audio_quality_validation(self, reference_au...
    method test_audio_similarity_calculation_framework (line 93) | def test_audio_similarity_calculation_framework(self, reference_audio_...

FILE: tests/integration/test_roformer_backward_compatibility.py
  class TestRoformerBackwardCompatibility (line 22) | class TestRoformerBackwardCompatibility:
    method mock_old_roformer_model (line 26) | def mock_old_roformer_model(self):
    method mock_audio_file (line 55) | def mock_audio_file(self):
    method test_load_existing_older_model_without_regression (line 67) | def test_load_existing_older_model_without_regression(self, mock_old_r...
    method test_old_model_uses_fallback_implementation (line 90) | def test_old_model_uses_fallback_implementation(self, mock_old_roforme...
    method test_old_model_configuration_compatibility (line 121) | def test_old_model_configuration_compatibility(self, mock_old_roformer...
    method test_audio_quality_regression_detection (line 144) | def test_audio_quality_regression_detection(self, mock_old_roformer_mo...
    method test_performance_no_significant_degradation (line 167) | def test_performance_no_significant_degradation(self, mock_old_roforme...

FILE: tests/integration/test_roformer_config_validation.py
  class TestRoformerConfigValidation (line 19) | class TestRoformerConfigValidation:
    method mock_invalid_config_model (line 23) | def mock_invalid_config_model(self):
    method test_parameter_validation_error_handling (line 41) | def test_parameter_validation_error_handling(self, mock_invalid_config...

FILE: tests/integration/test_roformer_e2e.py
  class TestRoformerE2E (line 16) | class TestRoformerE2E:
    method setup_method (line 19) | def setup_method(self):
    method teardown_method (line 29) | def teardown_method(self):
    method _create_mock_audio_file (line 33) | def _create_mock_audio_file(self):
    method test_bs_roformer_sw_fixed_e2e (line 50) | def test_bs_roformer_sw_fixed_e2e(self):
    method test_legacy_roformer_e2e (line 116) | def test_legacy_roformer_e2e(self):
    method test_mel_band_roformer_e2e (line 176) | def test_mel_band_roformer_e2e(self):
    method test_roformer_e2e_with_different_audio_formats (line 232) | def test_roformer_e2e_with_different_audio_formats(self):
    method test_roformer_e2e_error_handling (line 270) | def test_roformer_e2e_error_handling(self):
    method test_roformer_e2e_performance_validation (line 304) | def test_roformer_e2e_performance_validation(self):
    method test_roformer_e2e_memory_usage (line 351) | def test_roformer_e2e_memory_usage(self):
    method test_roformer_e2e_batch_processing (line 389) | def test_roformer_e2e_batch_processing(self):

FILE: tests/integration/test_roformer_fallback_mechanism.py
  class TestRoformerFallbackMechanism (line 19) | class TestRoformerFallbackMechanism:
    method mock_edge_case_model (line 23) | def mock_edge_case_model(self):
    method test_fallback_mechanism_activation (line 41) | def test_fallback_mechanism_activation(self, mock_edge_case_model):

FILE: tests/integration/test_roformer_model_switching.py
  class TestRoformerModelSwitching (line 19) | class TestRoformerModelSwitching:
    method mock_bs_roformer_model (line 23) | def mock_bs_roformer_model(self):
    method mock_mel_band_roformer_model (line 39) | def mock_mel_band_roformer_model(self):
    method test_switch_bs_to_mel_band_roformer (line 56) | def test_switch_bs_to_mel_band_roformer(self, mock_bs_roformer_model, ...

FILE: tests/integration/test_roformer_new_parameters.py
  class TestRoformerNewParameters (line 21) | class TestRoformerNewParameters:
    method mock_new_roformer_model (line 25) | def mock_new_roformer_model(self):
    method mock_audio_file (line 58) | def mock_audio_file(self):
    method test_load_newer_model_with_new_parameters (line 68) | def test_load_newer_model_with_new_parameters(self, mock_new_roformer_...
    method test_new_model_uses_new_implementation (line 91) | def test_new_model_uses_new_implementation(self, mock_new_roformer_mod...
    method test_new_parameters_are_properly_handled (line 120) | def test_new_parameters_are_properly_handled(self, mock_new_roformer_m...
    method test_sage_attention_parameter_integration (line 137) | def test_sage_attention_parameter_integration(self, mock_new_roformer_...
    method test_mlp_expansion_factor_parameter_handling (line 158) | def test_mlp_expansion_factor_parameter_handling(self, mock_new_roform...
    method test_torch_checkpoint_parameter_integration (line 178) | def test_torch_checkpoint_parameter_integration(self, mock_new_roforme...
    method test_skip_connection_parameter_integration (line 195) | def test_skip_connection_parameter_integration(self, mock_new_roformer...
    method test_zero_dc_parameter_handling (line 209) | def test_zero_dc_parameter_handling(self, mock_new_roformer_model):
    method test_new_model_audio_quality_validation (line 225) | def test_new_model_audio_quality_validation(self, mock_new_roformer_mo...

FILE: tests/integration/test_separator_output_integration.py
  function fixture_input_file (line 11) | def fixture_input_file():
  function fixture_temp_output_dir (line 17) | def fixture_temp_output_dir():
  function test_separator_output_dir_and_custom_names (line 25) | def test_separator_output_dir_and_custom_names(input_file, temp_output_d...
  function test_separator_single_stem_output (line 83) | def test_separator_single_stem_output(input_file, temp_output_dir):
  function test_separator_output_without_custom_names (line 136) | def test_separator_output_without_custom_names(input_file, temp_output_d...

FILE: tests/model-metrics/test-all-models.py
  class DecimalEncoder (line 23) | class DecimalEncoder(JSONEncoder):
    method default (line 24) | def default(self, obj):
  function load_combined_results (line 47) | def load_combined_results():
  function save_combined_results (line 81) | def save_combined_results(combined_results):
  function update_combined_results (line 104) | def update_combined_results(model_name, track_name, track_data):
  function check_track_evaluated (line 125) | def check_track_evaluated(model_name, track_name):
  function get_track_results (line 131) | def get_track_results(model_name, track_name):
  function get_track_duration (line 139) | def get_track_duration(track_path):
  function evaluate_track (line 150) | def evaluate_track(track_name, track_path, test_model, mus_db):
  function convert_decimal_to_float (line 332) | def convert_decimal_to_float(obj):
  function calculate_median_scores (line 343) | def calculate_median_scores(track_scores):
  function check_disk_usage (line 380) | def check_disk_usage(path):
  function get_evaluated_track_count (line 453) | def get_evaluated_track_count(model_name, museval_results):
  function get_most_evaluated_tracks (line 460) | def get_most_evaluated_tracks(museval_results, min_count=10):
  function generate_summary_statistics (line 478) | def generate_summary_statistics(
  function check_stop_signal (line 530) | def check_stop_signal():
  function main (line 538) | def main():

FILE: tests/regression/test_all_models_stem_verification.py
  function audio_references (line 83) | def audio_references():
  function get_all_models (line 88) | def get_all_models():
  function build_model_params (line 95) | def build_model_params():
  function verify_stem_content (line 112) | def verify_stem_content(stem_path, stem_label, ref_vocal, ref_inst, ref_...
  function test_model_stem_labels (line 181) | def test_model_stem_labels(arch, friendly_name, model_filename, audio_re...

FILE: tests/regression/test_roformer_size_mismatch.py
  class TestRoformerSizeMismatch (line 13) | class TestRoformerSizeMismatch(unittest.TestCase):
    method setUp (line 16) | def setUp(self):
    method test_overlap_add_safe_lengths (line 25) | def test_overlap_add_safe_lengths(self):
    method _test_single_output_length (line 33) | def _test_single_output_length(self, output_length):
    method test_overlap_add_edge_cases (line 106) | def test_overlap_add_edge_cases(self):
    method test_counter_consistency_with_overlap_add (line 151) | def test_counter_consistency_with_overlap_add(self):
    method test_broadcast_error_prevention (line 207) | def test_broadcast_error_prevention(self):
    method test_output_length_preservation_regression (line 269) | def test_output_length_preservation_regression(self):
    method test_memory_layout_consistency (line 310) | def test_memory_layout_consistency(self):

FILE: tests/reproduce_ensemble_bug.py
  function main (line 26) | def main():

FILE: tests/unit/test_audio_chunking.py
  class TestAudioChunker (line 16) | class TestAudioChunker:
    method setup_method (line 19) | def setup_method(self):
    method test_initialization (line 25) | def test_initialization(self):
    method test_initialization_with_custom_logger (line 30) | def test_initialization_with_custom_logger(self):
    method test_should_chunk_true (line 37) | def test_should_chunk_true(self):
    method test_should_chunk_false (line 42) | def test_should_chunk_false(self):
    method test_should_chunk_exact_boundary (line 47) | def test_should_chunk_exact_boundary(self):
    method test_should_chunk_just_over_boundary (line 52) | def test_should_chunk_just_over_boundary(self):
    method test_split_audio_basic (line 60) | def test_split_audio_basic(self, _mock_makedirs, mock_exists, mock_fro...
    method test_split_audio_uneven_chunks (line 88) | def test_split_audio_uneven_chunks(self, _mock_makedirs, mock_exists, ...
    method test_split_audio_file_not_found (line 111) | def test_split_audio_file_not_found(self, tmp_path):
    method test_merge_chunks_basic (line 118) | def test_merge_chunks_basic(self, mock_exists, mock_from_file, tmp_path):
    method test_merge_chunks_empty_list (line 142) | def test_merge_chunks_empty_list(self, tmp_path):
    method test_merge_chunks_missing_file (line 148) | def test_merge_chunks_missing_file(self, mock_exists, tmp_path):
    method test_chunk_duration_calculation (line 155) | def test_chunk_duration_calculation(self):
  class TestAudioChunkerIntegration (line 167) | class TestAudioChunkerIntegration:
    method test_split_and_merge_round_trip (line 170) | def test_split_and_merge_round_trip(self):
    method test_split_with_different_formats (line 207) | def test_split_with_different_formats(self):
  class TestAudioChunkerEdgeCases (line 230) | class TestAudioChunkerEdgeCases:
    method test_very_short_file (line 233) | def test_very_short_file(self):
    method test_exact_multiple_of_chunk_size (line 255) | def test_exact_multiple_of_chunk_size(self):

FILE: tests/unit/test_bit_depth_detection.py
  function create_test_audio_file (line 18) | def create_test_audio_file(output_path, sample_rate=44100, duration=0.5,...
  function fixture_temp_audio_dir (line 56) | def fixture_temp_audio_dir():
  function fixture_mock_separator_config (line 65) | def fixture_mock_separator_config():
  function test_16bit_detection (line 90) | def test_16bit_detection(temp_audio_dir, mock_separator_config):
  function test_24bit_detection (line 114) | def test_24bit_detection(temp_audio_dir, mock_separator_config):
  function test_32bit_detection (line 138) | def test_32bit_detection(temp_audio_dir, mock_separator_config):
  function test_numpy_array_input_defaults_to_16bit (line 162) | def test_numpy_array_input_defaults_to_16bit(mock_separator_config):
  function test_bit_depth_preserved_across_multiple_files (line 182) | def test_bit_depth_preserved_across_multiple_files(temp_audio_dir, mock_...

FILE: tests/unit/test_bit_depth_writing.py
  function is_ffmpeg_available (line 19) | def is_ffmpeg_available():
  function create_test_audio_file (line 41) | def create_test_audio_file(output_path, sample_rate=44100, duration=0.5,...
  function get_audio_bit_depth (line 61) | def get_audio_bit_depth(file_path):
  function fixture_temp_dir (line 77) | def fixture_temp_dir():
  function fixture_mock_separator_config (line 85) | def fixture_mock_separator_config(temp_dir):
  function test_write_16bit_with_pydub (line 111) | def test_write_16bit_with_pydub(temp_dir, mock_separator_config):
  function test_write_24bit_with_pydub (line 146) | def test_write_24bit_with_pydub(temp_dir, mock_separator_config):
  function test_write_32bit_with_pydub (line 180) | def test_write_32bit_with_pydub(temp_dir, mock_separator_config):
  function test_write_24bit_with_soundfile (line 213) | def test_write_24bit_with_soundfile(temp_dir, mock_separator_config):
  function test_write_16bit_with_soundfile (line 249) | def test_write_16bit_with_soundfile(temp_dir, mock_separator_config):

FILE: tests/unit/test_cli.py
  function mock_distribution (line 13) | def mock_distribution():
  function common_expected_args (line 29) | def common_expected_args():
  function test_cli_version_subprocess (line 56) | def test_cli_version_subprocess():
  function test_cli_no_args (line 62) | def test_cli_no_args(capsys):
  function test_cli_multiple_filenames (line 68) | def test_cli_multiple_filenames():
  function test_cli_with_audio_file (line 99) | def test_cli_with_audio_file(capsys, common_expected_args):
  function test_cli_invalid_log_level (line 118) | def test_cli_invalid_log_level():
  function test_cli_model_filename_argument (line 128) | def test_cli_model_filename_argument(common_expected_args):
  function test_cli_output_dir_argument (line 142) | def test_cli_output_dir_argument(common_expected_args):
  function test_cli_output_format_argument (line 159) | def test_cli_output_format_argument(common_expected_args):
  function test_cli_normalization_threshold_argument (line 176) | def test_cli_normalization_threshold_argument(common_expected_args):
  function test_cli_amplification_threshold_argument (line 193) | def test_cli_amplification_threshold_argument(common_expected_args):
  function test_cli_single_stem_argument (line 210) | def test_cli_single_stem_argument(common_expected_args):
  function test_cli_invert_spectrogram_argument (line 227) | def test_cli_invert_spectrogram_argument(common_expected_args):
  function test_cli_use_autocast_argument (line 244) | def test_cli_use_autocast_argument(common_expected_args):
  function test_cli_custom_output_names_argument (line 261) | def test_cli_custom_output_names_argument(common_expected_args):
  function test_cli_demucs_output_names_argument (line 279) | def test_cli_demucs_output_names_argument(common_expected_args):
  function test_cli_extra_models_argument (line 301) | def test_cli_extra_models_argument(common_expected_args):
  function test_cli_single_model_passes_string (line 315) | def test_cli_single_model_passes_string(common_expected_args):
  function test_cli_old_syntax_model_before_audio (line 327) | def test_cli_old_syntax_model_before_audio(common_expected_args):
  function test_cli_ensemble_preset (line 340) | def test_cli_ensemble_preset(common_expected_args):
  function test_cli_list_presets (line 356) | def test_cli_list_presets(capsys):

FILE: tests/unit/test_configuration_normalizer.py
  class TestConfigurationNormalizer (line 29) | class TestConfigurationNormalizer:
    method setup_method (line 32) | def setup_method(self):
    method test_normalize_config_basic (line 36) | def test_normalize_config_basic(self):
    method test_normalize_config_with_defaults (line 50) | def test_normalize_config_with_defaults(self):
    method test_normalize_config_with_validation_valid (line 71) | def test_normalize_config_with_validation_valid(self):
    method test_normalize_config_with_validation_invalid (line 83) | def test_normalize_config_with_validation_invalid(self):
    method test_normalize_structure_flat_config (line 94) | def test_normalize_structure_flat_config(self):
    method test_normalize_structure_nested_config (line 108) | def test_normalize_structure_nested_config(self):
    method test_normalize_parameter_names_aliases (line 137) | def test_normalize_parameter_names_aliases(self):
    method test_normalize_parameter_values_booleans (line 162) | def test_normalize_parameter_values_booleans(self):
    method test_normalize_parameter_values_numbers (line 182) | def test_normalize_parameter_values_numbers(self):
    method test_normalize_parameter_values_tuples (line 207) | def test_normalize_parameter_values_tuples(self):
    method test_normalize_parameter_values_strings (line 226) | def test_normalize_parameter_values_strings(self):
    method test_detect_model_type_bs_roformer (line 240) | def test_detect_model_type_bs_roformer(self):
    method test_detect_model_type_mel_band_roformer (line 253) | def test_detect_model_type_mel_band_roformer(self):
    method test_detect_model_type_unknown (line 268) | def test_detect_model_type_unknown(self):
    method test_normalize_from_file_path_bs_roformer (line 280) | def test_normalize_from_file_path_bs_roformer(self):
    method test_normalize_from_file_path_mel_band_roformer (line 302) | def test_normalize_from_file_path_mel_band_roformer(self):
    method test_normalize_from_file_path_default_fallback (line 323) | def test_normalize_from_file_path_default_fallback(self):
    method test_normalization_preserves_original_config (line 340) | def test_normalization_preserves_original_config(self):
    method test_normalization_error_handling (line 362) | def test_normalization_error_handling(self):
    method test_comprehensive_normalization_workflow (line 378) | def test_comprehensive_normalization_workflow(self):

FILE: tests/unit/test_deploy_cloudrun_async.py
  class TestGPUSemaphore (line 9) | class TestGPUSemaphore:
    method test_semaphore_blocks_concurrent_jobs (line 12) | def test_semaphore_blocks_concurrent_jobs(self):
    method test_semaphore_releases_on_exception (line 33) | def test_semaphore_releases_on_exception(self):
    method test_semaphore_allows_sequential_access (line 62) | def test_semaphore_allows_sequential_access(self):
  class TestLazyInit (line 82) | class TestLazyInit:
    method test_get_job_store_returns_same_instance (line 85) | def test_get_job_store_returns_same_instance(self):
    method test_get_output_store_returns_same_instance (line 105) | def test_get_output_store_returns_same_instance(self):
  class TestFireAndForget (line 122) | class TestFireAndForget:
    method test_run_in_executor_without_await_returns_immediately (line 125) | def test_run_in_executor_without_await_returns_immediately(self):

FILE: tests/unit/test_ensemble_presets.py
  function mock_separator_init (line 10) | def mock_separator_init():
  function test_load_preset_vocal_balanced (line 16) | def test_load_preset_vocal_balanced(mock_separator_init):
  function test_load_preset_karaoke (line 26) | def test_load_preset_karaoke(mock_separator_init):
  function test_load_preset_instrumental_clean (line 32) | def test_load_preset_instrumental_clean(mock_separator_init):
  function test_preset_algorithm_override (line 38) | def test_preset_algorithm_override(mock_separator_init):
  function test_preset_no_algorithm_uses_preset_default (line 50) | def test_preset_no_algorithm_uses_preset_default(mock_separator_init):
  function test_preset_unknown_name (line 56) | def test_preset_unknown_name(mock_separator_init):
  function test_no_preset_defaults_to_avg_wave (line 61) | def test_no_preset_defaults_to_avg_wave(mock_separator_init):
  function test_list_ensemble_presets (line 67) | def test_list_ensemble_presets(mock_separator_init):
  function test_preset_loads_models_on_load_model (line 77) | def test_preset_loads_models_on_load_model(mock_separator_init):
  function test_preset_json_valid (line 85) | def test_preset_json_valid():
  function test_preset_validation_bad_weights_length (line 111) | def test_preset_validation_bad_weights_length(mock_separator_init):
  function test_preset_validation_bad_algorithm (line 132) | def test_preset_validation_bad_algorithm(mock_separator_init):
  function test_preset_validation_single_model (line 152) | def test_preset_validation_single_model(mock_separator_init):
  function test_preset_weights_applied (line 172) | def test_preset_weights_applied(mock_separator_init):
  function test_preset_explicit_weights_override (line 192) | def test_preset_explicit_weights_override(mock_separator_init):

FILE: tests/unit/test_ensembler.py
  function logger (line 7) | def logger():
  function test_ensembler_avg_wave (line 10) | def test_ensembler_avg_wave(logger):
  function test_ensembler_weighted_avg (line 18) | def test_ensembler_weighted_avg(logger):
  function test_ensembler_different_lengths (line 26) | def test_ensembler_different_lengths(logger):
  function test_ensembler_median_wave (line 36) | def test_ensembler_median_wave(logger):
  function test_ensembler_max_wave (line 44) | def test_ensembler_max_wave(logger):
  function test_ensembler_min_wave (line 53) | def test_ensembler_min_wave(logger):
  function test_ensembler_avg_fft (line 62) | def test_ensembler_avg_fft(logger):
  function test_ensembler_ensemble_wav_uvr (line 71) | def test_ensembler_ensemble_wav_uvr(logger):
  function test_ensembler_empty_list (line 81) | def test_ensembler_empty_list(logger):
  function test_ensembler_single_waveform (line 85) | def test_ensembler_single_waveform(logger):
  function test_ensembler_mismatched_channels (line 91) | def test_ensembler_mismatched_channels(logger):
  function test_ensembler_mono_stft (line 101) | def test_ensembler_mono_stft(logger):
  function test_ensembler_single_channel_stft (line 107) | def test_ensembler_single_channel_stft(logger):
  function test_ensembler_median_fft (line 113) | def test_ensembler_median_fft(logger):
  function test_ensembler_min_fft (line 122) | def test_ensembler_min_fft(logger):
  function test_ensembler_max_fft (line 130) | def test_ensembler_max_fft(logger):
  function test_ensembler_uvr_max_spec (line 138) | def test_ensembler_uvr_max_spec(logger):
  function test_ensembler_uvr_min_spec (line 146) | def test_ensembler_uvr_min_spec(logger):
  function test_ensembler_invalid_algorithm (line 154) | def test_ensembler_invalid_algorithm(logger):
  function test_ensembler_weight_mismatch_fallback (line 160) | def test_ensembler_weight_mismatch_fallback(logger):

FILE: tests/unit/test_job_store.py
  function mock_firestore_client (line 7) | def mock_firestore_client():
  function store (line 15) | def store(mock_firestore_client):
  class TestFirestoreJobStore (line 19) | class TestFirestoreJobStore:
    method test_set_creates_document (line 20) | def test_set_creates_document(self, store, mock_firestore_client):
    method test_get_returns_document_data (line 39) | def test_get_returns_document_data(self, store, mock_firestore_client):
    method test_get_returns_none_for_missing_document (line 56) | def test_get_returns_none_for_missing_document(self, store, mock_fires...
    method test_contains_checks_existence (line 66) | def test_contains_checks_existence(self, store, mock_firestore_client):
    method test_update_merges_fields (line 75) | def test_update_merges_fields(self, store, mock_firestore_client):
    method test_delete_removes_document (line 87) | def test_delete_removes_document(self, store, mock_firestore_client):
    method test_cleanup_old_jobs (line 95) | def test_cleanup_old_jobs(self, store, mock_firestore_client):

FILE: tests/unit/test_mdxc_roformer_chunking.py
  class TestMDXCRoformerChunking (line 13) | class TestMDXCRoformerChunking:
    method setup_method (line 16) | def setup_method(self):
    method test_chunk_size_uses_model_stft_hop_length (line 31) | def test_chunk_size_uses_model_stft_hop_length(self):
    method test_chunk_size_falls_back_to_audio_hop_length (line 36) | def test_chunk_size_falls_back_to_audio_hop_length(self):
    method test_step_clamped_to_chunk_size (line 41) | def test_step_clamped_to_chunk_size(self):
    method test_overlap_add_short_output_safe (line 65) | def test_overlap_add_short_output_safe(self):
    method test_counter_updates_safe_len (line 102) | def test_counter_updates_safe_len(self):
    method test_counter_clamp_no_nan (line 137) | def test_counter_clamp_no_nan(self):
    method test_short_audio_last_block (line 170) | def test_short_audio_last_block(self):
    method test_parametrized_shape_invariants (line 221) | def test_parametrized_shape_invariants(self, dim_t, hop_length):
    method test_logging_for_hop_and_step (line 258) | def test_logging_for_hop_and_step(self, caplog):
    method test_iteration_count_reasonable (line 300) | def test_iteration_count_reasonable(self):

FILE: tests/unit/test_model_configuration.py
  class TestModelConfiguration (line 28) | class TestModelConfiguration:
    method test_model_configuration_creation_valid (line 31) | def test_model_configuration_creation_valid(self):
    method test_model_configuration_defaults (line 59) | def test_model_configuration_defaults(self):
    method test_model_configuration_immutable (line 84) | def test_model_configuration_immutable(self):
    method test_model_configuration_type_validation (line 94) | def test_model_configuration_type_validation(self):
    method test_model_configuration_edge_values (line 108) | def test_model_configuration_edge_values(self):
    method test_model_configuration_boolean_parameters (line 137) | def test_model_configuration_boolean_parameters(self):
    method test_model_configuration_new_parameters (line 157) | def test_model_configuration_new_parameters(self):
    method test_model_configuration_repr (line 176) | def test_model_configuration_repr(self):
    method test_model_configuration_equality (line 185) | def test_model_configuration_equality(self):
    method test_model_configuration_hash (line 194) | def test_model_configuration_hash(self):
    method test_model_configuration_from_dict (line 210) | def test_model_configuration_from_dict(self):
    method test_model_configuration_with_extra_kwargs (line 228) | def test_model_configuration_with_extra_kwargs(self):

FILE: tests/unit/test_output_store.py
  function mock_storage_client (line 7) | def mock_storage_client():
  function store (line 15) | def store(mock_storage_client):
  class TestGCSOutputStore (line 19) | class TestGCSOutputStore:
    method test_upload_directory (line 20) | def test_upload_directory(self, store, mock_storage_client):
    method test_upload_builds_correct_gcs_paths (line 31) | def test_upload_builds_correct_gcs_paths(self, store, mock_storage_cli...
    method test_download_file (line 40) | def test_download_file(self, store, mock_storage_client):
    method test_get_file_bytes (line 49) | def test_get_file_bytes(self, store, mock_storage_client):
    method test_delete_task_outputs (line 60) | def test_delete_task_outputs(self, store, mock_storage_client):

FILE: tests/unit/test_parameter_validator.py
  class TestParameterValidator (line 29) | class TestParameterValidator:
    method setup_method (line 32) | def setup_method(self):
    method test_validate_required_parameters_bs_roformer_valid (line 36) | def test_validate_required_parameters_bs_roformer_valid(self):
    method test_validate_required_parameters_bs_roformer_missing (line 47) | def test_validate_required_parameters_bs_roformer_missing(self):
    method test_validate_required_parameters_mel_band_roformer_valid (line 66) | def test_validate_required_parameters_mel_band_roformer_valid(self):
    method test_validate_required_parameters_mel_band_roformer_missing (line 77) | def test_validate_required_parameters_mel_band_roformer_missing(self):
    method test_validate_parameter_types_valid (line 91) | def test_validate_parameter_types_valid(self):
    method test_validate_parameter_types_invalid (line 105) | def test_validate_parameter_types_invalid(self):
    method test_validate_parameter_ranges_valid (line 124) | def test_validate_parameter_ranges_valid(self):
    method test_validate_parameter_ranges_invalid (line 137) | def test_validate_parameter_ranges_invalid(self):
    method test_validate_parameter_compatibility_sage_flash_conflict (line 156) | def test_validate_parameter_compatibility_sage_flash_conflict(self):
    method test_validate_parameter_compatibility_freqs_per_bands_warning (line 168) | def test_validate_parameter_compatibility_freqs_per_bands_warning(self):
    method test_validate_normalization_config_valid (line 179) | def test_validate_normalization_config_valid(self):
    method test_validate_normalization_config_invalid (line 193) | def test_validate_normalization_config_invalid(self):
    method test_get_parameter_defaults_bs_roformer (line 206) | def test_get_parameter_defaults_bs_roformer(self):
    method test_get_parameter_defaults_mel_band_roformer (line 219) | def test_get_parameter_defaults_mel_band_roformer(self):
    method test_apply_parameter_defaults (line 231) | def test_apply_parameter_defaults(self):
    method test_validate_all_comprehensive (line 251) | def test_validate_all_comprehensive(self):
    method test_validate_all_with_errors (line 266) | def test_validate_all_with_errors(self):
    method test_validate_and_raise_success (line 285) | def test_validate_and_raise_success(self):
    method test_validate_and_raise_error (line 296) | def test_validate_and_raise_error(self):
    method test_private_helper_methods (line 312) | def test_private_helper_methods(self):

FILE: tests/unit/test_remote_api_client.py
  function logger (line 14) | def logger():
  function api_client (line 20) | def api_client(logger):
  function mock_audio_file (line 26) | def mock_audio_file():
  class TestAudioSeparatorAPIClient (line 34) | class TestAudioSeparatorAPIClient:
    method test_init (line 37) | def test_init(self, logger):
    method test_separate_audio_success (line 48) | def test_separate_audio_success(self, mock_file, mock_post, api_client...
    method test_separate_audio_with_multiple_models (line 79) | def test_separate_audio_with_multiple_models(self, mock_file, mock_pos...
    method test_separate_audio_with_custom_parameters (line 99) | def test_separate_audio_with_custom_parameters(self, mock_file, mock_p...
    method test_separate_audio_file_not_found (line 122) | def test_separate_audio_file_not_found(self, mock_post, api_client):
    method test_separate_audio_request_error (line 129) | def test_separate_audio_request_error(self, mock_file, mock_post, api_...
    method test_get_job_status_success (line 137) | def test_get_job_status_success(self, mock_get, api_client):
    method test_get_job_status_error (line 151) | def test_get_job_status_error(self, mock_get, api_client):
    method test_download_file_success (line 160) | def test_download_file_success(self, mock_file, mock_get, api_client):
    method test_download_file_default_output_path (line 176) | def test_download_file_default_output_path(self, mock_file, mock_get, ...
    method test_download_file_with_spaces_in_filename (line 191) | def test_download_file_with_spaces_in_filename(self, mock_file, mock_g...
    method test_download_file_with_special_characters (line 210) | def test_download_file_with_special_characters(self, mock_file, mock_g...
    method test_download_file_with_unicode_characters (line 229) | def test_download_file_with_unicode_characters(self, mock_file, mock_g...
    method test_download_file_error (line 247) | def test_download_file_error(self, mock_get, api_client):
    method test_list_models_pretty_format (line 255) | def test_list_models_pretty_format(self, mock_get, api_client):
    method test_list_models_json_format (line 268) | def test_list_models_json_format(self, mock_get, api_client):
    method test_list_models_with_filter (line 282) | def test_list_models_with_filter(self, mock_get, api_client):
    method test_get_server_version_success (line 295) | def test_get_server_version_success(self, mock_get, api_client):
    method test_get_server_version_no_version (line 308) | def test_get_server_version_no_version(self, mock_get, api_client):
    method test_get_server_version_error (line 320) | def test_get_server_version_error(self, mock_get, api_client):
    method test_separate_audio_and_wait_success (line 331) | def test_separate_audio_and_wait_success(self, mock_sleep, mock_downlo...
    method test_separate_audio_and_wait_error (line 359) | def test_separate_audio_and_wait_error(self, mock_sleep, mock_status, ...
    method test_separate_audio_and_wait_timeout (line 373) | def test_separate_audio_and_wait_timeout(self, mock_sleep, mock_status...
    method test_separate_audio_and_wait_no_download (line 387) | def test_separate_audio_and_wait_no_download(self, mock_sleep, mock_do...
    method test_separate_audio_and_wait_with_output_dir (line 402) | def test_separate_audio_and_wait_with_output_dir(self, mock_sleep, moc...
    method test_separate_audio_and_wait_with_special_character_filenames (line 418) | def test_separate_audio_and_wait_with_special_character_filenames(self...
    method test_download_file_server_side_url_decoding_scenario (line 449) | def test_download_file_server_side_url_decoding_scenario(self, mock_fi...
    method test_download_file_by_hash (line 469) | def test_download_file_by_hash(self, mock_file, mock_get, api_client):
    method test_separate_audio_and_wait_with_hash_format (line 492) | def test_separate_audio_and_wait_with_hash_format(self, mock_sleep, mo...
    method test_separate_audio_with_gcs_uri (line 522) | def test_separate_audio_with_gcs_uri(self, mock_post, api_client):
    method test_separate_audio_requires_file_or_gcs_uri (line 545) | def test_separate_audio_requires_file_or_gcs_uri(self, api_client):
    method test_separate_audio_rejects_both_file_and_gcs_uri (line 550) | def test_separate_audio_rejects_both_file_and_gcs_uri(self, api_client...
    method test_separate_audio_and_wait_with_gcs_uri (line 561) | def test_separate_audio_and_wait_with_gcs_uri(self, mock_sleep, mock_s...

FILE: tests/unit/test_remote_cli.py
  function mock_api_client (line 16) | def mock_api_client():
  function mock_logger (line 22) | def mock_logger():
  function mock_audio_file (line 28) | def mock_audio_file():
  class TestRemoteCLI (line 36) | class TestRemoteCLI:
    method test_version_command_no_api_url (line 42) | def test_version_command_no_api_url(self, mock_print, mock_metadata, m...
    method test_version_command_with_api_url (line 57) | def test_version_command_with_api_url(self, mock_print, mock_client_cl...
    method test_version_command_server_error (line 76) | def test_version_command_server_error(self, mock_print, mock_client_cl...
    method test_no_api_url_error (line 92) | def test_no_api_url_error(self, mock_print):
    method test_separate_command (line 103) | def test_separate_command(self, mock_handle_separate, mock_client_class):
    method test_status_command (line 120) | def test_status_command(self, mock_handle_status, mock_client_class):
    method test_models_command (line 133) | def test_models_command(self, mock_handle_models, mock_client_class):
    method test_download_command (line 146) | def test_download_command(self, mock_handle_download, mock_client_class):
    method test_custom_api_url (line 158) | def test_custom_api_url(self, mock_handle_models, mock_client_class):
    method test_debug_logging (line 174) | def test_debug_logging(self, mock_handle_models, mock_client_class):
    method test_handle_separate_command_success (line 184) | def test_handle_separate_command_success(self, mock_api_client, mock_l...
    method test_handle_separate_command_with_multiple_models (line 246) | def test_handle_separate_command_with_multiple_models(self, mock_api_c...
    method test_handle_separate_command_error (line 275) | def test_handle_separate_command_error(self, mock_api_client, mock_log...
    method test_handle_separate_command_exception (line 301) | def test_handle_separate_command_exception(self, mock_api_client, mock...
    method test_handle_status_command_success (line 322) | def test_handle_status_command_success(self, mock_api_client, mock_log...
    method test_handle_status_command_error_status (line 343) | def test_handle_status_command_error_status(self, mock_api_client, moc...
    method test_handle_status_command_exception (line 358) | def test_handle_status_command_exception(self, mock_api_client, mock_l...
    method test_handle_models_command_pretty_format (line 369) | def test_handle_models_command_pretty_format(self, mock_api_client, mo...
    method test_handle_models_command_json_format (line 385) | def test_handle_models_command_json_format(self, mock_api_client, mock...
    method test_handle_models_command_exception (line 402) | def test_handle_models_command_exception(self, mock_api_client, mock_l...
    method test_handle_download_command_success (line 414) | def test_handle_download_command_success(self, mock_api_client, mock_l...
    method test_handle_download_command_exception (line 434) | def test_handle_download_command_exception(self, mock_api_client, mock...

FILE: tests/unit/test_separator_chunking.py
  class TestSeparatorChunking (line 17) | class TestSeparatorChunking:
    method setup_method (line 20) | def setup_method(self):
    method teardown_method (line 25) | def teardown_method(self):
    method test_process_with_chunking_2_stems (line 32) | def test_process_with_chunking_2_stems(self, mock_chunker_class):
    method test_process_with_chunking_4_stems (line 85) | def test_process_with_chunking_4_stems(self, mock_chunker_class):
    method test_process_with_chunking_6_stems (line 144) | def test_process_with_chunking_6_stems(self, mock_chunker_class):
    method test_stem_name_extraction_from_filename (line 195) | def test_stem_name_extraction_from_filename(self):
    method test_stem_name_extraction_fallback (line 219) | def test_stem_name_extraction_fallback(self):
    method test_chunking_preserves_stem_order (line 238) | def test_chunking_preserves_stem_order(self, mock_chunker_class):
  class TestSeparatorChunkingLogic (line 286) | class TestSeparatorChunkingLogic:
    method setup_method (line 289) | def setup_method(self):
    method teardown_method (line 294) | def teardown_method(self):
    method test_state_restoration_after_chunking (line 301) | def test_state_restoration_after_chunking(self, mock_chunker_class):
    method test_gpu_cache_cleared_between_chunks (line 348) | def test_gpu_cache_cleared_between_chunks(self, mock_chunker_class):
    method test_temp_directory_cleanup (line 386) | def test_temp_directory_cleanup(self, mock_chunker_class):
    method test_error_handling_with_state_restoration (line 431) | def test_error_handling_with_state_restoration(self, mock_chunker_class):
    method test_audio_chunker_initialization (line 469) | def test_audio_chunker_initialization(self, mock_chunker_class):
    method test_custom_output_names_applied_to_merged_output (line 503) | def test_custom_output_names_applied_to_merged_output(self, mock_chunk...
  class TestSeparatorChunkingEdgeCases (line 568) | class TestSeparatorChunkingEdgeCases:
    method setup_method (line 571) | def setup_method(self):
    method teardown_method (line 576) | def teardown_method(self):
    method test_empty_output_handling (line 583) | def test_empty_output_handling(self, mock_chunker_class):
    method test_inconsistent_stem_count_across_chunks (line 618) | def test_inconsistent_stem_count_across_chunks(self, mock_chunker_class):
    method test_filename_without_stem_pattern (line 662) | def test_filename_without_stem_pattern(self, mock_chunker_class):

FILE: tests/unit/test_separator_detection.py
  class TestSeparatorDetection (line 12) | class TestSeparatorDetection:
    method setup_method (line 15) | def setup_method(self):
    method teardown_method (line 19) | def teardown_method(self):
    method test_is_roformer_set_from_yaml_path (line 24) | def test_is_roformer_set_from_yaml_path(self):
    method test_roformer_detection_case_insensitive (line 97) | def test_roformer_detection_case_insensitive(self):
    method test_roformer_detection_with_full_paths (line 119) | def test_roformer_detection_with_full_paths(self):
    method test_roformer_detection_with_config_content (line 141) | def test_roformer_detection_with_config_content(self):
    method test_roformer_routing_integration (line 173) | def test_roformer_routing_integration(self):
    method test_roformer_detection_edge_cases (line 212) | def test_roformer_detection_edge_cases(self):
    method test_roformer_detection_with_model_extensions (line 240) | def test_roformer_detection_with_model_extensions(self):

FILE: tests/unit/test_stem_naming.py
  class TestCommonSeparatorStemSwap (line 11) | class TestCommonSeparatorStemSwap:
    method _make_config (line 14) | def _make_config(self, model_data):
    method test_no_swap_when_target_matches_instruments0 (line 39) | def test_no_swap_when_target_matches_instruments0(self, mock_detect):
    method test_swap_when_target_mismatches_instruments0 (line 53) | def test_swap_when_target_mismatches_instruments0(self, mock_detect):
    method test_no_swap_when_no_target_instrument (line 68) | def test_no_swap_when_no_target_instrument(self, mock_detect):
    method test_no_swap_when_target_not_in_instruments (line 81) | def test_no_swap_when_target_not_in_instruments(self, mock_detect):
    method test_single_instrument_no_swap (line 95) | def test_single_instrument_no_swap(self, mock_detect):
  class TestStemNameMap (line 108) | class TestStemNameMap:
    method test_stem_name_map_has_expected_entries (line 111) | def test_stem_name_map_has_expected_entries(self):
    method test_stem_name_map_keys_are_lowercase (line 123) | def test_stem_name_map_keys_are_lowercase(self):
  class TestEnsembleOutputFilenames (line 129) | class TestEnsembleOutputFilenames:
    method test_preset_filename_format (line 132) | def test_preset_filename_format(self):
    method test_custom_ensemble_slug_generation (line 142) | def test_custom_ensemble_slug_generation(self):
  class TestEnsembleCustomOutputNames (line 166) | class TestEnsembleCustomOutputNames:
    method test_custom_output_names_not_passed_to_intermediate_separation (line 169) | def test_custom_output_names_not_passed_to_intermediate_separation(self):

FILE: tests/unit/test_stft.py
  class TestSTFT (line 22) | class TestSTFT(unittest.TestCase):
    method setUp (line 23) | def setUp(self):
    method create_mock_tensor (line 30) | def create_mock_tensor(self, shape, device=None):
    method test_stft_initialization (line 36) | def test_stft_initialization(self):
    method test_stft_call (line 43) | def test_stft_call(self):
    method test_calculate_inverse_dimensions (line 77) | def test_calculate_inverse_dimensions(self):
    method test_pad_frequency_dimension (line 92) | def test_pad_frequency_dimension(self):
    method test_prepare_for_istft (line 106) | def test_prepare_for_istft(self):
    method test_inverse_stft (line 124) | def test_inverse_stft(self):
    method test_stft_with_mps_device (line 141) | def test_stft_with_mps_device(self):
    method test_inverse_with_mps_device (line 150) | def test_inverse_with_mps_device(self):
  class MockLogger (line 160) | class MockLogger:
    method debug (line 161) | def debug(self, message):

FILE: tests/utils.py
  function generate_waveform_image (line 13) | def generate_waveform_image(audio_path, output_path=None, fig_size=(10, ...
  function generate_spectrogram_image (line 58) | def generate_spectrogram_image(audio_path, output_path=None, fig_size=(1...
  function compare_images (line 117) | def compare_images(image1_path, image2_path, min_similarity_threshold=0....
  function generate_reference_images (line 161) | def generate_reference_images(input_path, output_dir=None, prefix=""):

FILE: tests/utils_audio_verification.py
  class StemVerification (line 16) | class StemVerification:
  function load_references (line 28) | def load_references(input_dir="tests/inputs", sr=44100):
  function classify_audio (line 49) | def classify_audio(audio_mono, ref_vocal, ref_instrumental, ref_mix, min...
  function verify_stem (line 77) | def verify_stem(file_path, label, ref_vocal, ref_instrumental, ref_mix, ...
  function verify_separation_outputs (line 118) | def verify_separation_outputs(output_files, ref_vocal, ref_instrumental,...
  function print_verification_report (line 143) | def print_verification_report(results):

FILE: tools/calculate-model-hashes.py
  function get_model_hash (line 20) | def get_model_hash(model_path):
  function download_file_if_missing (line 38) | def download_file_if_missing(url, local_path):
  function load_json_data (line 55) | def load_json_data(file_path):
  function iterate_and_hash (line 70) | def iterate_and_hash(directory):

FILE: tools/sync-to-github.py
  function debug_request (line 17) | def debug_request(url: str, headers: dict, response: requests.Response):
  function get_release_assets (line 28) | def get_release_assets() -> List[Dict]:
  function list_local_files (line 46) | def list_local_files() -> List[str]:
  function calculate_file_hash (line 51) | def calculate_file_hash(filepath: str) -> str:
  function upload_asset (line 60) | def upload_asset(release_id: int, filepath: str):
  function download_asset (line 79) | def download_asset(asset: Dict):
  function main (line 96) | def main():
Condensed preview — 271 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (4,980K chars).
[
  {
    "path": ".claude/plans/gha-gpu-runner.plan.md",
    "chars": 7743,
    "preview": "# Plan: GCP GPU Runner for Integration Tests\n\n**Created:** 2026-03-16\n**Branch:** feat/gha-gpu-runner\n**Status:** Implem"
  },
  {
    "path": ".cursor/commands/analyze.md",
    "chars": 6250,
    "preview": "---\ndescription: Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and "
  },
  {
    "path": ".cursor/commands/clarify.md",
    "chars": 9936,
    "preview": "---\ndescription: Identify underspecified areas in the current feature spec by asking up to 5 highly targeted clarificati"
  },
  {
    "path": ".cursor/commands/constitution.md",
    "chars": 5124,
    "preview": "---\ndescription: Create or update the project constitution from interactive or provided principle inputs, ensuring all d"
  },
  {
    "path": ".cursor/commands/implement.md",
    "chars": 3175,
    "preview": "---\ndescription: Execute the implementation plan by processing and executing all tasks defined in tasks.md\n---\n\nThe user"
  },
  {
    "path": ".cursor/commands/plan.md",
    "chars": 2397,
    "preview": "---\ndescription: Execute the implementation planning workflow using the plan template to generate design artifacts.\n---\n"
  },
  {
    "path": ".cursor/commands/specify.md",
    "chars": 1454,
    "preview": "---\ndescription: Create or update the feature specification from a natural language feature description.\n---\n\nThe user i"
  },
  {
    "path": ".cursor/commands/tasks.md",
    "chars": 2551,
    "preview": "---\ndescription: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts"
  },
  {
    "path": ".cursor/rules/specify-rules.mdc",
    "chars": 724,
    "preview": "# python-audio-separator Development Guidelines\n\nAuto-generated from all feature plans. Last updated: 2025-09-25\n\n## Act"
  },
  {
    "path": ".github/FUNDING.yml",
    "chars": 16,
    "preview": "github: beveradb"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/BUG_REPORT.yml",
    "chars": 1743,
    "preview": "name: Bug report\ndescription: Report a problem you encountered\ntitle: \"[Bug]: \"\nlabels: [\"bug\"]\nbody:\n  - type: textarea"
  },
  {
    "path": ".github/ISSUE_TEMPLATE/FEATURE_REQUEST.yml",
    "chars": 386,
    "preview": "name: Feature request\ndescription: Suggest an idea for this project\ntitle: \"[Feature]: \"\nlabels: [\"enhancement\", \"featur"
  },
  {
    "path": ".github/prompts/analyze.prompt.md",
    "chars": 6250,
    "preview": "---\ndescription: Perform a non-destructive cross-artifact consistency and quality analysis across spec.md, plan.md, and "
  },
  {
    "path": ".github/prompts/clarify.prompt.md",
    "chars": 9936,
    "preview": "---\ndescription: Identify underspecified areas in the current feature spec by asking up to 5 highly targeted clarificati"
  },
  {
    "path": ".github/prompts/constitution.prompt.md",
    "chars": 5124,
    "preview": "---\ndescription: Create or update the project constitution from interactive or provided principle inputs, ensuring all d"
  },
  {
    "path": ".github/prompts/implement.prompt.md",
    "chars": 3175,
    "preview": "---\ndescription: Execute the implementation plan by processing and executing all tasks defined in tasks.md\n---\n\nThe user"
  },
  {
    "path": ".github/prompts/plan.prompt.md",
    "chars": 2397,
    "preview": "---\ndescription: Execute the implementation planning workflow using the plan template to generate design artifacts.\n---\n"
  },
  {
    "path": ".github/prompts/specify.prompt.md",
    "chars": 1454,
    "preview": "---\ndescription: Create or update the feature specification from a natural language feature description.\n---\n\nThe user i"
  },
  {
    "path": ".github/prompts/tasks.prompt.md",
    "chars": 2551,
    "preview": "---\ndescription: Generate an actionable, dependency-ordered tasks.md for the feature based on available design artifacts"
  },
  {
    "path": ".github/workflows/deploy-to-cloudrun.yml",
    "chars": 1883,
    "preview": "name: Deploy to Cloud Run\n\non:\n  # Deploy when a new PyPI release is published\n  workflow_run:\n    workflows: [\"Publish "
  },
  {
    "path": ".github/workflows/deploy-to-modal.yml",
    "chars": 1580,
    "preview": "name: deploy-to-modal\n\non:\n  # Deploy after PyPI publish (when new version is available)\n  workflow_run:\n    workflows: "
  },
  {
    "path": ".github/workflows/github-sponsors.yml",
    "chars": 580,
    "preview": "name: Generate Sponsors README\non:\n  workflow_dispatch:\n  schedule:\n    - cron: 30 15 * * 0-6\npermissions:\n  contents: w"
  },
  {
    "path": ".github/workflows/publish-to-docker.yml",
    "chars": 2988,
    "preview": "name: publish-to-docker\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - pyproject.toml\n      - Dockerfile.cpu"
  },
  {
    "path": ".github/workflows/publish-to-pypi.yml",
    "chars": 560,
    "preview": "name: publish-to-pypi\n\non:\n  push:\n    branches:\n      - main\n    paths:\n      - pyproject.toml\n  workflow_dispatch:\n\njo"
  },
  {
    "path": ".github/workflows/run-integration-tests.yaml",
    "chars": 7105,
    "preview": "name: run-integration-tests\n\non:\n  pull_request:\n\njobs:\n  changes:\n    runs-on: ubuntu-latest\n    outputs:\n      should_"
  },
  {
    "path": ".github/workflows/run-unit-tests.yaml",
    "chars": 3575,
    "preview": "name: run-unit-tests\n\non:\n  pull_request:\n\njobs:\n  changes:\n    runs-on: ubuntu-latest\n    outputs:\n      should_run: ${"
  },
  {
    "path": ".gitignore",
    "chars": 3265,
    "preview": "# Andrew env\n.DS_Store\n.vscode\n\n# Andrew functional adds\n/tracks/\n/lyrics/\n/.cache/\n*.onnx\n*.pth\n*.wav\n/*.flac\n*.mp3\ntes"
  },
  {
    "path": ".specify/memory/constitution.md",
    "chars": 4290,
    "preview": "<!--\nSync Impact Report:\nVersion change: Initial → 1.0.0\nModified principles: All (new constitution)\nAdded sections: Cor"
  },
  {
    "path": ".specify/scripts/bash/check-prerequisites.sh",
    "chars": 4946,
    "preview": "#!/usr/bin/env bash\n\n# Consolidated prerequisite checking script\n#\n# This script provides unified prerequisite checking "
  },
  {
    "path": ".specify/scripts/bash/common.sh",
    "chars": 3297,
    "preview": "#!/usr/bin/env bash\n# Common functions and variables for all scripts\n\n# Get repository root, with fallback for non-git r"
  },
  {
    "path": ".specify/scripts/bash/create-new-feature.sh",
    "chars": 2921,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\nJSON_MODE=false\nARGS=()\nfor arg in \"$@\"; do\n    case \"$arg\" in\n        --json) JSON_MODE=tr"
  },
  {
    "path": ".specify/scripts/bash/setup-plan.sh",
    "chars": 1616,
    "preview": "#!/usr/bin/env bash\n\nset -e\n\n# Parse command line arguments\nJSON_MODE=false\nARGS=()\n\nfor arg in \"$@\"; do\n    case \"$arg\""
  },
  {
    "path": ".specify/scripts/bash/update-agent-context.sh",
    "chars": 23009,
    "preview": "#!/usr/bin/env bash\n\n# Update agent context files with information from plan.md\n#\n# This script maintains AI agent conte"
  },
  {
    "path": ".specify/templates/agent-file-template.md",
    "chars": 454,
    "preview": "# [PROJECT NAME] Development Guidelines\n\nAuto-generated from all feature plans. Last updated: [DATE]\n\n## Active Technolo"
  },
  {
    "path": ".specify/templates/plan-template.md",
    "chars": 9056,
    "preview": "\n# Implementation Plan: [FEATURE]\n\n**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]\n**Input**: Fea"
  },
  {
    "path": ".specify/templates/spec-template.md",
    "chars": 4140,
    "preview": "# Feature Specification: [FEATURE NAME]\n\n**Feature Branch**: `[###-feature-name]`  \n**Created**: [DATE]  \n**Status**: Dr"
  },
  {
    "path": ".specify/templates/tasks-template.md",
    "chars": 4591,
    "preview": "# Tasks: [FEATURE NAME]\n\n**Input**: Design documents from `/specs/[###-feature-name]/`\n**Prerequisites**: plan.md (requi"
  },
  {
    "path": "Dockerfile.cloudrun",
    "chars": 3271,
    "preview": "# Audio Separator API - Cloud Run GPU Deployment\n# Optimized for NVIDIA L4 GPU on Google Cloud Run\n#\n# Models are baked "
  },
  {
    "path": "Dockerfile.cpu",
    "chars": 438,
    "preview": "# Use an official Python runtime as a parent image\nFROM python:3.12-slim\n\n# Set the working directory in the container\nW"
  },
  {
    "path": "Dockerfile.cuda11",
    "chars": 719,
    "preview": "# Use an official Python runtime as a parent image\nFROM nvidia/cuda:11.8.0-base-ubuntu22.04\n\n# Set the working directory"
  },
  {
    "path": "Dockerfile.cuda12",
    "chars": 958,
    "preview": "# Use the latest CUDA 12 runtime as base image\nFROM nvidia/cuda:12.3.1-devel-ubuntu22.04\n\n# Set the working directory in"
  },
  {
    "path": "Dockerfile.runpod-cuda11",
    "chars": 641,
    "preview": "# Runpod Base image: https://github.com/runpod/containers/blob/main/official-templates/base/Dockerfile\nFROM runpod/base:"
  },
  {
    "path": "Dockerfile.runpod-cuda12",
    "chars": 985,
    "preview": "# Runpod Base image: https://github.com/runpod/containers/blob/main/official-templates/base/Dockerfile\nFROM runpod/base:"
  },
  {
    "path": "LICENSE",
    "chars": 1069,
    "preview": "MIT License\n\nCopyright (c) 2023 karaokenerds\n\nPermission is hereby granted, free of charge, to any person obtaining a co"
  },
  {
    "path": "README.md",
    "chars": 39380,
    "preview": "<div align=\"center\">\n\n# 🎶 Audio Separator 🎶\n\n[![PyPI version](https://badge.fury.io/py/audio-separator.svg)](https://bad"
  },
  {
    "path": "TODO.md",
    "chars": 1040,
    "preview": "# Audio-Separator TO-DO list\n\nIf you see something here, Andrew is aware it needs to be done, and he will hopefully get "
  },
  {
    "path": "audio_separator/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "audio_separator/ensemble_presets.json",
    "chars": 4395,
    "preview": "{\n    \"version\": 1,\n    \"presets\": {\n        \"instrumental_clean\": {\n            \"name\": \"Instrumental Clean\",\n         "
  },
  {
    "path": "audio_separator/model-data.json",
    "chars": 922,
    "preview": "{\n    \"vr_model_data\": {\n        \"97dc361a7a88b2c4542f68364b32c7f6\": {\n            \"vr_model_param\": \"4band_v4_ms_fullba"
  },
  {
    "path": "audio_separator/models-scores.json",
    "chars": 1286638,
    "preview": "{\n  \"1_HP-UVR.pth\": {\n    \"model_name\": \"VR Arch Single Model v5: 1_HP-UVR\",\n    \"track_scores\": [\n      {\n        \"trac"
  },
  {
    "path": "audio_separator/models.json",
    "chars": 15283,
    "preview": "{\n    \"vr_download_list\": {\n        \"VR Arch Single Model v4: UVR-De-Reverb by aufr33-jarredou\": \"UVR-De-Reverb-aufr33-j"
  },
  {
    "path": "audio_separator/remote/README.md",
    "chars": 12129,
    "preview": "## Remote API Usage 🌐\n\nAudio Separator includes a remote API client that allows you to connect to a deployed Audio Separ"
  },
  {
    "path": "audio_separator/remote/__init__.py",
    "chars": 87,
    "preview": "from .api_client import AudioSeparatorAPIClient\n\n__all__ = [\"AudioSeparatorAPIClient\"]\n"
  },
  {
    "path": "audio_separator/remote/api_client.py",
    "chars": 23138,
    "preview": "#!/usr/bin/env python\nimport os\nimport logging\nimport json\nfrom typing import Optional, List, Dict\nfrom urllib.parse imp"
  },
  {
    "path": "audio_separator/remote/cli.py",
    "chars": 17155,
    "preview": "#!/usr/bin/env python\nimport argparse\nimport json\nimport logging\nimport os\nimport sys\nimport time\nfrom importlib import "
  },
  {
    "path": "audio_separator/remote/deploy_cloudrun.py",
    "chars": 27769,
    "preview": "\"\"\"\nAudio Separator API - Cloud Run GPU Deployment\n\nA FastAPI service for separating vocals from instrumental tracks usi"
  },
  {
    "path": "audio_separator/remote/deploy_modal.py",
    "chars": 35149,
    "preview": "\"\"\"\nAudio Separator API - Simple Modal Deployment\nA FastAPI service for separating vocals from instrumental tracks using"
  },
  {
    "path": "audio_separator/remote/job_store.py",
    "chars": 2554,
    "preview": "\"\"\"Firestore-backed job status store for audio separation jobs.\n\nReplaces the in-memory dict so any Cloud Run instance c"
  },
  {
    "path": "audio_separator/remote/output_store.py",
    "chars": 2223,
    "preview": "\"\"\"GCS-backed output file store for audio separation results.\n\nUploads separation output files to GCS so any Cloud Run i"
  },
  {
    "path": "audio_separator/remote/requirements.txt",
    "chars": 6,
    "preview": "modal\n"
  },
  {
    "path": "audio_separator/separator/__init__.py",
    "chars": 33,
    "preview": "from .separator import Separator\n"
  },
  {
    "path": "audio_separator/separator/architectures/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "audio_separator/separator/architectures/demucs_separator.py",
    "chars": 8745,
    "preview": "import os\nimport sys\nfrom pathlib import Path\nimport torch\nimport numpy as np\nfrom audio_separator.separator.common_sepa"
  },
  {
    "path": "audio_separator/separator/architectures/mdx_separator.py",
    "chars": 24072,
    "preview": "\"\"\"Module for separating audio sources using MDX architecture models.\"\"\"\n\nimport os\nimport platform\nimport torch\nimport "
  },
  {
    "path": "audio_separator/separator/architectures/mdxc_separator.py",
    "chars": 25432,
    "preview": "import os\nimport sys\n\nimport torch\nimport numpy as np\nfrom tqdm import tqdm\nfrom ml_collections import ConfigDict\nfrom s"
  },
  {
    "path": "audio_separator/separator/architectures/vr_separator.py",
    "chars": 20947,
    "preview": "\"\"\"Module for separating audio sources using VR architecture models.\"\"\"\n\nimport os\nimport math\n\nimport torch\nimport libr"
  },
  {
    "path": "audio_separator/separator/audio_chunking.py",
    "chars": 5216,
    "preview": "\"\"\"Audio chunking utilities for processing large audio files to prevent OOM errors.\"\"\"\n\nimport os\nimport logging\nfrom ty"
  },
  {
    "path": "audio_separator/separator/common_separator.py",
    "chars": 26116,
    "preview": "\"\"\" This file contains the CommonSeparator class, common to all architecture-specific Separator classes. \"\"\"\n\nfrom loggi"
  },
  {
    "path": "audio_separator/separator/ensembler.py",
    "chars": 7221,
    "preview": "import numpy as np\nimport librosa\nfrom audio_separator.separator.uvr_lib_v5 import spec_utils\n\n\nclass Ensembler:\n    def"
  },
  {
    "path": "audio_separator/separator/roformer/README.md",
    "chars": 4635,
    "preview": "# Roformer Implementation - Updated Parameter Support\n\nThis directory contains the updated Roformer implementation with "
  },
  {
    "path": "audio_separator/separator/roformer/__init__.py",
    "chars": 550,
    "preview": "\"\"\"\nRoformer implementation module.\nUpdated implementation supporting both old and new Roformer model parameters.\n\"\"\"\n\nf"
  },
  {
    "path": "audio_separator/separator/roformer/bs_roformer_config.py",
    "chars": 5527,
    "preview": "\"\"\"\nBSRoformer-specific configuration class.\nExtends ModelConfiguration with BSRoformer-specific parameters.\n\"\"\"\n\nfrom d"
  },
  {
    "path": "audio_separator/separator/roformer/bs_roformer_validator.py",
    "chars": 9098,
    "preview": "\"\"\"\nBSRoformer-specific parameter validator.\nExtends the base ParameterValidator with BSRoformer-specific validation log"
  },
  {
    "path": "audio_separator/separator/roformer/configuration_normalizer.py",
    "chars": 12148,
    "preview": "\"\"\"\nConfiguration normalizer for Roformer models.\nNormalizes and standardizes configuration dictionaries from various so"
  },
  {
    "path": "audio_separator/separator/roformer/mel_band_roformer_config.py",
    "chars": 6914,
    "preview": "\"\"\"\nMelBandRoformer-specific configuration class.\nExtends ModelConfiguration with MelBandRoformer-specific parameters.\n\""
  },
  {
    "path": "audio_separator/separator/roformer/mel_band_roformer_validator.py",
    "chars": 11955,
    "preview": "\"\"\"\nMelBandRoformer-specific parameter validator.\nExtends the base ParameterValidator with MelBandRoformer-specific vali"
  },
  {
    "path": "audio_separator/separator/roformer/model_configuration.py",
    "chars": 5876,
    "preview": "\"\"\"\nModel configuration dataclass for Roformer models.\nSupports both old and new parameter sets with backward compatibil"
  },
  {
    "path": "audio_separator/separator/roformer/model_loading_result.py",
    "chars": 7288,
    "preview": "\"\"\"\nModel loading result dataclass.\nContains the result of model loading operations with success/failure information.\n\"\""
  },
  {
    "path": "audio_separator/separator/roformer/parameter_validation_error.py",
    "chars": 6857,
    "preview": "\"\"\"\nParameter validation error exception.\nRaised when model parameters are invalid or incompatible.\n\"\"\"\n\nfrom typing imp"
  },
  {
    "path": "audio_separator/separator/roformer/parameter_validator.py",
    "chars": 16355,
    "preview": "\"\"\"\nParameter validator implementation.\nValidates Roformer model parameters according to interface contracts.\n\"\"\"\n\nfrom "
  },
  {
    "path": "audio_separator/separator/roformer/roformer_loader.py",
    "chars": 13553,
    "preview": "\"\"\"Roformer model loader with simplified new-implementation only path.\"\"\"\nfrom typing import Dict, Any\nimport logging\nim"
  },
  {
    "path": "audio_separator/separator/separator.py",
    "chars": 69841,
    "preview": "\"\"\" This file contains the Separator class, to facilitate the separation of stems from audio. \"\"\"\n\nfrom importlib import"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/__init__.py",
    "chars": 196,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/__main__.py",
    "chars": 8165,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/apply.py",
    "chars": 10890,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/demucs.py",
    "chars": 16906,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/filtering.py",
    "chars": 19727,
    "preview": "from typing import Optional\nimport torch\nimport torch.nn as nn\nfrom torch import Tensor\nfrom torch.utils.data import Dat"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/hdemucs.py",
    "chars": 29751,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/htdemucs.py",
    "chars": 25947,
    "preview": "# Copyright (c) Meta, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the license"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/model.py",
    "chars": 7168,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/model_v2.py",
    "chars": 7270,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/pretrained.py",
    "chars": 5554,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/repo.py",
    "chars": 4671,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/spec.py",
    "chars": 1298,
    "preview": "# Copyright (c) Meta Platforms, Inc. and affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the l"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/states.py",
    "chars": 3963,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/tasnet.py",
    "chars": 14831,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/tasnet_v2.py",
    "chars": 14968,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/transformer.py",
    "chars": 25350,
    "preview": "# Copyright (c) 2019-present, Meta, Inc.\n# All rights reserved.\n#\n# This source code is licensed under the license found"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/demucs/utils.py",
    "chars": 16401,
    "preview": "# Copyright (c) Facebook, Inc. and its affiliates.\n# All rights reserved.\n#\n# This source code is licensed under the lic"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/mdxnet.py",
    "chars": 4199,
    "preview": "import torch\nimport torch.nn as nn\nfrom .modules import TFC_TDF\nfrom pytorch_lightning import LightningModule\n\ndim_s = 4"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/modules.py",
    "chars": 2005,
    "preview": "import torch\nimport torch.nn as nn\n\n\nclass TFC(nn.Module):\n    def __init__(self, c, l, k, norm):\n        super(TFC, sel"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/playsound.py",
    "chars": 8804,
    "preview": "import logging\nlogger = logging.getLogger(__name__)\n\nclass PlaysoundException(Exception):\n    pass\n\ndef _canonicalizePat"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/pyrb.py",
    "chars": 2135,
    "preview": "import os\nimport subprocess\nimport tempfile\nimport six\nimport numpy as np\nimport soundfile as sf\nimport sys\n\nif getattr("
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/results.py",
    "chars": 1583,
    "preview": "# -*- coding: utf-8 -*-\n\n\"\"\"\nMatchering - Audio Matching and Mastering Python Library\nCopyright (C) 2016-2022 Sergree\n\nT"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/roformer/attend.py",
    "chars": 3061,
    "preview": "from functools import wraps\nfrom packaging import version\nfrom collections import namedtuple\n\nimport torch\nfrom torch im"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/roformer/bs_roformer.py",
    "chars": 16896,
    "preview": "from functools import partial\n\nimport torch\nfrom torch import nn, einsum, Tensor\nfrom torch.nn import Module, ModuleList"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/roformer/mel_band_roformer.py",
    "chars": 16120,
    "preview": "from functools import partial\n\nimport torch\nfrom torch import nn, einsum, Tensor\nfrom torch.nn import Module, ModuleList"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/spec_utils.py",
    "chars": 46460,
    "preview": "import audioread\r\nimport librosa\r\nimport numpy as np\r\nimport soundfile as sf\r\nimport math\r\nimport platform\r\nimport trace"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/stft.py",
    "chars": 6332,
    "preview": "import torch\n\n\nclass STFT:\n    \"\"\"\n    This class performs the Short-Time Fourier Transform (STFT) and its inverse (ISTF"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/tfc_tdf_v3.py",
    "chars": 8107,
    "preview": "import torch\nimport torch.nn as nn\nfrom functools import partial\n\nclass STFT:\n    def __init__(self, n_fft, hop_length, "
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/__init__.py",
    "chars": 11,
    "preview": "# VR init.\n"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/layers.py",
    "chars": 16717,
    "preview": "import torch\r\nfrom torch import nn\r\nimport torch.nn.functional as F\r\n\r\nfrom audio_separator.separator.uvr_lib_v5 import "
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/layers_new.py",
    "chars": 6463,
    "preview": "import torch\nfrom torch import nn\nimport torch.nn.functional as F\n\nfrom audio_separator.separator.uvr_lib_v5 import spec"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/model_param_init.py",
    "chars": 2666,
    "preview": "import json\r\n\r\ndefault_param = {}\r\ndefault_param[\"bins\"] = -1\r\ndefault_param[\"unstable_bins\"] = -1  # training only\r\ndef"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr16000_hl512.json",
    "chars": 292,
    "preview": "{\n\t\"bins\": 1024,\n\t\"unstable_bins\": 0,\n\t\"reduction_bins\": 0,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 16000,\n\t\t\t\"hl\": 512,\n\t\t\t\"n_fft\""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr32000_hl512.json",
    "chars": 294,
    "preview": "{\n\t\"bins\": 1024,\n\t\"unstable_bins\": 0,\n\t\"reduction_bins\": 0,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 32000,\n\t\t\t\"hl\": 512,\n\t\t\t\"n_fft\""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr33075_hl384.json",
    "chars": 292,
    "preview": "{\n\t\"bins\": 1024,\n\t\"unstable_bins\": 0,\n\t\"reduction_bins\": 0,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 33075,\n\t\t\t\"hl\": 384,\n\t\t\t\"n_fft\""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr44100_hl1024.json",
    "chars": 293,
    "preview": "{\n\t\"bins\": 1024,\n\t\"unstable_bins\": 0,\n\t\"reduction_bins\": 0,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 44100,\n\t\t\t\"hl\": 1024,\n\t\t\t\"n_fft"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr44100_hl256.json",
    "chars": 287,
    "preview": "{\n\t\"bins\": 256,\n\t\"unstable_bins\": 0,\n\t\"reduction_bins\": 0,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 44100,\n\t\t\t\"hl\": 256,\n\t\t\t\"n_fft\":"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr44100_hl512.json",
    "chars": 292,
    "preview": "{\n\t\"bins\": 1024,\n\t\"unstable_bins\": 0,\n\t\"reduction_bins\": 0,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 44100,\n\t\t\t\"hl\": 512,\n\t\t\t\"n_fft\""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr44100_hl512_cut.json",
    "chars": 290,
    "preview": "{\n\t\"bins\": 1024,\n\t\"unstable_bins\": 0,\n\t\"reduction_bins\": 0,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 44100,\n\t\t\t\"hl\": 512,\n\t\t\t\"n_fft\""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/1band_sr44100_hl512_nf1024.json",
    "chars": 306,
    "preview": "{\r\n\t\"bins\": 512,\r\n\t\"unstable_bins\": 0,\r\n\t\"reduction_bins\": 0,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 44100,\r\n\t\t\t\"hl\": 512,\r\n\t\t\t"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/2band_32000.json",
    "chars": 483,
    "preview": "{\n\t\"bins\": 768,\n\t\"unstable_bins\": 7,\n\t\"reduction_bins\": 705,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 6000,\n\t\t\t\"hl\": 66,\n\t\t\t\"n_fft\":"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/2band_44100_lofi.json",
    "chars": 485,
    "preview": "{\n\t\"bins\": 512,\n\t\"unstable_bins\": 7,\n\t\"reduction_bins\": 510,\n\t\"band\": {\n\t\t\"1\": {\n\t\t\t\"sr\": 11025,\n\t\t\t\"hl\": 160,\n\t\t\t\"n_fft"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/2band_48000.json",
    "chars": 511,
    "preview": "{\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 705,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 6000,\r\n\t\t\t\"hl\": 66,\r\n\t\t\t"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/3band_44100.json",
    "chars": 737,
    "preview": "{\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 5,\r\n\t\"reduction_bins\": 733,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 11025,\r\n\t\t\t\"hl\": 128,\r\n\t"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/3band_44100_mid.json",
    "chars": 757,
    "preview": "{\r\n\t\"mid_side\": true,\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 5,\r\n\t\"reduction_bins\": 733,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 1102"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/3band_44100_msb2.json",
    "chars": 757,
    "preview": "{\r\n\t\"mid_side_b2\": true,\r\n\t\"bins\": 640,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 565,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 1"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_44100.json",
    "chars": 960,
    "preview": "{\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 668,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 11025,\r\n\t\t\t\"hl\": 128,\r\n\t"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_44100_mid.json",
    "chars": 980,
    "preview": "{\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 7,\r\n\t\"mid_side\": true,\r\n\t\"reduction_bins\": 668,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 1102"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_44100_msb.json",
    "chars": 980,
    "preview": "{\r\n\t\"mid_side_b\": true,\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 668,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 11"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_44100_msb2.json",
    "chars": 980,
    "preview": "{\r\n\t\"mid_side_b\": true,\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 668,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 11"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_44100_reverse.json",
    "chars": 977,
    "preview": "{\r\n\t\"reverse\": true,\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 668,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 11025"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_44100_sw.json",
    "chars": 978,
    "preview": "{\r\n\t\"stereo_w\": true,\r\n\t\"bins\": 768,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 668,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 1102"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_v2.json",
    "chars": 947,
    "preview": "{\r\n\t\"bins\": 672,\r\n\t\"unstable_bins\": 8,\r\n\t\"reduction_bins\": 637,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 7350,\r\n\t\t\t\"hl\": 80,\r\n\t\t\t"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_v2_sn.json",
    "chars": 983,
    "preview": "{\r\n\t\"bins\": 672,\r\n\t\"unstable_bins\": 8,\r\n\t\"reduction_bins\": 637,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 7350,\r\n\t\t\t\"hl\": 80,\r\n\t\t\t"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_v3.json",
    "chars": 944,
    "preview": "{\r\n\t\"bins\": 672,\r\n\t\"unstable_bins\": 8,\r\n\t\"reduction_bins\": 530,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 7350,\r\n\t\t\t\"hl\": 80,\r\n\t\t\t"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_v3_sn.json",
    "chars": 979,
    "preview": "{\r\n\t\"n_bins\": 672,\r\n\t\"unstable_bins\": 8,\r\n\t\"stable_bins\": 530,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": 7350,\r\n\t\t\t\"hl\": 80,\r\n\t\t\t\""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/4band_v4_ms_fullband.json",
    "chars": 1495,
    "preview": "{\r\n    \"n_bins\": 896,\r\n    \"unstable_bins\": 9,\r\n    \"stable_bins\": 530,\r\n    \"band\": {\r\n        \"1\": {\r\n            \"sr\""
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/modelparams/ensemble.json",
    "chars": 761,
    "preview": "{\r\n\t\"mid_side_b2\": true,\r\n\t\"bins\": 1280,\r\n\t\"unstable_bins\": 7,\r\n\t\"reduction_bins\": 565,\r\n\t\"band\": {\r\n\t\t\"1\": {\r\n\t\t\t\"sr\": "
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/nets.py",
    "chars": 9100,
    "preview": "import torch\r\nfrom torch import nn\r\nimport torch.nn.functional as F\r\n\r\nfrom . import layers\r\n\r\n\r\nclass BaseASPPNet(nn.Mo"
  },
  {
    "path": "audio_separator/separator/uvr_lib_v5/vr_network/nets_new.py",
    "chars": 7317,
    "preview": "import torch\nfrom torch import nn\nimport torch.nn.functional as F\nfrom . import layers_new as layers\n\n\nclass BaseNet(nn."
  },
  {
    "path": "audio_separator/utils/__init__.py",
    "chars": 0,
    "preview": ""
  },
  {
    "path": "audio_separator/utils/cli.py",
    "chars": 20134,
    "preview": "#!/usr/bin/env python\nimport argparse\nimport logging\nimport json\nimport sys\nimport os\nfrom importlib import metadata\n\n\nd"
  },
  {
    "path": "cloudbuild.yaml",
    "chars": 799,
    "preview": "# Cloud Build config for building the audio-separator Docker image with baked models.\n# Run manually: gcloud builds subm"
  },
  {
    "path": "docs/BIT_DEPTH_IMPLEMENTATION_SUMMARY.md",
    "chars": 3554,
    "preview": "# Summary: Bit Depth Preservation Implementation\n\n## Issue\n[GitHub Issue #243](https://github.com/nomadkaraoke/python-au"
  },
  {
    "path": "docs/BIT_DEPTH_PRESERVATION.md",
    "chars": 4655,
    "preview": "# Bit Depth Preservation Implementation\n\n## Summary\n\nThis implementation ensures that the output audio files from audio-"
  },
  {
    "path": "docs/CI-GPU-RUNNERS.md",
    "chars": 6124,
    "preview": "# CI GPU Runner Infrastructure\n\nThis document explains how the GPU-based integration test infrastructure works for this "
  },
  {
    "path": "docs/archive/2026-03-22-modal-to-gcp-migration-plan.md",
    "chars": 18466,
    "preview": "# Plan: Modal → GCP Audio Separation Migration\n\n**Created:** 2026-03-22\n**Branch:** feat/sess-20260321-2314-modal-gcp-mi"
  },
  {
    "path": "docs/deton24-audio-separation-info-2026-03-15.md",
    "chars": 1733678,
    "preview": "## *edit.* 14.03.26\n\n*deton24’s*\n\n**Instrumental and vocal & stems separation &** [***mastering***](#_k34y1vaaneb1)\n\n*(U"
  },
  {
    "path": "docs/deton24-model-mapping-and-ensemble-guide.md",
    "chars": 30156,
    "preview": "# Deton24 Doc ↔ Audio-Separator Model Mapping & Ensemble Guide\n\n**Date:** 2026-03-15\n**Source document:** `docs/deton24-"
  },
  {
    "path": "environment.yml",
    "chars": 179,
    "preview": "name: audio-separator-dev\nchannels:\n  - conda-forge\ndependencies:\n  - python >=3.10\n  - anaconda-client\n  - conda-build\n"
  },
  {
    "path": "pyproject.toml",
    "chars": 2589,
    "preview": "[build-system]\nrequires = [\"poetry-core\"]\nbuild-backend = \"poetry.core.masonry.api\"\n\n[tool.poetry]\nname = \"audio-separat"
  },
  {
    "path": "pytest.ini",
    "chars": 233,
    "preview": "# Used by PyDub, which uses a pure-python fallback when needed already, not an issue\n[pytest]\nfilterwarnings =\n    ignor"
  },
  {
    "path": "scripts/download_preset_models.py",
    "chars": 731,
    "preview": "\"\"\"Download ensemble preset models for baking into Docker image.\"\"\"\nimport json\nimport importlib.resources as resources\n"
  },
  {
    "path": "specs/001-update-roformer-implementation/001-update-roformer-implementation.md",
    "chars": 8643,
    "preview": "# Feature Specification: Update Roformer Implementation\n\n**Feature Branch**: `001-update-roformer-implementation`  \n**Cr"
  },
  {
    "path": "specs/001-update-roformer-implementation/contracts/fallback_loader_interface.py",
    "chars": 1911,
    "preview": "\"\"\"\nInterface contract for fallback loader implementations.\nDefines the expected behavior for fallback loading mechanism"
  },
  {
    "path": "specs/001-update-roformer-implementation/contracts/parameter_validator_interface.py",
    "chars": 6790,
    "preview": "\"\"\"\nAPI Contract: Parameter Validator Interface\nThis defines the interface for validating Roformer model parameters.\n\"\"\""
  },
  {
    "path": "specs/001-update-roformer-implementation/contracts/roformer_loader_interface.py",
    "chars": 6529,
    "preview": "\"\"\"\nAPI Contract: Roformer Model Loader Interface\nThis defines the interface for loading Roformer models with backward c"
  },
  {
    "path": "specs/001-update-roformer-implementation/data-model.md",
    "chars": 5528,
    "preview": "# Data Model: Roformer Implementation Update\n\n## Core Entities\n\n### RoformerModel\nRepresents a Roformer audio separation"
  },
  {
    "path": "specs/001-update-roformer-implementation/plan.md",
    "chars": 9668,
    "preview": "# Implementation Plan: Update Roformer Implementation\n\n**Branch**: `001-update-roformer-implementation` | **Date**: Sept"
  },
  {
    "path": "specs/001-update-roformer-implementation/post-implementation-issues.md",
    "chars": 2990,
    "preview": "### Post-Implementation Issues: Roformer Routing and Execution Paths\n\n- **Observed behavior**: New Roformer models load "
  },
  {
    "path": "specs/001-update-roformer-implementation/quickstart.md",
    "chars": 6572,
    "preview": "# Quickstart Guide: Updated Roformer Implementation\n\nThis guide demonstrates how to use the updated Roformer implementat"
  },
  {
    "path": "specs/001-update-roformer-implementation/research.md",
    "chars": 5291,
    "preview": "# Research Findings: Roformer Implementation Update\n\n## Key Differences Between Old and New Implementations\n\n### 1. BSRo"
  },
  {
    "path": "specs/001-update-roformer-implementation/tasks.md",
    "chars": 12966,
    "preview": "# Tasks: Update Roformer Implementation\n\n**Input**: Design documents from `/specs/001-update-roformer-implementation/`\n*"
  },
  {
    "path": "specs/main/plan.md",
    "chars": 9056,
    "preview": "\n# Implementation Plan: [FEATURE]\n\n**Branch**: `[###-feature-name]` | **Date**: [DATE] | **Spec**: [link]\n**Input**: Fea"
  },
  {
    "path": "tests/README.md",
    "chars": 5167,
    "preview": "# Audio Separator Tests\n\nThis directory contains tests for the audio-separator project.\n\n## Test Structure\n\n### Unit Tes"
  },
  {
    "path": "tests/TODO.txt",
    "chars": 1490,
    "preview": "- Test running CLI with minimal input file for each major supported model (e.g. at least 1 from each architecture) outpu"
  },
  {
    "path": "tests/contract/test_parameter_validator_interface.py",
    "chars": 14255,
    "preview": "\"\"\"\nContract tests for ParameterValidatorInterface.\nThese tests verify the parameter validation interface contracts.\n\"\"\""
  },
  {
    "path": "tests/contract/test_roformer_loader_interface.py",
    "chars": 6761,
    "preview": "\"\"\"\nContract tests for RoformerLoaderInterface.\nThese tests verify the interface contracts defined in the specification."
  },
  {
    "path": "tests/integration/README.md",
    "chars": 2766,
    "preview": "# Integration Tests\n\nThese tests verify the end-to-end functionality of the audio-separator CLI.\n\n## Test Files\n\n### 16-"
  },
  {
    "path": "tests/integration/generate_multi_stem_references.py",
    "chars": 5939,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nGenerate reference stems for multi-stem integration tests.\n\nRuns best-in-class models on test"
  },
  {
    "path": "tests/integration/generate_reference_images.py",
    "chars": 1919,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nScript to generate reference waveform and spectrogram images for model outputs.\nThis script s"
  },
  {
    "path": "tests/integration/generate_reference_images_24bit.py",
    "chars": 4331,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nScript to generate reference waveform and spectrogram images for 24-bit model outputs.\nThis s"
  },
  {
    "path": "tests/integration/generate_reference_images_ensemble.py",
    "chars": 2901,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nScript to generate reference waveform and spectrogram images for ensemble preset outputs.\n\nUs"
  },
  {
    "path": "tests/integration/requirements.txt",
    "chars": 25,
    "preview": "matplotlib\nscikit-image\n\n"
  },
  {
    "path": "tests/integration/test_24bit_preservation.py",
    "chars": 8468,
    "preview": "\"\"\"\nIntegration tests for 24-bit audio bit depth preservation.\n\nTests that 24-bit input audio files produce 24-bit outpu"
  },
  {
    "path": "tests/integration/test_cli_integration.py",
    "chars": 8352,
    "preview": "import os\nimport subprocess\nimport sys\nfrom pathlib import Path\n\nimport pytest\nsys.path.append(os.path.dirname(os.path.d"
  },
  {
    "path": "tests/integration/test_ensemble_integration.py",
    "chars": 7718,
    "preview": "\"\"\"\nIntegration tests for ensemble preset separations.\n\nTests that each ensemble preset produces correct output by:\n1. R"
  },
  {
    "path": "tests/integration/test_ensemble_meaningful.py",
    "chars": 9879,
    "preview": "\"\"\"\nIntegration tests verifying ensemble presets produce meaningful results.\n\nThese tests go beyond regression (does out"
  },
  {
    "path": "tests/integration/test_multi_stem_verification.py",
    "chars": 12169,
    "preview": "\"\"\"\nIntegration tests for multi-stem and instrument-specific separation models.\n\nTests a matrix of models × clips, verif"
  },
  {
    "path": "tests/integration/test_remote_api_integration.py",
    "chars": 21726,
    "preview": "import json\nimport pytest\nimport logging\nimport tempfile\nimport os\nimport time\nfrom pathlib import Path\nfrom unittest.mo"
  },
  {
    "path": "tests/integration/test_roformer_audio_quality.py",
    "chars": 5121,
    "preview": "\"\"\"\nAudio quality validation tests for Roformer models.\nThese tests ensure audio quality hasn't regressed after the upda"
  },
  {
    "path": "tests/integration/test_roformer_backward_compatibility.py",
    "chars": 8426,
    "preview": "\"\"\"\nIntegration test for existing older model compatibility.\nThis test ensures that existing models continue to work wit"
  },
  {
    "path": "tests/integration/test_roformer_config_validation.py",
    "chars": 2106,
    "preview": "\"\"\"\nIntegration test for configuration validation error handling.\nThis test ensures invalid configurations are caught wi"
  },
  {
    "path": "tests/integration/test_roformer_e2e.py",
    "chars": 19084,
    "preview": "\"\"\"\nEnd-to-end integration tests for Roformer models.\nTests complete separation workflow with both new and legacy models"
  },
  {
    "path": "tests/integration/test_roformer_fallback_mechanism.py",
    "chars": 2009,
    "preview": "\"\"\"\nIntegration test for fallback mechanism activation.\nThis test ensures fallback from new to old implementation works "
  },
  {
    "path": "tests/integration/test_roformer_model_switching.py",
    "chars": 2733,
    "preview": "\"\"\"\nIntegration test for model type switching (BSRoformer ↔ MelBandRoformer).\nThis test ensures seamless switching betwe"
  },
  {
    "path": "tests/integration/test_roformer_new_parameters.py",
    "chars": 10698,
    "preview": "\"\"\"\nIntegration test for newer models with new parameters.\nThis test ensures that newer Roformer models with additional "
  },
  {
    "path": "tests/integration/test_separator_output_integration.py",
    "chars": 8991,
    "preview": "import os\nimport pytest\nimport tempfile\nimport shutil\nfrom pathlib import Path\n\nfrom audio_separator.separator import Se"
  },
  {
    "path": "tests/model-metrics/test-all-models.py",
    "chars": 39847,
    "preview": "#!/usr/bin/env python\nimport os\nimport time\nimport museval\nimport numpy as np\nimport soundfile as sf\nfrom audio_separato"
  },
  {
    "path": "tests/regression/test_all_models_stem_verification.py",
    "chars": 10274,
    "preview": "#!/usr/bin/env python3\n\"\"\"\nOn-demand regression test: verify every supported model's output stem labels\nmatch their actu"
  },
  {
    "path": "tests/regression/test_roformer_size_mismatch.py",
    "chars": 17166,
    "preview": "\"\"\"\nRegression tests for Roformer size mismatch issues.\nTests the handling of shorter outputs and broadcast errors in ov"
  },
  {
    "path": "tests/remote/README.md",
    "chars": 6104,
    "preview": "# Remote API Tests\n\nThis directory contains comprehensive tests for the remote API functionality of audio-separator, whi"
  },
  {
    "path": "tests/reproduce_ensemble_bug.py",
    "chars": 4063,
    "preview": "\"\"\"\nReproduce the ensemble + custom_output_names bug against the live API.\n\nThis script simulates exactly what karaoke-g"
  },
  {
    "path": "tests/unit/test_audio_chunking.py",
    "chars": 10690,
    "preview": "\"\"\"\nUnit tests for audio chunking functionality.\nTests the AudioChunker class for splitting and merging audio files.\n\"\"\""
  },
  {
    "path": "tests/unit/test_bit_depth_detection.py",
    "chars": 7760,
    "preview": "\"\"\"\nUnit tests for bit depth preservation functionality in CommonSeparator.\n\nTests the bit depth detection and storage l"
  },
  {
    "path": "tests/unit/test_bit_depth_writing.py",
    "chars": 9971,
    "preview": "\"\"\"\nUnit tests for bit depth preservation in audio writing functions.\n\nTests that the write_audio functions preserve the"
  },
  {
    "path": "tests/unit/test_cli.py",
    "chars": 15618,
    "preview": "import json\nimport pytest\nimport logging\nfrom audio_separator.utils.cli import main\nimport subprocess\nimport importlib.m"
  }
]

// ... and 71 more files (download for full content)

About this extraction

This page contains the full source code of the nomadkaraoke/python-audio-separator GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 271 files (4.5 MB), approximately 1.2M tokens, and a symbol index with 1337 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!