Stable Audio 3
English
music
audio
autoencoder
lora
thecollabagepatch commited on
Commit
b6d7247
Β·
verified Β·
1 Parent(s): 682d98c

Rewrite model card: lead with audio, tighten prose, re-measure on screened koan ladder

Browse files
Files changed (1) hide show
  1. README.md +150 -220
README.md CHANGED
@@ -17,223 +17,176 @@ tags:
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
- ### What it sounds like
98
-
99
- Squeaks and chirps on hi hats, snares and percussion fills β€” a hat turning into a
100
- little whistle. Present on a single generation and worse every time the audio goes
101
- back through the autoencoder, which a continuation and a transform both do.
102
-
103
- ### Measured effect
104
-
105
- Tonal frames (>12 dB tonality, 6–16 kHz) on 2-minute generations, mean of 4, the
106
- decoder adapter the only variable:
107
-
108
- | depth | stock | `squeakfix_v3` | | 12–16 kHz | SI-SDR vs own d0 |
109
- |---|---|---|---|---|---|
110
- | d0 β€” fresh generation | 364 | 422 | βˆ’16% | βˆ’5.6 β†’ βˆ’5.3 | β€” |
111
- | d1 β€” one transform or continuation | 432 | 445 | βˆ’3% | βˆ’6.2 β†’ βˆ’5.5 | 14.7 β†’ 18.3 |
112
- | d2 | 821 | 519 | **37% fewer** | βˆ’6.6 β†’ βˆ’5.6 | 10.1 β†’ 13.7 |
113
- | d3 | 1665 | 619 | **63% fewer** | βˆ’7.1 β†’ βˆ’5.8 | 7.8 β†’ 11.2 |
114
-
115
- The last two columns are there because a tonal-frame count can fall for the wrong
116
- reason β€” an adapter that sands the top end posts a great count. This one does the
117
- opposite: at every depth it holds **more** 12–16 kHz energy than stock, sits
118
- marginally louder, and stays closer to its own depth-0 render, so it drifts less
119
- with depth rather than erasing what drifts. The band that drops is 8–12 kHz,
120
- where the artifact concentrates.
121
-
122
- Same shape at fp16 serving precision, on two different DiT LoRAs, at 30 s and
123
- 120 s. Because a transform and a continuation each re-encode their input,
124
- anything past the first generation already sits at dβ‰₯1 and a chained session
125
- climbs from there β€” that is where this earns its place.
126
-
127
- ### The honest gap
128
-
129
- **The squeak is clearly audible at d0 β€” hi hats and snares especially, reported
130
- by several listeners β€” and no metric here shows it.** Tried and flat or slightly
131
- negative at d0: tonality p95 in 6–16 kHz and 1–8 kHz, frame counts over 10/12/15
132
- dB, onset-locked tonality excess, fp32 and fp16, both LoRAs, both lengths.
133
-
134
- The likely reason is that the measurement has no headroom at d0: ~640 of ~10,300
135
- frames already read as tonal before any re-encoding, because cymbals and
136
- distorted guitar genuinely are tonal, and a few dozen added squeak frames cannot
137
- move a count that size. Separating artifact from content works at depth but not
138
- at d0 without a clean reference, which generated audio does not have.
139
-
140
- There is also precedent in this project for the tonality detector pointing the
141
- wrong way β€” on SAME-S the clip that sounds squeakiest scores lowest. So the d0
142
- βˆ’16% is not evidence the adapter hurts; it is a regime where this instrument does
143
- not resolve.
144
-
145
- Listen before deciding. Do not take the d0 number as the verdict.
146
-
147
- On the round-trip ladder against real held-out audio β€” the eval this checkpoint
148
- was selected against:
149
-
150
- | metric | stock | `squeakfix_v3` | Ξ” |
151
- |---|---|---|---|
152
- | tonality p95 | 17.08 | **9.41** | βˆ’7.67 |
153
- | transient excess (dB) | 6.32 | **1.24** | βˆ’5.08 |
154
- | latent drift per round trip | 10.91 % | **5.85 %** | βˆ’5.06 pp |
155
- | onset artifact (dB) | βˆ’3.50 | βˆ’7.53 | βˆ’4.03 |
156
-
157
- `transient excess` is added-HF on transient frames minus that on sustained
158
- frames; positive means the artifact rides percussion, which is its signature.
159
-
160
- ---
161
-
162
- ## Honest limits
163
-
164
- **Any decoder LoRA trained this way stamps a comb into the output β€” this one
165
- doesn't, and that is the whole reason it exists.** The autoencoder's un-patch is
166
- a bare reshape at `patch_size 256`, so output channel index and
167
- time-position-within-patch are the same axis, and any channel-wise bias the
168
- adapter learns is repeated identically in every patch. That is a harmonic comb at
169
- `sr/256 = 172.27 Hz`, with an F3 fundamental β€” it reads as a wrong note, not as
170
- noise. It is inaudible in a mix and obvious once a stem separator strips the
171
- masking content, which is how it was found.
172
-
173
- `squeakfix_v3` was trained with an explicit penalty on that structure
174
- (`--lambda_patch 30`). A `v1` trained identically *without* it is the control.
175
-
176
- Measured on the distribution that matters β€” audio **generated by the model
177
- itself** (medium + a DiT LoRA), the same latents decoded through each adapter, so
178
- the decoder is the only variable. Comb excess in dB over a control comb at
179
- meaningless spacing, mean of 4 generations:
180
-
181
- | variant | comb excess | vs stock |
182
- |---|---|---|
183
- | stock | 2.80 | β€” |
184
- | v1 @ strength 1 | 13.70 | **+10.90** |
185
- | **v3 @ strength 1** | 1.97 | **βˆ’0.83** |
186
- | stock, +3 round trips | 1.64 | βˆ’1.17 |
187
- | v1 @ 1, +3 round trips | 13.34 | +10.54 |
188
- | **v3 @ 1, +3 round trips** | 1.37 | **βˆ’1.43** |
189
- | v1 @ strength 2 | 18.52 | +15.72 |
190
- | **v3 @ strength 2** | 3.49 | **+0.68** |
191
-
192
- v1 adds ~11 dB of comb. **v3 sits at or slightly below stock**, and stays there
193
- under re-encoding. Even at strength 2 β€” double what it ships at, where every
194
- effect is 2–4Γ— clearer β€” it is within 0.7 dB of stock, while v1 is nearly 16 dB
195
- above it.
196
-
197
- One caveat for anyone reproducing this: on **real** audio pushed round the
198
- autoencoder, rather than on model output, v3 measures +1.5 to +4.0 dB of comb
199
- excess instead of ~0. Real music and model output are different distributions and
200
- the artifact does not behave the same on both. Measure on generated audio β€” that
201
- is what the decoder is actually asked to render, and it is where the artifact was
202
- audible in the first place.
203
-
204
- Other things worth knowing:
205
-
206
- - **This is one checkpoint from one dataset**, and it was selected partly by ear.
207
- The in-loop ladder kept improving past step 2000; step 2000 is what was chosen
208
- on re-encode behaviour and listening. Your material may want a different one.
209
- - **The squeaks it targets are partly an upstream prompt-distribution problem.**
210
- Out-of-distribution prompts produce far more of the offending frames than
211
- in-distribution ones. This adapter reduces the artifact; it does not make
212
  prompt choice irrelevant.
