so-vits-svc/modules/F0Predictor/HarvestF0Predictor.py

55 lines
2.1 KiB
Python

from modules.F0Predictor.F0Predictor import F0Predictor
import pyworld
import numpy as np
import scipy
class HarvestF0Predictor(F0Predictor):
def __init__(self,hop_length=512,f0_min=50,f0_max=1100,sampling_rate=44100):
self.hop_length = hop_length
self.f0_min = f0_min
self.f0_max = f0_max
self.sampling_rate = sampling_rate
def resize_f0(self,x, target_len):
source = np.array(x)
source[source<0.001] = np.nan
target = np.interp(np.arange(0, len(source)*target_len, len(source))/ target_len, np.arange(0, len(source)), source)
res = np.nan_to_num(target)
return res
def resize_f0_uv(self,x, target_len):
source = np.array(x)
vuv_vector = np.zeros_like(x)
vuv_vector[x > 0.0] = 1.0
vuv_vector[x < 0.001] = 0.0
source[source<0.001] = np.nan
target = np.interp(np.arange(0, len(source)*target_len, len(source))/ target_len, np.arange(0, len(source)), source)
res = np.nan_to_num(target)
vuv_vector = np.ceil(scipy.ndimage.zoom(vuv_vector,target_len/len(vuv_vector),order = 0))
return res,vuv_vector
def compute_f0(self,wav,p_len=None):
if p_len is None:
p_len = wav.shape[0]//self.hop_length
f0, t = pyworld.harvest(
wav.astype(np.double),
fs=self.hop_length,
f0_ceil=self.f0_max,
f0_floor=self.f0_min,
frame_period=1000 * self.hop_length / self.sampling_rate,
)
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.fs)
return self.resize_f0(f0, p_len)
def compute_f0_uv(self,wav,p_len=None):
if p_len is None:
p_len = wav.shape[0]//self.hop_length
f0, t = pyworld.harvest(
wav.astype(np.double),
fs=self.sampling_rate,
f0_floor=self.f0_min,
f0_ceil=self.f0_max,
frame_period=1000 * self.hop_length / self.sampling_rate,
)
f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
return self.resize_f0_uv(f0, p_len)