import torch, os, math from einops import rearrange, repeat from diffsynth.core import attention_forward, gradient_checkpoint_forward from transformers.models.qwen3.modeling_qwen3 import Qwen3RotaryEmbedding class TimestepEmbedding(torch.nn.Module): def __init__(self, in_channels, time_embed_dim, scale=1): super().__init__() self.linear_1 = torch.nn.Linear(in_channels, time_embed_dim, bias=True) self.act1 = torch.nn.SiLU() self.linear_2 = torch.nn.Linear(time_embed_dim, time_embed_dim, bias=True) self.in_channels = in_channels self.act2 = torch.nn.SiLU() self.time_proj = torch.nn.Linear(time_embed_dim, time_embed_dim * 6) self.scale = scale def timestep_embedding(self, t, dim, max_period=10000): t = t * self.scale half = dim // 2 freqs = torch.exp( -math.log(max_period) * torch.arange(start=0, end=half, dtype=torch.float32) / half ).to(device=t.device) args = t[:, None].float() * freqs[None] embedding = torch.cat([torch.cos(args), torch.sin(args)], dim=-1) if dim % 2: embedding = torch.cat([embedding, torch.zeros_like(embedding[:, :1])], dim=-1) return embedding def forward(self, t): t_freq = self.timestep_embedding(t, self.in_channels) temb = self.linear_1(t_freq.to(t.dtype)) temb = self.act1(temb) temb = self.linear_2(temb) timestep_proj = self.time_proj(self.act2(temb)).unflatten(1, (6, -1)) return temb, timestep_proj class DiffSynthMusicTimestepEmbedding(torch.nn.Module): def __init__(self, in_channels, time_embed_dim): super().__init__() self.time_embed = TimestepEmbedding(in_channels, time_embed_dim) self.time_embed_r = TimestepEmbedding(in_channels, time_embed_dim) def forward(self, timestep): timestep_r = timestep temb_t, timestep_proj_t = self.time_embed(timestep) temb_r, timestep_proj_r = self.time_embed_r(timestep - timestep_r) temb = temb_t + temb_r timestep_proj = timestep_proj_t + timestep_proj_r return temb, timestep_proj class DiffSynthMusicAttention(torch.nn.Module): def __init__(self, dim, num_heads_q, num_heads_kv, head_dim): super().__init__() self.head_dim = head_dim self.q_proj = torch.nn.Linear(dim, num_heads_q * self.head_dim, bias=False) self.k_proj = torch.nn.Linear(dim, num_heads_kv * self.head_dim, bias=False) self.v_proj = torch.nn.Linear(dim, num_heads_kv * self.head_dim, bias=False) self.o_proj = torch.nn.Linear(num_heads_q * self.head_dim, dim, bias=False) self.q_norm = torch.nn.RMSNorm(self.head_dim, eps=1e-6) self.k_norm = torch.nn.RMSNorm(self.head_dim, eps=1e-6) def rotate_half(self, x): x1 = x[..., : x.shape[-1] // 2] x2 = x[..., x.shape[-1] // 2 :] return torch.cat((-x2, x1), dim=-1) def apply_rotary_pos_emb(self, q, k, cos, sin, unsqueeze_dim=2): cos = cos.unsqueeze(unsqueeze_dim) sin = sin.unsqueeze(unsqueeze_dim) q_embed = (q * cos) + (self.rotate_half(q) * sin) k_embed = (k * cos) + (self.rotate_half(k) * sin) return q_embed, k_embed def forward(self, x, y=None, window_size=None, pos_emb=None, return_kv=False, kv_cache=None) -> torch.Tensor: q = self.q_proj(x) q = rearrange(q, "b s (n d) -> b s n d", d=self.head_dim) q = self.q_norm(q) if y is None: y = x k, v = self.k_proj(y), self.v_proj(y) k, v = rearrange(k, "b s (n d) -> b s n d", d=self.head_dim), rearrange(v, "b s (n d) -> b s n d", d=self.head_dim) k = self.k_norm(k) if pos_emb is not None: q, k = self.apply_rotary_pos_emb(q, k, *pos_emb) if kv_cache is not None: k = torch.concat([k, kv_cache[0]], dim=1) v = torch.concat([v, kv_cache[1]], dim=1) attn_output = attention_forward( q, k, v, q_pattern="b s n d", k_pattern="b s n d", v_pattern="b s n d", out_pattern="b s (n d)", window_size=window_size, ) attn_output = self.o_proj(attn_output) if return_kv: return attn_output, (k, v) else: return attn_output class MLP(torch.nn.Module): def __init__(self, dim, dim_hidden): super().__init__() self.gate_proj = torch.nn.Linear(dim, dim_hidden, bias=False) self.up_proj = torch.nn.Linear(dim, dim_hidden, bias=False) self.down_proj = torch.nn.Linear(dim_hidden, dim, bias=False) self.act_fn = torch.nn.SiLU() def forward(self, x): return self.down_proj(self.act_fn(self.gate_proj(x)) * self.up_proj(x)) class DiffSynthMusicDiTLayer(torch.nn.Module): def __init__(self, dim=2560, num_heads_q=32, num_heads_kv=8, head_dim=128, dim_mlp=9728, window_size=None): super().__init__() self.self_attn_norm = torch.nn.RMSNorm(dim, eps=1e-6) self.self_attn = DiffSynthMusicAttention(dim=dim, num_heads_q=num_heads_q, num_heads_kv=num_heads_kv, head_dim=head_dim) self.cross_attn_norm = torch.nn.RMSNorm(dim, eps=1e-6) self.cross_attn = DiffSynthMusicAttention(dim=dim, num_heads_q=num_heads_q, num_heads_kv=num_heads_kv, head_dim=head_dim) self.mlp_norm = torch.nn.RMSNorm(dim, eps=1e-6) self.mlp = MLP(dim, dim_mlp) self.scale_shift_table = torch.nn.Parameter(torch.randn(1, 6, dim) / dim**0.5) self.window_size = window_size def forward(self, x, y, pos_emb, temb, return_kv=False, kv_cache=None) -> torch.Tensor: shift_msa, scale_msa, gate_msa, c_shift_msa, c_scale_msa, c_gate_msa = (self.scale_shift_table.to(dtype=x.dtype, device=x.device) + temb).chunk(6, dim=1) x_hidden = self.self_attn_norm(x) * (1 + scale_msa) + shift_msa x_hidden = self.self_attn(x=x_hidden, pos_emb=pos_emb, window_size=self.window_size, kv_cache=kv_cache, return_kv=return_kv) if return_kv: x_hidden, kv = x_hidden x = x + x_hidden * gate_msa x_hidden = self.cross_attn_norm(x) x_hidden = self.cross_attn(x=x_hidden, y=y) x = x + x_hidden x_hidden = self.mlp_norm(x) * (1 + c_scale_msa) + c_shift_msa x_hidden = self.mlp(x_hidden) x = x + x_hidden * c_gate_msa if return_kv: return x, kv else: return x class DiffSynthMusicChannelProj(torch.nn.Module): def __init__(self, in_channels, out_channels, patch_size, bias=False, transposed=False): super().__init__() if transposed: self.conv = torch.nn.ConvTranspose1d(in_channels=in_channels, out_channels=out_channels, kernel_size=patch_size, stride=patch_size, bias=bias) else: self.conv = torch.nn.Conv1d(in_channels=in_channels, out_channels=out_channels, kernel_size=patch_size, stride=patch_size, bias=bias) def forward(self, x): x = x.transpose(1, 2) x = self.conv(x) x = x.transpose(1, 2) return x class DiffSynthMusicDiTModel(torch.nn.Module): def __init__(self, dim=2560, dim_mlp=9728, dim_condition=2048, num_blocks=32, num_heads_q=32, num_heads_kv=8, head_dim=128, window_size=128, patch_size=2): super().__init__() self.rotary_emb = Qwen3RotaryEmbedding(type('RopeConfig', (), {'head_dim': head_dim, 'max_position_embeddings': 32768, 'rope_theta': 1000000, 'rope_parameters': {'rope_type': 'default', 'rope_theta': 1000000}})()) self.x_emb = DiffSynthMusicChannelProj(in_channels=64*3, out_channels=dim, patch_size=patch_size, bias=True) self.timestep_emb = DiffSynthMusicTimestepEmbedding(in_channels=256, time_embed_dim=dim) self.condition_emb = torch.nn.Linear(dim_condition, dim, bias=True) self.layers = torch.nn.ModuleList([ DiffSynthMusicDiTLayer(dim=dim, num_heads_q=num_heads_q, num_heads_kv=num_heads_kv, dim_mlp=dim_mlp, window_size=window_size if block_id % 2 == 0 else None) for block_id in range(num_blocks) ]) self.norm_out = torch.nn.RMSNorm(dim, eps=1e-6) self.proj_out = DiffSynthMusicChannelProj(in_channels=dim, out_channels=64, patch_size=patch_size, bias=True, transposed=True) self.scale_shift_table = torch.nn.Parameter(torch.randn(1, 2, dim) / dim**0.5) self.placeholder_audio = torch.nn.Parameter(torch.zeros((1, 15000, 64))) def forward_kv_cache( self, x: torch.Tensor, y: torch.Tensor, use_gradient_checkpointing: bool = False, use_gradient_checkpointing_offload: bool = False, **kwargs, ): x = torch.concat([self.placeholder_audio[:, :x.shape[1]], torch.ones_like(x), x], dim=-1) x = self.x_emb(x) y = self.condition_emb(y) timestep = torch.zeros((1,), dtype=x.dtype, device=x.device) final_timestep_emb, timestep_emb = self.timestep_emb(timestep) pos_emb = self.rotary_emb(x, torch.arange(0, x.shape[1], device=x.device).unsqueeze(0)) kv_cache = {} for block_id, block in enumerate(self.layers): return_kv = block.window_size is None x = gradient_checkpoint_forward( block, use_gradient_checkpointing, use_gradient_checkpointing_offload, x, y, pos_emb, timestep_emb, return_kv=return_kv, kv_cache=None, ) if return_kv: x, kv = x kv_cache[f"{block_id}"] = kv return kv_cache def forward( self, x: torch.Tensor, y: torch.Tensor, timestep: torch.Tensor, residual: list[torch.Tensor] = None, residual_x: torch.Tensor = None, kv_cache = None, use_gradient_checkpointing: bool = False, use_gradient_checkpointing_offload: bool = False, **kwargs, ): x = torch.concat([self.placeholder_audio[:, :x.shape[1]], torch.ones_like(x), x], dim=-1) x = self.x_emb(x) if residual_x is not None: x = x + residual_x y = self.condition_emb(y) final_timestep_emb, timestep_emb = self.timestep_emb(timestep) pos_emb = self.rotary_emb(x, torch.arange(0, x.shape[1], device=x.device).unsqueeze(0)) for block_id, block in enumerate(self.layers): x = gradient_checkpoint_forward( block, use_gradient_checkpointing, use_gradient_checkpointing_offload, x, y, pos_emb, timestep_emb, return_kv=False, kv_cache=None if kv_cache is None else kv_cache.get(f"{block_id}"), ) if residual is not None: x = x + residual[block_id] shift, scale = (self.scale_shift_table.to(dtype=x.dtype, device=x.device) + final_timestep_emb.unsqueeze(1)).chunk(2, dim=1) x = self.proj_out(self.norm_out(x) * (1 + scale) + shift) return x class MusicKVCacheModel(DiffSynthMusicDiTModel): def __init__(self): super().__init__() self.y = torch.nn.Parameter(torch.zeros((1, 70, 2560))) def cut_audio(self, audio, length=1920*256): x = audio.abs().mean(axis=0) value = [] for i in range(0, len(x) - length + 1, 1*1920): value.append(x[i: i + length].mean().item()) idx = value.index(max(value)) audio = audio[:, idx * 1 * 1920: idx * 1 * 1920 + length] return audio @torch.no_grad() def process_inputs(self, pipe, audio=None, **kwargs): if audio.shape[-1] == 64: x = audio else: pipe.load_models_to_device(["vae"]) audio = self.cut_audio(audio) audio = audio.unsqueeze(0) audio = pipe.vae.encode(audio.to(dtype=pipe.torch_dtype, device=pipe.device)).transpose(1, 2) x = audio x = x.to(dtype=pipe.torch_dtype, device=pipe.device) return {"x": x} def forward( self, x: torch.Tensor, use_gradient_checkpointing: bool = False, use_gradient_checkpointing_offload: bool = False, **kwargs, ): x = torch.concat([self.placeholder_audio[:, :x.shape[1]], torch.ones_like(x), x], dim=-1) x = self.x_emb(x) y = self.y timestep = torch.zeros((1,), dtype=x.dtype, device=x.device) final_timestep_emb, timestep_emb = self.timestep_emb(timestep) pos_emb = self.rotary_emb(x, torch.arange(0, x.shape[1], device=x.device).unsqueeze(0)) kv_cache = {} for block_id, block in enumerate(self.layers): return_kv = block.window_size is None x = gradient_checkpoint_forward( block, use_gradient_checkpointing, use_gradient_checkpointing_offload, x, y, pos_emb, timestep_emb, return_kv=return_kv, kv_cache=None, ) if return_kv: x, kv = x kv_cache[f"{block_id}"] = kv return {"kv_cache": kv_cache} class DataAnnotator: def __init__(self): self.target_sample_rate = 48000 self.max_audio_duration = 480 import torchaudio self.audio_loader = torchaudio.load self.audio_resampler = torchaudio.functional.resample def load_audio(self, path): waveform, sample_rate = self.audio_loader(path) if len(waveform.shape) == 2 and waveform.shape[0] == 1: waveform = repeat(waveform, "c l -> (n c) l", n=2) if self.target_sample_rate is not None and sample_rate != self.target_sample_rate: waveform = self.audio_resampler(waveform, sample_rate, self.target_sample_rate) sample_rate = self.target_sample_rate if self.max_audio_duration is not None and waveform.shape[1] > sample_rate * self.max_audio_duration: waveform = waveform[:, :int(sample_rate * self.max_audio_duration)] return waveform def load_latents(self, path): latents = torch.load(path, weights_only=True, map_location="cpu") return latents def __call__(self, audio, **kwargs): if audio.endswith(".pth"): return {"audio": self.load_latents(audio)} else: return {"audio": self.load_audio(audio)} def initialize_model_weights(): from diffsynth import load_state_dict from safetensors.torch import save_file sd_ = MusicKVCacheModel().state_dict() sd = load_state_dict("models/DiffSynth-Music/dit_base_v4.safetensors") for i in sd_: if i in sd: sd_[i] = sd[i] elif i == "y": sd_[i] = torch.load(os.path.join(os.path.dirname(__file__), "y.pth")) else: print(i, sd_[i].shape) save_file(sd_, os.path.join(os.path.dirname(__file__), "model.safetensors")) TEMPLATE_MODEL = MusicKVCacheModel TEMPLATE_MODEL_PATH = "model.safetensors" TEMPLATE_DATA_PROCESSOR = DataAnnotator