213
- - **The benefit scales with re-encode depth.** If your workflow is one-shot
214
- generation and nothing else, the measurable gain is small. If you chain
215
- continuations or transforms, it compounds in your favour.
216
- - **It is a SAME-L adapter.** SAME-S has the same patch grid but its artifact
217
- sits in a different band (1–8 kHz rather than 6 kHz and up) and wants a
218
- different recipe. Loading this on SAME-S will not error β€” it will just sound
219
- wrong.
220
  - **Neither half of the autoencoder is bit-deterministic** (encoder 1.5 %
221
- relative, decoder 7e-3 max abs). Any A/B you run against this adapter has to be
222
- read as a multiple of those floors; absolute tolerances are meaningless.
223
-
224
- ---
225
 
226
  ## Training
227
 
228
- | | |
229
- |---|---|
230
- | base model | `stabilityai/SAME-L` |
231
- | target | `decoder` (encoder frozen) |
232
- | rank / alpha | 16 / 16.0 |
233
- | trainable | 5.63M params, 98 tensors (~1.30 % of the decoder) |
234
- | checkpoint | step 2000 of a run configured for 8000, stopped at 4000 |
235
- | precision | fp32 training, fp16 storage |
236
- | hardware | single GB10 (DGX Spark), ~2.9 s/step at 10 s crops, under 10 GB |
237
 
