Files
2026-07-13 12:35:17 +08:00

121 lines
5.3 KiB
Python

import pathlib
import numpy as np
import torch
import torch.nn.functional as F
import yaml
from librosa.filters import mel as librosa_mel_fn
from basics.base_vocoder import BaseVocoder
from modules.vocoders.registry import register_vocoder
from utils.hparams import hparams
class DotDict(dict):
def __getattr__(*args):
val = dict.get(*args)
return DotDict(val) if type(val) is dict else val
__setattr__ = dict.__setitem__
__delattr__ = dict.__delitem__
def load_model(model_path: pathlib.Path, device='cpu'):
config_file = model_path.with_name('config.yaml')
with open(config_file, "r") as config:
args = yaml.safe_load(config)
args = DotDict(args)
# load model
print(' [Loading] ' + str(model_path))
model = torch.jit.load(model_path, map_location=torch.device(device))
model.eval()
return model, args
@register_vocoder
class DDSP(BaseVocoder):
def __init__(self, device='cpu'):
self.device = device
model_path = pathlib.Path(hparams['vocoder_ckpt'])
assert model_path.exists(), 'DDSP model file is not found!'
self.model, self.args = load_model(model_path, device=self.device)
def to_device(self, device):
pass
def get_device(self):
return self.device
def spec2wav_torch(self, mel, f0): # mel: [B, T, bins] f0: [B, T]
if self.args.data.sampling_rate != hparams['audio_sample_rate']:
print('Mismatch parameters: hparams[\'audio_sample_rate\']=', hparams['audio_sample_rate'], '!=',
self.args.data.sampling_rate, '(vocoder)')
if self.args.data.n_mels != hparams['audio_num_mel_bins']:
print('Mismatch parameters: hparams[\'audio_num_mel_bins\']=', hparams['audio_num_mel_bins'], '!=',
self.args.data.n_mels, '(vocoder)')
if self.args.data.n_fft != hparams['fft_size']:
print('Mismatch parameters: hparams[\'fft_size\']=', hparams['fft_size'], '!=', self.args.data.n_fft,
'(vocoder)')
if self.args.data.win_length != hparams['win_size']:
print('Mismatch parameters: hparams[\'win_size\']=', hparams['win_size'], '!=', self.args.data.win_length,
'(vocoder)')
if self.args.data.block_size != hparams['hop_size']:
print('Mismatch parameters: hparams[\'hop_size\']=', hparams['hop_size'], '!=', self.args.data.block_size,
'(vocoder)')
if self.args.data.mel_fmin != hparams['fmin']:
print('Mismatch parameters: hparams[\'fmin\']=', hparams['fmin'], '!=', self.args.data.mel_fmin,
'(vocoder)')
if self.args.data.mel_fmax != hparams['fmax']:
print('Mismatch parameters: hparams[\'fmax\']=', hparams['fmax'], '!=', self.args.data.mel_fmax,
'(vocoder)')
with torch.no_grad():
mel = mel.to(self.device)
mel_base = hparams.get('mel_base', 10)
if mel_base != 'e':
assert mel_base in [10, '10'], "mel_base must be 'e', '10' or 10."
else:
# log mel to log10 mel
mel = 0.434294 * mel
f0 = f0.unsqueeze(-1).to(self.device)
signal, _, (s_h, s_n) = self.model(mel, f0)
signal = signal.view(-1)
return signal
def spec2wav(self, mel, f0):
if self.args.data.sampling_rate != hparams['audio_sample_rate']:
print('Mismatch parameters: hparams[\'audio_sample_rate\']=', hparams['audio_sample_rate'], '!=',
self.args.data.sampling_rate, '(vocoder)')
if self.args.data.n_mels != hparams['audio_num_mel_bins']:
print('Mismatch parameters: hparams[\'audio_num_mel_bins\']=', hparams['audio_num_mel_bins'], '!=',
self.args.data.n_mels, '(vocoder)')
if self.args.data.n_fft != hparams['fft_size']:
print('Mismatch parameters: hparams[\'fft_size\']=', hparams['fft_size'], '!=', self.args.data.n_fft,
'(vocoder)')
if self.args.data.win_length != hparams['win_size']:
print('Mismatch parameters: hparams[\'win_size\']=', hparams['win_size'], '!=', self.args.data.win_length,
'(vocoder)')
if self.args.data.block_size != hparams['hop_size']:
print('Mismatch parameters: hparams[\'hop_size\']=', hparams['hop_size'], '!=', self.args.data.block_size,
'(vocoder)')
if self.args.data.mel_fmin != hparams['fmin']:
print('Mismatch parameters: hparams[\'fmin\']=', hparams['fmin'], '!=', self.args.data.mel_fmin,
'(vocoder)')
if self.args.data.mel_fmax != hparams['fmax']:
print('Mismatch parameters: hparams[\'fmax\']=', hparams['fmax'], '!=', self.args.data.mel_fmax,
'(vocoder)')
with torch.no_grad():
mel = torch.FloatTensor(mel).unsqueeze(0).to(self.device)
mel_base = hparams.get('mel_base', 10)
if mel_base != 'e':
assert mel_base in [10, '10'], "mel_base must be 'e', '10' or 10."
else:
# log mel to log10 mel
mel = 0.434294 * mel
f0 = torch.FloatTensor(f0).unsqueeze(0).unsqueeze(-1).to(self.device)
signal, _, (s_h, s_n) = self.model(mel, f0)
signal = signal.view(-1)
wav_out = signal.cpu().numpy()
return wav_out