Stable Audio 3
English
music
audio
autoencoder
lora
thecollabagepatch commited on
Commit
d37c273
Β·
verified Β·
1 Parent(s): 4d802f5

SAME-L decoder LoRA (squeakfix_v3): round-trip artifact fix

Browse files
Files changed (2) hide show
  1. README.md +253 -0
  2. squeakfix_v3.safetensors +3 -0
README.md ADDED
@@ -0,0 +1,253 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ ---
2
+ language:
3
+ - en
4
+ library_name: stable-audio-3
5
+ license: other
6
+ license_name: stable-audio-community
7
+ license_link: https://huggingface.co/stabilityai/SAME-L/blob/main/LICENSE
8
+ base_model: stabilityai/SAME-L
9
+ tags:
10
+ - music
11
+ - audio
12
+ - autoencoder
13
+ - lora
14
+ - stable-audio-3
15
+ ---
16
+
17
+ # SAME-L Decoder LoRA (`squeakfix_v3`)
18
+
19
+ A LoRA on **SAME-L's decoder**. It changes how latents are rendered to audio, not
20
+ how latents are produced.
21
+
22
+ The encoder is untouched, so the latent space, the DiT and every existing DiT
23
+ LoRA stay bit-compatible. This adapter stacks with them in any order.
24
+
25
+ It exists to fix one specific thing: the high-frequency squeaks and chirps that
26
+ SAME's autoencoder manufactures on percussion when audio goes round the
27
+ encode/decode loop more than once β€” which is what every chained continuation
28
+ does.
29
+
30
+ **Trained and used by [the collabage patch](https://huggingface.co/thepatch).**
31
+ In production in a live `stable-audio-3` backend since 2026-08-14.
32
+
33
+ ---
34
+
35
+ ## Usage
36
+
37
+ Requires the `target: "decoder"` support in
38
+ [Stability-AI/stable-audio-3](https://github.com/Stability-AI/stable-audio-3).
39
+ No special loading path β€” the `target` field in the checkpoint config is what
40
+ routes it.
41
+
42
+ ```bash
43
+ python run_gradio.py --model medium-base \
44
+ --lora-ckpt-path squeakfix_v3.safetensors
45
+ ```
46
+
47
+ Stacked with a DiT LoRA, in either order:
48
+
49
+ ```bash
50
+ python run_gradio.py --model medium-base \
51
+ --lora-ckpt-path my_style.safetensors squeakfix_v3.safetensors
52
+ ```
53
+
54
+ Directly on the autoencoder:
55
+
56
+ ```python
57
+ from stable_audio_3 import AutoencoderModel
58
+ from stable_audio_3.models.lora.loader import load_and_apply_loras
59
+
60
+ ae = AutoencoderModel.from_pretrained("same-l", device="cuda").autoencoder
61
+ load_and_apply_loras(ae, ["squeakfix_v3.safetensors"], "autoencoder")
62
+
63
+ latents = ae.encode(waveform)
64
+ audio = ae.decode(latents)
65
+ ```
66
+
67
+ Strength is a **separate call** β€” `lora_configs` at inference only gates the
68
+ sigma interval and layer filter:
69
+
70
+ ```python
71
+ from stable_audio_3.models.lora.model import set_lora_strength
72
+ set_lora_strength(ae.decoder, 1.0) # 0.0 renders at the stock decode
73
+ ```
74
+
75
+ Ship at strength **1.0**. It was trained there and it is where it was auditioned.
76
+
77
+ ---
78
+
79
+ ## What it fixes
80
+
81
+ SAME downsamples 44.1 kHz stereo by 4096Γ—, so there is one latent frame per
82
+ 93 ms and a snare attack lives entirely inside a single frame. The decoder does
83
+ not reconstruct that attack β€” it resynthesizes one, slightly differently every
84
+ pass.
85
+
86
+ A single generation is fine. The problem is **feedback**: a continuation
87
+ re-encodes previously decoded audio, so N chained continuations put the audio
88
+ through N round trips. Measured on the round-trip ladder with no DiT involved,
89
+ invented HF energy climbs ~15 dB over six iterations while lost HF stays flat,
90
+ and every one of the twelve worst frames lands within 35 ms of a detected onset.
91
+
92
+ Nothing in SAME's training objective ever asked that `encode(decode(z)) β‰ˆ z` β€”
93
+ every loss is `real audio β†’ latent β†’ real audio` β€” so round-trip idempotence has
94
+ no reason to hold, and it does not. This adapter adds that objective after the
95
+ fact, on the decoder only.
96
+
97
+ ### Measured effect
98
+
99
+ **The win is at re-encode depth.** Every continuation and every transform
100
+ re-encodes previously decoded audio, so a chained session compounds. Measured on
101
+ audio the model generated (medium + a DiT LoRA), the same latents decoded through
102
+ each adapter β€” HF tonality, i.e. spectral peakiness, which is what "the hi-hat
103
+ became a whistle" looks like numerically:
104
+
105
+ | | tonal p95 at 1x | after 3 re-encodes | cost of depth |
106
+ |---|---|---|---|
107
+ | stock | 8.09 | 12.80 | **+4.71** |
108
+ | `squeakfix_v3` | 8.29 | 9.06 | **+0.78** |
109
+
110
+ The adapter cuts degradation-per-re-encode by ~83%. Chained continuations are
111
+ where it earns its place.
112
+
113
+ **At 1Γ— this metric is flat** (8.29 vs 8.09 β€” slightly worse, inside the noise).
114
+ A subtle improvement on single generations is reported by ear, and it is
115
+ plausible that it lives in pops and transient smear rather than tonality, but it
116
+ is not something these numbers demonstrate. Treat 1Γ— as neutral and the re-encode
117
+ behaviour as the reason to use this.
118
+
119
+ On the round-trip ladder against real held-out audio, which is the eval the
120
+ checkpoint was selected against:
121
+
122
+ | metric | stock | `squeakfix_v3` | Ξ” |
123
+ |---|---|---|---|
124
+ | tonality p95 | 17.08 | **9.41** | βˆ’7.67 |
125
+ | transient excess (dB) | 6.32 | **1.24** | βˆ’5.08 |
126
+ | latent drift per round trip | 10.91 % | **5.85 %** | βˆ’5.06 pp |
127
+ | onset artifact (dB) | βˆ’3.50 | βˆ’7.53 | βˆ’4.03 |
128
+
129
+ `transient excess` is added-HF on transient frames minus that on sustained
130
+ frames; positive means the artifact rides percussion, which is its signature.
131
+
132
+ ---
133
+
134
+ ## Honest limits
135
+
136
+ **Any decoder LoRA trained this way stamps a comb into the output β€” this one
137
+ doesn't, and that is the whole reason it exists.** The autoencoder's un-patch is
138
+ a bare reshape at `patch_size 256`, so output channel index and
139
+ time-position-within-patch are the same axis, and any channel-wise bias the
140
+ adapter learns is repeated identically in every patch. That is a harmonic comb at
141
+ `sr/256 = 172.27 Hz`, with an F3 fundamental β€” it reads as a wrong note, not as
142
+ noise. It is inaudible in a mix and obvious once a stem separator strips the
143
+ masking content, which is how it was found.
144
+
145
+ `squeakfix_v3` was trained with an explicit penalty on that structure
146
+ (`--lambda_patch 30`). A `v1` trained identically *without* it is the control.
147
+
148
+ Measured on the distribution that matters β€” audio **generated by the model
149
+ itself** (medium + a DiT LoRA), the same latents decoded through each adapter, so
150
+ the decoder is the only variable. Comb excess in dB over a control comb at
151
+ meaningless spacing, mean of 4 generations:
152
+
153
+ | variant | comb excess | vs stock |
154
+ |---|---|---|
155
+ | stock | 2.80 | β€” |
156
+ | v1 @ strength 1 | 13.70 | **+10.90** |
157
+ | **v3 @ strength 1** | 1.97 | **βˆ’0.83** |
158
+ | stock, +3 round trips | 1.64 | βˆ’1.17 |
159
+ | v1 @ 1, +3 round trips | 13.34 | +10.54 |
160
+ | **v3 @ 1, +3 round trips** | 1.37 | **βˆ’1.43** |
161
+ | v1 @ strength 2 | 18.52 | +15.72 |
162
+ | **v3 @ strength 2** | 3.49 | **+0.68** |
163
+
164
+ v1 adds ~11 dB of comb. **v3 sits at or slightly below stock**, and stays there
165
+ under re-encoding. Even at strength 2 β€” double what it ships at, where every
166
+ effect is 2–4Γ— clearer β€” it is within 0.7 dB of stock, while v1 is nearly 16 dB
167
+ above it.
168
+
169
+ One caveat for anyone reproducing this: on **real** audio pushed round the
170
+ autoencoder, rather than on model output, v3 measures +1.5 to +4.0 dB of comb
171
+ excess instead of ~0. Real music and model output are different distributions and
172
+ the artifact does not behave the same on both. Measure on generated audio β€” that
173
+ is what the decoder is actually asked to render, and it is where the artifact was
174
+ audible in the first place.
175
+
176
+ Other things worth knowing:
177
+
178
+ - **This is one checkpoint from one dataset**, and it was selected partly by ear.
179
+ The in-loop ladder kept improving past step 2000; step 2000 is what was chosen
180
+ on re-encode behaviour and listening. Your material may want a different one.
181
+ - **The squeaks it targets are partly an upstream prompt-distribution problem.**
182
+ Out-of-distribution prompts produce far more of the offending frames than
183
+ in-distribution ones. This adapter reduces the artifact; it does not make
184
+ prompt choice irrelevant.
185
+ - **It is a SAME-L adapter.** SAME-S has the same patch grid but its artifact
186
+ sits in a different band (1–8 kHz rather than 6 kHz and up) and wants a
187
+ different recipe. Loading this on SAME-S will not error β€” it will just sound
188
+ wrong.
189
+ - **Neither half of the autoencoder is bit-deterministic** (encoder 1.5 %
190
+ relative, decoder 7e-3 max abs). Any A/B you run against this adapter has to be
191
+ read as a multiple of those floors; absolute tolerances are meaningless.
192
+
193
+ ---
194
+
195
+ ## Training
196
+
197
+ | | |
198
+ |---|---|
199
+ | base model | `stabilityai/SAME-L` |
200
+ | target | `decoder` (encoder frozen) |
201
+ | rank / alpha | 16 / 16.0 |
202
+ | trainable | 5.63M params, 98 tensors (~1.30 % of the decoder) |
203
+ | checkpoint | step 2000 of a run configured for 8000, stopped at 4000 |
204
+ | precision | fp32 training, fp16 storage |
205
+ | hardware | single GB10 (DGX Spark), ~2.9 s/step at 10 s crops, under 10 GB |
206
+
207
+ ```bash
208
+ python scripts/train_decoder_lora.py \
209
+ --model same-l --rank 16 --steps 8000 --lr 1e-4 \
210
+ --w_real 0.4 --w_drift 0.3 --w_dit 0.3 \
211
+ --lambda_cycle 10.0 --lambda_tonal 0.3 --lambda_patch 30 \
212
+ --patch_size 256 --crop_seconds 10 --seed 0 \
213
+ --dit_latent_dir out/dit_latents \
214
+ --data_dir /path/to/audio --eval_audio /path/to/holdout.wav \
215
+ --out_dir out/declora
216
+ ```
217
+
218
+ The objective is self-supervised β€” audio only, no captions, no paired data.
219
+ Latents come from three buckets: real audio, drifted audio (`E(D(E(x)))` at depth
220
+ β‰₯ 1, targeted against the **original** audio so the decoder is asked to undo
221
+ accumulated drift), and latents sampled from the base DiT. The DiT bucket earns
222
+ its place because generated latents drift 15–18.5 % against real audio's 10.5 %,
223
+ and that gap is in the base model rather than in any adapter.
224
+
225
+ Losses: multi-resolution log-STFT L1 (K-weighted, kept deliberately β€” this
226
+ decoder over-generates HF, so removing the perceptual de-emphasis would push the
227
+ wrong way), relative round-trip consistency `β€–E(D(z)) βˆ’ zβ€–/β€–zβ€–` with the encoder
228
+ frozen, a **one-sided** HF tonality penalty (so legitimate cymbal ring and
229
+ sibilance are never punished), and the patch-grid penalty described above. No
230
+ discriminator: adversarial training makes a decoder invent *more* detail, and the
231
+ failure mode of plain reconstruction losses is the direction this wants.
232
+
233
+ Full method, ablations and traps: [Decoder LoRA
234
+ workflow](https://github.com/Stability-AI/stable-audio-3/blob/main/docs/workflows/decoder-lora.md).
235
+
236
+ ---
237
+
238
+ ## Files
239
+
240
+ | file | what it is |
241
+ |---|---|
242
+ | `squeakfix_v3.safetensors` | the adapter β€” SAME-L decoder, rank 16, trained with `--lambda_patch 30` |
243
+
244
+ Provenance (base model, step, full recipe) is embedded in the file's
245
+ `lora_config` metadata, so it identifies itself without this card.
246
+
247
+ The `v1` column in the tables above is an internal checkpoint trained on the
248
+ identical recipe with `--lambda_patch 0`. It is not published β€” it is reported
249
+ because "the patch penalty matters" is a claim that needs the control.
250
+
251
+ ## Citation
252
+
253
+ The autoencoder this adapts: [SAME](https://arxiv.org/abs/2605.18613).
squeakfix_v3.safetensors ADDED
@@ -0,0 +1,3 @@
 
 
 
 
1
+ version https://git-lfs.github.com/spec/v1
2
+ oid sha256:99942d64e822138fc67445d3c664f31c714ca62cf5d9a21b20ba33a41d9e99ed
3
+ size 11278296