238
  ```bash
239
  python scripts/train_decoder_lora.py \
@@ -246,39 +199,16 @@ python scripts/train_decoder_lora.py \
246
  --out_dir out/declora
247
  ```
248
 
249
- The objective is self-supervised β€” audio only, no captions, no paired data.
250
  Latents come from three buckets: real audio, drifted audio (`E(D(E(x)))` at depth
251
- β‰₯ 1, targeted against the **original** audio so the decoder is asked to undo
252
- accumulated drift), and latents sampled from the base DiT. The DiT bucket earns
253
- its place because generated latents drift 15–18.5 % against real audio's 10.5 %,
254
- and that gap is in the base model rather than in any adapter.
255
-
256
- Losses: multi-resolution log-STFT L1 (K-weighted, kept deliberately β€” this
257
- decoder over-generates HF, so removing the perceptual de-emphasis would push the
258
- wrong way), relative round-trip consistency `β€–E(D(z)) βˆ’ zβ€–/β€–zβ€–` with the encoder
259
- frozen, a **one-sided** HF tonality penalty (so legitimate cymbal ring and
260
- sibilance are never punished), and the patch-grid penalty described above. No
261
- discriminator: adversarial training makes a decoder invent *more* detail, and the
262
- failure mode of plain reconstruction losses is the direction this wants.
263
-
264
- Full method, ablations and traps: [Decoder LoRA
265
- workflow](https://github.com/Stability-AI/stable-audio-3/blob/main/docs/workflows/decoder-lora.md).
266
 
267
- ---
268
-
269
- ## Files
270
-
271
- | file | what it is |
272
- |---|---|
273
- | `squeakfix_v3.safetensors` | the adapter β€” SAME-L decoder, rank 16, trained with `--lambda_patch 30` |
274
-
275
- Provenance (base model, step, full recipe) is embedded in the file's
276
- `lora_config` metadata, so it identifies itself without this card.
277
-
278
- The `v1` column in the tables above is an internal checkpoint trained on the
279
- identical recipe with `--lambda_patch 0`. It is not published β€” it is reported
280
- because "the patch penalty matters" is a claim that needs the control.
281
-
282
- ## Citation
283
 
284
  The autoencoder this adapts: [SAME](https://arxiv.org/abs/2605.18613).
 
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 β€” the encoder is untouched, so the latent space, the DiT
21
+ and every existing DiT LoRA stay bit-compatible, and this stacks with them in any
22
+ order.
23
 
24
+ It fixes one thing: the high-frequency squeaks SAME's autoencoder manufactures on
25
+ percussion when audio goes round the encode/decode loop more than once. SAME
26
+ downsamples 44.1 kHz stereo by 4096Γ—, so a snare attack lives entirely inside a
27
+ single latent frame β€” the decoder doesn't reconstruct that attack, it
28
+ resynthesizes one, slightly differently every pass. Nothing in SAME's training
29
+ objective ever asked that `encode(decode(z)) β‰ˆ z`; every loss is
30
+ `real audio β†’ latent β†’ real audio`. This adapter adds that objective after the
31
+ fact, on the decoder only. Since a continuation or a transform re-encodes its
32
+ input, a chained session compounds the artifact β€” that's where this earns its
33
+ place.
34
 
35
+ Trained and used by [the collabage patch](https://huggingface.co/thepatch), in
36
+ production in a live `stable-audio-3` backend since 2026-08-14. Ship at
37
+ strength **1.0** β€” that's where it was trained and auditioned.
 
38
 
39
+ ## Hear it
 
40
 
41
+ Since we keep struggling to produce clean metrics surrounding this artifact, we
42
+ place these examples so you can really hear what it's doing.
43
+
44
+ Same latent, same seed, decoder adapter the only variable; every clip is 15 s,
45
+ peak-matched to βˆ’1 dBFS so level can't masquerade as quality. Generated with the
46
+ `koan` DiT LoRA on `medium`.
47
+
48
+ ### Round trips β€” where it earns its place
49
+
50
+ | | stock decoder | `squeakfix_v3` |
51
+ |---|---|---|
52
+ | **jungle** β€” fresh generation | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/jungle_stock_d0.wav"></audio> | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/jungle_v3_d0.wav"></audio> |
53
+ | **jungle** β€” after 3 round trips | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/jungle_stock_d3.wav"></audio> | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/jungle_v3_d3.wav"></audio> |
54
+ | **drums** β€” fresh generation | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/drums_stock_d0.wav"></audio> | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/drums_v3_d0.wav"></audio> |
55
+ | **drums** β€” after 3 round trips | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/drums_stock_d3.wav"></audio> | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/drums_v3_d3.wav"></audio> |
56
+ | **neurofunk** β€” fresh generation | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/neurofunk_stock_d0.wav"></audio> | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/neurofunk_v3_d0.wav"></audio> |
57
+ | **neurofunk** β€” after 3 round trips | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/neurofunk_stock_d3.wav"></audio> | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/neurofunk_v3_d3.wav"></audio> |
58
+
59
+ These three prompts were **not** selected for artifact content β€” they are
60
+ ordinary koan generations, and the fresh-generation rows are here so you can
61
+ follow the progression rather than because much is audible in them. Three round
62
+ trips is a short chained session: two continuations and a transform get you
63
+ there. jungle is the worst of the three; drums and neurofunk are unremarkable.
64
+
65
+ It isn't winning by sanding the top end, which is the easy way to fake this. At
66
+ d3 all three hold **2.0 to 9.3 dB more** 12–16 kHz and 16–22 kHz energy than the
67
+ stock render, at a higher RMS, while showing a fraction of the tonal frames. The
68
+ only band that ever drops is 8–12 kHz on the drums clip, by 0.9 dB β€” and that is
69
+ exactly where the artifact concentrates.
70
+
71
+ ### A fresh generation β€” subtler, but we do hear it
72
+
73
+ We swear we hear it on initial generations too, and it is **much** more subtle.
74
+ This pair is the worst of 16 candidates, screened by how far tonality runs away
75
+ over 3 round trips with the adapter off β€” screening is how you find an audible
76
+ A/B for something this small, and it means this pair is a worst case, not a
77
+ typical one.
78
+
79
+ | | stock decoder | `squeakfix_v3` |
80
+ |---|---|---|
81
+ | **glitch hop** β€” fresh generation, screened | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/glitchhop_stock_d0.wav"></audio> | <audio controls src="https://huggingface.co/thepatch/same-l-decoder-lora/resolve/main/samples/glitchhop_v3_d0.wav"></audio> |
82
+
83
+ What changes here is **air, not squeak count**. Across the three screened
84
+ generations the adapter moves tonality by βˆ’0.37 dB at d0 β€” nothing β€” while
85
+ restoring **1.5 to 2.4 dB** of 16–22 kHz top octave in every one. On this
86
+ particular pair tonality moves βˆ’0.08 dB, i.e. not at all, and air moves +2.4 dB.
87
+ If you are looking for the difference in a tonal-frame count you will not find
88
+ it.
89
 
90
  ## Usage
91
 
92
+ Requires `target: "decoder"` support in
93
  [Stability-AI/stable-audio-3](https://github.com/Stability-AI/stable-audio-3).
94
+ The `target` field in the checkpoint config is what routes it; there's no special
95
+ loading path.
96
 
97
  ```bash
98
+ python run_gradio.py --model medium-base --lora-ckpt-path squeakfix_v3.safetensors
 
 
 
 
99
 
100
+ # stacks with a DiT LoRA, either order
101
  python run_gradio.py --model medium-base \
102
  --lora-ckpt-path my_style.safetensors squeakfix_v3.safetensors
103
  ```
104
 
 
 
105
  ```python
106
  from stable_audio_3 import AutoencoderModel
107
  from stable_audio_3.models.lora.loader import load_and_apply_loras
108
+ from stable_audio_3.models.lora.model import set_lora_strength
109
 
110
  ae = AutoencoderModel.from_pretrained("same-l", device="cuda").autoencoder
111
  load_and_apply_loras(ae, ["squeakfix_v3.safetensors"], "autoencoder")
112
+ set_lora_strength(ae.decoder, 1.0) # separate call; 0.0 is the stock decode
113
 
114
+ audio = ae.decode(ae.encode(waveform))
 
115
  ```
116
 
117
+ ## Measured
118
+
119
+ Four `koan` generations of 2 minutes, screened from 12 candidates by how far
120
+ 6–16 kHz tonality runs away with the adapter off. Each latent is decoded twice β€”
121
+ adapter off, adapter on β€” and each chain re-encodes in place, so dN is genuinely
122
+ N round trips of that decoder config. The adapter is the only variable.
123
+
124
+ | depth | tonality p95 | tonal frames | 12–16 kHz | SI-SDR vs own d0 |
125
+ |---|---|---|---|---|
126
+ | d0 β€” fresh generation | 11.25 β†’ 11.33 | 780 β†’ 933 | 20.7 β†’ 21.4 | β€” |
127
+ | d1 β€” one continuation or transform | 12.46 β†’ **11.59** | 972 β†’ 1074 | 19.9 β†’ **21.2** | 13.5 β†’ **17.5** |
128
+ | d2 | 14.42 β†’ **11.81** | 1492 β†’ **1246** | 19.3 β†’ **21.0** | 8.9 β†’ **12.8** |
129
+ | d3 | 17.03 β†’ **12.06** | 2453 β†’ **1411** | 18.6 β†’ **20.9** | 6.7 β†’ **10.4** |
130
+
131
+ **Stock tonality climbs +5.79 dB over three round trips. With the adapter it
132
+ climbs +0.73 dB.** That holds on every generation individually β€” stock +4.98 to
133
+ +6.97, the adapter +0.18 to +1.40 β€” and it is the whole claim: the artifact
134
+ stops compounding.
135
+
136
+ **The tonal-frame column rises at d0 and d1, and that is not a regression.**
137
+ That count rewards peakiness, and the adapter puts high-frequency energy back;
138
+ restored harmonics read as tonal. It is also dominated by two of the four
139
+ generations, which start near 1000 and 2100 frames because glitchcore genuinely
140
+ is tonal. The other two start at **zero** and stay there with the adapter β€” 0 β†’
141
+ 39 and 0 β†’ 8 at d3 β€” while stock reaches 1038 and 268. Where the artifact has
142
+ room to appear, the adapter suppresses it; where the material is already tonal,
143
+ the count cannot tell artifact from content. Read p95, not the count.
144
+
145
+ **It is not sanding the top end**, which is the easy way to post a good number.
146
+ At every depth it holds more 12–16 kHz energy than stock and the gap *widens*
147
+ with depth (+0.70, +1.31, +1.76, +2.30 dB at d0–d3), while SI-SDR against its
148
+ own d0 runs 3.6 to 3.9 dB better. It drifts less rather than erasing what drifts.
149
+
150
+ At d0 the change is air, not squeak count: on a separate screened 30 s set the
151
+ adapter moves tonality by βˆ’0.37 dB β€” nothing β€” while restoring 1.5 to 2.4 dB of
152
+ 16–22 kHz top octave in all three generations. Trust the clips above over any of
153
+ these numbers.
154
+
155
+ This table is `koan` at 120 s and fp16. An earlier unscreened run covering `kev`
156
+ as well, at both 30 s and 120 s, showed the same direction at depth.
157
+
158
+ ## Limits
159
+
160
+ - **Decoder LoRAs trained this way stamp a comb into the output β€” this one
161
+ doesn't, and that's most of why it exists.** The un-patch is a bare reshape at
162
+ `patch_size 256`, so output channel and time-position-within-patch are the same
163
+ axis, and any channel-wise bias the adapter learns repeats identically in every
164
+ patch: a harmonic comb at `sr/256 = 172.27 Hz` that reads as a wrong note, not
165
+ as noise. Inaudible in a mix, obvious once a stem separator strips the masking
166
+ content, which is how it was found. `--lambda_patch 30` is what prevents it. On
167
+ model output, a `v1` control trained on the identical recipe with
168
+ `--lambda_patch 0` sits **+10.9 dB** of comb excess over stock; v3 sits
169
+ **βˆ’0.8 dB**, and both hold that gap through three further round trips. On
170
+ *real* audio rather than model output v3 measures +1.5 to +4.0 dB β€” different
171
+ distribution, so measure on generated audio.
172
+ - **SAME-L only.** SAME-S shares the patch grid but its artifact sits 1–8 kHz and
173
+ wants a different recipe. Loading this there won't error; it'll sound wrong.
174
+ - **The gain scales with re-encode depth** β€” small for one-shot generation, it
175
+ compounds across chained continuations.
176
+ - **The squeaks are partly an upstream prompt-distribution problem.** OOD prompts
177
+ produce far more offending frames; this reduces the artifact, it doesn't make
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
178
  prompt choice irrelevant.
179
+ - **One checkpoint, one dataset, chosen partly by ear** at step 2000 on re-encode
180
+ behaviour. Your material may want a different one.
 
 
 
 
 
181
  - **Neither half of the autoencoder is bit-deterministic** (encoder 1.5 %
182
+ relative, decoder 7e-3 max abs) β€” read any A/B as a multiple of those floors.
 
 
 
183
 
184
  ## Training
185
 
186
+ Self-supervised β€” audio only, no captions, no paired data. Rank 16 / alpha 16,
187
+ 5.63M trainable params (~1.30 % of the decoder), step 2000 of a run configured
188
+ for 8000, fp32 training and fp16 storage, single GB10 (DGX Spark) at ~2.9 s/step
189
+ on 10 s crops, under 10 GB.
 
 
 
 
 
190
 
191
  ```bash
192
  python scripts/train_decoder_lora.py \
 
199
  --out_dir out/declora
200
  ```
201
 
 
202
  Latents come from three buckets: real audio, drifted audio (`E(D(E(x)))` at depth
203
+ β‰₯ 1, targeted against the **original** so the decoder is asked to undo
204
+ accumulated drift), and latents sampled from the base DiT. No discriminator β€”
205
+ adversarial training makes a decoder invent *more* detail, and the failure mode
206
+ of plain reconstruction losses is the direction this wants.
 
 
 
 
 
 
 
 
 
 
 
207
 
208
+ Full method, losses, ablations and traps: [Decoder LoRA
209
+ workflow](https://github.com/Stability-AI/stable-audio-3/blob/main/docs/workflows/decoder-lora.md).
210
+ Provenance β€” base model, step, full recipe β€” is embedded in the file's
211
+ `lora_config` metadata, so the checkpoint identifies itself without this card.
212
+ `v1` (identical recipe, `--lambda_patch 0`) is an internal control, not published.
 
 
 
 
 
 
 
 
 
 
 
213
 
214
  The autoencoder this adapts: [SAME](https://arxiv.org/abs/2605.18613).