Style-Bert-VITS2-RT / resample.py
TAKESHI0\ogawa
up
c282b65
import argparse
import os
from concurrent.futures import ThreadPoolExecutor
import librosa
import pyloudnorm as pyln
import soundfile
from tqdm import tqdm
from common.log import logger
from common.stdout_wrapper import SAFE_STDOUT
from config import config
DEFAULT_BLOCK_SIZE: float = 0.400 # seconds
class BlockSizeException(Exception):
pass
def normalize_audio(data, sr):
meter = pyln.Meter(sr, block_size=DEFAULT_BLOCK_SIZE) # create BS.1770 meter
try:
loudness = meter.integrated_loudness(data)
except ValueError as e:
raise BlockSizeException(e)
# logger.info(f"loudness: {loudness}")
data = pyln.normalize.loudness(data, loudness, -23.0)
return data
def process(item):
spkdir, wav_name, args = item
wav_path = os.path.join(args.in_dir, spkdir, wav_name)
if os.path.exists(wav_path) and wav_path.lower().endswith(".wav"):
wav, sr = librosa.load(wav_path, sr=args.sr)
if args.normalize:
try:
wav = normalize_audio(wav, sr)
except BlockSizeException:
logger.info(
f"Skip normalize due to less than {DEFAULT_BLOCK_SIZE} second audio: {wav_path}"
)
if args.trim:
wav, _ = librosa.effects.trim(wav, top_db=30)
soundfile.write(os.path.join(args.out_dir, spkdir, wav_name), wav, sr)
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument(
"--sr",
type=int,
default=config.resample_config.sampling_rate,
help="sampling rate",
)
parser.add_argument(
"--in_dir",
"-i",
type=str,
default=config.resample_config.in_dir,
help="path to source dir",
)
parser.add_argument(
"--out_dir",
"-o",
type=str,
default=config.resample_config.out_dir,
help="path to target dir",
)
parser.add_argument(
"--num_processes",
type=int,
default=4,
help="cpu_processes",
)
parser.add_argument(
"--normalize",
action="store_true",
default=False,
help="loudness normalize audio",
)
parser.add_argument(
"--trim",
action="store_true",
default=False,
help="trim silence (start and end only)",
)
args, _ = parser.parse_known_args()
# autodl 无卡模式会识别出46个cpu
if args.num_processes == 0:
processes = cpu_count() - 2 if cpu_count() > 4 else 1
else:
processes = args.num_processes
tasks = []
for dirpath, _, filenames in os.walk(args.in_dir):
# 子级目录
spk_dir = os.path.relpath(dirpath, args.in_dir)
spk_dir_out = os.path.join(args.out_dir, spk_dir)
if not os.path.isdir(spk_dir_out):
os.makedirs(spk_dir_out, exist_ok=True)
for filename in filenames:
if filename.lower().endswith(".wav"):
twople = (spk_dir, filename, args)
tasks.append(twople)
if len(tasks) == 0:
logger.error(f"No wav files found in {args.in_dir}")
raise ValueError(f"No wav files found in {args.in_dir}")
# pool = Pool(processes=processes)
# for _ in tqdm(
# pool.imap_unordered(process, tasks), file=SAFE_STDOUT, total=len(tasks)
# ):
# pass
# pool.close()
# pool.join()
with ThreadPoolExecutor(max_workers=processes) as executor:
_ = list(
tqdm(
executor.map(process, tasks),
total=len(tasks),
file=SAFE_STDOUT,
)
)
logger.info("Resampling Done!")