Files
diodiogod 40f0e873be Integrate Voice Fixer audio restoration (Issue #153)
- 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
2025-10-29 14:15:52 -03:00

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)