- Bundle VoiceFixer locally to avoid cache downloads - Create voice_fixer_downloader for TTS/voicefixer/ model management - Implement Voice Fixer node with 3 restoration modes (original, high-freq removal, train mode) - Register node in nodes.py with proper error handling - Patch bundled VoiceFixer hardcoded paths to use TTS/voicefixer/ directory - Disable auto-download in restorer/__init__.py, handled by node instead - Support lazy loading and CUDA acceleration - All models download to organized TTS/ folder, never to cache
136 lines
4.0 KiB
Python
136 lines
4.0 KiB
Python
from voicefixer_bundled.vocoder.config import Config
|
|
from voicefixer_bundled.tools.pytorch_util import try_tensor_cuda, check_cuda_availability
|
|
import torch
|
|
import librosa
|
|
import numpy as np
|
|
|
|
|
|
def tr_normalize(S):
|
|
if Config.allow_clipping_in_normalization:
|
|
if Config.symmetric_mels:
|
|
return torch.clip(
|
|
(2 * Config.max_abs_value) * ((S - Config.min_db) / (-Config.min_db))
|
|
- Config.max_abs_value,
|
|
-Config.max_abs_value,
|
|
Config.max_abs_value,
|
|
)
|
|
else:
|
|
return torch.clip(
|
|
Config.max_abs_value * ((S - Config.min_db) / (-Config.min_db)),
|
|
0,
|
|
Config.max_abs_value,
|
|
)
|
|
|
|
assert S.max() <= 0 and S.min() - Config.min_db >= 0
|
|
if Config.symmetric_mels:
|
|
return (2 * Config.max_abs_value) * (
|
|
(S - Config.min_db) / (-Config.min_db)
|
|
) - Config.max_abs_value
|
|
else:
|
|
return Config.max_abs_value * ((S - Config.min_db) / (-Config.min_db))
|
|
|
|
|
|
def tr_amp_to_db(x):
|
|
min_level = torch.exp(Config.min_level_db / 20 * torch.log(torch.tensor(10.0)))
|
|
min_level = min_level.type_as(x)
|
|
return 20 * torch.log10(torch.maximum(min_level, x))
|
|
|
|
|
|
def normalize(S):
|
|
if Config.allow_clipping_in_normalization:
|
|
if Config.symmetric_mels:
|
|
return np.clip(
|
|
(2 * Config.max_abs_value) * ((S - Config.min_db) / (-Config.min_db))
|
|
- Config.max_abs_value,
|
|
-Config.max_abs_value,
|
|
Config.max_abs_value,
|
|
)
|
|
else:
|
|
return np.clip(
|
|
Config.max_abs_value * ((S - Config.min_db) / (-Config.min_db)),
|
|
0,
|
|
Config.max_abs_value,
|
|
)
|
|
|
|
assert S.max() <= 0 and S.min() - Config.min_db >= 0
|
|
if Config.symmetric_mels:
|
|
return (2 * Config.max_abs_value) * (
|
|
(S - Config.min_db) / (-Config.min_db)
|
|
) - Config.max_abs_value
|
|
else:
|
|
return Config.max_abs_value * ((S - Config.min_db) / (-Config.min_db))
|
|
|
|
|
|
def amp_to_db(x):
|
|
min_level = np.exp(Config.min_level_db / 20 * np.log(10))
|
|
return 20 * np.log10(np.maximum(min_level, x))
|
|
|
|
|
|
def tr_pre(npy):
|
|
# conditions = torch.FloatTensor(npy).type_as(npy) # to(device)
|
|
conditions = npy.transpose(1, 2)
|
|
l = conditions.size(-1)
|
|
pad_tail = l % 2 + 4
|
|
zeros = (
|
|
torch.zeros([conditions.size()[0], Config.num_mels, pad_tail]).type_as(
|
|
conditions
|
|
)
|
|
+ -4.0
|
|
)
|
|
return torch.cat([conditions, zeros], dim=-1)
|
|
|
|
|
|
def pre(npy):
|
|
conditions = npy
|
|
## padding tail
|
|
if type(conditions) == np.ndarray:
|
|
conditions = torch.FloatTensor(conditions).unsqueeze(0)
|
|
else:
|
|
conditions = torch.FloatTensor(conditions.float()).unsqueeze(0)
|
|
conditions = conditions.transpose(1, 2)
|
|
l = conditions.size(-1)
|
|
pad_tail = l % 2 + 4
|
|
zeros = torch.zeros([1, Config.num_mels, pad_tail]) + -4.0
|
|
return torch.cat([conditions, zeros], dim=-1)
|
|
|
|
|
|
def load_try(state, model):
|
|
model_dict = model.state_dict()
|
|
try:
|
|
model_dict.update(state)
|
|
model.load_state_dict(model_dict)
|
|
except RuntimeError as e:
|
|
print(str(e))
|
|
model_dict = model.state_dict()
|
|
for k, v in state.items():
|
|
model_dict[k] = v
|
|
model.load_state_dict(model_dict)
|
|
|
|
|
|
def load_checkpoint(checkpoint_path, device):
|
|
checkpoint = torch.load(checkpoint_path, map_location=device)
|
|
return checkpoint
|
|
|
|
|
|
def build_mel_basis():
|
|
return librosa.filters.mel(
|
|
sr=Config.sample_rate,
|
|
n_fft=Config.n_fft,
|
|
htk=True,
|
|
n_mels=Config.num_mels,
|
|
fmin=0,
|
|
fmax=int(Config.sample_rate // 2)
|
|
)
|
|
|
|
|
|
def linear_to_mel(spectogram):
|
|
_mel_basis = build_mel_basis()
|
|
return np.dot(_mel_basis, spectogram)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
data = torch.randn((3, 5, 100))
|
|
b = normalize(amp_to_db(data.numpy()))
|
|
a = tr_normalize(tr_amp_to_db(data)).numpy()
|
|
print(a - b)
|