CoolFace
Apppublic

kwau/sovits-isla

sourceHugging Faceupdated 3y agoView on Hugging Face
0likes
utils.py573 linesDownload Raw Back to root
1import argparse2import glob3import json4import logging5import os6import re7import subprocess8import sys9import traceback10from multiprocessing import cpu_count11 12import faiss13import librosa14import numpy as np15import torch16from scipy.io.wavfile import read17from sklearn.cluster import MiniBatchKMeans18from torch.nn import functional as F19 20MATPLOTLIB_FLAG = False21 22logging.basicConfig(stream=sys.stdout, level=logging.WARN)23logger = logging24 25f0_bin = 25626f0_max = 1100.027f0_min = 50.028f0_mel_min = 1127 * np.log(1 + f0_min / 700)29f0_mel_max = 1127 * np.log(1 + f0_max / 700)30 31def normalize_f0(f0, x_mask, uv, random_scale=True):32    # calculate means based on x_mask33    uv_sum = torch.sum(uv, dim=1, keepdim=True)34    uv_sum[uv_sum == 0] = 999935    means = torch.sum(f0[:, 0, :] * uv, dim=1, keepdim=True) / uv_sum36 37    if random_scale:38        factor = torch.Tensor(f0.shape[0], 1).uniform_(0.8, 1.2).to(f0.device)39    else:40        factor = torch.ones(f0.shape[0], 1).to(f0.device)41    # normalize f0 based on means and factor42    f0_norm = (f0 - means.unsqueeze(-1)) * factor.unsqueeze(-1)43    if torch.isnan(f0_norm).any():44        exit(0)45    return f0_norm * x_mask46def plot_data_to_numpy(x, y):47    global MATPLOTLIB_FLAG48    if not MATPLOTLIB_FLAG:49        import matplotlib50        matplotlib.use("Agg")51        MATPLOTLIB_FLAG = True52        mpl_logger = logging.getLogger('matplotlib')53        mpl_logger.setLevel(logging.WARNING)54    import matplotlib.pylab as plt55    import numpy as np56 57    fig, ax = plt.subplots(figsize=(10, 2))58    plt.plot(x)59    plt.plot(y)60    plt.tight_layout()61 62    fig.canvas.draw()63    data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')64    data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))65    plt.close()66    return data67 68 69def f0_to_coarse(f0):70  f0_mel = 1127 * (1 + f0 / 700).log()71  a = (f0_bin - 2) / (f0_mel_max - f0_mel_min)72  b = f0_mel_min * a - 1.73  f0_mel = torch.where(f0_mel > 0, f0_mel * a - b, f0_mel)74  # torch.clip_(f0_mel, min=1., max=float(f0_bin - 1))75  f0_coarse = torch.round(f0_mel).long()76  f0_coarse = f0_coarse * (f0_coarse > 0)77  f0_coarse = f0_coarse + ((f0_coarse < 1) * 1)78  f0_coarse = f0_coarse * (f0_coarse < f0_bin)79  f0_coarse = f0_coarse + ((f0_coarse >= f0_bin) * (f0_bin - 1))80  return f0_coarse81 82def get_content(cmodel, y):83    with torch.no_grad():84        c = cmodel.extract_features(y.squeeze(1))[0]85    c = c.transpose(1, 2)86    return c87 88def get_f0_predictor(f0_predictor,hop_length,sampling_rate,**kargs):89    if f0_predictor == "pm":90        from modules.F0Predictor.PMF0Predictor import PMF0Predictor91        f0_predictor_object = PMF0Predictor(hop_length=hop_length,sampling_rate=sampling_rate)92    elif f0_predictor == "crepe":93        from modules.F0Predictor.CrepeF0Predictor import CrepeF0Predictor94        f0_predictor_object = CrepeF0Predictor(hop_length=hop_length,sampling_rate=sampling_rate,device=kargs["device"],threshold=kargs["threshold"])95    elif f0_predictor == "harvest":96        from modules.F0Predictor.HarvestF0Predictor import HarvestF0Predictor97        f0_predictor_object = HarvestF0Predictor(hop_length=hop_length,sampling_rate=sampling_rate)98    elif f0_predictor == "dio":99        from modules.F0Predictor.DioF0Predictor import DioF0Predictor100        f0_predictor_object = DioF0Predictor(hop_length=hop_length,sampling_rate=sampling_rate) 101    elif f0_predictor == "rmvpe":102        from modules.F0Predictor.RMVPEF0Predictor import RMVPEF0Predictor103        f0_predictor_object = RMVPEF0Predictor(hop_length=hop_length,sampling_rate=sampling_rate,dtype=torch.float32 ,device=kargs["device"],threshold=kargs["threshold"])104    elif f0_predictor == "fcpe":105        from modules.F0Predictor.FCPEF0Predictor import FCPEF0Predictor106        f0_predictor_object = FCPEF0Predictor(hop_length=hop_length,sampling_rate=sampling_rate,dtype=torch.float32 ,device=kargs["device"],threshold=kargs["threshold"])107    else:108        raise Exception("Unknown f0 predictor")109    return f0_predictor_object110 111def get_speech_encoder(speech_encoder,device=None,**kargs):112    if speech_encoder == "vec768l12":113        from vencoder.ContentVec768L12 import ContentVec768L12114        speech_encoder_object = ContentVec768L12(device = device)115    elif speech_encoder == "vec256l9":116        from vencoder.ContentVec256L9 import ContentVec256L9117        speech_encoder_object = ContentVec256L9(device = device)118    elif speech_encoder == "vec256l9-onnx":119        from vencoder.ContentVec256L9_Onnx import ContentVec256L9_Onnx120        speech_encoder_object = ContentVec256L9_Onnx(device = device)121    elif speech_encoder == "vec256l12-onnx":122        from vencoder.ContentVec256L12_Onnx import ContentVec256L12_Onnx123        speech_encoder_object = ContentVec256L12_Onnx(device = device)124    elif speech_encoder == "vec768l9-onnx":125        from vencoder.ContentVec768L9_Onnx import ContentVec768L9_Onnx126        speech_encoder_object = ContentVec768L9_Onnx(device = device)127    elif speech_encoder == "vec768l12-onnx":128        from vencoder.ContentVec768L12_Onnx import ContentVec768L12_Onnx129        speech_encoder_object = ContentVec768L12_Onnx(device = device)130    elif speech_encoder == "hubertsoft-onnx":131        from vencoder.HubertSoft_Onnx import HubertSoft_Onnx132        speech_encoder_object = HubertSoft_Onnx(device = device)133    elif speech_encoder == "hubertsoft":134        from vencoder.HubertSoft import HubertSoft135        speech_encoder_object = HubertSoft(device = device)136    elif speech_encoder == "whisper-ppg":137        from vencoder.WhisperPPG import WhisperPPG138        speech_encoder_object = WhisperPPG(device = device)139    elif speech_encoder == "cnhubertlarge":140        from vencoder.CNHubertLarge import CNHubertLarge141        speech_encoder_object = CNHubertLarge(device = device)142    elif speech_encoder == "dphubert":143        from vencoder.DPHubert import DPHubert144        speech_encoder_object = DPHubert(device = device)145    elif speech_encoder == "whisper-ppg-large":146        from vencoder.WhisperPPGLarge import WhisperPPGLarge147        speech_encoder_object = WhisperPPGLarge(device = device)148    elif speech_encoder == "wavlmbase+":149        from vencoder.WavLMBasePlus import WavLMBasePlus150        speech_encoder_object = WavLMBasePlus(device = device)151    else:152        raise Exception("Unknown speech encoder")153    return speech_encoder_object 154 155def load_checkpoint(checkpoint_path, model, optimizer=None, skip_optimizer=False):156    assert os.path.isfile(checkpoint_path)157    checkpoint_dict = torch.load(checkpoint_path, map_location='cpu')158    iteration = checkpoint_dict['iteration']159    learning_rate = checkpoint_dict['learning_rate']160    if optimizer is not None and not skip_optimizer and checkpoint_dict['optimizer'] is not None:161        optimizer.load_state_dict(checkpoint_dict['optimizer'])162    saved_state_dict = checkpoint_dict['model']163    model = model.to(list(saved_state_dict.values())[0].dtype)164    if hasattr(model, 'module'):165        state_dict = model.module.state_dict()166    else:167        state_dict = model.state_dict()168    new_state_dict = {}169    for k, v in state_dict.items():170        try:171            # assert "dec" in k or "disc" in k172            # print("load", k)173            new_state_dict[k] = saved_state_dict[k]174            assert saved_state_dict[k].shape == v.shape, (saved_state_dict[k].shape, v.shape)175        except Exception:176            if "enc_q" not in k or "emb_g" not in k:177              print("%s is not in the checkpoint,please check your checkpoint.If you're using pretrain model,just ignore this warning." % k)178              logger.info("%s is not in the checkpoint" % k)179              new_state_dict[k] = v180    if hasattr(model, 'module'):181        model.module.load_state_dict(new_state_dict)182    else:183        model.load_state_dict(new_state_dict)184    print("load ")185    logger.info("Loaded checkpoint '{}' (iteration {})".format(186        checkpoint_path, iteration))187    return model, optimizer, learning_rate, iteration188 189 190def save_checkpoint(model, optimizer, learning_rate, iteration, checkpoint_path):191  logger.info("Saving model and optimizer state at iteration {} to {}".format(192    iteration, checkpoint_path))193  if hasattr(model, 'module'):194    state_dict = model.module.state_dict()195  else:196    state_dict = model.state_dict()197  torch.save({'model': state_dict,198              'iteration': iteration,199              'optimizer': optimizer.state_dict(),200              'learning_rate': learning_rate}, checkpoint_path)201 202def clean_checkpoints(path_to_models='logs/44k/', n_ckpts_to_keep=2, sort_by_time=True):203  """Freeing up space by deleting saved ckpts204 205  Arguments:206  path_to_models    --  Path to the model directory207  n_ckpts_to_keep   --  Number of ckpts to keep, excluding G_0.pth and D_0.pth208  sort_by_time      --  True -> chronologically delete ckpts209                        False -> lexicographically delete ckpts210  """211  ckpts_files = [f for f in os.listdir(path_to_models) if os.path.isfile(os.path.join(path_to_models, f))]212  def name_key(_f):213      return int(re.compile("._(\\d+)\\.pth").match(_f).group(1))214  def time_key(_f):215      return os.path.getmtime(os.path.join(path_to_models, _f))216  sort_key = time_key if sort_by_time else name_key217  def x_sorted(_x):218      return sorted([f for f in ckpts_files if f.startswith(_x) and not f.endswith("_0.pth")], key=sort_key)219  to_del = [os.path.join(path_to_models, fn) for fn in220            (x_sorted('G')[:-n_ckpts_to_keep] + x_sorted('D')[:-n_ckpts_to_keep])]221  def del_info(fn):222      return logger.info(f".. Free up space by deleting ckpt {fn}")223  def del_routine(x):224      return [os.remove(x), del_info(x)]225  [del_routine(fn) for fn in to_del]226 227def summarize(writer, global_step, scalars={}, histograms={}, images={}, audios={}, audio_sampling_rate=22050):228  for k, v in scalars.items():229    writer.add_scalar(k, v, global_step)230  for k, v in histograms.items():231    writer.add_histogram(k, v, global_step)232  for k, v in images.items():233    writer.add_image(k, v, global_step, dataformats='HWC')234  for k, v in audios.items():235    writer.add_audio(k, v, global_step, audio_sampling_rate)236 237 238def latest_checkpoint_path(dir_path, regex="G_*.pth"):239  f_list = glob.glob(os.path.join(dir_path, regex))240  f_list.sort(key=lambda f: int("".join(filter(str.isdigit, f))))241  x = f_list[-1]242  print(x)243  return x244 245 246def plot_spectrogram_to_numpy(spectrogram):247  global MATPLOTLIB_FLAG248  if not MATPLOTLIB_FLAG:249    import matplotlib250    matplotlib.use("Agg")251    MATPLOTLIB_FLAG = True252    mpl_logger = logging.getLogger('matplotlib')253    mpl_logger.setLevel(logging.WARNING)254  import matplotlib.pylab as plt255  import numpy as np256 257  fig, ax = plt.subplots(figsize=(10,2))258  im = ax.imshow(spectrogram, aspect="auto", origin="lower",259                  interpolation='none')260  plt.colorbar(im, ax=ax)261  plt.xlabel("Frames")262  plt.ylabel("Channels")263  plt.tight_layout()264 265  fig.canvas.draw()266  data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')267  data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))268  plt.close()269  return data270 271 272def plot_alignment_to_numpy(alignment, info=None):273  global MATPLOTLIB_FLAG274  if not MATPLOTLIB_FLAG:275    import matplotlib276    matplotlib.use("Agg")277    MATPLOTLIB_FLAG = True278    mpl_logger = logging.getLogger('matplotlib')279    mpl_logger.setLevel(logging.WARNING)280  import matplotlib.pylab as plt281  import numpy as np282 283  fig, ax = plt.subplots(figsize=(6, 4))284  im = ax.imshow(alignment.transpose(), aspect='auto', origin='lower',285                  interpolation='none')286  fig.colorbar(im, ax=ax)287  xlabel = 'Decoder timestep'288  if info is not None:289      xlabel += '\n\n' + info290  plt.xlabel(xlabel)291  plt.ylabel('Encoder timestep')292  plt.tight_layout()293 294  fig.canvas.draw()295  data = np.fromstring(fig.canvas.tostring_rgb(), dtype=np.uint8, sep='')296  data = data.reshape(fig.canvas.get_width_height()[::-1] + (3,))297  plt.close()298  return data299 300 301def load_wav_to_torch(full_path):302  sampling_rate, data = read(full_path)303  return torch.FloatTensor(data.astype(np.float32)), sampling_rate304 305 306def load_filepaths_and_text(filename, split="|"):307  with open(filename, encoding='utf-8') as f:308    filepaths_and_text = [line.strip().split(split) for line in f]309  return filepaths_and_text310 311 312def get_hparams(init=True):313  parser = argparse.ArgumentParser()314  parser.add_argument('-c', '--config', type=str, default="./configs/config.json",315                      help='JSON file for configuration')316  parser.add_argument('-m', '--model', type=str, required=True,317                      help='Model name')318 319  args = parser.parse_args()320  model_dir = os.path.join("./logs", args.model)321 322  if not os.path.exists(model_dir):323    os.makedirs(model_dir)324 325  config_path = args.config326  config_save_path = os.path.join(model_dir, "config.json")327  if init:328    with open(config_path, "r") as f:329      data = f.read()330    with open(config_save_path, "w") as f:331      f.write(data)332  else:333    with open(config_save_path, "r") as f:334      data = f.read()335  config = json.loads(data)336 337  hparams = HParams(**config)338  hparams.model_dir = model_dir339  return hparams340 341 342def get_hparams_from_dir(model_dir):343  config_save_path = os.path.join(model_dir, "config.json")344  with open(config_save_path, "r") as f:345    data = f.read()346  config = json.loads(data)347 348  hparams =HParams(**config)349  hparams.model_dir = model_dir350  return hparams351 352 353def get_hparams_from_file(config_path, infer_mode = False):354  with open(config_path, "r") as f:355    data = f.read()356  config = json.loads(data)357  hparams =HParams(**config) if not infer_mode else InferHParams(**config)358  return hparams359 360 361def check_git_hash(model_dir):362  source_dir = os.path.dirname(os.path.realpath(__file__))363  if not os.path.exists(os.path.join(source_dir, ".git")):364    logger.warn("{} is not a git repository, therefore hash value comparison will be ignored.".format(365      source_dir366    ))367    return368 369  cur_hash = subprocess.getoutput("git rev-parse HEAD")370 371  path = os.path.join(model_dir, "githash")372  if os.path.exists(path):373    saved_hash = open(path).read()374    if saved_hash != cur_hash:375      logger.warn("git hash values are different. {}(saved) != {}(current)".format(376        saved_hash[:8], cur_hash[:8]))377  else:378    open(path, "w").write(cur_hash)379 380 381def get_logger(model_dir, filename="train.log"):382  global logger383  logger = logging.getLogger(os.path.basename(model_dir))384  logger.setLevel(logging.DEBUG)385 386  formatter = logging.Formatter("%(asctime)s\t%(name)s\t%(levelname)s\t%(message)s")387  if not os.path.exists(model_dir):388    os.makedirs(model_dir)389  h = logging.FileHandler(os.path.join(model_dir, filename))390  h.setLevel(logging.DEBUG)391  h.setFormatter(formatter)392  logger.addHandler(h)393  return logger394 395 396def repeat_expand_2d(content, target_len, mode = 'left'):397    # content : [h, t]398    return repeat_expand_2d_left(content, target_len) if mode == 'left' else repeat_expand_2d_other(content, target_len, mode)399 400 401 402def repeat_expand_2d_left(content, target_len):403    # content : [h, t]404 405    src_len = content.shape[-1]406    target = torch.zeros([content.shape[0], target_len], dtype=torch.float).to(content.device)407    temp = torch.arange(src_len+1) * target_len / src_len408    current_pos = 0409    for i in range(target_len):410        if i < temp[current_pos+1]:411            target[:, i] = content[:, current_pos]412        else:413            current_pos += 1414            target[:, i] = content[:, current_pos]415 416    return target417 418 419# mode : 'nearest'| 'linear'| 'bilinear'| 'bicubic'| 'trilinear'| 'area'420def repeat_expand_2d_other(content, target_len, mode = 'nearest'):421    # content : [h, t]422    content = content[None,:,:]423    target = F.interpolate(content,size=target_len,mode=mode)[0]424    return target425 426 427def mix_model(model_paths,mix_rate,mode):428  mix_rate = torch.FloatTensor(mix_rate)/100429  model_tem = torch.load(model_paths[0])430  models = [torch.load(path)["model"] for path in model_paths]431  if mode == 0:432     mix_rate = F.softmax(mix_rate,dim=0)433  for k in model_tem["model"].keys():434     model_tem["model"][k] = torch.zeros_like(model_tem["model"][k])435     for i,model in enumerate(models):436        model_tem["model"][k] += model[k]*mix_rate[i]437  torch.save(model_tem,os.path.join(os.path.curdir,"output.pth"))438  return os.path.join(os.path.curdir,"output.pth")439  440def change_rms(data1, sr1, data2, sr2, rate):  # 1是输入音频,2是输出音频,rate是2的占比 from RVC441    # print(data1.max(),data2.max())442    rms1 = librosa.feature.rms(443        y=data1, frame_length=sr1 // 2 * 2, hop_length=sr1 // 2444    )  # 每半秒一个点445    rms2 = librosa.feature.rms(y=data2.detach().cpu().numpy(), frame_length=sr2 // 2 * 2, hop_length=sr2 // 2)446    rms1 = torch.from_numpy(rms1).to(data2.device)447    rms1 = F.interpolate(448        rms1.unsqueeze(0), size=data2.shape[0], mode="linear"449    ).squeeze()450    rms2 = torch.from_numpy(rms2).to(data2.device)451    rms2 = F.interpolate(452        rms2.unsqueeze(0), size=data2.shape[0], mode="linear"453    ).squeeze()454    rms2 = torch.max(rms2, torch.zeros_like(rms2) + 1e-6)455    data2 *= (456        torch.pow(rms1, torch.tensor(1 - rate))457        * torch.pow(rms2, torch.tensor(rate - 1))458    )459    return data2460 461def train_index(spk_name,root_dir = "dataset/44k/"):  #from: RVC https://github.com/RVC-Project/Retrieval-based-Voice-Conversion-WebUI462    n_cpu = cpu_count()463    print("The feature index is constructing.")464    exp_dir = os.path.join(root_dir,spk_name)465    listdir_res = []466    for file in os.listdir(exp_dir):467       if ".wav.soft.pt" in file:468          listdir_res.append(os.path.join(exp_dir,file))469    if len(listdir_res) == 0:470        raise Exception("You need to run preprocess_hubert_f0.py!")471    npys = []472    for name in sorted(listdir_res):473        phone = torch.load(name)[0].transpose(-1,-2).numpy()474        npys.append(phone)475    big_npy = np.concatenate(npys, 0)476    big_npy_idx = np.arange(big_npy.shape[0])477    np.random.shuffle(big_npy_idx)478    big_npy = big_npy[big_npy_idx]479    if big_npy.shape[0] > 2e5:480        # if(1):481        info = "Trying doing kmeans %s shape to 10k centers." % big_npy.shape[0]482        print(info)483        try:484            big_npy = (485                MiniBatchKMeans(486                    n_clusters=10000,487                    verbose=True,488                    batch_size=256 * n_cpu,489                    compute_labels=False,490                    init="random",491                )492                .fit(big_npy)493                .cluster_centers_494            )495        except Exception:496            info = traceback.format_exc()497            print(info)498    n_ivf = min(int(16 * np.sqrt(big_npy.shape[0])), big_npy.shape[0] // 39)499    index = faiss.index_factory(big_npy.shape[1] , "IVF%s,Flat" % n_ivf)500    index_ivf = faiss.extract_index_ivf(index)  #501    index_ivf.nprobe = 1502    index.train(big_npy)503    batch_size_add = 8192504    for i in range(0, big_npy.shape[0], batch_size_add):505        index.add(big_npy[i : i + batch_size_add])506    # faiss.write_index(507    #     index,508    #     f"added_{spk_name}.index"509    # )510    print("Successfully build index")511    return index512 513 514class HParams():515  def __init__(self, **kwargs):516    for k, v in kwargs.items():517      if type(v) == dict:518        v = HParams(**v)519      self[k] = v520 521  def keys(self):522    return self.__dict__.keys()523 524  def items(self):525    return self.__dict__.items()526 527  def values(self):528    return self.__dict__.values()529 530  def __len__(self):531    return len(self.__dict__)532 533  def __getitem__(self, key):534    return getattr(self, key)535 536  def __setitem__(self, key, value):537    return setattr(self, key, value)538 539  def __contains__(self, key):540    return key in self.__dict__541 542  def __repr__(self):543    return self.__dict__.__repr__()544 545  def get(self,index):546    return self.__dict__.get(index)547 548  549class InferHParams(HParams):550  def __init__(self, **kwargs):551    for k, v in kwargs.items():552      if type(v) == dict:553        v = InferHParams(**v)554      self[k] = v555 556  def __getattr__(self,index):557    return self.get(index)558 559 560class Volume_Extractor:561    def __init__(self, hop_size = 512):562        self.hop_size = hop_size563        564    def extract(self, audio): # audio: 2d tensor array565        if not isinstance(audio,torch.Tensor):566           audio = torch.Tensor(audio)567        n_frames = int(audio.size(-1) // self.hop_size)568        audio2 = audio ** 2569        audio2 = torch.nn.functional.pad(audio2, (int(self.hop_size // 2), int((self.hop_size + 1) // 2)), mode = 'reflect')570        volume = torch.nn.functional.unfold(audio2[:,None,None,:],(1,self.hop_size),stride=self.hop_size)[:,:,:n_frames].mean(dim=1)[0]571        volume = torch.sqrt(volume)572        return volume573