--- language: - en library_name: stable-audio-3 license: other license_name: stable-audio-community license_link: https://huggingface.co/stabilityai/SAME-L/blob/main/LICENSE base_model: stabilityai/SAME-L tags: - music - audio - autoencoder - lora - stable-audio-3 --- # SAME-L Decoder LoRA (`squeakfix_v3`) A LoRA on **SAME-L's decoder**. It changes how latents are rendered to audio, not how latents are produced — the encoder is untouched, so the latent space, the DiT and every existing DiT LoRA stay bit-compatible, and this stacks with them in any order. It fixes one thing: the high-frequency squeaks SAME's autoencoder manufactures on percussion when audio goes round the encode/decode loop more than once. SAME downsamples 44.1 kHz stereo by 4096×, so a snare attack lives entirely inside a single latent frame — the decoder doesn't reconstruct that attack, it resynthesizes one, slightly differently every pass. Nothing in SAME's training objective ever asked that `encode(decode(z)) ≈ z`; every loss is `real audio → latent → real audio`. This adapter adds that objective after the fact, on the decoder only. Since a continuation or a transform re-encodes its input, a chained session compounds the artifact — that's where this earns its place. Trained and used by [the collabage patch](https://huggingface.co/thepatch), in production in a live `stable-audio-3` backend since 2026-08-14. Ship at strength **1.0** — that's where it was trained and auditioned. ## Hear it Since we keep struggling to produce clean metrics surrounding this artifact, we place these examples so you can really hear what it's doing. Same latent, same seed, decoder adapter the only variable; every clip is 15 s, peak-matched to −1 dBFS so level can't masquerade as quality. Generated with the `koan` DiT LoRA on `medium`. ### Round trips — where it earns its place | | stock decoder | `squeakfix_v3` | |---|---|---| | **jungle** — fresh generation | | | | **jungle** — after 3 round trips | | | | **drums** — fresh generation | | | | **drums** — after 3 round trips | | | | **neurofunk** — fresh generation | | | | **neurofunk** — after 3 round trips | | | These three prompts were **not** selected for artifact content — they are ordinary koan generations, and the fresh-generation rows are here so you can follow the progression rather than because much is audible in them. Three round trips is a short chained session: two continuations and a transform get you there. jungle is the worst of the three; drums and neurofunk are unremarkable. It isn't winning by sanding the top end, which is the easy way to fake this. At d3 all three hold **2.0 to 9.3 dB more** 12–16 kHz and 16–22 kHz energy than the stock render, at a higher RMS, while showing a fraction of the tonal frames. The only band that ever drops is 8–12 kHz on the drums clip, by 0.9 dB — and that is exactly where the artifact concentrates. ### A fresh generation — subtler, but we do hear it We swear we hear it on initial generations too, and it is **much** more subtle. This pair is the worst of 16 candidates, screened by how far tonality runs away over 3 round trips with the adapter off — screening is how you find an audible A/B for something this small, and it means this pair is a worst case, not a typical one. | | stock decoder | `squeakfix_v3` | |---|---|---| | **glitch hop** — fresh generation, screened | | | What changes here is **air, not squeak count**. Across the three screened generations the adapter moves tonality by −0.37 dB at d0 — nothing — while restoring **1.5 to 2.4 dB** of 16–22 kHz top octave in every one. On this particular pair tonality moves −0.08 dB, i.e. not at all, and air moves +2.4 dB. If you are looking for the difference in a tonal-frame count you will not find it. ## Usage Requires `target: "decoder"` support in [Stability-AI/stable-audio-3](https://github.com/Stability-AI/stable-audio-3). The `target` field in the checkpoint config is what routes it; there's no special loading path. ```bash python run_gradio.py --model medium-base --lora-ckpt-path squeakfix_v3.safetensors # stacks with a DiT LoRA, either order python run_gradio.py --model medium-base \ --lora-ckpt-path my_style.safetensors squeakfix_v3.safetensors ``` ```python from stable_audio_3 import AutoencoderModel from stable_audio_3.models.lora.loader import load_and_apply_loras from stable_audio_3.models.lora.model import set_lora_strength ae = AutoencoderModel.from_pretrained("same-l", device="cuda").autoencoder load_and_apply_loras(ae, ["squeakfix_v3.safetensors"], "autoencoder") set_lora_strength(ae.decoder, 1.0) # separate call; 0.0 is the stock decode audio = ae.decode(ae.encode(waveform)) ``` ## Measured Four `koan` generations of 2 minutes, screened from 12 candidates by how far 6–16 kHz tonality runs away with the adapter off. Each latent is decoded twice — adapter off, adapter on — and each chain re-encodes in place, so dN is genuinely N round trips of that decoder config. The adapter is the only variable. | depth | tonality p95 | tonal frames | 12–16 kHz | SI-SDR vs own d0 | |---|---|---|---|---| | d0 — fresh generation | 11.25 → 11.33 | 780 → 933 | 20.7 → 21.4 | — | | d1 — one continuation or transform | 12.46 → **11.59** | 972 → 1074 | 19.9 → **21.2** | 13.5 → **17.5** | | d2 | 14.42 → **11.81** | 1492 → **1246** | 19.3 → **21.0** | 8.9 → **12.8** | | d3 | 17.03 → **12.06** | 2453 → **1411** | 18.6 → **20.9** | 6.7 → **10.4** | **Stock tonality climbs +5.79 dB over three round trips. With the adapter it climbs +0.73 dB.** That holds on every generation individually — stock +4.98 to +6.97, the adapter +0.18 to +1.40 — and it is the whole claim: the artifact stops compounding. **The tonal-frame column rises at d0 and d1, and that is not a regression.** That count rewards peakiness, and the adapter puts high-frequency energy back; restored harmonics read as tonal. It is also dominated by two of the four generations, which start near 1000 and 2100 frames because glitchcore genuinely is tonal. The other two start at **zero** and stay there with the adapter — 0 → 39 and 0 → 8 at d3 — while stock reaches 1038 and 268. Where the artifact has room to appear, the adapter suppresses it; where the material is already tonal, the count cannot tell artifact from content. Read p95, not the count. **It is not sanding the top end**, which is the easy way to post a good number. At every depth it holds more 12–16 kHz energy than stock and the gap *widens* with depth (+0.70, +1.31, +1.76, +2.30 dB at d0–d3), while SI-SDR against its own d0 runs 3.6 to 3.9 dB better. It drifts less rather than erasing what drifts. At d0 the change is air, not squeak count: on a separate screened 30 s set the adapter moves tonality by −0.37 dB — nothing — while restoring 1.5 to 2.4 dB of 16–22 kHz top octave in all three generations. Trust the clips above over any of these numbers. This table is `koan` at 120 s and fp16. An earlier unscreened run covering `kev` as well, at both 30 s and 120 s, showed the same direction at depth. ## Limits - **Decoder LoRAs trained this way stamp a comb into the output — this one doesn't, and that's most of why it exists.** The un-patch is a bare reshape at `patch_size 256`, so output channel and time-position-within-patch are the same axis, and any channel-wise bias the adapter learns repeats identically in every patch: a harmonic comb at `sr/256 = 172.27 Hz` that reads as a wrong note, not as noise. Inaudible in a mix, obvious once a stem separator strips the masking content, which is how it was found. `--lambda_patch 30` is what prevents it. On model output, a `v1` control trained on the identical recipe with `--lambda_patch 0` sits **+10.9 dB** of comb excess over stock; v3 sits **−0.8 dB**, and both hold that gap through three further round trips. On *real* audio rather than model output v3 measures +1.5 to +4.0 dB — different distribution, so measure on generated audio. - **SAME-L only.** SAME-S shares the patch grid but its artifact sits 1–8 kHz and wants a different recipe. Loading this there won't error; it'll sound wrong. - **The gain scales with re-encode depth** — small for one-shot generation, it compounds across chained continuations. - **The squeaks are partly an upstream prompt-distribution problem.** OOD prompts produce far more offending frames; this reduces the artifact, it doesn't make prompt choice irrelevant. - **One checkpoint, one dataset, chosen partly by ear** at step 2000 on re-encode behaviour. Your material may want a different one. - **Neither half of the autoencoder is bit-deterministic** (encoder 1.5 % relative, decoder 7e-3 max abs) — read any A/B as a multiple of those floors. ## Training Self-supervised — audio only, no captions, no paired data. Rank 16 / alpha 16, 5.63M trainable params (~1.30 % of the decoder), step 2000 of a run configured for 8000, fp32 training and fp16 storage, single GB10 (DGX Spark) at ~2.9 s/step on 10 s crops, under 10 GB. ```bash python scripts/train_decoder_lora.py \ --model same-l --rank 16 --steps 8000 --lr 1e-4 \ --w_real 0.4 --w_drift 0.3 --w_dit 0.3 \ --lambda_cycle 10.0 --lambda_tonal 0.3 --lambda_patch 30 \ --patch_size 256 --crop_seconds 10 --seed 0 \ --dit_latent_dir out/dit_latents \ --data_dir /path/to/audio --eval_audio /path/to/holdout.wav \ --out_dir out/declora ``` Latents come from three buckets: real audio, drifted audio (`E(D(E(x)))` at depth ≥ 1, targeted against the **original** so the decoder is asked to undo accumulated drift), and latents sampled from the base DiT. No discriminator — adversarial training makes a decoder invent *more* detail, and the failure mode of plain reconstruction losses is the direction this wants. Full method, losses, ablations and traps: [Decoder LoRA workflow](https://github.com/Stability-AI/stable-audio-3/blob/main/docs/workflows/decoder-lora.md). Provenance — base model, step, full recipe — is embedded in the file's `lora_config` metadata, so the checkpoint identifies itself without this card. `v1` (identical recipe, `--lambda_patch 0`) is an internal control, not published. The autoencoder this adapts: [SAME](https://arxiv.org/abs/2605.18613).