Spaces:
Sleeping
Sleeping
| #!/usr/bin/env python3 | |
| # -*- coding: utf-8 -*- | |
| # Copyright 2019 Tomoki Hayashi | |
| # MIT License (https://opensource.org/licenses/MIT) | |
| """Calculate statistics of feature files.""" | |
| import argparse | |
| import logging | |
| import os | |
| import numpy as np | |
| import yaml | |
| from sklearn.preprocessing import StandardScaler | |
| from tqdm import tqdm | |
| from parallel_wavegan.datasets import MelDataset, MelSCPDataset | |
| from parallel_wavegan.utils import read_hdf5, write_hdf5 | |
| def main(): | |
| """Run preprocessing process.""" | |
| parser = argparse.ArgumentParser( | |
| description=( | |
| "Compute mean and variance of dumped raw features " | |
| "(See detail in parallel_wavegan/bin/compute_statistics.py)." | |
| ) | |
| ) | |
| parser.add_argument( | |
| "--feats-scp", | |
| "--scp", | |
| default=None, | |
| type=str, | |
| help=( | |
| "kaldi-style feats.scp file. " | |
| "you need to specify either feats-scp or rootdir." | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--rootdir", | |
| type=str, | |
| required=True, | |
| help=( | |
| "directory including feature files. " | |
| "you need to specify either feats-scp or rootdir." | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--config", | |
| type=str, | |
| required=True, | |
| help="yaml format configuration file.", | |
| ) | |
| parser.add_argument( | |
| "--dumpdir", | |
| default=None, | |
| type=str, | |
| required=True, | |
| help=( | |
| "directory to save statistics. if not provided, " | |
| "stats will be saved in the above root directory." | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--target-feats", | |
| type=str, | |
| default="feats", | |
| choices=["feats", "local"], | |
| help="target name to compute statistics.", | |
| ) | |
| parser.add_argument( | |
| "--utt2spk", | |
| default=None, | |
| type=str, | |
| help=( | |
| "kaldi-style spk2utt file. if given, calculate statistics of each speaker." | |
| ), | |
| ) | |
| parser.add_argument( | |
| "--verbose", | |
| type=int, | |
| default=1, | |
| help="logging level. higher is more logging.", | |
| ) | |
| args = parser.parse_args() | |
| # set logger | |
| if args.verbose > 1: | |
| logging.basicConfig( | |
| level=logging.DEBUG, | |
| format="%(asctime)s (%(module)s:%(lineno)d) %(levelname)s: %(message)s", | |
| ) | |
| elif args.verbose > 0: | |
| logging.basicConfig( | |
| level=logging.INFO, | |
| format="%(asctime)s (%(module)s:%(lineno)d) %(levelname)s: %(message)s", | |
| ) | |
| else: | |
| logging.basicConfig( | |
| level=logging.WARN, | |
| format="%(asctime)s (%(module)s:%(lineno)d) %(levelname)s: %(message)s", | |
| ) | |
| logging.warning("Skip DEBUG/INFO messages") | |
| # load config | |
| with open(args.config) as f: | |
| config = yaml.load(f, Loader=yaml.Loader) | |
| config.update(vars(args)) | |
| # check arguments | |
| if (args.feats_scp is not None and args.rootdir is not None) or ( | |
| args.feats_scp is None and args.rootdir is None | |
| ): | |
| raise ValueError("Please specify either --rootdir or --feats-scp.") | |
| # check directory existence | |
| if not os.path.exists(args.dumpdir): | |
| os.makedirs(args.dumpdir) | |
| # get dataset | |
| if args.feats_scp is None: | |
| if config["format"] == "hdf5": | |
| mel_query = "*.h5" | |
| mel_load_fn = lambda x: read_hdf5(x, args.target_feats) # NOQA | |
| elif config["format"] == "npy": | |
| mel_query = f"*-{args.target_feats}.npy" | |
| mel_load_fn = np.load | |
| else: | |
| raise ValueError("support only hdf5 or npy format.") | |
| dataset = MelDataset( | |
| args.rootdir, | |
| mel_query=mel_query, | |
| mel_load_fn=mel_load_fn, | |
| return_utt_id=False if args.utt2spk is None else True, | |
| ) | |
| else: | |
| if args.target_feats != "feats": | |
| raise NotImplementedError("Not supported.") | |
| dataset = MelSCPDataset( | |
| args.feats_scp, | |
| return_utt_id=False if args.utt2spk is None else True, | |
| ) | |
| logging.info(f"The number of files = {len(dataset)}.") | |
| if args.utt2spk is None: | |
| # calculate global statistics | |
| logging.info("Caluculate global statistics.") | |
| scaler = StandardScaler() | |
| for mel in tqdm(dataset): | |
| scaler.partial_fit(mel) | |
| if config["format"] == "hdf5": | |
| write_hdf5( | |
| os.path.join(args.dumpdir, "stats.h5"), | |
| "mean", | |
| scaler.mean_.astype(np.float32), | |
| ) | |
| write_hdf5( | |
| os.path.join(args.dumpdir, "stats.h5"), | |
| "scale", | |
| scaler.scale_.astype(np.float32), | |
| ) | |
| else: | |
| stats = np.stack([scaler.mean_, scaler.scale_], axis=0) | |
| np.save( | |
| os.path.join(args.dumpdir, "stats.npy"), | |
| stats.astype(np.float32), | |
| allow_pickle=False, | |
| ) | |
| else: | |
| # calculate statistics of each speaker | |
| logging.info("Caluculate each speaker statistics.") | |
| with open(args.utt2spk) as f: | |
| lines = [line.replace("\n", "") for line in f.readlines()] | |
| utt2spk = {line.split()[0]: line.split()[1] for line in lines} | |
| spks = list(set(utt2spk.values())) | |
| spk2scaler = {spk: StandardScaler() for spk in spks} | |
| for utt_id, mel in tqdm(dataset): | |
| spk = utt2spk[utt_id] | |
| spk2scaler[spk].partial_fit(mel) | |
| for spk, scaler in spk2scaler.items(): | |
| if config["format"] == "hdf5": | |
| write_hdf5( | |
| os.path.join(args.dumpdir, "stats.h5"), | |
| f"{spk}/mean", | |
| scaler.mean_.astype(np.float32), | |
| ) | |
| write_hdf5( | |
| os.path.join(args.dumpdir, "stats.h5"), | |
| f"{spk}/scale", | |
| scaler.scale_.astype(np.float32), | |
| ) | |
| else: | |
| stats = np.stack([scaler.mean_, scaler.scale_], axis=0) | |
| np.save( | |
| os.path.join(args.dumpdir, f"stats-{spk}.npy"), | |
| stats.astype(np.float32), | |
| allow_pickle=False, | |
| ) | |
| if __name__ == "__main__": | |
| main() | |