multimodalart HF Staff commited on
Commit
beb59ca
·
verified ·
1 Parent(s): a0edc57

Upload magenta_rt/torch/spectrostream.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. magenta_rt/torch/spectrostream.py +94 -0
magenta_rt/torch/spectrostream.py CHANGED
@@ -222,6 +222,100 @@ class SpectroStreamDecoder(nn.Module):
222
  x = self.decode_embeddings(emb)
223
  return self._istft(x)
224
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
225
  def _istft(self, x):
226
  v = x.permute(0, 2, 3, 1).contiguous() # [b,T,480,4]
227
  b, T, nb, nc = v.shape
 
222
  x = self.decode_embeddings(emb)
223
  return self._istft(x)
224
 
225
+ # ---- streaming decode (per-frame, stateful) — bit-exact-in-bf16 vs forward,
226
+ # FLOP-optimal (no overlap-save re-decode). state = mutable dict of caches. ----
227
+ def _s_conv2d(self, x, prefix, kh, kw, st, key, strides=(1, 1), dil=(1, 1)):
228
+ pt = _semicausal_pad(kh, strides[0], dil[0])
229
+ pf = _sym_freq_pad(kw, strides[1], dil[1])
230
+ c = st.get(key)
231
+ if c is None:
232
+ c = x.new_zeros(x.shape[0], x.shape[1], pt[0], x.shape[3])
233
+ xc = torch.cat([c, x], dim=2)
234
+ st[key] = xc[:, :, xc.shape[2] - pt[0]:, :] if pt[0] > 0 else c
235
+ xp = F.pad(xc, (pf[0], pf[1], 0, pt[1]))
236
+ w = self._g(prefix + "/conv/kernel"); b = self._g(prefix + "/conv/bias")
237
+ return F.conv2d(xp, w.permute(3, 2, 0, 1).to(x.dtype), bias=b.to(x.dtype),
238
+ stride=strides, dilation=dil)
239
+
240
+ def _s_conv_transpose(self, x, prefix, kh, kw, strides, st, key):
241
+ sh, sw = strides
242
+ pt = _transpose_pad(kh, sh, "causal"); pf = _transpose_pad(kw, sw, "same")
243
+ ctx = (pt[0] + sh - 1) // sh + 1
244
+ c = st.get(key)
245
+ if c is None:
246
+ c = x.new_zeros(x.shape[0], x.shape[1], ctx, x.shape[3])
247
+ C = x.shape[2]
248
+ xc = torch.cat([c, x], dim=2)
249
+ st[key] = xc[:, :, xc.shape[2] - ctx:, :]
250
+ xp = F.pad(_dilate2d(xc, strides), (pf[0], pf[1], pt[0], pt[1]))
251
+ w = self._g(prefix + "/conv/kernel"); b = self._g(prefix + "/conv/bias")
252
+ out = F.conv2d(xp, w.permute(3, 2, 0, 1).to(x.dtype), bias=b.to(x.dtype), stride=1)
253
+ return out[:, :, out.shape[2] - C * sh:, :]
254
+
255
+ def _s_resunit(self, x, prefix, strides, transposed, kt, st, key):
256
+ inp = x; y = elu(x)
257
+ if transposed:
258
+ kh, kw = kt
259
+ y = self._s_conv_transpose(y, prefix + "/conv2dtranspose_%dx%d" % (kh, kw), kh, kw, strides, st, key + "/ct")
260
+ else:
261
+ y = self._s_conv2d(y, prefix + "/conv2d_3x3_a", 3, 3, st, key + "/a")
262
+ y = elu(y)
263
+ y = self._s_conv2d(y, prefix + "/conv2d_3x3", 3, 3, st, key + "/b")
264
+ sc = inp
265
+ if (prefix + "/shortcut_layer/conv1x1/conv/kernel").replace("/", "__") in self.w:
266
+ sc = self._conv1x1(sc, prefix + "/shortcut_layer/conv1x1")
267
+ if strides != (1, 1):
268
+ sc = self._upsample(sc, strides)
269
+ return y + sc
270
+
271
+ def _s_decode_emb(self, emb_new, st):
272
+ b, t, _ = emb_new.shape
273
+ x = emb_new.permute(0, 2, 1).unsqueeze(-1)
274
+ main = self._conv1x1(x, "input_layer/conv1x1_first")
275
+ sc = self._conv1x1(x, "input_layer/shortcut_layer/conv1x1_b1"); sc = elu(sc)
276
+ sc = self._conv1x1(sc, "input_layer/shortcut_layer/conv1x1_b2")
277
+ x = (main + sc).squeeze(-1).view(b, INPUT_BINS, INPUT_CHANNELS, t).permute(0, 2, 3, 1)
278
+ x = self._s_resunit(x, "input_layers_residual_unit", (1, 1), False, None, st, "ilru")
279
+ rev = RATIOS[::-1]
280
+ x = self._s_resunit(x, "decoder_0", rev[0], True, (max(3, 2 * rev[0][0]), max(3, 2 * rev[0][1])), st, "d0")
281
+ outs = []
282
+ for gi, g in enumerate(torch.chunk(x, CHANNEL_SPLITS, dim=1)):
283
+ h = g
284
+ for i in range(1, len(RATIOS)):
285
+ s = rev[i]
286
+ h = self._s_resunit(h, f"decoder_{i}", s, True, (max(3, 2 * s[0]), max(3, 2 * s[1])), st, f"g{gi}/d{i}")
287
+ h = elu(h)
288
+ h = self._s_conv2d(h, "output_layer/base_conv_last", 7, 7, st, f"g{gi}/out")
289
+ outs.append(h)
290
+ return torch.cat(outs, dim=1)
291
+
292
+ def _s_istft(self, xnew, st):
293
+ v = xnew.permute(0, 2, 3, 1).contiguous(); b, T, nb, nc = v.shape
294
+ if T == 0:
295
+ return xnew.new_zeros(b, 0, 2)
296
+ v = F.pad(v, (0, 0, 0, 1)).float()
297
+ comp = torch.view_as_complex(v.view(b, T, 481, nc // 2, 2).contiguous())
298
+ frames = torch.fft.irfft(comp, n=FFT_LENGTH, dim=2) * self.inv_window.view(1, 1, FRAME_LENGTH, 1)
299
+ fr = frames.permute(0, 3, 1, 2)
300
+ tail = st.get("_tail")
301
+ if tail is None:
302
+ tail = fr.new_zeros(b, 2, FRAME_STEP)
303
+ emits = []
304
+ for i in range(T):
305
+ f = fr[:, :, i, :]; emits.append(tail + f[:, :, :FRAME_STEP]); tail = f[:, :, FRAME_STEP:]
306
+ st["_tail"] = tail
307
+ return torch.cat(emits, dim=2).permute(0, 2, 1)
308
+
309
+ def decode_streaming(self, emb_new, state):
310
+ """Incremental decode. `state` is a mutable dict (start with {}). Returns the
311
+ newly-available audio [b, N, 2] for `emb_new` [b, t_new, 256], carrying overlap
312
+ + per-layer conv state across calls. Output == forward(full_emb), 1 frame latency."""
313
+ x = self._s_decode_emb(emb_new, state)
314
+ wm = state.get("_warm", DECODER_LOOKAHEAD * TOTAL_TIME_STRIDE)
315
+ if wm > 0:
316
+ d = min(wm, x.shape[2]); x = x[:, :, d:, :]; state["_warm"] = wm - d
317
+ return self._s_istft(x, state)
318
+
319
  def _istft(self, x):
320
  v = x.permute(0, 2, 3, 1).contiguous() # [b,T,480,4]
321
  b, T, nb, nc = v.shape