ouzhang57's picture
Upload folder using huggingface_hub (part 10)
2e1a430 verified
Raw
History Blame Contribute Delete
19.9 kB
import math
import torch
import torch as th
from einops import rearrange
from torch import nn
from torch.nn import functional as F
import fractions
import torchaudio
def spectro(x, n_fft, hop_length):
*other, length = x.shape
x = x.reshape(-1, length)
z = th.stft(x, n_fft, hop_length, window=th.hann_window(n_fft).to(x),
win_length=n_fft, normalized=True, center=True,
return_complex=True, pad_mode="reflect")
_, freqs, frame = z.shape
return z.view(*other, freqs, frame)
def ispectro(z, hop_length, length):
*other, freqs, frames = z.shape
n_fft = 2 * freqs - 2
z = z.view(-1, freqs, frames)
x = th.istft(z, n_fft, hop_length, window=th.hann_window(n_fft).to(z.real),
win_length=n_fft, normalized=True, length=length, center=True)
return x.view(*other, x.shape[-1])
class LayerScale(nn.Module):
def __init__(self, channels, init=0, channel_last=False):
super().__init__()
self.channel_last = channel_last
self.scale = nn.Parameter(torch.full((channels,), float(init)))
def forward(self, x):
return self.scale * x if self.channel_last else self.scale[:, None] * x
class DConv(nn.Module):
def __init__(self, channels, compress=8, depth=2, init=1e-3, kernel=3):
super().__init__()
hidden = int(channels / compress)
self.layers = nn.ModuleList()
for d in range(depth):
dilation = 2 ** d
padding = dilation * (kernel // 2)
self.layers.append(nn.Sequential(
nn.Conv1d(channels, hidden, kernel, dilation=dilation, padding=padding),
nn.GroupNorm(1, hidden), nn.GELU(),
nn.Conv1d(hidden, 2 * channels, 1),
nn.GroupNorm(1, 2 * channels), nn.GLU(1),
LayerScale(channels, init),
))
def forward(self, x):
for layer in self.layers:
x = x + layer(x)
return x
class ScaledEmbedding(nn.Module):
def __init__(self, num_embeddings, embedding_dim, scale=10.0):
super().__init__()
self.embedding = nn.Embedding(num_embeddings, embedding_dim)
weight = torch.cumsum(self.embedding.weight.data, dim=0)
weight = weight / torch.arange(1, num_embeddings + 1).to(weight).sqrt()[:, None]
self.embedding.weight.data[:] = weight / scale
self.scale = scale
def forward(self, x):
return self.embedding(x) * self.scale
class HEncLayer(nn.Module):
def __init__(self, chin, chout, kernel_size=8, stride=4, freq=True, context=0,
dconv_kw={}):
super().__init__()
self.freq = freq
self.stride = stride
pad = kernel_size // 4
klass = nn.Conv2d if freq else nn.Conv1d
if freq:
kernel_size, stride, pad = [kernel_size, 1], [stride, 1], [pad, 0]
self.conv = klass(chin, chout, kernel_size, stride, pad)
self.rewrite = klass(chout, 2 * chout, 1 + 2 * context, 1, context)
self.dconv = DConv(chout, **dconv_kw)
def forward(self, x):
if not self.freq:
if x.dim() == 4:
B, C, Fr, T = x.shape
x = x.view(B, -1, T)
le = x.shape[-1]
if le % self.stride:
x = F.pad(x, (0, self.stride - (le % self.stride)))
y = F.gelu(self.conv(x))
if self.freq:
B, C, Fr, T = y.shape
y = y.permute(0, 2, 1, 3).reshape(-1, C, T)
y = self.dconv(y).view(B, Fr, C, T).permute(0, 2, 1, 3)
else:
y = self.dconv(y)
return F.glu(self.rewrite(y), dim=1)
class HDecLayer(nn.Module):
def __init__(self, chin, chout, last=False, kernel_size=8, stride=4, freq=True,
context=1, dconv_kw={}):
super().__init__()
pad = kernel_size // 4
self.pad = pad
self.last = last
self.freq = freq
self.chin = chin
klass = nn.Conv2d if freq else nn.Conv1d
klass_tr = nn.ConvTranspose2d if freq else nn.ConvTranspose1d
ks, st = ([kernel_size, 1], [stride, 1]) if freq else (kernel_size, stride)
self.conv_tr = klass_tr(chin, chout, ks, st)
self.rewrite = klass(chin, 2 * chin, 1 + 2 * context, 1, context)
self.dconv = DConv(chin, **dconv_kw)
def forward(self, x, skip, length):
if self.freq and x.dim() == 3:
B, C, T = x.shape
x = x.view(B, self.chin, -1, T)
x = x + skip
y = F.glu(self.rewrite(x), dim=1)
if self.freq:
B, C, Fr, T = y.shape
y = y.permute(0, 2, 1, 3).reshape(-1, C, T)
y = self.dconv(y).view(B, Fr, C, T).permute(0, 2, 1, 3)
else:
y = self.dconv(y)
z = self.conv_tr(y)
if self.freq:
z = z[..., self.pad: -self.pad, :]
else:
z = z[..., self.pad: self.pad + length]
if not self.last:
z = F.gelu(z)
return z, y
def create_sin_embedding(length, dim, device, max_period=10000):
pos = torch.arange(length, device=device).view(-1, 1, 1)
half_dim = dim // 2
adim = torch.arange(half_dim, device=device).view(1, 1, -1)
phase = pos / (max_period ** (adim / (half_dim - 1)))
return torch.cat([torch.cos(phase), torch.sin(phase)], dim=-1)
def create_2d_sin_embedding(d_model, height, width, device, max_period=10000):
pe = torch.zeros(d_model, height, width)
d_model = d_model // 2
div_term = torch.exp(torch.arange(0.0, d_model, 2) * -(math.log(max_period) / d_model))
pos_w = torch.arange(0.0, width).unsqueeze(1)
pos_h = torch.arange(0.0, height).unsqueeze(1)
pe[0:d_model:2, :, :] = torch.sin(pos_w * div_term).transpose(0, 1).unsqueeze(1).repeat(1, height, 1)
pe[1:d_model:2, :, :] = torch.cos(pos_w * div_term).transpose(0, 1).unsqueeze(1).repeat(1, height, 1)
pe[d_model::2, :, :] = torch.sin(pos_h * div_term).transpose(0, 1).unsqueeze(2).repeat(1, 1, width)
pe[d_model + 1:: 2, :, :] = torch.cos(pos_h * div_term).transpose(0, 1).unsqueeze(2).repeat(1, 1, width)
return pe[None, :].to(device)
class MyGroupNorm(nn.GroupNorm):
def forward(self, x):
return super().forward(x.transpose(1, 2)).transpose(1, 2)
class MyTransformerEncoderLayer(nn.TransformerEncoderLayer):
def __init__(self, d_model, nhead, dim_feedforward, dropout, activation):
super().__init__(d_model=d_model, nhead=nhead, dim_feedforward=dim_feedforward,
dropout=dropout, activation=activation, batch_first=True,
norm_first=True)
self.norm_out = MyGroupNorm(1, d_model)
self.gamma_1 = LayerScale(d_model, 1e-4, True)
self.gamma_2 = LayerScale(d_model, 1e-4, True)
def forward(self, x, **unused):
x = x + self.gamma_1(self._sa_block(self.norm1(x), None, None))
x = x + self.gamma_2(self._ff_block(self.norm2(x)))
return self.norm_out(x)
class CrossTransformerEncoderLayer(nn.Module):
def __init__(self, d_model, nhead, dim_feedforward, dropout, activation):
super().__init__()
self.cross_attn = nn.MultiheadAttention(d_model, nhead, dropout=dropout, batch_first=True)
self.linear1 = nn.Linear(d_model, dim_feedforward)
self.dropout = nn.Dropout(dropout)
self.linear2 = nn.Linear(dim_feedforward, d_model)
self.norm1 = nn.LayerNorm(d_model)
self.norm2 = nn.LayerNorm(d_model)
self.norm3 = nn.LayerNorm(d_model)
self.norm_out = MyGroupNorm(1, d_model)
self.gamma_1 = LayerScale(d_model, 1e-4, True)
self.gamma_2 = LayerScale(d_model, 1e-4, True)
self.dropout1 = nn.Dropout(dropout)
self.dropout2 = nn.Dropout(dropout)
self.activation = activation
def forward(self, q, k):
x = q + self.gamma_1(self.dropout1(
self.cross_attn(self.norm1(q), self.norm2(k), self.norm2(k), need_weights=False)[0]))
x = x + self.gamma_2(self._ff_block(self.norm3(x)))
return self.norm_out(x)
def _ff_block(self, x):
return self.dropout2(self.linear2(self.dropout(self.activation(self.linear1(x)))))
class CrossTransformerEncoder(nn.Module):
def __init__(self, dim, hidden_scale=4.0, num_heads=8, num_layers=5, dropout=0.0,
max_period=10000.0, gelu=True):
super().__init__()
hidden_dim = int(dim * hidden_scale)
self.num_layers = num_layers
self.max_period = max_period
self.norm_in = nn.LayerNorm(dim)
self.norm_in_t = nn.LayerNorm(dim)
activation = F.gelu if gelu else F.relu
self.layers = nn.ModuleList()
self.layers_t = nn.ModuleList()
common = dict(d_model=dim, nhead=num_heads, dim_feedforward=hidden_dim,
dropout=dropout, activation=activation)
for idx in range(num_layers):
klass = MyTransformerEncoderLayer if idx % 2 == 0 else CrossTransformerEncoderLayer
self.layers.append(klass(**common))
self.layers_t.append(klass(**common))
def forward(self, x, xt):
B, C, Fr, T1 = x.shape
pos_2d = rearrange(create_2d_sin_embedding(C, Fr, T1, x.device, self.max_period),
"b c fr t1 -> b (t1 fr) c")
x = (self.norm_in(rearrange(x, "b c fr t1 -> b (t1 fr) c")) + pos_2d).to(x.dtype)
B, C, T2 = xt.shape
pos = rearrange(create_sin_embedding(T2, C, x.device, self.max_period), "t2 b c -> b t2 c")
xt = (self.norm_in_t(rearrange(xt, "b c t2 -> b t2 c")) + pos).to(xt.dtype)
for idx in range(self.num_layers):
if idx % 2 == 0:
x = self.layers[idx](x)
xt = self.layers_t[idx](xt)
else:
old_x = x
x = self.layers[idx](x, xt)
xt = self.layers_t[idx](xt, old_x)
x = rearrange(x, "b (t1 fr) c -> b c fr t1", t1=T1)
xt = rearrange(xt, "b t2 c -> b c t2")
return x, xt
class HTDemucs(nn.Module):
def __init__(self, sources=['drums', 'bass', 'other', 'vocals'], audio_channels=2, channels=48, growth=2, nfft=4096, cac=True,
depth=4, freq_emb=0.2, emb_scale=10, kernel_size=8, time_stride=2, stride=4,
context=1, context_enc=0, dconv_depth=2, dconv_comp=8, dconv_init=1e-3,
bottom_channels=512, t_layers=5, t_hidden_scale=4.0, t_heads=8, t_dropout=0.0,
t_max_period=10000.0, t_gelu=True, samplerate=44100, segment=fractions.Fraction(39, 5), **unused):
super().__init__()
self.audio_channels = audio_channels
self.sources = sources
self.depth = depth
self.bottom_channels = bottom_channels
self.samplerate = samplerate
self.segment = segment
self.nfft = nfft
self.hop_length = nfft // 4
self.encoder = nn.ModuleList()
self.decoder = nn.ModuleList()
self.tencoder = nn.ModuleList()
self.tdecoder = nn.ModuleList()
chin = audio_channels
chin_z = chin * 2
chout = chout_z = channels
freqs = nfft // 2
for index in range(depth):
dconv_kw = {"depth": dconv_depth, "compress": dconv_comp, "init": dconv_init}
kw = {"kernel_size": kernel_size, "stride": stride, "dconv_kw": dconv_kw}
kwt = dict(kw, freq=False)
self.encoder.append(HEncLayer(chin_z, chout_z, context=context_enc, **kw))
self.tencoder.append(HEncLayer(chin, chout, freq=False, context=context_enc, **kw))
if index == 0:
chin = self.audio_channels * len(self.sources)
chin_z = chin * 2
self.decoder.insert(0, HDecLayer(chout_z, chin_z, last=index == 0, context=context, **kw))
self.tdecoder.insert(0, HDecLayer(chout, chin, last=index == 0, context=context, **kwt))
chin, chin_z = chout, chout_z
chout = int(growth * chout)
chout_z = int(growth * chout_z)
freqs //= stride
if index == 0:
self.freq_emb = ScaledEmbedding(freqs, chin_z, scale=emb_scale)
self.freq_emb_scale = freq_emb
transformer_channels = channels * growth ** (depth - 1)
self.channel_upsampler = nn.Conv1d(transformer_channels, bottom_channels, 1)
self.channel_downsampler = nn.Conv1d(bottom_channels, transformer_channels, 1)
self.channel_upsampler_t = nn.Conv1d(transformer_channels, bottom_channels, 1)
self.channel_downsampler_t = nn.Conv1d(bottom_channels, transformer_channels, 1)
self.crosstransformer = CrossTransformerEncoder(
dim=bottom_channels, hidden_scale=t_hidden_scale, num_heads=t_heads,
num_layers=t_layers, dropout=t_dropout, max_period=t_max_period, gelu=t_gelu)
def _spec(self, x):
hl, nfft = self.hop_length, self.nfft
le = int(math.ceil(x.shape[-1] / hl))
pad = hl // 2 * 3
x = F.pad(x, (pad, pad + le * hl - x.shape[-1]), mode="reflect")
z = spectro(x.float(), nfft, hl)[..., :-1, :]
return z[..., 2: 2 + le]
def _ispec(self, z, length):
hl = self.hop_length
z = F.pad(z, (0, 0, 0, 1))
z = F.pad(z, (2, 2))
pad = hl // 2 * 3
le = hl * int(math.ceil(length / hl)) + 2 * pad
return ispectro(z, hl, le)[..., pad: pad + length]
def _magnitude(self, z):
# cac: 复数实虚部当作额外通道
B, C, Fr, T = z.shape
return torch.view_as_real(z).permute(0, 1, 4, 2, 3).reshape(B, C * 2, Fr, T)
def _mask(self, m):
# cac: m 即完整复数谱(通道形式), 还原成复数
B, S, C, Fr, T = m.shape
out = m.view(B, S, -1, 2, Fr, T).permute(0, 1, 2, 4, 5, 3)
return torch.view_as_complex(out.contiguous())
def forward(self, mix):
length = mix.shape[-1]
z = self._spec(mix)
x = self._magnitude(z).to(device=mix.device, dtype=mix.dtype)
B, C, Fq, T = x.shape
mean = x.mean(dim=(1, 2, 3), keepdim=True)
std = x.std(dim=(1, 2, 3), keepdim=True)
x = (x - mean) / (1e-5 + std)
xt = mix
meant = xt.mean(dim=(1, 2), keepdim=True)
stdt = xt.std(dim=(1, 2), keepdim=True)
xt = (xt - meant) / (1e-5 + stdt)
saved, saved_t, lengths, lengths_t = [], [], [], []
for idx, encode in enumerate(self.encoder):
lengths.append(x.shape[-1])
lengths_t.append(xt.shape[-1])
xt = self.tencoder[idx](xt)
saved_t.append(xt)
x = encode(x)
if idx == 0:
frs = torch.arange(x.shape[-2], device=x.device)
emb = self.freq_emb(frs).t()[None, :, :, None].expand_as(x)
x = x + self.freq_emb_scale * emb
saved.append(x)
b, c, f, t = x.shape
x = rearrange(x, "b c f t-> b c (f t)")
x = self.channel_upsampler(x)
x = rearrange(x, "b c (f t)-> b c f t", f=f)
xt = self.channel_upsampler_t(xt)
x, xt = self.crosstransformer(x, xt)
x = rearrange(x, "b c f t-> b c (f t)")
x = self.channel_downsampler(x)
x = rearrange(x, "b c (f t)-> b c f t", f=f)
xt = self.channel_downsampler_t(xt)
for idx, decode in enumerate(self.decoder):
x, pre = decode(x, saved.pop(-1), lengths.pop(-1))
xt, _ = self.tdecoder[idx](xt, saved_t.pop(-1), lengths_t.pop(-1))
S = len(self.sources)
x = x.view(B, S, -1, Fq, T) * std[:, None] + mean[:, None]
x = self._ispec(self._mask(x.float()), length).to(mix.dtype)
xt = xt.view(B, S, -1, length) * stdt[:, None] + meant[:, None]
return xt + x
def extract_track(self, audio, sample_rate, track="vocals"):
if sample_rate != 44100:
audio = torchaudio.functional.resample(audio, sample_rate, 44100)
ref = audio.mean(0)
audio = (audio - ref.mean()) / (ref.std() + 1e-8)
out = apply_model(self, audio[None], shifts=1, split=True, overlap=0.25,
device=audio.device, progress=True)[0]
out = out * (ref.std() + 1e-8) + ref.mean()
out = out / max(1.01 * out.abs().max(), 1)
out = out.clamp_(-1, 1).cpu()
out = out[self.sources.index(track)]
return out
def center_trim(tensor, length):
delta = tensor.size(-1) - length
if delta:
tensor = tensor[..., delta // 2: -(delta - delta // 2)]
return tensor
class TensorChunk:
def __init__(self, tensor, offset=0, length=None):
total = tensor.shape[-1]
if isinstance(tensor, TensorChunk):
self.tensor, self.offset = tensor.tensor, offset + tensor.offset
else:
self.tensor, self.offset = tensor, offset
self.length = total - offset if length is None else min(total - offset, length)
self.device = tensor.device
@property
def shape(self):
shape = list(self.tensor.shape)
shape[-1] = self.length
return shape
def padded(self, target_length):
delta = target_length - self.length
total = self.tensor.shape[-1]
start = self.offset - delta // 2
end = start + target_length
correct_start, correct_end = max(0, start), min(total, end)
out = F.pad(self.tensor[..., correct_start:correct_end],
(correct_start - start, end - correct_end))
return out
def apply_model(model, mix, shifts=1, split=True, overlap=0.25, device=None, segment=None,
progress=False):
device = th.device(device) if device is not None else mix.device
batch, channels, length = mix.shape
if shifts:
max_shift = int(0.5 * model.samplerate)
mix = mix if isinstance(mix, TensorChunk) else TensorChunk(mix)
padded_mix = mix.padded(length + 2 * max_shift)
out = 0.0
for _ in range(shifts):
offset = int(th.randint(0, max_shift, (1,)).item())
shifted = TensorChunk(padded_mix, offset, length + max_shift - offset)
shifted_out = apply_model(model, shifted, shifts=0, split=split, overlap=overlap,
device=device, segment=segment, progress=progress)
out += shifted_out[..., max_shift - offset:]
return out / shifts
if split:
out = th.zeros(batch, len(model.sources), channels, length, device=mix.device)
sum_weight = th.zeros(length, device=mix.device)
if segment is None:
segment = model.segment
segment_length = int(model.samplerate * segment)
stride = int((1 - overlap) * segment_length)
offsets = range(0, length, stride)
scale = float(format(stride / model.samplerate, ".2f"))
weight = th.cat([th.arange(1, segment_length // 2 + 1, device=device),
th.arange(segment_length - segment_length // 2, 0, -1, device=device)])
weight = weight / weight.max()
iterator = offsets
for offset in iterator:
chunk = TensorChunk(mix, offset, segment_length)
chunk_out = apply_model(model, chunk, shifts=0, split=False, device=device, segment=segment)
cl = chunk_out.shape[-1]
out[..., offset:offset + segment_length] += (weight[:cl] * chunk_out).to(mix.device)
sum_weight[offset:offset + segment_length] += weight[:cl].to(mix.device)
return out / sum_weight
valid_length = int(segment * model.samplerate)
mix = mix if isinstance(mix, TensorChunk) else TensorChunk(mix)
padded_mix = mix.padded(valid_length).to(device)
out = model(padded_mix)
return center_trim(out, length)