Spaces:
Running on Zero
Running on Zero
Download vendor/model/diffwave.py from teamup-tech/DExter: direct link, hf CLI and curl.
- Browser
- Download file 12.9 kB
-
https://huggingface.co/spaces/teamup-tech/DExter/resolve/main/vendor/model/diffwave.py
- Command line
-
hf download hf://spaces/teamup-tech/DExter/vendor/model/diffwave.py
-
curl -L -o diffwave.py https://huggingface.co/spaces/teamup-tech/DExter/resolve/main/vendor/model/diffwave.py
12.9 kB
| # Copyright 2020 LMNT, Inc. All Rights Reserved. | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| # ============================================================================== | |
| import numpy as np | |
| import torch | |
| import torch.nn as nn | |
| import torch.nn.functional as F | |
| from task.diffusion import CodecDiffusion | |
| import torchaudio | |
| from model.utils import Normalization | |
| from math import sqrt | |
| Linear = nn.Linear | |
| ConvTranspose2d = nn.ConvTranspose2d | |
| def Conv1d(*args, **kwargs): | |
| layer = nn.Conv1d(*args, **kwargs) | |
| nn.init.kaiming_normal_(layer.weight) | |
| return layer | |
| def Conv2d(*args, **kwargs): | |
| layer = nn.Conv2d(*args, **kwargs) | |
| nn.init.kaiming_normal_(layer.weight) | |
| return layer | |
| def silu(x): | |
| return x * torch.sigmoid(x) | |
| class DiffusionEmbedding(nn.Module): | |
| def __init__(self, max_steps): | |
| super().__init__() | |
| self.register_buffer('embedding', self._build_embedding(max_steps), persistent=False) | |
| self.projection1 = Linear(128, 512) | |
| self.projection2 = Linear(512, 512) | |
| def forward(self, diffusion_step): | |
| if diffusion_step.dtype in [torch.int32, torch.int64]: | |
| x = self.embedding[diffusion_step] | |
| else: | |
| x = self._lerp_embedding(diffusion_step) | |
| x = self.projection1(x) | |
| x = silu(x) | |
| x = self.projection2(x) | |
| x = silu(x) | |
| return x | |
| def _lerp_embedding(self, t): | |
| low_idx = torch.floor(t).long() | |
| high_idx = torch.ceil(t).long() | |
| low = self.embedding[low_idx] | |
| high = self.embedding[high_idx] | |
| return low + (high - low) * (t - low_idx) | |
| def _build_embedding(self, max_steps): | |
| steps = torch.arange(max_steps).unsqueeze(1) # [T,1] | |
| dims = torch.arange(64).unsqueeze(0) # [1,64] | |
| table = steps * 10.0**(dims * 4.0 / 63.0) # [T,64] | |
| table = torch.cat([torch.sin(table), torch.cos(table)], dim=1) | |
| return table | |
| class ResidualBlock(nn.Module): | |
| def __init__(self, | |
| residual_channels, | |
| dilation, | |
| kernel_size=3, | |
| uncond=False, | |
| condition_rows=4): | |
| ''' | |
| :param residual_channels: audio conv | |
| :param dilation: audio conv dilation | |
| :param uncond: disable s_codec conditional | |
| ''' | |
| super().__init__() | |
| self.dilated_conv = Conv1d(residual_channels, | |
| 2 * residual_channels, | |
| kernel_size, | |
| padding=((kernel_size-1)*(dilation-1)+kernel_size-1)//2, | |
| dilation=dilation) | |
| self.diffusion_projection = Linear(512, residual_channels) | |
| if not uncond: # conditional model | |
| self.conditioner_projection = Conv1d(condition_rows, 2 * residual_channels, 1) | |
| else: # unconditional model | |
| self.conditioner_projection = None | |
| self.output_projection = Conv1d(residual_channels, 2 * residual_channels, 1) | |
| def forward(self, x, diffusion_step, conditioner=None): | |
| assert (conditioner is None and self.conditioner_projection is None) or \ | |
| (conditioner is not None and self.conditioner_projection is not None) | |
| diffusion_step = self.diffusion_projection(diffusion_step).unsqueeze(-1) | |
| y = x + diffusion_step | |
| if self.conditioner_projection is None: # using a unconditional model | |
| y = self.dilated_conv(y) | |
| else: | |
| conditioner = self.conditioner_projection(conditioner) | |
| y = self.dilated_conv(y) + conditioner | |
| gate, filter = torch.chunk(y, 2, dim=1) | |
| y = torch.sigmoid(gate) * torch.tanh(filter) | |
| y = self.output_projection(y) | |
| residual, skip = torch.chunk(y, 2, dim=1) | |
| return (x + residual) / sqrt(2.0), skip | |
| class ResidualBlockwithFilm(nn.Module): | |
| def __init__(self, | |
| residual_channels, | |
| dilation, | |
| kernel_size=3, | |
| uncond=False, | |
| condition_rows=4): | |
| ''' | |
| :param residual_channels: audio conv | |
| :param dilation: audio conv dilation | |
| :param uncond: disable s_codec conditional | |
| ''' | |
| super().__init__() | |
| self.dilated_conv = Conv1d(residual_channels, | |
| 2 * residual_channels, | |
| kernel_size, | |
| padding=((kernel_size-1)*(dilation-1)+kernel_size-1)//2, | |
| dilation=dilation) | |
| self.diffusion_projection = Linear(512, residual_channels) | |
| if not uncond: # conditional model | |
| self.conditioner_projection = Conv1d(condition_rows, 2 * residual_channels, 1) | |
| else: # unconditional model | |
| self.conditioner_projection = None | |
| self.output_projection = Conv1d(residual_channels, 2 * residual_channels, 1) | |
| def forward(self, x, diffusion_step, gamma, beta, conditioner=None): | |
| assert (conditioner is None and self.conditioner_projection is None) or \ | |
| (conditioner is not None and self.conditioner_projection is not None) | |
| diffusion_step = self.diffusion_projection(diffusion_step).unsqueeze(-1) | |
| y = x + diffusion_step | |
| if self.conditioner_projection is None: # using a unconditional model | |
| y = self.dilated_conv(y) | |
| else: | |
| conditioner = self.conditioner_projection(conditioner) | |
| y = self.dilated_conv(y) + conditioner | |
| # Insert FiLM conditions; beta and gammas for each residual layer. | |
| y = y*gamma[:, None, None] + beta[:, None, None] | |
| gate, filter = torch.chunk(y, 2, dim=1) | |
| y = torch.sigmoid(gate) * torch.tanh(filter) | |
| y = self.output_projection(y) | |
| residual, skip = torch.chunk(y, 2, dim=1) | |
| return (x + residual) / sqrt(2.0), skip | |
| class DiffWave(nn.Module): | |
| def __init__(self, params): | |
| super().__init__() | |
| self.params = params | |
| self.input_projection = Conv1d(1, params.residual_channels, 1) | |
| self.diffusion_embedding = DiffusionEmbedding(len(params.noise_schedule)) | |
| if self.params.unconditional: # use unconditional model | |
| self.spectrogram_upsampler = None | |
| else: | |
| self.spectrogram_upsampler = SpectrogramUpsampler(params.n_mels) | |
| self.residual_layers = nn.ModuleList([ | |
| ResidualBlock(params.n_mels, params.residual_channels, 2**(i % params.dilation_base), uncond=params.unconditional) | |
| for i in range(params.residual_layers) | |
| ]) | |
| self.skip_projection = Conv1d(params.residual_channels, params.residual_channels, 1) | |
| self.output_projection = Conv1d(params.residual_channels, 1, 1) | |
| nn.init.zeros_(self.output_projection.weight) | |
| def forward(self, audio, diffusion_step, spectrogram=None): | |
| assert (spectrogram is None and self.spectrogram_upsampler is None) or \ | |
| (spectrogram is not None and self.spectrogram_upsampler is not None) | |
| x = audio.unsqueeze(1) | |
| x = self.input_projection(x) | |
| x = F.relu(x) | |
| diffusion_step = self.diffusion_embedding(diffusion_step) | |
| if self.spectrogram_upsampler: # use conditional model | |
| spectrogram = self.spectrogram_upsampler(spectrogram) | |
| skip = None | |
| index = 0 | |
| for layer in self.residual_layers: | |
| index += 1 | |
| x, skip_connection = layer(x, diffusion_step, spectrogram) | |
| skip = skip_connection if skip is None else skip_connection + skip | |
| x = skip / sqrt(len(self.residual_layers)) | |
| x = self.skip_projection(x) | |
| x = F.relu(x) | |
| x = self.output_projection(x) | |
| return x | |
| class ClassifierFreeDenoiser(CodecDiffusion): | |
| def __init__(self, | |
| residual_channels, | |
| unconditional, | |
| condition, | |
| p_codec_rows, | |
| s_codec_rows, | |
| c_codec_rows, | |
| norm_args, | |
| seg_len, | |
| residual_layers = 30, | |
| kernel_size = 3, | |
| dilation_base = 1, | |
| dilation_bound = 4, | |
| cond_dropout = 0.5, | |
| **kwargs): | |
| self.cond_dropout = cond_dropout | |
| super().__init__(**kwargs) | |
| self.condition_normalize = Normalization(norm_args[0], norm_args[1], norm_args[2]) | |
| self.input_projection = Conv1d(p_codec_rows, residual_channels, 1) | |
| self.diffusion_embedding = DiffusionEmbedding(len(self.betas)) | |
| if condition == 'trainable_score': | |
| trainable_parameters = torch.full((s_codec_rows, self.hparams.seg_len), -1).float() | |
| trainable_parameters = nn.Parameter(trainable_parameters, requires_grad=True) | |
| self.register_parameter("trainable_parameters", trainable_parameters) | |
| self.uncon_dropout = self.trainable_dropout | |
| elif condition == 'fixed': | |
| self.uncon_dropout = self.fixed_dropout | |
| else: | |
| raise ValueError("unrecognized condition '{condition}'") | |
| # Original dilation was 2**(i % dilation_cycle_length) | |
| self.residual_layers = nn.ModuleList([ | |
| ResidualBlock(residual_channels, dilation_base**(i % dilation_bound), kernel_size, | |
| uncond=unconditional, condition_rows=s_codec_rows) | |
| for i in range(residual_layers) | |
| ]) | |
| #FiLM condition parameter (beta and gamma) generator for score information (MIDI frame roll) | |
| #The socre length is fixed for 20 sec and 32 resolution/second for the MIDI frame roll. | |
| # self.film_layer = nn.Linear(in_features= 200*c_codec_rows, out_features= 2*residual_layers, bias= True) | |
| self.skip_projection = Conv1d(residual_channels, residual_channels, 1) | |
| self.output_projection = Conv1d(residual_channels, p_codec_rows, 1) | |
| nn.init.zeros_(self.output_projection.weight) | |
| def forward(self, x_t, s_codec, c_codec, diffusion_step, sampling=False): | |
| """ | |
| x_t : (B, 1, T, N) | |
| s_codec : (B, 4, N) | |
| c_codec : (B, 7, N) | |
| """ | |
| x_t = x_t.squeeze(1).transpose(1, 2) # (B, 5, LEN) | |
| s_codec = s_codec.transpose(1, 2).float() | |
| s_codec = self.condition_normalize(s_codec) | |
| # c_codec = self.condition_normalize(c_codec) | |
| if self.training: # only use dropout during training | |
| s_codec = self.uncon_dropout(s_codec, self.hparams.cond_dropout) # making some score 0 to be unconditional | |
| # c_codec = self.uncon_dropout(c_codec, self.hparams.cond_dropout) | |
| # Generate FiLM conditions (beta and gamma) by FiLM generator (Linear layer) | |
| # c_codec_flat = torch.flatten(c_codec, start_dim = 1).float() | |
| # film_feat = self.film_layer(c_codec_flat) | |
| x = self.input_projection(x_t) # (B, 512, LEN) | |
| x = F.relu(x) | |
| diffusion_step = self.diffusion_embedding(diffusion_step) # (B, 512) | |
| skip = None | |
| index = 0 | |
| for layer in self.residual_layers: | |
| index += 1 | |
| # gamma = film_feat[:, 2*(index-1)] | |
| # beta = film_feat[:, 2*index-1] | |
| # all shapes: (B, 512, LEN) | |
| x, skip_connection = layer(x, diffusion_step, s_codec) | |
| skip = skip_connection if skip is None else skip_connection + skip | |
| x = skip / sqrt(len(self.residual_layers)) | |
| x = self.skip_projection(x) # (B, 512, LEN) | |
| x = F.relu(x) | |
| x = self.output_projection(x) # (B, 4, LEN) | |
| return x.transpose(1,2).unsqueeze(1), s_codec # (B, 1, LEN, 4) | |
| def fixed_dropout(self, x, p, masked_value=-1): | |
| mask = torch.distributions.Bernoulli(probs=(p)).sample((x.shape[0],)).long() | |
| mask_idx = mask.nonzero() | |
| x[mask_idx] = masked_value | |
| return x | |
| def trainable_dropout(self, x, p): | |
| mask = torch.distributions.Bernoulli(probs=(p)).sample((x.shape[0],)).long() | |
| mask_idx = mask.nonzero() | |
| x[mask_idx] = self.trainable_parameters | |
| return x |