diff --git a/.gitignore b/.gitignore index 7e37724..5bfc69d 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ __pycache__/ *.pyc .DS_Store run*.sh +.vscode \ No newline at end of file diff --git a/datasets/kusal.py b/datasets/kusal.py new file mode 100644 index 0000000..b870956 --- /dev/null +++ b/datasets/kusal.py @@ -0,0 +1,67 @@ +from concurrent.futures import ProcessPoolExecutor +from functools import partial +import glob +import librosa +import numpy as np +import os + +from hparams import hparams +from util import audio + + +def build_from_path(in_dir, out_dir, num_workers=1, tqdm=lambda x: x): + '''Preprocesses the Amy dataset from a given input path into a given output directory.''' + # executor = ProcessPoolExecutor(max_workers=num_workers) + futures = [] + count = 0 + len_files = 0 + # Read all of the .wav files: + paths = {} + for path in glob.glob(os.path.join(in_dir, 'audio', '*.wav')): + prompt_id = os.path.basename(path).split('-')[-2] + paths[prompt_id] = path + + # Read the prompts file: + with open(os.path.join(in_dir, 'prompts.txt'), encoding='utf-8') as f: + for line in f: + parts = line.strip().split('\t') + if len(parts) == 4 and parts[0] in paths: + path = paths[parts[0]] + text = parts[2] + # futures.append(executor.submit(partial(_process_utterance, out_dir, parts[0], path, text))) + futures.append(partial(_process_utterance, out_dir, parts[0], path, text)) + len_files += 1 + # return [future.result() for future in futures] + # return [future() for future in futures] + metadata = [] + for future in tqdm(futures): + try: + data = future() + metadata.append(data) + except: + count += 1 + print("failed to process" , count, "/", len_files) + return metadata + +def _process_utterance(out_dir, prompt_id, wav_path, text): + # Load the audio to a numpy array: + wav = audio.load_wav(wav_path) + # Trim leading and trailing silence: + margin = int(hparams.sample_rate * 0.1) + wav = wav[margin:-margin] + wav, _ = librosa.effects.trim(wav, top_db=40, frame_length=1024, hop_length=256) + + # Compute the linear-scale spectrogram from the wav: + spectrogram = audio.spectrogram(wav).astype(np.float32) + n_frames = spectrogram.shape[1] + + # Compute a mel-scale spectrogram from the wav: + mel_spectrogram = audio.melspectrogram(wav).astype(np.float32) + + # Write the spectrograms to disk: + spectrogram_filename = 'kusal-spec-%s.npy' % prompt_id + mel_filename = 'kusal-mel-%s.npy' % prompt_id + np.save(os.path.join(out_dir, spectrogram_filename), spectrogram.T, allow_pickle=False) + np.save(os.path.join(out_dir, mel_filename), mel_spectrogram.T, allow_pickle=False) + # Return a tuple describing this training example: + return (spectrogram_filename, mel_filename, n_frames, text) diff --git a/eval.py b/eval.py index 8f87aba..3840ff9 100644 --- a/eval.py +++ b/eval.py @@ -43,7 +43,10 @@ def main(): parser.add_argument('--checkpoint', required=True, help='Path to model checkpoint') parser.add_argument('--hparams', default='', help='Hyperparameter overrides as a comma-separated list of name=value pairs') + parser.add_argument('--force_cpu', default=False, help='Force synthesize with cpu') args = parser.parse_args() + if args.force_cpu: + os.environ['CUDA_VISIBLE_DEVICES'] = '' os.environ['TF_CPP_MIN_LOG_LEVEL'] = '2' hparams.parse(args.hparams) run_eval(args) diff --git a/preprocess.py b/preprocess.py index 90e318a..1fef213 100644 --- a/preprocess.py +++ b/preprocess.py @@ -2,7 +2,7 @@ import argparse import os from multiprocessing import cpu_count from tqdm import tqdm -from datasets import amy, blizzard, ljspeech +from datasets import amy, blizzard, ljspeech, kusal from hparams import hparams @@ -30,6 +30,14 @@ def preprocess_amy(args): write_metadata(metadata, out_dir) +def preprocess_kusal(args): + in_dir = os.path.join(args.base_dir, 'kusal') + out_dir = os.path.join(args.base_dir, args.output) + os.makedirs(out_dir, exist_ok=True) + metadata = kusal.build_from_path(in_dir, out_dir, args.num_workers, tqdm=tqdm) + write_metadata(metadata, out_dir) + + def write_metadata(metadata, out_dir): with open(os.path.join(out_dir, 'train.txt'), 'w', encoding='utf-8') as f: for m in metadata: @@ -45,7 +53,7 @@ def main(): parser = argparse.ArgumentParser() parser.add_argument('--base_dir', default=os.path.expanduser('~/tacotron')) parser.add_argument('--output', default='training') - parser.add_argument('--dataset', required=True, choices=['amy', 'blizzard', 'ljspeech']) + parser.add_argument('--dataset', required=True, choices=['amy', 'blizzard', 'ljspeech', 'kusal']) parser.add_argument('--num_workers', type=int, default=cpu_count()) args = parser.parse_args() if args.dataset == 'amy': @@ -54,6 +62,8 @@ def main(): preprocess_blizzard(args) elif args.dataset == 'ljspeech': preprocess_ljspeech(args) + elif args.dataset == 'kusal': + preprocess_kusal(args) if __name__ == "__main__":