| --- |
| license: mit |
| tags: |
| - audio |
| - source-separation |
| - music |
| - demucs |
| - core-ai |
| --- |
| |
| # htdemucs on Core AI |
|
|
| Meta's [Hybrid Transformer Demucs](https://github.com/facebookresearch/demucs) (`htdemucs`: drums, bass, other, vocals) converted to a Core AI model for macOS 27 on Apple Silicon. It is the drum, bass and other separator in slurper, a stem-splitting command-line tool. |
|
|
| ## Graph |
|
|
| `htdemucs_fp32.aimodel`, float32, one function `main`, fixed shapes for one 7.8 s segment at 44.1 kHz: |
|
|
| | | Name | Shape | Contents | |
| |---|---|---|---| |
| | in | `mix` | `[1, 2, 343980]` | stereo audio | |
| | in | `spec` | `[1, 4, 2048, 336]` | `HTDemucs._magnitude(HTDemucs._spec(mix))`: left real, left imaginary, right real, right imaginary | |
| | out | `time` | `[1, 8, 343980]` | time branch, 4 sources × 2 channels | |
| | out | `freq` | `[1, 16, 2048, 336]` | frequency branch, 4 sources × 2 channels × real/imaginary | |
|
|
| The graph is `HTDemucs.forward` from its normalization to just before `_mask`; both outputs are denormalized. The complex STFT stays on the host, so a caller: |
|
|
| 1. computes `spec` as demucs does: reflect-pad by 1536 samples plus the remainder of the last hop, take a centered, normalized STFT (4096-sample periodic Hann, hop 1024), and keep bins 0..<2048 of frames 2..<338; |
| 2. runs `main`; |
| 3. inverts each source and channel of `freq` with `HTDemucs._ispec` (zero Nyquist bin, two zero frames each side, normalized inverse STFT, trim) and adds `time`. |
|
|
| For whole songs, split into 7.8 s segments overlapping by a quarter with triangular crossfades, as demucs's `apply_model` does. Source order is drums, bass, other, vocals. |
|
|
| float16 overflows to NaN in the frequency branch. Running two inferences at once on one loaded model corrupted the outputs, so run segments one at a time. |
|
|
| ## Verification |
|
|
| - A synthetic segment through Core AI on the GPU against PyTorch `HTDemucs.forward`: 114 dB (drums), 129 dB (bass), 114 dB (other), 100 dB (vocals) SDR. |
| - A 135 s song through slurper's Swift host against PyTorch `apply_model` (no shifts, overlap 0.25): 113-120 dB SDR per stem. |
|
|
| ## Conversion |
|
|
| `scripts/convert_htdemucs.py` in slurper: demucs 4.1.0, torch 2.13.0, coreai-torch 0.4.2 (coreai-core 1.0.0b2). It exports the core with `torch.export`, converts it with `TorchConverter`, and checks the Core AI output against PyTorch before saving. |
|
|
| ## License |
|
|
| MIT, as are the htdemucs weights in facebookresearch/demucs. |
|
|