joycent-demo / ParallelWaveGAN /parallel_wavegan /bin /compute_statistics.py
walston's picture
Upload folder using huggingface_hub
66b8580 verified
Raw
History Blame Contribute Delete
6.33 kB
#!/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()