Upload magenta_rt/torch/spectrostream.py with huggingface_hub
Browse files
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
|