dskill/DiffRhythm
2
1"""2ein notation:3b - batch4n - sequence5nt - text sequence6nw - raw wave length7d - dimension8"""9 10from __future__ import annotations11from typing import Optional12import math13 14import torch15from torch import nn16import torch17import torch.nn.functional as F18import torchaudio19 20from x_transformers.x_transformers import apply_rotary_pos_emb21 22 23 24class FiLMLayer(nn.Module):25 """26 Feature-wise Linear Modulation (FiLM) layer27 Reference: https://arxiv.org/abs/1709.0787128 """29 def __init__(self, in_channels, cond_channels):30 31 super(FiLMLayer, self).__init__()32 self.in_channels = in_channels33 self.film = nn.Conv1d(cond_channels, in_channels * 2, 1)34 35 def forward(self, x, c):36 gamma, beta = torch.chunk(self.film(c.unsqueeze(2)), chunks=2, dim=1)37 gamma = gamma.transpose(1, 2)38 beta = beta.transpose(1, 2)39 # print(gamma.shape, beta.shape)40 return gamma * x + beta41 42# raw wav to mel spec43 44 45class MelSpec(nn.Module):46 def __init__(47 self,48 filter_length=1024,49 hop_length=256,50 win_length=1024,51 n_mel_channels=100,52 target_sample_rate=24_000,53 normalize=False,54 power=1,55 norm=None,56 center=True,57 ):58 super().__init__()59 self.n_mel_channels = n_mel_channels60 61 self.mel_stft = torchaudio.transforms.MelSpectrogram(62 sample_rate=target_sample_rate,63 n_fft=filter_length,64 win_length=win_length,65 hop_length=hop_length,66 n_mels=n_mel_channels,67 power=power,68 center=center,69 normalized=normalize,70 norm=norm,71 )72 73 self.register_buffer("dummy", torch.tensor(0), persistent=False)74 75 def forward(self, inp):76 if len(inp.shape) == 3:77 inp = inp.squeeze(1) # 'b 1 nw -> b nw'78 79 assert len(inp.shape) == 280 81 if self.dummy.device != inp.device:82 self.to(inp.device)83 84 mel = self.mel_stft(inp)85 mel = mel.clamp(min=1e-5).log()86 return mel87 88 89# sinusoidal position embedding90 91 92class SinusPositionEmbedding(nn.Module):93 def __init__(self, dim):94 super().__init__()95 self.dim = dim96 97 def forward(self, x, scale=1000):98 device = x.device99 half_dim = self.dim // 2100 emb = math.log(10000) / (half_dim - 1)101 emb = torch.exp(torch.arange(half_dim, device=device).float() * -emb)102 emb = scale * x.unsqueeze(1) * emb.unsqueeze(0)103 emb = torch.cat((emb.sin(), emb.cos()), dim=-1)104 return emb105 106 107# convolutional position embedding108 109 110class ConvPositionEmbedding(nn.Module):111 def __init__(self, dim, kernel_size=31, groups=16):112 super().__init__()113 assert kernel_size % 2 != 0114 self.conv1d = nn.Sequential(115 nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2),116 nn.Mish(),117 nn.Conv1d(dim, dim, kernel_size, groups=groups, padding=kernel_size // 2),118 nn.Mish(),119 )120 121 def forward(self, x: float["b n d"], mask: bool["b n"] | None = None): # noqa: F722122 if mask is not None:123 mask = mask[..., None]124 x = x.masked_fill(~mask, 0.0)125 126 x = x.permute(0, 2, 1)127 x = self.conv1d(x)128 out = x.permute(0, 2, 1)129 130 if mask is not None:131 out = out.masked_fill(~mask, 0.0)132 133 return out134 135 136# rotary positional embedding related137 138 139def precompute_freqs_cis(dim: int, end: int, theta: float = 10000.0, theta_rescale_factor=1.0):140 # proposed by reddit user bloc97, to rescale rotary embeddings to longer sequence length without fine-tuning141 # has some connection to NTK literature142 # https://www.reddit.com/r/LocalLLaMA/comments/14lz7j5/ntkaware_scaled_rope_allows_llama_models_to_have/143 # https://github.com/lucidrains/rotary-embedding-torch/blob/main/rotary_embedding_torch/rotary_embedding_torch.py144 theta *= theta_rescale_factor ** (dim / (dim - 2))145 freqs = 1.0 / (theta ** (torch.arange(0, dim, 2)[: (dim // 2)].float() / dim))146 t = torch.arange(end, device=freqs.device) # type: ignore147 freqs = torch.outer(t, freqs).float() # type: ignore148 freqs_cos = torch.cos(freqs) # real part149 freqs_sin = torch.sin(freqs) # imaginary part150 return torch.cat([freqs_cos, freqs_sin], dim=-1)151 152 153def get_pos_embed_indices(start, length, max_pos, scale=1.0):154 # length = length if isinstance(length, int) else length.max()155 scale = scale * torch.ones_like(start, dtype=torch.float32) # in case scale is a scalar156 pos = (157 start.unsqueeze(1)158 + (torch.arange(length, device=start.device, dtype=torch.float32).unsqueeze(0) * scale.unsqueeze(1)).long()159 )160 # avoid extra long error.161 pos = torch.where(pos < max_pos, pos, max_pos - 1)162 return pos163 164 165# Global Response Normalization layer (Instance Normalization ?)166 167 168class GRN(nn.Module):169 def __init__(self, dim):170 super().__init__()171 self.gamma = nn.Parameter(torch.zeros(1, 1, dim))172 self.beta = nn.Parameter(torch.zeros(1, 1, dim))173 174 def forward(self, x):175 Gx = torch.norm(x, p=2, dim=1, keepdim=True)176 Nx = Gx / (Gx.mean(dim=-1, keepdim=True) + 1e-6)177 return self.gamma * (x * Nx) + self.beta + x178 179 180# ConvNeXt-V2 Block https://github.com/facebookresearch/ConvNeXt-V2/blob/main/models/convnextv2.py181# ref: https://github.com/bfs18/e2_tts/blob/main/rfwave/modules.py#L108182 183 184class ConvNeXtV2Block(nn.Module):185 def __init__(186 self,187 dim: int,188 intermediate_dim: int,189 dilation: int = 1,190 ):191 super().__init__()192 padding = (dilation * (7 - 1)) // 2193 self.dwconv = nn.Conv1d(194 dim, dim, kernel_size=7, padding=padding, groups=dim, dilation=dilation195 ) # depthwise conv196 self.norm = nn.LayerNorm(dim, eps=1e-6)197 self.pwconv1 = nn.Linear(dim, intermediate_dim) # pointwise/1x1 convs, implemented with linear layers198 self.act = nn.GELU()199 self.grn = GRN(intermediate_dim)200 self.pwconv2 = nn.Linear(intermediate_dim, dim)201 202 def forward(self, x: torch.Tensor) -> torch.Tensor:203 residual = x204 x = x.transpose(1, 2) # b n d -> b d n205 x = self.dwconv(x)206 x = x.transpose(1, 2) # b d n -> b n d207 x = self.norm(x)208 x = self.pwconv1(x)209 x = self.act(x)210 x = self.grn(x)211 x = self.pwconv2(x)212 return residual + x213 214 215# AdaLayerNormZero216# return with modulated x for attn input, and params for later mlp modulation217 218 219class AdaLayerNormZero(nn.Module):220 def __init__(self, dim):221 super().__init__()222 223 self.silu = nn.SiLU()224 self.linear = nn.Linear(dim, dim * 6)225 226 self.norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)227 228 def forward(self, x, emb=None):229 emb = self.linear(self.silu(emb))230 shift_msa, scale_msa, gate_msa, shift_mlp, scale_mlp, gate_mlp = torch.chunk(emb, 6, dim=1)231 232 x = self.norm(x) * (1 + scale_msa[:, None]) + shift_msa[:, None]233 return x, gate_msa, shift_mlp, scale_mlp, gate_mlp234 235 236# AdaLayerNormZero for final layer237# return only with modulated x for attn input, cuz no more mlp modulation238 239 240class AdaLayerNormZero_Final(nn.Module):241 def __init__(self, dim, cond_dim):242 super().__init__()243 244 self.silu = nn.SiLU()245 self.linear = nn.Linear(cond_dim, dim * 2)246 247 self.norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)248 249 def forward(self, x, emb):250 emb = self.linear(self.silu(emb))251 scale, shift = torch.chunk(emb, 2, dim=1)252 253 x = self.norm(x) * (1 + scale)[:, None, :] + shift[:, None, :]254 return x255 256 257# FeedForward258 259 260class FeedForward(nn.Module):261 def __init__(self, dim, dim_out=None, mult=4, dropout=0.0, approximate: str = "none"):262 super().__init__()263 inner_dim = int(dim * mult)264 dim_out = dim_out if dim_out is not None else dim265 266 activation = nn.GELU(approximate=approximate)267 #activation = nn.SiLU()268 project_in = nn.Sequential(nn.Linear(dim, inner_dim), activation)269 self.ff = nn.Sequential(project_in, nn.Dropout(dropout), nn.Linear(inner_dim, dim_out))270 271 def forward(self, x):272 return self.ff(x)273 274 275# Attention with possible joint part276# modified from diffusers/src/diffusers/models/attention_processor.py277 278 279class Attention(nn.Module):280 def __init__(281 self,282 processor: JointAttnProcessor | AttnProcessor,283 dim: int,284 heads: int = 8,285 dim_head: int = 64,286 dropout: float = 0.0,287 context_dim: Optional[int] = None, # if not None -> joint attention288 context_pre_only=None,289 ):290 super().__init__()291 292 if not hasattr(F, "scaled_dot_product_attention"):293 raise ImportError("Attention equires PyTorch 2.0, to use it, please upgrade PyTorch to 2.0.")294 295 self.processor = processor296 297 self.dim = dim298 self.heads = heads299 self.inner_dim = dim_head * heads300 self.dropout = dropout301 302 self.context_dim = context_dim303 self.context_pre_only = context_pre_only304 305 self.to_q = nn.Linear(dim, self.inner_dim)306 self.to_k = nn.Linear(dim, self.inner_dim)307 self.to_v = nn.Linear(dim, self.inner_dim)308 309 if self.context_dim is not None:310 self.to_k_c = nn.Linear(context_dim, self.inner_dim)311 self.to_v_c = nn.Linear(context_dim, self.inner_dim)312 if self.context_pre_only is not None:313 self.to_q_c = nn.Linear(context_dim, self.inner_dim)314 315 self.to_out = nn.ModuleList([])316 self.to_out.append(nn.Linear(self.inner_dim, dim))317 self.to_out.append(nn.Dropout(dropout))318 319 if self.context_pre_only is not None and not self.context_pre_only:320 self.to_out_c = nn.Linear(self.inner_dim, dim)321 322 def forward(323 self,324 x: float["b n d"], # noised input x # noqa: F722325 c: float["b n d"] = None, # context c # noqa: F722326 mask: bool["b n"] | None = None, # noqa: F722327 rope=None, # rotary position embedding for x328 c_rope=None, # rotary position embedding for c329 ) -> torch.Tensor:330 if c is not None:331 return self.processor(self, x, c=c, mask=mask, rope=rope, c_rope=c_rope)332 else:333 return self.processor(self, x, mask=mask, rope=rope)334 335 336# Attention processor337 338 339class AttnProcessor:340 def __init__(self):341 pass342 343 def __call__(344 self,345 attn: Attention,346 x: float["b n d"], # noised input x # noqa: F722347 mask: bool["b n"] | None = None, # noqa: F722348 rope=None, # rotary position embedding349 ) -> torch.FloatTensor:350 batch_size = x.shape[0]351 352 # `sample` projections.353 query = attn.to_q(x)354 key = attn.to_k(x)355 value = attn.to_v(x)356 357 # apply rotary position embedding358 if rope is not None:359 freqs, xpos_scale = rope360 q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0)361 362 query = apply_rotary_pos_emb(query, freqs, q_xpos_scale)363 key = apply_rotary_pos_emb(key, freqs, k_xpos_scale)364 365 # attention366 inner_dim = key.shape[-1]367 head_dim = inner_dim // attn.heads368 query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)369 key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)370 value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)371 372 # mask. e.g. inference got a batch with different target durations, mask out the padding373 if mask is not None:374 attn_mask = mask375 attn_mask = attn_mask.unsqueeze(1).unsqueeze(1) # 'b n -> b 1 1 n'376 attn_mask = attn_mask.expand(batch_size, attn.heads, query.shape[-2], key.shape[-2])377 else:378 attn_mask = None379 380 x = F.scaled_dot_product_attention(query, key, value, attn_mask=attn_mask, dropout_p=0.0, is_causal=False)381 x = x.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim)382 x = x.to(query.dtype)383 384 # linear proj385 x = attn.to_out[0](x)386 # dropout387 x = attn.to_out[1](x)388 389 if mask is not None:390 mask = mask.unsqueeze(-1)391 x = x.masked_fill(~mask, 0.0)392 393 return x394 395 396# Joint Attention processor for MM-DiT397# modified from diffusers/src/diffusers/models/attention_processor.py398 399 400class JointAttnProcessor:401 def __init__(self):402 pass403 404 def __call__(405 self,406 attn: Attention,407 x: float["b n d"], # noised input x # noqa: F722408 c: float["b nt d"] = None, # context c, here text # noqa: F722409 mask: bool["b n"] | None = None, # noqa: F722410 rope=None, # rotary position embedding for x411 c_rope=None, # rotary position embedding for c412 ) -> torch.FloatTensor:413 residual = x414 415 batch_size = c.shape[0]416 417 # `sample` projections.418 query = attn.to_q(x)419 key = attn.to_k(x)420 value = attn.to_v(x)421 422 # `context` projections.423 c_query = attn.to_q_c(c)424 c_key = attn.to_k_c(c)425 c_value = attn.to_v_c(c)426 427 # apply rope for context and noised input independently428 if rope is not None:429 freqs, xpos_scale = rope430 q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0)431 query = apply_rotary_pos_emb(query, freqs, q_xpos_scale)432 key = apply_rotary_pos_emb(key, freqs, k_xpos_scale)433 if c_rope is not None:434 freqs, xpos_scale = c_rope435 q_xpos_scale, k_xpos_scale = (xpos_scale, xpos_scale**-1.0) if xpos_scale is not None else (1.0, 1.0)436 c_query = apply_rotary_pos_emb(c_query, freqs, q_xpos_scale)437 c_key = apply_rotary_pos_emb(c_key, freqs, k_xpos_scale)438 439 # attention440 query = torch.cat([query, c_query], dim=1)441 key = torch.cat([key, c_key], dim=1)442 value = torch.cat([value, c_value], dim=1)443 444 inner_dim = key.shape[-1]445 head_dim = inner_dim // attn.heads446 query = query.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)447 key = key.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)448 value = value.view(batch_size, -1, attn.heads, head_dim).transpose(1, 2)449 450 # mask. e.g. inference got a batch with different target durations, mask out the padding451 if mask is not None:452 attn_mask = F.pad(mask, (0, c.shape[1]), value=True) # no mask for c (text)453 attn_mask = attn_mask.unsqueeze(1).unsqueeze(1) # 'b n -> b 1 1 n'454 attn_mask = attn_mask.expand(batch_size, attn.heads, query.shape[-2], key.shape[-2])455 else:456 attn_mask = None457 458 x = F.scaled_dot_product_attention(query, key, value, attn_mask=attn_mask, dropout_p=0.0, is_causal=False)459 x = x.transpose(1, 2).reshape(batch_size, -1, attn.heads * head_dim)460 x = x.to(query.dtype)461 462 # Split the attention outputs.463 x, c = (464 x[:, : residual.shape[1]],465 x[:, residual.shape[1] :],466 )467 468 # linear proj469 x = attn.to_out[0](x)470 # dropout471 x = attn.to_out[1](x)472 if not attn.context_pre_only:473 c = attn.to_out_c(c)474 475 if mask is not None:476 mask = mask.unsqueeze(-1)477 x = x.masked_fill(~mask, 0.0)478 # c = c.masked_fill(~mask, 0.) # no mask for c (text)479 480 return x, c481 482 483# DiT Block484 485 486class DiTBlock(nn.Module):487 def __init__(self, dim, heads, dim_head, ff_mult=4, dropout=0.1, use_style_prompt=False):488 super().__init__()489 490 self.attn_norm = AdaLayerNormZero(dim)491 self.attn = Attention(492 processor=AttnProcessor(),493 dim=dim,494 heads=heads,495 dim_head=dim_head,496 dropout=dropout,497 )498 499 self.ff_norm = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)500 self.ff = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh")501 502 self.use_style_prompt = use_style_prompt503 if use_style_prompt:504 #self.film = FiLMLayer(dim, dim)505 self.prompt_norm = AdaLayerNormZero_Final(dim)506 507 def forward(self, x, t, c=None, mask=None, rope=None): # x: noised input, t: time embedding508 if c is not None and self.use_style_prompt:509 #x = self.film(x, c)510 x = self.prompt_norm(x, c)511 512 # pre-norm & modulation for attention input513 norm, gate_msa, shift_mlp, scale_mlp, gate_mlp = self.attn_norm(x, emb=t)514 515 # attention516 attn_output = self.attn(x=norm, mask=mask, rope=rope)517 518 # process attention output for input x519 x = x + gate_msa.unsqueeze(1) * attn_output520 521 norm = self.ff_norm(x) * (1 + scale_mlp[:, None]) + shift_mlp[:, None]522 ff_output = self.ff(norm)523 x = x + gate_mlp.unsqueeze(1) * ff_output524 525 return x526 527 528# MMDiT Block https://arxiv.org/abs/2403.03206529 530 531class MMDiTBlock(nn.Module):532 r"""533 modified from diffusers/src/diffusers/models/attention.py534 535 notes.536 _c: context related. text, cond, etc. (left part in sd3 fig2.b)537 _x: noised input related. (right part)538 context_pre_only: last layer only do prenorm + modulation cuz no more ffn539 """540 541 def __init__(self, dim, heads, dim_head, ff_mult=4, dropout=0.1, context_pre_only=False):542 super().__init__()543 544 self.context_pre_only = context_pre_only545 546 self.attn_norm_c = AdaLayerNormZero_Final(dim) if context_pre_only else AdaLayerNormZero(dim)547 self.attn_norm_x = AdaLayerNormZero(dim)548 self.attn = Attention(549 processor=JointAttnProcessor(),550 dim=dim,551 heads=heads,552 dim_head=dim_head,553 dropout=dropout,554 context_dim=dim,555 context_pre_only=context_pre_only,556 )557 558 if not context_pre_only:559 self.ff_norm_c = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)560 self.ff_c = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh")561 else:562 self.ff_norm_c = None563 self.ff_c = None564 self.ff_norm_x = nn.LayerNorm(dim, elementwise_affine=False, eps=1e-6)565 self.ff_x = FeedForward(dim=dim, mult=ff_mult, dropout=dropout, approximate="tanh")566 567 def forward(self, x, c, t, mask=None, rope=None, c_rope=None): # x: noised input, c: context, t: time embedding568 # pre-norm & modulation for attention input569 if self.context_pre_only:570 norm_c = self.attn_norm_c(c, t)571 else:572 norm_c, c_gate_msa, c_shift_mlp, c_scale_mlp, c_gate_mlp = self.attn_norm_c(c, emb=t)573 norm_x, x_gate_msa, x_shift_mlp, x_scale_mlp, x_gate_mlp = self.attn_norm_x(x, emb=t)574 575 # attention576 x_attn_output, c_attn_output = self.attn(x=norm_x, c=norm_c, mask=mask, rope=rope, c_rope=c_rope)577 578 # process attention output for context c579 if self.context_pre_only:580 c = None581 else: # if not last layer582 c = c + c_gate_msa.unsqueeze(1) * c_attn_output583 584 norm_c = self.ff_norm_c(c) * (1 + c_scale_mlp[:, None]) + c_shift_mlp[:, None]585 c_ff_output = self.ff_c(norm_c)586 c = c + c_gate_mlp.unsqueeze(1) * c_ff_output587 588 # process attention output for input x589 x = x + x_gate_msa.unsqueeze(1) * x_attn_output590 591 norm_x = self.ff_norm_x(x) * (1 + x_scale_mlp[:, None]) + x_shift_mlp[:, None]592 x_ff_output = self.ff_x(norm_x)593 x = x + x_gate_mlp.unsqueeze(1) * x_ff_output594 595 return c, x596 597 598# time step conditioning embedding599 600 601class TimestepEmbedding(nn.Module):602 def __init__(self, dim, freq_embed_dim=256):603 super().__init__()604 self.time_embed = SinusPositionEmbedding(freq_embed_dim)605 self.time_mlp = nn.Sequential(nn.Linear(freq_embed_dim, dim), nn.SiLU(), nn.Linear(dim, dim))606 607 def forward(self, timestep: float["b"]): # noqa: F821608 time_hidden = self.time_embed(timestep)609 time_hidden = time_hidden.to(timestep.dtype)610 time = self.time_mlp(time_hidden) # b d611 return time612 