chore: import upstream snapshot with attribution

This commit is contained in:
wehub-resource-sync
2026-07-13 12:35:17 +08:00
commit 344816a5d8
136 changed files with 25044 additions and 0 deletions
View File
+220
View File
@@ -0,0 +1,220 @@
from __future__ import annotations
from typing import List, Tuple
import torch
from torch import Tensor
from modules.core import (
GaussianDiffusion, PitchDiffusion, MultiVarianceDiffusion
)
def extract(a, t):
return a[t].reshape((1, 1, 1, 1))
# noinspection PyMethodOverriding
class GaussianDiffusionONNX(GaussianDiffusion):
@property
def backbone(self):
return self.denoise_fn
# We give up the setter for the property `backbone` because this will cause TorchScript to fail
# @backbone.setter
@torch.jit.unused
def set_backbone(self, value):
self.denoise_fn = value
def q_sample(self, x_start, t, noise):
return (
extract(self.sqrt_alphas_cumprod, t) * x_start +
extract(self.sqrt_one_minus_alphas_cumprod, t) * noise
)
def p_sample(self, x, t, cond):
x_pred = self.denoise_fn(x, t, cond)
x_recon = (
extract(self.sqrt_recip_alphas_cumprod, t) * x -
extract(self.sqrt_recipm1_alphas_cumprod, t) * x_pred
)
# This is previously inherited from original DiffSinger repository
# and disabled due to some loudness issues when speedup = 1.
# x_recon = torch.clamp(x_recon, min=-1., max=1.)
model_mean = (
extract(self.posterior_mean_coef1, t) * x_recon +
extract(self.posterior_mean_coef2, t) * x
)
model_log_variance = extract(self.posterior_log_variance_clipped, t)
noise = torch.randn_like(x)
# no noise when t == 0
nonzero_mask = ((t > 0).float()).reshape(1, 1, 1, 1)
return model_mean + nonzero_mask * (0.5 * model_log_variance).exp() * noise
def p_sample_ddim(self, x, t, interval: int, cond):
a_t = extract(self.alphas_cumprod, t)
t_prev = t - interval
a_prev = extract(self.alphas_cumprod, t_prev * (t_prev > 0))
noise_pred = self.denoise_fn(x, t, cond=cond)
x_prev = a_prev.sqrt() * (
x / a_t.sqrt() + (((1 - a_prev) / a_prev).sqrt() - ((1 - a_t) / a_t).sqrt()) * noise_pred
)
return x_prev
def plms_get_x_pred(self, x, noise_t, t, t_prev):
a_t = extract(self.alphas_cumprod, t)
a_prev = extract(self.alphas_cumprod, t_prev)
a_t_sq, a_prev_sq = a_t.sqrt(), a_prev.sqrt()
x_delta = (a_prev - a_t) * ((1 / (a_t_sq * (a_t_sq + a_prev_sq))) * x - 1 / (
a_t_sq * (((1 - a_prev) * a_t).sqrt() + ((1 - a_t) * a_prev).sqrt())) * noise_t)
x_pred = x + x_delta
return x_pred
def p_sample_plms(self, x_prev, t, interval: int, cond, noise_list: List[Tensor], stage: int):
noise_pred = self.denoise_fn(x_prev, t, cond)
t_prev = t - interval
t_prev = t_prev * (t_prev > 0)
if stage == 0:
x_pred = self.plms_get_x_pred(x_prev, noise_pred, t, t_prev)
noise_pred_prev = self.denoise_fn(x_pred, t_prev, cond)
noise_pred_prime = (noise_pred + noise_pred_prev) / 2.
elif stage == 1:
noise_pred_prime = (3. * noise_pred - noise_list[-1]) / 2.
elif stage == 2:
noise_pred_prime = (23. * noise_pred - 16. * noise_list[-1] + 5. * noise_list[-2]) / 12.
else:
noise_pred_prime = (55. * noise_pred - 59. * noise_list[-1] + 37.
* noise_list[-2] - 9. * noise_list[-3]) / 24.
x_prev = self.plms_get_x_pred(x_prev, noise_pred_prime, t, t_prev)
return noise_pred, x_prev
def norm_spec(self, x):
k = (self.spec_max - self.spec_min) / 2.
b = (self.spec_max + self.spec_min) / 2.
return (x - b) / k
def denorm_spec(self, x):
k = (self.spec_max - self.spec_min) / 2.
b = (self.spec_max + self.spec_min) / 2.
return x * k + b
def forward(self, condition, x_start=None, depth=None, steps: int = 10):
condition = condition.transpose(1, 2) # [1, T, H] => [1, H, T]
device = condition.device
n_frames = condition.shape[2]
noise = torch.randn((1, self.num_feats, self.out_dims, n_frames), device=device)
if x_start is None:
speedup = max(1, self.timesteps // steps)
speedup = self.timestep_factors[torch.sum(self.timestep_factors <= speedup) - 1]
step_range = torch.arange(0, self.k_step, speedup, dtype=torch.long, device=device).flip(0)[:, None]
x = noise
else:
depth_int64 = min(torch.round(depth * self.timesteps).long(), self.k_step)
speedup = max(1, depth_int64 // steps)
depth_int64 = depth_int64 // speedup * speedup # make depth_int64 a multiple of speedup
step_range = torch.arange(0, depth_int64, speedup, dtype=torch.long, device=device).flip(0)[:, None]
x_start = self.norm_spec(x_start).transpose(-2, -1)
if self.num_feats == 1:
x_start = x_start[:, None, :, :]
if depth_int64 >= self.timesteps:
x = noise
elif depth_int64 > 0:
x = self.q_sample(
x_start, torch.full((1,), depth_int64 - 1, device=device, dtype=torch.long), noise
)
else:
x = x_start
if speedup > 1:
for t in step_range:
x = self.p_sample_ddim(x, t, interval=speedup, cond=condition)
# plms_noise_stage: int = 0
# noise_list: List[Tensor] = []
# for t in step_range:
# noise_pred, x = self.p_sample_plms(
# x, t, interval=speedup, cond=condition,
# noise_list=noise_list, stage=plms_noise_stage
# )
# if plms_noise_stage == 0:
# noise_list = [noise_pred]
# plms_noise_stage = plms_noise_stage + 1
# else:
# if plms_noise_stage >= 3:
# noise_list.pop(0)
# else:
# plms_noise_stage = plms_noise_stage + 1
# noise_list.append(noise_pred)
else:
for t in step_range:
x = self.p_sample(x, t, cond=condition)
if self.num_feats == 1:
x = x.squeeze(1).permute(0, 2, 1) # [B, 1, M, T] => [B, T, M]
else:
x = x.permute(0, 1, 3, 2) # [B, F, M, T] => [B, F, T, M]
x = self.denorm_spec(x)
return x
class PitchDiffusionONNX(GaussianDiffusionONNX, PitchDiffusion):
def __init__(self, vmin: float, vmax: float,
cmin: float, cmax: float, repeat_bins,
timesteps=1000, k_step=1000,
backbone_type=None, backbone_args=None,
betas=None):
self.vmin = vmin
self.vmax = vmax
self.cmin = cmin
self.cmax = cmax
super(PitchDiffusion, self).__init__(
vmin=vmin, vmax=vmax, repeat_bins=repeat_bins,
timesteps=timesteps, k_step=k_step,
backbone_type=backbone_type, backbone_args=backbone_args,
betas=betas
)
def clamp_spec(self, x):
return x.clamp(min=self.cmin, max=self.cmax)
def denorm_spec(self, x):
d = (self.spec_max - self.spec_min) / 2.
m = (self.spec_max + self.spec_min) / 2.
x = x * d + m
x = x.mean(dim=-1)
return x
class MultiVarianceDiffusionONNX(GaussianDiffusionONNX, MultiVarianceDiffusion):
def __init__(
self, ranges: List[Tuple[float, float]],
clamps: List[Tuple[float | None, float | None] | None],
repeat_bins, timesteps=1000, k_step=1000,
backbone_type=None, backbone_args=None,
betas=None
):
assert len(ranges) == len(clamps)
self.clamps = clamps
vmin = [r[0] for r in ranges]
vmax = [r[1] for r in ranges]
if len(vmin) == 1:
vmin = vmin[0]
if len(vmax) == 1:
vmax = vmax[0]
super(MultiVarianceDiffusion, self).__init__(
vmin=vmin, vmax=vmax, repeat_bins=repeat_bins,
timesteps=timesteps, k_step=k_step,
backbone_type=backbone_type, backbone_args=backbone_args,
betas=betas
)
def denorm_spec(self, x):
d = (self.spec_max - self.spec_min) / 2.
m = (self.spec_max + self.spec_min) / 2.
x = x * d + m
x = x.mean(dim=-1)
return x
+235
View File
@@ -0,0 +1,235 @@
import copy
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from modules.commons.common_layers import NormalInitEmbedding as Embedding
from modules.fastspeech.acoustic_encoder import FastSpeech2Acoustic
from modules.fastspeech.variance_encoder import FastSpeech2Variance
from utils.hparams import hparams
from utils.phoneme_utils import PAD_INDEX
f0_bin = 256
f0_max = 1100.0
f0_min = 50.0
f0_mel_min = 1127 * np.log(1 + f0_min / 700)
f0_mel_max = 1127 * np.log(1 + f0_max / 700)
def uniform_attention_pooling(spk_embed, durations):
_, T_mel, _ = spk_embed.shape
ph_starts = torch.cumsum(torch.cat([torch.zeros_like(durations[:, :1]), durations[:, :-1]], dim=1), dim=1)
ph_ends = ph_starts + durations
mel_indices = torch.arange(T_mel, device=spk_embed.device).view(1, 1, T_mel)
phoneme_to_mel_mask = (mel_indices >= ph_starts.unsqueeze(-1)) & (mel_indices < ph_ends.unsqueeze(-1))
uniform_scores = phoneme_to_mel_mask.float()
sum_scores = uniform_scores.sum(dim=2, keepdim=True)
attn_weights = uniform_scores / (sum_scores + (sum_scores == 0).float()) # [B, T_ph, T_mel]
ph_spk_embed = torch.bmm(attn_weights, spk_embed)
return ph_spk_embed
def f0_to_coarse(f0):
f0_mel = 1127 * (1 + f0 / 700).log()
a = (f0_bin - 2) / (f0_mel_max - f0_mel_min)
b = f0_mel_min * a - 1.
f0_mel = torch.where(f0_mel > 0, f0_mel * a - b, f0_mel)
torch.clip_(f0_mel, min=1., max=float(f0_bin - 1))
f0_coarse = torch.round(f0_mel).long()
return f0_coarse
class LengthRegulator(nn.Module):
# noinspection PyMethodMayBeStatic
def forward(self, dur):
token_idx = torch.arange(1, dur.shape[1] + 1, device=dur.device)[None, :, None]
dur_cumsum = torch.cumsum(dur, dim=1)
dur_cumsum_prev = F.pad(dur_cumsum, (1, -1), mode='constant', value=0)
pos_idx = torch.arange(dur.sum(dim=1).max(), device=dur.device)[None, None]
token_mask = (pos_idx >= dur_cumsum_prev[:, :, None]) & (pos_idx < dur_cumsum[:, :, None])
mel2ph = (token_idx * token_mask).sum(dim=1)
return mel2ph
class FastSpeech2AcousticONNX(FastSpeech2Acoustic):
def __init__(self, vocab_size, cross_lingual_token_idx=None):
super().__init__(vocab_size=vocab_size)
self.register_buffer(
'cross_lingual_token_idx',
torch.LongTensor(cross_lingual_token_idx),
persistent=False
) # [N,]
if len(cross_lingual_token_idx) == 0:
self.use_lang_id = False
# for temporary compatibility; will be completely removed in the future
self.f0_embed_type = hparams.get('f0_embed_type', 'continuous')
if self.f0_embed_type == 'discrete':
self.pitch_embed = Embedding(300, hparams['hidden_size'], PAD_INDEX)
self.lr = LengthRegulator()
if hparams['use_key_shift_embed']:
self.shift_min, self.shift_max = hparams['augmentation_args']['random_pitch_shifting']['range']
if hparams['use_speed_embed']:
self.speed_min, self.speed_max = hparams['augmentation_args']['random_time_stretching']['range']
# noinspection PyMethodOverriding
def forward(
self, tokens, durations,
f0, variances: dict,
gender=None, velocity=None,
spk_embed=None,
languages=None
):
txt_embed = self.txt_embed(tokens)
durations = durations * (tokens > 0)
mel2ph = self.lr(durations)
_mel2ph = mel2ph
f0 = f0 * (mel2ph > 0)
mel2ph = mel2ph[..., None].repeat((1, 1, hparams['hidden_size']))
if self.use_variance_scaling:
dur_embed = self.dur_embed(torch.log(1 + durations.float())[:, :, None])
else:
dur_embed = self.dur_embed(durations.float()[:, :, None])
if self.use_lang_id:
lang_mask = torch.any(
tokens[..., None] == self.cross_lingual_token_idx[None, None],
dim=-1
)
lang_embed = self.lang_embed(languages * lang_mask)
extra_embed = dur_embed + lang_embed
else:
extra_embed = dur_embed
if hparams.get('use_mix_ln', False):
if hasattr(self, 'frozen_spk_embed'):
ph_spk_embed = self.frozen_spk_embed.repeat(1, tokens.shape[1], 1)
else:
ph_spk_embed = uniform_attention_pooling(spk_embed, durations)
else:
ph_spk_embed = None
encoded = self.encoder(txt_embed, extra_embed, tokens == PAD_INDEX, spk_embed=ph_spk_embed)
encoded = F.pad(encoded, (0, 0, 1, 0))
condition = torch.gather(encoded, 1, mel2ph)
if self.use_stretch_embed:
stretch = torch.round(1000 * self.sr(_mel2ph, durations))
table = self.stretch_embed(torch.arange(0, 1001, device=stretch.device))
stretch_embed = torch.index_select(table, 0, stretch.view(-1).long()).view_as(condition)
condition += stretch_embed
stretch_embed_rnn_out, _ = self.stretch_embed_rnn(condition)
condition += stretch_embed_rnn_out
if self.f0_embed_type == 'discrete':
pitch = f0_to_coarse(f0)
pitch_embed = self.pitch_embed(pitch)
else:
f0_mel = (1 + f0 / 700).log()
pitch_embed = self.pitch_embed(f0_mel[:, :, None])
condition += pitch_embed
if self.use_variance_embeds:
variance_embeds = torch.stack([
self.variance_embeds[v_name](variances[v_name][:, :, None] * self.variance_scaling_factor[v_name])
for v_name in self.variance_embed_list
], dim=-1).sum(-1)
condition += variance_embeds
if hparams['use_key_shift_embed']:
if hasattr(self, 'frozen_key_shift'):
key_shift_embed = self.key_shift_embed(self.frozen_key_shift[:, None, None] * self.variance_scaling_factor['key_shift'])
else:
gender = torch.clip(gender, min=-1., max=1.)
gender_mask = (gender < 0.).float()
key_shift = gender * ((1. - gender_mask) * self.shift_max + gender_mask * abs(self.shift_min))
key_shift_embed = self.key_shift_embed(key_shift[:, :, None] * self.variance_scaling_factor['key_shift'])
condition += key_shift_embed
if hparams['use_speed_embed']:
if velocity is not None:
velocity = torch.clip(velocity, min=self.speed_min, max=self.speed_max)
speed_embed = self.speed_embed(velocity[:, :, None] * self.variance_scaling_factor['speed'])
else:
speed_embed = self.speed_embed(torch.FloatTensor([1.]).to(condition.device)[:, None, None] * self.variance_scaling_factor['speed'])
condition += speed_embed
if hparams['use_spk_id']:
if hasattr(self, 'frozen_spk_embed'):
condition += self.frozen_spk_embed
else:
condition += spk_embed
return condition
class FastSpeech2VarianceONNX(FastSpeech2Variance):
def __init__(self, vocab_size, cross_lingual_token_idx=None):
super().__init__(vocab_size=vocab_size)
self.register_buffer(
'cross_lingual_token_idx',
torch.LongTensor(cross_lingual_token_idx),
persistent=False
)
if len(cross_lingual_token_idx) == 0:
self.use_lang_id = False
self.lr = LengthRegulator()
def forward_encoder_word(self, tokens, word_div, word_dur, languages=None):
txt_embed = self.txt_embed(tokens)
ph2word = self.lr(word_div)
onset = ph2word > F.pad(ph2word, [1, -1])
onset_embed = self.onset_embed(onset.long())
ph_word_dur = torch.gather(F.pad(word_dur, [1, 0]), 1, ph2word)
word_dur_embed = self.word_dur_embed(ph_word_dur.float()[:, :, None])
extra_embed = onset_embed + word_dur_embed
if self.use_lang_id:
lang_mask = torch.any(
tokens[..., None] == self.cross_lingual_token_idx[None, None],
dim=-1
)
lang_embed = self.lang_embed(languages * lang_mask)
extra_embed += lang_embed
x_masks = tokens == PAD_INDEX
return self.encoder(txt_embed, extra_embed, x_masks), x_masks
def forward_encoder_phoneme(self, tokens, ph_dur, languages=None):
txt_embed = self.txt_embed(tokens)
if self.use_variance_scaling:
ph_dur_embed = self.ph_dur_embed(torch.log(1 + ph_dur.float())[:, :, None])
else:
ph_dur_embed = self.ph_dur_embed(ph_dur.float()[:, :, None])
if self.use_lang_id:
lang_mask = torch.any(
tokens[..., None] == self.cross_lingual_token_idx[None, None],
dim=-1
)
lang_embed = self.lang_embed(languages * lang_mask)
extra_embed = ph_dur_embed + lang_embed
else:
extra_embed = ph_dur_embed
x_masks = tokens == PAD_INDEX
return self.encoder(txt_embed, extra_embed, x_masks), x_masks
def forward_dur_predictor(self, encoder_out, x_masks, ph_midi, spk_embed=None):
midi_embed = self.midi_embed(ph_midi)
dur_cond = encoder_out + midi_embed
if hparams['use_spk_id'] and spk_embed is not None:
dur_cond += spk_embed
ph_dur = self.dur_predictor(dur_cond, x_masks=x_masks)
return ph_dur
def view_as_encoder(self):
model = copy.deepcopy(self)
if self.predict_dur:
del model.dur_predictor
model.forward = model.forward_encoder_word
else:
model.forward = model.forward_encoder_phoneme
return model
def view_as_dur_predictor(self):
model = copy.deepcopy(self)
del model.encoder
model.forward = model.forward_dur_predictor
return model
+16
View File
@@ -0,0 +1,16 @@
import torch
from modules.nsf_hifigan.env import AttrDict
from modules.nsf_hifigan.models import Generator
# noinspection SpellCheckingInspection
class NSFHiFiGANONNX(torch.nn.Module):
def __init__(self, attrs: dict):
super().__init__()
self.generator = Generator(AttrDict(attrs))
def forward(self, mel: torch.Tensor, f0: torch.Tensor):
mel = mel.transpose(1, 2)
wav = self.generator(mel, f0)
return wav.squeeze(1)
+123
View File
@@ -0,0 +1,123 @@
from __future__ import annotations
from typing import List, Tuple
import torch
from modules.core import (
RectifiedFlow, PitchRectifiedFlow, MultiVarianceRectifiedFlow
)
class RectifiedFlowONNX(RectifiedFlow):
@property
def backbone(self):
return self.velocity_fn
# We give up the setter for the property `backbone` because this will cause TorchScript to fail
# @backbone.setter
@torch.jit.unused
def set_backbone(self, value):
self.velocity_fn = value
def sample_euler(self, x, t, dt: float, cond):
x += self.velocity_fn(x, t * self.time_scale_factor, cond) * dt
return x
def norm_spec(self, x):
k = (self.spec_max - self.spec_min) / 2.
b = (self.spec_max + self.spec_min) / 2.
return (x - b) / k
def denorm_spec(self, x):
k = (self.spec_max - self.spec_min) / 2.
b = (self.spec_max + self.spec_min) / 2.
return x * k + b
def forward(self, condition, x_end=None, depth=None, steps: int = 10):
condition = condition.transpose(1, 2) # [1, T, H] => [1, H, T]
device = condition.device
n_frames = condition.shape[2]
noise = torch.randn((1, self.num_feats, self.out_dims, n_frames), device=device)
if x_end is None:
t_start = 0.
x = noise
else:
t_start = torch.max(1 - depth, torch.tensor(self.t_start, dtype=torch.float32, device=device))
x_end = self.norm_spec(x_end).transpose(-2, -1)
if self.num_feats == 1:
x_end = x_end[:, None, :, :]
if t_start <= 0.:
x = noise
elif t_start >= 1.:
x = x_end
else:
x = t_start * x_end + (1 - t_start) * noise
t_width = 1. - t_start
if t_width >= 0.:
dt = t_width / max(1, steps)
for t in torch.arange(steps, dtype=torch.long, device=device)[:, None].float() * dt + t_start:
x = self.sample_euler(x, t, dt, condition)
if self.num_feats == 1:
x = x.squeeze(1).permute(0, 2, 1) # [B, 1, M, T] => [B, T, M]
else:
x = x.permute(0, 1, 3, 2) # [B, F, M, T] => [B, F, T, M]
x = self.denorm_spec(x)
return x
class PitchRectifiedFlowONNX(RectifiedFlowONNX, PitchRectifiedFlow):
def __init__(self, vmin: float, vmax: float,
cmin: float, cmax: float, repeat_bins,
time_scale_factor=1000,
backbone_type=None, backbone_args=None):
self.vmin = vmin
self.vmax = vmax
self.cmin = cmin
self.cmax = cmax
super(PitchRectifiedFlow, self).__init__(
vmin=vmin, vmax=vmax, repeat_bins=repeat_bins,
time_scale_factor=time_scale_factor,
backbone_type=backbone_type, backbone_args=backbone_args
)
def clamp_spec(self, x):
return x.clamp(min=self.cmin, max=self.cmax)
def denorm_spec(self, x):
d = (self.spec_max - self.spec_min) / 2.
m = (self.spec_max + self.spec_min) / 2.
x = x * d + m
x = x.mean(dim=-1)
return x
class MultiVarianceRectifiedFlowONNX(RectifiedFlowONNX, MultiVarianceRectifiedFlow):
def __init__(
self, ranges: List[Tuple[float, float]],
clamps: List[Tuple[float | None, float | None] | None],
repeat_bins, time_scale_factor=1000,
backbone_type=None, backbone_args=None
):
assert len(ranges) == len(clamps)
self.clamps = clamps
vmin = [r[0] for r in ranges]
vmax = [r[1] for r in ranges]
if len(vmin) == 1:
vmin = vmin[0]
if len(vmax) == 1:
vmax = vmax[0]
super(MultiVarianceRectifiedFlow, self).__init__(
vmin=vmin, vmax=vmax, repeat_bins=repeat_bins,
time_scale_factor=time_scale_factor,
backbone_type=backbone_type, backbone_args=backbone_args
)
def denorm_spec(self, x):
d = (self.spec_max - self.spec_min) / 2.
m = (self.spec_max + self.spec_min) / 2.
x = x * d + m
x = x.mean(dim=-1)
return x
+413
View File
@@ -0,0 +1,413 @@
import copy
import numpy as np
import torch
import torch.nn as nn
import torch.nn.functional as F
from torch import Tensor
from deployment.modules.diffusion import (
GaussianDiffusionONNX, PitchDiffusionONNX, MultiVarianceDiffusionONNX
)
from deployment.modules.rectified_flow import (
RectifiedFlowONNX, PitchRectifiedFlowONNX, MultiVarianceRectifiedFlowONNX
)
from deployment.modules.fastspeech2 import FastSpeech2AcousticONNX, FastSpeech2VarianceONNX
from modules.toplevel import DiffSingerAcoustic, DiffSingerVariance
from utils.hparams import hparams
class DiffSingerAcousticONNX(DiffSingerAcoustic):
def __init__(self, vocab_size, out_dims, cross_lingual_token_idx=None):
super().__init__(vocab_size, out_dims)
del self.fs2
del self.diffusion
self.fs2 = FastSpeech2AcousticONNX(
vocab_size=vocab_size,
cross_lingual_token_idx=cross_lingual_token_idx
)
if self.diffusion_type == 'ddpm':
self.diffusion = GaussianDiffusionONNX(
out_dims=out_dims,
num_feats=1,
timesteps=hparams['timesteps'],
k_step=hparams['K_step'],
backbone_type=self.backbone_type,
backbone_args=self.backbone_args,
spec_min=hparams['spec_min'],
spec_max=hparams['spec_max']
)
elif self.diffusion_type == 'reflow':
self.diffusion = RectifiedFlowONNX(
out_dims=out_dims,
num_feats=1,
t_start=hparams['T_start'],
time_scale_factor=hparams['time_scale_factor'],
backbone_type=self.backbone_type,
backbone_args=self.backbone_args,
spec_min=hparams['spec_min'],
spec_max=hparams['spec_max']
)
else:
raise ValueError(f"Invalid diffusion type: {self.diffusion_type}")
self.mel_base = hparams.get('mel_base', '10')
def ensure_mel_base(self, mel):
if self.mel_base != 'e':
# log10 mel to log mel
mel = mel * 2.30259
return mel
def forward_fs2_aux(
self,
tokens: Tensor,
durations: Tensor,
f0: Tensor,
variances: dict,
gender: Tensor = None,
velocity: Tensor = None,
spk_embed: Tensor = None,
languages: Tensor = None
):
condition = self.fs2(
tokens, durations, f0, variances=variances,
gender=gender, velocity=velocity, spk_embed=spk_embed,
languages=languages
)
if self.use_shallow_diffusion:
aux_mel_pred = self.aux_decoder(condition, infer=True)
return condition, aux_mel_pred
else:
return condition
def forward_shallow_diffusion(
self, condition: Tensor, x_start: Tensor,
depth, steps: int
) -> Tensor:
mel_pred = self.diffusion(condition, x_start=x_start, depth=depth, steps=steps)
return self.ensure_mel_base(mel_pred)
def forward_diffusion(self, condition: Tensor, steps: int):
mel_pred = self.diffusion(condition, steps=steps)
return self.ensure_mel_base(mel_pred)
def forward_shallow_reflow(
self, condition: Tensor, x_end: Tensor,
depth, steps: int
):
mel_pred = self.diffusion(condition, x_end=x_end, depth=depth, steps=steps)
return self.ensure_mel_base(mel_pred)
def forward_reflow(self, condition: Tensor, steps: int):
mel_pred = self.diffusion(condition, steps=steps)
return self.ensure_mel_base(mel_pred)
def view_as_fs2_aux(self) -> nn.Module:
model = copy.deepcopy(self)
del model.diffusion
model.forward = model.forward_fs2_aux
return model
def view_as_diffusion(self) -> nn.Module:
model = copy.deepcopy(self)
del model.fs2
if self.use_shallow_diffusion:
del model.aux_decoder
model.forward = model.forward_shallow_diffusion
else:
model.forward = model.forward_diffusion
return model
def view_as_reflow(self) -> nn.Module:
model = copy.deepcopy(self)
del model.fs2
if self.use_shallow_diffusion:
del model.aux_decoder
model.forward = model.forward_shallow_reflow
else:
model.forward = model.forward_reflow
return model
class DiffSingerVarianceONNX(DiffSingerVariance):
def __init__(self, vocab_size, cross_lingual_token_idx=None):
super().__init__(vocab_size=vocab_size)
del self.fs2
self.fs2 = FastSpeech2VarianceONNX(
vocab_size=vocab_size,
cross_lingual_token_idx=cross_lingual_token_idx
)
self.hidden_size = hparams['hidden_size']
if self.predict_pitch:
del self.pitch_predictor
self.smooth: nn.Conv1d = None
pitch_hparams = hparams['pitch_prediction_args']
if self.diffusion_type == 'ddpm':
self.pitch_predictor = PitchDiffusionONNX(
vmin=pitch_hparams['pitd_norm_min'],
vmax=pitch_hparams['pitd_norm_max'],
cmin=pitch_hparams['pitd_clip_min'],
cmax=pitch_hparams['pitd_clip_max'],
repeat_bins=pitch_hparams['repeat_bins'],
timesteps=hparams['timesteps'],
k_step=hparams['K_step'],
backbone_type=self.pitch_backbone_type,
backbone_args=self.pitch_backbone_args
)
elif self.diffusion_type == 'reflow':
self.pitch_predictor = PitchRectifiedFlowONNX(
vmin=pitch_hparams['pitd_norm_min'],
vmax=pitch_hparams['pitd_norm_max'],
cmin=pitch_hparams['pitd_clip_min'],
cmax=pitch_hparams['pitd_clip_max'],
repeat_bins=pitch_hparams['repeat_bins'],
time_scale_factor=hparams['time_scale_factor'],
backbone_type=self.pitch_backbone_type,
backbone_args=self.pitch_backbone_args
)
else:
raise ValueError(f"Invalid diffusion type: {self.diffusion_type}")
if self.predict_variances:
del self.variance_predictor
if self.diffusion_type == 'ddpm':
self.variance_predictor = self.build_adaptor(cls=MultiVarianceDiffusionONNX)
elif self.diffusion_type == 'reflow':
self.variance_predictor = self.build_adaptor(cls=MultiVarianceRectifiedFlowONNX)
else:
raise NotImplementedError(self.diffusion_type)
def build_smooth_op(self, device):
smooth_kernel_size = round(hparams['midi_smooth_width'] * hparams['audio_sample_rate'] / hparams['hop_size'])
smooth = nn.Conv1d(
in_channels=1,
out_channels=1,
kernel_size=smooth_kernel_size,
bias=False,
padding='same',
padding_mode='replicate'
).eval()
smooth_kernel = torch.sin(torch.from_numpy(
np.linspace(0, 1, smooth_kernel_size).astype(np.float32) * np.pi
))
smooth_kernel /= smooth_kernel.sum()
smooth.weight.data = smooth_kernel[None, None]
self.smooth = smooth.to(device)
def embed_frozen_spk(self, encoder_out):
if hparams['use_spk_id'] and hasattr(self, 'frozen_spk_embed'):
encoder_out += self.frozen_spk_embed
return encoder_out
def forward_linguistic_encoder_word(self, tokens, word_div, word_dur, languages=None):
encoder_out, x_masks = self.fs2.forward_encoder_word(tokens, word_div, word_dur, languages=languages)
encoder_out = self.embed_frozen_spk(encoder_out)
return encoder_out, x_masks
def forward_linguistic_encoder_phoneme(self, tokens, ph_dur, languages=None):
encoder_out, x_masks = self.fs2.forward_encoder_phoneme(tokens, ph_dur, languages=languages)
encoder_out = self.embed_frozen_spk(encoder_out)
return encoder_out, x_masks
def forward_dur_predictor(self, encoder_out, x_masks, ph_midi, spk_embed=None):
return self.fs2.forward_dur_predictor(encoder_out, x_masks, ph_midi, spk_embed=spk_embed)
def forward_mel2x_gather(self, x_src, x_dur, x_dim=None, check_stretch_embed=False):
mel2x = self.lr(x_dur)
_mel2x = mel2x
if x_dim is not None:
x_src = F.pad(x_src, [0, 0, 1, 0])
mel2x = mel2x[..., None].repeat([1, 1, x_dim])
else:
x_src = F.pad(x_src, [1, 0])
x_cond = torch.gather(x_src, 1, mel2x)
if self.use_stretch_embed and check_stretch_embed:
stretch = torch.round(1000 * self.sr(_mel2x, x_dur))
table = self.stretch_embed(torch.arange(0, 1001, device=stretch.device))
stretch_embed = torch.index_select(table, 0, stretch.view(-1).long()).view_as(x_cond)
x_cond += stretch_embed
stretch_embed_rnn_out, _ = self.stretch_embed_rnn(x_cond)
x_cond += stretch_embed_rnn_out
return x_cond
def forward_pitch_preprocess(
self, encoder_out, ph_dur,
note_midi=None, note_rest=None, note_dur=None, note_glide=None,
pitch=None, expr=None, retake=None, spk_embed=None
):
condition = self.forward_mel2x_gather(encoder_out, ph_dur, x_dim=self.hidden_size, check_stretch_embed=True)
if self.use_melody_encoder:
if self.melody_encoder.use_glide_embed and note_glide is None:
note_glide = torch.LongTensor([[0]]).to(encoder_out.device)
melody_encoder_out = self.melody_encoder(
note_midi, note_rest, note_dur,
glide=note_glide
)
melody_encoder_out = self.forward_mel2x_gather(melody_encoder_out, note_dur, x_dim=self.hidden_size)
condition += melody_encoder_out
if expr is None:
retake_embed = self.pitch_retake_embed(retake.long())
else:
retake_true_embed = self.pitch_retake_embed(
torch.ones(1, 1, dtype=torch.long, device=encoder_out.device)
) # [B=1, T=1] => [B=1, T=1, H]
retake_false_embed = self.pitch_retake_embed(
torch.zeros(1, 1, dtype=torch.long, device=encoder_out.device)
) # [B=1, T=1] => [B=1, T=1, H]
expr = (expr * retake)[:, :, None] # [B, T, 1]
retake_embed = expr * retake_true_embed + (1. - expr) * retake_false_embed
pitch_cond = condition + retake_embed
frame_midi_pitch = self.forward_mel2x_gather(note_midi, note_dur, x_dim=None)
base_pitch = self.smooth(frame_midi_pitch)
if self.use_melody_encoder:
delta_pitch = (pitch - base_pitch) * ~retake
if self.use_variance_scaling:
pitch_cond += self.delta_pitch_embed(delta_pitch[:, :, None] / 12)
else:
pitch_cond += self.delta_pitch_embed(delta_pitch[:, :, None])
else:
base_pitch = base_pitch * retake + pitch * ~retake
if self.use_variance_scaling:
pitch_cond += self.base_pitch_embed(base_pitch[:, :, None] / 128)
else:
pitch_cond += self.base_pitch_embed(base_pitch[:, :, None])
if hparams['use_spk_id'] and spk_embed is not None:
pitch_cond += spk_embed
return pitch_cond, base_pitch
def forward_pitch_reflow(
self, pitch_cond, steps: int = 10
):
x_pred = self.pitch_predictor(pitch_cond, steps=steps)
return x_pred
def forward_pitch_postprocess(self, x_pred, base_pitch):
pitch_pred = self.pitch_predictor.clamp_spec(x_pred) + base_pitch
return pitch_pred
def forward_variance_preprocess(
self, encoder_out, ph_dur, pitch,
variances: dict = None, retake=None, spk_embed=None
):
condition = self.forward_mel2x_gather(encoder_out, ph_dur, x_dim=self.hidden_size, check_stretch_embed=True)
if self.use_variance_scaling:
variance_cond = condition + self.pitch_embed(pitch[:, :, None] / 12)
else:
variance_cond = condition + self.pitch_embed(pitch[:, :, None])
non_retake_masks = [
v_retake.float() # [B, T, 1]
for v_retake in (~retake).split(1, dim=2)
]
variance_embeds = [
self.variance_embeds[v_name](variances[v_name][:, :, None] * self.variance_retake_scaling[v_name]) * v_masks
for v_name, v_masks in zip(self.variance_prediction_list, non_retake_masks)
]
variance_cond += torch.stack(variance_embeds, dim=-1).sum(-1)
if hparams['use_spk_id'] and spk_embed is not None:
variance_cond += spk_embed
return variance_cond
def forward_variance_reflow(self, variance_cond, steps: int = 10):
xs_pred = self.variance_predictor(variance_cond, steps=steps)
return xs_pred
def forward_variance_postprocess(self, xs_pred):
if self.variance_predictor.num_feats == 1:
xs_pred = [xs_pred]
else:
xs_pred = xs_pred.unbind(dim=1)
variance_pred = self.variance_predictor.clamp_spec(xs_pred)
return tuple(variance_pred)
def view_as_linguistic_encoder(self):
model = copy.deepcopy(self)
if self.predict_pitch:
del model.pitch_predictor
if self.use_melody_encoder:
del model.melody_encoder
if self.predict_variances:
del model.variance_predictor
model.fs2 = model.fs2.view_as_encoder()
if self.predict_dur:
model.forward = model.forward_linguistic_encoder_word
else:
model.forward = model.forward_linguistic_encoder_phoneme
return model
def view_as_dur_predictor(self):
assert self.predict_dur
model = copy.deepcopy(self)
if self.predict_pitch:
del model.pitch_predictor
if self.use_melody_encoder:
del model.melody_encoder
if self.predict_variances:
del model.variance_predictor
model.fs2 = model.fs2.view_as_dur_predictor()
model.forward = model.forward_dur_predictor
return model
def view_as_pitch_preprocess(self):
model = copy.deepcopy(self)
del model.fs2
if self.predict_pitch:
del model.pitch_predictor
if self.predict_variances:
del model.variance_predictor
model.forward = model.forward_pitch_preprocess
return model
def view_as_pitch_predictor(self):
assert self.predict_pitch
model = copy.deepcopy(self)
del model.fs2
del model.lr
if self.use_melody_encoder:
del model.melody_encoder
if self.predict_variances:
del model.variance_predictor
model.forward = model.forward_pitch_reflow
return model
def view_as_pitch_postprocess(self):
model = copy.deepcopy(self)
del model.fs2
if self.use_melody_encoder:
del model.melody_encoder
if self.predict_variances:
del model.variance_predictor
model.forward = model.forward_pitch_postprocess
return model
def view_as_variance_preprocess(self):
model = copy.deepcopy(self)
del model.fs2
if self.predict_pitch:
del model.pitch_predictor
if self.use_melody_encoder:
del model.melody_encoder
if self.predict_variances:
del model.variance_predictor
model.forward = model.forward_variance_preprocess
return model
def view_as_variance_predictor(self):
assert self.predict_variances
model = copy.deepcopy(self)
del model.fs2
del model.lr
if self.predict_pitch:
del model.pitch_predictor
if self.use_melody_encoder:
del model.melody_encoder
model.forward = model.forward_variance_reflow
return model
def view_as_variance_postprocess(self):
model = copy.deepcopy(self)
del model.fs2
if self.predict_pitch:
del model.pitch_predictor
if self.use_melody_encoder:
del model.melody_encoder
model.forward = model.forward_variance_postprocess
return model