From f8606a4840a530cfcb0c9c1f92c31263c9f8a368 Mon Sep 17 00:00:00 2001 From: mrfakename Date: Mon, 7 Apr 2025 18:24:00 -0700 Subject: [PATCH 1/7] Reorganize codebase, move CLI to Click, make pip installable --- .gitignore | 127 +- README.md | 9 +- config.py | 1003 +++++++-- data/combined_dataset.py | 436 +++- data/emilia_preprocessing/encodec.py | 714 +++++-- data/emilia_preprocessing/sha256hash.py | 4 +- data/emilia_preprocessing/step1_download.py | 16 +- .../step4_construct_manifest.py | 61 +- data/emilia_preprocessing/step5_phonemize.py | 51 +- .../step6_encodec_encode.py | 220 +- data/encodec.py | 714 +++++-- data/ll60k_preprocessing/encodec.py | 714 +++++-- .../ll60k_preprocessing/step2_resplit_long.py | 45 +- .../step3_seg_phn_manifest.py | 185 +- .../step4_encodec_encode.py | 230 +- .../step5_find_nearest_neighbor.py | 170 +- .../step6_forced_alignment.py | 79 +- .../step7_ipa_alignment.py | 87 +- data/ll60k_preprocessing/tokenizer.py | 22 +- data/tokenizer.py | 73 +- generated_tts/generated.wav | Bin 251598 -> 503120 bytes inference_gradio.py | 113 +- inference_tts_utils.py | 213 +- models/voice_star.py | 784 ------- copy_codebase.py => scripts/copy_codebase.py | 7 +- {z_scripts_new => scripts}/e1_840M_30s.sh | 0 setup.py | 47 + steps/optim.py | 113 +- steps/trainer.py | 892 +++++--- steps/trainer_utils.py | 184 +- main.py => train/train.py | 40 +- voicestar/__init__.py | 202 ++ voicestar/api.py | 380 ++++ inference_commandline.py => voicestar/cli.py | 133 +- .../modules => voicestar/data}/__init__.py | 0 voicestar/data/encodec.py | 1842 +++++++++++++++++ .../.gitkeep => voicestar/modules/__init__.py | 0 {models => voicestar}/modules/activation.py | 251 ++- {models => voicestar}/modules/embedding.py | 50 +- {models => voicestar}/modules/sampling.py | 27 +- {models => voicestar}/modules/scaling.py | 110 +- {models => voicestar}/modules/transformer.py | 452 ++-- {models => voicestar}/modules/utils.py | 15 +- {models => voicestar}/modules/visualizer.py | 15 +- voicestar/utils.py | 32 + voicestar/voicestar.py | 1042 ++++++++++ 46 files changed, 8804 insertions(+), 3100 deletions(-) delete mode 100644 models/voice_star.py rename copy_codebase.py => scripts/copy_codebase.py (94%) rename {z_scripts_new => scripts}/e1_840M_30s.sh (100%) create mode 100644 setup.py rename main.py => train/train.py (69%) create mode 100644 voicestar/__init__.py create mode 100644 voicestar/api.py rename inference_commandline.py => voicestar/cli.py (52%) rename {models/modules => voicestar/data}/__init__.py (100%) create mode 100644 voicestar/data/encodec.py rename pretrained/.gitkeep => voicestar/modules/__init__.py (100%) rename {models => voicestar}/modules/activation.py (83%) rename {models => voicestar}/modules/embedding.py (79%) rename {models => voicestar}/modules/sampling.py (88%) rename {models => voicestar}/modules/scaling.py (94%) rename {models => voicestar}/modules/transformer.py (75%) rename {models => voicestar}/modules/utils.py (79%) rename {models => voicestar}/modules/visualizer.py (88%) create mode 100644 voicestar/utils.py create mode 100644 voicestar/voicestar.py diff --git a/.gitignore b/.gitignore index 7fa359a..37c40aa 100644 --- a/.gitignore +++ b/.gitignore @@ -1,39 +1,114 @@ -__pycache__/ -*.py[cod] *$py.class +*.cover +*.egg *.egg-info -.pytest_cache -.ipynb_checkpoints - -thumbs.db -.DS_Store -.idea +*.egg-info/ +*.flac +*.gz *.log -*rtx* -*.pdf +*.manifest *.mkv +*.mo +*.mp3 *.mp4 -*a40* -*durip* +*.pdf *.png -sim_lr.ipynb -*.mp3 -*.gz -*.flac -*.th -*.pth +*.pot *.pt -local_* +*.pth +*.py,cover +*.py[cod] +*.sage.py +*.so +*.spec +*.th +*a40* +*durip* +*rtx* +.cache +.coverage +.coverage.* +.dmypy.json +.DS_Store +.eggs/ +.env +.hypothesis/ +.idea +.installed.cfg +.ipynb_checkpoints +.mypy_cache/ +.nox/ +.pdm-build/ +.pdm-python +.pdm.toml +.pybuilder/ +.pypirc +.pyre/ +.pytest_cache +.pytest_cache/ +.Python +.pytype/ +.ropeproject +.ruff_cache/ +.scrapy +.spyderproject +.spyproject +.tox/ +.venv +.webassets-cache +/site +amt/ +bad_files/ +build/ +celerybeat-schedule +celerybeat.pid +cover/ +coverage.xml +cython_debug/ +db.sqlite3 +db.sqlite3-journal +demo/generated_tts +develop-eggs/ +dist/ +dmypy.json +docs/_build/ +downloads/ +eggs/ +env.bak/ +env/ +ENV/ +file_log.txt +file_log_debug*.txt +htmlcov/ hub/ +instance/ +ipython_config.py +lib/ +lib64/ +local_* +local_settings.py +MANIFEST +nosetests.xml +parts/ per_sample_res/ -src/ -res/seed_tts_eval/ +pip-delete-this-directory.txt +pip-log.txt +profile_default/ res/lspc_eval -file_log.txt -file_log_debug*.txt -bad_files/ -amt/ +res/seed_tts_eval/ sam1.wav sam2.wav sam3.wav -demo/generated_tts \ No newline at end of file +sdist/ +share/python-wheels/ +sim_lr.ipynb +src/ +target/ +thumbs.db +var/ +venv.bak/ +venv/ +wheels/ +__pycache__/ +__pypackages__/ +generated_tts/ \ No newline at end of file diff --git a/README.md b/README.md index 3b9096c..5cccfc6 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# VoiceStar: Robust, Duration-controllable TTS that can Extrapolate +# VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate ## TODO - [x] Gradio demo ETA: 6 April 2025 @@ -8,9 +8,10 @@ ### Download model ```bash # under VoiceStar root dir -wget -O ./pretrained/encodec_6f79c6a8.th https://huggingface.co/pyp1/VoiceCraft/resolve/main/encodec_4cb2048_giga.th?download=true -wget -O ./pretrained/VoiceStar_840M_30s.pth https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_30s.pth?download=true -wget -O ./pretrained/VoiceStar_840M_40s.pth https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_40s.pth?download=true +mkdir pretrained +wget -O ./pretrained/encodec_6f79c6a8.th "https://huggingface.co/pyp1/VoiceCraft/resolve/main/encodec_4cb2048_giga.th" +wget -O ./pretrained/VoiceStar_840M_30s.pth "https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_30s.pth" +wget -O ./pretrained/VoiceStar_840M_40s.pth "https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_40s.pth" ``` ### Inference only: ```bash diff --git a/config.py b/config.py index 50d241b..1338dfa 100644 --- a/config.py +++ b/config.py @@ -1,5 +1,6 @@ import argparse + def int_or_str(value): """Custom function to allow both int and str types.""" try: @@ -7,219 +8,841 @@ def int_or_str(value): except ValueError: return value # If conversion fails, return as string + def MyParser(): - parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) - # general training + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + # general training parser.add_argument("--seed", type=int, default=1) parser.add_argument("--debug", type=int, default=0) parser.add_argument("--multinodes", type=int, default=0) parser.add_argument("--dist_url", default="env://", type=str) parser.add_argument("--dist_backend", default="nccl", type=str) - parser.add_argument("--precision", type=str, default="float16", help="we might need float32 for NAR model") + parser.add_argument( + "--precision", + type=str, + default="float16", + help="we might need float32 for NAR model", + ) parser.add_argument("--num_workers", type=int, default=8, help="per gpu") parser.add_argument("--resume", action="store_true", default=False) parser.add_argument("--tb_write_every_n_steps", type=int, default=100) parser.add_argument("--print_every_n_steps", type=int, default=250) parser.add_argument("--val_every_n_steps", type=int, default=500) - parser.add_argument("--inference_every_n_steps", type=int, default=3000, help="will only get to inference when model is saved, and therefore this needs to be multiple of val_every_n_steps") - parser.add_argument("--save_every_n_steps", type=int, default=10000000, help="save the model every n steps, will save the model as bundle_step$step.pth") + parser.add_argument( + "--inference_every_n_steps", + type=int, + default=3000, + help="will only get to inference when model is saved, and therefore this needs to be multiple of val_every_n_steps", + ) + parser.add_argument( + "--save_every_n_steps", + type=int, + default=10000000, + help="save the model every n steps, will save the model as bundle_step$step.pth", + ) parser.add_argument("--lr", type=float, default=1e-4) - parser.add_argument("--batch_size", type=int, default=100, help="this is the effective batch size per gpu, no matter whether using gradient_accumulation_steps") + parser.add_argument( + "--batch_size", + type=int, + default=100, + help="this is the effective batch size per gpu, no matter whether using gradient_accumulation_steps", + ) parser.add_argument("--weight_decay", type=float, default=1e-2) - parser.add_argument("--warmup_fraction", type=float, default=0.1, help="use linear warmup, the proportion of the training steps that are used for warming up") + parser.add_argument( + "--warmup_fraction", + type=float, + default=0.1, + help="use linear warmup, the proportion of the training steps that are used for warming up", + ) parser.add_argument("--num_epochs", type=int, default=10) - parser.add_argument("--num_steps", type=int, default=None, help="if not None, will ignore n_epochs and use num_steps as the total number of amount of training, can try e.g. 400000 i.e. 400k steps") + parser.add_argument( + "--num_steps", + type=int, + default=None, + help="if not None, will ignore n_epochs and use num_steps as the total number of amount of training, can try e.g. 400000 i.e. 400k steps", + ) parser.add_argument("--gradient_accumulation_steps", type=int, default=1) - parser.add_argument("--gradient_clip_val", type=float, default=1.0, help="the value for torch.nn.utils.clip_grad_norm_()") - parser.add_argument("--early_stop_step", type=int, default=3200, help="stop training after this many steps of non-improvement") - parser.add_argument("--early_stop_threshold", type=float, default=-1.0, help="early stop after the improvement is below this threshold for certain number of steps") - + parser.add_argument( + "--gradient_clip_val", + type=float, + default=1.0, + help="the value for torch.nn.utils.clip_grad_norm_()", + ) + parser.add_argument( + "--early_stop_step", + type=int, + default=3200, + help="stop training after this many steps of non-improvement", + ) + parser.add_argument( + "--early_stop_threshold", + type=float, + default=-1.0, + help="early stop after the improvement is below this threshold for certain number of steps", + ) # path - parser.add_argument("--exp_dir", type=str, default='/saltpool0/scratch/pyp/VoiceEditor/', help="will be combined with dataset name") - parser.add_argument("--dataset", type=str, help="e.g. 'libritts', 'librilight', 'spotify', they are folder name in the data dir also") - parser.add_argument("--dataset_dir", type=str, help="need to be compatible with corresponding dataset py file") - parser.add_argument("--compact_folder_name", type=str, default=None, help="if not None, will use compact_combined_dataset.py, and this is the folder name of the compact dataset") - parser.add_argument("--inference_dataset_dir", type=str, default="/data/scratch/pyp/datasets/librilight/preprocessed", help="need to be compatible with corresponding dataset py file") - - parser.add_argument("--training_stage", type=int, default=1, help="if 1, train VoiceEditor_one, if 2 train VoiceEditor_seven") - parser.add_argument("--local_wandb", type=int, default=0, help="if 1, will use local wandb, otherwise use the global one") - parser.add_argument("--wandb_entity", type=str, default="puyuanpeng", help="the entity (usually your username) for wandb") + parser.add_argument( + "--exp_dir", + type=str, + default="/saltpool0/scratch/pyp/VoiceEditor/", + help="will be combined with dataset name", + ) + parser.add_argument( + "--dataset", + type=str, + help="e.g. 'libritts', 'librilight', 'spotify', they are folder name in the data dir also", + ) + parser.add_argument( + "--dataset_dir", + type=str, + help="need to be compatible with corresponding dataset py file", + ) + parser.add_argument( + "--compact_folder_name", + type=str, + default=None, + help="if not None, will use compact_combined_dataset.py, and this is the folder name of the compact dataset", + ) + parser.add_argument( + "--inference_dataset_dir", + type=str, + default="/data/scratch/pyp/datasets/librilight/preprocessed", + help="need to be compatible with corresponding dataset py file", + ) + + parser.add_argument( + "--training_stage", + type=int, + default=1, + help="if 1, train VoiceEditor_one, if 2 train VoiceEditor_seven", + ) + parser.add_argument( + "--local_wandb", + type=int, + default=0, + help="if 1, will use local wandb, otherwise use the global one", + ) + parser.add_argument( + "--wandb_entity", + type=str, + default="puyuanpeng", + help="the entity (usually your username) for wandb", + ) # data - parser.add_argument("--librilight_ratio", type=float, default=1, help='the portion of lightlight compared to gigaspeech, 1 means equal, 2 means librilight data is twice as much as gigaspeech') - parser.add_argument("--plus_librilight_root", type=str, default=None, help="if not None, will combine gigaspeech and librilight, this is the root folder to librilight. Note that will need to merge the vocab.txt based on gigaspeech's, in order to be able to load a pretrained model") - parser.add_argument("--plus_librilight_phn_folder_name", type=str, default=None, help="if not None, will combine gigaspeech and librilight, this is the phoneme folder name of librilight") - parser.add_argument("--plus_librilight_encodec_folder_name", type=str, default=None, help="if not None, will combine gigaspeech and librilight, this is the encodec folder name of librilight") - parser.add_argument("--plus_librilight_manifest_name", type=str, default=None, help="if not None, will combine gigaspeech and librilight, this is the manifest folder name of librilight") - parser.add_argument("--skip_us", type=int, default=0, help="skip the giga utterances that contains 'j uː ɛ s' because of the tokenization issue") - parser.add_argument("--pseudo_epoch_size", type=int, default=37901, help="only use for Eden scheduler. 37901 is the epoch size in the default optim setting, this is probably too big") - parser.add_argument("--switch_order", type=int, default=0, help="this is only for hificodec, where we switch the order of 2 and 3nd codebook") - parser.add_argument("--phn_folder_name", type=str, default="phoneme", help="for libritts I also have arpa phns, in which case should be phonemes_arpa") - parser.add_argument("--encodec_folder_name", type=str, default="mimi_8cb", help="folder where encodec codes are stored") - parser.add_argument("--manifest_name", type=str, default="manifest_final", help="if using hificodec, it should be hificodec_menifest, if using encodec, it is the default") - parser.add_argument("--pad_x", type=int, default=1, help="whether or not always pad x to have text_max_length. select 1 to get the maximal memory consumption, but the actual case should be smaller, better to have it being 0") - parser.add_argument("--max_num_tokens", type=int, default=18750, help="max number of encodec tokens per gpu, this is only used when using dynamic batching, will ignore batch size. Note that batch size is the final effective batch size (sum of batch on each gpu), but max_num_tokens is per gpu") - parser.add_argument("--val_max_num_tokens", type=int, default=6000, help="FOR validation, this basically is for music-gen because of high mem consumption. max number of encodec tokens per gpu, this is only used when using dynamic batching, will ignore batch size. Note that batch size is the final effective batch size (sum of batch on each gpu), but max_num_tokens is per gpu") + parser.add_argument( + "--librilight_ratio", + type=float, + default=1, + help="the portion of lightlight compared to gigaspeech, 1 means equal, 2 means librilight data is twice as much as gigaspeech", + ) + parser.add_argument( + "--plus_librilight_root", + type=str, + default=None, + help="if not None, will combine gigaspeech and librilight, this is the root folder to librilight. Note that will need to merge the vocab.txt based on gigaspeech's, in order to be able to load a pretrained model", + ) + parser.add_argument( + "--plus_librilight_phn_folder_name", + type=str, + default=None, + help="if not None, will combine gigaspeech and librilight, this is the phoneme folder name of librilight", + ) + parser.add_argument( + "--plus_librilight_encodec_folder_name", + type=str, + default=None, + help="if not None, will combine gigaspeech and librilight, this is the encodec folder name of librilight", + ) + parser.add_argument( + "--plus_librilight_manifest_name", + type=str, + default=None, + help="if not None, will combine gigaspeech and librilight, this is the manifest folder name of librilight", + ) + parser.add_argument( + "--skip_us", + type=int, + default=0, + help="skip the giga utterances that contains 'j uː ɛ s' because of the tokenization issue", + ) + parser.add_argument( + "--pseudo_epoch_size", + type=int, + default=37901, + help="only use for Eden scheduler. 37901 is the epoch size in the default optim setting, this is probably too big", + ) + parser.add_argument( + "--switch_order", + type=int, + default=0, + help="this is only for hificodec, where we switch the order of 2 and 3nd codebook", + ) + parser.add_argument( + "--phn_folder_name", + type=str, + default="phoneme", + help="for libritts I also have arpa phns, in which case should be phonemes_arpa", + ) + parser.add_argument( + "--encodec_folder_name", + type=str, + default="mimi_8cb", + help="folder where encodec codes are stored", + ) + parser.add_argument( + "--manifest_name", + type=str, + default="manifest_final", + help="if using hificodec, it should be hificodec_menifest, if using encodec, it is the default", + ) + parser.add_argument( + "--pad_x", + type=int, + default=1, + help="whether or not always pad x to have text_max_length. select 1 to get the maximal memory consumption, but the actual case should be smaller, better to have it being 0", + ) + parser.add_argument( + "--max_num_tokens", + type=int, + default=18750, + help="max number of encodec tokens per gpu, this is only used when using dynamic batching, will ignore batch size. Note that batch size is the final effective batch size (sum of batch on each gpu), but max_num_tokens is per gpu", + ) + parser.add_argument( + "--val_max_num_tokens", + type=int, + default=6000, + help="FOR validation, this basically is for music-gen because of high mem consumption. max number of encodec tokens per gpu, this is only used when using dynamic batching, will ignore batch size. Note that batch size is the final effective batch size (sum of batch on each gpu), but max_num_tokens is per gpu", + ) parser.add_argument("--num_buckets", type=int, default=10) parser.add_argument("--dynamic_batching", type=int, default=1) - parser.add_argument("--audio_max_length", type=float, default=120, help="in second, crop the audio is length is longer than this") - parser.add_argument("--audio_min_length", type=float, default=2, help="in second, drop the audio if length is shorter than this") - parser.add_argument("--text_max_length", type=int, default=1000, help='if too long, we crop') - parser.add_argument("--text_min_length", type=float, default=10, help="if too short, will drop") - parser.add_argument("--encodec_sr", type=float, default=50, help="for 24kHz mimi model, it produces 12.5 codes for 1 sec of audio") - parser.add_argument('--mask_len_min', type=int, default=20, help='Minimum mask length') - parser.add_argument('--mask_len_max', type=int, default=400, help='Maximum mask length') - parser.add_argument('--extra_mask_len_min', type=int, default=2, help='Minimum extra mask length') - parser.add_argument('--extra_mask_len_max', type=int, default=20, help='Maximum extra mask length') - parser.add_argument('--final_audio_token_len', type=int, default=772, help="this is only for stage 1 training, since we add eog, start_of_continue, and a random amount of extra mask, --audio_max_length won't be the final max length, the self.args.final_audio_token_len = self.args.audio_max_length*self.args.encodec_sr+self.args.extra_mask_len_max+2 ") + parser.add_argument( + "--audio_max_length", + type=float, + default=120, + help="in second, crop the audio is length is longer than this", + ) + parser.add_argument( + "--audio_min_length", + type=float, + default=2, + help="in second, drop the audio if length is shorter than this", + ) + parser.add_argument( + "--text_max_length", type=int, default=1000, help="if too long, we crop" + ) + parser.add_argument( + "--text_min_length", type=float, default=10, help="if too short, will drop" + ) + parser.add_argument( + "--encodec_sr", + type=float, + default=50, + help="for 24kHz mimi model, it produces 12.5 codes for 1 sec of audio", + ) + parser.add_argument( + "--mask_len_min", type=int, default=20, help="Minimum mask length" + ) + parser.add_argument( + "--mask_len_max", type=int, default=400, help="Maximum mask length" + ) + parser.add_argument( + "--extra_mask_len_min", type=int, default=2, help="Minimum extra mask length" + ) + parser.add_argument( + "--extra_mask_len_max", type=int, default=20, help="Maximum extra mask length" + ) + parser.add_argument( + "--final_audio_token_len", + type=int, + default=772, + help="this is only for stage 1 training, since we add eog, start_of_continue, and a random amount of extra mask, --audio_max_length won't be the final max length, the self.args.final_audio_token_len = self.args.audio_max_length*self.args.encodec_sr+self.args.extra_mask_len_max+2 ", + ) # model - parser.add_argument("--ttsonly", default=0, type=int, help="if 1, only train tts model, no CM3") - parser.add_argument("--load_existing_text_embedding", type=int, default=0, help="if 1, when load model and the text vocab doesn't match, will load the existing weights while the new weights will be initialized randomly") - parser.add_argument("--fly", type=int, default=0, help="if 1, encode chunked audio on the fly") - parser.add_argument("--encodec_ckpt", type=str, default="/data/scratch/pyp/exp_pyp/audiocraft/encodec/xps/6f79c6a8/checkpoint.th") - parser.add_argument("--downsample_rate", type=int, default=320, help="the downsample rate for the encodec model, 16000/320 = 50Hz") - parser.add_argument("--segtts_mask", type=int, default=0, help="if 1, use segtts_mask model, where we have a prefix and segment utterance into two and shifted separately for modeling, and use make use of mask:0, by insert two mask:0 in the middle of the two segments") - parser.add_argument("--segtts", type=int, default=0, help="if 1, use segtts model, where we have a prefix and segment utterance into two and shifted separately for modeling") - parser.add_argument("--edge", type=int, default=0, help="if 1, use edge prediction for the first codebook") - parser.add_argument("--duration_loss_weight", type=float, default=1.0, help="weight on the duration loss") - parser.add_argument("--drop_long", type=int, default=1, help="if this is true, will drop example whose encodec sequence or phone sequence is too long, rather than cropping as we did before, to avoid hellucination") - parser.add_argument("--eos", type=int, default=2051, help="this is to be used with reduced_eog, where we end the utterance with eos, and end the generated segment with eog, also when this is used, the n_special should be 4") - parser.add_argument("--reduced_eog", type=int, default=1, help="for the non-final segments, do not insert eog at the end, this could hopefully solve the early stopping issue when doing tts") - - parser.add_argument("--valle_orig", type=int, default=0, help="the original valle model, trained for TTS") - parser.add_argument("--valle_max_prompt_len", type=float, default=6, help='in sec.') + parser.add_argument( + "--ttsonly", default=0, type=int, help="if 1, only train tts model, no CM3" + ) + parser.add_argument( + "--load_existing_text_embedding", + type=int, + default=0, + help="if 1, when load model and the text vocab doesn't match, will load the existing weights while the new weights will be initialized randomly", + ) + parser.add_argument( + "--fly", type=int, default=0, help="if 1, encode chunked audio on the fly" + ) + parser.add_argument( + "--encodec_ckpt", + type=str, + default="/data/scratch/pyp/exp_pyp/audiocraft/encodec/xps/6f79c6a8/checkpoint.th", + ) + parser.add_argument( + "--downsample_rate", + type=int, + default=320, + help="the downsample rate for the encodec model, 16000/320 = 50Hz", + ) + parser.add_argument( + "--segtts_mask", + type=int, + default=0, + help="if 1, use segtts_mask model, where we have a prefix and segment utterance into two and shifted separately for modeling, and use make use of mask:0, by insert two mask:0 in the middle of the two segments", + ) + parser.add_argument( + "--segtts", + type=int, + default=0, + help="if 1, use segtts model, where we have a prefix and segment utterance into two and shifted separately for modeling", + ) + parser.add_argument( + "--edge", + type=int, + default=0, + help="if 1, use edge prediction for the first codebook", + ) + parser.add_argument( + "--duration_loss_weight", + type=float, + default=1.0, + help="weight on the duration loss", + ) + parser.add_argument( + "--drop_long", + type=int, + default=1, + help="if this is true, will drop example whose encodec sequence or phone sequence is too long, rather than cropping as we did before, to avoid hellucination", + ) + parser.add_argument( + "--eos", + type=int, + default=2051, + help="this is to be used with reduced_eog, where we end the utterance with eos, and end the generated segment with eog, also when this is used, the n_special should be 4", + ) + parser.add_argument( + "--reduced_eog", + type=int, + default=1, + help="for the non-final segments, do not insert eog at the end, this could hopefully solve the early stopping issue when doing tts", + ) + + parser.add_argument( + "--valle_orig", + type=int, + default=0, + help="the original valle model, trained for TTS", + ) + parser.add_argument("--valle_max_prompt_len", type=float, default=6, help="in sec.") # randomly choose a portion as tts examples during training - parser.add_argument("--tts_portion", type=float, default=0, help="randomly choose a portion of the training examples as tts examples, where no mask and rearrangement is used") + parser.add_argument( + "--tts_portion", + type=float, + default=0, + help="randomly choose a portion of the training examples as tts examples, where no mask and rearrangement is used", + ) # put special tokens first to handle different vocab_size - parser.add_argument("--special_first", type=int, default=0, help="if 1, need to have special tokens to be the first few tokens, e.g. 0, 1, 2, which means we need to adjust the preprocessing and postprocessing of the encodec codes. note that we hard coded to have 3 special tokens") + parser.add_argument( + "--special_first", + type=int, + default=0, + help="if 1, need to have special tokens to be the first few tokens, e.g. 0, 1, 2, which means we need to adjust the preprocessing and postprocessing of the encodec codes. note that we hard coded to have 3 special tokens", + ) parser.add_argument("--n_special", type=int, default=4, help="empty, eog, pad, eos") # weight codebook differently - parser.add_argument("--codebook_weight", type=str, default=None, help="e.g. ['5','1','0.5','0.1']") + parser.add_argument( + "--codebook_weight", type=str, default=None, help="e.g. ['5','1','0.5','0.1']" + ) # args for MusicGen - parser.add_argument("--mask_span_weight", default=1.0, type=float, help="the weight on the tokens in masked span") - parser.add_argument("--unmask_span_weight", default=1.0, type=float, help="the weight on unmasked span") - parser.add_argument("--start_end_weight", default=None, type=str, help="weight the start x tokens and end x tokens differently, e.g. (10,2.0), means x == 10, weight==2.0") + parser.add_argument( + "--mask_span_weight", + default=1.0, + type=float, + help="the weight on the tokens in masked span", + ) + parser.add_argument( + "--unmask_span_weight", + default=1.0, + type=float, + help="the weight on unmasked span", + ) + parser.add_argument( + "--start_end_weight", + default=None, + type=str, + help="weight the start x tokens and end x tokens differently, e.g. (10,2.0), means x == 10, weight==2.0", + ) # for now not consider the two weights above, only consider eog_weight, which is defined below somewhere, as the above two are not super principled - parser.add_argument("--musicgen", type=int, default=0, help="whether or not use this model, will also have an impact on the output shape of the dataset") - parser.add_argument("--enc_dec", default=0, type=int, help="use enc-dec architecture, text is from the enc, only for musicgen") - parser.add_argument("--dec", default=0, type=int, help="use dec only architecture, text is from the enc, only for musicgen. Exclusive with --enc_dec") - parser.add_argument("--empty_token", default=2048, type=int, help="indicating the no token at the position for the codebook") + parser.add_argument( + "--musicgen", + type=int, + default=0, + help="whether or not use this model, will also have an impact on the output shape of the dataset", + ) + parser.add_argument( + "--enc_dec", + default=0, + type=int, + help="use enc-dec architecture, text is from the enc, only for musicgen", + ) + parser.add_argument( + "--dec", + default=0, + type=int, + help="use dec only architecture, text is from the enc, only for musicgen. Exclusive with --enc_dec", + ) + parser.add_argument( + "--empty_token", + default=2048, + type=int, + help="indicating the no token at the position for the codebook", + ) # args for the optimizer and scheduler from Feiteng # original setup for the 3 params are 5000 4 and 1000 # but that's because set_epoch is run on num_gradient_accumulation_step*step (with 4 being the accumulation step) # so I scaled down them a little bit # will try scaling them back if this doesn't work - parser.add_argument("--optimizer_name", type=str, default="AdamW", help="can also use ScaledAdam, in which case we'll also use the Eden scheduler") - parser.add_argument("--reduce_lr_start_step", type=int, default=3000, help='after which significantly reduce the lr. a param for the eden optimizer') + parser.add_argument( + "--optimizer_name", + type=str, + default="AdamW", + help="can also use ScaledAdam, in which case we'll also use the Eden scheduler", + ) + parser.add_argument( + "--reduce_lr_start_step", + type=int, + default=3000, + help="after which significantly reduce the lr. a param for the eden optimizer", + ) parser.add_argument("--reduce_lr_start_epoch", type=int, default=4) parser.add_argument("--clipping_update_period", type=int, default=600) - # below are args for valle # below are args for valle - parser.add_argument("--valle", type=int, default=0, help="if 1, use valle model (cm3)") + parser.add_argument( + "--valle", type=int, default=0, help="if 1, use valle model (cm3)" + ) parser.add_argument("--decoder_dim", type=int, default=1024) parser.add_argument("--norm_first", action="store_true", default=True) parser.add_argument("--add_prenet", action="store_true", default=False) - parser.add_argument("--prefix_mode", type=int, default=5, help="this is for NAR, we only do 5, which is CM3") + parser.add_argument( + "--prefix_mode", + type=int, + default=5, + help="this is for NAR, we only do 5, which is CM3", + ) parser.add_argument("--share_embedding", action="store_true", default=False) parser.add_argument("--nar_scale_factor", type=float, default=1.0) parser.add_argument("--prepend_bos", action="store_true", default=False) - parser.add_argument("--sync_nar", type=int, default=0, help="whether to choose the same NAR model to run for training_stage==2 across different process (this is only for DDP)") + parser.add_argument( + "--sync_nar", + type=int, + default=0, + help="whether to choose the same NAR model to run for training_stage==2 across different process (this is only for DDP)", + ) # above are args for valle # above are args for valle + # add parallel_pattern + parser.add_argument( + "--parallel_pattern", + type=int, + default=0, + help="if 1, use parallel pattern, we also use LFSC codec", + ) + parser.add_argument( + "--full_prediction", + type=int, + default=0, + help="this is for ve1, if 1, use full autoregressive mask, and calculate loss over all tokens, except for mask_tokens", + ) + parser.add_argument( + "--multicm3", + type=int, + default=0, + help="cm3 model but allows multiple mask spans", + ) + parser.add_argument( + "--max_mask_portion", + type=float, + default=0.7, + help="should mask a utterance for more than this portion", + ) + parser.add_argument( + "--max_n_spans", + type=int, + default=8, + help="maximal number of spans, only use when using multicm3, this is used to decide number of mask_embedding, and max clamp value if use Poisson distribution, if use uniform distribution to sample number of spans if will be uniform(1,max_n_spans)", + ) + parser.add_argument( + "--shuffle_mask_embedding", + type=int, + default=0, + help="whether shuffle the mask embedding, so that mask:0 is not the most well trained, default is not shuffling. The default has it's benefit, as it make sure that mask:0 always appear the first", + ) + parser.add_argument( + "--mask_sample_dist", + type=str, + default="uniform", + help="uniform or poissonx, e.g. poisson1, meaning the parameter lambda is 1, it will most likely sample 1 masks", + ) + parser.add_argument( + "--min_gap", + type=int, + default=10, + help="after sampled starts, delete later one if it closer to the former start than the min_gap", + ) + parser.add_argument( + "--cm3", + type=int, + default=0, + help="use cm3 style for ve1, the input from dataloader is going to be just raw data, all masking and rearrangement will happen whin the model", + ) - # add parallel_pattern - parser.add_argument("--parallel_pattern", type=int, default=0, help="if 1, use parallel pattern, we also use LFSC codec") - parser.add_argument("--full_prediction", type=int, default=0, help='this is for ve1, if 1, use full autoregressive mask, and calculate loss over all tokens, except for mask_tokens') - parser.add_argument("--multicm3", type=int, default=0, help='cm3 model but allows multiple mask spans') - parser.add_argument("--max_mask_portion",type=float,default=0.7,help="should mask a utterance for more than this portion") - parser.add_argument("--max_n_spans", type=int, default=8, help='maximal number of spans, only use when using multicm3, this is used to decide number of mask_embedding, and max clamp value if use Poisson distribution, if use uniform distribution to sample number of spans if will be uniform(1,max_n_spans)') - parser.add_argument("--shuffle_mask_embedding", type=int, default=0, help="whether shuffle the mask embedding, so that mask:0 is not the most well trained, default is not shuffling. The default has it's benefit, as it make sure that mask:0 always appear the first") - parser.add_argument("--mask_sample_dist", type=str, default="uniform", help="uniform or poissonx, e.g. poisson1, meaning the parameter lambda is 1, it will most likely sample 1 masks") - parser.add_argument("--min_gap", type=int, default=10, help="after sampled starts, delete later one if it closer to the former start than the min_gap") - - parser.add_argument('--cm3', type=int, default=0, help="use cm3 style for ve1, the input from dataloader is going to be just raw data, all masking and rearrangement will happen whin the model") - - parser.add_argument('--sep_special_token', type=int, default=0, help="remove text/audio pad token, set audio_mask_token and start of continue to be separately learned embeddings. Therefore, for ve1 self.n_text_tokens == self.args.text_vocab_size, self.n_audio_tokens == self.args.audio_vocab_size + 2, for ve7, self.n_text_tokens == self.args.text_vocab_size, self.n_audio_tokens == self.args.audio_vocab_size") - parser.add_argument('--one_causal', type=int, default=0, help="whether model VE_one generation as autoregressive gen or non-autoregressive gen") - parser.add_argument('--n_codebooks', type=int, default=8) - parser.add_argument('--weight_sharing', type=int, default=0, help="sharing weights between VE_seven predict layer and embedding layer") - parser.add_argument('--text_vocab_size', type=int, default=86, help='Size of text vocabulary') - parser.add_argument('--text_pad_token', type=int, default=86, help='padding of the text tokens, not attended') + parser.add_argument( + "--sep_special_token", + type=int, + default=0, + help="remove text/audio pad token, set audio_mask_token and start of continue to be separately learned embeddings. Therefore, for ve1 self.n_text_tokens == self.args.text_vocab_size, self.n_audio_tokens == self.args.audio_vocab_size + 2, for ve7, self.n_text_tokens == self.args.text_vocab_size, self.n_audio_tokens == self.args.audio_vocab_size", + ) + parser.add_argument( + "--one_causal", + type=int, + default=0, + help="whether model VE_one generation as autoregressive gen or non-autoregressive gen", + ) + parser.add_argument("--n_codebooks", type=int, default=8) + parser.add_argument( + "--weight_sharing", + type=int, + default=0, + help="sharing weights between VE_seven predict layer and embedding layer", + ) + parser.add_argument( + "--text_vocab_size", type=int, default=86, help="Size of text vocabulary" + ) + parser.add_argument( + "--text_pad_token", + type=int, + default=86, + help="padding of the text tokens, not attended", + ) # parser.add_argument('--audio_vocab_size', type=int, default=1024, help='Size of audio vocabulary') - parser.add_argument('--audio_vocab_size', type=str, default='2048', help="Size of audio vocabulary, can be specified as '[128,512,1024,2048]'") - parser.add_argument('--audio_mask_token', type=int, default=1024, help='Audio mask token, this the the extra mask used in the masked region for AR, for NAR, the entire masked region will be filled with it') - parser.add_argument('--bog', type=int, default=1025, help='Begin of generation token') - parser.add_argument('--eog', type=int, default=2049, help='End of generation token') - parser.add_argument('--start_of_continue', type=int, default=1027, help='this token follows the masked region, proceeds the first unmasked token, to indicate that gt tokens starts') - parser.add_argument('--audio_pad_token', type=int, default=2050, help='padding of the encodec codes, not attended') - parser.add_argument('--d_model', type=int, default=1024, help='Model dimension') - parser.add_argument('--audio_embedding_dim', type=int, default=128, help='dimension for encodec continues embedding (before being quantized)') - parser.add_argument('--text_embedding_dropout', type=float, default=0.1, help='Dropout for text embedding') - parser.add_argument('--audio_embedding_dropout', type=float, default=0, help='Dropout for audio embedding') - parser.add_argument('--text_positional_embedding_dropout', type=float, default=0.1, help='Dropout for text positional embedding') - parser.add_argument('--audio_positional_embedding_dropout', type=float, default=0.1, help='Dropout for audio positional embedding') - parser.add_argument('--trm_dropout', type=float, default=0.1, help='Dropout for transformer') - parser.add_argument('--nhead', type=int, default=16, help='Number of attention heads') - parser.add_argument('--num_encoder_layers', type=int, default=12, help='Number of encoder layers') - parser.add_argument('--num_decoder_layers', type=int, default=12, help='Number of decoder layers') - parser.add_argument('--eog_weight', type=float, default=1.0, help='Weight for End of generation token') - parser.add_argument('--stage_one_load_encodec_embedding', type=str, default=None, help='Path to load encodec embedding for stage one. On our lab machine it is /saltpool0/scratch/pyp/VoiceEditor/encodec_embedding/24khz_8codebooks.pth, 8 is the n_codebooks') - parser.add_argument('--stage_two_load_encodec_embedding', type=str, default=None, help='Path to load encodec embedding for stage two。 On our lab machine it is /saltpool0/scratch/pyp/VoiceEditor/encodec_embedding/24khz_8codebooks.pth, 8 is the n_codebooks') - parser.add_argument('--stage_two_load_ve_one_embedding', type=str, default=None, help='Path to load VoiceEditor_one audio embedding for stage two') - parser.add_argument('--load_model_from', type=str, default=None, help='Path to load model from, this will be effective last, so will overwrite all previous load, including resume') - parser.add_argument('--load_model_from_ve1', type=str, default=None, help='Path to load ve1 model weights from, this will be effective last, designed for loading the encoder weights of the VE7 from a pretrained VE1') - + parser.add_argument( + "--audio_vocab_size", + type=str, + default="2048", + help="Size of audio vocabulary, can be specified as '[128,512,1024,2048]'", + ) + parser.add_argument( + "--audio_mask_token", + type=int, + default=1024, + help="Audio mask token, this the the extra mask used in the masked region for AR, for NAR, the entire masked region will be filled with it", + ) + parser.add_argument( + "--bog", type=int, default=1025, help="Begin of generation token" + ) + parser.add_argument("--eog", type=int, default=2049, help="End of generation token") + parser.add_argument( + "--start_of_continue", + type=int, + default=1027, + help="this token follows the masked region, proceeds the first unmasked token, to indicate that gt tokens starts", + ) + parser.add_argument( + "--audio_pad_token", + type=int, + default=2050, + help="padding of the encodec codes, not attended", + ) + parser.add_argument("--d_model", type=int, default=1024, help="Model dimension") + parser.add_argument( + "--audio_embedding_dim", + type=int, + default=128, + help="dimension for encodec continues embedding (before being quantized)", + ) + parser.add_argument( + "--text_embedding_dropout", + type=float, + default=0.1, + help="Dropout for text embedding", + ) + parser.add_argument( + "--audio_embedding_dropout", + type=float, + default=0, + help="Dropout for audio embedding", + ) + parser.add_argument( + "--text_positional_embedding_dropout", + type=float, + default=0.1, + help="Dropout for text positional embedding", + ) + parser.add_argument( + "--audio_positional_embedding_dropout", + type=float, + default=0.1, + help="Dropout for audio positional embedding", + ) + parser.add_argument( + "--trm_dropout", type=float, default=0.1, help="Dropout for transformer" + ) + parser.add_argument( + "--nhead", type=int, default=16, help="Number of attention heads" + ) + parser.add_argument( + "--num_encoder_layers", type=int, default=12, help="Number of encoder layers" + ) + parser.add_argument( + "--num_decoder_layers", type=int, default=12, help="Number of decoder layers" + ) + parser.add_argument( + "--eog_weight", + type=float, + default=1.0, + help="Weight for End of generation token", + ) + parser.add_argument( + "--stage_one_load_encodec_embedding", + type=str, + default=None, + help="Path to load encodec embedding for stage one. On our lab machine it is /saltpool0/scratch/pyp/VoiceEditor/encodec_embedding/24khz_8codebooks.pth, 8 is the n_codebooks", + ) + parser.add_argument( + "--stage_two_load_encodec_embedding", + type=str, + default=None, + help="Path to load encodec embedding for stage two。 On our lab machine it is /saltpool0/scratch/pyp/VoiceEditor/encodec_embedding/24khz_8codebooks.pth, 8 is the n_codebooks", + ) + parser.add_argument( + "--stage_two_load_ve_one_embedding", + type=str, + default=None, + help="Path to load VoiceEditor_one audio embedding for stage two", + ) + parser.add_argument( + "--load_model_from", + type=str, + default=None, + help="Path to load model from, this will be effective last, so will overwrite all previous load, including resume", + ) + parser.add_argument( + "--load_model_from_ve1", + type=str, + default=None, + help="Path to load ve1 model weights from, this will be effective last, designed for loading the encoder weights of the VE7 from a pretrained VE1", + ) ## below are args for the new long model - parser.add_argument("--target_time_stretch_prob", type=float, default=0, help="the probability of time stretching the target audio") - parser.add_argument("--target_time_stretch_bound", type=float, default=0.1, help="the bound of the time stretching target audio, e.g. 0.1 means the audio will be stretched by 0.9 to 1.1") - parser.add_argument("--time_stretch_prob", type=float, default=0, help="the probability of time stretching the audio") - parser.add_argument("--time_stretch_bound", type=float, default=0.3, help="the bound of the time stretching, e.g. 0.3 means the audio will be stretched by 0.7 to 1.3") - parser.add_argument("--no_loss_on_prefix", type=int, default=0, help="if 1, will not calculate loss on the prefix acoustic tokens") - parser.add_argument("--x_sep_token", type=int, default=None, help="if not None, will use this token in between prompt text and target generation text") - parser.add_argument("--y_sep_token", type=int, default=None, help="if not None, will use this token in between prompt codec tokens and target codec tokens") - parser.add_argument("--neighbor_prompt_prob", type=float, default=0, help="the probability of using the prompt from the neighbor") - parser.add_argument("--neighbor_folder_name", type=str, default='neighbors',help="folder where the neighbors of the current audio files are stored, each row contains three tab separated entries: neighbor_fn, neighbor_temporal_distance, neighbor_duration") - parser.add_argument("--alignment_folder_name", type=str, default='alignment', help="folder where the forced alignment of the current audio files are stored, in csv format, each row contains five comma separated entries: begin, end, label, type, speaker, the first row is header") - parser.add_argument("--ipa_alignment_folder_name", type=str, default='ipa_alignment', help="folder where the forced alignment of the current audio files are stored, in txt format, each row contains three tab separated entries: begin, end, ipa phn sequence, generated using data/ll60k_preprocessing/step7_ipa_alignment.py") - parser.add_argument("--max_prompt_len", type=float, default=30, help="in sec., maximal prompt length selected from some neighboring file") - parser.add_argument("--min_prompt_len", type=float, default=0.5, help="in sec., minimal prompt length selected from some neighboring file") - parser.add_argument("--neighbor_selection_method", type=str, default="maxdist_60", help="maxdist_60 means uniformly select a neighbor that's within 60 sec of the current audio file") - parser.add_argument("--num_trial", type=int, default=5, help="number of tries to select a neighbor") - parser.add_argument("--prompt_start_from_begining_prob", type=float, default=0.5, help="the probability of starting the prompt from the beginning of the neighbor") - parser.add_argument("--min_alignment_len", type=int, default=5, help="in number of words") - parser.add_argument("--audio_folder_name", type=str, default='audio', help="folder where the audio files are stored") - + parser.add_argument( + "--target_time_stretch_prob", + type=float, + default=0, + help="the probability of time stretching the target audio", + ) + parser.add_argument( + "--target_time_stretch_bound", + type=float, + default=0.1, + help="the bound of the time stretching target audio, e.g. 0.1 means the audio will be stretched by 0.9 to 1.1", + ) + parser.add_argument( + "--time_stretch_prob", + type=float, + default=0, + help="the probability of time stretching the audio", + ) + parser.add_argument( + "--time_stretch_bound", + type=float, + default=0.3, + help="the bound of the time stretching, e.g. 0.3 means the audio will be stretched by 0.7 to 1.3", + ) + parser.add_argument( + "--no_loss_on_prefix", + type=int, + default=0, + help="if 1, will not calculate loss on the prefix acoustic tokens", + ) + parser.add_argument( + "--x_sep_token", + type=int, + default=None, + help="if not None, will use this token in between prompt text and target generation text", + ) + parser.add_argument( + "--y_sep_token", + type=int, + default=None, + help="if not None, will use this token in between prompt codec tokens and target codec tokens", + ) + parser.add_argument( + "--neighbor_prompt_prob", + type=float, + default=0, + help="the probability of using the prompt from the neighbor", + ) + parser.add_argument( + "--neighbor_folder_name", + type=str, + default="neighbors", + help="folder where the neighbors of the current audio files are stored, each row contains three tab separated entries: neighbor_fn, neighbor_temporal_distance, neighbor_duration", + ) + parser.add_argument( + "--alignment_folder_name", + type=str, + default="alignment", + help="folder where the forced alignment of the current audio files are stored, in csv format, each row contains five comma separated entries: begin, end, label, type, speaker, the first row is header", + ) + parser.add_argument( + "--ipa_alignment_folder_name", + type=str, + default="ipa_alignment", + help="folder where the forced alignment of the current audio files are stored, in txt format, each row contains three tab separated entries: begin, end, ipa phn sequence, generated using data/ll60k_preprocessing/step7_ipa_alignment.py", + ) + parser.add_argument( + "--max_prompt_len", + type=float, + default=30, + help="in sec., maximal prompt length selected from some neighboring file", + ) + parser.add_argument( + "--min_prompt_len", + type=float, + default=0.5, + help="in sec., minimal prompt length selected from some neighboring file", + ) + parser.add_argument( + "--neighbor_selection_method", + type=str, + default="maxdist_60", + help="maxdist_60 means uniformly select a neighbor that's within 60 sec of the current audio file", + ) + parser.add_argument( + "--num_trial", type=int, default=5, help="number of tries to select a neighbor" + ) + parser.add_argument( + "--prompt_start_from_begining_prob", + type=float, + default=0.5, + help="the probability of starting the prompt from the beginning of the neighbor", + ) + parser.add_argument( + "--min_alignment_len", type=int, default=5, help="in number of words" + ) + parser.add_argument( + "--audio_folder_name", + type=str, + default="audio", + help="folder where the audio files are stored", + ) + # rope parameters - parser.add_argument("--decoder_regular_rope", type=int, default=0, help="if 1, will use regular rope for the decoder (note that we always use regular rope for encoder). ") - parser.add_argument("--progress_no_multiple", type=int, default=0, help="if 1, will not multiple the percentage progress by the length of the key, see apply_rotary_pos_emb in models/modules/activation.py, this applies to both rope and sinusoidal positional encoding. Note that progress scale is still applied, i.e. when we only apply progress scale, but not multiple, the scaling factor is constant for every sample, rather than sample dependent") - parser.add_argument("--add_eos_to_text", type=int, default=0, help="if not 0, use this number as eos and add to the end of text token, usually use the second to last token in the vocab size") - parser.add_argument("--add_bos_to_text", type=int, default=0, help="if not 0, use this number as bos and add to the begining of text token, usually use the third to last token in the vocab size") - parser.add_argument("--use_sinusoidal", type=int, default=0, help="if 1, will use sinusoidal positional encoding, otherwise use rope. BUT if rope_base is None, will use sinusoidal") - parser.add_argument("--sinusoidal_base", type=int, default=1e4, help="the base of the exponential function, default is 1e4") - parser.add_argument("--use_sinusoidal_progress", type=int, default=0, help="if 1, will use sinusoidal positional encoding for progress, otherwise use rope") - parser.add_argument("--rope_base", type=int, default=None, help="the base of the exponential function, default is 1e4, if None, will not use rope") - parser.add_argument("--multiple_key_length", type=int, default=0, help="if 1, during progress calculation, will multiple the precentage progress by the length of the key, otherwise multiple with length of query. see models/rope_playground.ipynb") - parser.add_argument("--progress_scale", type=float, default=1.0, help="scale the progress, the smaller the value, the bigger the diagonal in attention score, see models/rope_playground.ipynb") + parser.add_argument( + "--decoder_regular_rope", + type=int, + default=0, + help="if 1, will use regular rope for the decoder (note that we always use regular rope for encoder). ", + ) + parser.add_argument( + "--progress_no_multiple", + type=int, + default=0, + help="if 1, will not multiple the percentage progress by the length of the key, see apply_rotary_pos_emb in models/modules/activation.py, this applies to both rope and sinusoidal positional encoding. Note that progress scale is still applied, i.e. when we only apply progress scale, but not multiple, the scaling factor is constant for every sample, rather than sample dependent", + ) + parser.add_argument( + "--add_eos_to_text", + type=int, + default=0, + help="if not 0, use this number as eos and add to the end of text token, usually use the second to last token in the vocab size", + ) + parser.add_argument( + "--add_bos_to_text", + type=int, + default=0, + help="if not 0, use this number as bos and add to the begining of text token, usually use the third to last token in the vocab size", + ) + parser.add_argument( + "--use_sinusoidal", + type=int, + default=0, + help="if 1, will use sinusoidal positional encoding, otherwise use rope. BUT if rope_base is None, will use sinusoidal", + ) + parser.add_argument( + "--sinusoidal_base", + type=int, + default=1e4, + help="the base of the exponential function, default is 1e4", + ) + parser.add_argument( + "--use_sinusoidal_progress", + type=int, + default=0, + help="if 1, will use sinusoidal positional encoding for progress, otherwise use rope", + ) + parser.add_argument( + "--rope_base", + type=int, + default=None, + help="the base of the exponential function, default is 1e4, if None, will not use rope", + ) + parser.add_argument( + "--multiple_key_length", + type=int, + default=0, + help="if 1, during progress calculation, will multiple the precentage progress by the length of the key, otherwise multiple with length of query. see models/rope_playground.ipynb", + ) + parser.add_argument( + "--progress_scale", + type=float, + default=1.0, + help="scale the progress, the smaller the value, the bigger the diagonal in attention score, see models/rope_playground.ipynb", + ) # attention alignment loss - parser.add_argument("--attention_alignment_loss", type=float, default=0.0, help="the weight on the attention alignment loss, if 0, will not calculate the loss") - parser.add_argument("--alignment_loss_layer", type=str, default="['0-1', '2', '3']", help='the layers to calculate the alignment loss, e.g. ["0-1", "2", "3"]') - parser.add_argument("--alignment_loss_head", type=str, default="['0-1', '2', '3']", help='the attention heads to calculate the alignment loss, e.g. ["0-1", "2", "3"]') - parser.add_argument("--alignment_blank_logit", type=float, default=-1.0, help="the logit for the blank token added to the attention weights") + parser.add_argument( + "--attention_alignment_loss", + type=float, + default=0.0, + help="the weight on the attention alignment loss, if 0, will not calculate the loss", + ) + parser.add_argument( + "--alignment_loss_layer", + type=str, + default="['0-1', '2', '3']", + help='the layers to calculate the alignment loss, e.g. ["0-1", "2", "3"]', + ) + parser.add_argument( + "--alignment_loss_head", + type=str, + default="['0-1', '2', '3']", + help='the attention heads to calculate the alignment loss, e.g. ["0-1", "2", "3"]', + ) + parser.add_argument( + "--alignment_blank_logit", + type=float, + default=-1.0, + help="the logit for the blank token added to the attention weights", + ) # inference parameters - parser.add_argument("--metrics", type=str, default="['spk_sim','wer','mcd','pitch','energy','pesq','utmos']") - parser.add_argument("--res_jsonl_root", type=str, default="/home/pyp/BoostedVoiceEditor/res") + parser.add_argument( + "--metrics", + type=str, + default="['spk_sim','wer','mcd','pitch','energy','pesq','utmos']", + ) + parser.add_argument( + "--res_jsonl_root", type=str, default="/home/pyp/BoostedVoiceEditor/res" + ) parser.add_argument("--res_name", type=str, default="2jan25.jsonl") parser.add_argument("--inference_seed", type=int, default=1) parser.add_argument("--codec_audio_sr", type=int, default=16000) @@ -231,24 +854,76 @@ def MyParser(): parser.add_argument("--kvcache", type=int, default=0) parser.add_argument("--stop_repetition", type=int, default=3) parser.add_argument("--sample_batch_size", type=int, default=1) - parser.add_argument("--inference_manifest_fns", type=str, default="['/home/pyp/BoostedVoiceEditor/manifests/debug.jsonl']") + parser.add_argument( + "--inference_manifest_fns", + type=str, + default="['/home/pyp/BoostedVoiceEditor/manifests/debug.jsonl']", + ) parser.add_argument("--use_gt_duration", type=int, default=1) - parser.add_argument("--save_root", type=str, default="/data/scratch/pyp/exp_pyp/BoostedVoiceEditor/gens") - parser.add_argument("--encodec_signature", type=str, default="/data/scratch/pyp/exp_pyp/audiocraft/encodec/xps/6f79c6a8/checkpoint.th") - parser.add_argument("--extra_cutoff", type=float, default=5, help="in rare cases where the model doesn't follow specified target duration (only happened in extrapolation cases), we will terminate generation once the extra duration exceeds this value") - parser.add_argument("--duration_margin", type=float, default=0.04, help="used along with extra_cutoff, when extra_cutoff is used (i.e. model doesn't follow specified target_duration), we terminate the generate, and cut the results to target_duration + duration_margin") + parser.add_argument( + "--save_root", + type=str, + default="/data/scratch/pyp/exp_pyp/BoostedVoiceEditor/gens", + ) + parser.add_argument( + "--encodec_signature", + type=str, + default="/data/scratch/pyp/exp_pyp/audiocraft/encodec/xps/6f79c6a8/checkpoint.th", + ) + parser.add_argument( + "--extra_cutoff", + type=float, + default=5, + help="in rare cases where the model doesn't follow specified target duration (only happened in extrapolation cases), we will terminate generation once the extra duration exceeds this value", + ) + parser.add_argument( + "--duration_margin", + type=float, + default=0.04, + help="used along with extra_cutoff, when extra_cutoff is used (i.e. model doesn't follow specified target_duration), we terminate the generate, and cut the results to target_duration + duration_margin", + ) # add repeat_prompt and asr_model_name - parser.add_argument("--repeat_prompt", type=int_or_str, default=0, help="if 1, will repeat the prompt for each segment") - parser.add_argument("--asr_model_name", type=str, default="w2v2", help="the name of the asr model, if not None, will use the asr model to generate the prompt") + parser.add_argument( + "--repeat_prompt", + type=int_or_str, + default=0, + help="if 1, will repeat the prompt for each segment", + ) + parser.add_argument( + "--asr_model_name", + type=str, + default="w2v2", + help="the name of the asr model, if not None, will use the asr model to generate the prompt", + ) # depth transformer parameters parser.add_argument("--depth_dec_num_layers", type=int, default=0) parser.add_argument("--depth_dec_d_model", type=int, default=768) parser.add_argument("--depth_dec_nhead", type=int, default=12) - parser.add_argument("--moshi_depth", type=int, default=0, help="if 1, will use the same parameterization as moshi, i.e. temporal trm output will gets added to every transformed token embedding") + parser.add_argument( + "--moshi_depth", + type=int, + default=0, + help="if 1, will use the same parameterization as moshi, i.e. temporal trm output will gets added to every transformed token embedding", + ) - parser.add_argument("--validation_sample_cap", type=int, default=None, help="cap the validation data to this number") - parser.add_argument("--no_libri_in_training", type=int, default=None, help="if 1, will not use librilight in training, only use in validation") - parser.add_argument("--uniform_weight_start_step", type=int, default=1e50, help="set all codebook weight to be uniform starting from this step") + parser.add_argument( + "--validation_sample_cap", + type=int, + default=None, + help="cap the validation data to this number", + ) + parser.add_argument( + "--no_libri_in_training", + type=int, + default=None, + help="if 1, will not use librilight in training, only use in validation", + ) + parser.add_argument( + "--uniform_weight_start_step", + type=int, + default=1e50, + help="set all codebook weight to be uniform starting from this step", + ) - return parser \ No newline at end of file + return parser diff --git a/data/combined_dataset.py b/data/combined_dataset.py index b7925cf..70c12ea 100644 --- a/data/combined_dataset.py +++ b/data/combined_dataset.py @@ -11,6 +11,8 @@ import glob import numpy as np from data.tokenizer import TextTokenizer, tokenize_text, AudioTokenizer + + def find_files(root_dir, endswith=".wav"): files = [] # os.walk generates the file names in a directory tree @@ -24,16 +26,25 @@ def find_files(root_dir, endswith=".wav"): files.append(full_path) return files + class dataset(torch.utils.data.Dataset): def __init__(self, args, split): super().__init__() self.args = args - self.args.target_time_stretch_prob = getattr(self.args, "target_time_stretch_prob", 0) - self.args.target_time_stretch_bound = getattr(self.args, "target_time_stretch_bound", 0.1) + self.args.target_time_stretch_prob = getattr( + self.args, "target_time_stretch_prob", 0 + ) + self.args.target_time_stretch_bound = getattr( + self.args, "target_time_stretch_bound", 0.1 + ) self.split = split - - assert self.split in ['train', 'valid', 'test'], f"split should be one of ['train', 'valid', 'test'], but it's {split}" - + + assert self.split in [ + "train", + "valid", + "test", + ], f"split should be one of ['train', 'valid', 'test'], but it's {split}" + if "[" not in self.args.dataset_dir or "]" not in self.args.dataset_dir: self.dataset_dir = f"['{self.args.dataset_dir}']" else: @@ -46,29 +57,45 @@ def __init__(self, args, split): self.args.manifest_name = copy.deepcopy(self.args.manifest_name) self.manifest_name = eval(self.args.manifest_name) if len(self.manifest_name) != len(self.dataset_dir): - assert len(self.manifest_name) == 1, f"len(self.manifest_name) should be 1 or equal to len(self.dataset_dir), but it's {len(self.manifest_name)}" + assert ( + len(self.manifest_name) == 1 + ), f"len(self.manifest_name) should be 1 or equal to len(self.dataset_dir), but it's {len(self.manifest_name)}" self.manifest_name = self.manifest_name * len(self.dataset_dir) for i_data, dataset_dir in enumerate(self.dataset_dir): - if getattr(self.args, "no_libri_in_training", None) != None and ("librilight" in dataset_dir) and self.split == "train": + if ( + getattr(self.args, "no_libri_in_training", None) != None + and ("librilight" in dataset_dir) + and self.split == "train" + ): if not dist.is_initialized() or dist.get_rank() == 0: logging.info(f"skipping librilight in training split") continue n_datapoints = 0 - manifest_fn = os.path.join(dataset_dir, self.manifest_name[i_data], self.split+".txt") + manifest_fn = os.path.join( + dataset_dir, self.manifest_name[i_data], self.split + ".txt" + ) if not os.path.isfile(manifest_fn): all_manifest_fn = glob.glob(manifest_fn.replace(".txt", "_*=*.txt")) if len(all_manifest_fn) == 0: - logging.info(f"no manifest file found for {split} split in {dataset_dir}") + logging.info( + f"no manifest file found for {split} split in {dataset_dir}" + ) continue if self.args.debug: - logging.info(f"debugging mode, only using the frist found manifest file: {all_manifest_fn[0]}") + logging.info( + f"debugging mode, only using the frist found manifest file: {all_manifest_fn[0]}" + ) all_manifest_fn = all_manifest_fn[:1] else: if dist.is_initialized() and dist.get_rank() == 0: - logging.info(f"Combining found manifest files for {split}: {all_manifest_fn}") + logging.info( + f"Combining found manifest files for {split}: {all_manifest_fn}" + ) for cur_manifest_fn in all_manifest_fn: with open(cur_manifest_fn, "r") as rf: - tmp = [l.strip().split("\t") + [i_data] for l in rf.readlines()] # i_data is the index of the dataset + tmp = [ + l.strip().split("\t") + [i_data] for l in rf.readlines() + ] # i_data is the index of the dataset n_datapoints += len(tmp) data += tmp else: @@ -77,15 +104,22 @@ def __init__(self, args, split): data += tmp n_datapoints += len(tmp) if dist.is_initialized() and dist.get_rank() == 0: - logging.info(f"number of data points for {split} split in {dataset_dir}: {n_datapoints}") + logging.info( + f"number of data points for {split} split in {dataset_dir}: {n_datapoints}" + ) assert len(data) > 0, f"no data found for {split} split" - lengths_list = [int(item[1]) for item in data] # use 1 because there might be more than 1 columns (for gigaspeech we have 3 columns: path, duration, selfsim) + lengths_list = [ + int(item[1]) for item in data + ] # use 1 because there might be more than 1 columns (for gigaspeech we have 3 columns: path, duration, selfsim) self.data = [] self.lengths_list = [] total_duration = 0 for d, l in zip(data, lengths_list): - if l >= self.args.encodec_sr*self.args.audio_min_length: - if self.args.drop_long and l > self.args.encodec_sr*self.args.audio_max_length: + if l >= self.args.encodec_sr * self.args.audio_min_length: + if ( + self.args.drop_long + and l > self.args.encodec_sr * self.args.audio_max_length + ): continue self.data.append(d) self.lengths_list.append(l) @@ -94,8 +128,12 @@ def __init__(self, args, split): # self.data = self.data[:1000] # self.lengths_list = self.lengths_list[:1000] if dist.is_initialized() and dist.get_rank() == 0: - logging.info(f"TOTAL number of data points for {self.split} split: {len(self.lengths_list)}") - logging.info(f"TOTAL duration for {self.split} split: {total_duration:.1f} hours") + logging.info( + f"TOTAL number of data points for {self.split} split: {len(self.lengths_list)}" + ) + logging.info( + f"TOTAL duration for {self.split} split: {total_duration:.1f} hours" + ) # phoneme vocabulary phn_set = set() for dataset_dir in self.dataset_dir: @@ -103,25 +141,41 @@ def __init__(self, args, split): with open(vocab_fn, "r") as f: temp = [l.strip().split("\t") for l in f.readlines() if len(l) != 0] phn_set.update([item[-1] for item in temp]) - self.phn2num = {item:i for i, item in enumerate(phn_set)} - assert self.args.text_vocab_size > len(self.phn2num), f"need self.args.text_vocab_size to be bigger than number of phns in vocab to handle OOD phn, but the former is {self.args.text_vocab_size} while the latter is {len(self.phn2num)}" + self.phn2num = {item: i for i, item in enumerate(phn_set)} + assert self.args.text_vocab_size > len( + self.phn2num + ), f"need self.args.text_vocab_size to be bigger than number of phns in vocab to handle OOD phn, but the former is {self.args.text_vocab_size} while the latter is {len(self.phn2num)}" - if (self.args.neighbor_prompt_prob > 0 and self.args.time_stretch_prob > 0) or self.args.target_time_stretch_prob > 0: + if ( + self.args.neighbor_prompt_prob > 0 and self.args.time_stretch_prob > 0 + ) or self.args.target_time_stretch_prob > 0: userdir = os.path.expanduser("~") - encodec_signature = getattr(self.args, "encodec_signature", os.path.join(userdir, "VoiceStar", "pretrained", "encodec_6f79c6a8.th")) - self.audio_tokenizer = AudioTokenizer(signature=encodec_signature, device=torch.device("cpu"), encode_only=True) - assert self.audio_tokenizer.sample_rate == self.args.codec_audio_sr, f"audio_tokenizer.sample_rate: {self.audio_tokenizer.sample_rate}, self.args.encodec_sr: {self.args.encodec_sr}" + encodec_signature = getattr( + self.args, + "encodec_signature", + os.path.join(userdir, "VoiceStar", "pretrained", "encodec_6f79c6a8.th"), + ) + self.audio_tokenizer = AudioTokenizer( + signature=encodec_signature, + device=torch.device("cpu"), + encode_only=True, + ) + assert ( + self.audio_tokenizer.sample_rate == self.args.codec_audio_sr + ), f"audio_tokenizer.sample_rate: {self.audio_tokenizer.sample_rate}, self.args.encodec_sr: {self.args.encodec_sr}" if dist.is_initialized() and dist.get_rank() == 0: - logging.info(f"rank: {dist.get_rank()}, audio_tokenizer device: {self.audio_tokenizer._device}") - + logging.info( + f"rank: {dist.get_rank()}, audio_tokenizer device: {self.audio_tokenizer._device}" + ) + def __len__(self): return len(self.lengths_list) - + def _load_phn_enc(self, index): item = self.data[index] dataset_dir = self.dataset_dir[item[-1]] - pf = os.path.join(dataset_dir, self.args.phn_folder_name, item[0]+".txt") - ef = os.path.join(dataset_dir, self.args.encodec_folder_name, item[0]+".txt") + pf = os.path.join(dataset_dir, self.args.phn_folder_name, item[0] + ".txt") + ef = os.path.join(dataset_dir, self.args.encodec_folder_name, item[0] + ".txt") # with certain probability, we load the audio, and time stretch it, note that we should not hit self.args.audio_max_length if "/librilight" in dataset_dir: audio_ext = ".flac" @@ -129,25 +183,54 @@ def _load_phn_enc(self, index): audio_ext = ".mp3" else: raise NotImplementedError(f"dataset_dir: {dataset_dir}") - - audio_fn = os.path.join(dataset_dir, self.args.audio_folder_name, item[0].replace(".txt", "")+audio_ext) - speed_factor = random.uniform(-self.args.target_time_stretch_bound, self.args.target_time_stretch_bound) + 1 - length_ok = (float(item[1]) / self.args.encodec_sr) / speed_factor < self.args.audio_max_length # NOTE to calculate the maximal duration after time stretching, we should be used as orig/(1-bound), rather than orig*(1+bound) - if self.args.target_time_stretch_prob > 0 and random.random() < self.args.target_time_stretch_prob and os.path.isfile(audio_fn) and length_ok: + + audio_fn = os.path.join( + dataset_dir, + self.args.audio_folder_name, + item[0].replace(".txt", "") + audio_ext, + ) + speed_factor = ( + random.uniform( + -self.args.target_time_stretch_bound, + self.args.target_time_stretch_bound, + ) + + 1 + ) + length_ok = ( + float(item[1]) / self.args.encodec_sr + ) / speed_factor < self.args.audio_max_length # NOTE to calculate the maximal duration after time stretching, we should be used as orig/(1-bound), rather than orig*(1+bound) + if ( + self.args.target_time_stretch_prob > 0 + and random.random() < self.args.target_time_stretch_prob + and os.path.isfile(audio_fn) + and length_ok + ): try: with open(pf, "r") as p: phns = [l.strip() for l in p.readlines()] assert len(phns) == 1, phns all_phns = phns[0].split(" ") - x = [self.phn2num[item] for item in all_phns if item in self.phn2num] + x = [ + self.phn2num[item] for item in all_phns if item in self.phn2num + ] except: - logging.info(f"loading failed for {pf}, maybe files don't exist or are corrupted") + logging.info( + f"loading failed for {pf}, maybe files don't exist or are corrupted" + ) return [], [[]], dataset_dir, audio_ext # time stretch try: process = ( - ffmpeg.input(audio_fn, ss=0, t=float(item[1]) / self.args.encodec_sr) - .output('pipe:1', format='f32le', ac=1, ar=self.audio_tokenizer.sample_rate, filter='atempo={}'.format(speed_factor)) + ffmpeg.input( + audio_fn, ss=0, t=float(item[1]) / self.args.encodec_sr + ) + .output( + "pipe:1", + format="f32le", + ac=1, + ar=self.audio_tokenizer.sample_rate, + filter="atempo={}".format(speed_factor), + ) .run_async(pipe_stdout=True, pipe_stderr=True) ) # Read the processed audio from ffmpeg stdout @@ -159,11 +242,19 @@ def _load_phn_enc(self, index): # Reshape the numpy array back to the expected shape (1, samples for mono) waveform = torch.from_numpy(output_np) waveform = waveform.unsqueeze(0).unsqueeze(0) - assert waveform.ndim == 3 and waveform.shape[0] == 1 and waveform.shape[1] == 1, waveform.shape + assert ( + waveform.ndim == 3 + and waveform.shape[0] == 1 + and waveform.shape[1] == 1 + ), waveform.shape with torch.no_grad(): - encos = self.audio_tokenizer.encode(waveform.to(self.audio_tokenizer._device)) - assert encos.shape[1] == self.args.n_codebooks, f"encos.shape: {encos.shape}" - encos = encos.cpu().squeeze(0).numpy().tolist() # [K, T] + encos = self.audio_tokenizer.encode( + waveform.to(self.audio_tokenizer._device) + ) + assert ( + encos.shape[1] == self.args.n_codebooks + ), f"encos.shape: {encos.shape}" + encos = encos.cpu().squeeze(0).numpy().tolist() # [K, T] if self.args.special_first: raise NotImplementedError # y = [[int(n)+self.args.n_special for n in l] for l in encos] @@ -171,7 +262,9 @@ def _load_phn_enc(self, index): y = [[int(n) for n in l] for l in encos] return x, y, dataset_dir, audio_ext except Exception as e: - logging.info(f"failed with time stretch and codec encode for {audio_fn}") + logging.info( + f"failed with time stretch and codec encode for {audio_fn}" + ) logging.info(f"error: {e}") pass @@ -180,9 +273,15 @@ def _load_phn_enc(self, index): phns = [l.strip() for l in p.readlines()] assert len(phns) == 1, phns all_phns = phns[0].split(" ") - x = [self.phn2num[item] for item in all_phns if item in self.phn2num] # we assume that OOD will not happen, because phn vocab is small - encos = [l.strip().split() for k, l in enumerate(e.readlines()) if k < self.args.n_codebooks] - + x = [ + self.phn2num[item] for item in all_phns if item in self.phn2num + ] # we assume that OOD will not happen, because phn vocab is small + encos = [ + l.strip().split() + for k, l in enumerate(e.readlines()) + if k < self.args.n_codebooks + ] + assert len(encos) == self.args.n_codebooks, ef if self.args.special_first: @@ -191,7 +290,9 @@ def _load_phn_enc(self, index): else: y = [[int(n) for n in l] for l in encos] except: - logging.info(f"loading failed for {pf} and {ef}, maybe files don't exist or are corrupted") + logging.info( + f"loading failed for {pf} and {ef}, maybe files don't exist or are corrupted" + ) return [], [[]], dataset_dir, audio_ext return x, y, dataset_dir, audio_ext @@ -199,16 +300,29 @@ def _load_phn_enc(self, index): # this uses the output of step7_ipa_alignment.py def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): neighbor = random.choice(neighbors) - neighbor_enc_fn = os.path.join(dataset_dir, self.args.encodec_folder_name, neighbor[0]) + neighbor_enc_fn = os.path.join( + dataset_dir, self.args.encodec_folder_name, neighbor[0] + ) if not os.path.isfile(neighbor_enc_fn): return None, None - neighbor_audio_path = os.path.join(dataset_dir, self.args.audio_folder_name, neighbor[0].replace(".txt", audio_ext)) - if getattr(self.args, "time_stretch_prob", 0) > 0 and not os.path.isfile(neighbor_audio_path): + neighbor_audio_path = os.path.join( + dataset_dir, + self.args.audio_folder_name, + neighbor[0].replace(".txt", audio_ext), + ) + if getattr(self.args, "time_stretch_prob", 0) > 0 and not os.path.isfile( + neighbor_audio_path + ): logging.info(f"audio file not found: {neighbor_audio_path}") return None, None if random.random() < getattr(self.args, "time_stretch_prob", 0): time_stretch_flag = True - speed_factor = random.uniform(-self.args.time_stretch_bound, self.args.time_stretch_bound) + 1 + speed_factor = ( + random.uniform( + -self.args.time_stretch_bound, self.args.time_stretch_bound + ) + + 1 + ) duration_factor = 1 / speed_factor else: time_stretch_flag = False @@ -221,17 +335,27 @@ def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): if "/emilia" in dataset_dir: # get neighbor duration neighbor_dur = float(neighbor[2]) - if neighbor_dur * duration_factor + y_len / self.args.encodec_sr > self.args.audio_max_length or neighbor_dur * duration_factor < self.args.min_prompt_len: + if ( + neighbor_dur * duration_factor + y_len / self.args.encodec_sr + > self.args.audio_max_length + or neighbor_dur * duration_factor < self.args.min_prompt_len + ): return None, None try: - neighbor_pf = os.path.join(dataset_dir, self.args.phn_folder_name, neighbor[0]) + neighbor_pf = os.path.join( + dataset_dir, self.args.phn_folder_name, neighbor[0] + ) with open(neighbor_pf, "r") as p: phns = [l.strip() for l in p.readlines()] assert len(phns) == 1, phns all_phns = phns[0].split(" ") - phn_token = [self.phn2num[item] for item in all_phns if item in self.phn2num] + phn_token = [ + self.phn2num[item] for item in all_phns if item in self.phn2num + ] except: - logging.info(f"loading failed for {neighbor_pf}, maybe files don't exist") + logging.info( + f"loading failed for {neighbor_pf}, maybe files don't exist" + ) return None, None # if do not stretch the audio if not time_stretch_flag: @@ -239,21 +363,27 @@ def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): neighbor_enc = [l.strip().split() for l in f.readlines()] if len(neighbor_enc) != self.args.n_codebooks: return None, None - # if too long + # if too long else: if self.args.special_first: raise NotImplementedError # neighbor_enc = [[int(n)+self.args.n_special for n in l] for l in neighbor_enc] else: neighbor_enc = [[int(n) for n in l] for l in neighbor_enc] - + return phn_token, neighbor_enc - else: # stretch the audio with ffmpeg-python + else: # stretch the audio with ffmpeg-python process = ( ffmpeg.input(neighbor_audio_path, ss=0, t=neighbor_dur) - .output('pipe:1', format='f32le', ac=1, ar=self.audio_tokenizer.sample_rate, filter='atempo={}'.format(speed_factor)) - .run_async(pipe_stdout=True, pipe_stderr=True) + .output( + "pipe:1", + format="f32le", + ac=1, + ar=self.audio_tokenizer.sample_rate, + filter="atempo={}".format(speed_factor), ) + .run_async(pipe_stdout=True, pipe_stderr=True) + ) # Read the processed audio from ffmpeg stdout output, _ = process.communicate() @@ -263,34 +393,58 @@ def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): # Reshape the numpy array back to the expected shape (1, samples for mono) waveform = torch.from_numpy(output_np) waveform = waveform.unsqueeze(0).unsqueeze(0) - assert waveform.ndim == 3 and waveform.shape[0] == 1 and waveform.shape[1] == 1, waveform.shape + assert ( + waveform.ndim == 3 + and waveform.shape[0] == 1 + and waveform.shape[1] == 1 + ), waveform.shape with torch.no_grad(): - encos = self.audio_tokenizer.encode(waveform.to(self.audio_tokenizer._device)) - assert encos.shape[1] == self.args.n_codebooks, f"encos.shape: {encos.shape}" - neighbor_enc = encos.cpu().squeeze(0).numpy().tolist() # [K, T] + encos = self.audio_tokenizer.encode( + waveform.to(self.audio_tokenizer._device) + ) + assert ( + encos.shape[1] == self.args.n_codebooks + ), f"encos.shape: {encos.shape}" + neighbor_enc = encos.cpu().squeeze(0).numpy().tolist() # [K, T] return phn_token, neighbor_enc ####################### TODO for now always use the entire neighbor for emilia ####################### TODO for now always use the entire neighbor for emilia - ipa_alignment_fn = os.path.join(dataset_dir, self.args.ipa_alignment_folder_name, neighbor[0]) + ipa_alignment_fn = os.path.join( + dataset_dir, self.args.ipa_alignment_folder_name, neighbor[0] + ) if not os.path.isfile(ipa_alignment_fn): # print(f"file not found: {ipa_alignment_fn}", flush=True) return None, None with open(ipa_alignment_fn, "r") as f: alignments = [l.strip().split("\t") for l in f.readlines()] - alignments = [[float(l[0]), float(l[1]), l[2]] for l in alignments if len(l) == 3] - alignments = [l for l in alignments if self.args.min_prompt_len < (l[1] - l[0]) * duration_factor < self.args.max_prompt_len] + alignments = [ + [float(l[0]), float(l[1]), l[2]] for l in alignments if len(l) == 3 + ] + alignments = [ + l + for l in alignments + if self.args.min_prompt_len + < (l[1] - l[0]) * duration_factor + < self.args.max_prompt_len + ] if len(alignments) == 0: # print(f"no valid alignment found for {ipa_alignment_fn}") return None, None idx = random.choice(range(len(alignments))) - while (alignments[idx][1] - alignments[idx][0]) * duration_factor + y_len / self.args.encodec_sr > self.args.audio_max_length: + while ( + (alignments[idx][1] - alignments[idx][0]) * duration_factor + + y_len / self.args.encodec_sr + > self.args.audio_max_length + ): idx -= 1 if idx < 0: # print(f"too long combined with y_len {ipa_alignment_fn=}, and {y_len=}") return None, None - if (alignments[idx][1] - alignments[idx][0]) * duration_factor < self.args.min_prompt_len: + if ( + alignments[idx][1] - alignments[idx][0] + ) * duration_factor < self.args.min_prompt_len: return None, None - + start_time, end_time = alignments[idx][:2] phn = alignments[idx][2].split(" ") phn_token = [self.phn2num[item] for item in phn if item in self.phn2num] @@ -301,7 +455,13 @@ def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): duration = end_time - start_time process = ( ffmpeg.input(neighbor_audio_path, ss=start_time, t=duration) - .output('pipe:1', format='f32le', ac=1, ar=self.audio_tokenizer.sample_rate, filter='atempo={}'.format(speed_factor)) + .output( + "pipe:1", + format="f32le", + ac=1, + ar=self.audio_tokenizer.sample_rate, + filter="atempo={}".format(speed_factor), + ) .run_async(pipe_stdout=True, pipe_stderr=True) ) # Read the processed audio from ffmpeg stdout @@ -313,15 +473,23 @@ def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): # Reshape the numpy array back to the expected shape (1, samples for mono) waveform = torch.from_numpy(output_np) waveform = waveform.unsqueeze(0).unsqueeze(0) - assert waveform.ndim == 3 and waveform.shape[0] == 1 and waveform.shape[1] == 1, waveform.shape + assert ( + waveform.ndim == 3 and waveform.shape[0] == 1 and waveform.shape[1] == 1 + ), waveform.shape try: with torch.no_grad(): - encos = self.audio_tokenizer.encode(waveform.to(self.audio_tokenizer._device)) + encos = self.audio_tokenizer.encode( + waveform.to(self.audio_tokenizer._device) + ) except: - logging.info(f"failed with time stretch for {neighbor_audio_path}, from {start_time} to {end_time} with duration factor {duration_factor}, which leads to {duration*duration_factor} seconds") + logging.info( + f"failed with time stretch for {neighbor_audio_path}, from {start_time} to {end_time} with duration factor {duration_factor}, which leads to {duration*duration_factor} seconds" + ) return None, None - assert encos.shape[1] == self.args.n_codebooks, f"encos.shape: {encos.shape}" - neighbor_enc = encos.cpu().squeeze(0).numpy().tolist() # [K, T] + assert ( + encos.shape[1] == self.args.n_codebooks + ), f"encos.shape: {encos.shape}" + neighbor_enc = encos.cpu().squeeze(0).numpy().tolist() # [K, T] return phn_token, neighbor_enc else: # get encodec codes from storage @@ -334,7 +502,9 @@ def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): # trim the encodec codes to the segment start_enc_frame = int(start_time * self.args.encodec_sr) end_enc_frame = int(end_time * self.args.encodec_sr) - neighbor_enc = [l[start_enc_frame:end_enc_frame] for l in neighbor_enc] + neighbor_enc = [ + l[start_enc_frame:end_enc_frame] for l in neighbor_enc + ] if len(neighbor_enc[0]) == 0: # print(f"no valid encodec codes found for {neighbor_enc_fn}") return None, None @@ -347,27 +517,33 @@ def find_neighbor(self, neighbors, y_len, dataset_dir, audio_ext): def __getitem__(self, index): x, y, dataset_dir, audio_ext = self._load_phn_enc(index) x_len, y_len = len(x), len(y[0]) - extra_ret = {'x_sep_token_position': 0, 'y_sep_token_position': 0} + extra_ret = {"x_sep_token_position": 0, "y_sep_token_position": 0} if x_len == 0 or y_len == 0: ret = { - "x": None, - "x_len": None, - "y": None, + "x": None, + "x_len": None, + "y": None, "y_len": None, - } + } ret.update(extra_ret) return ret - while y_len < self.args.encodec_sr*self.args.audio_min_length: + while y_len < self.args.encodec_sr * self.args.audio_min_length: assert not self.args.dynamic_batching - index = random.choice(range(len(self))) # regenerate an index + index = random.choice(range(len(self))) # regenerate an index x, y, dataset_dir, audio_ext = self._load_phn_enc(index) x_len, y_len = len(x), len(y[0]) - + # if use neighbor prompt x_neighbor, y_neighbor = None, None use_neighbor_prob = random.random() - neighbor_fn = os.path.join(dataset_dir, self.args.neighbor_folder_name, self.data[index][0]+".txt") - if self.args.neighbor_prompt_prob > 0 and use_neighbor_prob < self.args.neighbor_prompt_prob and os.path.isfile(neighbor_fn): # it might not exist, just because we didn't find neighbor for this file (other than itself, which is common for emilia) + neighbor_fn = os.path.join( + dataset_dir, self.args.neighbor_folder_name, self.data[index][0] + ".txt" + ) + if ( + self.args.neighbor_prompt_prob > 0 + and use_neighbor_prob < self.args.neighbor_prompt_prob + and os.path.isfile(neighbor_fn) + ): # it might not exist, just because we didn't find neighbor for this file (other than itself, which is common for emilia) with open(neighbor_fn, "r") as f: neighbors = [l.strip().split("\t") for l in f.readlines()] # select neighbors @@ -379,26 +555,38 @@ def __getitem__(self, index): raise NotImplementedError x_neighbor, y_neighbor = None, None if len(neighbors) > 0: - x_neighbor, y_neighbor = self.find_neighbor(neighbors, y_len, dataset_dir, audio_ext) + x_neighbor, y_neighbor = self.find_neighbor( + neighbors, y_len, dataset_dir, audio_ext + ) i_trial = 0 - while x_neighbor is None and i_trial < self.args.num_trial and i_trial < len(neighbors): - x_neighbor, y_neighbor = self.find_neighbor(neighbors, y_len, dataset_dir, audio_ext) + while ( + x_neighbor is None + and i_trial < self.args.num_trial + and i_trial < len(neighbors) + ): + x_neighbor, y_neighbor = self.find_neighbor( + neighbors, y_len, dataset_dir, audio_ext + ) i_trial += 1 - + if x_neighbor != None: if self.args.x_sep_token != None: x = x_neighbor + [self.args.x_sep_token] + x else: x = x_neighbor + x if self.args.y_sep_token != None: - y = [y_neighbor[i] + [self.args.y_sep_token] + y[i] for i in range(len(y))] + y = [ + y_neighbor[i] + [self.args.y_sep_token] + y[i] + for i in range(len(y)) + ] else: y = [y_neighbor[i] + y[i] for i in range(len(y))] - extra_ret['y_sep_token_position'] = len(y_neighbor[0]) + 1 # if using y_sep_token, this is actually the position of the token right before the y_sep_token, but since y_sep_token is ignored in loss computation, it's fine that we use the position of the token right before it - extra_ret['x_sep_token_position'] = len(x_neighbor) + 1 + extra_ret["y_sep_token_position"] = ( + len(y_neighbor[0]) + 1 + ) # if using y_sep_token, this is actually the position of the token right before the y_sep_token, but since y_sep_token is ignored in loss computation, it's fine that we use the position of the token right before it + extra_ret["x_sep_token_position"] = len(x_neighbor) + 1 x_len, y_len = len(x), len(y[0]) - # consider adding eos to the end of the text if self.args.add_eos_to_text != 0: x.append(self.args.add_eos_to_text) @@ -411,37 +599,46 @@ def __getitem__(self, index): # adjust the length of encodec codes, pad to max_len or randomly crop orig_y_len = copy.copy(y_len) max_len = int(self.args.audio_max_length * self.args.encodec_sr) - if y_len > max_len + 10: # give it some margin for rounding error + if y_len > max_len + 10: # give it some margin for rounding error raise RuntimeError(f"audio is too long, {y_len=}, {max_len=}") else: audio_start = 0 if not self.args.dynamic_batching: - pad = [0] * (max_len - y_len) if self.args.sep_special_token else [self.args.audio_pad_token] * (max_len - y_len) + pad = ( + [0] * (max_len - y_len) + if self.args.sep_special_token + else [self.args.audio_pad_token] * (max_len - y_len) + ) for i in range(len(y)): y[i] = y[i] + pad - + if self.args.pad_x and x_len <= self.args.text_max_length: - pad = [0] * (self.args.text_max_length - x_len) if self.args.sep_special_token else [self.args.text_pad_token] * (self.args.text_max_length - x_len) + pad = ( + [0] * (self.args.text_max_length - x_len) + if self.args.sep_special_token + else [self.args.text_pad_token] * (self.args.text_max_length - x_len) + ) x = x + pad - + ret = { - "x": torch.LongTensor(x), - "x_len": x_len, - "y": torch.LongTensor(y), + "x": torch.LongTensor(x), + "x_len": x_len, + "y": torch.LongTensor(y), "y_len": y_len, - } + } ret.update(extra_ret) return ret - def collate(self, batch): # make sure keys in every batch is the same for batch1, batch2 in zip(batch[:-1], batch[1:]): - assert set(batch1.keys()) == set(batch2.keys()), f"keys in batch1: {batch1.keys()} and keys in batch2: {batch2.keys()} are different" - out = {key:[] for key in batch[0]} + assert set(batch1.keys()) == set( + batch2.keys() + ), f"keys in batch1: {batch1.keys()} and keys in batch2: {batch2.keys()} are different" + out = {key: [] for key in batch[0]} for item in batch: - if item['x'] == None: # deal with load failure + if item["x"] == None: # deal with load failure continue for key, val in item.items(): out[key].append(val) @@ -449,18 +646,27 @@ def collate(self, batch): if self.args.pad_x: res["x"] = torch.stack(out["x"], dim=0) else: - res["x"] = torch.nn.utils.rnn.pad_sequence(out["x"], batch_first=True, padding_value=self.args.text_pad_token) + res["x"] = torch.nn.utils.rnn.pad_sequence( + out["x"], batch_first=True, padding_value=self.args.text_pad_token + ) res["x_lens"] = torch.LongTensor(out["x_len"]) if self.args.dynamic_batching: - res['y'] = torch.nn.utils.rnn.pad_sequence([item.transpose(1,0) for item in out['y']],padding_value=self.args.audio_pad_token) - res['y'] = res['y'].permute(1,2,0) # T B K -> B K T + res["y"] = torch.nn.utils.rnn.pad_sequence( + [item.transpose(1, 0) for item in out["y"]], + padding_value=self.args.audio_pad_token, + ) + res["y"] = res["y"].permute(1, 2, 0) # T B K -> B K T else: - res['y'] = torch.stack(out['y'], dim=0) + res["y"] = torch.stack(out["y"], dim=0) res["y_lens"] = torch.LongTensor(out["y_len"]) - res["text_padding_mask"] = torch.arange(res['x'][0].shape[-1]).unsqueeze(0) >= res['x_lens'].unsqueeze(1) - res["audio_padding_mask"] = torch.arange(res['y'][0].shape[-1]).unsqueeze(0) >= res['y_lens'].unsqueeze(1) + res["text_padding_mask"] = torch.arange(res["x"][0].shape[-1]).unsqueeze( + 0 + ) >= res["x_lens"].unsqueeze(1) + res["audio_padding_mask"] = torch.arange(res["y"][0].shape[-1]).unsqueeze( + 0 + ) >= res["y_lens"].unsqueeze(1) if "y_sep_token_position" in out: res["y_sep_token_position"] = torch.LongTensor(out["y_sep_token_position"]) if "x_sep_token_position" in out: res["x_sep_token_position"] = torch.LongTensor(out["x_sep_token_position"]) - return res \ No newline at end of file + return res diff --git a/data/emilia_preprocessing/encodec.py b/data/emilia_preprocessing/encodec.py index be65978..074fd69 100644 --- a/data/emilia_preprocessing/encodec.py +++ b/data/emilia_preprocessing/encodec.py @@ -25,10 +25,13 @@ import warnings from einops import rearrange, repeat import omegaconf + # import flashy -CONV_NORMALIZATIONS = frozenset(['none', 'weight_norm', 'spectral_norm', - 'time_group_norm']) +CONV_NORMALIZATIONS = frozenset( + ["none", "weight_norm", "spectral_norm", "time_group_norm"] +) + def dict_from_config(cfg: omegaconf.DictConfig) -> dict: """Convenience function to map an omegaconf configuration to a dictionary. @@ -42,6 +45,7 @@ def dict_from_config(cfg: omegaconf.DictConfig) -> dict: assert isinstance(dct, dict) return dct + @dataclass class QuantizedResult: x: torch.Tensor @@ -50,9 +54,9 @@ class QuantizedResult: penalty: tp.Optional[torch.Tensor] = None metrics: dict = field(default_factory=dict) + class BaseQuantizer(nn.Module): - """Base class for quantizers. - """ + """Base class for quantizers.""" def forward(self, x: torch.Tensor, frame_rate: int) -> QuantizedResult: """ @@ -85,17 +89,19 @@ def set_num_codebooks(self, n: int): """Set the number of active codebooks.""" raise NotImplementedError() + class CompressionModel(ABC, nn.Module): """Base API for all compression model that aim at being used as audio tokenizers with a language model. """ @abstractmethod - def forward(self, x: torch.Tensor) -> QuantizedResult: - ... + def forward(self, x: torch.Tensor) -> QuantizedResult: ... @abstractmethod - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """See `EncodecModel.encode`.""" ... @@ -111,44 +117,39 @@ def decode_latent(self, codes: torch.Tensor): @property @abstractmethod - def channels(self) -> int: - ... + def channels(self) -> int: ... @property @abstractmethod - def frame_rate(self) -> float: - ... + def frame_rate(self) -> float: ... @property @abstractmethod - def sample_rate(self) -> int: - ... + def sample_rate(self) -> int: ... @property @abstractmethod - def cardinality(self) -> int: - ... + def cardinality(self) -> int: ... @property @abstractmethod - def num_codebooks(self) -> int: - ... + def num_codebooks(self) -> int: ... @property @abstractmethod - def total_codebooks(self) -> int: - ... + def total_codebooks(self) -> int: ... @abstractmethod def set_num_codebooks(self, n: int): """Set the active number of codebooks used by the quantizer.""" ... -def apply_parametrization_norm(module: nn.Module, norm: str = 'none'): + +def apply_parametrization_norm(module: nn.Module, norm: str = "none"): assert norm in CONV_NORMALIZATIONS - if norm == 'weight_norm': + if norm == "weight_norm": return weight_norm(module) - elif norm == 'spectral_norm': + elif norm == "spectral_norm": return spectral_norm(module) else: # We already check was in CONV_NORMALIZATION, so any other choice @@ -156,12 +157,14 @@ def apply_parametrization_norm(module: nn.Module, norm: str = 'none'): return module -def get_norm_module(module: nn.Module, causal: bool = False, norm: str = 'none', **norm_kwargs): +def get_norm_module( + module: nn.Module, causal: bool = False, norm: str = "none", **norm_kwargs +): """Return the proper normalization module. If causal is True, this will ensure the returned module is causal, or return an error if the normalization doesn't support causal evaluation. """ assert norm in CONV_NORMALIZATIONS - if norm == 'time_group_norm': + if norm == "time_group_norm": if causal: raise ValueError("GroupNorm doesn't support causal evaluation.") assert isinstance(module, nn.modules.conv._ConvNd) @@ -170,8 +173,9 @@ def get_norm_module(module: nn.Module, causal: bool = False, norm: str = 'none', return nn.Identity() -def get_extra_padding_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, - padding_total: int = 0) -> int: +def get_extra_padding_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +) -> int: """See `pad_for_conv1d`.""" length = x.shape[-1] n_frames = (length - kernel_size + padding_total) / stride + 1 @@ -179,7 +183,9 @@ def get_extra_padding_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, return ideal_length - length -def pad_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0): +def pad_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +): """Pad for a convolution to make sure that the last window is full. Extra padding is added at the end. This is required to ensure that we can rebuild an output of the same length, as otherwise, even with padding, some time steps @@ -194,14 +200,19 @@ def pad_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, padding_total return F.pad(x, (0, extra_padding)) -def pad1d(x: torch.Tensor, paddings: tp.Tuple[int, int], mode: str = 'constant', value: float = 0.): +def pad1d( + x: torch.Tensor, + paddings: tp.Tuple[int, int], + mode: str = "constant", + value: float = 0.0, +): """Tiny wrapper around F.pad, just to allow for reflect padding on small input. If this is the case, we insert extra 0 padding to the right before the reflection happen. """ length = x.shape[-1] padding_left, padding_right = paddings assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) - if mode == 'reflect': + if mode == "reflect": max_pad = max(padding_left, padding_right) extra_pad = 0 if length <= max_pad: @@ -220,15 +231,22 @@ def unpad1d(x: torch.Tensor, paddings: tp.Tuple[int, int]): assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) assert (padding_left + padding_right) <= x.shape[-1] end = x.shape[-1] - padding_right - return x[..., padding_left: end] + return x[..., padding_left:end] class NormConv1d(nn.Module): """Wrapper around Conv1d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, causal: bool = False, norm: str = 'none', - norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() self.conv = apply_parametrization_norm(nn.Conv1d(*args, **kwargs), norm) self.norm = get_norm_module(self.conv, causal, norm, **norm_kwargs) @@ -244,7 +262,14 @@ class NormConv2d(nn.Module): """Wrapper around Conv2d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() self.conv = apply_parametrization_norm(nn.Conv2d(*args, **kwargs), norm) self.norm = get_norm_module(self.conv, causal=False, norm=norm, **norm_kwargs) @@ -260,10 +285,19 @@ class NormConvTranspose1d(nn.Module): """Wrapper around ConvTranspose1d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, causal: bool = False, norm: str = 'none', - norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() - self.convtr = apply_parametrization_norm(nn.ConvTranspose1d(*args, **kwargs), norm) + self.convtr = apply_parametrization_norm( + nn.ConvTranspose1d(*args, **kwargs), norm + ) self.norm = get_norm_module(self.convtr, causal, norm, **norm_kwargs) self.norm_type = norm @@ -277,9 +311,18 @@ class NormConvTranspose2d(nn.Module): """Wrapper around ConvTranspose2d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() - self.convtr = apply_parametrization_norm(nn.ConvTranspose2d(*args, **kwargs), norm) + self.convtr = apply_parametrization_norm( + nn.ConvTranspose2d(*args, **kwargs), norm + ) self.norm = get_norm_module(self.convtr, causal=False, norm=norm, **norm_kwargs) def forward(self, x): @@ -292,19 +335,40 @@ class StreamableConv1d(nn.Module): """Conv1d with some builtin handling of asymmetric or causal padding and normalization. """ - def __init__(self, in_channels: int, out_channels: int, - kernel_size: int, stride: int = 1, dilation: int = 1, - groups: int = 1, bias: bool = True, causal: bool = False, - norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, - pad_mode: str = 'reflect'): + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + dilation: int = 1, + groups: int = 1, + bias: bool = True, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + pad_mode: str = "reflect", + ): super().__init__() # warn user on unusual setup between dilation and stride if stride > 1 and dilation > 1: - warnings.warn("StreamableConv1d has been initialized with stride > 1 and dilation > 1" - f" (kernel_size={kernel_size} stride={stride}, dilation={dilation}).") - self.conv = NormConv1d(in_channels, out_channels, kernel_size, stride, - dilation=dilation, groups=groups, bias=bias, causal=causal, - norm=norm, norm_kwargs=norm_kwargs) + warnings.warn( + "StreamableConv1d has been initialized with stride > 1 and dilation > 1" + f" (kernel_size={kernel_size} stride={stride}, dilation={dilation})." + ) + self.conv = NormConv1d( + in_channels, + out_channels, + kernel_size, + stride, + dilation=dilation, + groups=groups, + bias=bias, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) self.causal = causal self.pad_mode = pad_mode @@ -313,9 +377,13 @@ def forward(self, x): kernel_size = self.conv.conv.kernel_size[0] stride = self.conv.conv.stride[0] dilation = self.conv.conv.dilation[0] - kernel_size = (kernel_size - 1) * dilation + 1 # effective kernel size with dilations + kernel_size = ( + kernel_size - 1 + ) * dilation + 1 # effective kernel size with dilations padding_total = kernel_size - stride - extra_padding = get_extra_padding_for_conv1d(x, kernel_size, stride, padding_total) + extra_padding = get_extra_padding_for_conv1d( + x, kernel_size, stride, padding_total + ) if self.causal: # Left padding for causal x = pad1d(x, (padding_total, extra_padding), mode=self.pad_mode) @@ -323,7 +391,9 @@ def forward(self, x): # Asymmetric padding required for odd strides padding_right = padding_total // 2 padding_left = padding_total - padding_right - x = pad1d(x, (padding_left, padding_right + extra_padding), mode=self.pad_mode) + x = pad1d( + x, (padding_left, padding_right + extra_padding), mode=self.pad_mode + ) return self.conv(x) @@ -331,18 +401,34 @@ class StreamableConvTranspose1d(nn.Module): """ConvTranspose1d with some builtin handling of asymmetric or causal padding and normalization. """ - def __init__(self, in_channels: int, out_channels: int, - kernel_size: int, stride: int = 1, causal: bool = False, - norm: str = 'none', trim_right_ratio: float = 1., - norm_kwargs: tp.Dict[str, tp.Any] = {}): + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + causal: bool = False, + norm: str = "none", + trim_right_ratio: float = 1.0, + norm_kwargs: tp.Dict[str, tp.Any] = {}, + ): super().__init__() - self.convtr = NormConvTranspose1d(in_channels, out_channels, kernel_size, stride, - causal=causal, norm=norm, norm_kwargs=norm_kwargs) + self.convtr = NormConvTranspose1d( + in_channels, + out_channels, + kernel_size, + stride, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) self.causal = causal self.trim_right_ratio = trim_right_ratio - assert self.causal or self.trim_right_ratio == 1., \ - "`trim_right_ratio` != 1.0 only makes sense for causal convolutions" - assert self.trim_right_ratio >= 0. and self.trim_right_ratio <= 1. + assert ( + self.causal or self.trim_right_ratio == 1.0 + ), "`trim_right_ratio` != 1.0 only makes sense for causal convolutions" + assert self.trim_right_ratio >= 0.0 and self.trim_right_ratio <= 1.0 def forward(self, x): kernel_size = self.convtr.convtr.kernel_size[0] @@ -373,6 +459,7 @@ class StreamableLSTM(nn.Module): """LSTM without worrying about the hidden state, nor the layout of the data. Expects input as convolutional layout. """ + def __init__(self, dimension: int, num_layers: int = 2, skip: bool = True): super().__init__() self.skip = skip @@ -404,12 +491,25 @@ class SEANetResnetBlock(nn.Module): true_skip (bool): Whether to use true skip connection or a simple (streamable) convolution as the skip connection. """ - def __init__(self, dim: int, kernel_sizes: tp.List[int] = [3, 1], dilations: tp.List[int] = [1, 1], - activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, causal: bool = False, - pad_mode: str = 'reflect', compress: int = 2, true_skip: bool = True): + + def __init__( + self, + dim: int, + kernel_sizes: tp.List[int] = [3, 1], + dilations: tp.List[int] = [1, 1], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + causal: bool = False, + pad_mode: str = "reflect", + compress: int = 2, + true_skip: bool = True, + ): super().__init__() - assert len(kernel_sizes) == len(dilations), 'Number of kernel sizes should match number of dilations' + assert len(kernel_sizes) == len( + dilations + ), "Number of kernel sizes should match number of dilations" act = getattr(nn, activation) hidden = dim // compress block = [] @@ -418,17 +518,31 @@ def __init__(self, dim: int, kernel_sizes: tp.List[int] = [3, 1], dilations: tp. out_chs = dim if i == len(kernel_sizes) - 1 else hidden block += [ act(**activation_params), - StreamableConv1d(in_chs, out_chs, kernel_size=kernel_size, dilation=dilation, - norm=norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode), + StreamableConv1d( + in_chs, + out_chs, + kernel_size=kernel_size, + dilation=dilation, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] self.block = nn.Sequential(*block) self.shortcut: nn.Module if true_skip: self.shortcut = nn.Identity() else: - self.shortcut = StreamableConv1d(dim, dim, kernel_size=1, norm=norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode) + self.shortcut = StreamableConv1d( + dim, + dim, + kernel_size=1, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) def forward(self, x): return self.shortcut(x) + self.block(x) @@ -462,12 +576,29 @@ class SEANetEncoder(nn.Module): disable_norm_outer_blocks (int): Number of blocks for which we don't apply norm. For the encoder, it corresponds to the N first blocks. """ - def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, n_residual_layers: int = 3, - ratios: tp.List[int] = [8, 5, 4, 2], activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, kernel_size: int = 7, - last_kernel_size: int = 7, residual_kernel_size: int = 3, dilation_base: int = 2, causal: bool = False, - pad_mode: str = 'reflect', true_skip: bool = True, compress: int = 2, lstm: int = 0, - disable_norm_outer_blocks: int = 0): + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + ): super().__init__() self.channels = channels self.dimension = dimension @@ -478,36 +609,61 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, self.hop_length = np.prod(self.ratios) self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks self.disable_norm_outer_blocks = disable_norm_outer_blocks - assert self.disable_norm_outer_blocks >= 0 and self.disable_norm_outer_blocks <= self.n_blocks, \ - "Number of blocks for which to disable norm is invalid." \ + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) act = getattr(nn, activation) mult = 1 model: tp.List[nn.Module] = [ - StreamableConv1d(channels, mult * n_filters, kernel_size, - norm='none' if self.disable_norm_outer_blocks >= 1 else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + channels, + mult * n_filters, + kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) ] # Downsample to raw audio scale for i, ratio in enumerate(self.ratios): - block_norm = 'none' if self.disable_norm_outer_blocks >= i + 2 else norm + block_norm = "none" if self.disable_norm_outer_blocks >= i + 2 else norm # Add residual layers for j in range(n_residual_layers): model += [ - SEANetResnetBlock(mult * n_filters, kernel_sizes=[residual_kernel_size, 1], - dilations=[dilation_base ** j, 1], - norm=block_norm, norm_params=norm_params, - activation=activation, activation_params=activation_params, - causal=causal, pad_mode=pad_mode, compress=compress, true_skip=true_skip)] + SEANetResnetBlock( + mult * n_filters, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + norm=block_norm, + norm_params=norm_params, + activation=activation, + activation_params=activation_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] # Add downsampling layers model += [ act(**activation_params), - StreamableConv1d(mult * n_filters, mult * n_filters * 2, - kernel_size=ratio * 2, stride=ratio, - norm=block_norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode), + StreamableConv1d( + mult * n_filters, + mult * n_filters * 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] mult *= 2 @@ -516,9 +672,17 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, model += [ act(**activation_params), - StreamableConv1d(mult * n_filters, dimension, last_kernel_size, - norm='none' if self.disable_norm_outer_blocks == self.n_blocks else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + mult * n_filters, + dimension, + last_kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] self.model = nn.Sequential(*model) @@ -557,13 +721,32 @@ class SEANetDecoder(nn.Module): trim_right_ratio (float): Ratio for trimming at the right of the transposed convolution under the causal setup. If equal to 1.0, it means that all the trimming is done at the right. """ - def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, n_residual_layers: int = 3, - ratios: tp.List[int] = [8, 5, 4, 2], activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - final_activation: tp.Optional[str] = None, final_activation_params: tp.Optional[dict] = None, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, kernel_size: int = 7, - last_kernel_size: int = 7, residual_kernel_size: int = 3, dilation_base: int = 2, causal: bool = False, - pad_mode: str = 'reflect', true_skip: bool = True, compress: int = 2, lstm: int = 0, - disable_norm_outer_blocks: int = 0, trim_right_ratio: float = 1.0): + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + final_activation: tp.Optional[str] = None, + final_activation_params: tp.Optional[dict] = None, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + trim_right_ratio: float = 1.0, + ): super().__init__() self.dimension = dimension self.channels = channels @@ -574,16 +757,28 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, self.hop_length = np.prod(self.ratios) self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks self.disable_norm_outer_blocks = disable_norm_outer_blocks - assert self.disable_norm_outer_blocks >= 0 and self.disable_norm_outer_blocks <= self.n_blocks, \ - "Number of blocks for which to disable norm is invalid." \ + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) act = getattr(nn, activation) mult = int(2 ** len(self.ratios)) model: tp.List[nn.Module] = [ - StreamableConv1d(dimension, mult * n_filters, kernel_size, - norm='none' if self.disable_norm_outer_blocks == self.n_blocks else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + dimension, + mult * n_filters, + kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) ] if lstm: @@ -591,40 +786,63 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, # Upsample to raw audio scale for i, ratio in enumerate(self.ratios): - block_norm = 'none' if self.disable_norm_outer_blocks >= self.n_blocks - (i + 1) else norm + block_norm = ( + "none" + if self.disable_norm_outer_blocks >= self.n_blocks - (i + 1) + else norm + ) # Add upsampling layers model += [ act(**activation_params), - StreamableConvTranspose1d(mult * n_filters, mult * n_filters // 2, - kernel_size=ratio * 2, stride=ratio, - norm=block_norm, norm_kwargs=norm_params, - causal=causal, trim_right_ratio=trim_right_ratio), + StreamableConvTranspose1d( + mult * n_filters, + mult * n_filters // 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + trim_right_ratio=trim_right_ratio, + ), ] # Add residual layers for j in range(n_residual_layers): model += [ - SEANetResnetBlock(mult * n_filters // 2, kernel_sizes=[residual_kernel_size, 1], - dilations=[dilation_base ** j, 1], - activation=activation, activation_params=activation_params, - norm=block_norm, norm_params=norm_params, causal=causal, - pad_mode=pad_mode, compress=compress, true_skip=true_skip)] + SEANetResnetBlock( + mult * n_filters // 2, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + activation=activation, + activation_params=activation_params, + norm=block_norm, + norm_params=norm_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] mult //= 2 # Add final layers model += [ act(**activation_params), - StreamableConv1d(n_filters, channels, last_kernel_size, - norm='none' if self.disable_norm_outer_blocks >= 1 else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + n_filters, + channels, + last_kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] # Add optional final activation to decoder (eg. tanh) if final_activation is not None: final_act = getattr(nn, final_activation) final_activation_params = final_activation_params or {} - model += [ - final_act(**final_activation_params) - ] + model += [final_act(**final_activation_params)] self.model = nn.Sequential(*model) def forward(self, z): @@ -675,10 +893,8 @@ def kmeans(samples, num_clusters: int, num_iters: int = 10): means = sample_vectors(samples, num_clusters) for _ in range(num_iters): - diffs = rearrange(samples, "n d -> n () d") - rearrange( - means, "c d -> () c d" - ) - dists = -(diffs ** 2).sum(dim=-1) + diffs = rearrange(samples, "n d -> n () d") - rearrange(means, "c d -> () c d") + dists = -(diffs**2).sum(dim=-1) buckets = dists.max(dim=-1).indices bins = torch.bincount(buckets, minlength=num_clusters) @@ -700,7 +916,7 @@ def orthogonal_loss_fn(t): normed_codes = l2norm(t) identity = torch.eye(n, device=t.device) cosine_sim = einsum("i d, j d -> i j", normed_codes, normed_codes) - return ((cosine_sim - identity) ** 2).sum() / (n ** 2) + return ((cosine_sim - identity) ** 2).sum() / (n**2) class EuclideanCodebook(nn.Module): @@ -719,6 +935,7 @@ class EuclideanCodebook(nn.Module): that have an exponential moving average cluster size less than the specified threshold with randomly selected vector from the current batch. """ + def __init__( self, dim: int, @@ -731,7 +948,9 @@ def __init__( ): super().__init__() self.decay = decay - init_fn: tp.Union[tp.Callable[..., torch.Tensor], tp.Any] = uniform_init if not kmeans_init else torch.zeros + init_fn: tp.Union[tp.Callable[..., torch.Tensor], tp.Any] = ( + uniform_init if not kmeans_init else torch.zeros + ) embed = init_fn(codebook_size, dim) self.codebook_size = codebook_size @@ -862,6 +1081,7 @@ class VectorQuantization(nn.Module): that have an exponential moving average cluster size less than the specified threshold with randomly selected vector from the current batch. """ + def __init__( self, dim: int, @@ -873,7 +1093,7 @@ def __init__( kmeans_iters: int = 10, threshold_ema_dead_code: int = 2, channels_last: bool = False, - commitment_weight: float = 1., + commitment_weight: float = 1.0, orthogonal_reg_weight: float = 0.0, orthogonal_reg_active_codes_only: bool = False, orthogonal_reg_max_codes: tp.Optional[int] = None, @@ -882,8 +1102,12 @@ def __init__( _codebook_dim: int = default(codebook_dim, dim) requires_projection = _codebook_dim != dim - self.project_in = (nn.Linear(dim, _codebook_dim) if requires_projection else nn.Identity()) - self.project_out = (nn.Linear(_codebook_dim, dim) if requires_projection else nn.Identity()) + self.project_in = ( + nn.Linear(dim, _codebook_dim) if requires_projection else nn.Identity() + ) + self.project_out = ( + nn.Linear(_codebook_dim, dim) if requires_projection else nn.Identity() + ) self.epsilon = epsilon self.commitment_weight = commitment_weight @@ -892,10 +1116,15 @@ def __init__( self.orthogonal_reg_active_codes_only = orthogonal_reg_active_codes_only self.orthogonal_reg_max_codes = orthogonal_reg_max_codes - self._codebook = EuclideanCodebook(dim=_codebook_dim, codebook_size=codebook_size, - kmeans_init=kmeans_init, kmeans_iters=kmeans_iters, - decay=decay, epsilon=epsilon, - threshold_ema_dead_code=threshold_ema_dead_code) + self._codebook = EuclideanCodebook( + dim=_codebook_dim, + codebook_size=codebook_size, + kmeans_init=kmeans_init, + kmeans_iters=kmeans_iters, + decay=decay, + epsilon=epsilon, + threshold_ema_dead_code=threshold_ema_dead_code, + ) self.codebook_size = codebook_size self.channels_last = channels_last @@ -956,8 +1185,13 @@ def forward(self, x): codebook = codebook[unique_code_ids] num_codes = codebook.shape[0] - if exists(self.orthogonal_reg_max_codes) and num_codes > self.orthogonal_reg_max_codes: - rand_ids = torch.randperm(num_codes, device=device)[:self.orthogonal_reg_max_codes] + if ( + exists(self.orthogonal_reg_max_codes) + and num_codes > self.orthogonal_reg_max_codes + ): + rand_ids = torch.randperm(num_codes, device=device)[ + : self.orthogonal_reg_max_codes + ] codebook = codebook[rand_ids] orthogonal_reg_loss = orthogonal_loss_fn(codebook) @@ -974,17 +1208,20 @@ class ResidualVectorQuantization(nn.Module): Follows Algorithm 1. in https://arxiv.org/pdf/2107.03312.pdf """ + def __init__(self, *, num_quantizers, **kwargs): super().__init__() - codebook_size = kwargs.pop('codebook_size', None) + codebook_size = kwargs.pop("codebook_size", None) if codebook_size is None: raise ValueError("codebook_size must be provided in kwargs") if type(codebook_size) != list: codebook_size = [codebook_size] * num_quantizers self.layers = nn.ModuleList( - [VectorQuantization(codebook_size=cur_codebook_size, **kwargs) for _,cur_codebook_size in zip(range(num_quantizers), codebook_size)] + [ + VectorQuantization(codebook_size=cur_codebook_size, **kwargs) + for _, cur_codebook_size in zip(range(num_quantizers), codebook_size) + ] ) - # self.layers = nn.ModuleList( # [VectorQuantization(**kwargs) for _ in range(num_quantizers)] @@ -1058,6 +1295,7 @@ class ResidualVectorQuantizer(BaseQuantizer): orthogonal_reg_max_codes (optional int): Maximum number of codes to consider. for orthogonal regularization. """ + def __init__( self, dimension: int = 256, @@ -1096,7 +1334,7 @@ def __init__( orthogonal_reg_weight=self.orthogonal_reg_weight, orthogonal_reg_active_codes_only=self.orthogonal_reg_active_codes_only, orthogonal_reg_max_codes=self.orthogonal_reg_max_codes, - channels_last=False + channels_last=False, ) def forward(self, x: torch.Tensor, frame_rate: int): @@ -1144,15 +1382,18 @@ def set_num_codebooks(self, n: int): assert n > 0 and n <= self.max_n_q self.n_q = n + class DummyQuantizer(BaseQuantizer): - """Fake quantizer that actually does not perform any quantization. - """ + """Fake quantizer that actually does not perform any quantization.""" + def __init__(self): super().__init__() def forward(self, x: torch.Tensor, frame_rate: int): q = x.unsqueeze(1) - return QuantizedResult(x, q, torch.tensor(q.numel() * 32 * frame_rate / 1000 / len(x)).to(x)) + return QuantizedResult( + x, q, torch.tensor(q.numel() * 32 * frame_rate / 1000 / len(x)).to(x) + ) def encode(self, x: torch.Tensor) -> torch.Tensor: """Encode a given input tensor with the specified sample rate at the given bandwidth. @@ -1180,7 +1421,9 @@ def num_codebooks(self): def set_num_codebooks(self, n: int): """Set the number of active codebooks.""" - raise AttributeError("Cannot override the number of codebooks for the dummy quantizer") + raise AttributeError( + "Cannot override the number of codebooks for the dummy quantizer" + ) class EncodecModel(CompressionModel): @@ -1196,21 +1439,24 @@ class EncodecModel(CompressionModel): causal (bool): Whether to use a causal version of the model. renormalize (bool): Whether to renormalize the audio before running the model. """ + # we need assignment to override the property in the abstract class, # I couldn't find a better way... frame_rate: float = 0 sample_rate: int = 0 channels: int = 0 - def __init__(self, - encoder: nn.Module, - decoder: nn.Module, - quantizer: BaseQuantizer, - frame_rate: int, - sample_rate: int, - channels: int, - causal: bool = False, - renormalize: bool = False): + def __init__( + self, + encoder: nn.Module, + decoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): super().__init__() self.encoder = encoder self.decoder = decoder @@ -1223,7 +1469,7 @@ def __init__(self, if self.causal: # we force disabling here to avoid handling linear overlap of segments # as supported in original EnCodec codebase. - assert not self.renormalize, 'Causal model does not support renormalize' + assert not self.renormalize, "Causal model does not support renormalize" @property def total_codebooks(self): @@ -1244,7 +1490,9 @@ def cardinality(self): """Cardinality of each codebook.""" return self.quantizer.bins - def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: scale: tp.Optional[torch.Tensor] if self.renormalize: mono = x.mean(dim=1, keepdim=True) @@ -1256,9 +1504,9 @@ def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torc scale = None return x, scale - def postprocess(self, - x: torch.Tensor, - scale: tp.Optional[torch.Tensor] = None) -> torch.Tensor: + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: if scale is not None: assert self.renormalize x = x * scale.view(-1, 1, 1) @@ -1285,7 +1533,9 @@ def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: return q_res - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """Encode the given input tensor to quantized representation along with scale parameter. Args: @@ -1323,6 +1573,7 @@ def decode_latent(self, codes: torch.Tensor): """Decode from the discrete codes to continuous latent space.""" return self.quantizer.decode(codes) + class EncodecModel_encode_only(CompressionModel): """Encodec model operating on the raw waveform. Encode only, so no decoder @@ -1335,20 +1586,23 @@ class EncodecModel_encode_only(CompressionModel): causal (bool): Whether to use a causal version of the model. renormalize (bool): Whether to renormalize the audio before running the model. """ + # we need assignment to override the property in the abstract class, # I couldn't find a better way... frame_rate: float = 0 sample_rate: int = 0 channels: int = 0 - def __init__(self, - encoder: nn.Module, - quantizer: BaseQuantizer, - frame_rate: int, - sample_rate: int, - channels: int, - causal: bool = False, - renormalize: bool = False): + def __init__( + self, + encoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): super().__init__() self.encoder = encoder self.quantizer = quantizer @@ -1360,7 +1614,7 @@ def __init__(self, if self.causal: # we force disabling here to avoid handling linear overlap of segments # as supported in original EnCodec codebase. - assert not self.renormalize, 'Causal model does not support renormalize' + assert not self.renormalize, "Causal model does not support renormalize" @property def total_codebooks(self): @@ -1381,7 +1635,9 @@ def cardinality(self): """Cardinality of each codebook.""" return self.quantizer.bins - def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: scale: tp.Optional[torch.Tensor] if self.renormalize: mono = x.mean(dim=1, keepdim=True) @@ -1393,9 +1649,9 @@ def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torc scale = None return x, scale - def postprocess(self, - x: torch.Tensor, - scale: tp.Optional[torch.Tensor] = None) -> torch.Tensor: + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: if scale is not None: assert self.renormalize x = x * scale.view(-1, 1, 1) @@ -1422,7 +1678,9 @@ def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: return q_res - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """Encode the given input tensor to quantized representation along with scale parameter. Args: @@ -1462,21 +1720,22 @@ def decode_latent(self, codes: torch.Tensor): raise NotImplementedError("Decode is not supported for encode only model") return self.quantizer.decode(codes) -def get_quantizer(quantizer: str, cfg: omegaconf.DictConfig, dimension: int) -> BaseQuantizer: - klass = { - 'no_quant': DummyQuantizer, - 'rvq': ResidualVectorQuantizer - }[quantizer] + +def get_quantizer( + quantizer: str, cfg: omegaconf.DictConfig, dimension: int +) -> BaseQuantizer: + klass = {"no_quant": DummyQuantizer, "rvq": ResidualVectorQuantizer}[quantizer] kwargs = dict_from_config(getattr(cfg, quantizer)) - if quantizer != 'no_quant': - kwargs['dimension'] = dimension + if quantizer != "no_quant": + kwargs["dimension"] = dimension return klass(**kwargs) + def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): - if encoder_name == 'seanet': - kwargs = dict_from_config(getattr(cfg, 'seanet')) - encoder_override_kwargs = kwargs.pop('encoder') - decoder_override_kwargs = kwargs.pop('decoder') + if encoder_name == "seanet": + kwargs = dict_from_config(getattr(cfg, "seanet")) + encoder_override_kwargs = kwargs.pop("encoder") + decoder_override_kwargs = kwargs.pop("decoder") encoder_kwargs = {**kwargs, **encoder_override_kwargs} decoder_kwargs = {**kwargs, **decoder_override_kwargs} encoder = SEANetEncoder(**encoder_kwargs) @@ -1489,56 +1748,85 @@ def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: """Instantiate a compression model.""" if device == None: - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - state = torch.load(ckpt_fn, map_location='cpu') - cfg = state['xp.cfg'] + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + state = torch.load(ckpt_fn, map_location="cpu") + cfg = state["xp.cfg"] cfg.device = str(device) - weights = state['best_state']['model'] - assert cfg.compression_model == 'encodec', "Only Encodec model is supported for now." + weights = state["best_state"]["model"] + assert ( + cfg.compression_model == "encodec" + ), "Only Encodec model is supported for now." if encode_only: all_keys = list(weights.keys()) for key in all_keys: - if key.startswith('decoder'): + if key.startswith("decoder"): del weights[key] - kwargs = dict_from_config(getattr(cfg, 'encodec')) - encoder_name = kwargs.pop('autoencoder') - quantizer_name = kwargs.pop('quantizer') + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") encoder, _ = get_encodec_autoencoder(encoder_name, cfg) quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) - frame_rate = kwargs['sample_rate'] // encoder.hop_length - renormalize = kwargs.pop('renormalize', False) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) # deprecated params - kwargs.pop('renorm', None) - compression_model = EncodecModel_encode_only(encoder, quantizer, - frame_rate=frame_rate, renormalize=renormalize, **kwargs).to(cfg.device) - assert compression_model.sample_rate == cfg.sample_rate, "Compression model sample rate should match" + kwargs.pop("renorm", None) + compression_model = EncodecModel_encode_only( + encoder, quantizer, frame_rate=frame_rate, renormalize=renormalize, **kwargs + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" compression_model.load_state_dict(weights) compression_model.eval() return compression_model else: - kwargs = dict_from_config(getattr(cfg, 'encodec')) - encoder_name = kwargs.pop('autoencoder') - quantizer_name = kwargs.pop('quantizer') + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") encoder, decoder = get_encodec_autoencoder(encoder_name, cfg) quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) - frame_rate = kwargs['sample_rate'] // encoder.hop_length - renormalize = kwargs.pop('renormalize', False) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) # deprecated params - kwargs.pop('renorm', None) - compression_model = EncodecModel(encoder, decoder, quantizer, - frame_rate=frame_rate, renormalize=renormalize, **kwargs).to(cfg.device) - assert compression_model.sample_rate == cfg.sample_rate, "Compression model sample rate should match" + kwargs.pop("renorm", None) + compression_model = EncodecModel( + encoder, + decoder, + quantizer, + frame_rate=frame_rate, + renormalize=renormalize, + **kwargs, + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" compression_model.load_state_dict(weights) compression_model.eval() return compression_model + if __name__ == "__main__": import torchaudio + ckpt_fn = "/home/pyp/BoostedVoiceEditor/pretrained/encodec_6f79c6a8.th" - audio_in_fns = ["/home/pyp/BoostedVoiceEditor/demo/pam.wav", "/home/pyp/BoostedVoiceEditor/demo/ray.wav", "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000.wav", "/home/pyp/BoostedVoiceEditor/demo/caribbean.wav", "/home/pyp/BoostedVoiceEditor/demo/bible.wav", "/home/pyp/BoostedVoiceEditor/demo/miley.wav"] - audio_out_fns = ["/home/pyp/BoostedVoiceEditor/demo/pam_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/ray_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/caribbean_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav"] - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + audio_in_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley.wav", + ] + audio_out_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", + ] + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") model = get_compression_model(ckpt_fn, device=device) for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): @@ -1551,4 +1839,4 @@ def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> Compressi audio_in = audio_in.to(torch.float32).to(device) codes = model.encode(audio_in)[0] audio_out = model.decode(codes)[0].cpu() - torchaudio.save(audio_out_fn, audio_out, model.sample_rate) \ No newline at end of file + torchaudio.save(audio_out_fn, audio_out, model.sample_rate) diff --git a/data/emilia_preprocessing/sha256hash.py b/data/emilia_preprocessing/sha256hash.py index 42802a2..3e43ad1 100644 --- a/data/emilia_preprocessing/sha256hash.py +++ b/data/emilia_preprocessing/sha256hash.py @@ -1,6 +1,7 @@ import hashlib import sys + def sha256_hash_file(filename): sha256_hash = hashlib.sha256() with open(filename, "rb") as file: @@ -9,6 +10,7 @@ def sha256_hash_file(filename): sha256_hash.update(byte_block) return sha256_hash.hexdigest() + # Usage example filename = sys.argv[1] -print(sha256_hash_file(filename)) \ No newline at end of file +print(sha256_hash_file(filename)) diff --git a/data/emilia_preprocessing/step1_download.py b/data/emilia_preprocessing/step1_download.py index 601b4de..258f294 100644 --- a/data/emilia_preprocessing/step1_download.py +++ b/data/emilia_preprocessing/step1_download.py @@ -1,9 +1,19 @@ # conda activate emilia from datasets import load_dataset import fire -def main(root: str="/data/scratch/pyp/datasets/emilia"): + + +def main(root: str = "/data/scratch/pyp/datasets/emilia"): path = "EN/*.tar.gz*" - dataset = load_dataset("amphion/Emilia-Dataset", data_files={"en": path}, split="en", streaming=False, revision="fc71e07e8572f5f3be1dbd02ed3172a4d298f152", cache_dir=root) + dataset = load_dataset( + "amphion/Emilia-Dataset", + data_files={"en": path}, + split="en", + streaming=False, + revision="fc71e07e8572f5f3be1dbd02ed3172a4d298f152", + cache_dir=root, + ) + if __name__ == "__main__": - fire.Fire(main) \ No newline at end of file + fire.Fire(main) diff --git a/data/emilia_preprocessing/step4_construct_manifest.py b/data/emilia_preprocessing/step4_construct_manifest.py index b97d868..aaae973 100644 --- a/data/emilia_preprocessing/step4_construct_manifest.py +++ b/data/emilia_preprocessing/step4_construct_manifest.py @@ -12,17 +12,22 @@ from multiprocessing import Pool import glob, os from collections import defaultdict + + def write_jsonl(data, fn): with open(fn, "w") as file: for entry in data: file.write(json.dumps(entry, ensure_ascii=False) + "\n") + + def read_jsonl(file_path): cur_data = [] - with open(file_path, 'r', encoding='utf-8-sig') as file: + with open(file_path, "r", encoding="utf-8-sig") as file: for line in file: cur_data.append(json.loads(line.strip())) return cur_data + def repetition_found(text, length=2, tolerance=10): pattern_count = defaultdict(int) for i in range(len(text) - length + 1): @@ -34,7 +39,6 @@ def repetition_found(text, length=2, tolerance=10): return False - out_en = { "EN_B00013_S00913", "EN_B00042_S00120", @@ -114,6 +118,7 @@ def repetition_found(text, length=2, tolerance=10): from multiprocessing import Pool + def process_meta_item(item, root, sub_root, audio_folder, audio_ext, text_ext): global filtered_duration, filtered_count, total_duration, total_count # Data filtering following Yushen's approach @@ -123,13 +128,15 @@ def process_meta_item(item, root, sub_root, audio_folder, audio_ext, text_ext): or repetition_found(item["text"], length=4) ): return None, item["duration"], 1, 0, 0, (None, None) # Return filtered results - + # Trim leading space from text if exists if item["text"].startswith(" "): item["text"] = item["text"][1:] - + # write text to text file - text_fn = os.path.join(root, sub_root, audio_folder, item["wav"].replace(audio_ext, text_ext)) + text_fn = os.path.join( + root, sub_root, audio_folder, item["wav"].replace(audio_ext, text_ext) + ) os.makedirs(os.path.dirname(text_fn), exist_ok=True) with open(text_fn, "w") as f: f.write(item["text"]) @@ -141,24 +148,29 @@ def process_meta_item(item, root, sub_root, audio_folder, audio_ext, text_ext): 0, item["duration"], 1, - (item['speaker'], item) + (item["speaker"], item), ) # Return processed results -def parallel_process_meta(meta, root, sub_root, audio_folder, num_workers, audio_ext, text_ext): +def parallel_process_meta( + meta, root, sub_root, audio_folder, num_workers, audio_ext, text_ext +): with Pool(num_workers) as pool: results = pool.starmap( process_meta_item, - [(item, root, sub_root, audio_folder, audio_ext, text_ext) for item in meta], + [ + (item, root, sub_root, audio_folder, audio_ext, text_ext) + for item in meta + ], ) - + processed_items = [] spkitem = [] filtered_duration = 0 filtered_count = 0 total_duration = 0 total_count = 0 - + for result in results: if result[0]: # If the item was processed processed_items.append(result[0]) @@ -167,8 +179,15 @@ def parallel_process_meta(meta, root, sub_root, audio_folder, num_workers, audio total_duration += result[3] total_count += result[4] spkitem.append(result[5]) - - return processed_items, filtered_duration, filtered_count, total_duration, total_count, spkitem + + return ( + processed_items, + filtered_duration, + filtered_count, + total_duration, + total_count, + spkitem, + ) def main( @@ -189,7 +208,7 @@ def main( ] print(f"found {len(all_fns)} untarred segments") print(f"{all_fns[:3]}") - + res = [] total_duration = 0 total_count = 0 @@ -200,12 +219,12 @@ def main( spk2info = defaultdict(list) metafn = os.path.join(root, "EN", os.path.basename(fn) + ".jsonl") meta = read_jsonl(metafn) - + # Parallel process metadata processed_items, fd, fc, td, tc, spkitem = parallel_process_meta( meta, root, sub_root, audio_folder, num_workers, audio_ext, text_ext ) - + # Aggregate results res.extend(processed_items) filtered_duration += fd @@ -216,7 +235,7 @@ def main( for spk, item in spkitem: if spk: spk2info[spk].append(item) - + # Save neighbor files for spk in spk2info: for item in spk2info[spk]: @@ -227,11 +246,15 @@ def main( item["wav"].replace(audio_ext, text_ext), ) os.makedirs(os.path.dirname(neighbor_fn), exist_ok=True) - tobe_write = [f"{neighbor_item['wav'].replace(audio_ext, text_ext)}\t0\t{neighbor_item['duration']}\n" for neighbor_item in spk2info[spk] if neighbor_item["wav"] != item["wav"]] + tobe_write = [ + f"{neighbor_item['wav'].replace(audio_ext, text_ext)}\t0\t{neighbor_item['duration']}\n" + for neighbor_item in spk2info[spk] + if neighbor_item["wav"] != item["wav"] + ] if tobe_write: with open(neighbor_fn, "w") as f: f.writelines(tobe_write) - + print( f"total duration: {total_duration / 3600:.2f} hours, total count: {total_count}" ) @@ -248,4 +271,4 @@ def main( if __name__ == "__main__": import fire - fire.Fire(main) \ No newline at end of file + fire.Fire(main) diff --git a/data/emilia_preprocessing/step5_phonemize.py b/data/emilia_preprocessing/step5_phonemize.py index bf0d046..ae8148b 100644 --- a/data/emilia_preprocessing/step5_phonemize.py +++ b/data/emilia_preprocessing/step5_phonemize.py @@ -6,9 +6,11 @@ from multiprocessing import Pool import glob, os, fire from collections import defaultdict + sys.path.insert(0, "../../") from data.tokenizer import TextTokenizer, tokenize_text + def write_jsonl(data, fn): with open(fn, "w") as file: for entry in data: @@ -17,7 +19,7 @@ def write_jsonl(data, fn): def read_jsonl(file_path): cur_data = [] - with open(file_path, 'r', encoding='utf-8-sig') as file: + with open(file_path, "r", encoding="utf-8-sig") as file: for line in file: cur_data.append(json.loads(line.strip())) return cur_data @@ -32,9 +34,21 @@ def phonemize_and_save(text, fn, text_tokenizer): return set(phn) -def process_item(item, root, sub_root, audio_folder, phn_folder, audio_ext, text_ext, phn_ext, text_tokenizer): +def process_item( + item, + root, + sub_root, + audio_folder, + phn_folder, + audio_ext, + text_ext, + phn_ext, + text_tokenizer, +): """Worker function to process a single item.""" - text_path = os.path.join(root, sub_root, audio_folder, item[0].replace(audio_ext, text_ext)) + text_path = os.path.join( + root, sub_root, audio_folder, item[0].replace(audio_ext, text_ext) + ) if not os.path.exists(text_path): return {"missing_text": text_path, "success": False, "cur_phn_set": set()} @@ -42,7 +56,9 @@ def process_item(item, root, sub_root, audio_folder, phn_folder, audio_ext, text text = [line.strip() for line in f.readlines()] text = " ".join(text) - phn_path = os.path.join(root, sub_root, phn_folder, item[0].replace(audio_ext, phn_ext)) + phn_path = os.path.join( + root, sub_root, phn_folder, item[0].replace(audio_ext, phn_ext) + ) cur_phn_set = phonemize_and_save(text, phn_path, text_tokenizer) return {"missing_text": None, "success": True, "cur_phn_set": cur_phn_set} @@ -51,6 +67,7 @@ def process_item_star(args): """Unpacks arguments for `process_item` to work with `imap`.""" return process_item(*args) + def main( root="/data/scratch/pyp/datasets/emilia", sub_root="preprocessed", @@ -73,7 +90,7 @@ def main( for fn in all_fns: with open(fn, "r") as f: data += [line.strip().split("\t") for line in f] - + vocab = set() ################## parallel processing ################## @@ -118,7 +135,9 @@ def main( ################## sequential processing ################## missing_text = [] for item in tqdm.tqdm(data): - text_path = os.path.join(root, sub_root, audio_folder, item[0].replace(audio_ext, text_ext)) + text_path = os.path.join( + root, sub_root, audio_folder, item[0].replace(audio_ext, text_ext) + ) if not os.path.exists(text_path): missing_text.append(text_path) continue @@ -129,7 +148,13 @@ def main( except: print(f"Error reading {text_path}") continue - cur_phn_set = phonemize_and_save(text, os.path.join(root, sub_root, phn_folder, item[0].replace(audio_ext, phn_ext)), text_tokenizer) + cur_phn_set = phonemize_and_save( + text, + os.path.join( + root, sub_root, phn_folder, item[0].replace(audio_ext, phn_ext) + ), + text_tokenizer, + ) vocab.update(cur_phn_set) ################## sequential processing ################## ################## sequential processing ################## @@ -145,14 +170,10 @@ def main( # Collect missing text paths print(f"Missing text files: {len(missing_text)}") if missing_text: - print("Some missing files:", missing_text[:10]) # Print the first 10 missing files as an example - + print( + "Some missing files:", missing_text[:10] + ) # Print the first 10 missing files as an example + if __name__ == "__main__": fire.Fire(main) - - - - - - diff --git a/data/emilia_preprocessing/step6_encodec_encode.py b/data/emilia_preprocessing/step6_encodec_encode.py index 952d422..a7e3037 100644 --- a/data/emilia_preprocessing/step6_encodec_encode.py +++ b/data/emilia_preprocessing/step6_encodec_encode.py @@ -1,27 +1,70 @@ import argparse from email.policy import default + + def parse_args(): parser = argparse.ArgumentParser(description="encode the dataset using codec model") - parser.add_argument('--root', type=str, default="/data/scratch/pyp/datasets/emilia", help="Path to the directory") - parser.add_argument('--sub_root', type=str, default="preprocessed", help="sub directory") - parser.add_argument('--encodec_name', type=str, default="encodec_6f79c6a8.th", help="name of the codec model") - parser.add_argument('--n_workers', type=int, default=16, help="Number of parallel worker processes") - parser.add_argument('--batch_size', type=int, default=16, help="batch size for codec encoding, decrease it if OOM. This is the sum of batch size *over each gpu*, so increase it if you are using more gpus") - parser.add_argument('--audio_sr', type=int, default=16000, help='input audio sample rate') - parser.add_argument('--model_sr', type=int, default=16000, help='encodec input audio sample rate') - parser.add_argument('--downsample_rate', type=int, default=320, help='encodec downsample rate') - parser.add_argument('--model_code_sr', type=float, default=50, help='codec model code sample rate') - parser.add_argument('--len_cap', type=float, default=1000, help='will drop audios that are longer than this number') - parser.add_argument('--min_len', type=float, default=0.5, help='will drop audios that are shorter than this number') - parser.add_argument('--partition', type=str, default="1/1", help='split for parallel processing') - parser.add_argument('--split', type=str, default='train', choices=['train', 'valid', 'test']) + parser.add_argument( + "--root", + type=str, + default="/data/scratch/pyp/datasets/emilia", + help="Path to the directory", + ) + parser.add_argument( + "--sub_root", type=str, default="preprocessed", help="sub directory" + ) + parser.add_argument( + "--encodec_name", + type=str, + default="encodec_6f79c6a8.th", + help="name of the codec model", + ) + parser.add_argument( + "--n_workers", type=int, default=16, help="Number of parallel worker processes" + ) + parser.add_argument( + "--batch_size", + type=int, + default=16, + help="batch size for codec encoding, decrease it if OOM. This is the sum of batch size *over each gpu*, so increase it if you are using more gpus", + ) + parser.add_argument( + "--audio_sr", type=int, default=16000, help="input audio sample rate" + ) + parser.add_argument( + "--model_sr", type=int, default=16000, help="encodec input audio sample rate" + ) + parser.add_argument( + "--downsample_rate", type=int, default=320, help="encodec downsample rate" + ) + parser.add_argument( + "--model_code_sr", type=float, default=50, help="codec model code sample rate" + ) + parser.add_argument( + "--len_cap", + type=float, + default=1000, + help="will drop audios that are longer than this number", + ) + parser.add_argument( + "--min_len", + type=float, + default=0.5, + help="will drop audios that are shorter than this number", + ) + parser.add_argument( + "--partition", type=str, default="1/1", help="split for parallel processing" + ) + parser.add_argument( + "--split", type=str, default="train", choices=["train", "valid", "test"] + ) return parser.parse_args() + if __name__ == "__main__": import logging - formatter = ( - "%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d || %(message)s" - ) + + formatter = "%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d || %(message)s" logging.basicConfig(format=formatter, level=logging.INFO) import os, sys @@ -35,31 +78,43 @@ def parse_args(): def sort_by_audio_len(lens): inds = np.argsort(lens).tolist() - - logging.info(f"longest: {lens[inds[-1]]/args.downsample_rate} encodec codes, {lens[inds[-1]]/args.model_sr:.2f} sec.") - logging.info(f"shortest: {lens[inds[0]]/args.downsample_rate} encodec codes, {lens[inds[0]]/args.model_sr:.2f} sec.") - logging.info(f"median: {lens[inds[len(inds)//2]]/args.downsample_rate} encodec codes, {lens[inds[len(inds)//2]]/args.model_sr:.2f} sec.") - logging.info(f"95 percentile longest: {lens[inds[int(len(inds)*0.95)]]/args.downsample_rate} encodec codes, {lens[inds[int(len(inds)*0.95)]]/args.model_sr:.2f} sec.") + + logging.info( + f"longest: {lens[inds[-1]]/args.downsample_rate} encodec codes, {lens[inds[-1]]/args.model_sr:.2f} sec." + ) + logging.info( + f"shortest: {lens[inds[0]]/args.downsample_rate} encodec codes, {lens[inds[0]]/args.model_sr:.2f} sec." + ) + logging.info( + f"median: {lens[inds[len(inds)//2]]/args.downsample_rate} encodec codes, {lens[inds[len(inds)//2]]/args.model_sr:.2f} sec." + ) + logging.info( + f"95 percentile longest: {lens[inds[int(len(inds)*0.95)]]/args.downsample_rate} encodec codes, {lens[inds[int(len(inds)*0.95)]]/args.model_sr:.2f} sec." + ) return inds[::-1] def write_array_to_txt_file(array, filename): - with open(filename, 'w') as f: + with open(filename, "w") as f: for a in array[:-1]: - f.write(' '.join(map(str, a))+'\n') - f.write(' '.join(map(str, array[-1]))) + f.write(" ".join(map(str, a)) + "\n") + f.write(" ".join(map(str, array[-1]))) class mydataset(torch.utils.data.Dataset): def __init__(self, split): super().__init__() self.split = split self.audio_dir = audio_dir - manifest_fn = os.path.join(encodec_manifest_dir, split+".txt") - cur_sp = int(args.partition.split("/")[0])-1 + manifest_fn = os.path.join(encodec_manifest_dir, split + ".txt") + cur_sp = int(args.partition.split("/")[0]) - 1 total_sp = int(args.partition.split("/")[1]) with open(manifest_fn, "r") as rf: - self.data = [l.strip().split("\t") for l in rf.readlines()][cur_sp::total_sp] + self.data = [l.strip().split("\t") for l in rf.readlines()][ + cur_sp::total_sp + ] + def __len__(self): return len(self.data) + def __getitem__(self, ind): try: afn = self.data[ind][0] @@ -72,8 +127,13 @@ def __getitem__(self, ind): except Exception as e: # logging.info(f"{e}") return None, None, None - assert audio.ndim==2 and audio.shape[0] == 1, audio.shape - return audio.type(torch.float32).squeeze(0), audio.shape[-1], os.path.splitext(afn)[0] + assert audio.ndim == 2 and audio.shape[0] == 1, audio.shape + return ( + audio.type(torch.float32).squeeze(0), + audio.shape[-1], + os.path.splitext(afn)[0], + ) + def collate(self, batch): lens, audios, segment_ids = [], [], [] for item in batch: @@ -82,49 +142,70 @@ def collate(self, batch): lens.append(item[1]) segment_ids.append(item[2]) return audios, lens, segment_ids - + # roots sub_root = args.sub_root encodec_manifest_dir = os.path.join(args.root, sub_root, "manifest_for_codec") audio_dir = os.path.join(args.root, sub_root, "audio") - save_manifest_dir = os.path.join(args.root, sub_root,"manifest_final_encodec") + save_manifest_dir = os.path.join(args.root, sub_root, "manifest_final_encodec") if args.encodec_name == "encodec_6f79c6a8.th": - save_codes_dir = os.path.join(args.root, sub_root,"encodec_4cb") + save_codes_dir = os.path.join(args.root, sub_root, "encodec_4cb") elif args.encodec_name == "encodec_8cb1024_giga.th": - save_codes_dir = os.path.join(args.root, sub_root,"encodec_8cb") + save_codes_dir = os.path.join(args.root, sub_root, "encodec_8cb") os.makedirs(save_manifest_dir, exist_ok=True) os.makedirs(save_codes_dir, exist_ok=True) - + def import_encodec(): from encodec import get_compression_model + userdir = os.path.expanduser("~") - model = get_compression_model(os.path.join(userdir, "VoiceStar", f"pretrained/{args.encodec_name}"), encode_only=True, device="cuda") + model = get_compression_model( + os.path.join(userdir, "VoiceStar", f"pretrained/{args.encodec_name}"), + encode_only=True, + device="cuda", + ) model = torch.nn.DataParallel(model) return model + model = import_encodec() - + # setup dataloader mega_batch_size = 2048 batch_size = args.batch_size - + dataset = mydataset(args.split) if len(dataset) == 0: logging.info(f"no data found for split {args.split} partition {args.partition}") sys.exit(0) - loader = torch.torch.utils.data.DataLoader(dataset, batch_size=mega_batch_size, shuffle=False, drop_last=False, num_workers=args.n_workers, collate_fn=dataset.collate) + loader = torch.torch.utils.data.DataLoader( + dataset, + batch_size=mega_batch_size, + shuffle=False, + drop_last=False, + num_workers=args.n_workers, + collate_fn=dataset.collate, + ) split = args.split skip = 0 logging.info(f"now processing split {split} partition {args.partition}...") mega_n_steps = int(np.ceil(len(loader.dataset) / mega_batch_size)) # mega_n_steps = int(np.ceil(len(gs) / mega_batch_size)) - logging.info(f"partition the split {split} into {mega_n_steps} parts, each has at most {mega_batch_size} samples") - mani_fn = os.path.join(save_manifest_dir, f"{split}_{args.partition.replace('/', '=')}.txt") - logging.info(f"manifest for split {split} partition {args.partition.replace('/', '=')}.txt will be saved at {mani_fn}") + logging.info( + f"partition the split {split} into {mega_n_steps} parts, each has at most {mega_batch_size} samples" + ) + mani_fn = os.path.join( + save_manifest_dir, f"{split}_{args.partition.replace('/', '=')}.txt" + ) + logging.info( + f"manifest for split {split} partition {args.partition.replace('/', '=')}.txt will be saved at {mani_fn}" + ) with open(mani_fn, "w") as mani_wf: - # with open(mani_fn, "a") as mani_wf: # resume from where we failed - for m, mega_batch in enumerate(tqdm.tqdm(loader, mininterval=60, maxinterval=60)): + # with open(mani_fn, "a") as mani_wf: # resume from where we failed + for m, mega_batch in enumerate( + tqdm.tqdm(loader, mininterval=60, maxinterval=60) + ): logging.info(f"====================================") logging.info(f"====================================") @@ -134,44 +215,65 @@ def import_encodec(): lengths = np.array(mega_batch[1]) sorted_inds = sort_by_audio_len(lengths) for j in range(len(sorted_inds))[::-1]: - if lengths[sorted_inds[j]] < args.model_sr*args.min_len or lengths[sorted_inds[j]] > args.model_sr*args.len_cap: # skip samples that are too short (shorter than 0.2s), or too big (bigger than 80s) + if ( + lengths[sorted_inds[j]] < args.model_sr * args.min_len + or lengths[sorted_inds[j]] > args.model_sr * args.len_cap + ): # skip samples that are too short (shorter than 0.2s), or too big (bigger than 80s) skip += 1 del sorted_inds[j] - + n_steps = int(np.ceil(len(sorted_inds) / batch_size)) for n in tqdm.tqdm(range(n_steps), disable=True): - inds_used = sorted_inds[n*batch_size:(n+1)*batch_size] + inds_used = sorted_inds[n * batch_size : (n + 1) * batch_size] wav_batch = [mega_batch[0][id] for id in inds_used] all_lens = [mega_batch[1][id] for id in inds_used] segment_id_batch = [mega_batch[2][id] for id in inds_used] - padded_wav = torch.nn.utils.rnn.pad_sequence(wav_batch, batch_first=True).unsqueeze(1) # [B, T] -> [B, 1, T] + padded_wav = torch.nn.utils.rnn.pad_sequence( + wav_batch, batch_first=True + ).unsqueeze( + 1 + ) # [B, T] -> [B, 1, T] # Extract discrete codes from EnCodec with torch.no_grad(): - if max(all_lens) > 300000 and len(all_lens) > 1: # if utterances are long, simply pass half of them at a time + if ( + max(all_lens) > 300000 and len(all_lens) > 1 + ): # if utterances are long, simply pass half of them at a time codes = [] inwav = padded_wav.cuda() - codes.append(model(inwav[:len(inwav)//2])[0].cpu()) - codes.append(model(inwav[len(inwav)//2:])[0].cpu()) + codes.append(model(inwav[: len(inwav) // 2])[0].cpu()) + codes.append(model(inwav[len(inwav) // 2 :])[0].cpu()) codes = torch.cat(codes, dim=0) else: - encoded_frames = model(padded_wav.cuda()) - codes = encoded_frames[0].cpu() # [B, n_codebook, T] + encoded_frames = model(padded_wav.cuda()) + codes = encoded_frames[0].cpu() # [B, n_codebook, T] for i, length in enumerate(all_lens): - save_fn = os.path.join(save_codes_dir, segment_id_batch[i]+".txt") - actual_len = round(length / args.downsample_rate) # 320 is downsample rate for this model - cur_code = codes[i].tolist() if type(codes) == list else codes[i, :, :actual_len].tolist() + save_fn = os.path.join( + save_codes_dir, segment_id_batch[i] + ".txt" + ) + actual_len = round( + length / args.downsample_rate + ) # 320 is downsample rate for this model + cur_code = ( + codes[i].tolist() + if type(codes) == list + else codes[i, :, :actual_len].tolist() + ) os.makedirs(os.path.dirname(save_fn), exist_ok=True) write_array_to_txt_file(cur_code, save_fn) - mani_wf.write(f"{segment_id_batch[i]}\t{len(cur_code[0])}\n") # write to manifest file + mani_wf.write( + f"{segment_id_batch[i]}\t{len(cur_code[0])}\n" + ) # write to manifest file # if i == 10: # raise except Exception as e: - print(f'exception!! at {m+1}') + print(f"exception!! at {m+1}") print(e) continue # break - logging.info(f"split {split} partition {args.partition} has {len(loader.dataset)} samples in total, skipped {skip} due to utterance being too long or too short") - # break + logging.info( + f"split {split} partition {args.partition} has {len(loader.dataset)} samples in total, skipped {skip} due to utterance being too long or too short" + ) + # break diff --git a/data/encodec.py b/data/encodec.py index be65978..fdb9267 100644 --- a/data/encodec.py +++ b/data/encodec.py @@ -25,10 +25,13 @@ import warnings from einops import rearrange, repeat import omegaconf + # import flashy -CONV_NORMALIZATIONS = frozenset(['none', 'weight_norm', 'spectral_norm', - 'time_group_norm']) +CONV_NORMALIZATIONS = frozenset( + ["none", "weight_norm", "spectral_norm", "time_group_norm"] +) + def dict_from_config(cfg: omegaconf.DictConfig) -> dict: """Convenience function to map an omegaconf configuration to a dictionary. @@ -42,6 +45,7 @@ def dict_from_config(cfg: omegaconf.DictConfig) -> dict: assert isinstance(dct, dict) return dct + @dataclass class QuantizedResult: x: torch.Tensor @@ -50,9 +54,9 @@ class QuantizedResult: penalty: tp.Optional[torch.Tensor] = None metrics: dict = field(default_factory=dict) + class BaseQuantizer(nn.Module): - """Base class for quantizers. - """ + """Base class for quantizers.""" def forward(self, x: torch.Tensor, frame_rate: int) -> QuantizedResult: """ @@ -85,17 +89,19 @@ def set_num_codebooks(self, n: int): """Set the number of active codebooks.""" raise NotImplementedError() + class CompressionModel(ABC, nn.Module): """Base API for all compression model that aim at being used as audio tokenizers with a language model. """ @abstractmethod - def forward(self, x: torch.Tensor) -> QuantizedResult: - ... + def forward(self, x: torch.Tensor) -> QuantizedResult: ... @abstractmethod - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """See `EncodecModel.encode`.""" ... @@ -111,44 +117,39 @@ def decode_latent(self, codes: torch.Tensor): @property @abstractmethod - def channels(self) -> int: - ... + def channels(self) -> int: ... @property @abstractmethod - def frame_rate(self) -> float: - ... + def frame_rate(self) -> float: ... @property @abstractmethod - def sample_rate(self) -> int: - ... + def sample_rate(self) -> int: ... @property @abstractmethod - def cardinality(self) -> int: - ... + def cardinality(self) -> int: ... @property @abstractmethod - def num_codebooks(self) -> int: - ... + def num_codebooks(self) -> int: ... @property @abstractmethod - def total_codebooks(self) -> int: - ... + def total_codebooks(self) -> int: ... @abstractmethod def set_num_codebooks(self, n: int): """Set the active number of codebooks used by the quantizer.""" ... -def apply_parametrization_norm(module: nn.Module, norm: str = 'none'): + +def apply_parametrization_norm(module: nn.Module, norm: str = "none"): assert norm in CONV_NORMALIZATIONS - if norm == 'weight_norm': + if norm == "weight_norm": return weight_norm(module) - elif norm == 'spectral_norm': + elif norm == "spectral_norm": return spectral_norm(module) else: # We already check was in CONV_NORMALIZATION, so any other choice @@ -156,12 +157,14 @@ def apply_parametrization_norm(module: nn.Module, norm: str = 'none'): return module -def get_norm_module(module: nn.Module, causal: bool = False, norm: str = 'none', **norm_kwargs): +def get_norm_module( + module: nn.Module, causal: bool = False, norm: str = "none", **norm_kwargs +): """Return the proper normalization module. If causal is True, this will ensure the returned module is causal, or return an error if the normalization doesn't support causal evaluation. """ assert norm in CONV_NORMALIZATIONS - if norm == 'time_group_norm': + if norm == "time_group_norm": if causal: raise ValueError("GroupNorm doesn't support causal evaluation.") assert isinstance(module, nn.modules.conv._ConvNd) @@ -170,8 +173,9 @@ def get_norm_module(module: nn.Module, causal: bool = False, norm: str = 'none', return nn.Identity() -def get_extra_padding_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, - padding_total: int = 0) -> int: +def get_extra_padding_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +) -> int: """See `pad_for_conv1d`.""" length = x.shape[-1] n_frames = (length - kernel_size + padding_total) / stride + 1 @@ -179,7 +183,9 @@ def get_extra_padding_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, return ideal_length - length -def pad_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0): +def pad_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +): """Pad for a convolution to make sure that the last window is full. Extra padding is added at the end. This is required to ensure that we can rebuild an output of the same length, as otherwise, even with padding, some time steps @@ -194,14 +200,19 @@ def pad_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, padding_total return F.pad(x, (0, extra_padding)) -def pad1d(x: torch.Tensor, paddings: tp.Tuple[int, int], mode: str = 'constant', value: float = 0.): +def pad1d( + x: torch.Tensor, + paddings: tp.Tuple[int, int], + mode: str = "constant", + value: float = 0.0, +): """Tiny wrapper around F.pad, just to allow for reflect padding on small input. If this is the case, we insert extra 0 padding to the right before the reflection happen. """ length = x.shape[-1] padding_left, padding_right = paddings assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) - if mode == 'reflect': + if mode == "reflect": max_pad = max(padding_left, padding_right) extra_pad = 0 if length <= max_pad: @@ -220,15 +231,22 @@ def unpad1d(x: torch.Tensor, paddings: tp.Tuple[int, int]): assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) assert (padding_left + padding_right) <= x.shape[-1] end = x.shape[-1] - padding_right - return x[..., padding_left: end] + return x[..., padding_left:end] class NormConv1d(nn.Module): """Wrapper around Conv1d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, causal: bool = False, norm: str = 'none', - norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() self.conv = apply_parametrization_norm(nn.Conv1d(*args, **kwargs), norm) self.norm = get_norm_module(self.conv, causal, norm, **norm_kwargs) @@ -244,7 +262,14 @@ class NormConv2d(nn.Module): """Wrapper around Conv2d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() self.conv = apply_parametrization_norm(nn.Conv2d(*args, **kwargs), norm) self.norm = get_norm_module(self.conv, causal=False, norm=norm, **norm_kwargs) @@ -260,10 +285,19 @@ class NormConvTranspose1d(nn.Module): """Wrapper around ConvTranspose1d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, causal: bool = False, norm: str = 'none', - norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() - self.convtr = apply_parametrization_norm(nn.ConvTranspose1d(*args, **kwargs), norm) + self.convtr = apply_parametrization_norm( + nn.ConvTranspose1d(*args, **kwargs), norm + ) self.norm = get_norm_module(self.convtr, causal, norm, **norm_kwargs) self.norm_type = norm @@ -277,9 +311,18 @@ class NormConvTranspose2d(nn.Module): """Wrapper around ConvTranspose2d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() - self.convtr = apply_parametrization_norm(nn.ConvTranspose2d(*args, **kwargs), norm) + self.convtr = apply_parametrization_norm( + nn.ConvTranspose2d(*args, **kwargs), norm + ) self.norm = get_norm_module(self.convtr, causal=False, norm=norm, **norm_kwargs) def forward(self, x): @@ -292,19 +335,40 @@ class StreamableConv1d(nn.Module): """Conv1d with some builtin handling of asymmetric or causal padding and normalization. """ - def __init__(self, in_channels: int, out_channels: int, - kernel_size: int, stride: int = 1, dilation: int = 1, - groups: int = 1, bias: bool = True, causal: bool = False, - norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, - pad_mode: str = 'reflect'): + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + dilation: int = 1, + groups: int = 1, + bias: bool = True, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + pad_mode: str = "reflect", + ): super().__init__() # warn user on unusual setup between dilation and stride if stride > 1 and dilation > 1: - warnings.warn("StreamableConv1d has been initialized with stride > 1 and dilation > 1" - f" (kernel_size={kernel_size} stride={stride}, dilation={dilation}).") - self.conv = NormConv1d(in_channels, out_channels, kernel_size, stride, - dilation=dilation, groups=groups, bias=bias, causal=causal, - norm=norm, norm_kwargs=norm_kwargs) + warnings.warn( + "StreamableConv1d has been initialized with stride > 1 and dilation > 1" + f" (kernel_size={kernel_size} stride={stride}, dilation={dilation})." + ) + self.conv = NormConv1d( + in_channels, + out_channels, + kernel_size, + stride, + dilation=dilation, + groups=groups, + bias=bias, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) self.causal = causal self.pad_mode = pad_mode @@ -313,9 +377,13 @@ def forward(self, x): kernel_size = self.conv.conv.kernel_size[0] stride = self.conv.conv.stride[0] dilation = self.conv.conv.dilation[0] - kernel_size = (kernel_size - 1) * dilation + 1 # effective kernel size with dilations + kernel_size = ( + kernel_size - 1 + ) * dilation + 1 # effective kernel size with dilations padding_total = kernel_size - stride - extra_padding = get_extra_padding_for_conv1d(x, kernel_size, stride, padding_total) + extra_padding = get_extra_padding_for_conv1d( + x, kernel_size, stride, padding_total + ) if self.causal: # Left padding for causal x = pad1d(x, (padding_total, extra_padding), mode=self.pad_mode) @@ -323,7 +391,9 @@ def forward(self, x): # Asymmetric padding required for odd strides padding_right = padding_total // 2 padding_left = padding_total - padding_right - x = pad1d(x, (padding_left, padding_right + extra_padding), mode=self.pad_mode) + x = pad1d( + x, (padding_left, padding_right + extra_padding), mode=self.pad_mode + ) return self.conv(x) @@ -331,18 +401,34 @@ class StreamableConvTranspose1d(nn.Module): """ConvTranspose1d with some builtin handling of asymmetric or causal padding and normalization. """ - def __init__(self, in_channels: int, out_channels: int, - kernel_size: int, stride: int = 1, causal: bool = False, - norm: str = 'none', trim_right_ratio: float = 1., - norm_kwargs: tp.Dict[str, tp.Any] = {}): + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + causal: bool = False, + norm: str = "none", + trim_right_ratio: float = 1.0, + norm_kwargs: tp.Dict[str, tp.Any] = {}, + ): super().__init__() - self.convtr = NormConvTranspose1d(in_channels, out_channels, kernel_size, stride, - causal=causal, norm=norm, norm_kwargs=norm_kwargs) + self.convtr = NormConvTranspose1d( + in_channels, + out_channels, + kernel_size, + stride, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) self.causal = causal self.trim_right_ratio = trim_right_ratio - assert self.causal or self.trim_right_ratio == 1., \ - "`trim_right_ratio` != 1.0 only makes sense for causal convolutions" - assert self.trim_right_ratio >= 0. and self.trim_right_ratio <= 1. + assert ( + self.causal or self.trim_right_ratio == 1.0 + ), "`trim_right_ratio` != 1.0 only makes sense for causal convolutions" + assert self.trim_right_ratio >= 0.0 and self.trim_right_ratio <= 1.0 def forward(self, x): kernel_size = self.convtr.convtr.kernel_size[0] @@ -373,6 +459,7 @@ class StreamableLSTM(nn.Module): """LSTM without worrying about the hidden state, nor the layout of the data. Expects input as convolutional layout. """ + def __init__(self, dimension: int, num_layers: int = 2, skip: bool = True): super().__init__() self.skip = skip @@ -404,12 +491,25 @@ class SEANetResnetBlock(nn.Module): true_skip (bool): Whether to use true skip connection or a simple (streamable) convolution as the skip connection. """ - def __init__(self, dim: int, kernel_sizes: tp.List[int] = [3, 1], dilations: tp.List[int] = [1, 1], - activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, causal: bool = False, - pad_mode: str = 'reflect', compress: int = 2, true_skip: bool = True): + + def __init__( + self, + dim: int, + kernel_sizes: tp.List[int] = [3, 1], + dilations: tp.List[int] = [1, 1], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + causal: bool = False, + pad_mode: str = "reflect", + compress: int = 2, + true_skip: bool = True, + ): super().__init__() - assert len(kernel_sizes) == len(dilations), 'Number of kernel sizes should match number of dilations' + assert len(kernel_sizes) == len( + dilations + ), "Number of kernel sizes should match number of dilations" act = getattr(nn, activation) hidden = dim // compress block = [] @@ -418,17 +518,31 @@ def __init__(self, dim: int, kernel_sizes: tp.List[int] = [3, 1], dilations: tp. out_chs = dim if i == len(kernel_sizes) - 1 else hidden block += [ act(**activation_params), - StreamableConv1d(in_chs, out_chs, kernel_size=kernel_size, dilation=dilation, - norm=norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode), + StreamableConv1d( + in_chs, + out_chs, + kernel_size=kernel_size, + dilation=dilation, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] self.block = nn.Sequential(*block) self.shortcut: nn.Module if true_skip: self.shortcut = nn.Identity() else: - self.shortcut = StreamableConv1d(dim, dim, kernel_size=1, norm=norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode) + self.shortcut = StreamableConv1d( + dim, + dim, + kernel_size=1, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) def forward(self, x): return self.shortcut(x) + self.block(x) @@ -462,12 +576,29 @@ class SEANetEncoder(nn.Module): disable_norm_outer_blocks (int): Number of blocks for which we don't apply norm. For the encoder, it corresponds to the N first blocks. """ - def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, n_residual_layers: int = 3, - ratios: tp.List[int] = [8, 5, 4, 2], activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, kernel_size: int = 7, - last_kernel_size: int = 7, residual_kernel_size: int = 3, dilation_base: int = 2, causal: bool = False, - pad_mode: str = 'reflect', true_skip: bool = True, compress: int = 2, lstm: int = 0, - disable_norm_outer_blocks: int = 0): + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + ): super().__init__() self.channels = channels self.dimension = dimension @@ -478,36 +609,61 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, self.hop_length = np.prod(self.ratios) self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks self.disable_norm_outer_blocks = disable_norm_outer_blocks - assert self.disable_norm_outer_blocks >= 0 and self.disable_norm_outer_blocks <= self.n_blocks, \ - "Number of blocks for which to disable norm is invalid." \ + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) act = getattr(nn, activation) mult = 1 model: tp.List[nn.Module] = [ - StreamableConv1d(channels, mult * n_filters, kernel_size, - norm='none' if self.disable_norm_outer_blocks >= 1 else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + channels, + mult * n_filters, + kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) ] # Downsample to raw audio scale for i, ratio in enumerate(self.ratios): - block_norm = 'none' if self.disable_norm_outer_blocks >= i + 2 else norm + block_norm = "none" if self.disable_norm_outer_blocks >= i + 2 else norm # Add residual layers for j in range(n_residual_layers): model += [ - SEANetResnetBlock(mult * n_filters, kernel_sizes=[residual_kernel_size, 1], - dilations=[dilation_base ** j, 1], - norm=block_norm, norm_params=norm_params, - activation=activation, activation_params=activation_params, - causal=causal, pad_mode=pad_mode, compress=compress, true_skip=true_skip)] + SEANetResnetBlock( + mult * n_filters, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + norm=block_norm, + norm_params=norm_params, + activation=activation, + activation_params=activation_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] # Add downsampling layers model += [ act(**activation_params), - StreamableConv1d(mult * n_filters, mult * n_filters * 2, - kernel_size=ratio * 2, stride=ratio, - norm=block_norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode), + StreamableConv1d( + mult * n_filters, + mult * n_filters * 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] mult *= 2 @@ -516,9 +672,17 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, model += [ act(**activation_params), - StreamableConv1d(mult * n_filters, dimension, last_kernel_size, - norm='none' if self.disable_norm_outer_blocks == self.n_blocks else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + mult * n_filters, + dimension, + last_kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] self.model = nn.Sequential(*model) @@ -557,13 +721,32 @@ class SEANetDecoder(nn.Module): trim_right_ratio (float): Ratio for trimming at the right of the transposed convolution under the causal setup. If equal to 1.0, it means that all the trimming is done at the right. """ - def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, n_residual_layers: int = 3, - ratios: tp.List[int] = [8, 5, 4, 2], activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - final_activation: tp.Optional[str] = None, final_activation_params: tp.Optional[dict] = None, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, kernel_size: int = 7, - last_kernel_size: int = 7, residual_kernel_size: int = 3, dilation_base: int = 2, causal: bool = False, - pad_mode: str = 'reflect', true_skip: bool = True, compress: int = 2, lstm: int = 0, - disable_norm_outer_blocks: int = 0, trim_right_ratio: float = 1.0): + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + final_activation: tp.Optional[str] = None, + final_activation_params: tp.Optional[dict] = None, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + trim_right_ratio: float = 1.0, + ): super().__init__() self.dimension = dimension self.channels = channels @@ -574,16 +757,28 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, self.hop_length = np.prod(self.ratios) self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks self.disable_norm_outer_blocks = disable_norm_outer_blocks - assert self.disable_norm_outer_blocks >= 0 and self.disable_norm_outer_blocks <= self.n_blocks, \ - "Number of blocks for which to disable norm is invalid." \ + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) act = getattr(nn, activation) mult = int(2 ** len(self.ratios)) model: tp.List[nn.Module] = [ - StreamableConv1d(dimension, mult * n_filters, kernel_size, - norm='none' if self.disable_norm_outer_blocks == self.n_blocks else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + dimension, + mult * n_filters, + kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) ] if lstm: @@ -591,40 +786,63 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, # Upsample to raw audio scale for i, ratio in enumerate(self.ratios): - block_norm = 'none' if self.disable_norm_outer_blocks >= self.n_blocks - (i + 1) else norm + block_norm = ( + "none" + if self.disable_norm_outer_blocks >= self.n_blocks - (i + 1) + else norm + ) # Add upsampling layers model += [ act(**activation_params), - StreamableConvTranspose1d(mult * n_filters, mult * n_filters // 2, - kernel_size=ratio * 2, stride=ratio, - norm=block_norm, norm_kwargs=norm_params, - causal=causal, trim_right_ratio=trim_right_ratio), + StreamableConvTranspose1d( + mult * n_filters, + mult * n_filters // 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + trim_right_ratio=trim_right_ratio, + ), ] # Add residual layers for j in range(n_residual_layers): model += [ - SEANetResnetBlock(mult * n_filters // 2, kernel_sizes=[residual_kernel_size, 1], - dilations=[dilation_base ** j, 1], - activation=activation, activation_params=activation_params, - norm=block_norm, norm_params=norm_params, causal=causal, - pad_mode=pad_mode, compress=compress, true_skip=true_skip)] + SEANetResnetBlock( + mult * n_filters // 2, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + activation=activation, + activation_params=activation_params, + norm=block_norm, + norm_params=norm_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] mult //= 2 # Add final layers model += [ act(**activation_params), - StreamableConv1d(n_filters, channels, last_kernel_size, - norm='none' if self.disable_norm_outer_blocks >= 1 else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + n_filters, + channels, + last_kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] # Add optional final activation to decoder (eg. tanh) if final_activation is not None: final_act = getattr(nn, final_activation) final_activation_params = final_activation_params or {} - model += [ - final_act(**final_activation_params) - ] + model += [final_act(**final_activation_params)] self.model = nn.Sequential(*model) def forward(self, z): @@ -675,10 +893,8 @@ def kmeans(samples, num_clusters: int, num_iters: int = 10): means = sample_vectors(samples, num_clusters) for _ in range(num_iters): - diffs = rearrange(samples, "n d -> n () d") - rearrange( - means, "c d -> () c d" - ) - dists = -(diffs ** 2).sum(dim=-1) + diffs = rearrange(samples, "n d -> n () d") - rearrange(means, "c d -> () c d") + dists = -(diffs**2).sum(dim=-1) buckets = dists.max(dim=-1).indices bins = torch.bincount(buckets, minlength=num_clusters) @@ -700,7 +916,7 @@ def orthogonal_loss_fn(t): normed_codes = l2norm(t) identity = torch.eye(n, device=t.device) cosine_sim = einsum("i d, j d -> i j", normed_codes, normed_codes) - return ((cosine_sim - identity) ** 2).sum() / (n ** 2) + return ((cosine_sim - identity) ** 2).sum() / (n**2) class EuclideanCodebook(nn.Module): @@ -719,6 +935,7 @@ class EuclideanCodebook(nn.Module): that have an exponential moving average cluster size less than the specified threshold with randomly selected vector from the current batch. """ + def __init__( self, dim: int, @@ -731,7 +948,9 @@ def __init__( ): super().__init__() self.decay = decay - init_fn: tp.Union[tp.Callable[..., torch.Tensor], tp.Any] = uniform_init if not kmeans_init else torch.zeros + init_fn: tp.Union[tp.Callable[..., torch.Tensor], tp.Any] = ( + uniform_init if not kmeans_init else torch.zeros + ) embed = init_fn(codebook_size, dim) self.codebook_size = codebook_size @@ -862,6 +1081,7 @@ class VectorQuantization(nn.Module): that have an exponential moving average cluster size less than the specified threshold with randomly selected vector from the current batch. """ + def __init__( self, dim: int, @@ -873,7 +1093,7 @@ def __init__( kmeans_iters: int = 10, threshold_ema_dead_code: int = 2, channels_last: bool = False, - commitment_weight: float = 1., + commitment_weight: float = 1.0, orthogonal_reg_weight: float = 0.0, orthogonal_reg_active_codes_only: bool = False, orthogonal_reg_max_codes: tp.Optional[int] = None, @@ -882,8 +1102,12 @@ def __init__( _codebook_dim: int = default(codebook_dim, dim) requires_projection = _codebook_dim != dim - self.project_in = (nn.Linear(dim, _codebook_dim) if requires_projection else nn.Identity()) - self.project_out = (nn.Linear(_codebook_dim, dim) if requires_projection else nn.Identity()) + self.project_in = ( + nn.Linear(dim, _codebook_dim) if requires_projection else nn.Identity() + ) + self.project_out = ( + nn.Linear(_codebook_dim, dim) if requires_projection else nn.Identity() + ) self.epsilon = epsilon self.commitment_weight = commitment_weight @@ -892,10 +1116,15 @@ def __init__( self.orthogonal_reg_active_codes_only = orthogonal_reg_active_codes_only self.orthogonal_reg_max_codes = orthogonal_reg_max_codes - self._codebook = EuclideanCodebook(dim=_codebook_dim, codebook_size=codebook_size, - kmeans_init=kmeans_init, kmeans_iters=kmeans_iters, - decay=decay, epsilon=epsilon, - threshold_ema_dead_code=threshold_ema_dead_code) + self._codebook = EuclideanCodebook( + dim=_codebook_dim, + codebook_size=codebook_size, + kmeans_init=kmeans_init, + kmeans_iters=kmeans_iters, + decay=decay, + epsilon=epsilon, + threshold_ema_dead_code=threshold_ema_dead_code, + ) self.codebook_size = codebook_size self.channels_last = channels_last @@ -956,8 +1185,13 @@ def forward(self, x): codebook = codebook[unique_code_ids] num_codes = codebook.shape[0] - if exists(self.orthogonal_reg_max_codes) and num_codes > self.orthogonal_reg_max_codes: - rand_ids = torch.randperm(num_codes, device=device)[:self.orthogonal_reg_max_codes] + if ( + exists(self.orthogonal_reg_max_codes) + and num_codes > self.orthogonal_reg_max_codes + ): + rand_ids = torch.randperm(num_codes, device=device)[ + : self.orthogonal_reg_max_codes + ] codebook = codebook[rand_ids] orthogonal_reg_loss = orthogonal_loss_fn(codebook) @@ -974,17 +1208,20 @@ class ResidualVectorQuantization(nn.Module): Follows Algorithm 1. in https://arxiv.org/pdf/2107.03312.pdf """ + def __init__(self, *, num_quantizers, **kwargs): super().__init__() - codebook_size = kwargs.pop('codebook_size', None) + codebook_size = kwargs.pop("codebook_size", None) if codebook_size is None: raise ValueError("codebook_size must be provided in kwargs") if type(codebook_size) != list: codebook_size = [codebook_size] * num_quantizers self.layers = nn.ModuleList( - [VectorQuantization(codebook_size=cur_codebook_size, **kwargs) for _,cur_codebook_size in zip(range(num_quantizers), codebook_size)] + [ + VectorQuantization(codebook_size=cur_codebook_size, **kwargs) + for _, cur_codebook_size in zip(range(num_quantizers), codebook_size) + ] ) - # self.layers = nn.ModuleList( # [VectorQuantization(**kwargs) for _ in range(num_quantizers)] @@ -1058,6 +1295,7 @@ class ResidualVectorQuantizer(BaseQuantizer): orthogonal_reg_max_codes (optional int): Maximum number of codes to consider. for orthogonal regularization. """ + def __init__( self, dimension: int = 256, @@ -1096,7 +1334,7 @@ def __init__( orthogonal_reg_weight=self.orthogonal_reg_weight, orthogonal_reg_active_codes_only=self.orthogonal_reg_active_codes_only, orthogonal_reg_max_codes=self.orthogonal_reg_max_codes, - channels_last=False + channels_last=False, ) def forward(self, x: torch.Tensor, frame_rate: int): @@ -1144,15 +1382,18 @@ def set_num_codebooks(self, n: int): assert n > 0 and n <= self.max_n_q self.n_q = n + class DummyQuantizer(BaseQuantizer): - """Fake quantizer that actually does not perform any quantization. - """ + """Fake quantizer that actually does not perform any quantization.""" + def __init__(self): super().__init__() def forward(self, x: torch.Tensor, frame_rate: int): q = x.unsqueeze(1) - return QuantizedResult(x, q, torch.tensor(q.numel() * 32 * frame_rate / 1000 / len(x)).to(x)) + return QuantizedResult( + x, q, torch.tensor(q.numel() * 32 * frame_rate / 1000 / len(x)).to(x) + ) def encode(self, x: torch.Tensor) -> torch.Tensor: """Encode a given input tensor with the specified sample rate at the given bandwidth. @@ -1180,7 +1421,9 @@ def num_codebooks(self): def set_num_codebooks(self, n: int): """Set the number of active codebooks.""" - raise AttributeError("Cannot override the number of codebooks for the dummy quantizer") + raise AttributeError( + "Cannot override the number of codebooks for the dummy quantizer" + ) class EncodecModel(CompressionModel): @@ -1196,21 +1439,24 @@ class EncodecModel(CompressionModel): causal (bool): Whether to use a causal version of the model. renormalize (bool): Whether to renormalize the audio before running the model. """ + # we need assignment to override the property in the abstract class, # I couldn't find a better way... frame_rate: float = 0 sample_rate: int = 0 channels: int = 0 - def __init__(self, - encoder: nn.Module, - decoder: nn.Module, - quantizer: BaseQuantizer, - frame_rate: int, - sample_rate: int, - channels: int, - causal: bool = False, - renormalize: bool = False): + def __init__( + self, + encoder: nn.Module, + decoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): super().__init__() self.encoder = encoder self.decoder = decoder @@ -1223,7 +1469,7 @@ def __init__(self, if self.causal: # we force disabling here to avoid handling linear overlap of segments # as supported in original EnCodec codebase. - assert not self.renormalize, 'Causal model does not support renormalize' + assert not self.renormalize, "Causal model does not support renormalize" @property def total_codebooks(self): @@ -1244,7 +1490,9 @@ def cardinality(self): """Cardinality of each codebook.""" return self.quantizer.bins - def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: scale: tp.Optional[torch.Tensor] if self.renormalize: mono = x.mean(dim=1, keepdim=True) @@ -1256,9 +1504,9 @@ def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torc scale = None return x, scale - def postprocess(self, - x: torch.Tensor, - scale: tp.Optional[torch.Tensor] = None) -> torch.Tensor: + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: if scale is not None: assert self.renormalize x = x * scale.view(-1, 1, 1) @@ -1285,7 +1533,9 @@ def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: return q_res - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """Encode the given input tensor to quantized representation along with scale parameter. Args: @@ -1323,6 +1573,7 @@ def decode_latent(self, codes: torch.Tensor): """Decode from the discrete codes to continuous latent space.""" return self.quantizer.decode(codes) + class EncodecModel_encode_only(CompressionModel): """Encodec model operating on the raw waveform. Encode only, so no decoder @@ -1335,20 +1586,23 @@ class EncodecModel_encode_only(CompressionModel): causal (bool): Whether to use a causal version of the model. renormalize (bool): Whether to renormalize the audio before running the model. """ + # we need assignment to override the property in the abstract class, # I couldn't find a better way... frame_rate: float = 0 sample_rate: int = 0 channels: int = 0 - def __init__(self, - encoder: nn.Module, - quantizer: BaseQuantizer, - frame_rate: int, - sample_rate: int, - channels: int, - causal: bool = False, - renormalize: bool = False): + def __init__( + self, + encoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): super().__init__() self.encoder = encoder self.quantizer = quantizer @@ -1360,7 +1614,7 @@ def __init__(self, if self.causal: # we force disabling here to avoid handling linear overlap of segments # as supported in original EnCodec codebase. - assert not self.renormalize, 'Causal model does not support renormalize' + assert not self.renormalize, "Causal model does not support renormalize" @property def total_codebooks(self): @@ -1381,7 +1635,9 @@ def cardinality(self): """Cardinality of each codebook.""" return self.quantizer.bins - def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: scale: tp.Optional[torch.Tensor] if self.renormalize: mono = x.mean(dim=1, keepdim=True) @@ -1393,9 +1649,9 @@ def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torc scale = None return x, scale - def postprocess(self, - x: torch.Tensor, - scale: tp.Optional[torch.Tensor] = None) -> torch.Tensor: + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: if scale is not None: assert self.renormalize x = x * scale.view(-1, 1, 1) @@ -1422,7 +1678,9 @@ def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: return q_res - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """Encode the given input tensor to quantized representation along with scale parameter. Args: @@ -1462,21 +1720,22 @@ def decode_latent(self, codes: torch.Tensor): raise NotImplementedError("Decode is not supported for encode only model") return self.quantizer.decode(codes) -def get_quantizer(quantizer: str, cfg: omegaconf.DictConfig, dimension: int) -> BaseQuantizer: - klass = { - 'no_quant': DummyQuantizer, - 'rvq': ResidualVectorQuantizer - }[quantizer] + +def get_quantizer( + quantizer: str, cfg: omegaconf.DictConfig, dimension: int +) -> BaseQuantizer: + klass = {"no_quant": DummyQuantizer, "rvq": ResidualVectorQuantizer}[quantizer] kwargs = dict_from_config(getattr(cfg, quantizer)) - if quantizer != 'no_quant': - kwargs['dimension'] = dimension + if quantizer != "no_quant": + kwargs["dimension"] = dimension return klass(**kwargs) + def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): - if encoder_name == 'seanet': - kwargs = dict_from_config(getattr(cfg, 'seanet')) - encoder_override_kwargs = kwargs.pop('encoder') - decoder_override_kwargs = kwargs.pop('decoder') + if encoder_name == "seanet": + kwargs = dict_from_config(getattr(cfg, "seanet")) + encoder_override_kwargs = kwargs.pop("encoder") + decoder_override_kwargs = kwargs.pop("decoder") encoder_kwargs = {**kwargs, **encoder_override_kwargs} decoder_kwargs = {**kwargs, **decoder_override_kwargs} encoder = SEANetEncoder(**encoder_kwargs) @@ -1489,56 +1748,85 @@ def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: """Instantiate a compression model.""" if device == None: - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - state = torch.load(ckpt_fn, map_location='cpu') - cfg = state['xp.cfg'] + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + state = torch.load(ckpt_fn, map_location="cpu", weights_only=False) # TODO: Convert to SafeTensors + cfg = state["xp.cfg"] cfg.device = str(device) - weights = state['best_state']['model'] - assert cfg.compression_model == 'encodec', "Only Encodec model is supported for now." + weights = state["best_state"]["model"] + assert ( + cfg.compression_model == "encodec" + ), "Only Encodec model is supported for now." if encode_only: all_keys = list(weights.keys()) for key in all_keys: - if key.startswith('decoder'): + if key.startswith("decoder"): del weights[key] - kwargs = dict_from_config(getattr(cfg, 'encodec')) - encoder_name = kwargs.pop('autoencoder') - quantizer_name = kwargs.pop('quantizer') + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") encoder, _ = get_encodec_autoencoder(encoder_name, cfg) quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) - frame_rate = kwargs['sample_rate'] // encoder.hop_length - renormalize = kwargs.pop('renormalize', False) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) # deprecated params - kwargs.pop('renorm', None) - compression_model = EncodecModel_encode_only(encoder, quantizer, - frame_rate=frame_rate, renormalize=renormalize, **kwargs).to(cfg.device) - assert compression_model.sample_rate == cfg.sample_rate, "Compression model sample rate should match" + kwargs.pop("renorm", None) + compression_model = EncodecModel_encode_only( + encoder, quantizer, frame_rate=frame_rate, renormalize=renormalize, **kwargs + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" compression_model.load_state_dict(weights) compression_model.eval() return compression_model else: - kwargs = dict_from_config(getattr(cfg, 'encodec')) - encoder_name = kwargs.pop('autoencoder') - quantizer_name = kwargs.pop('quantizer') + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") encoder, decoder = get_encodec_autoencoder(encoder_name, cfg) quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) - frame_rate = kwargs['sample_rate'] // encoder.hop_length - renormalize = kwargs.pop('renormalize', False) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) # deprecated params - kwargs.pop('renorm', None) - compression_model = EncodecModel(encoder, decoder, quantizer, - frame_rate=frame_rate, renormalize=renormalize, **kwargs).to(cfg.device) - assert compression_model.sample_rate == cfg.sample_rate, "Compression model sample rate should match" + kwargs.pop("renorm", None) + compression_model = EncodecModel( + encoder, + decoder, + quantizer, + frame_rate=frame_rate, + renormalize=renormalize, + **kwargs, + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" compression_model.load_state_dict(weights) compression_model.eval() return compression_model + if __name__ == "__main__": import torchaudio + ckpt_fn = "/home/pyp/BoostedVoiceEditor/pretrained/encodec_6f79c6a8.th" - audio_in_fns = ["/home/pyp/BoostedVoiceEditor/demo/pam.wav", "/home/pyp/BoostedVoiceEditor/demo/ray.wav", "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000.wav", "/home/pyp/BoostedVoiceEditor/demo/caribbean.wav", "/home/pyp/BoostedVoiceEditor/demo/bible.wav", "/home/pyp/BoostedVoiceEditor/demo/miley.wav"] - audio_out_fns = ["/home/pyp/BoostedVoiceEditor/demo/pam_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/ray_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/caribbean_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav"] - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + audio_in_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley.wav", + ] + audio_out_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", + ] + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") model = get_compression_model(ckpt_fn, device=device) for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): @@ -1551,4 +1839,4 @@ def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> Compressi audio_in = audio_in.to(torch.float32).to(device) codes = model.encode(audio_in)[0] audio_out = model.decode(codes)[0].cpu() - torchaudio.save(audio_out_fn, audio_out, model.sample_rate) \ No newline at end of file + torchaudio.save(audio_out_fn, audio_out, model.sample_rate) diff --git a/data/ll60k_preprocessing/encodec.py b/data/ll60k_preprocessing/encodec.py index be65978..074fd69 100644 --- a/data/ll60k_preprocessing/encodec.py +++ b/data/ll60k_preprocessing/encodec.py @@ -25,10 +25,13 @@ import warnings from einops import rearrange, repeat import omegaconf + # import flashy -CONV_NORMALIZATIONS = frozenset(['none', 'weight_norm', 'spectral_norm', - 'time_group_norm']) +CONV_NORMALIZATIONS = frozenset( + ["none", "weight_norm", "spectral_norm", "time_group_norm"] +) + def dict_from_config(cfg: omegaconf.DictConfig) -> dict: """Convenience function to map an omegaconf configuration to a dictionary. @@ -42,6 +45,7 @@ def dict_from_config(cfg: omegaconf.DictConfig) -> dict: assert isinstance(dct, dict) return dct + @dataclass class QuantizedResult: x: torch.Tensor @@ -50,9 +54,9 @@ class QuantizedResult: penalty: tp.Optional[torch.Tensor] = None metrics: dict = field(default_factory=dict) + class BaseQuantizer(nn.Module): - """Base class for quantizers. - """ + """Base class for quantizers.""" def forward(self, x: torch.Tensor, frame_rate: int) -> QuantizedResult: """ @@ -85,17 +89,19 @@ def set_num_codebooks(self, n: int): """Set the number of active codebooks.""" raise NotImplementedError() + class CompressionModel(ABC, nn.Module): """Base API for all compression model that aim at being used as audio tokenizers with a language model. """ @abstractmethod - def forward(self, x: torch.Tensor) -> QuantizedResult: - ... + def forward(self, x: torch.Tensor) -> QuantizedResult: ... @abstractmethod - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """See `EncodecModel.encode`.""" ... @@ -111,44 +117,39 @@ def decode_latent(self, codes: torch.Tensor): @property @abstractmethod - def channels(self) -> int: - ... + def channels(self) -> int: ... @property @abstractmethod - def frame_rate(self) -> float: - ... + def frame_rate(self) -> float: ... @property @abstractmethod - def sample_rate(self) -> int: - ... + def sample_rate(self) -> int: ... @property @abstractmethod - def cardinality(self) -> int: - ... + def cardinality(self) -> int: ... @property @abstractmethod - def num_codebooks(self) -> int: - ... + def num_codebooks(self) -> int: ... @property @abstractmethod - def total_codebooks(self) -> int: - ... + def total_codebooks(self) -> int: ... @abstractmethod def set_num_codebooks(self, n: int): """Set the active number of codebooks used by the quantizer.""" ... -def apply_parametrization_norm(module: nn.Module, norm: str = 'none'): + +def apply_parametrization_norm(module: nn.Module, norm: str = "none"): assert norm in CONV_NORMALIZATIONS - if norm == 'weight_norm': + if norm == "weight_norm": return weight_norm(module) - elif norm == 'spectral_norm': + elif norm == "spectral_norm": return spectral_norm(module) else: # We already check was in CONV_NORMALIZATION, so any other choice @@ -156,12 +157,14 @@ def apply_parametrization_norm(module: nn.Module, norm: str = 'none'): return module -def get_norm_module(module: nn.Module, causal: bool = False, norm: str = 'none', **norm_kwargs): +def get_norm_module( + module: nn.Module, causal: bool = False, norm: str = "none", **norm_kwargs +): """Return the proper normalization module. If causal is True, this will ensure the returned module is causal, or return an error if the normalization doesn't support causal evaluation. """ assert norm in CONV_NORMALIZATIONS - if norm == 'time_group_norm': + if norm == "time_group_norm": if causal: raise ValueError("GroupNorm doesn't support causal evaluation.") assert isinstance(module, nn.modules.conv._ConvNd) @@ -170,8 +173,9 @@ def get_norm_module(module: nn.Module, causal: bool = False, norm: str = 'none', return nn.Identity() -def get_extra_padding_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, - padding_total: int = 0) -> int: +def get_extra_padding_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +) -> int: """See `pad_for_conv1d`.""" length = x.shape[-1] n_frames = (length - kernel_size + padding_total) / stride + 1 @@ -179,7 +183,9 @@ def get_extra_padding_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, return ideal_length - length -def pad_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0): +def pad_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +): """Pad for a convolution to make sure that the last window is full. Extra padding is added at the end. This is required to ensure that we can rebuild an output of the same length, as otherwise, even with padding, some time steps @@ -194,14 +200,19 @@ def pad_for_conv1d(x: torch.Tensor, kernel_size: int, stride: int, padding_total return F.pad(x, (0, extra_padding)) -def pad1d(x: torch.Tensor, paddings: tp.Tuple[int, int], mode: str = 'constant', value: float = 0.): +def pad1d( + x: torch.Tensor, + paddings: tp.Tuple[int, int], + mode: str = "constant", + value: float = 0.0, +): """Tiny wrapper around F.pad, just to allow for reflect padding on small input. If this is the case, we insert extra 0 padding to the right before the reflection happen. """ length = x.shape[-1] padding_left, padding_right = paddings assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) - if mode == 'reflect': + if mode == "reflect": max_pad = max(padding_left, padding_right) extra_pad = 0 if length <= max_pad: @@ -220,15 +231,22 @@ def unpad1d(x: torch.Tensor, paddings: tp.Tuple[int, int]): assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) assert (padding_left + padding_right) <= x.shape[-1] end = x.shape[-1] - padding_right - return x[..., padding_left: end] + return x[..., padding_left:end] class NormConv1d(nn.Module): """Wrapper around Conv1d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, causal: bool = False, norm: str = 'none', - norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() self.conv = apply_parametrization_norm(nn.Conv1d(*args, **kwargs), norm) self.norm = get_norm_module(self.conv, causal, norm, **norm_kwargs) @@ -244,7 +262,14 @@ class NormConv2d(nn.Module): """Wrapper around Conv2d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() self.conv = apply_parametrization_norm(nn.Conv2d(*args, **kwargs), norm) self.norm = get_norm_module(self.conv, causal=False, norm=norm, **norm_kwargs) @@ -260,10 +285,19 @@ class NormConvTranspose1d(nn.Module): """Wrapper around ConvTranspose1d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, causal: bool = False, norm: str = 'none', - norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() - self.convtr = apply_parametrization_norm(nn.ConvTranspose1d(*args, **kwargs), norm) + self.convtr = apply_parametrization_norm( + nn.ConvTranspose1d(*args, **kwargs), norm + ) self.norm = get_norm_module(self.convtr, causal, norm, **norm_kwargs) self.norm_type = norm @@ -277,9 +311,18 @@ class NormConvTranspose2d(nn.Module): """Wrapper around ConvTranspose2d and normalization applied to this conv to provide a uniform interface across normalization approaches. """ - def __init__(self, *args, norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, **kwargs): + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): super().__init__() - self.convtr = apply_parametrization_norm(nn.ConvTranspose2d(*args, **kwargs), norm) + self.convtr = apply_parametrization_norm( + nn.ConvTranspose2d(*args, **kwargs), norm + ) self.norm = get_norm_module(self.convtr, causal=False, norm=norm, **norm_kwargs) def forward(self, x): @@ -292,19 +335,40 @@ class StreamableConv1d(nn.Module): """Conv1d with some builtin handling of asymmetric or causal padding and normalization. """ - def __init__(self, in_channels: int, out_channels: int, - kernel_size: int, stride: int = 1, dilation: int = 1, - groups: int = 1, bias: bool = True, causal: bool = False, - norm: str = 'none', norm_kwargs: tp.Dict[str, tp.Any] = {}, - pad_mode: str = 'reflect'): + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + dilation: int = 1, + groups: int = 1, + bias: bool = True, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + pad_mode: str = "reflect", + ): super().__init__() # warn user on unusual setup between dilation and stride if stride > 1 and dilation > 1: - warnings.warn("StreamableConv1d has been initialized with stride > 1 and dilation > 1" - f" (kernel_size={kernel_size} stride={stride}, dilation={dilation}).") - self.conv = NormConv1d(in_channels, out_channels, kernel_size, stride, - dilation=dilation, groups=groups, bias=bias, causal=causal, - norm=norm, norm_kwargs=norm_kwargs) + warnings.warn( + "StreamableConv1d has been initialized with stride > 1 and dilation > 1" + f" (kernel_size={kernel_size} stride={stride}, dilation={dilation})." + ) + self.conv = NormConv1d( + in_channels, + out_channels, + kernel_size, + stride, + dilation=dilation, + groups=groups, + bias=bias, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) self.causal = causal self.pad_mode = pad_mode @@ -313,9 +377,13 @@ def forward(self, x): kernel_size = self.conv.conv.kernel_size[0] stride = self.conv.conv.stride[0] dilation = self.conv.conv.dilation[0] - kernel_size = (kernel_size - 1) * dilation + 1 # effective kernel size with dilations + kernel_size = ( + kernel_size - 1 + ) * dilation + 1 # effective kernel size with dilations padding_total = kernel_size - stride - extra_padding = get_extra_padding_for_conv1d(x, kernel_size, stride, padding_total) + extra_padding = get_extra_padding_for_conv1d( + x, kernel_size, stride, padding_total + ) if self.causal: # Left padding for causal x = pad1d(x, (padding_total, extra_padding), mode=self.pad_mode) @@ -323,7 +391,9 @@ def forward(self, x): # Asymmetric padding required for odd strides padding_right = padding_total // 2 padding_left = padding_total - padding_right - x = pad1d(x, (padding_left, padding_right + extra_padding), mode=self.pad_mode) + x = pad1d( + x, (padding_left, padding_right + extra_padding), mode=self.pad_mode + ) return self.conv(x) @@ -331,18 +401,34 @@ class StreamableConvTranspose1d(nn.Module): """ConvTranspose1d with some builtin handling of asymmetric or causal padding and normalization. """ - def __init__(self, in_channels: int, out_channels: int, - kernel_size: int, stride: int = 1, causal: bool = False, - norm: str = 'none', trim_right_ratio: float = 1., - norm_kwargs: tp.Dict[str, tp.Any] = {}): + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + causal: bool = False, + norm: str = "none", + trim_right_ratio: float = 1.0, + norm_kwargs: tp.Dict[str, tp.Any] = {}, + ): super().__init__() - self.convtr = NormConvTranspose1d(in_channels, out_channels, kernel_size, stride, - causal=causal, norm=norm, norm_kwargs=norm_kwargs) + self.convtr = NormConvTranspose1d( + in_channels, + out_channels, + kernel_size, + stride, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) self.causal = causal self.trim_right_ratio = trim_right_ratio - assert self.causal or self.trim_right_ratio == 1., \ - "`trim_right_ratio` != 1.0 only makes sense for causal convolutions" - assert self.trim_right_ratio >= 0. and self.trim_right_ratio <= 1. + assert ( + self.causal or self.trim_right_ratio == 1.0 + ), "`trim_right_ratio` != 1.0 only makes sense for causal convolutions" + assert self.trim_right_ratio >= 0.0 and self.trim_right_ratio <= 1.0 def forward(self, x): kernel_size = self.convtr.convtr.kernel_size[0] @@ -373,6 +459,7 @@ class StreamableLSTM(nn.Module): """LSTM without worrying about the hidden state, nor the layout of the data. Expects input as convolutional layout. """ + def __init__(self, dimension: int, num_layers: int = 2, skip: bool = True): super().__init__() self.skip = skip @@ -404,12 +491,25 @@ class SEANetResnetBlock(nn.Module): true_skip (bool): Whether to use true skip connection or a simple (streamable) convolution as the skip connection. """ - def __init__(self, dim: int, kernel_sizes: tp.List[int] = [3, 1], dilations: tp.List[int] = [1, 1], - activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, causal: bool = False, - pad_mode: str = 'reflect', compress: int = 2, true_skip: bool = True): + + def __init__( + self, + dim: int, + kernel_sizes: tp.List[int] = [3, 1], + dilations: tp.List[int] = [1, 1], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + causal: bool = False, + pad_mode: str = "reflect", + compress: int = 2, + true_skip: bool = True, + ): super().__init__() - assert len(kernel_sizes) == len(dilations), 'Number of kernel sizes should match number of dilations' + assert len(kernel_sizes) == len( + dilations + ), "Number of kernel sizes should match number of dilations" act = getattr(nn, activation) hidden = dim // compress block = [] @@ -418,17 +518,31 @@ def __init__(self, dim: int, kernel_sizes: tp.List[int] = [3, 1], dilations: tp. out_chs = dim if i == len(kernel_sizes) - 1 else hidden block += [ act(**activation_params), - StreamableConv1d(in_chs, out_chs, kernel_size=kernel_size, dilation=dilation, - norm=norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode), + StreamableConv1d( + in_chs, + out_chs, + kernel_size=kernel_size, + dilation=dilation, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] self.block = nn.Sequential(*block) self.shortcut: nn.Module if true_skip: self.shortcut = nn.Identity() else: - self.shortcut = StreamableConv1d(dim, dim, kernel_size=1, norm=norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode) + self.shortcut = StreamableConv1d( + dim, + dim, + kernel_size=1, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) def forward(self, x): return self.shortcut(x) + self.block(x) @@ -462,12 +576,29 @@ class SEANetEncoder(nn.Module): disable_norm_outer_blocks (int): Number of blocks for which we don't apply norm. For the encoder, it corresponds to the N first blocks. """ - def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, n_residual_layers: int = 3, - ratios: tp.List[int] = [8, 5, 4, 2], activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, kernel_size: int = 7, - last_kernel_size: int = 7, residual_kernel_size: int = 3, dilation_base: int = 2, causal: bool = False, - pad_mode: str = 'reflect', true_skip: bool = True, compress: int = 2, lstm: int = 0, - disable_norm_outer_blocks: int = 0): + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + ): super().__init__() self.channels = channels self.dimension = dimension @@ -478,36 +609,61 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, self.hop_length = np.prod(self.ratios) self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks self.disable_norm_outer_blocks = disable_norm_outer_blocks - assert self.disable_norm_outer_blocks >= 0 and self.disable_norm_outer_blocks <= self.n_blocks, \ - "Number of blocks for which to disable norm is invalid." \ + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) act = getattr(nn, activation) mult = 1 model: tp.List[nn.Module] = [ - StreamableConv1d(channels, mult * n_filters, kernel_size, - norm='none' if self.disable_norm_outer_blocks >= 1 else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + channels, + mult * n_filters, + kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) ] # Downsample to raw audio scale for i, ratio in enumerate(self.ratios): - block_norm = 'none' if self.disable_norm_outer_blocks >= i + 2 else norm + block_norm = "none" if self.disable_norm_outer_blocks >= i + 2 else norm # Add residual layers for j in range(n_residual_layers): model += [ - SEANetResnetBlock(mult * n_filters, kernel_sizes=[residual_kernel_size, 1], - dilations=[dilation_base ** j, 1], - norm=block_norm, norm_params=norm_params, - activation=activation, activation_params=activation_params, - causal=causal, pad_mode=pad_mode, compress=compress, true_skip=true_skip)] + SEANetResnetBlock( + mult * n_filters, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + norm=block_norm, + norm_params=norm_params, + activation=activation, + activation_params=activation_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] # Add downsampling layers model += [ act(**activation_params), - StreamableConv1d(mult * n_filters, mult * n_filters * 2, - kernel_size=ratio * 2, stride=ratio, - norm=block_norm, norm_kwargs=norm_params, - causal=causal, pad_mode=pad_mode), + StreamableConv1d( + mult * n_filters, + mult * n_filters * 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] mult *= 2 @@ -516,9 +672,17 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, model += [ act(**activation_params), - StreamableConv1d(mult * n_filters, dimension, last_kernel_size, - norm='none' if self.disable_norm_outer_blocks == self.n_blocks else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + mult * n_filters, + dimension, + last_kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] self.model = nn.Sequential(*model) @@ -557,13 +721,32 @@ class SEANetDecoder(nn.Module): trim_right_ratio (float): Ratio for trimming at the right of the transposed convolution under the causal setup. If equal to 1.0, it means that all the trimming is done at the right. """ - def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, n_residual_layers: int = 3, - ratios: tp.List[int] = [8, 5, 4, 2], activation: str = 'ELU', activation_params: dict = {'alpha': 1.0}, - final_activation: tp.Optional[str] = None, final_activation_params: tp.Optional[dict] = None, - norm: str = 'none', norm_params: tp.Dict[str, tp.Any] = {}, kernel_size: int = 7, - last_kernel_size: int = 7, residual_kernel_size: int = 3, dilation_base: int = 2, causal: bool = False, - pad_mode: str = 'reflect', true_skip: bool = True, compress: int = 2, lstm: int = 0, - disable_norm_outer_blocks: int = 0, trim_right_ratio: float = 1.0): + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + final_activation: tp.Optional[str] = None, + final_activation_params: tp.Optional[dict] = None, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + trim_right_ratio: float = 1.0, + ): super().__init__() self.dimension = dimension self.channels = channels @@ -574,16 +757,28 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, self.hop_length = np.prod(self.ratios) self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks self.disable_norm_outer_blocks = disable_norm_outer_blocks - assert self.disable_norm_outer_blocks >= 0 and self.disable_norm_outer_blocks <= self.n_blocks, \ - "Number of blocks for which to disable norm is invalid." \ + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) act = getattr(nn, activation) mult = int(2 ** len(self.ratios)) model: tp.List[nn.Module] = [ - StreamableConv1d(dimension, mult * n_filters, kernel_size, - norm='none' if self.disable_norm_outer_blocks == self.n_blocks else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + dimension, + mult * n_filters, + kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) ] if lstm: @@ -591,40 +786,63 @@ def __init__(self, channels: int = 1, dimension: int = 128, n_filters: int = 32, # Upsample to raw audio scale for i, ratio in enumerate(self.ratios): - block_norm = 'none' if self.disable_norm_outer_blocks >= self.n_blocks - (i + 1) else norm + block_norm = ( + "none" + if self.disable_norm_outer_blocks >= self.n_blocks - (i + 1) + else norm + ) # Add upsampling layers model += [ act(**activation_params), - StreamableConvTranspose1d(mult * n_filters, mult * n_filters // 2, - kernel_size=ratio * 2, stride=ratio, - norm=block_norm, norm_kwargs=norm_params, - causal=causal, trim_right_ratio=trim_right_ratio), + StreamableConvTranspose1d( + mult * n_filters, + mult * n_filters // 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + trim_right_ratio=trim_right_ratio, + ), ] # Add residual layers for j in range(n_residual_layers): model += [ - SEANetResnetBlock(mult * n_filters // 2, kernel_sizes=[residual_kernel_size, 1], - dilations=[dilation_base ** j, 1], - activation=activation, activation_params=activation_params, - norm=block_norm, norm_params=norm_params, causal=causal, - pad_mode=pad_mode, compress=compress, true_skip=true_skip)] + SEANetResnetBlock( + mult * n_filters // 2, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + activation=activation, + activation_params=activation_params, + norm=block_norm, + norm_params=norm_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] mult //= 2 # Add final layers model += [ act(**activation_params), - StreamableConv1d(n_filters, channels, last_kernel_size, - norm='none' if self.disable_norm_outer_blocks >= 1 else norm, - norm_kwargs=norm_params, causal=causal, pad_mode=pad_mode) + StreamableConv1d( + n_filters, + channels, + last_kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), ] # Add optional final activation to decoder (eg. tanh) if final_activation is not None: final_act = getattr(nn, final_activation) final_activation_params = final_activation_params or {} - model += [ - final_act(**final_activation_params) - ] + model += [final_act(**final_activation_params)] self.model = nn.Sequential(*model) def forward(self, z): @@ -675,10 +893,8 @@ def kmeans(samples, num_clusters: int, num_iters: int = 10): means = sample_vectors(samples, num_clusters) for _ in range(num_iters): - diffs = rearrange(samples, "n d -> n () d") - rearrange( - means, "c d -> () c d" - ) - dists = -(diffs ** 2).sum(dim=-1) + diffs = rearrange(samples, "n d -> n () d") - rearrange(means, "c d -> () c d") + dists = -(diffs**2).sum(dim=-1) buckets = dists.max(dim=-1).indices bins = torch.bincount(buckets, minlength=num_clusters) @@ -700,7 +916,7 @@ def orthogonal_loss_fn(t): normed_codes = l2norm(t) identity = torch.eye(n, device=t.device) cosine_sim = einsum("i d, j d -> i j", normed_codes, normed_codes) - return ((cosine_sim - identity) ** 2).sum() / (n ** 2) + return ((cosine_sim - identity) ** 2).sum() / (n**2) class EuclideanCodebook(nn.Module): @@ -719,6 +935,7 @@ class EuclideanCodebook(nn.Module): that have an exponential moving average cluster size less than the specified threshold with randomly selected vector from the current batch. """ + def __init__( self, dim: int, @@ -731,7 +948,9 @@ def __init__( ): super().__init__() self.decay = decay - init_fn: tp.Union[tp.Callable[..., torch.Tensor], tp.Any] = uniform_init if not kmeans_init else torch.zeros + init_fn: tp.Union[tp.Callable[..., torch.Tensor], tp.Any] = ( + uniform_init if not kmeans_init else torch.zeros + ) embed = init_fn(codebook_size, dim) self.codebook_size = codebook_size @@ -862,6 +1081,7 @@ class VectorQuantization(nn.Module): that have an exponential moving average cluster size less than the specified threshold with randomly selected vector from the current batch. """ + def __init__( self, dim: int, @@ -873,7 +1093,7 @@ def __init__( kmeans_iters: int = 10, threshold_ema_dead_code: int = 2, channels_last: bool = False, - commitment_weight: float = 1., + commitment_weight: float = 1.0, orthogonal_reg_weight: float = 0.0, orthogonal_reg_active_codes_only: bool = False, orthogonal_reg_max_codes: tp.Optional[int] = None, @@ -882,8 +1102,12 @@ def __init__( _codebook_dim: int = default(codebook_dim, dim) requires_projection = _codebook_dim != dim - self.project_in = (nn.Linear(dim, _codebook_dim) if requires_projection else nn.Identity()) - self.project_out = (nn.Linear(_codebook_dim, dim) if requires_projection else nn.Identity()) + self.project_in = ( + nn.Linear(dim, _codebook_dim) if requires_projection else nn.Identity() + ) + self.project_out = ( + nn.Linear(_codebook_dim, dim) if requires_projection else nn.Identity() + ) self.epsilon = epsilon self.commitment_weight = commitment_weight @@ -892,10 +1116,15 @@ def __init__( self.orthogonal_reg_active_codes_only = orthogonal_reg_active_codes_only self.orthogonal_reg_max_codes = orthogonal_reg_max_codes - self._codebook = EuclideanCodebook(dim=_codebook_dim, codebook_size=codebook_size, - kmeans_init=kmeans_init, kmeans_iters=kmeans_iters, - decay=decay, epsilon=epsilon, - threshold_ema_dead_code=threshold_ema_dead_code) + self._codebook = EuclideanCodebook( + dim=_codebook_dim, + codebook_size=codebook_size, + kmeans_init=kmeans_init, + kmeans_iters=kmeans_iters, + decay=decay, + epsilon=epsilon, + threshold_ema_dead_code=threshold_ema_dead_code, + ) self.codebook_size = codebook_size self.channels_last = channels_last @@ -956,8 +1185,13 @@ def forward(self, x): codebook = codebook[unique_code_ids] num_codes = codebook.shape[0] - if exists(self.orthogonal_reg_max_codes) and num_codes > self.orthogonal_reg_max_codes: - rand_ids = torch.randperm(num_codes, device=device)[:self.orthogonal_reg_max_codes] + if ( + exists(self.orthogonal_reg_max_codes) + and num_codes > self.orthogonal_reg_max_codes + ): + rand_ids = torch.randperm(num_codes, device=device)[ + : self.orthogonal_reg_max_codes + ] codebook = codebook[rand_ids] orthogonal_reg_loss = orthogonal_loss_fn(codebook) @@ -974,17 +1208,20 @@ class ResidualVectorQuantization(nn.Module): Follows Algorithm 1. in https://arxiv.org/pdf/2107.03312.pdf """ + def __init__(self, *, num_quantizers, **kwargs): super().__init__() - codebook_size = kwargs.pop('codebook_size', None) + codebook_size = kwargs.pop("codebook_size", None) if codebook_size is None: raise ValueError("codebook_size must be provided in kwargs") if type(codebook_size) != list: codebook_size = [codebook_size] * num_quantizers self.layers = nn.ModuleList( - [VectorQuantization(codebook_size=cur_codebook_size, **kwargs) for _,cur_codebook_size in zip(range(num_quantizers), codebook_size)] + [ + VectorQuantization(codebook_size=cur_codebook_size, **kwargs) + for _, cur_codebook_size in zip(range(num_quantizers), codebook_size) + ] ) - # self.layers = nn.ModuleList( # [VectorQuantization(**kwargs) for _ in range(num_quantizers)] @@ -1058,6 +1295,7 @@ class ResidualVectorQuantizer(BaseQuantizer): orthogonal_reg_max_codes (optional int): Maximum number of codes to consider. for orthogonal regularization. """ + def __init__( self, dimension: int = 256, @@ -1096,7 +1334,7 @@ def __init__( orthogonal_reg_weight=self.orthogonal_reg_weight, orthogonal_reg_active_codes_only=self.orthogonal_reg_active_codes_only, orthogonal_reg_max_codes=self.orthogonal_reg_max_codes, - channels_last=False + channels_last=False, ) def forward(self, x: torch.Tensor, frame_rate: int): @@ -1144,15 +1382,18 @@ def set_num_codebooks(self, n: int): assert n > 0 and n <= self.max_n_q self.n_q = n + class DummyQuantizer(BaseQuantizer): - """Fake quantizer that actually does not perform any quantization. - """ + """Fake quantizer that actually does not perform any quantization.""" + def __init__(self): super().__init__() def forward(self, x: torch.Tensor, frame_rate: int): q = x.unsqueeze(1) - return QuantizedResult(x, q, torch.tensor(q.numel() * 32 * frame_rate / 1000 / len(x)).to(x)) + return QuantizedResult( + x, q, torch.tensor(q.numel() * 32 * frame_rate / 1000 / len(x)).to(x) + ) def encode(self, x: torch.Tensor) -> torch.Tensor: """Encode a given input tensor with the specified sample rate at the given bandwidth. @@ -1180,7 +1421,9 @@ def num_codebooks(self): def set_num_codebooks(self, n: int): """Set the number of active codebooks.""" - raise AttributeError("Cannot override the number of codebooks for the dummy quantizer") + raise AttributeError( + "Cannot override the number of codebooks for the dummy quantizer" + ) class EncodecModel(CompressionModel): @@ -1196,21 +1439,24 @@ class EncodecModel(CompressionModel): causal (bool): Whether to use a causal version of the model. renormalize (bool): Whether to renormalize the audio before running the model. """ + # we need assignment to override the property in the abstract class, # I couldn't find a better way... frame_rate: float = 0 sample_rate: int = 0 channels: int = 0 - def __init__(self, - encoder: nn.Module, - decoder: nn.Module, - quantizer: BaseQuantizer, - frame_rate: int, - sample_rate: int, - channels: int, - causal: bool = False, - renormalize: bool = False): + def __init__( + self, + encoder: nn.Module, + decoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): super().__init__() self.encoder = encoder self.decoder = decoder @@ -1223,7 +1469,7 @@ def __init__(self, if self.causal: # we force disabling here to avoid handling linear overlap of segments # as supported in original EnCodec codebase. - assert not self.renormalize, 'Causal model does not support renormalize' + assert not self.renormalize, "Causal model does not support renormalize" @property def total_codebooks(self): @@ -1244,7 +1490,9 @@ def cardinality(self): """Cardinality of each codebook.""" return self.quantizer.bins - def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: scale: tp.Optional[torch.Tensor] if self.renormalize: mono = x.mean(dim=1, keepdim=True) @@ -1256,9 +1504,9 @@ def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torc scale = None return x, scale - def postprocess(self, - x: torch.Tensor, - scale: tp.Optional[torch.Tensor] = None) -> torch.Tensor: + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: if scale is not None: assert self.renormalize x = x * scale.view(-1, 1, 1) @@ -1285,7 +1533,9 @@ def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: return q_res - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """Encode the given input tensor to quantized representation along with scale parameter. Args: @@ -1323,6 +1573,7 @@ def decode_latent(self, codes: torch.Tensor): """Decode from the discrete codes to continuous latent space.""" return self.quantizer.decode(codes) + class EncodecModel_encode_only(CompressionModel): """Encodec model operating on the raw waveform. Encode only, so no decoder @@ -1335,20 +1586,23 @@ class EncodecModel_encode_only(CompressionModel): causal (bool): Whether to use a causal version of the model. renormalize (bool): Whether to renormalize the audio before running the model. """ + # we need assignment to override the property in the abstract class, # I couldn't find a better way... frame_rate: float = 0 sample_rate: int = 0 channels: int = 0 - def __init__(self, - encoder: nn.Module, - quantizer: BaseQuantizer, - frame_rate: int, - sample_rate: int, - channels: int, - causal: bool = False, - renormalize: bool = False): + def __init__( + self, + encoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): super().__init__() self.encoder = encoder self.quantizer = quantizer @@ -1360,7 +1614,7 @@ def __init__(self, if self.causal: # we force disabling here to avoid handling linear overlap of segments # as supported in original EnCodec codebase. - assert not self.renormalize, 'Causal model does not support renormalize' + assert not self.renormalize, "Causal model does not support renormalize" @property def total_codebooks(self): @@ -1381,7 +1635,9 @@ def cardinality(self): """Cardinality of each codebook.""" return self.quantizer.bins - def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: scale: tp.Optional[torch.Tensor] if self.renormalize: mono = x.mean(dim=1, keepdim=True) @@ -1393,9 +1649,9 @@ def preprocess(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torc scale = None return x, scale - def postprocess(self, - x: torch.Tensor, - scale: tp.Optional[torch.Tensor] = None) -> torch.Tensor: + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: if scale is not None: assert self.renormalize x = x * scale.view(-1, 1, 1) @@ -1422,7 +1678,9 @@ def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: return q_res - def encode(self, x: torch.Tensor) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: """Encode the given input tensor to quantized representation along with scale parameter. Args: @@ -1462,21 +1720,22 @@ def decode_latent(self, codes: torch.Tensor): raise NotImplementedError("Decode is not supported for encode only model") return self.quantizer.decode(codes) -def get_quantizer(quantizer: str, cfg: omegaconf.DictConfig, dimension: int) -> BaseQuantizer: - klass = { - 'no_quant': DummyQuantizer, - 'rvq': ResidualVectorQuantizer - }[quantizer] + +def get_quantizer( + quantizer: str, cfg: omegaconf.DictConfig, dimension: int +) -> BaseQuantizer: + klass = {"no_quant": DummyQuantizer, "rvq": ResidualVectorQuantizer}[quantizer] kwargs = dict_from_config(getattr(cfg, quantizer)) - if quantizer != 'no_quant': - kwargs['dimension'] = dimension + if quantizer != "no_quant": + kwargs["dimension"] = dimension return klass(**kwargs) + def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): - if encoder_name == 'seanet': - kwargs = dict_from_config(getattr(cfg, 'seanet')) - encoder_override_kwargs = kwargs.pop('encoder') - decoder_override_kwargs = kwargs.pop('decoder') + if encoder_name == "seanet": + kwargs = dict_from_config(getattr(cfg, "seanet")) + encoder_override_kwargs = kwargs.pop("encoder") + decoder_override_kwargs = kwargs.pop("decoder") encoder_kwargs = {**kwargs, **encoder_override_kwargs} decoder_kwargs = {**kwargs, **decoder_override_kwargs} encoder = SEANetEncoder(**encoder_kwargs) @@ -1489,56 +1748,85 @@ def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: """Instantiate a compression model.""" if device == None: - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") - state = torch.load(ckpt_fn, map_location='cpu') - cfg = state['xp.cfg'] + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + state = torch.load(ckpt_fn, map_location="cpu") + cfg = state["xp.cfg"] cfg.device = str(device) - weights = state['best_state']['model'] - assert cfg.compression_model == 'encodec', "Only Encodec model is supported for now." + weights = state["best_state"]["model"] + assert ( + cfg.compression_model == "encodec" + ), "Only Encodec model is supported for now." if encode_only: all_keys = list(weights.keys()) for key in all_keys: - if key.startswith('decoder'): + if key.startswith("decoder"): del weights[key] - kwargs = dict_from_config(getattr(cfg, 'encodec')) - encoder_name = kwargs.pop('autoencoder') - quantizer_name = kwargs.pop('quantizer') + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") encoder, _ = get_encodec_autoencoder(encoder_name, cfg) quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) - frame_rate = kwargs['sample_rate'] // encoder.hop_length - renormalize = kwargs.pop('renormalize', False) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) # deprecated params - kwargs.pop('renorm', None) - compression_model = EncodecModel_encode_only(encoder, quantizer, - frame_rate=frame_rate, renormalize=renormalize, **kwargs).to(cfg.device) - assert compression_model.sample_rate == cfg.sample_rate, "Compression model sample rate should match" + kwargs.pop("renorm", None) + compression_model = EncodecModel_encode_only( + encoder, quantizer, frame_rate=frame_rate, renormalize=renormalize, **kwargs + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" compression_model.load_state_dict(weights) compression_model.eval() return compression_model else: - kwargs = dict_from_config(getattr(cfg, 'encodec')) - encoder_name = kwargs.pop('autoencoder') - quantizer_name = kwargs.pop('quantizer') + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") encoder, decoder = get_encodec_autoencoder(encoder_name, cfg) quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) - frame_rate = kwargs['sample_rate'] // encoder.hop_length - renormalize = kwargs.pop('renormalize', False) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) # deprecated params - kwargs.pop('renorm', None) - compression_model = EncodecModel(encoder, decoder, quantizer, - frame_rate=frame_rate, renormalize=renormalize, **kwargs).to(cfg.device) - assert compression_model.sample_rate == cfg.sample_rate, "Compression model sample rate should match" + kwargs.pop("renorm", None) + compression_model = EncodecModel( + encoder, + decoder, + quantizer, + frame_rate=frame_rate, + renormalize=renormalize, + **kwargs, + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" compression_model.load_state_dict(weights) compression_model.eval() return compression_model + if __name__ == "__main__": import torchaudio + ckpt_fn = "/home/pyp/BoostedVoiceEditor/pretrained/encodec_6f79c6a8.th" - audio_in_fns = ["/home/pyp/BoostedVoiceEditor/demo/pam.wav", "/home/pyp/BoostedVoiceEditor/demo/ray.wav", "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000.wav", "/home/pyp/BoostedVoiceEditor/demo/caribbean.wav", "/home/pyp/BoostedVoiceEditor/demo/bible.wav", "/home/pyp/BoostedVoiceEditor/demo/miley.wav"] - audio_out_fns = ["/home/pyp/BoostedVoiceEditor/demo/pam_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/ray_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/caribbean_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav"] - device = torch.device("cuda" if torch.cuda.is_available() else "cpu") + audio_in_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley.wav", + ] + audio_out_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", + ] + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") model = get_compression_model(ckpt_fn, device=device) for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): @@ -1551,4 +1839,4 @@ def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> Compressi audio_in = audio_in.to(torch.float32).to(device) codes = model.encode(audio_in)[0] audio_out = model.decode(codes)[0].cpu() - torchaudio.save(audio_out_fn, audio_out, model.sample_rate) \ No newline at end of file + torchaudio.save(audio_out_fn, audio_out, model.sample_rate) diff --git a/data/ll60k_preprocessing/step2_resplit_long.py b/data/ll60k_preprocessing/step2_resplit_long.py index a2a53d3..9f1150b 100644 --- a/data/ll60k_preprocessing/step2_resplit_long.py +++ b/data/ll60k_preprocessing/step2_resplit_long.py @@ -5,29 +5,44 @@ import os, random, numpy as np, socket import json import tqdm + + def write_jsonl(data, fn): with open(fn, "w") as file: for entry in data: file.write(json.dumps(entry, ensure_ascii=False) + "\n") + + def read_jsonl(file_path): cur_data = [] - with open(file_path, 'r', encoding='utf-8-sig') as file: + with open(file_path, "r", encoding="utf-8-sig") as file: for line in file: cur_data.append(json.loads(line.strip())) return cur_data + + import os -dataroot=os.environ["DATAROOT"] -manifestroot=os.path.join(dataroot, "libriheavy") -tgt_names = ['libriheavy_cuts_dev.jsonl', 'libriheavy_cuts_test_clean.jsonl', 'libriheavy_cuts_test_other.jsonl'] -orig_names = ['libriheavy_long_original_cuts_small.jsonl', 'libriheavy_long_original_cuts_medium.jsonl', 'libriheavy_long_original_cuts_large.jsonl'] + +dataroot = os.environ["DATAROOT"] +manifestroot = os.path.join(dataroot, "libriheavy") +tgt_names = [ + "libriheavy_cuts_dev.jsonl", + "libriheavy_cuts_test_clean.jsonl", + "libriheavy_cuts_test_other.jsonl", +] +orig_names = [ + "libriheavy_long_original_cuts_small.jsonl", + "libriheavy_long_original_cuts_medium.jsonl", + "libriheavy_long_original_cuts_large.jsonl", +] id2split = {} data = read_jsonl(os.path.join(manifestroot, "libriheavy_cuts_dev.jsonl")) -dev_ids = set(["/".join(item['id'].split("/")[:3]) for item in data]) +dev_ids = set(["/".join(item["id"].split("/")[:3]) for item in data]) data = read_jsonl(os.path.join(manifestroot, "libriheavy_cuts_test_clean.jsonl")) -test_clean_ids = set(["/".join(item['id'].split("/")[:3]) for item in data]) +test_clean_ids = set(["/".join(item["id"].split("/")[:3]) for item in data]) data = read_jsonl(os.path.join(manifestroot, "libriheavy_cuts_test_other.jsonl")) -test_other_ids = set(["/".join(item['id'].split("/")[:3]) for item in data]) +test_other_ids = set(["/".join(item["id"].split("/")[:3]) for item in data]) long_dev = [] long_test_clean = [] @@ -36,16 +51,20 @@ def read_jsonl(file_path): keep = [] data = read_jsonl(os.path.join(manifestroot, orig_name)) for item in tqdm.tqdm(data): - if "/".join(item['id'].split("/")[:3]) in dev_ids: + if "/".join(item["id"].split("/")[:3]) in dev_ids: long_dev.append(item) - elif "/".join(item['id'].split("/")[:3]) in test_clean_ids: + elif "/".join(item["id"].split("/")[:3]) in test_clean_ids: long_test_clean.append(item) - elif "/".join(item['id'].split("/")[:3]) in test_other_ids: + elif "/".join(item["id"].split("/")[:3]) in test_other_ids: long_test_other.append(item) else: keep.append(item) write_jsonl(keep, os.path.join(manifestroot, orig_name.replace("_original", ""))) write_jsonl(long_dev, os.path.join(manifestroot, "libriheavy_long_cuts_dev.jsonl")) -write_jsonl(long_test_clean, os.path.join(manifestroot, "libriheavy_long_cuts_test_clean.jsonl")) -write_jsonl(long_test_other, os.path.join(manifestroot, "libriheavy_long_cuts_test_other.jsonl")) \ No newline at end of file +write_jsonl( + long_test_clean, os.path.join(manifestroot, "libriheavy_long_cuts_test_clean.jsonl") +) +write_jsonl( + long_test_other, os.path.join(manifestroot, "libriheavy_long_cuts_test_other.jsonl") +) diff --git a/data/ll60k_preprocessing/step3_seg_phn_manifest.py b/data/ll60k_preprocessing/step3_seg_phn_manifest.py index 6743eef..e64fabf 100644 --- a/data/ll60k_preprocessing/step3_seg_phn_manifest.py +++ b/data/ll60k_preprocessing/step3_seg_phn_manifest.py @@ -15,33 +15,42 @@ import os, random, numpy as np, socket import json import tqdm + + def write_jsonl(data, fn): with open(fn, "w") as file: for entry in data: file.write(json.dumps(entry, ensure_ascii=False) + "\n") + + def read_jsonl(file_path): cur_data = [] - with open(file_path, 'r', encoding='utf-8-sig') as file: + with open(file_path, "r", encoding="utf-8-sig") as file: for line in file: cur_data.append(json.loads(line.strip())) return cur_data + + def save_audio(seq, fn): output = seq os.makedirs(os.path.dirname(fn), exist_ok=True) sf.write(fn, output, samplerate=16000) + def save_text(text, fn): os.makedirs(os.path.dirname(fn), exist_ok=True) with open(fn, "w") as wwf: wwf.writelines(text) + def phonemize_and_save(text, fn): phn = tokenize_text(text_tokenizer, text) os.makedirs(os.path.dirname(fn), exist_ok=True) with open(fn, "w") as f: - f.write(' '.join(phn)) + f.write(" ".join(phn)) return set(phn) + def cut_sequence(task): in_audio_fn, output_dir, metadata = task if not os.path.isfile(in_audio_fn): @@ -52,85 +61,103 @@ def cut_sequence(task): assert samplerate == 16000 all_phns = set() for item in metadata: - out_fn = item['file_id'] + out_fn = item["file_id"] out_audio_fn = os.path.join(output_dir, "audio", out_fn) out_text_fn = os.path.join(output_dir, "audio", out_fn.replace(".flac", ".txt")) - out_phn_fn = os.path.join(output_dir, "phoneme", out_fn.replace(".flac", ".txt")) - save_audio(data[int(item['vad'][0]*samplerate):int(item['vad'][1]*samplerate)], out_audio_fn) - save_text(item['text'], out_text_fn) - phns = phonemize_and_save(item['text'], out_phn_fn) + out_phn_fn = os.path.join( + output_dir, "phoneme", out_fn.replace(".flac", ".txt") + ) + save_audio( + data[int(item["vad"][0] * samplerate) : int(item["vad"][1] * samplerate)], + out_audio_fn, + ) + save_text(item["text"], out_text_fn) + phns = phonemize_and_save(item["text"], out_phn_fn) all_phns.update(phns) - + return all_phns from collections import defaultdict + + # Function to create a defaultdict recursively def nested_defaultdict(levels, inner_type): if levels <= 1: return defaultdict(inner_type) - return defaultdict(lambda: nested_defaultdict(levels-1, inner_type)) + return defaultdict(lambda: nested_defaultdict(levels - 1, inner_type)) def open_mani(fn): print("load segmentation and transcription metadata...") stime = time.time() data = [] - with gzip.open(fn, 'rt', encoding='utf-8') as f: + with gzip.open(fn, "rt", encoding="utf-8") as f: for line in f: data.append(json.loads(line)) print(f"loading done, took {time.time() - stime:.4f} seconds") return data -def cut(split, - audio_dir, - mani_dir, - output_dir, - n_process=32, - percent=0.5): + +def cut(split, audio_dir, mani_dir, output_dir, n_process=32, percent=0.5): split2manifest = { - "train": [ - "libriheavy_long_cuts_small.jsonl", - "libriheavy_long_cuts_medium.jsonl", - "libriheavy_long_cuts_large.jsonl", - "libriheavy_cuts_small.jsonl", - "libriheavy_cuts_medium.jsonl", - "libriheavy_cuts_large.jsonl", - ], - "valid": [ - "libriheavy_cuts_dev.jsonl", - "libriheavy_long_cuts_dev.jsonl" - ], - "test": [ - "libriheavy_cuts_test_clean.jsonl", - "libriheavy_cuts_test_other.jsonl", - "libriheavy_long_cuts_test_clean.jsonl", - "libriheavy_long_cuts_test_other.jsonl" - ] - } + "train": [ + "libriheavy_long_cuts_small.jsonl", + "libriheavy_long_cuts_medium.jsonl", + "libriheavy_long_cuts_large.jsonl", + "libriheavy_cuts_small.jsonl", + "libriheavy_cuts_medium.jsonl", + "libriheavy_cuts_large.jsonl", + ], + "valid": ["libriheavy_cuts_dev.jsonl", "libriheavy_long_cuts_dev.jsonl"], + "test": [ + "libriheavy_cuts_test_clean.jsonl", + "libriheavy_cuts_test_other.jsonl", + "libriheavy_long_cuts_test_clean.jsonl", + "libriheavy_long_cuts_test_other.jsonl", + ], + } print("organize data by recording_id (i.e. the original big .flac file name)...") stime = time.time() organized_data = nested_defaultdict(4, list) - manifest_fn = os.path.join(output_dir, "manifest_mimi", split+".txt") + manifest_fn = os.path.join(output_dir, "manifest_mimi", split + ".txt") os.makedirs(os.path.join(output_dir, "manifest_mimi"), exist_ok=True) with open(manifest_fn, "w") as wf: for mani_fn in split2manifest[split]: # data = open_mani(os.path.join(mani_dir, mani_fn)) data = read_jsonl(os.path.join(mani_dir, mani_fn)) for item in data: - file_id = item['supervisions'][0]['id'] + '.flac' - recording_id = item['recording']['id'] + '.flac' - sizeSplit, spk, book, flac = recording_id.split("/") # e.g. 'medium/100/emerald_city_librivox_64kb_mp3/emeraldcity_01_baum_64kb' + file_id = item["supervisions"][0]["id"] + ".flac" + recording_id = item["recording"]["id"] + ".flac" + sizeSplit, spk, book, flac = recording_id.split( + "/" + ) # e.g. 'medium/100/emerald_city_librivox_64kb_mp3/emeraldcity_01_baum_64kb' if os.path.isfile(os.path.join(audio_dir, recording_id)): - vad = (item['start'], item['start']+item['duration']) - text = item['supervisions'][0]['custom']['texts'][0] - file_id = file_id.replace(".flac", "") + f"_{vad[0]:.2f}_{vad[1]:.2f}.flac" - organized_data[sizeSplit][spk][book][recording_id].append({"file_id": file_id, "vad":vad, "text": text}) + vad = (item["start"], item["start"] + item["duration"]) + text = item["supervisions"][0]["custom"]["texts"][0] + file_id = ( + file_id.replace(".flac", "") + + f"_{vad[0]:.2f}_{vad[1]:.2f}.flac" + ) + organized_data[sizeSplit][spk][book][recording_id].append( + {"file_id": file_id, "vad": vad, "text": text} + ) wf.writelines(f"{file_id}\t{item['duration']}\n") - + # #### take only a subet of tasks - tasks = [(os.path.join(audio_dir, recording_id), output_dir, organized_data[sizeSplit][spk][book][recording_id], spk) for sizeSplit in organized_data for spk in organized_data[sizeSplit] for book in organized_data[sizeSplit][spk] for recording_id in organized_data[sizeSplit][spk][book]] + tasks = [ + ( + os.path.join(audio_dir, recording_id), + output_dir, + organized_data[sizeSplit][spk][book][recording_id], + spk, + ) + for sizeSplit in organized_data + for spk in organized_data[sizeSplit] + for book in organized_data[sizeSplit][spk] + for recording_id in organized_data[sizeSplit][spk][book] + ] ntasks = len(tasks) spk2tasks = defaultdict(list) for task in tasks: @@ -146,7 +173,9 @@ def cut(split, if len(spk2tasks[spk]) == 0: continue tasks.append(spk2tasks[spk].pop()[:-1]) - print(f"take only {percent*100:.2f}% of the tasks, {len(tasks)} out of {ntasks} tasks") + print( + f"take only {percent*100:.2f}% of the tasks, {len(tasks)} out of {ntasks} tasks" + ) #### take only a subet of tasks print(f"organizing done, took {time.time() - stime:.4f} seconds") @@ -154,7 +183,9 @@ def cut(split, phn_vocab = set() cnt = 0 with multiprocessing.Pool(processes=n_process) as pool: - for phns in tqdm.tqdm(pool.imap_unordered(cut_sequence, tasks), total=len(tasks)): + for phns in tqdm.tqdm( + pool.imap_unordered(cut_sequence, tasks), total=len(tasks) + ): cnt += 1 if phns != None: phn_vocab.update(phns) @@ -168,21 +199,46 @@ def cut(split, f.write(f"{str(i)}\t{phn}\n") else: f.write(f"{str(i)}\t{phn}") - -def parse_args(): - parser = argparse.ArgumentParser(description="Cut a dataset in small " - "sequences using VAD files") - parser.add_argument('--split', type=str, default='train', choices=['train', 'valid', 'test'], help="train = libriheavy_cuts_{small,medium,large}.jsonl.gz, valid = libriheavy_cuts_dev_{clean,other}.jsonl.gz, test = libriheavy_cuts_test_{clean,other}.jsonl.gz") - parser.add_argument('--audio_dir', type=str, default="/data/scratch/pyp/datasets/librilight_example", - help="Path to the audio directory") - parser.add_argument('--manifest_dir', type=str, default="/data/scratch/pyp/datasets/librilight/libriheavy", help="path to the transcription file's dir, can be downloaded https://huggingface.co/datasets/pkufool/libriheavy/tree/main/v0.1") - parser.add_argument('--output_dir', type=str, default="/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed", - help="Path to the output directory") - parser.add_argument('--n_workers', type=int, default=16, - help="Number of parallel worker processes") - parser.add_argument('--percent', type=float, default=0.5, help="take only this percent of the tasks, randomly sampled from each speaker") +def parse_args(): + parser = argparse.ArgumentParser( + description="Cut a dataset in small " "sequences using VAD files" + ) + parser.add_argument( + "--split", + type=str, + default="train", + choices=["train", "valid", "test"], + help="train = libriheavy_cuts_{small,medium,large}.jsonl.gz, valid = libriheavy_cuts_dev_{clean,other}.jsonl.gz, test = libriheavy_cuts_test_{clean,other}.jsonl.gz", + ) + parser.add_argument( + "--audio_dir", + type=str, + default="/data/scratch/pyp/datasets/librilight_example", + help="Path to the audio directory", + ) + parser.add_argument( + "--manifest_dir", + type=str, + default="/data/scratch/pyp/datasets/librilight/libriheavy", + help="path to the transcription file's dir, can be downloaded https://huggingface.co/datasets/pkufool/libriheavy/tree/main/v0.1", + ) + parser.add_argument( + "--output_dir", + type=str, + default="/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed", + help="Path to the output directory", + ) + parser.add_argument( + "--n_workers", type=int, default=16, help="Number of parallel worker processes" + ) + parser.add_argument( + "--percent", + type=float, + default=0.5, + help="take only this percent of the tasks, randomly sampled from each speaker", + ) return parser.parse_args() @@ -191,4 +247,11 @@ def parse_args(): args = parse_args() pathlib.Path(args.output_dir).mkdir(exist_ok=True, parents=True) text_tokenizer = TextTokenizer() - cut(args.split, args.audio_dir, args.manifest_dir, args.output_dir, args.n_workers, args.percent) \ No newline at end of file + cut( + args.split, + args.audio_dir, + args.manifest_dir, + args.output_dir, + args.n_workers, + args.percent, + ) diff --git a/data/ll60k_preprocessing/step4_encodec_encode.py b/data/ll60k_preprocessing/step4_encodec_encode.py index 7aaf62a..69d265a 100644 --- a/data/ll60k_preprocessing/step4_encodec_encode.py +++ b/data/ll60k_preprocessing/step4_encodec_encode.py @@ -1,27 +1,72 @@ import argparse from email.policy import default + + def parse_args(): - parser = argparse.ArgumentParser(description="encode the librilight dataset using codec model") - parser.add_argument('--dir', type=str, default="/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed", help="Path to the directory") - parser.add_argument('--sub_root', type=str, default="preprocessed", help="sub directory") - parser.add_argument('--encodec_name', type=str, default="encodec_6f79c6a8.th", help="name of the codec model") - parser.add_argument('--n_workers', type=int, default=16, help="Number of parallel worker processes") - parser.add_argument('--batch_size', type=int, default=16, help="batch size for codec encoding, decrease it if OOM. This is the sum of batch size *over each gpu*, so increase it if you are using more gpus") - parser.add_argument('--audio_sr', type=int, default=16000, help='input audio sample rate') - parser.add_argument('--model_sr', type=int, default=16000, help='encodec input audio sample rate') - parser.add_argument('--downsample_rate', type=int, default=320, help='encodec downsample rate') - parser.add_argument('--model_code_sr', type=float, default=50, help='codec model code sample rate') - parser.add_argument('--len_cap', type=float, default=1000, help='will drop audios that are longer than this number') - parser.add_argument('--min_len', type=float, default=0.5, help='will drop audios that are shorter than this number') - parser.add_argument('--partition', type=str, default="1/1", help='split for parallel processing') - parser.add_argument('--split', type=str, default='train', choices=['train', 'valid', 'test']) + parser = argparse.ArgumentParser( + description="encode the librilight dataset using codec model" + ) + parser.add_argument( + "--dir", + type=str, + default="/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed", + help="Path to the directory", + ) + parser.add_argument( + "--sub_root", type=str, default="preprocessed", help="sub directory" + ) + parser.add_argument( + "--encodec_name", + type=str, + default="encodec_6f79c6a8.th", + help="name of the codec model", + ) + parser.add_argument( + "--n_workers", type=int, default=16, help="Number of parallel worker processes" + ) + parser.add_argument( + "--batch_size", + type=int, + default=16, + help="batch size for codec encoding, decrease it if OOM. This is the sum of batch size *over each gpu*, so increase it if you are using more gpus", + ) + parser.add_argument( + "--audio_sr", type=int, default=16000, help="input audio sample rate" + ) + parser.add_argument( + "--model_sr", type=int, default=16000, help="encodec input audio sample rate" + ) + parser.add_argument( + "--downsample_rate", type=int, default=320, help="encodec downsample rate" + ) + parser.add_argument( + "--model_code_sr", type=float, default=50, help="codec model code sample rate" + ) + parser.add_argument( + "--len_cap", + type=float, + default=1000, + help="will drop audios that are longer than this number", + ) + parser.add_argument( + "--min_len", + type=float, + default=0.5, + help="will drop audios that are shorter than this number", + ) + parser.add_argument( + "--partition", type=str, default="1/1", help="split for parallel processing" + ) + parser.add_argument( + "--split", type=str, default="train", choices=["train", "valid", "test"] + ) return parser.parse_args() + if __name__ == "__main__": import logging - formatter = ( - "%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d || %(message)s" - ) + + formatter = "%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d || %(message)s" logging.basicConfig(format=formatter, level=logging.INFO) import os, sys @@ -37,31 +82,47 @@ def sort_by_audio_len(lens): inds = np.argsort(lens).tolist() if len(inds) < 10: return inds[::-1] - logging.info(f"longest: {lens[inds[-1]]/args.downsample_rate} encodec codes, {lens[inds[-1]]/args.model_sr:.2f} sec.") - logging.info(f"shortest: {lens[inds[0]]/args.downsample_rate} encodec codes, {lens[inds[0]]/args.model_sr:.2f} sec.") - logging.info(f"median: {lens[inds[len(inds)//2]]/args.downsample_rate} encodec codes, {lens[inds[len(inds)//2]]/args.model_sr:.2f} sec.") - logging.info(f"95 percentile longest: {lens[inds[int(len(inds)*0.95)]]/args.downsample_rate} encodec codes, {lens[inds[int(len(inds)*0.95)]]/args.model_sr:.2f} sec.") + logging.info( + f"longest: {lens[inds[-1]]/args.downsample_rate} encodec codes, {lens[inds[-1]]/args.model_sr:.2f} sec." + ) + logging.info( + f"shortest: {lens[inds[0]]/args.downsample_rate} encodec codes, {lens[inds[0]]/args.model_sr:.2f} sec." + ) + logging.info( + f"median: {lens[inds[len(inds)//2]]/args.downsample_rate} encodec codes, {lens[inds[len(inds)//2]]/args.model_sr:.2f} sec." + ) + logging.info( + f"95 percentile longest: {lens[inds[int(len(inds)*0.95)]]/args.downsample_rate} encodec codes, {lens[inds[int(len(inds)*0.95)]]/args.model_sr:.2f} sec." + ) return inds[::-1] def write_array_to_txt_file(array, filename): - with open(filename, 'w') as f: + with open(filename, "w") as f: for a in array[:-1]: - f.write(' '.join(map(str, a))+'\n') - f.write(' '.join(map(str, array[-1]))) + f.write(" ".join(map(str, a)) + "\n") + f.write(" ".join(map(str, array[-1]))) class mydataset(torch.utils.data.Dataset): def __init__(self, split): super().__init__() self.split = split self.audio_dir = audio_dir - manifest_fn = os.path.join(encodec_manifest_dir, split+".txt") - cur_sp = int(args.partition.split("/")[0])-1 + manifest_fn = os.path.join(encodec_manifest_dir, split + ".txt") + cur_sp = int(args.partition.split("/")[0]) - 1 total_sp = int(args.partition.split("/")[1]) with open(manifest_fn, "r") as rf: - self.data = [l.strip().split("\t") for l in rf.readlines()][cur_sp::total_sp] - self.data = [l for l in self.data if os.path.isfile(os.path.join(self.audio_dir, l[0]))] + self.data = [l.strip().split("\t") for l in rf.readlines()][ + cur_sp::total_sp + ] + self.data = [ + l + for l in self.data + if os.path.isfile(os.path.join(self.audio_dir, l[0])) + ] + def __len__(self): return len(self.data) + def __getitem__(self, ind): try: afn = self.data[ind][0] @@ -74,8 +135,13 @@ def __getitem__(self, ind): except Exception as e: # logging.info(f"{e}") return None, None, None - assert audio.ndim==2 and audio.shape[0] == 1, audio.shape - return audio.type(torch.float32).squeeze(0), audio.shape[-1], os.path.splitext(afn)[0] + assert audio.ndim == 2 and audio.shape[0] == 1, audio.shape + return ( + audio.type(torch.float32).squeeze(0), + audio.shape[-1], + os.path.splitext(afn)[0], + ) + def collate(self, batch): lens, audios, segment_ids = [], [], [] for item in batch: @@ -89,96 +155,138 @@ def collate(self, batch): sub_root = args.sub_root encodec_manifest_dir = os.path.join(args.dir, sub_root, "manifest_mimi") audio_dir = os.path.join(args.dir, sub_root, "audio") - save_manifest_dir = os.path.join(args.dir, sub_root,"manifest_final_encodec") + save_manifest_dir = os.path.join(args.dir, sub_root, "manifest_final_encodec") if args.encodec_name == "encodec_6f79c6a8.th": - save_codes_dir = os.path.join(args.dir, sub_root,"encodec_4cb") + save_codes_dir = os.path.join(args.dir, sub_root, "encodec_4cb") elif args.encodec_name == "encodec_8cb1024_giga.th": - save_codes_dir = os.path.join(args.dir, sub_root,"encodec_8cb") + save_codes_dir = os.path.join(args.dir, sub_root, "encodec_8cb") os.makedirs(save_manifest_dir, exist_ok=True) os.makedirs(save_codes_dir, exist_ok=True) - + # load the encodec model def import_encodec(): from encodec import get_compression_model + userdir = os.path.expanduser("~") - model = get_compression_model(os.path.join(userdir, "VoiceStar", f"pretrained/{args.encodec_name}"), encode_only=True, device="cuda") + model = get_compression_model( + os.path.join(userdir, "VoiceStar", f"pretrained/{args.encodec_name}"), + encode_only=True, + device="cuda", + ) model = torch.nn.DataParallel(model) return model + model = import_encodec() - + # setup dataloader mega_batch_size = 1024 batch_size = args.batch_size - + dataset = mydataset(args.split) if len(dataset) == 0: logging.info(f"no data found for split {args.split} partition {args.partition}") sys.exit(0) - loader = torch.torch.utils.data.DataLoader(dataset, batch_size=mega_batch_size, shuffle=False, drop_last=False, num_workers=args.n_workers, collate_fn=dataset.collate) + loader = torch.torch.utils.data.DataLoader( + dataset, + batch_size=mega_batch_size, + shuffle=False, + drop_last=False, + num_workers=args.n_workers, + collate_fn=dataset.collate, + ) split = args.split skip = 0 logging.info(f"now processing split {split} partition {args.partition}...") mega_n_steps = int(np.ceil(len(loader.dataset) / mega_batch_size)) # mega_n_steps = int(np.ceil(len(gs) / mega_batch_size)) - logging.info(f"partition the split {split} into {mega_n_steps} parts, each has at most {mega_batch_size} samples") - mani_fn = os.path.join(save_manifest_dir, f"{split}_{args.partition.replace('/', '=')}.txt") - logging.info(f"manifest for split {split} partition {args.partition.replace('/', '=')}.txt will be saved at {mani_fn}") + logging.info( + f"partition the split {split} into {mega_n_steps} parts, each has at most {mega_batch_size} samples" + ) + mani_fn = os.path.join( + save_manifest_dir, f"{split}_{args.partition.replace('/', '=')}.txt" + ) + logging.info( + f"manifest for split {split} partition {args.partition.replace('/', '=')}.txt will be saved at {mani_fn}" + ) with open(mani_fn, "w") as mani_wf: - # with open(mani_fn, "a") as mani_wf: # resume from where we failed + # with open(mani_fn, "a") as mani_wf: # resume from where we failed for m, mega_batch in enumerate(tqdm.tqdm(loader)): logging.info(f"====================================") logging.info(f"====================================") logging.info(f"now processing mega step {m+1}/{mega_n_steps}") try: - # if True: + # if True: lengths = np.array(mega_batch[1]) - if len(lengths) == 0: # the loader might not find any audio because step3 will write to manifest first, and then might selection a subset to cut and save audio + if ( + len(lengths) == 0 + ): # the loader might not find any audio because step3 will write to manifest first, and then might selection a subset to cut and save audio continue sorted_inds = sort_by_audio_len(lengths) for j in range(len(sorted_inds))[::-1]: - if lengths[sorted_inds[j]] < args.model_sr*args.min_len or lengths[sorted_inds[j]] > args.model_sr*args.len_cap: # skip samples that are too short (shorter than 0.2s), or too big (bigger than 80s) + if ( + lengths[sorted_inds[j]] < args.model_sr * args.min_len + or lengths[sorted_inds[j]] > args.model_sr * args.len_cap + ): # skip samples that are too short (shorter than 0.2s), or too big (bigger than 80s) skip += 1 del sorted_inds[j] - + n_steps = int(np.ceil(len(sorted_inds) / batch_size)) for n in tqdm.tqdm(range(n_steps), disable=True): - inds_used = sorted_inds[n*batch_size:(n+1)*batch_size] + inds_used = sorted_inds[n * batch_size : (n + 1) * batch_size] while len(inds_used) < batch_size: - inds_used += sorted_inds[:batch_size-len(inds_used)] + inds_used += sorted_inds[: batch_size - len(inds_used)] wav_batch = [mega_batch[0][id] for id in inds_used] all_lens = [mega_batch[1][id] for id in inds_used] segment_id_batch = [mega_batch[2][id] for id in inds_used] - padded_wav = torch.nn.utils.rnn.pad_sequence(wav_batch, batch_first=True).unsqueeze(1) # [B, T] -> [B, 1, T] + padded_wav = torch.nn.utils.rnn.pad_sequence( + wav_batch, batch_first=True + ).unsqueeze( + 1 + ) # [B, T] -> [B, 1, T] # Extract discrete codes from EnCodec with torch.no_grad(): - if max(all_lens) > 300000 and len(all_lens) > 1: # if utterances are long, simply pass half of them at a time + if ( + max(all_lens) > 300000 and len(all_lens) > 1 + ): # if utterances are long, simply pass half of them at a time codes = [] inwav = padded_wav.cuda() - codes.append(model(inwav[:len(inwav)//2])[0].cpu()) - codes.append(model(inwav[len(inwav)//2:])[0].cpu()) + codes.append(model(inwav[: len(inwav) // 2])[0].cpu()) + codes.append(model(inwav[len(inwav) // 2 :])[0].cpu()) codes = torch.cat(codes, dim=0) else: - encoded_frames = model(padded_wav.cuda()) - codes = encoded_frames[0].cpu() # [B, n_codebook, T] + encoded_frames = model(padded_wav.cuda()) + codes = encoded_frames[0].cpu() # [B, n_codebook, T] for i, length in enumerate(all_lens): - save_fn = os.path.join(save_codes_dir, segment_id_batch[i]+".txt") - actual_len = round(length / args.downsample_rate) # 320 is downsample rate for this model - cur_code = codes[i].tolist() if type(codes) == list else codes[i, :, :actual_len].tolist() + save_fn = os.path.join( + save_codes_dir, segment_id_batch[i] + ".txt" + ) + actual_len = round( + length / args.downsample_rate + ) # 320 is downsample rate for this model + cur_code = ( + codes[i].tolist() + if type(codes) == list + else codes[i, :, :actual_len].tolist() + ) os.makedirs(os.path.dirname(save_fn), exist_ok=True) write_array_to_txt_file(cur_code, save_fn) - mani_wf.write(f"{segment_id_batch[i]}\t{len(cur_code[0])}\n") # write to manifest file + mani_wf.write( + f"{segment_id_batch[i]}\t{len(cur_code[0])}\n" + ) # write to manifest file # if i == 10: # raise except Exception as e: - print(f'exception!! at {m+1}') + print(f"exception!! at {m+1}") print(e) continue # break - logging.info(f"split {split} partition {args.partition} has {len(loader.dataset)} samples in total, skipped {skip} due to utterance being too long or too short") - # break \ No newline at end of file + logging.info( + f"split {split} partition {args.partition} has {len(loader.dataset)} samples in total, skipped {skip} due to utterance being too long or too short" + ) + # break diff --git a/data/ll60k_preprocessing/step5_find_nearest_neighbor.py b/data/ll60k_preprocessing/step5_find_nearest_neighbor.py index 9118941..8cc195b 100644 --- a/data/ll60k_preprocessing/step5_find_nearest_neighbor.py +++ b/data/ll60k_preprocessing/step5_find_nearest_neighbor.py @@ -18,44 +18,50 @@ import tqdm import json import tqdm + + def write_jsonl(data, fn): with open(fn, "w") as file: for entry in data: file.write(json.dumps(entry, ensure_ascii=False) + "\n") + + def read_jsonl(file_path): cur_data = [] - with open(file_path, 'r', encoding='utf-8-sig') as file: + with open(file_path, "r", encoding="utf-8-sig") as file: for line in file: cur_data.append(json.loads(line.strip())) return cur_data + + from collections import defaultdict + + # Function to create a defaultdict recursively def nested_defaultdict(levels, inner_type): if levels <= 1: return defaultdict(inner_type) - return defaultdict(lambda: nested_defaultdict(levels-1, inner_type)) + return defaultdict(lambda: nested_defaultdict(levels - 1, inner_type)) + def find_neighbor(args): split2manifest = { - "train": [ - "libriheavy_cuts_small.jsonl", - "libriheavy_cuts_medium.jsonl", - "libriheavy_cuts_large.jsonl", - "libriheavy_long_cuts_small.jsonl", - "libriheavy_long_cuts_medium.jsonl", - "libriheavy_long_cuts_large.jsonl" - ], - "valid": [ - "libriheavy_cuts_dev.jsonl", - "libriheavy_long_cuts_dev.jsonl" - ], - "test": [ - "libriheavy_cuts_test_clean.jsonl", - "libriheavy_cuts_test_other.jsonl", - "libriheavy_long_cuts_test_clean.jsonl", - "libriheavy_long_cuts_test_other.jsonl" - ] - } + "train": [ + "libriheavy_cuts_small.jsonl", + "libriheavy_cuts_medium.jsonl", + "libriheavy_cuts_large.jsonl", + "libriheavy_long_cuts_small.jsonl", + "libriheavy_long_cuts_medium.jsonl", + "libriheavy_long_cuts_large.jsonl", + ], + "valid": ["libriheavy_cuts_dev.jsonl", "libriheavy_long_cuts_dev.jsonl"], + "test": [ + "libriheavy_cuts_test_clean.jsonl", + "libriheavy_cuts_test_other.jsonl", + "libriheavy_long_cuts_test_clean.jsonl", + "libriheavy_long_cuts_test_other.jsonl", + ], + } stime = time.time() organized_data = nested_defaultdict(4, list) @@ -64,15 +70,21 @@ def find_neighbor(args): mani_full_fn = os.path.join(args.manifest_dir, mani_fn) data = read_jsonl(mani_full_fn) for item in data: - file_id = item['supervisions'][0]['id'] + '.flac' - recording_id = item['recording']['id'] + '.flac' - sizeSplit, spk, book, flac = recording_id.split("/") # e.g. 'medium/100/emerald_city_librivox_64kb_mp3/emeraldcity_01_baum_64kb' + file_id = item["supervisions"][0]["id"] + ".flac" + recording_id = item["recording"]["id"] + ".flac" + sizeSplit, spk, book, flac = recording_id.split( + "/" + ) # e.g. 'medium/100/emerald_city_librivox_64kb_mp3/emeraldcity_01_baum_64kb' if os.path.isfile(os.path.join(args.audio_dir, recording_id)): - vad = (item['start'], item['start']+item['duration']) - text = item['supervisions'][0]['custom']['texts'][0] - file_id = file_id.replace(".flac", "") + f"_{vad[0]:.2f}_{vad[1]:.2f}.flac" - organized_data[sizeSplit][spk][book][recording_id].append({"file_id": file_id, "vad":vad, "text": text}) - + vad = (item["start"], item["start"] + item["duration"]) + text = item["supervisions"][0]["custom"]["texts"][0] + file_id = ( + file_id.replace(".flac", "") + f"_{vad[0]:.2f}_{vad[1]:.2f}.flac" + ) + organized_data[sizeSplit][spk][book][recording_id].append( + {"file_id": file_id, "vad": vad, "text": text} + ) + # # for each recording_id, find the non-overlapping neighboring segments based on vad # for sizeSplit in organized_data: # for spk in organized_data[sizeSplit]: @@ -98,33 +110,70 @@ def find_neighbor(args): # f.write(f"{neighbor}\t{dist}\n") # use multiprocessing.Pool for the above - segments = [organized_data[sizeSplit][spk][book][recording_id] for sizeSplit in organized_data for spk in organized_data[sizeSplit] for book in organized_data[sizeSplit][spk] for recording_id in organized_data[sizeSplit][spk][book]] + segments = [ + organized_data[sizeSplit][spk][book][recording_id] + for sizeSplit in organized_data + for spk in organized_data[sizeSplit] + for book in organized_data[sizeSplit][spk] + for recording_id in organized_data[sizeSplit][spk][book] + ] # only keep those that are exist print(f"originally total {len(segments)} segments") - segments = [seg for seg in segments if os.path.isfile(os.path.join("/".join(args.output_dir.split("/")[:-1]),"audio", seg[0]['file_id']))] + segments = [ + seg + for seg in segments + if os.path.isfile( + os.path.join( + "/".join(args.output_dir.split("/")[:-1]), "audio", seg[0]["file_id"] + ) + ) + ] print(f"after check existance, total {len(segments)} segments") print(f"organizing took {(time.time()-stime)/60:.2f} minutes") with multiprocessing.Pool(processes=args.n_workers) as pool: - for _ in tqdm.tqdm(pool.imap_unordered(find_neighbor_each, segments), total=len(segments)): + for _ in tqdm.tqdm( + pool.imap_unordered(find_neighbor_each, segments), total=len(segments) + ): pass + # audio_root = "/data/scratch/pyp/datasets/librilight/preprocessed/audio" def find_neighbor_each(segments): # for each recording_id, find the non-overlapping neighboring segments based on vad # only keep segments that have audio files # actually only keep segments that have ipa_alignment files - segments = [seg for seg in segments if os.path.isfile(os.path.join("/".join(args.output_dir.split("/")[:-1]),"ipa_alignment", seg['file_id'].replace(".flac", ".txt")))] + segments = [ + seg + for seg in segments + if os.path.isfile( + os.path.join( + "/".join(args.output_dir.split("/")[:-1]), + "ipa_alignment", + seg["file_id"].replace(".flac", ".txt"), + ) + ) + ] if len(segments) <= 1: return for i in range(len(segments)): # for segment i, find the non-overlapping neighboring segments - write_fn = os.path.join(args.output_dir, f"{segments[i]['file_id'].replace('.flac', '.txt')}") + write_fn = os.path.join( + args.output_dir, f"{segments[i]['file_id'].replace('.flac', '.txt')}" + ) neighbors = [] distance = [] for j in range(len(segments)): - if segments[i]['vad'][1] < segments[j]['vad'][0] or segments[i]['vad'][0] > segments[j]['vad'][0]: + if ( + segments[i]["vad"][1] < segments[j]["vad"][0] + or segments[i]["vad"][0] > segments[j]["vad"][0] + ): neighbors.append(segments[j]) - distance.append(min(abs(segments[i]['vad'][1] - segments[j]['vad'][0]), abs(segments[i]['vad'][0] - segments[j]['vad'][1]))) + distance.append( + min( + abs(segments[i]["vad"][1] - segments[j]["vad"][0]), + abs(segments[i]["vad"][0] - segments[j]["vad"][1]), + ) + ) if len(neighbors) == 0: continue # order neighbors by distance @@ -134,24 +183,47 @@ def find_neighbor_each(segments): with open(write_fn, "w") as f: # note that there might be no neighbors, in which case the file is empty for neighbor, dist in neighbors_distance: - f.write(f"{neighbor['file_id'].replace('.flac', '.txt')}\t{dist}\t{neighbor['vad'][1] - neighbor['vad'][0]}\n") # file_id, distance, duration - + f.write( + f"{neighbor['file_id'].replace('.flac', '.txt')}\t{dist}\t{neighbor['vad'][1] - neighbor['vad'][0]}\n" + ) # file_id, distance, duration def parse_args(): - parser = argparse.ArgumentParser(description="Cut a dataset in small " - "sequences using VAD files") - parser.add_argument('--split', type=str, default='train', choices=['train', 'valid', 'test'], help="train = libriheavy_cuts_{small,medium,large}.jsonl.gz, valid = libriheavy_cuts_dev_{clean,other}.jsonl.gz, test = libriheavy_cuts_test_{clean,other}.jsonl.gz") - parser.add_argument('--audio_dir', type=str, default="/data/scratch/pyp/datasets/librilight_example", - help="Path to the audio directory") - parser.add_argument('--manifest_dir', type=str, default="/data/scratch/pyp/datasets/librilight/libriheavy", help="path to the transcription file's dir, can be downloaded https://huggingface.co/datasets/pkufool/libriheavy/tree/main/v0.1") - parser.add_argument('--output_dir', type=str, default="/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed/neighbors", - help="Path to the output directory") - parser.add_argument('--n_workers', type=int, default=16, - help="Number of parallel worker processes") + parser = argparse.ArgumentParser( + description="Cut a dataset in small " "sequences using VAD files" + ) + parser.add_argument( + "--split", + type=str, + default="train", + choices=["train", "valid", "test"], + help="train = libriheavy_cuts_{small,medium,large}.jsonl.gz, valid = libriheavy_cuts_dev_{clean,other}.jsonl.gz, test = libriheavy_cuts_test_{clean,other}.jsonl.gz", + ) + parser.add_argument( + "--audio_dir", + type=str, + default="/data/scratch/pyp/datasets/librilight_example", + help="Path to the audio directory", + ) + parser.add_argument( + "--manifest_dir", + type=str, + default="/data/scratch/pyp/datasets/librilight/libriheavy", + help="path to the transcription file's dir, can be downloaded https://huggingface.co/datasets/pkufool/libriheavy/tree/main/v0.1", + ) + parser.add_argument( + "--output_dir", + type=str, + default="/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed/neighbors", + help="Path to the output directory", + ) + parser.add_argument( + "--n_workers", type=int, default=16, help="Number of parallel worker processes" + ) return parser.parse_args() + if __name__ == "__main__": args = parse_args() pathlib.Path(args.output_dir).mkdir(exist_ok=True, parents=True) - find_neighbor(args) \ No newline at end of file + find_neighbor(args) diff --git a/data/ll60k_preprocessing/step6_forced_alignment.py b/data/ll60k_preprocessing/step6_forced_alignment.py index 2606cac..31f700c 100644 --- a/data/ll60k_preprocessing/step6_forced_alignment.py +++ b/data/ll60k_preprocessing/step6_forced_alignment.py @@ -2,25 +2,46 @@ import subprocess, tqdm from concurrent.futures import ThreadPoolExecutor + def align_folders(audio_root, subfolder, subsubfolder): # Construct output folder path file_root = os.path.dirname(audio_root) out_folder = f"{file_root}/alignment/{subfolder}/{subsubfolder}" - + # Create the output directory os.makedirs(out_folder, exist_ok=True) - + # Construct the MFA align command command = [ - "mfa", "align", "--single_speaker", "-j", "8", "--clean", - f"{audio_root}/{subfolder}/{subsubfolder}", "english_us_arpa", "english_us_arpa", - out_folder, "--beam", "50", "--retry_beam", "400", "--output_format", "csv" + "mfa", + "align", + "--single_speaker", + "-j", + "8", + "--clean", + f"{audio_root}/{subfolder}/{subsubfolder}", + "english_us_arpa", + "english_us_arpa", + out_folder, + "--beam", + "50", + "--retry_beam", + "400", + "--output_format", + "csv", ] - + # Run the command subprocess.run(command, check=True) -def main(file_root = "/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed", max_parallel_jobs=10, max_spk=100, partition="1/10", n_workers=64): + +def main( + file_root="/data/scratch/pyp/datasets/librilight/librilight_example_preprocessed", + max_parallel_jobs=10, + max_spk=100, + partition="1/10", + n_workers=64, +): # Find all subfolder/subsubfolder combinations tasks = [] audio_root = os.path.join(file_root, "audio") @@ -34,18 +55,28 @@ def main(file_root = "/data/scratch/pyp/datasets/librilight/librilight_example_p speaker_folder_map = {} for audio_root, subfolder, subsubfolder in tasks: if os.path.join(audio_root, subfolder) not in speaker_folder_map: - speaker_folder_map[os.path.join(audio_root, subfolder)] = [os.path.join(audio_root, subfolder, subsubfolder)] + speaker_folder_map[os.path.join(audio_root, subfolder)] = [ + os.path.join(audio_root, subfolder, subsubfolder) + ] else: - speaker_folder_map[os.path.join(audio_root, subfolder)].append(os.path.join(audio_root, subfolder, subsubfolder)) + speaker_folder_map[os.path.join(audio_root, subfolder)].append( + os.path.join(audio_root, subfolder, subsubfolder) + ) speaker_folder_partitions = [] for audio_root_subfolder, speaker_folders in speaker_folder_map.items(): - speaker_folder_partitions.extend([speaker_folders[i:i+max_spk] for i in range(0, len(speaker_folders), max_spk)]) + speaker_folder_partitions.extend( + [ + speaker_folders[i : i + max_spk] + for i in range(0, len(speaker_folders), max_spk) + ] + ) s, e = partition.split("/") - s, e = int(s)-1, int(e) + s, e = int(s) - 1, int(e) cur_tasks = speaker_folder_partitions[s::e] import secrets, string import soundfile, glob from joblib import Parallel, delayed + def delete_corrupted(fn): try: x = soundfile.read(fn) @@ -59,19 +90,29 @@ def delete_corrupted(fn): # assert that all subs are the same assert len(set(subs)) == 1, subs sub = subs[0] - # randomly generate a foldername + # randomly generate a foldername # generate a random character # make softlink from item in task to temp folder - random_string = ''.join(secrets.choice(string.ascii_letters + string.digits) for i in range(10)) + random_string = "".join( + secrets.choice(string.ascii_letters + string.digits) for i in range(10) + ) temp_folder = os.path.join(file_root, "softlink_audio", random_string) os.makedirs(temp_folder, exist_ok=True) out_folder = f"{file_root}/alignment/{sub}" - all_out_speaker_folders = [os.path.join(out_folder, os.path.basename(item)) for item in task] - if sum(os.path.isdir(curpath) for curpath in all_out_speaker_folders) == len(all_out_speaker_folders): + all_out_speaker_folders = [ + os.path.join(out_folder, os.path.basename(item)) for item in task + ] + if sum(os.path.isdir(curpath) for curpath in all_out_speaker_folders) == len( + all_out_speaker_folders + ): continue # remove audio files that are corrupted - all_audio_files = [audiofile for item in task for audiofile in glob.glob(item+"/*/*.flac")] - Parallel(n_jobs=n_workers)(delayed(delete_corrupted)(audiofn) for audiofn in all_audio_files) + all_audio_files = [ + audiofile for item in task for audiofile in glob.glob(item + "/*/*.flac") + ] + Parallel(n_jobs=n_workers)( + delayed(delete_corrupted)(audiofn) for audiofn in all_audio_files + ) for item in task: # make softlink from subsubfolder to a new folder in temp folder os.symlink(item, os.path.join(temp_folder, os.path.basename(item))) @@ -81,6 +122,8 @@ def delete_corrupted(fn): # delete the temp_folder os.system(f"rm -r {temp_folder}") + if __name__ == "__main__": import fire - fire.Fire(main) \ No newline at end of file + + fire.Fire(main) diff --git a/data/ll60k_preprocessing/step7_ipa_alignment.py b/data/ll60k_preprocessing/step7_ipa_alignment.py index 137c530..0dec3f5 100644 --- a/data/ll60k_preprocessing/step7_ipa_alignment.py +++ b/data/ll60k_preprocessing/step7_ipa_alignment.py @@ -1,6 +1,6 @@ -# we have raw transcript at +# we have raw transcript at # /data/scratch/pyp/datasets/librilight/preprocessed/audio -# we have word and ARPA alignment at +# we have word and ARPA alignment at # /data/scratch/pyp/datasets/librilight/preprocessed/alignment # we have manifest at /data/scratch/pyp/datasets/librilight/preprocessed/manifest_mimi @@ -15,12 +15,23 @@ def remove_punctuation(input_string): - translator = str.maketrans('', '', string.punctuation) + translator = str.maketrans("", "", string.punctuation) return input_string.translate(translator) - -def create_alignment(fn, trans_dir, align_dir, audio_ext, trans_ext, arpa_ext, text_tokenizer, use_prob, ipa_alignment_fn, save=False, prompt_dur=30): +def create_alignment( + fn, + trans_dir, + align_dir, + audio_ext, + trans_ext, + arpa_ext, + text_tokenizer, + use_prob, + ipa_alignment_fn, + save=False, + prompt_dur=30, +): os.makedirs(os.path.dirname(ipa_alignment_fn), exist_ok=True) trans_fn = os.path.join(trans_dir, fn.replace(audio_ext, trans_ext)) if not os.path.isfile(trans_fn): @@ -29,13 +40,13 @@ def create_alignment(fn, trans_dir, align_dir, audio_ext, trans_ext, arpa_ext, t if not os.path.isfile(align_fn): return [], True # get raw transcript - with open(trans_fn, 'r') as f: + with open(trans_fn, "r") as f: transcript = f.read().strip() raw_word_list = transcript.split(" ") # get word alignment - with open(align_fn, 'r') as f: + with open(align_fn, "r") as f: word_alignment = csv.reader(f) - word_alignment = [row for row in word_alignment if row[3]=='words'] + word_alignment = [row for row in word_alignment if row[3] == "words"] ipa_alignment = [] @@ -48,67 +59,83 @@ def create_alignment(fn, trans_dir, align_dir, audio_ext, trans_ext, arpa_ext, t # print(f"word from alignment csv: {word}, word from txt: {raw_word}") return ipa_alignment, True if random.random() < use_prob: - cur_words = " ".join(raw_word_list[:j+1]) + cur_words = " ".join(raw_word_list[: j + 1]) phn = tokenize_text(text_tokenizer, cur_words) if len(phn) == 0: continue phn = " ".join(phn) - start = 0 # at this point, we always start from the beginning of the sentence + start = ( + 0 # at this point, we always start from the beginning of the sentence + ) ipa_alignment.append([start, end, phn]) if save: if ipa_alignment: - with open(ipa_alignment_fn, 'w') as f: + with open(ipa_alignment_fn, "w") as f: for item in ipa_alignment: f.write(f"{item[0]}\t{item[1]}\t{item[2]}\n") else: return ipa_alignment, False - def main( - data_root: str = '/data/scratch/pyp/datasets/librilight/preprocessed', - audio_ext: str = '.flac', - arpa_ext: str = '.csv', - trans_ext: str = '.txt', - split: str = 'valid', + data_root: str = "/data/scratch/pyp/datasets/librilight/preprocessed", + audio_ext: str = ".flac", + arpa_ext: str = ".csv", + trans_ext: str = ".txt", + split: str = "valid", use_prob: float = 0.5, - max_dur: float = 30., # do not consider utterance longer than this - prompt_dur: float = 30., # do not consider prompt longer than this + max_dur: float = 30.0, # do not consider utterance longer than this + prompt_dur: float = 30.0, # do not consider prompt longer than this ): text_tokenizer = TextTokenizer() - trans_dir = f'{data_root}/audio' - align_dir = f'{data_root}/alignment' + trans_dir = f"{data_root}/audio" + align_dir = f"{data_root}/alignment" manifest_fn = f"{data_root}/manifest_final_encodec/{split}*=*.txt" manifest_fns = glob.glob(manifest_fn) - target_dir = f'{data_root}/ipa_alignment' + target_dir = f"{data_root}/ipa_alignment" encodec_sr = 50 os.makedirs(target_dir, exist_ok=True) manifest = [] for manifest_fn in manifest_fns: - with open(manifest_fn, 'r') as f: + with open(manifest_fn, "r") as f: temp = [l.strip().split("\t") for l in f.readlines()] - manifest += [l[0] + audio_ext for l in temp if float(l[1])/encodec_sr < max_dur] + manifest += [ + l[0] + audio_ext for l in temp if float(l[1]) / encodec_sr < max_dur + ] # # sequential processing n_flags = 0 zero_words = 0 for j, fn in enumerate(tqdm.tqdm(manifest)): - ipa_alignment_fn = os.path.join(target_dir, fn.replace(audio_ext, '.txt')) - ipa_alignment, flag = create_alignment(fn, trans_dir, align_dir, audio_ext, trans_ext, arpa_ext, text_tokenizer, use_prob, ipa_alignment_fn, prompt_dur=prompt_dur) + ipa_alignment_fn = os.path.join(target_dir, fn.replace(audio_ext, ".txt")) + ipa_alignment, flag = create_alignment( + fn, + trans_dir, + align_dir, + audio_ext, + trans_ext, + arpa_ext, + text_tokenizer, + use_prob, + ipa_alignment_fn, + prompt_dur=prompt_dur, + ) n_flags += flag if not ipa_alignment: zero_words += 1 # print(f"{n_flags} out of {j+1} utterances have mismatched words") # print(f"{zero_words} out of {j+1} utterances have zero words") if ipa_alignment: - with open(ipa_alignment_fn, 'w') as f: + with open(ipa_alignment_fn, "w") as f: for item in ipa_alignment: f.write(f"{item[0]}\t{item[1]}\t{item[2]}\n") - + # # # # do the above using joblib parallisim # print(f"Processing {len(manifest)} utterances") # from joblib import Parallel, delayed # Parallel(n_jobs=32, verbose=2)(delayed(create_alignment)(fn, trans_dir, align_dir, audio_ext, trans_ext, arpa_ext, text_tokenizer, use_prob, os.path.join(target_dir, fn.replace(audio_ext, '.txt')), save=True) for fn in manifest) - + + if __name__ == "__main__": import fire - fire.Fire(main) \ No newline at end of file + + fire.Fire(main) diff --git a/data/ll60k_preprocessing/tokenizer.py b/data/ll60k_preprocessing/tokenizer.py index ad9f114..cd39c6d 100644 --- a/data/ll60k_preprocessing/tokenizer.py +++ b/data/ll60k_preprocessing/tokenizer.py @@ -20,6 +20,7 @@ import numpy as np import torch import torchaudio + # from encodec import EncodecModel # from encodec.utils import convert_audio # from lhotse.features import FeatureExtractor @@ -62,9 +63,7 @@ def phonemize( phones = [] if self.backend == "pypinyin": for n, py in enumerate( - pinyin( - _text, style=Style.TONE3, neutral_tone_with_five=True - ) + pinyin(_text, style=Style.TONE3, neutral_tone_with_five=True) ): if all([c in self.punctuation_marks for c in py[0]]): if len(phones): @@ -76,9 +75,7 @@ def phonemize( phones.extend([py[0], separator.syllable]) elif self.backend == "pypinyin_initials_finals": for n, py in enumerate( - pinyin( - _text, style=Style.TONE3, neutral_tone_with_five=True - ) + pinyin(_text, style=Style.TONE3, neutral_tone_with_five=True) ): if all([c in self.punctuation_marks for c in py[0]]): if len(phones): @@ -89,10 +86,7 @@ def phonemize( if py[0][-1].isalnum(): initial = get_initials(py[0], strict=False) if py[0][-1].isdigit(): - final = ( - get_finals(py[0][:-1], strict=False) - + py[0][-1] - ) + final = get_finals(py[0][:-1], strict=False) + py[0][-1] else: final = get_finals(py[0], strict=False) phones.extend( @@ -155,8 +149,7 @@ def to_list(self, phonemized: str) -> List[str]: # "ɐ m|iː|n?" ɹ|ɪ|z|ɜː|v; h|ɪ|z. pp = re.findall(r"\w+|[^\w\s]", word, re.UNICODE) fields.extend( - [p for p in pp if p != self.separator.phone] - + [self.separator.word] + [p for p in pp if p != self.separator.phone] + [self.separator.word] ) assert len("".join(fields[:-1])) == len(phonemized) - phonemized.count( self.separator.phone @@ -182,6 +175,7 @@ def remove_encodec_weight_norm(model): from encodec.modules import SConv1d from encodec.modules.seanet import SConvTranspose1d, SEANetResnetBlock from torch.nn.utils import remove_weight_norm + encoder = model.encoder.model for key in encoder._modules: if isinstance(encoder._modules[key], SEANetResnetBlock): @@ -326,7 +320,7 @@ def remove_encodec_weight_norm(model): # # ret = self.codec.cpu().decode([(frames[0][0].cpu(),None)])[0].to(self._device) # # self.codec.to(self._device) # # return [ret] - + # def tokenize_audio(tokenizer: AudioTokenizer, audio_path: str, offset = -1, num_frames=-1): # # Load and pre-process the audio waveform # if offset != -1 and num_frames!=-1: @@ -457,4 +451,4 @@ def remove_encodec_weight_norm(model): remove_encodec_weight_norm(model) codes_raw = model.encode(samples.cuda()) - assert torch.allclose(codes_raw[0][0], codes_norm[0][0]) \ No newline at end of file + assert torch.allclose(codes_raw[0][0], codes_norm[0][0]) diff --git a/data/tokenizer.py b/data/tokenizer.py index 46bcaa0..ce6b9ff 100644 --- a/data/tokenizer.py +++ b/data/tokenizer.py @@ -16,10 +16,11 @@ import re from dataclasses import asdict, dataclass from typing import Any, Dict, List, Optional, Pattern, Union - +from voicestar.data.encodec import get_compression_model import numpy as np import torch import torchaudio + # from encodec import EncodecModel # from encodec.utils import convert_audio # from lhotse.features import FeatureExtractor @@ -63,9 +64,7 @@ def phonemize( phones = [] if self.backend == "pypinyin": for n, py in enumerate( - pinyin( - _text, style=Style.TONE3, neutral_tone_with_five=True - ) + pinyin(_text, style=Style.TONE3, neutral_tone_with_five=True) ): if all([c in self.punctuation_marks for c in py[0]]): if len(phones): @@ -77,9 +76,7 @@ def phonemize( phones.extend([py[0], separator.syllable]) elif self.backend == "pypinyin_initials_finals": for n, py in enumerate( - pinyin( - _text, style=Style.TONE3, neutral_tone_with_five=True - ) + pinyin(_text, style=Style.TONE3, neutral_tone_with_five=True) ): if all([c in self.punctuation_marks for c in py[0]]): if len(phones): @@ -90,10 +87,7 @@ def phonemize( if py[0][-1].isalnum(): initial = get_initials(py[0], strict=False) if py[0][-1].isdigit(): - final = ( - get_finals(py[0][:-1], strict=False) - + py[0][-1] - ) + final = get_finals(py[0][:-1], strict=False) + py[0][-1] else: final = get_finals(py[0], strict=False) phones.extend( @@ -156,8 +150,7 @@ def to_list(self, phonemized: str) -> List[str]: # "ɐ m|iː|n?" ɹ|ɪ|z|ɜː|v; h|ɪ|z. pp = re.findall(r"\w+|[^\w\s]", word, re.UNICODE) fields.extend( - [p for p in pp if p != self.separator.phone] - + [self.separator.word] + [p for p in pp if p != self.separator.phone] + [self.separator.word] ) assert len("".join(fields[:-1])) == len(phonemized) - phonemized.count( self.separator.phone @@ -183,6 +176,7 @@ def remove_encodec_weight_norm(model): from encodec.modules import SConv1d from encodec.modules.seanet import SConvTranspose1d, SEANetResnetBlock from torch.nn.utils import remove_weight_norm + encoder = model.encoder.model for key in encoder._modules: if isinstance(encoder._modules[key], SEANetResnetBlock): @@ -212,14 +206,14 @@ class AudioTokenizer: def __init__( self, - bandwidth: float=6.0, + bandwidth: float = 6.0, device: Any = None, hificodec=False, - signature = None, - encode_only = False + signature=None, + encode_only=False, ) -> None: self.signature = signature - from data.encodec import get_compression_model + model = get_compression_model(signature, encode_only=encode_only, device=device) self.sample_rate = model.sample_rate self.channels = model.channels @@ -240,35 +234,44 @@ def device(self): def encode(self, wav: torch.Tensor) -> torch.Tensor: if self.signature != None: if self.signature == "lfsc": - if wav.ndim==3: - assert wav.shape[:2] == torch.Size((1,1)), wav.shape + if wav.ndim == 3: + assert wav.shape[:2] == torch.Size((1, 1)), wav.shape wav = wav.squeeze(0) - elif wav.ndim==2: + elif wav.ndim == 2: assert wav.shape[0] == 1, wav.shape else: raise ValueError(wav.shape) audio_len = torch.tensor([wav.shape[1]]).to(self.device) - codes, encoded_len = self.codec.encode(audio=wav.to(self.device), audio_len=audio_len) - return codes[:, :, :encoded_len[0]] + codes, encoded_len = self.codec.encode( + audio=wav.to(self.device), audio_len=audio_len + ) + return codes[:, :, : encoded_len[0]] else: codes = self.codec.encode(wav.to(self.device)) return codes[0] else: - assert wav.ndim==3 and wav.shape[:2] == torch.Size((1,1)), wav.shape + assert wav.ndim == 3 and wav.shape[:2] == torch.Size((1, 1)), wav.shape return self.codec.encode(wav.to(self.device)) def decode(self, frames: torch.Tensor) -> torch.Tensor: if self.signature != None and self.signature == "lfsc": encoded_len = torch.tensor([frames.shape[-1]]).to(self.device) - reconstructed_audio, decoded_len = self.codec.decode(tokens=frames, tokens_len=encoded_len) - return reconstructed_audio[:, :decoded_len[0]].unsqueeze(0) + reconstructed_audio, decoded_len = self.codec.decode( + tokens=frames, tokens_len=encoded_len + ) + return reconstructed_audio[:, : decoded_len[0]].unsqueeze(0) else: return self.codec.decode(frames) - -def tokenize_audio(tokenizer: AudioTokenizer, audio_path: str, offset = -1, num_frames=-1): + + +def tokenize_audio( + tokenizer: AudioTokenizer, audio_path: str, offset=-1, num_frames=-1 +): # Load and pre-process the audio waveform - if offset != -1 and num_frames!=-1: - wav, sr = torchaudio.load(audio_path, frame_offset=offset, num_frames=num_frames) + if offset != -1 and num_frames != -1: + wav, sr = torchaudio.load( + audio_path, frame_offset=offset, num_frames=num_frames + ) else: wav, sr = torchaudio.load(audio_path) if sr != tokenizer.sample_rate: @@ -285,11 +288,17 @@ def tokenize_audio(tokenizer: AudioTokenizer, audio_path: str, offset = -1, num_ if __name__ == "__main__": # tok = AudioTokenizer(signature="lfsc", device="cpu") - tok = AudioTokenizer(signature="/home/pyp/BoostedVoiceEditor/pretrained/encodec_6f79c6a8.th", device="cpu") + tok = AudioTokenizer( + signature="/home/pyp/BoostedVoiceEditor/pretrained/encodec_6f79c6a8.th", + device="cpu", + ) inaudio = "/home/pyp/BoostedVoiceEditor/demo/pam.wav" encoded_frames = tokenize_audio(tok, inaudio) print(encoded_frames.shape) # decode it back decoded_audio = tok.decode(encoded_frames) - torchaudio.save("/home/pyp/BoostedVoiceEditor/demo/pam_reconstructed_encodec_4cb_2nd.wav", decoded_audio[0], tok.sample_rate) - + torchaudio.save( + "/home/pyp/BoostedVoiceEditor/demo/pam_reconstructed_encodec_4cb_2nd.wav", + decoded_audio[0], + tok.sample_rate, + ) diff --git a/generated_tts/generated.wav b/generated_tts/generated.wav index a04b7e1cd99fcc42fe2b786d5cbb79ced02f03d5..ccd20bca4c75ec370e9589cf1779f376794bbc21 100644 GIT binary patch literal 503120 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 z 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�B$I%<;+LBmmPre;lf- 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

1#EZO4AbQ|K+9-2R34iH5%Z@4(zS<-Fc%P& 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�SiCRrVA9mn_pGl#vIHfK42 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

B) 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

Tzw%~arw_NcoKrKe#8uXBjq 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≫CnpcJ7z{&Ywa=L3+cjK&k{3{ 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 E1G|hG%K!iX diff --git a/inference_gradio.py b/inference_gradio.py index 4bb2879..bb58f04 100644 --- a/inference_gradio.py +++ b/inference_gradio.py @@ -16,6 +16,7 @@ import whisper import gradio as gr from argparse import Namespace +from huggingface_hub import hf_hub_download # --------------------------------------------------------------------- # The following imports assume your local project structure: @@ -25,7 +26,7 @@ # Adjust if needed. # --------------------------------------------------------------------- from data.tokenizer import AudioTokenizer, TextTokenizer -from models import voice_star +from voicestar import voicestar as voice_star # legacy compatability TODO: change from inference_tts_utils import inference_one_sample @@ -33,56 +34,40 @@ # Utility Functions ############################################################ -def seed_everything(seed=1): - os.environ['PYTHONHASHSEED'] = str(seed) - random.seed(seed) - np.random.seed(seed) - torch.manual_seed(seed) - torch.cuda.manual_seed(seed) - torch.backends.cudnn.benchmark = False - torch.backends.cudnn.deterministic = True +from voicestar.utils import seed_everything, estimate_duration -def estimate_duration(ref_audio_path, text): - """ - Estimate duration based on seconds per character from the reference audio. - """ - info = torchaudio.info(ref_audio_path) - audio_duration = info.num_frames / info.sample_rate - length_text = max(len(text), 1) - spc = audio_duration / length_text # seconds per character - return len(text) * spc ############################################################ # Main Inference Function ############################################################ + def run_inference( # User-adjustable parameters (no "# do not change" in snippet) reference_speech="./demo/5895_34622_000026_000002.wav", target_text="VoiceStar is a very interesting model, it's duration controllable and can extrapolate", model_name="VoiceStar_840M_40s", model_root="./pretrained", - reference_text=None, # optional - target_duration=None, # optional - top_k=10, # can try 10, 20, 30, 40 + reference_text=None, # optional + target_duration=None, # optional + top_k=10, # can try 10, 20, 30, 40 temperature=1, - kvcache=1, # if OOM, set to 0 - repeat_prompt=1, # use higher to improve speaker similarity - stop_repetition=3, # snippet says "will not use it" but not "do not change" + kvcache=1, # if OOM, set to 0 + repeat_prompt=1, # use higher to improve speaker similarity + stop_repetition=3, # snippet says "will not use it" but not "do not change" seed=1, output_dir="./generated_tts", - # Non-adjustable parameters (based on snippet instructions) - codec_audio_sr=16000, # do not change - codec_sr=50, # do not change - top_p=1, # do not change - min_p=1, # do not change - silence_tokens=None, # do not change it - multi_trial=None, # do not change it - sample_batch_size=1, # do not change - cut_off_sec=100, # do not adjust + codec_audio_sr=16000, # do not change + codec_sr=50, # do not change + top_p=1, # do not change + min_p=1, # do not change + silence_tokens=None, # do not change it + multi_trial=None, # do not change it + sample_batch_size=1, # do not change + cut_off_sec=100, # do not adjust ): """ Inference script for VoiceStar TTS. @@ -92,24 +77,23 @@ def run_inference( # 2. Load model checkpoint torch.serialization.add_safe_globals([Namespace]) - device = "cuda" if torch.cuda.is_available() else "cpu" - ckpt_fn = os.path.join(model_root, model_name + ".pth") - if not os.path.exists(ckpt_fn): - # use wget to download - print(f"[Info] Downloading {model_name} checkpoint...") - os.system(f"wget https://huggingface.co/pyp1/VoiceStar/resolve/main/{model_name}.pth?download=true -O {ckpt_fn}") + device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" # MPS support + ckpt_fn = hf_hub_download(repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth") + bundle = torch.load(ckpt_fn, map_location=device, weights_only=True) args = bundle["args"] phn2num = bundle["phn2num"] - model = voice_star.VoiceStar(args) + model = voice_star.VoiceStarModel(args) model.load_state_dict(bundle["model"]) model.to(device) model.eval() # 3. If reference_text not provided, transcribe reference speech with Whisper if reference_text is None: - print("[Info] No reference_text provided. Transcribing reference_speech with Whisper (large-v3-turbo).") + print( + "[Info] No reference_text provided. Transcribing reference_speech with Whisper (large-v3-turbo)." + ) wh_model = whisper.load_model("large-v3-turbo") result = wh_model.transcribe(reference_speech) prefix_transcript = result["text"] @@ -120,7 +104,9 @@ def run_inference( # 4. If target_duration not provided, estimate from reference speech + target_text if target_duration is None: target_generation_length = estimate_duration(reference_speech, target_text) - print(f"[Info] target_duration not provided, estimated as {target_generation_length:.2f}s. Provide --target_duration if needed.") + print( + f"[Info] target_duration not provided, estimated as {target_generation_length:.2f}s. Provide --target_duration if needed." + ) else: target_generation_length = float(target_duration) @@ -164,9 +150,15 @@ def run_inference( # 8. Run inference print("[Info] Running TTS inference...") concated_audio, gen_audio = inference_one_sample( - model, args, phn2num, text_tokenizer, audio_tokenizer, - reference_speech, target_text, - device, decode_config, + model, + args, + phn2num, + text_tokenizer, + audio_tokenizer, + reference_speech, + target_text, + device, + decode_config, prompt_end_frame=prompt_end_frame, target_generation_length=target_generation_length, delay_pattern_increment=delay_pattern_increment, @@ -192,6 +184,7 @@ def run_inference( # Transcription function ############################ + def transcribe_audio(reference_speech): """ Transcribe uploaded reference audio with Whisper, return text. @@ -209,19 +202,19 @@ def transcribe_audio(reference_speech): result = model.transcribe(audio_path) return result["text"] + ############################ # Gradio UI ############################ + def main(): with gr.Blocks() as demo: gr.Markdown("## VoiceStar TTS with Editable Reference Text") with gr.Row(): reference_speech_input = gr.Audio( - label="Reference Speech", - type="filepath", - elem_id="ref_speech" + label="Reference Speech", type="filepath", elem_id="ref_speech" ) transcribe_button = gr.Button("Transcribe") @@ -229,28 +222,25 @@ def main(): reference_text_box = gr.Textbox( label="Reference Text (Editable)", placeholder="Click 'Transcribe' to auto-fill from reference speech...", - lines=2 + lines=2, ) target_text_box = gr.Textbox( label="Target Text", value="VoiceStar is a very interesting model, it's duration controllable and can extrapolate to unseen duration.", - lines=3 + lines=3, ) - model_name_box = gr.Textbox( - label="Model Name", - value="VoiceStar_840M_40s" - ) + model_name_box = gr.Textbox(label="Model Name", value="VoiceStar_840M_40s") model_root_box = gr.Textbox( label="Model Root Directory", - value="/data1/scratch/pyp/BoostedVoiceEditor/runs" + value="/data1/scratch/pyp/BoostedVoiceEditor/runs", ) reference_duration_box = gr.Textbox( label="Target Duration (Optional)", - placeholder="Leave empty for auto-estimate." + placeholder="Leave empty for auto-estimate.", ) top_k_box = gr.Number(label="top_k", value=10) @@ -271,7 +261,7 @@ def main(): outputs=[reference_text_box], ) - # 2) The actual TTS generation function. + # 2) The actual TTS generation function. def gradio_inference( reference_speech, reference_text, @@ -285,7 +275,7 @@ def gradio_inference( repeat_prompt, stop_repetition, seed, - output_dir + output_dir, ): # Convert any empty strings to None for optional fields dur = float(target_duration) if target_duration else None @@ -303,7 +293,7 @@ def gradio_inference( repeat_prompt=int(repeat_prompt), stop_repetition=int(stop_repetition), seed=int(seed), - output_dir=output_dir + output_dir=output_dir, ) return out_path @@ -323,12 +313,13 @@ def gradio_inference( repeat_prompt_box, stop_repetition_box, seed_box, - output_dir_box + output_dir_box, ], outputs=[output_audio], ) demo.launch(server_name="0.0.0.0", server_port=7860, debug=True) + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/inference_tts_utils.py b/inference_tts_utils.py index 412e7c2..8c3e305 100644 --- a/inference_tts_utils.py +++ b/inference_tts_utils.py @@ -5,43 +5,88 @@ import torch import torchaudio -from data.tokenizer import ( - AudioTokenizer, - TextTokenizer, - tokenize_audio, - tokenize_text -) +from data.tokenizer import AudioTokenizer, TextTokenizer, tokenize_audio, tokenize_text import argparse, time, tqdm # this script only works for the musicgen architecture def get_args(): - parser = argparse.ArgumentParser(formatter_class=argparse.ArgumentDefaultsHelpFormatter) + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) parser.add_argument("--manifest_fn", type=str, default="path/to/eval_metadata_file") parser.add_argument("--audio_root", type=str, default="path/to/audio_folder") parser.add_argument("--exp_dir", type=str, default="path/to/model_folder") parser.add_argument("--seed", type=int, default=1) - parser.add_argument("--codec_audio_sr", type=int, default=16000, help='the sample rate of audio that the codec is trained for') - parser.add_argument("--codec_sr", type=int, default=50, help='the sample rate of the codec codes') + parser.add_argument( + "--codec_audio_sr", + type=int, + default=16000, + help="the sample rate of audio that the codec is trained for", + ) + parser.add_argument( + "--codec_sr", type=int, default=50, help="the sample rate of the codec codes" + ) parser.add_argument("--top_k", type=int, default=0, help="sampling param") parser.add_argument("--top_p", type=float, default=0.8, help="sampling param") parser.add_argument("--temperature", type=float, default=1.0, help="sampling param") parser.add_argument("--output_dir", type=str, default=None) parser.add_argument("--device", type=str, default="cuda") - parser.add_argument("--signature", type=str, default=None, help="path to the encodec model") + parser.add_argument( + "--signature", type=str, default=None, help="path to the encodec model" + ) parser.add_argument("--crop_concat", type=int, default=0) - parser.add_argument("--stop_repetition", type=int, default=-1, help="used for inference, when the number of consecutive repetition of a token is bigger than this, stop it") - parser.add_argument("--kvcache", type=int, default=1, help='if true, use kv cache, which is 4-8x faster than without') - parser.add_argument("--sample_batch_size", type=int, default=1, help="batch size for sampling, NOTE that it's not running inference for several samples, but duplicate one input sample batch_size times, and during inference, we only return the shortest generation") - parser.add_argument("--silence_tokens", type=str, default="[1388,1898,131]", help="note that if you are not using the pretrained encodec 6f79c6a8, make sure you specified it yourself, rather than using the default") + parser.add_argument( + "--stop_repetition", + type=int, + default=-1, + help="used for inference, when the number of consecutive repetition of a token is bigger than this, stop it", + ) + parser.add_argument( + "--kvcache", + type=int, + default=1, + help="if true, use kv cache, which is 4-8x faster than without", + ) + parser.add_argument( + "--sample_batch_size", + type=int, + default=1, + help="batch size for sampling, NOTE that it's not running inference for several samples, but duplicate one input sample batch_size times, and during inference, we only return the shortest generation", + ) + parser.add_argument( + "--silence_tokens", + type=str, + default="[1388,1898,131]", + help="note that if you are not using the pretrained encodec 6f79c6a8, make sure you specified it yourself, rather than using the default", + ) return parser.parse_args() @torch.no_grad() -def inference_one_sample(model, model_args, phn2num, text_tokenizer, audio_tokenizer, audio_fn, target_text, device, decode_config, prompt_end_frame, target_generation_length, delay_pattern_increment, prefix_transcript=None, quiet=False, repeat_prompt=0, multi_trial=[]): +def inference_one_sample( + model, + model_args, + phn2num, + text_tokenizer, + audio_tokenizer, + audio_fn, + target_text, + device, + decode_config, + prompt_end_frame, + target_generation_length, + delay_pattern_increment, + prefix_transcript=None, + quiet=False, + repeat_prompt=0, + multi_trial=[], +): # seq_len_thres = 500 # 10s, 26% of the data in seed tts # encode audio - encoded_frames = tokenize_audio(audio_tokenizer, audio_fn, offset=0, num_frames=prompt_end_frame) + encoded_frames = tokenize_audio( + audio_tokenizer, audio_fn, offset=0, num_frames=prompt_end_frame + ) # if sequence length is shorter than seq_len_thres, repeat the audio # if encoded_frames.shape[2] < seq_len_thres: # encoded_frames = torch.cat([encoded_frames, encoded_frames, encoded_frames], dim=2) @@ -55,34 +100,57 @@ def inference_one_sample(model, model_args, phn2num, text_tokenizer, audio_token cur_repeat_prompt -= 1 elif isinstance(repeat_prompt, str) and repeat_prompt.lower() == "max": repeat_prompt = 0 - while encoded_frames.shape[2] + decode_config['codec_sr'] * target_generation_length + delay_pattern_increment + single_encoded_frames.shape[2] < model_args.audio_max_length * decode_config['codec_sr']: + while ( + encoded_frames.shape[2] + + decode_config["codec_sr"] * target_generation_length + + delay_pattern_increment + + single_encoded_frames.shape[2] + < model_args.audio_max_length * decode_config["codec_sr"] + ): encoded_frames = torch.cat([encoded_frames, single_encoded_frames], dim=2) repeat_prompt += 1 if getattr(model_args, "y_sep_token", None) != None: - encoded_frames = torch.cat([encoded_frames, torch.LongTensor([model_args.y_sep_token]*model_args.n_codebooks).unsqueeze(0).unsqueeze(2).to(encoded_frames.device)], dim=2) + encoded_frames = torch.cat( + [ + encoded_frames, + torch.LongTensor([model_args.y_sep_token] * model_args.n_codebooks) + .unsqueeze(0) + .unsqueeze(2) + .to(encoded_frames.device), + ], + dim=2, + ) # print(encoded_frames.shape) - original_audio = encoded_frames.transpose(2,1) # [1,T,K] - assert original_audio.ndim==3 and original_audio.shape[0] == 1 and original_audio.shape[2] == model_args.n_codebooks, original_audio.shape + original_audio = encoded_frames.transpose(2, 1) # [1,T,K] + assert ( + original_audio.ndim == 3 + and original_audio.shape[0] == 1 + and original_audio.shape[2] == model_args.n_codebooks + ), original_audio.shape # phonemize if isinstance(target_text, list): text_tokens = [phn2num[phn] for phn in target_text if phn in phn2num] else: - text_tokens = [phn2num[phn] for phn in - tokenize_text( - text_tokenizer, text=target_text.strip() - ) if phn in phn2num - ] + text_tokens = [ + phn2num[phn] + for phn in tokenize_text(text_tokenizer, text=target_text.strip()) + if phn in phn2num + ] if getattr(model_args, "x_sep_token", None) != None: - assert prefix_transcript != None, "prefix_transcript must be provided if x_sep_token is not None" + assert ( + prefix_transcript != None + ), "prefix_transcript must be provided if x_sep_token is not None" if prefix_transcript is not None: if isinstance(prefix_transcript, list): - prefix_tokens = [phn2num[phn] for phn in prefix_transcript if phn in phn2num] + prefix_tokens = [ + phn2num[phn] for phn in prefix_transcript if phn in phn2num + ] else: - prefix_tokens = [phn2num[phn] for phn in - tokenize_text( - text_tokenizer, text=prefix_transcript.strip() - ) if phn in phn2num + prefix_tokens = [ + phn2num[phn] + for phn in tokenize_text(text_tokenizer, text=prefix_transcript.strip()) + if phn in phn2num ] # if doubled: # prefix_tokens = prefix_tokens + prefix_tokens + prefix_tokens @@ -91,7 +159,9 @@ def inference_one_sample(model, model_args, phn2num, text_tokenizer, audio_token prefix_tokens = prefix_tokens + single_prefix_tokens repeat_prompt -= 1 if getattr(model_args, "x_sep_token", None) != None: - text_tokens = prefix_tokens + [getattr(model_args, "x_sep_token", None)] + text_tokens + text_tokens = ( + prefix_tokens + [getattr(model_args, "x_sep_token", None)] + text_tokens + ) else: text_tokens = prefix_tokens + text_tokens if getattr(model_args, "add_eos_to_text", 0) != 0: @@ -102,38 +172,61 @@ def inference_one_sample(model, model_args, phn2num, text_tokenizer, audio_token text_tokens_lens = torch.LongTensor([text_tokens.shape[-1]]) if not quiet: - logging.info(f"original audio length: {original_audio.shape[1]} codec frames, which is {original_audio.shape[1]/decode_config['codec_sr']:.2f} sec.") - + logging.info( + f"original audio length: {original_audio.shape[1]} codec frames, which is {original_audio.shape[1]/decode_config['codec_sr']:.2f} sec." + ) if getattr(model_args, "parallel_pattern", 0) != 0: - tgt_y_lens = torch.LongTensor([int(original_audio.shape[1] + decode_config['codec_sr'] * target_generation_length + 2)]) # parallel pattern, therefore only add the empty_token (i.e. the sos token) and eos (i.e. 2 more tokens). Note that the delayed pattern between, both sos and eos is counted (sos is counted in the n_codebooks, eos is counted in the 1) + tgt_y_lens = torch.LongTensor( + [ + int( + original_audio.shape[1] + + decode_config["codec_sr"] * target_generation_length + + 2 + ) + ] + ) # parallel pattern, therefore only add the empty_token (i.e. the sos token) and eos (i.e. 2 more tokens). Note that the delayed pattern between, both sos and eos is counted (sos is counted in the n_codebooks, eos is counted in the 1) else: - tgt_y_lens = torch.LongTensor([int(original_audio.shape[1] + decode_config['codec_sr'] * target_generation_length + delay_pattern_increment)]) # delay pattern increment has accounted for the added eos + tgt_y_lens = torch.LongTensor( + [ + int( + original_audio.shape[1] + + decode_config["codec_sr"] * target_generation_length + + delay_pattern_increment + ) + ] + ) # delay pattern increment has accounted for the added eos # forward - assert decode_config['sample_batch_size'] <= 1 + assert decode_config["sample_batch_size"] <= 1 stime = time.time() - assert multi_trial == [] + assert multi_trial == [] if not quiet: logging.info(f"running inference with batch size 1") concat_frames, gen_frames = model.inference_tts( text_tokens.to(device), text_tokens_lens.to(device), - original_audio[...,:model_args.n_codebooks].to(device), # [1,T,8] - tgt_y_lens = tgt_y_lens.to(device), - top_k=decode_config['top_k'], - top_p=decode_config['top_p'], - min_p=decode_config['min_p'], - temperature=decode_config['temperature'], - stop_repetition=decode_config['stop_repetition'], - kvcache=decode_config['kvcache'], - silence_tokens=eval(decode_config['silence_tokens']) if type(decode_config['silence_tokens'])==str else decode_config['silence_tokens'] - ) # output is [1,K,T] + original_audio[..., : model_args.n_codebooks].to(device), # [1,T,8] + tgt_y_lens=tgt_y_lens.to(device), + top_k=decode_config["top_k"], + top_p=decode_config["top_p"], + min_p=decode_config["min_p"], + temperature=decode_config["temperature"], + stop_repetition=decode_config["stop_repetition"], + kvcache=decode_config["kvcache"], + silence_tokens=( + eval(decode_config["silence_tokens"]) + if type(decode_config["silence_tokens"]) == str + else decode_config["silence_tokens"] + ), + ) # output is [1,K,T] if not quiet: logging.info(f"inference on one sample take: {time.time() - stime:.4f} sec.") - logging.info(f"generated encoded_frames.shape: {gen_frames.shape}, which is {gen_frames.shape[-1]/decode_config['codec_sr']} sec.") - + logging.info( + f"generated encoded_frames.shape: {gen_frames.shape}, which is {gen_frames.shape[-1]/decode_config['codec_sr']} sec." + ) + # for timestamp, codes in enumerate(gen_frames[0].transpose(1,0)): # logging.info(f"{timestamp}: {codes.tolist()}") # decode (both original and generated) @@ -141,15 +234,17 @@ def inference_one_sample(model, model_args, phn2num, text_tokenizer, audio_token # [(concat_frames, None)] # [1,T,8] -> [1,8,T] # ) if getattr(model_args, "y_sep_token", None) != None: - concat_frames = torch.cat([concat_frames[:, :, :original_audio.shape[1]-1], concat_frames[:, :, original_audio.shape[1]:]], dim=2) - concat_sample = audio_tokenizer.decode( - concat_frames # [1,8,T] - ) - gen_sample = audio_tokenizer.decode( - gen_frames - ) - #Empty cuda cache between runs + concat_frames = torch.cat( + [ + concat_frames[:, :, : original_audio.shape[1] - 1], + concat_frames[:, :, original_audio.shape[1] :], + ], + dim=2, + ) + concat_sample = audio_tokenizer.decode(concat_frames) # [1,8,T] + gen_sample = audio_tokenizer.decode(gen_frames) + # Empty cuda cache between runs if torch.cuda.is_available(): torch.cuda.empty_cache() # return - return concat_sample, gen_sample \ No newline at end of file + return concat_sample, gen_sample diff --git a/models/voice_star.py b/models/voice_star.py deleted file mode 100644 index 7cc4806..0000000 --- a/models/voice_star.py +++ /dev/null @@ -1,784 +0,0 @@ -import random, os, copy -from typing import Dict, Iterator, List, Tuple, Union -import logging -import numpy as np - -import torch -import torch.nn as nn -import torch.nn.functional as F -from torchmetrics.classification import MulticlassAccuracy -import torch.distributed as dist - -from .modules.utils import make_pad_mask, generate_partial_autoregressive_mask - -from .modules.embedding import SinePositionalEmbedding, TokenEmbedding, SinePositionalEmbedding_progress -from .modules.transformer import ( - AdaptiveLayerNorm, - LayerNorm, - TransformerDecoderLayer, - TransformerDecoder, - TransformerEncoder, - TransformerEncoderLayer, -) - -def top_k_top_p_filtering( - logits, top_k=0, top_p=1.0, min_p=1.0, filter_value=-float("Inf"), min_tokens_to_keep=1 -): - """Filter a distribution of logits using top-k and/or nucleus (top-p) filtering - Args: - logits: logits distribution shape (batch size, vocabulary size) - if top_k > 0: keep only top k tokens with highest probability (top-k filtering). - if top_p < 1.0: keep the top tokens with cumulative probability >= top_p (nucleus filtering). - Nucleus filtering is described in Holtzman et al. (http://arxiv.org/abs/1904.09751) - Make sure we keep at least min_tokens_to_keep per batch example in the output - From: https://gist.github.com/thomwolf/1a5a29f6962089e871b94cbd09daf317 - """ - if min_p < 1.0: - probs = F.softmax(logits, dim=-1) - indices_to_remove = probs < min_p - if not torch.any(indices_to_remove.sum(-1) == logits.size(-1)): - logits[indices_to_remove] = filter_value - top_k = 0 - top_p = 1.0 - # else will use other types of sampling, or no filtering - - # If top_k is a single integer - if isinstance(top_k, int) and top_k > 0: - # Safety check to ensure we don't ask for more than available - top_k = min(max(top_k, min_tokens_to_keep), logits.size(-1)) - - # Remove all tokens with a probability less than the last token of the top-k - threshold = torch.topk(logits, top_k, dim=-1)[0][..., -1, None] - indices_to_remove = logits < threshold - logits[indices_to_remove] = filter_value - - # If top_k is a list, assume it has the same length as M - elif isinstance(top_k, list): - # Ensure the length matches the first dimension - assert len(top_k) == logits.size(0), \ - f"top_k list length ({len(top_k)}) must match logits.size(0) ({logits.size(0)})" - - for i in range(logits.size(0)): - k_i = top_k[i] - if k_i > 0: - # Safety check - k_i = min(max(k_i, min_tokens_to_keep), logits.size(-1)) - row_threshold = torch.topk(logits[i], k_i, dim=-1)[0][-1] - indices_to_remove_i = logits[i] < row_threshold - logits[i, indices_to_remove_i] = filter_value - - if top_p < 1.0: - sorted_logits, sorted_indices = torch.sort(logits, descending=True) - cumulative_probs = torch.cumsum( - F.softmax(sorted_logits, dim=-1), dim=-1 - ) - - # Remove tokens with cumulative probability above the threshold (token with 0 are kept) - sorted_indices_to_remove = cumulative_probs > top_p - if min_tokens_to_keep > 1: - # Keep at least min_tokens_to_keep (set to min_tokens_to_keep-1 because we add the first one below) - sorted_indices_to_remove[..., :min_tokens_to_keep] = 0 - # Shift the indices to the right to keep also the first token above the threshold - sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[ - ..., :-1 - ].clone() - sorted_indices_to_remove[..., 0] = 0 - - return logits - - -def topk_sampling(logits, top_k=10, top_p=1.0, min_p=1.0, temperature=1.0): - # temperature: (`optional`) float - # The value used to module the next token probabilities. Must be strictly positive. Default to 1.0. - # top_k: (`optional`) int - # The number of highest probability vocabulary tokens to keep for top-k-filtering. Between 1 and infinity. Default to 50. - # top_p: (`optional`) float - # The cumulative probability of parameter highest probability vocabulary tokens to keep for nucleus sampling. Must be between 0 and 1. Default to 1. - - # Temperature (higher temperature => more likely to sample low probability tokens) - if temperature != 1.0: - logits = logits / temperature - # Top-p/top-k filtering - logits = top_k_top_p_filtering(logits, top_k=top_k, top_p=top_p, min_p=min_p) - # Sample - token = torch.multinomial(F.softmax(logits, dim=-1), num_samples=1) - return token - - - -class VoiceStar(nn.Module): - def __init__(self, args): - super().__init__() - self.args = args - assert self.args.enc_dec ^ self.args.dec, f"self.args.enc_dec: {self.args.enc_dec}, self.args.dec: {self.args.dec}" - if not getattr(self.args, "special_first", False): - self.args.special_first = 0 - if not getattr(self.args, "n_special", False): - self.args.n_special = 3 - self.args.eos = getattr(self.args, "eos", -1) - self.eog = nn.Parameter(torch.full((self.args.n_codebooks, 1), self.args.eog, dtype=torch.long), requires_grad=False) # [K 1] - if self.args.eos > 0: - assert self.args.eos != self.args.audio_pad_token and self.args.eos != self.args.empty_token, self.args.eos - self.eos = nn.Parameter(torch.full((self.args.n_codebooks, 1), self.args.eos, dtype=torch.long), requires_grad=False) # [K 1] - if type(self.args.audio_vocab_size) == str: - self.args.audio_vocab_size = eval(self.args.audio_vocab_size) - if type(self.args.audio_vocab_size) == list: # otherwise they are all lists - assert self.args.special_first - - - self.n_text_tokens = self.args.text_vocab_size + 1 - assert self.args.text_pad_token == self.args.text_vocab_size, f"self.args.text_vocab_size: {self.args.text_vocab_size}, self.args.text_pad_token: {self.args.text_pad_token}" - - if self.args.special_first and type(self.args.audio_vocab_size) == list: - self.n_audio_tokens = [tok + self.args.n_special for tok in self.args.audio_vocab_size] # special tokens: empty token, EOG token, audio pad token - assert self.args.empty_token == 0, self.args.empty_token - assert self.args.eog == 1, self.args.eog - assert self.args.audio_pad_token == 2, self.args.audio_pad_token - else: - self.n_audio_tokens = [self.args.audio_vocab_size + self.args.n_special] * self.args.n_codebooks # special tokens: empty token, EOG token, audio pad token - assert self.args.audio_vocab_size == self.args.empty_token, self.args.empty_token - assert self.args.eog == self.args.audio_vocab_size + 1, self.args.eog - assert self.args.audio_pad_token == self.args.audio_vocab_size + 2, self.args.audio_pad_token - - self.text_embedding = TokenEmbedding( - dim_model=self.args.d_model, - vocab_size=self.n_text_tokens, - dropout=self.args.text_embedding_dropout - ) - - self.audio_embedding = nn.ModuleList( - [ - TokenEmbedding( - dim_model=self.args.audio_embedding_dim, - vocab_size=self.n_audio_tokens[k], - dropout=self.args.audio_embedding_dropout - ) for k in range(self.args.n_codebooks) - ] - ) - - rope_base = getattr(self.args, "rope_base", None) - use_sinusoidal = getattr(self.args, "use_sinusoidal", False) - use_sinusoidal_progress = getattr(self.args, "use_sinusoidal_progress", False) - logging.info(f"rope_base: {rope_base}, use_sinusoidal: {use_sinusoidal}") - if use_sinusoidal: - self.text_positional_embedding = SinePositionalEmbedding( - self.args.d_model, - dropout=self.args.text_positional_embedding_dropout, - scale=False, - alpha=True, # learnable scaler, scale the volume of positional embedding - ) - self.audio_positional_embedding = SinePositionalEmbedding( - self.args.d_model, - dropout=self.args.audio_positional_embedding_dropout, - scale=False, - alpha=True, # learnable scaler, scale the volume of positional embedding - ) - elif use_sinusoidal_progress: - self.text_positional_embedding = SinePositionalEmbedding_progress( - self.args.d_model, - dropout=self.args.text_positional_embedding_dropout, - scale=False, - alpha=True, # learnable scaler, scale the volume of positional embedding - args = self.args - ) - self.audio_positional_embedding = SinePositionalEmbedding_progress( - self.args.d_model, - dropout=self.args.audio_positional_embedding_dropout, - scale=False, - alpha=True, # learnable scaler, scale the volume of positional embedding - args = self.args - ) - - else: - class NoOp: - def __init__(self): - pass - def __call__(self, *args, **kwargs): - return args[0] - self.text_positional_embedding = NoOp() - self.audio_positional_embedding = NoOp() - - if self.args.enc_dec: - enc_layer = TransformerEncoderLayer( - d_model=self.args.d_model, - nhead=self.args.nhead, - dim_feedforward=self.args.d_model*4, - dropout=self.args.trm_dropout, - batch_first=True, - norm_first=True, - layer_norm_cls=LayerNorm - ) # use the pre-norm arch - - self.encoder = TransformerEncoder( - encoder_layer=enc_layer, - num_layers=self.args.num_encoder_layers, - norm=LayerNorm(self.args.d_model), - rope_base = self.args.rope_base, - d_model = self.args.d_model, - nhead = self.args.nhead, - args = self.args - ) # use the pre-norm arch - - dec_layer = TransformerDecoderLayer( - d_model=self.args.d_model, - nhead=self.args.nhead, - dim_feedforward=self.args.d_model*4, - dropout=self.args.trm_dropout, - batch_first=True, - norm_first=True, - layer_norm_cls=LayerNorm - ) - - self.decoder = TransformerDecoder( - decoder_layer=dec_layer, - num_layers=self.args.num_decoder_layers, - norm=LayerNorm(self.args.d_model), - rope_base = self.args.rope_base, - d_model = self.args.d_model, - nhead = self.args.nhead, - args = self.args - ) # NOTE: this one I use torch.nn native implementation, as it's not implemented in .modules - - else: - dec_layer = TransformerEncoderLayer( - self.args.d_model, - self.args.nhead, - dim_feedforward=self.args.d_model * 4, - dropout=self.args.trm_dropout, - batch_first=True, - norm_first=True, - layer_norm_cls=LayerNorm - ) - self.decoder = TransformerEncoder( - dec_layer, - num_layers=self.args.num_decoder_layers, - norm=LayerNorm(self.args.d_model), - ) - - if type(self.args.audio_vocab_size) == int: - self.predict_layer = nn.ModuleList( - [ - nn.Sequential(nn.Linear(self.args.d_model, self.args.audio_vocab_size//2), nn.GELU(), nn.Linear(self.args.audio_vocab_size//2, self.n_audio_tokens[k])) for k in range(self.args.n_codebooks) - ] - ) - else: - self.predict_layer = nn.ModuleList( - [ - nn.Sequential(nn.Linear(self.args.d_model, self.args.d_model//2), nn.GELU(), nn.Linear(self.args.d_model//2, self.n_audio_tokens[k])) for k in range(self.args.n_codebooks) - ] - ) - - self.accuracy_metrics = nn.ModuleList( - [MulticlassAccuracy( - self.n_audio_tokens[k], - top_k=10, - average="micro", - multidim_average="global", - ignore_index=None, - ) for k in range(self.args.n_codebooks)] - ) - - if self.args.eog_weight != 1: - raise NotImplementedError("now have different vocab_size for different codebooks, therefore currently don't support eog_weight") - self.class_weight = nn.Parameter(torch.ones(self.n_audio_tokens), requires_grad=False) - self.class_weight.data[self.args.eog] = self.args.eog_weight - - def dec_forward( - self, - x_input, - x_lens, - x_attention_mask, - x_padding_mask, - y_input, - new_y_lens, - y_attention_mask, - y_padding_mask, - need_weights=False, - past=None, - last_3_tokens=False - ): - x_attn_mask = F.pad( - x_attention_mask, - (0, new_y_lens.max()), - value=True, - ) # x attn to all x, doesn't attn to any y, this follow figure 3 of the valle paper - y_attn_mask = F.pad( - y_attention_mask, - (x_lens.max(), 0), # y is padded at the front - value=False, - ) # y attn to all x, for y itself use lower triangle mask to ensure autoregressive - xy_attn_mask = torch.concat([x_attn_mask, y_attn_mask], dim=0) - - # merge key padding and attention masks - bsz, src_len = x_input.shape[0], x_lens.max() + new_y_lens.max() - xy_padding_mask = torch.concat([x_padding_mask, y_padding_mask], dim=1) - _xy_padding_mask = ( - xy_padding_mask.view(bsz, 1, 1, src_len) - .expand(-1, self.args.nhead, -1, -1) - .reshape(bsz * self.args.nhead, 1, src_len) - ) - xy_attn_mask = xy_attn_mask.logical_or(_xy_padding_mask) - - new_attn_mask = torch.zeros_like(xy_attn_mask) - new_attn_mask.masked_fill_(xy_attn_mask, float("-inf")) - xy_attn_mask = new_attn_mask - - xy_input = torch.cat([x_input, y_input], dim=1) - if need_weights: - raise NotImplementedError("not implemented yet") - out, layer_attn_weights = self.decoder((xy_input, None), mask=xy_attn_mask, need_weights=True) - return layer_attn_weights - - if past == None: # do not use kvcache - out, _ = self.decoder((xy_input, None), mask=xy_attn_mask) - return out[:, x_lens.max():], None - else: # use kvcache - if past.ndim > 3: # uses kvcache, only need to pass the last tokens, this doesn't work with multi-span speech editing yet - if last_3_tokens: - xy_input = xy_input[:, -3:] - xy_attn_mask = xy_attn_mask[:, -3:] - else: - xy_input = xy_input[:, -1:] - xy_attn_mask = xy_attn_mask[:, -1:] - - out, present = self.decoder((xy_input, None), mask=xy_attn_mask, past=past) - if isinstance(out, tuple): # get rid of stage_embedding - out = out[0] - - if out.shape[1] > x_lens.max(): # the first pass, not kvcache yet - return out[:, x_lens.max():], present - else: # used kvcache - return out, present - - def enc_dec_forward( - self, - xa, - x_attention_mask, - x_padding_mask, - y_input, - new_y_lens, - y_attention_mask, - y_padding_mask, - tgt_y_lens=None, - need_weights=False, - past=None, - last_3_tokens=False - ): - assert not need_weights - if past != None and past.ndim > 3: - y_input = y_input[:, -1:] - y_attention_mask = y_attention_mask[-1:] - yhat, present = self.decoder(tgt=y_input, memory=xa, tgt_mask=y_attention_mask, tgt_key_padding_mask=y_padding_mask, memory_key_padding_mask=x_padding_mask, query_lens=tgt_y_lens, past=past) - return yhat, present - - def forward(self, batch, calc_loss = False): - """ - Args: - x: - A 2-D tensor of shape (N, S). - x_lens: - A 1-D tensor of shape (N,). It contains the number of tokens in `x` - before padding. - y: - A 3-D tensor of shape (N, K, T). - where K is the number of codebooks - y_lens: - A 1-D tensor of shape (N,). It contains the number of tokens in `x` - before padding. - """ - x, x_lens, y, y_lens = batch["x"], batch["x_lens"], batch["y"], batch["y_lens"] - if len(x) == 0: - return None - x = x[:, :x_lens.max()] # this deal with gradient accumulation, where x_lens.max() might not be longer than the length of the current slice of x - y = y[...,:y_lens.max()] - assert x.ndim == 2, x.shape - assert x_lens.ndim == 1, x_lens.shape - assert y.ndim == 3 and y.shape[1] == self.args.n_codebooks, y.shape - assert y_lens.ndim == 1, y_lens.shape - x_padding_mask = make_pad_mask(x_lens).to(x.device) - x_attention_mask = torch.triu(torch.ones(x.shape[1], x.shape[1]), diagonal=1).bool().to(x_padding_mask.device) - x_input = self.text_embedding(x) - x_input = self.text_positional_embedding(x_input, x_lens) - y_with_eos = [torch.cat([item[:, :y_lens[i]], self.eos], dim=-1) for i, item in enumerate(y)] - targets = y_with_eos - # apply delayed stacking on y - shifted_y = [] - patterns = [] - new_y_lens = [] - if getattr(self, "empty_tokens", None) == None: - self.empty_tokens = torch.full((self.args.n_codebooks, self.args.n_codebooks), self.args.empty_token, dtype=torch.long).to(y.device) # [K, K] - for i in range(len(y)): - tmp = torch.cat([y_with_eos[i], self.empty_tokens], dim=-1) # [K, T+n_codebooks] - for ii in range(self.args.n_codebooks): - tmp[ii] = torch.roll(tmp[ii], shifts=ii+1, dims=0) - shifted_y.append(tmp.transpose(1,0)) # [K, T+n_codebooks] -> [T+n_codebooks, K] - new_y_lens.append(y_with_eos[i].shape[1] + self.empty_tokens.shape[1]) - - new_y_lens = torch.LongTensor(new_y_lens).to(y.device) - - cated_y = torch.nn.utils.rnn.pad_sequence(shifted_y, batch_first=False, padding_value=self.args.audio_pad_token) - assert cated_y.shape == torch.Size([max(new_y_lens), len(y), self.args.n_codebooks]), cated_y.shape - cated_y = cated_y.permute(2,0,1) # [T,B,K]->[K,T,B] - stacked_embedded_y = torch.stack([self.audio_embedding[k](cated_y[k]) for k in range(self.args.n_codebooks)], dim=0) # [K, T, B, D] - assert stacked_embedded_y.shape[0] == self.args.n_codebooks and stacked_embedded_y.shape[2] == len(y) and stacked_embedded_y.shape[-1] == self.args.d_model, stacked_embedded_y.shape - embedded_y = stacked_embedded_y.sum(dim=0) # [K,T,B,D]->[T,B,D] - embedded_y = embedded_y.transpose(1,0) # [T,B,D]->[B,T,D] - assert embedded_y.shape[1:] == torch.Size([max(new_y_lens), self.args.d_model]), embedded_y.shape - y_input = self.audio_positional_embedding(embedded_y, new_y_lens) - y_padding_mask = make_pad_mask(new_y_lens).to(y.device) - y_attention_mask = torch.triu(torch.ones(y_input.shape[1], y_input.shape[1]), diagonal=1).bool().to(y_padding_mask.device) - if self.args.dec: - y_out = self.dec_forward( - x_input, - x_lens, - x_attention_mask, - x_padding_mask, - y_input, - new_y_lens, - y_attention_mask, - y_padding_mask - ) - else: - xa = self.encoder(src=x_input, src_key_padding_mask=x_padding_mask) - y_out = self.enc_dec_forward( - xa, - x_attention_mask, - x_padding_mask, - y_input, - new_y_lens, - y_attention_mask, - y_padding_mask - ) - y_out = y_out[0] # no kv-caching during training - assert y_out.shape == y_input.shape, f"y_out.shape: {y_out.shape}, y_input.shape: {y_input.shape}" # [B S D] - logits = torch.stack([self.predict_layer[i](y_out) for i in range(self.args.n_codebooks)], dim=1) # [B K S card] - assert logits.shape[1] == self.args.n_codebooks and logits.shape[3] == self.n_audio_tokens[0], logits.shape - logits_use = [logit[:, :new_y_lens[i]] for i, logit in enumerate(logits)] # each of shape [K, T, card] - logits_final = [] - for i, logit in enumerate(logits_use): - logit_copy = logit.clone() - for ii in range(self.args.n_codebooks): - logit_copy[ii] = torch.roll(logit_copy[ii], shifts=-ii, dims=0) - logit = logit_copy[:, :-self.args.n_codebooks] # [K, T, card] -> [K, T-n_codebooks, card] - logits_final.append(logit) - if self.args.no_loss_on_prefix: - assert "y_sep_token_position" in batch, f"y_sep_token_position should be in batch, but it's not" - logit_temp = [] - target_temp = [] - for jj, (logit, target) in enumerate(zip(logits_final, targets)): - # TODO already taken into consideration in depth transformer - logit_temp.append(logit[:, batch['y_sep_token_position'][jj]:]) - target_temp.append(target[:, batch['y_sep_token_position'][jj]:]) - logits_final = logit_temp - targets = target_temp - logits = torch.cat(logits_final, dim=1) # [K, T1+T2+T3+..., card] - targets = torch.cat(targets, dim=1) # [K, T1+T2+T3+...] - - assert targets.shape[:2] == logits.shape[:2], f"{targets.shape}, {logits.shape}" - loss = [] - ntokens = [] - top10acc = [] - for k, (logit, target) in enumerate(zip(logits, targets)): # even though the loss and top10acc is calculated in a loop (loop through n_codebooks), validation is still taking a lot of mem, need to optimize this a little more - loss.append(F.cross_entropy(logit, target, reduction='mean', weight=self.class_weight.data if self.args.eog_weight!=1 else None, ignore_index=self.args.y_sep_token if self.args.y_sep_token != None else -100)) # ignore audio sep token as it's unpredictable (like the random early stop bug happened in 2023) - # NOTE have to ignore the sep token in the loss calculation - top10acc.append(self.accuracy_metrics[k](logit.detach(), target)) - ntokens.append(len(logit)) - - all_ntokens = sum(ntokens) - if self.args.codebook_weight != None: - codebook_weight = eval(self.args.codebook_weight) if isinstance(self.args.codebook_weight, str) else self.args.codebook_weight - else: - codebook_weight = [1.] * self.args.n_codebooks - perplexity_by_codebook = [torch.exp(l) for l in loss] - loss = sum([l*nt*cw for l, nt, cw in zip(loss, ntokens, codebook_weight)]) - - top10acc_by_codebook = [t10a*nt for t10a, nt in zip(top10acc, ntokens)] - top10acc = sum(top10acc_by_codebook) - - ntokens = torch.tensor(all_ntokens).to(logits.device) - - ret = { - "loss": loss, - "perplexity_by_codebook": perplexity_by_codebook, - "top10acc": top10acc, - "top10acc_by_codebook": top10acc_by_codebook, - "effective_ntoken": ntokens, - } - - return ret - - def inference_tts( - self, - x: torch.Tensor, - x_lens: torch.Tensor, - y: torch.Tensor, - tgt_y_lens: torch.Tensor, # - top_k: Union[int, list[int]]=-100, - top_p: float=1.0, - min_p: float=1.0, - temperature: float=1.0, - stop_repetition: int=3, - kvcache: int=1, - silence_tokens: list[int]=[], - multi_trial: list[int]=[], - *kargs - ) -> torch.Tensor: - """ - different from inference_tts, this implementation uses kvcache, which should have significant speed up - Args: - x: - A 2-D tensor of shape (1, L). - x_lens: - A 1-D tensor of shape (1,). It contains the number of tokens in `x` - before padding. - y: - A 3-D tensor of shape (1, T, K). - tgt_y_lens: - *new arg* this specify the target length of y - top_k: (`optional`) int - The number of highest probability tokens to keep for top-k-filtering. Default to -100. - top_p: (`optional`) float - For Neucleus sampling - min_p: (`optional`) float - For min_p filtered sampling - temperature: (`optional`) float - The value used to module the next token probabilities. Must be strictly positive. Default to 1.0. - multi_trial: (`optional`) list[int] - If not empty, it will be [n_trials, beam_size, trial_interval] - from the start and begining trial_interval, we duplicate the current sample by beam_size, - at the end of every trial_interval, we choose the sample with the highest log likelihood to keep and throw away the rest - """ - eog_inference = self.args.eos if self.args.eos>0 else self.args.eog - assert x.ndim == 2, x.shape - assert x_lens.ndim == 1, x_lens.shape - assert y.ndim == 3, y.shape - if self.args.special_first: - y = y + int(self.args.n_special) - y = y.transpose(2,1) # [1,T,K] -> [1,K,T] - assert y.shape[0] == 1 and y.shape[1] == self.args.n_codebooks, y.shape # there is no padding - - # make x attention mask and x_input - x_attention_mask = torch.triu(torch.ones(x.shape[1], x.shape[1]), diagonal=1).bool().to(x.device) - # x_attention_mask = torch.zeros(x.shape[1], x.shape[1]).bool().to(x.device) - x_input = self.text_embedding(x) - x_input = self.text_positional_embedding(x_input, x_lens) - - y_len = y.shape[2] - y_lens = torch.LongTensor([y_len]).to(y.device) - - # rearrange y, we don't add eog to the end, this doesn't actually do anything in the tts scenario - rearranged_y = [[y[0]]] - assert rearranged_y[0][0].shape[0] == self.args.n_codebooks, rearranged_y[0][0].shape - - # # shift y to create the delayed pattern - if getattr(self, "empty_tokens", None) == None: - self.empty_tokens = torch.full((self.args.n_codebooks, self.args.n_codebooks), self.args.empty_token, dtype=torch.long).to(y.device) # [K, K] - temp = rearranged_y[0][0] - assert temp.ndim == 2 and temp.shape[0] == self.args.n_codebooks, temp.shape - temp = torch.cat([temp, self.empty_tokens], dim=-1) # [K, T+n_codebooks] - for ii in range(self.args.n_codebooks): - temp[ii] = torch.roll(temp[ii], shifts=ii+1, dims=0) - shifted_y = [[temp]] - - # below is different from forward or inference - # where we cut this shifted part - shifted_y[0][0] = shifted_y[0][0][:, :-(self.args.n_codebooks-1)] - assert not (shifted_y[0][0][self.args.n_codebooks:] == self.args.empty_token).any() and not (shifted_y[0][0][self.args.n_codebooks:] == self.args.eog).any(), shifted_y[0][0] - # next section in inference is insert mask at the intersection of each tensor in a sample, but we don't need to do that - # next section is concate tensors of each sample to one tensor, which we also don't need - cated_y = shifted_y[0][0].unsqueeze(-1) #[K,S]->[K,S,B] - new_y_lens = torch.LongTensor([cated_y.shape[1]]).to(cated_y.device) - assert cated_y.shape == torch.Size((self.args.n_codebooks, cated_y.shape[1], 1)) - assert not (cated_y == self.args.audio_pad_token).any(), cated_y - - # replace tokens in y with the embeddings, add sum codebooks up - embedded_y = torch.stack([self.audio_embedding[k](cated_y[k]) for k in range(self.args.n_codebooks)], dim=0) # [K, S, B, D] - assert embedded_y.shape[0] == self.args.n_codebooks, embedded_y.shape - assert embedded_y.shape[-1] == self.args.d_model, embedded_y.shape - embedded_y = embedded_y.sum(dim=0) # [K,S,B,D]->[S,B,D] - embedded_y = embedded_y.transpose(1,0) # [S,B,D]->[B,S,D] - - # positional embedding - y_input = self.audio_positional_embedding(embedded_y, tgt_y_lens) - - # make attention mask and padding mask - y_attention_mask = torch.triu(torch.ones(y_input.shape[1], y_input.shape[1]), diagonal=1).bool().to(y.device) - - x_padding_mask = torch.full((1,x_lens[0]), False).to(x.device) - y_padding_mask = torch.full((1,new_y_lens[0]), False).to(y.device) - - # entering the generation stage - # starting from line 708 - codebook_eog = [False] * self.args.n_codebooks - generated = [] # doesn't contain any empty token, contain eog - cur_generated = [] - # say 0 is empty, 4 is eog - # tensor([[ 1, 2, 3, 4, 0, 0], - # [ 0, 1, 2, 3, 4, 0], - # [ 0, 0, 1, 2, 3, 4]]) - num_gen = [] - cur_num_gen = 0 - ##################### silence repetition handling ##################### - ##################### silence repetition handling ##################### - # silence_tokens = [1388,1898,131] # [1388, 2045, 2041, 1996] - # silence_tokens = [] - consec_silence_count = 0 - prev_token = None - ##################### silence repetition handling ##################### - ##################### silence repetition handling ##################### - - def sample_helper(n_eog, logits, codebook_eog, top_k, top_p, min_p, temperature, prev_token, consec_silence_count, stop_repetition, silence_tokens, cur_num_gen): - if n_eog == 0: - logits_adjust = logits - for jj in range(1,self.args.n_codebooks): - logits_adjust[jj][eog_inference] = -10000 - logits_adjust[jj][self.args.empty_token] = -10000 - if cur_num_gen <= self.args.encodec_sr // 5: # this shouldn't happen, but just in case the model stopped too early - logits_adjust[0][eog_inference] = -10000 - ##################### silence repetition handling ##################### - if stop_repetition > 0 and prev_token in silence_tokens and consec_silence_count > stop_repetition: - if logits_adjust[0, prev_token] < 0: - logits_adjust[0, prev_token] = logits_adjust[0, prev_token] * (consec_silence_count - (stop_repetition-1)) - else: - logits_adjust[0, prev_token] = logits_adjust[0, prev_token] / (consec_silence_count - (stop_repetition-1)) - ##################### silence repetition handling ##################### - samples = topk_sampling( - logits_adjust, top_k=top_k, top_p=top_p, min_p=min_p, temperature=temperature - ) # [K, 1] - assert samples.shape == torch.Size((self.args.n_codebooks, 1)), f"samples.shape: {samples.shape}" - if cur_num_gen < self.args.n_codebooks-1: - for jj in range(1, self.args.n_codebooks - cur_num_gen): - samples[-jj, 0] = self.args.empty_token - - if ( - samples[0,0] == eog_inference or torch.argmax(logits[0], dim=-1) == eog_inference or y_input.shape[1] > x_lens[0] * (self.args.encodec_sr//4) - ) or self.args.rope_base is not None and not self.args.decoder_regular_rope and self.args.progress_no_multiple and cur_num_gen > (tgt_y_lens[0] + self.args.encodec_sr * getattr(self.args, "extra_cutoff", 5)): - # last one condition in the first bracket means y is already too long, shouldn't happen, but put it here - # the second bracket means we are using progress-monitoring RoPE, but the model is generating excessively long sequence (5 seconds more than specified), in which case we terminate the generation - samples[0,0] = eog_inference - codebook_eog[0] = True - ##################### silence repetition handling ##################### - if samples[0,0] in silence_tokens and samples[0,0] == prev_token: - consec_silence_count += 1 - else: - consec_silence_count = 0 - prev_token = samples[0,0] - ##################### silence repetition handling ##################### - return samples, codebook_eog, prev_token, consec_silence_count - else: - assert sum(codebook_eog[i] for i in range(n_eog)) == n_eog, f"codebook_eog: {codebook_eog}, but n_eog: {n_eog}" - logits_adjust = logits - for jj in range(n_eog+1,self.args.n_codebooks): - logits_adjust[jj][eog_inference] = -10000 - logits_adjust[jj][self.args.empty_token] = -10000 - samples = topk_sampling( - logits_adjust, top_k=top_k, top_p=top_p, min_p=min_p, temperature=temperature - ) # [K, 1] - for jj in range(n_eog): - samples[jj, 0] = self.args.empty_token - samples[n_eog, 0] = eog_inference - codebook_eog[n_eog] = True - return samples, codebook_eog, prev_token, consec_silence_count - - # prepare the cache placeholder - # n_layers, 2, bsz, num_heads, src_len, head_dim, 2 means [key, value] - past = torch.ones([self.args.num_decoder_layers, 2, x.shape[0]], device=x.device, dtype=torch.float32) if kvcache else None - if self.args.enc_dec: - xa = self.encoder(src=x_input, src_key_padding_mask=x_padding_mask) - while True: - if self.args.dec: - y_out, present = self.dec_forward( - x_input, - x_lens, - x_attention_mask, - x_padding_mask, - y_input, - new_y_lens, - y_attention_mask, - y_padding_mask, - past=past - ) - else: - y_out, present = self.enc_dec_forward( - xa, - x_attention_mask, - x_padding_mask, - y_input, - new_y_lens, - y_attention_mask, - y_padding_mask, - tgt_y_lens=tgt_y_lens, - past=past - ) - if past != None: - past = torch.cat([past, present.to(past.dtype)], dim=-2) if past.ndim > 3 else present.to(past.dtype) - - - y_out = y_out[:, -1:] # only take the last token - - logits = torch.stack([self.predict_layer[i](y_out) for i in range(self.args.n_codebooks)], dim=1) # [B K S card], B==S==1, so [1 K 1 card] - logits = logits.squeeze(0).squeeze(1) # [K card] - assert logits.shape == torch.Size((self.args.n_codebooks, self.n_audio_tokens[0])), f"{logits.shape}" - - n_eog = sum(codebook_eog) - assert n_eog < self.args.n_codebooks - if self.args.eos > 0: # if we are using end-of-sentence token (which is used by default), eog shouldn't be used here, as there is no masked spans - for jj in range(self.args.n_codebooks): - logits[jj][self.args.eog] = -10000. - - samples, codebook_eog, prev_token, consec_silence_count = sample_helper(n_eog, logits, codebook_eog, top_k, top_p, min_p, temperature, prev_token, consec_silence_count, stop_repetition, silence_tokens, cur_num_gen) - # samples.shape is [K,1] - # ge samples_emb - samples_emb = torch.stack([self.audio_embedding[k](samples[k]) for k in range(self.args.n_codebooks)], dim=0) # [K,1,D] - samples_emb = samples_emb.sum(dim=0,keepdim=True) # [1,1,D] - - cur_num_gen += 1 - cur_generated.append(samples.squeeze(-1)) # [K,1] -> [K] - - if sum(codebook_eog) == self.args.n_codebooks: # generation for the current span is done - codebook_eog = [False] * self.args.n_codebooks - num_gen.append(cur_num_gen) - cur_num_gen = 0 - generated.append(cur_generated) - cur_generated = [] - break - else: - assert samples_emb.shape == torch.Size((1,1,self.args.d_model)), f"samples_emb.shape: {samples_emb.shape}" - - embedded_y = torch.cat([embedded_y, samples_emb], dim=1) - new_y_lens = torch.LongTensor([embedded_y.shape[1]]).to(y.device) - y_input = self.audio_positional_embedding(embedded_y, tgt_y_lens) # [B T D] - # make attention mask and padding mask - y_attention_mask = torch.triu(torch.ones(y_input.shape[1], y_input.shape[1]), diagonal=1).bool().to(y.device) - y_padding_mask = torch.full((1,new_y_lens[0]), False).to(y.device) - - assert len(generated) == 1, f"len(generated): {len(generated)}" - - # revert the pattern - flatten_gen = [] - for l, orig_span in enumerate(generated): - span = torch.stack(orig_span, dim=0) # [T, K] - span = span.transpose(1,0) # [K, T] - assert span.shape[0] == self.args.n_codebooks, span.shape - unshifted_span = [] - for j, s in enumerate(span): - start_from = j - end_at = - (self.args.n_codebooks - start_from) - unshifted_span.append(s[start_from:end_at]) - unshifted_span = torch.stack(unshifted_span, dim=0) - - assert unshifted_span.shape[1] == num_gen[l] - self.args.n_codebooks, f"len(unshifted_spans[0]): {len(unshifted_span[0])}, num_gen[l]: {num_gen[l]}" - - flatten_gen.append(unshifted_span) - assert len(flatten_gen) == 1, len(flatten_gen) - - # combine - res = [y[0], flatten_gen[0]] - res = torch.cat(res, dim=1).unsqueeze(0) # [K, new_t] -> [1, K, new_T] - expected_y_len = y_len + sum([item - self.args.n_codebooks for item in num_gen]) - assert res.shape == torch.Size((1, self.args.n_codebooks, expected_y_len)), f"res.shape: {res.shape}, expected_y_len: {expected_y_len}. y_len + sum([item - self.args.n_codebooks for item in num_gen]): {y_len} + {sum([item - self.args.n_codebooks for item in num_gen])}" - - if self.args.special_first: - res = res - int(self.args.n_special) - flatten_gen = flatten_gen - int(self.args.n_special) - return res, flatten_gen[0].unsqueeze(0) \ No newline at end of file diff --git a/copy_codebase.py b/scripts/copy_codebase.py similarity index 94% rename from copy_codebase.py rename to scripts/copy_codebase.py index 0bee09d..ea2fcc5 100644 --- a/copy_codebase.py +++ b/scripts/copy_codebase.py @@ -1,8 +1,8 @@ - import os import shutil import fnmatch + def parse_gitignore(gitignore_path): """Parse a .gitignore file and return a list of patterns.""" patterns = [] @@ -16,6 +16,7 @@ def parse_gitignore(gitignore_path): patterns.append(line) return patterns + def file_matches_patterns(file_path, patterns): """Check if a file matches any of the patterns in .gitignore.""" for pattern in patterns: @@ -23,8 +24,9 @@ def file_matches_patterns(file_path, patterns): return True return False + def copy_codebase(src, dst, max_size_mb=5, gitignore_path=None): - """ Copy files from src to dst, skipping files larger than max_size_mb and matching .gitignore patterns. """ + """Copy files from src to dst, skipping files larger than max_size_mb and matching .gitignore patterns.""" if gitignore_path and os.path.exists(gitignore_path): patterns = parse_gitignore(gitignore_path) else: @@ -50,7 +52,6 @@ def copy_codebase(src, dst, max_size_mb=5, gitignore_path=None): print(f"Skipping {file_path} because it's larger than {max_size_mb}MB") continue - # Make sure the destination directory exists os.makedirs(os.path.dirname(dst_path), exist_ok=True) shutil.copy(file_path, dst_path) diff --git a/z_scripts_new/e1_840M_30s.sh b/scripts/e1_840M_30s.sh similarity index 100% rename from z_scripts_new/e1_840M_30s.sh rename to scripts/e1_840M_30s.sh diff --git a/setup.py b/setup.py new file mode 100644 index 0000000..1b4778f --- /dev/null +++ b/setup.py @@ -0,0 +1,47 @@ +from setuptools import setup, find_packages +from voicestar import __version__ + +setup( + name="voicestar", + version=__version__, + description="VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate", + long_description=open("README.md").read(), + long_description_content_type="text/markdown", + url="https://github.com/jasonppy/VoiceStar", + author="Puyuan Peng", + license="MIT", + packages=find_packages(), + install_requires=[ + "torch", + "torchaudio", + "numpy", + "tqdm", + "fire", + "phonemizer", + "torchmetrics", + "einops", + "omegaconf==2.3.0", + "openai-whisper", + "transformers[torch]", + "huggingface_hub", + "gradio", + "click" + ], + extras_require={ + "train": [ + "huggingface_hub", + "datasets", + "tensorboard", + "wandb", + "matplotlib", + "ffmpeg-python", + "scipy", + "soundfile" + ] + }, + entry_points={ + "console_scripts": [ + "voicestar=voicestar.cli:run_inference" + ] + } +) \ No newline at end of file diff --git a/steps/optim.py b/steps/optim.py index 88bd02b..ab1a6b6 100644 --- a/steps/optim.py +++ b/steps/optim.py @@ -80,7 +80,9 @@ def batched_params(self, param_group, group_params_names): list ) # `batches` maps from tuple (dtype_as_str,*shape) to list of str - assert len(param_group) == len(group_params_names), f"len(param_group): {len(param_group)}, len(group_params_names): {len(group_params_names)}" + assert len(param_group) == len( + group_params_names + ), f"len(param_group): {len(param_group)}, len(group_params_names): {len(group_params_names)}" for p, named_p in zip(param_group, group_params_names): key = (str(p.dtype), *p.shape) batches[key].append(p) @@ -90,9 +92,7 @@ def batched_params(self, param_group, group_params_names): sorted_idx = sorted( range(len(batches_names)), key=lambda i: batches_names_keys[i] ) - batches_names = [ - batches_names[batches_names_keys[idx]] for idx in sorted_idx - ] + batches_names = [batches_names[batches_names_keys[idx]] for idx in sorted_idx] batches = [batches[batches_names_keys[idx]] for idx in sorted_idx] stacked_params_dict = dict() @@ -110,10 +110,7 @@ def batched_params(self, param_group, group_params_names): state = self.state[p] p_stacked = torch.stack(batch) grad = torch.stack( - [ - torch.zeros_like(p) if p.grad is None else p.grad - for p in batch - ] + [torch.zeros_like(p) if p.grad is None else p.grad for p in batch] ) p_stacked.grad = grad stacked_params_dict[key] = p_stacked @@ -121,7 +118,7 @@ def batched_params(self, param_group, group_params_names): yield tuples # <-- calling code will do the actual optimization here! - for ((stacked_params, _state, _names), batch) in zip(tuples, batches): + for (stacked_params, _state, _names), batch in zip(tuples, batches): for i, p in enumerate(batch): # batch is list of Parameter p.copy_(stacked_params[i]) @@ -227,13 +224,9 @@ def step(self, closure=None): batch = True - for group, group_params_names in zip( - self.param_groups, self.parameters_names - ): + for group, group_params_names in zip(self.param_groups, self.parameters_names): - with self.batched_params( - group["params"], group_params_names - ) as batches: + with self.batched_params(group["params"], group_params_names) as batches: # batches is list of pairs (stacked_param, state). stacked_param is like # a regular parameter, and will have a .grad, but the 1st dim corresponds to @@ -286,9 +279,7 @@ def _init_state(self, group: dict, p: Tensor, state: dict): # parameter-change "delta", which combines all forms of # update. this is equivalent to how it's done in Adam, # except for the first few steps. - state["delta"] = torch.zeros_like( - p, memory_format=torch.preserve_format - ) + state["delta"] = torch.zeros_like(p, memory_format=torch.preserve_format) batch_size = p.shape[0] numel = p.numel() // batch_size @@ -298,9 +289,7 @@ def _init_state(self, group: dict, p: Tensor, state: dict): # "param_rms" just periodically records the scalar root-mean-square value of # the parameter tensor. # it has a shape like (batch_size, 1, 1, 1, 1) - param_rms = ( - (p ** 2).mean(dim=list(range(1, p.ndim)), keepdim=True).sqrt() - ) + param_rms = (p**2).mean(dim=list(range(1, p.ndim)), keepdim=True).sqrt() state["param_rms"] = param_rms state["scale_exp_avg_sq"] = torch.zeros_like(param_rms) @@ -309,9 +298,7 @@ def _init_state(self, group: dict, p: Tensor, state: dict): ) # exp_avg_sq is the weighted sum of scaled gradients. as in Adam. - state["exp_avg_sq"] = torch.zeros_like( - p, memory_format=torch.preserve_format - ) + state["exp_avg_sq"] = torch.zeros_like(p, memory_format=torch.preserve_format) def _get_clipping_scale( self, group: dict, tuples: List[Tuple[Tensor, dict, List[str]]] @@ -340,16 +327,14 @@ def _get_clipping_scale( clipping_update_period = group["clipping_update_period"] tot_sumsq = torch.tensor(0.0, device=first_p.device) - for (p, state, param_names) in tuples: + for p, state, param_names in tuples: grad = p.grad if grad.is_sparse: raise RuntimeError( "ScaledAdam optimizer does not support sparse gradients" ) if p.numel() == p.shape[0]: # a batch of scalars - tot_sumsq += ( - grad ** 2 - ).sum() # sum() to change shape [1] to [] + tot_sumsq += (grad**2).sum() # sum() to change shape [1] to [] else: tot_sumsq += ((grad * state["param_rms"]) ** 2).sum() @@ -428,11 +413,11 @@ def _show_gradient_dominating_parameter( from tuples, we still pass it to save some time. """ all_sumsq_orig = {} - for (p, state, batch_param_names) in tuples: + for p, state, batch_param_names in tuples: # p is a stacked batch parameters. batch_grad = p.grad if p.numel() == p.shape[0]: # a batch of scalars - batch_sumsq_orig = batch_grad ** 2 + batch_sumsq_orig = batch_grad**2 # Dummpy values used by following `zip` statement. batch_rms_orig = torch.ones(p.shape[0]) else: @@ -510,9 +495,7 @@ def _step_one_batch( if step % size_update_period == size_update_period - 1: param_rms = state["param_rms"] # shape: (batch_size, 1, 1, ..) param_rms.copy_( - (p ** 2) - .mean(dim=list(range(1, p.ndim)), keepdim=True) - .sqrt() + (p**2).mean(dim=list(range(1, p.ndim)), keepdim=True).sqrt() ) if step > 0: # self._size_update() learns the overall scale on the @@ -557,32 +540,23 @@ def _size_update( size_update_period = scale_grads.shape[0] # correct beta2 for the size update period: we will have # faster decay at this level. - beta2_corr = beta2 ** size_update_period + beta2_corr = beta2**size_update_period - scale_exp_avg_sq = state[ - "scale_exp_avg_sq" - ] # shape: (batch_size, 1, 1, ..) + scale_exp_avg_sq = state["scale_exp_avg_sq"] # shape: (batch_size, 1, 1, ..) scale_exp_avg_sq.mul_(beta2_corr).add_( - (scale_grads ** 2).mean( - dim=0 - ), # mean over dim `size_update_period` + (scale_grads**2).mean(dim=0), # mean over dim `size_update_period` alpha=1 - beta2_corr, ) # shape is (batch_size, 1, 1, ...) # The 1st time we reach here is when size_step == 1. size_step = (step + 1) // size_update_period - bias_correction2 = 1 - beta2_corr ** size_step + bias_correction2 = 1 - beta2_corr**size_step # we don't bother with bias_correction1; this will help prevent divergence # at the start of training. denom = scale_exp_avg_sq.sqrt() + eps - scale_step = ( - -size_lr - * (bias_correction2 ** 0.5) - * scale_grads.sum(dim=0) - / denom - ) + scale_step = -size_lr * (bias_correction2**0.5) * scale_grads.sum(dim=0) / denom is_too_small = param_rms < param_min_rms is_too_large = param_rms > param_max_rms @@ -618,9 +592,7 @@ def _step(self, group: dict, p: Tensor, state: dict): exp_avg_sq = state["exp_avg_sq"] exp_avg_sq.mul_(beta2).addcmul_(grad, grad, value=(1 - beta2)) - this_step = state["step"] - ( - state["zero_step"] if "zero_step" in state else 0 - ) + this_step = state["step"] - (state["zero_step"] if "zero_step" in state else 0) bias_correction2 = 1 - beta2 ** (this_step + 1) if bias_correction2 < 0.99: # note: not in-place. @@ -670,9 +642,7 @@ class LRScheduler(object): def __init__(self, optimizer: Optimizer, verbose: bool = False): # Attach optimizer if not isinstance(optimizer, Optimizer): - raise TypeError( - "{} is not an Optimizer".format(type(optimizer).__name__) - ) + raise TypeError("{} is not an Optimizer".format(type(optimizer).__name__)) self.optimizer = optimizer self.verbose = verbose @@ -793,10 +763,9 @@ def __init__( def get_lr(self): factor = ( - (self.batch ** 2 + self.lr_batches ** 2) / self.lr_batches ** 2 + (self.batch**2 + self.lr_batches**2) / self.lr_batches**2 ) ** -0.25 * ( - ((self.epoch ** 2 + self.lr_epochs ** 2) / self.lr_epochs ** 2) - ** -0.25 + ((self.epoch**2 + self.lr_epochs**2) / self.lr_epochs**2) ** -0.25 ) warmup_factor = ( 1.0 @@ -883,17 +852,11 @@ def __init__( if not 0.0 <= eps: raise ValueError("Invalid epsilon value: {}".format(eps)) if not 0.0 <= betas[0] < 1.0: - raise ValueError( - "Invalid beta parameter at index 0: {}".format(betas[0]) - ) + raise ValueError("Invalid beta parameter at index 0: {}".format(betas[0])) if not 0.0 <= betas[1] < 1.0: - raise ValueError( - "Invalid beta parameter at index 1: {}".format(betas[1]) - ) + raise ValueError("Invalid beta parameter at index 1: {}".format(betas[1])) if not 0 <= weight_decay <= 0.1: - raise ValueError( - "Invalid weight_decay value: {}".format(weight_decay) - ) + raise ValueError("Invalid weight_decay value: {}".format(weight_decay)) if not 0 < target_rms <= 10.0: raise ValueError("Invalid target_rms value: {}".format(target_rms)) defaults = dict( @@ -929,9 +892,7 @@ def step(self, closure=None): # Perform optimization step grad = p.grad if grad.is_sparse: - raise RuntimeError( - "AdamW does not support sparse gradients" - ) + raise RuntimeError("AdamW does not support sparse gradients") state = self.state[p] @@ -958,7 +919,7 @@ def step(self, closure=None): # Decay the first and second moment running average coefficient exp_avg.mul_(beta1).add_(grad, alpha=1 - beta1) exp_avg_sq.mul_(beta2).addcmul_(grad, grad, value=1 - beta2) - denom = (exp_avg_sq.sqrt() * (bias_correction2 ** -0.5)).add_( + denom = (exp_avg_sq.sqrt() * (bias_correction2**-0.5)).add_( group["eps"] ) @@ -969,9 +930,7 @@ def step(self, closure=None): if p.numel() > 1: # avoid applying this weight-decay on "scaling factors" # (which are scalar). - is_above_target_rms = p.norm() > ( - target_rms * (p.numel() ** 0.5) - ) + is_above_target_rms = p.norm() > (target_rms * (p.numel() ** 0.5)) p.mul_(1 - (weight_decay * is_above_target_rms)) p.addcdiv_(exp_avg, denom, value=-step_size) @@ -984,6 +943,7 @@ def step(self, closure=None): return loss + def ScaledLinear(*args, initial_scale: float = 1.0, **kwargs) -> nn.Linear: """ Behaves like a constructor of a modified version of nn.Linear @@ -1003,10 +963,10 @@ def ScaledLinear(*args, initial_scale: float = 1.0, **kwargs) -> nn.Linear: with torch.no_grad(): ans.weight[:] *= initial_scale if ans.bias is not None: - torch.nn.init.uniform_( - ans.bias, -0.1 * initial_scale, 0.1 * initial_scale - ) + torch.nn.init.uniform_(ans.bias, -0.1 * initial_scale, 0.1 * initial_scale) return ans + + def _test_scaled_adam(hidden_dim: int): import timeit @@ -1040,8 +1000,7 @@ def _test_scaled_adam(hidden_dim: int): 100.0 * torch.randn(B, T, E, device=device, dtype=dtype) * input_magnitudes, - torch.randn(B, T, E, device=device, dtype=dtype) - * output_magnitudes, + torch.randn(B, T, E, device=device, dtype=dtype) * output_magnitudes, ) for _ in range(20) ] diff --git a/steps/trainer.py b/steps/trainer.py index ee17c64..6f55278 100644 --- a/steps/trainer.py +++ b/steps/trainer.py @@ -1,3 +1,12 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" + import time, sys, subprocess, json, re from pathlib import Path import os, random @@ -14,77 +23,135 @@ import numpy as np from torch.utils.data.distributed import DistributedSampler import logging + # from data import librilight, gigaspeech, gigaspeech_waveform from data import combined_dataset -from models import voice_star - -from .trainer_utils import DistributedDynamicBatchSampler, StatefulDistributedSampler, StatefulSampler, AverageMeter, print_model_info +from voicestar import voicestar as voice_star # legacy compatability TODO: change + +from .trainer_utils import ( + DistributedDynamicBatchSampler, + StatefulDistributedSampler, + StatefulSampler, + AverageMeter, + print_model_info, +) from .optim import ScaledAdam, Eden import run_gen import wandb, socket + class Trainer: - + def __init__(self, args, world_size, rank, local_rank): self.start_time = time.time() self.args = args if self.args.val_max_num_tokens == None: - self.args.val_max_num_tokens = self.args.max_num_tokens + self.args.val_max_num_tokens = self.args.max_num_tokens self.world_size, self.rank, self.local_rank = world_size, rank, local_rank - self.device = torch.device(f"cuda:{local_rank}" if torch.cuda.is_available() else "cpu") + self.device = torch.device( + f"cuda:{local_rank}" if torch.cuda.is_available() else "cpu" + ) if self.rank == 0: self.writer = SummaryWriter(args.exp_dir) - self.wandb = wandb.init(project="voice_editor", name=args.exp_dir.split("/")[-1], config=args, dir=args.exp_dir, entity=self.args.wandb_entity) + self.wandb = wandb.init( + project="voice_editor", + name=args.exp_dir.split("/")[-1], + config=args, + dir=args.exp_dir, + entity=self.args.wandb_entity, + ) self.seed_everything(seed=self.args.seed) self.meters = self._setup_meters() self.progress, self.total_progress = self._setup_progress() - self.model, self.trainables, self.optim_states, self.scheduler_states, self.phn2num = self._setup_models() - - self.train_dataset_length, self.train_sampler, self.train_loader, self.valid_loader = self._setup_dataloader() # both are use DistributedSampler, train sampler is stateful + ( + self.model, + self.trainables, + self.optim_states, + self.scheduler_states, + self.phn2num, + ) = self._setup_models() + + ( + self.train_dataset_length, + self.train_sampler, + self.train_loader, + self.valid_loader, + ) = ( + self._setup_dataloader() + ) # both are use DistributedSampler, train sampler is stateful if self.args.num_steps != None: self.total_step = self.args.num_steps - self.args.num_epochs = math.ceil(self.total_step / math.floor(self.train_dataset_length / self.args.batch_size)) if not self.args.dynamic_batching else None + self.args.num_epochs = ( + math.ceil( + self.total_step + / math.floor(self.train_dataset_length / self.args.batch_size) + ) + if not self.args.dynamic_batching + else None + ) else: - self.total_step = int(math.floor(self.train_dataset_length / self.args.batch_size))*self.args.num_epochs + self.total_step = ( + int(math.floor(self.train_dataset_length / self.args.batch_size)) + * self.args.num_epochs + ) self.optimizer, self.scheduler = self._setup_optimizer() self.scaler = torch.cuda.amp.GradScaler() - self.model = torch.nn.parallel.DistributedDataParallel(self.model, device_ids=[self.local_rank], find_unused_parameters=False) + self.model = torch.nn.parallel.DistributedDataParallel( + self.model, device_ids=[self.local_rank], find_unused_parameters=False + ) self.early_stop_accu_steps = 0 if self.rank == 0: if self.args.dynamic_batching: - logging.info(f"max number of tokens per GPU in a training batch: {self.args.max_num_tokens}, max number of tokens per GPU in a inference batch: {self.args.val_max_num_tokens}") + logging.info( + f"max number of tokens per GPU in a training batch: {self.args.max_num_tokens}, max number of tokens per GPU in a inference batch: {self.args.val_max_num_tokens}" + ) else: logging.info(f"batch size (per gpu): {self.args.batch_size}") - - self.args.inference_every_n_steps = getattr(self.args, "inference_every_n_steps", self.args.val_every_n_steps*5) - assert self.args.inference_every_n_steps > self.args.val_every_n_steps and self.args.inference_every_n_steps % self.args.val_every_n_steps == 0, "inference_every_n_steps should be divisible by val_every_n_steps, otherwise the code will not get a chance to run inference" + + self.args.inference_every_n_steps = getattr( + self.args, "inference_every_n_steps", self.args.val_every_n_steps * 5 + ) + assert ( + self.args.inference_every_n_steps > self.args.val_every_n_steps + and self.args.inference_every_n_steps % self.args.val_every_n_steps == 0 + ), "inference_every_n_steps should be divisible by val_every_n_steps, otherwise the code will not get a chance to run inference" def train(self): flag = True skip_flag = False data_start_time = time.time() - if self.progress['step'] >= self.total_step: + if self.progress["step"] >= self.total_step: if self.rank == 0: self.writer.close() self.wandb.finish() return while flag: - self.train_sampler.set_epoch(self.progress['epoch']) + self.train_sampler.set_epoch(self.progress["epoch"]) for i, batch in enumerate(self.train_loader): - if len(batch['y_lens']) < self.args.gradient_accumulation_steps: + if len(batch["y_lens"]) < self.args.gradient_accumulation_steps: continue data_end_time = time.time() self.model.train() - if self.progress['step'] >= getattr(self.args, "uniform_weight_start_step", 1e50): - if self.progress['step'] == getattr(self.args, "uniform_weight_start_step", 1e50) and self.rank == 0: - logging.info("NOTE: start using uniform weight from step: {}".format(self.progress['step'])) - self.args.codebook_weight = [2.5,2,1.5,0.6] - self.model.module.args.codebook_weight = [2.5,2,1.5,0.6] + if self.progress["step"] >= getattr( + self.args, "uniform_weight_start_step", 1e50 + ): + if ( + self.progress["step"] + == getattr(self.args, "uniform_weight_start_step", 1e50) + and self.rank == 0 + ): + logging.info( + "NOTE: start using uniform weight from step: {}".format( + self.progress["step"] + ) + ) + self.args.codebook_weight = [2.5, 2, 1.5, 0.6] + self.model.module.args.codebook_weight = [2.5, 2, 1.5, 0.6] - if self.progress['step'] >= self.total_step: + if self.progress["step"] >= self.total_step: dist.barrier() flag = False self.validate_and_save() @@ -93,19 +160,26 @@ def train(self): self.wandb.finish() break if isinstance(self.scheduler, Eden): - self.scheduler.step_epoch(self.progress['step']//self.args.pseudo_epoch_size + 1) + self.scheduler.step_epoch( + self.progress["step"] // self.args.pseudo_epoch_size + 1 + ) if self.args.optimizer_name == "ScaledAdam": cur_lr = self.scheduler.get_last_lr()[0] else: - lrs = [param_group['lr'] for param_group in self.optimizer.param_groups] + lrs = [ + param_group["lr"] for param_group in self.optimizer.param_groups + ] assert lrs[0] == lrs[1] cur_lr = lrs[0] - if self.rank == 0 and self.progress['step'] % self.args.tb_write_every_n_steps == 0: - self.writer.add_scalar("train/lr", cur_lr, self.progress['step']) - self.wandb.log({"train/lr": cur_lr}, step=self.progress['step']) + if ( + self.rank == 0 + and self.progress["step"] % self.args.tb_write_every_n_steps == 0 + ): + self.writer.add_scalar("train/lr", cur_lr, self.progress["step"]) + self.wandb.log({"train/lr": cur_lr}, step=self.progress["step"]) - all_inds = list(range(len(batch['y']))) + all_inds = list(range(len(batch["y"]))) sum_losses = 0 sum_top10acc = 0 sum_ntoken = 0 @@ -116,28 +190,45 @@ def train(self): # therefore we re-calculate graduent_accumulation_steps based on the effective batch size if self.args.neighbor_prompt_prob > 0: - effective_batch_size = self.args.max_num_tokens // self.args.gradient_accumulation_steps - total_batch_size = sum(batch['y_lens']).item() - cur_gradient_accumulation_steps = max(self.args.gradient_accumulation_steps, total_batch_size // effective_batch_size) - gas = torch.tensor(cur_gradient_accumulation_steps, dtype=torch.int, device=self.local_rank) + effective_batch_size = ( + self.args.max_num_tokens + // self.args.gradient_accumulation_steps + ) + total_batch_size = sum(batch["y_lens"]).item() + cur_gradient_accumulation_steps = max( + self.args.gradient_accumulation_steps, + total_batch_size // effective_batch_size, + ) + gas = torch.tensor( + cur_gradient_accumulation_steps, + dtype=torch.int, + device=self.local_rank, + ) dist.all_reduce(gas, op=dist.ReduceOp.MAX) cur_gradient_accumulation_steps = gas.item() - len_batch = torch.tensor(len(batch['y']), dtype=torch.int, device=self.local_rank) + len_batch = torch.tensor( + len(batch["y"]), dtype=torch.int, device=self.local_rank + ) dist.all_reduce(len_batch, op=dist.ReduceOp.MIN) len_batch = len_batch.item() - cur_gradient_accumulation_steps = min(cur_gradient_accumulation_steps, len_batch) + cur_gradient_accumulation_steps = min( + cur_gradient_accumulation_steps, len_batch + ) # for those that cur_gradient_accumulation_steps * effective_batch_size < total_batch_size, we only use the first cur_gradient_accumulation_steps * effective_batch_size samples cur_len = 0 final_all_inds = [] pointer = 0 - while cur_len < self.args.max_num_tokens and pointer < len(all_inds): - cur_len += batch['y_lens'][pointer] + while cur_len < self.args.max_num_tokens and pointer < len( + all_inds + ): + cur_len += batch["y_lens"][pointer] final_all_inds.append(all_inds[pointer]) pointer += 1 all_inds = final_all_inds else: - cur_gradient_accumulation_steps = self.args.gradient_accumulation_steps - + cur_gradient_accumulation_steps = ( + self.args.gradient_accumulation_steps + ) sum_losses_local = 0.0 sum_top10acc_local = 0.0 @@ -159,12 +250,12 @@ def train(self): else: precision_used = torch.float32 - with torch.amp.autocast('cuda', dtype=precision_used): + with torch.amp.autocast("cuda", dtype=precision_used): out = self.model(cur_batch, calc_loss=True) if out is None: continue - if torch.isnan(out['loss']).any(): + if torch.isnan(out["loss"]).any(): local_nan_flag = torch.tensor(1, device=self.local_rank) else: local_nan_flag = torch.tensor(0, device=self.local_rank) @@ -174,56 +265,70 @@ def train(self): global_nan_flag = local_nan_flag.item() if global_nan_flag > 0: # Now *all* ranks break at the same j - logging.info(f"rank: {self.rank}. Loss at micro-batch {j} in step {self.progress['step']} was NaN on at least one rank; skipping.") + logging.info( + f"rank: {self.rank}. Loss at micro-batch {j} in step {self.progress['step']} was NaN on at least one rank; skipping." + ) break # Accumulate local values - record_loss = out['loss'].detach() - top10acc = out['top10acc'].detach() - effective_ntoken = out['effective_ntoken'].detach() + record_loss = out["loss"].detach() + top10acc = out["top10acc"].detach() + effective_ntoken = out["effective_ntoken"].detach() sum_losses_local += record_loss.item() sum_top10acc_local += top10acc.item() sum_ntoken_local += effective_ntoken.item() # Optional losses - if 'entropy_loss' in out: - sum_entropy_loss_local += out['entropy_loss'].detach().item() - if 'ctc_loss' in out: - sum_ctc_loss_local += out['ctc_loss'].detach().item() + if "entropy_loss" in out: + sum_entropy_loss_local += out["entropy_loss"].detach().item() + if "ctc_loss" in out: + sum_ctc_loss_local += out["ctc_loss"].detach().item() # Codebook accuracy - if 'top10acc_by_codebook' in out: + if "top10acc_by_codebook" in out: for cb in range(self.args.n_codebooks): - sum_top10acc_cbi_local[cb] += out['top10acc_by_codebook'][cb].detach().item() + sum_top10acc_cbi_local[cb] += ( + out["top10acc_by_codebook"][cb].detach().item() + ) # Backprop on this micro-batch if self.args.optimizer_name == "ScaledAdam": - self.scaler.scale(out['loss']).backward() + self.scaler.scale(out["loss"]).backward() else: - self.scaler.scale(out['loss'] / out['effective_ntoken']).backward() + self.scaler.scale( + out["loss"] / out["effective_ntoken"] + ).backward() if global_nan_flag > 0: # If *any* rank had NaN, skip this step - logging.info(f"rank: {self.rank}. Loss at one micro-batch in step {self.progress['step']} was NaN on at least one rank; skipping.") - self.progress['step'] += 1 - self.progress['cur_step'] += 1 + logging.info( + f"rank: {self.rank}. Loss at one micro-batch in step {self.progress['step']} was NaN on at least one rank; skipping." + ) + self.progress["step"] += 1 + self.progress["cur_step"] += 1 self.optimizer.zero_grad() continue # Otherwise, do one big reduce for the summed metrics - metrics_tensor = torch.tensor([ - sum_losses_local, - sum_top10acc_local, - sum_entropy_loss_local, - sum_ctc_loss_local, - sum_ntoken_local - ], device=self.local_rank, dtype=torch.float32) + metrics_tensor = torch.tensor( + [ + sum_losses_local, + sum_top10acc_local, + sum_entropy_loss_local, + sum_ctc_loss_local, + sum_ntoken_local, + ], + device=self.local_rank, + dtype=torch.float32, + ) dist.all_reduce(metrics_tensor, op=dist.ReduceOp.SUM) # Also reduce the codebook array in one shot if needed - codebook_tensor = torch.tensor(sum_top10acc_cbi_local, device=self.local_rank, dtype=torch.float32) + codebook_tensor = torch.tensor( + sum_top10acc_cbi_local, device=self.local_rank, dtype=torch.float32 + ) dist.all_reduce(codebook_tensor, op=dist.ReduceOp.SUM) # Convert them back to Python scalars @@ -237,166 +342,258 @@ def train(self): if self.args.optimizer_name != "ScaledAdam": self.scaler.unscale_(self.optimizer) - torch.nn.utils.clip_grad_norm_(self.model.parameters(), self.args.gradient_clip_val) + torch.nn.utils.clip_grad_norm_( + self.model.parameters(), self.args.gradient_clip_val + ) self.scaler.step(self.optimizer) self.scaler.update() self.optimizer.zero_grad() if self.args.optimizer_name == "ScaledAdam": - self.scheduler.step_batch(self.progress['step']) + self.scheduler.step_batch(self.progress["step"]) else: self.scheduler.step() - + # logging if self.rank == 0: average_loss = sum_losses / sum_ntoken average_top10acc = sum_top10acc / sum_ntoken - average_top10acc_cbi = [sum_top10acc_cbi[cb] / sum_ntoken * self.args.n_codebooks for cb in range(self.args.n_codebooks)] - self.meters['train_loss'].update(average_loss, batch['x'].shape[0]*self.world_size) - self.meters['train_top10acc'].update(average_top10acc, batch['x'].shape[0]*self.world_size) - self.meters['train_top10acc'].update(average_top10acc, batch['x'].shape[0]*self.world_size) + average_top10acc_cbi = [ + sum_top10acc_cbi[cb] / sum_ntoken * self.args.n_codebooks + for cb in range(self.args.n_codebooks) + ] + self.meters["train_loss"].update( + average_loss, batch["x"].shape[0] * self.world_size + ) + self.meters["train_top10acc"].update( + average_top10acc, batch["x"].shape[0] * self.world_size + ) + self.meters["train_top10acc"].update( + average_top10acc, batch["x"].shape[0] * self.world_size + ) for cb in range(self.args.n_codebooks): - self.meters[f'train_top10acc_cb{cb+1}'].update(average_top10acc_cbi[cb], batch['x'].shape[0]*self.world_size) - self.meters['data_time'].update(data_end_time - data_start_time) - self.meters['train_time'].update(time.time() - data_end_time) + self.meters[f"train_top10acc_cb{cb+1}"].update( + average_top10acc_cbi[cb], + batch["x"].shape[0] * self.world_size, + ) + self.meters["data_time"].update(data_end_time - data_start_time) + self.meters["train_time"].update(time.time() - data_end_time) # log extra losses for key in sum_extra_losses: - if "train_"+key not in self.meters: - self.meters["train_"+key] = AverageMeter() - self.meters["train_"+key].update(sum(sum_extra_losses[key])/len(sum_extra_losses[key]), batch['x'].shape[0]*self.world_size) + if "train_" + key not in self.meters: + self.meters["train_" + key] = AverageMeter() + self.meters["train_" + key].update( + sum(sum_extra_losses[key]) / len(sum_extra_losses[key]), + batch["x"].shape[0] * self.world_size, + ) - if self.progress['step'] % self.args.tb_write_every_n_steps == 0: - self.writer.add_scalar('train/loss', average_loss, self.progress['step']) - self.writer.add_scalar('train/top10acc', average_top10acc, self.progress['step']) - self.writer.add_scalar("train/ntokens", sum_ntoken, self.progress['step']) - self.wandb.log({"train/loss": average_loss, "train/top10acc": average_top10acc, "train/ntokens": sum_ntoken, "train/data_time": data_end_time - data_start_time, "train/train_time": time.time() - data_end_time}, step=self.progress['step']) + if self.progress["step"] % self.args.tb_write_every_n_steps == 0: + self.writer.add_scalar( + "train/loss", average_loss, self.progress["step"] + ) + self.writer.add_scalar( + "train/top10acc", average_top10acc, self.progress["step"] + ) + self.writer.add_scalar( + "train/ntokens", sum_ntoken, self.progress["step"] + ) + self.wandb.log( + { + "train/loss": average_loss, + "train/top10acc": average_top10acc, + "train/ntokens": sum_ntoken, + "train/data_time": data_end_time - data_start_time, + "train/train_time": time.time() - data_end_time, + }, + step=self.progress["step"], + ) for cb in range(self.args.n_codebooks): - self.writer.add_scalar(f'train/top10acc_cb{cb+1}', average_top10acc_cbi[cb], self.progress['step']) - self.wandb.log({f'train/top10acc_cb{cb+1}': average_top10acc_cbi[cb]}, step=self.progress['step']) - self.writer.add_scalar("train/data_time", data_end_time - data_start_time, self.progress['step']) - self.writer.add_scalar("train/train_time", time.time() - data_end_time, self.progress['step']) + self.writer.add_scalar( + f"train/top10acc_cb{cb+1}", + average_top10acc_cbi[cb], + self.progress["step"], + ) + self.wandb.log( + {f"train/top10acc_cb{cb+1}": average_top10acc_cbi[cb]}, + step=self.progress["step"], + ) + self.writer.add_scalar( + "train/data_time", + data_end_time - data_start_time, + self.progress["step"], + ) + self.writer.add_scalar( + "train/train_time", + time.time() - data_end_time, + self.progress["step"], + ) # write extra losses for key in sum_extra_losses: - self.writer.add_scalar(f"train/{key}", sum(sum_extra_losses[key])/len(sum_extra_losses[key]), self.progress['step']) - self.wandb.log({f"train/{key}": sum(sum_extra_losses[key])/len(sum_extra_losses[key])}, step=self.progress['step']) + self.writer.add_scalar( + f"train/{key}", + sum(sum_extra_losses[key]) / len(sum_extra_losses[key]), + self.progress["step"], + ) + self.wandb.log( + { + f"train/{key}": sum(sum_extra_losses[key]) + / len(sum_extra_losses[key]) + }, + step=self.progress["step"], + ) # logging.info(f"ntoken: {sum_ntoken}") - + # logging - if self.progress['step'] % self.args.print_every_n_steps == 0: + if self.progress["step"] % self.args.print_every_n_steps == 0: log_out = {} - log_out['cur_epoch'] = f"{self.progress['epoch']}/{self.args.num_epochs}" if self.args.num_epochs is not None else f"{self.progress['epoch']}" - log_out['cur_step'] = f"{int(self.progress['cur_step']+1)}" - log_out['total_step'] = f"{self.progress['step']}/{self.args.num_steps}" - log_out['lr'] = f"{cur_lr:.7f}" - log_out['ntokens'] = f"{sum_ntoken}" + log_out["cur_epoch"] = ( + f"{self.progress['epoch']}/{self.args.num_epochs}" + if self.args.num_epochs is not None + else f"{self.progress['epoch']}" + ) + log_out["cur_step"] = f"{int(self.progress['cur_step']+1)}" + log_out["total_step"] = ( + f"{self.progress['step']}/{self.args.num_steps}" + ) + log_out["lr"] = f"{cur_lr:.7f}" + log_out["ntokens"] = f"{sum_ntoken}" for key in self.meters: if self.meters[key].val != 0 or self.meters[key].avg != 0: - log_out[key] = f"{self.meters[key].val:.4f} ({self.meters[key].avg:.4f})" if isinstance(self.meters[key].val, float) else f"{self.meters[key].val}" + log_out[key] = ( + f"{self.meters[key].val:.4f} ({self.meters[key].avg:.4f})" + if isinstance(self.meters[key].val, float) + else f"{self.meters[key].val}" + ) logging.info(log_out) - if np.isnan(self.meters['train_loss'].avg): + if np.isnan(self.meters["train_loss"].avg): logging.warning("training diverged...") raise RuntimeError("training diverged...") # save the model only - if self.progress['step'] % self.args.save_every_n_steps == 0: + if self.progress["step"] % self.args.save_every_n_steps == 0: dist.barrier() if self.rank == 0: - save_path = os.path.join(self.args.exp_dir,f"bundle_step{self.progress['step']}.pth") + save_path = os.path.join( + self.args.exp_dir, f"bundle_step{self.progress['step']}.pth" + ) self.save_progress(name=f"step{self.progress['step']}") torch.save( { "model": self.model.module.state_dict(), "args": self.args, "phn2num": self.train_loader.dataset.phn2num, - "optimizer": self.optimizer.state_dict(), + "optimizer": self.optimizer.state_dict(), "scheduler": self.scheduler.state_dict(), - },save_path + }, + save_path, + ) + logging.info( + f"save model, optimizer, scheduler and progress at {save_path} at global step {self.progress['step']}" ) - logging.info(f"save model, optimizer, scheduler and progress at {save_path} at global step {self.progress['step']}") dist.barrier() - + # validation and save models - if self.progress['step'] % self.args.val_every_n_steps == 0: + if self.progress["step"] % self.args.val_every_n_steps == 0: dist.barrier() continue_training = self.validate_and_save() # broadcast continue_training to all processes, so that all processes gets into generation stage - continue_training = torch.tensor(int(continue_training), dtype=torch.int, device=self.local_rank) + continue_training = torch.tensor( + int(continue_training), dtype=torch.int, device=self.local_rank + ) dist.broadcast(continue_training, src=0) continue_training = bool(continue_training.item()) - dist.barrier() # need this to ensure all processes get to the next line? - logging.info(f"rank: {self.rank}, continue_training: {continue_training}") - if not continue_training: + dist.barrier() # need this to ensure all processes get to the next line? + logging.info( + f"rank: {self.rank}, continue_training: {continue_training}" + ) + if not continue_training: if self.rank == 0: self.writer.close() self.wandb.finish() flag = False break - self.progress['step'] += 1 - self.progress['cur_step'] += 1 + self.progress["step"] += 1 + self.progress["cur_step"] += 1 data_start_time = time.time() - self.progress['epoch'] += 1 - self.progress['cur_step'] = 0 # reset cur_step to be 0 + self.progress["epoch"] += 1 + self.progress["cur_step"] = 0 # reset cur_step to be 0 dist.destroy_process_group() def validate_and_save(self): self.model.eval() - + score = self.validate(self.valid_loader) if self.args.early_stop_threshold > 0: - if self.progress['best_score'] - score < self.args.early_stop_threshold: + if self.progress["best_score"] - score < self.args.early_stop_threshold: self.early_stop_accu_steps += self.args.val_every_n_steps - if self.early_stop_accu_steps >= self.args.early_stop_step-1: - logging.info(f"early stop based on self.args.early_stop_threshold: {self.args.early_stop_threshold}, and self.args.early_stop_step: {self.args.early_stop_step}") - logging.info(f"best validation score at step: {self.progress['best_step']}, and the score is {self.progress['best_score']:.4f}") + if self.early_stop_accu_steps >= self.args.early_stop_step - 1: + logging.info( + f"early stop based on self.args.early_stop_threshold: {self.args.early_stop_threshold}, and self.args.early_stop_step: {self.args.early_stop_step}" + ) + logging.info( + f"best validation score at step: {self.progress['best_step']}, and the score is {self.progress['best_score']:.4f}" + ) return False else: self.early_stop_accu_steps = 0 if self.rank == 0: - save_path = os.path.join(self.args.exp_dir,"bundle.pth") + save_path = os.path.join(self.args.exp_dir, "bundle.pth") if os.path.isfile(save_path): os.system(f"mv {save_path} {save_path.replace('.pth', '_prev.pth')}") torch.save( { "model": self.model.module.state_dict(), - "optimizer": self.optimizer.state_dict(), + "optimizer": self.optimizer.state_dict(), "scheduler": self.scheduler.state_dict(), "args": self.args, - "phn2num": self.train_loader.dataset.phn2num - },save_path + "phn2num": self.train_loader.dataset.phn2num, + }, + save_path, ) self.save_progress() - logging.info(f"save models, indices, acc and other statistics at {save_path} and {self.args.exp_dir}/progress.pkl at global step {self.progress['step']}") - if (score < self.progress['best_score']): - self.progress['best_step'] = self.progress['step'] - self.progress['best_score'] = score - save_path = os.path.join(self.args.exp_dir,"best_bundle.pth") + logging.info( + f"save models, indices, acc and other statistics at {save_path} and {self.args.exp_dir}/progress.pkl at global step {self.progress['step']}" + ) + if score < self.progress["best_score"]: + self.progress["best_step"] = self.progress["step"] + self.progress["best_score"] = score + save_path = os.path.join(self.args.exp_dir, "best_bundle.pth") if os.path.isfile(save_path): - os.system(f"mv {save_path} {save_path.replace('.pth', '_prev.pth')}") + os.system( + f"mv {save_path} {save_path.replace('.pth', '_prev.pth')}" + ) torch.save( { "model": self.model.module.state_dict(), - "optimizer": self.optimizer.state_dict(), + "optimizer": self.optimizer.state_dict(), "scheduler": self.scheduler.state_dict(), "args": self.args, - "phn2num": self.train_loader.dataset.phn2num - },save_path + "phn2num": self.train_loader.dataset.phn2num, + }, + save_path, + ) + logging.info( + f"save *best* models at {save_path} at global step {self.progress['step']}" ) - logging.info(f"save *best* models at {save_path} at global step {self.progress['step']}") - + # sync best score and best step, so that all processes early stop at the same time - best_score_tensor = torch.tensor(self.progress['best_score'], device=self.local_rank) + best_score_tensor = torch.tensor( + self.progress["best_score"], device=self.local_rank + ) dist.broadcast(best_score_tensor, src=0) - self.progress['best_score'] = float(best_score_tensor.item()) - best_step_tensor = torch.tensor(self.progress['best_step'], device=self.local_rank) + self.progress["best_score"] = float(best_score_tensor.item()) + best_step_tensor = torch.tensor( + self.progress["best_step"], device=self.local_rank + ) dist.broadcast(best_step_tensor, src=0) - self.progress['best_step'] = int(best_step_tensor.item()) + self.progress["best_step"] = int(best_step_tensor.item()) dist.barrier() return True @@ -419,29 +616,30 @@ def validate(self, valid_loader=None, hide_progress=True): with torch.no_grad(): for i, batch in enumerate(tqdm(valid_loader, disable=hide_progress)): - out = self.model(batch, calc_loss=True) # no reduction is applied to loss - sum_losses += out['loss'] - sum_top10acc += out['top10acc'] - sum_ntoken += out['effective_ntoken'] + out = self.model( + batch, calc_loss=True + ) # no reduction is applied to loss + sum_losses += out["loss"] + sum_top10acc += out["top10acc"] + sum_ntoken += out["effective_ntoken"] if "dur_loss" in out: - sum_dur_loss += out['dur_loss'] - sum_dur_acc += out['dur_acc'] + sum_dur_loss += out["dur_loss"] + sum_dur_acc += out["dur_acc"] if "entropy_loss" in out: - sum_entropy_loss += out['entropy_loss'] + sum_entropy_loss += out["entropy_loss"] if "ctc_loss" in out: - sum_ctc_loss += out['ctc_loss'] + sum_ctc_loss += out["ctc_loss"] # logging.info(f"iter {i}::: {sum_losses}, {sum_top10acc}, {sum_ntoken}") - if 'top10acc_by_codebook' in out: + if "top10acc_by_codebook" in out: for cb in range(self.args.n_codebooks): - sum_top10acc_cbi[cb] += out['top10acc_by_codebook'][cb] - - if 'perplexity_by_codebook' in out: + sum_top10acc_cbi[cb] += out["top10acc_by_codebook"][cb] + + if "perplexity_by_codebook" in out: for cb in range(self.args.n_codebooks): - mean_perplexity_cbi[cb] += out['perplexity_by_codebook'][cb] + mean_perplexity_cbi[cb] += out["perplexity_by_codebook"][cb] # if i > 10: # break - dist.all_reduce(sum_losses, op=dist.ReduceOp.SUM) dist.all_reduce(sum_top10acc, op=dist.ReduceOp.SUM) dist.all_reduce(sum_ntoken, op=dist.ReduceOp.SUM) @@ -453,110 +651,180 @@ def validate(self, valid_loader=None, hide_progress=True): if "ctc_loss" in out: dist.all_reduce(sum_ctc_loss, op=dist.ReduceOp.SUM) - if 'top10acc_by_codebook' in out: + if "top10acc_by_codebook" in out: for cb in range(self.args.n_codebooks): dist.all_reduce(sum_top10acc_cbi[cb], op=dist.ReduceOp.SUM) - - if 'perplexity_by_codebook' in out: + + if "perplexity_by_codebook" in out: for cb in range(self.args.n_codebooks): dist.all_reduce(mean_perplexity_cbi[cb], op=dist.ReduceOp.SUM) - + val_loss = sum_losses / sum_ntoken val_top10acc = sum_top10acc / sum_ntoken - + if self.rank == 0: if "dur_loss" in out: val_dur_loss = sum_dur_loss / sum_ntoken val_dur_acc = sum_dur_acc / sum_ntoken - self.meters['val_dur_loss'].update(val_dur_loss) + self.meters["val_dur_loss"].update(val_dur_loss) logging.info(f"val dur_loss: {val_dur_loss:.5f}") - self.meters['val_dur_acc'].update(val_dur_acc) + self.meters["val_dur_acc"].update(val_dur_acc) logging.info(f"val dur_acc: {val_dur_acc:.5f}") - self.writer.add_scalar("val/dur_loss", val_dur_loss, self.progress['step']) - self.writer.add_scalar("val/dur_acc", val_dur_acc, self.progress['step']) - self.wandb.log({"val/dur_loss": val_dur_loss, "val/dur_acc": val_dur_acc}, step=self.progress['step']) + self.writer.add_scalar( + "val/dur_loss", val_dur_loss, self.progress["step"] + ) + self.writer.add_scalar( + "val/dur_acc", val_dur_acc, self.progress["step"] + ) + self.wandb.log( + {"val/dur_loss": val_dur_loss, "val/dur_acc": val_dur_acc}, + step=self.progress["step"], + ) # logging - self.meters['val_loss'].update(val_loss) + self.meters["val_loss"].update(val_loss) logging.info(f"val loss: {val_loss:.5f}") - self.writer.add_scalar("val/loss", val_loss, self.progress['step']) - self.wandb.log({"val/loss": val_loss}, step=self.progress['step']) + self.writer.add_scalar("val/loss", val_loss, self.progress["step"]) + self.wandb.log({"val/loss": val_loss}, step=self.progress["step"]) - self.meters['val_top10acc'].update(val_top10acc) + self.meters["val_top10acc"].update(val_top10acc) logging.info(f"val top10acc: {val_top10acc:.5f}") - self.writer.add_scalar("val/top10acc", val_top10acc, self.progress['step']) - self.wandb.log({"val/top10acc": val_top10acc}, step=self.progress['step']) + self.writer.add_scalar("val/top10acc", val_top10acc, self.progress["step"]) + self.wandb.log({"val/top10acc": val_top10acc}, step=self.progress["step"]) for cb in range(self.args.n_codebooks): - average_top10acc_cbi = sum_top10acc_cbi[cb] / sum_ntoken * self.args.n_codebooks - self.meters[f'val_top10acc_cb{cb+1}'].update(average_top10acc_cbi) - self.writer.add_scalar(f'val/top10acc_cb{cb+1}', average_top10acc_cbi, self.progress['step']) - self.wandb.log({f'val/top10acc_cb{cb+1}': average_top10acc_cbi}, step=self.progress['step']) - - temp = mean_perplexity_cbi[cb]/len(valid_loader) - self.writer.add_scalar(f'val/perplexity_cb{cb+1}', temp, self.progress['step']) - self.wandb.log({f'val/perplexity_cb{cb+1}': temp}, step=self.progress['step']) - - average_perplexity = sum(mean_perplexity_cbi)/(self.args.n_codebooks*len(valid_loader)) - self.wandb.log({"val/average_perplexity": average_perplexity}, step=self.progress['step']) - self.writer.add_scalar('val/average_perplexity', average_perplexity, self.progress['step']) - + average_top10acc_cbi = ( + sum_top10acc_cbi[cb] / sum_ntoken * self.args.n_codebooks + ) + self.meters[f"val_top10acc_cb{cb+1}"].update(average_top10acc_cbi) + self.writer.add_scalar( + f"val/top10acc_cb{cb+1}", + average_top10acc_cbi, + self.progress["step"], + ) + self.wandb.log( + {f"val/top10acc_cb{cb+1}": average_top10acc_cbi}, + step=self.progress["step"], + ) + + temp = mean_perplexity_cbi[cb] / len(valid_loader) + self.writer.add_scalar( + f"val/perplexity_cb{cb+1}", temp, self.progress["step"] + ) + self.wandb.log( + {f"val/perplexity_cb{cb+1}": temp}, step=self.progress["step"] + ) + + average_perplexity = sum(mean_perplexity_cbi) / ( + self.args.n_codebooks * len(valid_loader) + ) + self.wandb.log( + {"val/average_perplexity": average_perplexity}, + step=self.progress["step"], + ) + self.writer.add_scalar( + "val/average_perplexity", average_perplexity, self.progress["step"] + ) + # log entropy and ctc loss if "entropy_loss" in out: - val_entropy_loss = sum_entropy_loss / ((i+1) * self.world_size) - self.meters['val_entropy_loss'].update(val_entropy_loss) + val_entropy_loss = sum_entropy_loss / ((i + 1) * self.world_size) + self.meters["val_entropy_loss"].update(val_entropy_loss) logging.info(f"val entropy_loss: {val_entropy_loss:.5f}") - self.writer.add_scalar("val/entropy_loss", val_entropy_loss, self.progress['step']) - self.wandb.log({"val/entropy_loss": val_entropy_loss}, step=self.progress['step']) + self.writer.add_scalar( + "val/entropy_loss", val_entropy_loss, self.progress["step"] + ) + self.wandb.log( + {"val/entropy_loss": val_entropy_loss}, step=self.progress["step"] + ) if "ctc_loss" in out: - val_ctc_loss = sum_ctc_loss / ((i+1) * self.world_size) - self.meters['val_ctc_loss'].update(val_ctc_loss) + val_ctc_loss = sum_ctc_loss / ((i + 1) * self.world_size) + self.meters["val_ctc_loss"].update(val_ctc_loss) logging.info(f"val ctc_loss: {val_ctc_loss:.5f}") - self.writer.add_scalar("val/ctc_loss", val_ctc_loss, self.progress['step']) - self.wandb.log({"val/ctc_loss": val_ctc_loss}, step=self.progress['step']) + self.writer.add_scalar( + "val/ctc_loss", val_ctc_loss, self.progress["step"] + ) + self.wandb.log( + {"val/ctc_loss": val_ctc_loss}, step=self.progress["step"] + ) logging.info(f"validation takes: {time.time() - start_val_time:.2f}s") - logging.info(f"Step [{self.progress['step']}/{self.total_step}]\t Time elapsed {(time.time() - self.start_time)/3600.:.2f}h, Val Loss: {val_loss:.4f}, Val Top10Acc: {val_top10acc:.4f}") + logging.info( + f"Step [{self.progress['step']}/{self.total_step}]\t Time elapsed {(time.time() - self.start_time)/3600.:.2f}h, Val Loss: {val_loss:.4f}, Val Top10Acc: {val_top10acc:.4f}" + ) return val_loss.item() def _setup_meters(self): meters = {} - meter_names = ['train_loss', 'val_loss', 'train_top10acc', 'val_top10acc', 'data_time', 'train_time'] - meter_names += ['train_dur_loss', 'train_dur_acc', 'val_dur_loss', 'val_dur_acc'] - meter_names += ['val_perplexity'] - meter_names += [f'train_top10acc_cb{cb+1}' for cb in range(self.args.n_codebooks)] - meter_names += [f'val_top10acc_cb{cb+1}' for cb in range(self.args.n_codebooks)] - meter_names += [f'val_perplexity_cb{cb+1}' for cb in range(self.args.n_codebooks)] + meter_names = [ + "train_loss", + "val_loss", + "train_top10acc", + "val_top10acc", + "data_time", + "train_time", + ] + meter_names += [ + "train_dur_loss", + "train_dur_acc", + "val_dur_loss", + "val_dur_acc", + ] + meter_names += ["val_perplexity"] + meter_names += [ + f"train_top10acc_cb{cb+1}" for cb in range(self.args.n_codebooks) + ] + meter_names += [f"val_top10acc_cb{cb+1}" for cb in range(self.args.n_codebooks)] + meter_names += [ + f"val_perplexity_cb{cb+1}" for cb in range(self.args.n_codebooks) + ] for name in meter_names: meters[name] = AverageMeter() return meters + def _setup_progress(self): """ Need to customize it """ progress = {} - progress['best_step'] = 1 - progress['best_score'] = np.inf # this records loss value - progress['step'] = 1 - progress['epoch'] = 1 - progress['cur_step'] = 0 # step in the current epoch, for resuming the sampler + progress["best_step"] = 1 + progress["best_score"] = np.inf # this records loss value + progress["step"] = 1 + progress["epoch"] = 1 + progress["cur_step"] = 0 # step in the current epoch, for resuming the sampler total_progress = [] # if self.args.resume or self.args.validate: if self.args.resume: progress_pkl = "%s/progress.pkl" % self.args.exp_dir with open(progress_pkl, "rb") as f: total_progress = pickle.load(f) - progress['best_step'], progress['best_score'], progress['step'], progress['epoch'], progress['cur_step'], _ = total_progress[-1] + ( + progress["best_step"], + progress["best_score"], + progress["step"], + progress["epoch"], + progress["cur_step"], + _, + ) = total_progress[-1] if self.rank == 0: logging.info("\nResume training from:") - logging.info(" epoch = %s" % progress['epoch']) - logging.info(" cur_step = %s" % progress['cur_step']) - logging.info(" step = %s" % progress['step']) - logging.info(" best_step = %s" % progress['best_step']) - logging.info(" best_score = %s" % progress['best_score']) + logging.info(" epoch = %s" % progress["epoch"]) + logging.info(" cur_step = %s" % progress["cur_step"]) + logging.info(" step = %s" % progress["step"]) + logging.info(" best_step = %s" % progress["best_step"]) + logging.info(" best_score = %s" % progress["best_score"]) return progress, total_progress - + def save_progress(self, name=None): - self.total_progress.append([self.progress['best_step'], self.progress['best_score'], int(self.progress['step']+1), self.progress['epoch'], int(self.progress['cur_step']+1), time.time() - self.start_time]) + self.total_progress.append( + [ + self.progress["best_step"], + self.progress["best_score"], + int(self.progress["step"] + 1), + self.progress["epoch"], + int(self.progress["cur_step"] + 1), + time.time() - self.start_time, + ] + ) if name is not None: progress_fn = f"{self.args.exp_dir}/progress_{name}.pkl" else: @@ -565,17 +833,60 @@ def save_progress(self, name=None): pickle.dump(self.total_progress, f) def _setup_dataloader(self): - train_dataset, val_dataset = combined_dataset.dataset(self.args, 'train'), combined_dataset.dataset(self.args, 'valid') # need to change 'train' to 'valid' in actual training + train_dataset, val_dataset = combined_dataset.dataset( + self.args, "train" + ), combined_dataset.dataset( + self.args, "valid" + ) # need to change 'train' to 'valid' in actual training if self.args.dynamic_batching: - train_sampler = DistributedDynamicBatchSampler(train_dataset, self.args, num_replicas=self.world_size, rank=self.rank, shuffle=True, seed=self.args.seed, drop_last=True, lengths_list=train_dataset.lengths_list, verbose=True, epoch=0) - valid_sampler = DistributedDynamicBatchSampler(val_dataset, self.args, num_replicas=self.world_size, rank=self.rank, shuffle=True, seed=self.args.seed, drop_last=True, lengths_list=val_dataset.lengths_list, verbose=True, epoch=0) + train_sampler = DistributedDynamicBatchSampler( + train_dataset, + self.args, + num_replicas=self.world_size, + rank=self.rank, + shuffle=True, + seed=self.args.seed, + drop_last=True, + lengths_list=train_dataset.lengths_list, + verbose=True, + epoch=0, + ) + valid_sampler = DistributedDynamicBatchSampler( + val_dataset, + self.args, + num_replicas=self.world_size, + rank=self.rank, + shuffle=True, + seed=self.args.seed, + drop_last=True, + lengths_list=val_dataset.lengths_list, + verbose=True, + epoch=0, + ) else: - train_sampler = StatefulDistributedSampler(train_dataset, self.args.batch_size//self.world_size, num_replicas=self.world_size, rank=self.rank, shuffle=True, seed=self.args.seed, drop_last=True) - valid_sampler = DistributedSampler(val_dataset, num_replicas=self.world_size, rank=self.rank, shuffle=False, seed=self.args.seed, drop_last=False) - - if self.progress['step'] > 1: - train_sampler.set_epoch_resume(self.progress['epoch'], self.progress['cur_step']) + train_sampler = StatefulDistributedSampler( + train_dataset, + self.args.batch_size // self.world_size, + num_replicas=self.world_size, + rank=self.rank, + shuffle=True, + seed=self.args.seed, + drop_last=True, + ) + valid_sampler = DistributedSampler( + val_dataset, + num_replicas=self.world_size, + rank=self.rank, + shuffle=False, + seed=self.args.seed, + drop_last=False, + ) + + if self.progress["step"] > 1: + train_sampler.set_epoch_resume( + self.progress["epoch"], self.progress["cur_step"] + ) assert self.phn2num != None if self.phn2num != None: @@ -583,79 +894,109 @@ def _setup_dataloader(self): val_dataset.phn2num = self.phn2num if self.args.dynamic_batching: - train_loader = torch.utils.data.DataLoader(train_dataset, - batch_sampler=train_sampler, - num_workers=self.args.num_workers, - collate_fn=train_dataset.collate, persistent_workers=True - ) - valid_loader = torch.utils.data.DataLoader(val_dataset, - batch_sampler=valid_sampler, - num_workers=self.args.num_workers, - collate_fn=val_dataset.collate, persistent_workers=True - ) + train_loader = torch.utils.data.DataLoader( + train_dataset, + batch_sampler=train_sampler, + num_workers=self.args.num_workers, + collate_fn=train_dataset.collate, + persistent_workers=True, + ) + valid_loader = torch.utils.data.DataLoader( + val_dataset, + batch_sampler=valid_sampler, + num_workers=self.args.num_workers, + collate_fn=val_dataset.collate, + persistent_workers=True, + ) else: - train_loader = torch.utils.data.DataLoader(train_dataset, - batch_size=self.args.batch_size, sampler=train_sampler, num_workers=self.args.num_workers, - collate_fn=train_dataset.collate, persistent_workers=True - ) - valid_loader = torch.utils.data.DataLoader(val_dataset, - batch_size=self.args.batch_size, sampler=valid_sampler, - num_workers=self.args.num_workers, - collate_fn=val_dataset.collate, persistent_workers=True - ) + train_loader = torch.utils.data.DataLoader( + train_dataset, + batch_size=self.args.batch_size, + sampler=train_sampler, + num_workers=self.args.num_workers, + collate_fn=train_dataset.collate, + persistent_workers=True, + ) + valid_loader = torch.utils.data.DataLoader( + val_dataset, + batch_size=self.args.batch_size, + sampler=valid_sampler, + num_workers=self.args.num_workers, + collate_fn=val_dataset.collate, + persistent_workers=True, + ) return len(train_dataset), train_sampler, train_loader, valid_loader - - def _setup_models(self): - model = voice_star.VoiceStar(self.args) + model = voice_star.VoiceStarModel(self.args) if self.rank == 0: logging.info(model) logging.info("model parameters") print_model_info(model) - + phn2num = None optim_states = None scheduler_states = None - if self.progress['step'] > 1: - bundle = torch.load(os.path.join(self.args.exp_dir, "bundle.pth"), map_location="cpu") - model.load_state_dict(bundle['model']) - optim_states = bundle['optimizer'] - scheduler_states = bundle['scheduler'] - phn2num = bundle['phn2num'] + if self.progress["step"] > 1: + bundle = torch.load( + os.path.join(self.args.exp_dir, "bundle.pth"), map_location="cpu" + ) + model.load_state_dict(bundle["model"]) + optim_states = bundle["optimizer"] + scheduler_states = bundle["scheduler"] + phn2num = bundle["phn2num"] if self.rank == 0: - logging.info("loaded parameters and data indices from epoch %d, global step %d" % (self.progress['epoch'], self.progress['step'])) - del bundle['model'] + logging.info( + "loaded parameters and data indices from epoch %d, global step %d" + % (self.progress["epoch"], self.progress["step"]) + ) + del bundle["model"] - if self.args.load_model_from != None and self.progress['step'] <= 1: + if self.args.load_model_from != None and self.progress["step"] <= 1: logging.info(f"load weights from {self.args.load_model_from}") sd = torch.load(self.args.load_model_from, map_location="cpu") if hasattr(model, "carefully_load_state_dict"): - model.carefully_load_state_dict(sd['model']) + model.carefully_load_state_dict(sd["model"]) else: - model.load_state_dict(sd['model']) - phn2num = sd['phn2num'] + model.load_state_dict(sd["model"]) + phn2num = sd["phn2num"] del sd - #### below operations is for getting params for optimizer, which is at wrapper level ### if self.args.optimizer_name == "ScaledAdam": trainables = [p for p in model.parameters() if p.requires_grad] else: - no_decay = [".bias", ".audio_embeddings.weight", ".text_embeddings.weight", ".norm.weight", ".norm1.weight", ".norm2.weight"] + no_decay = [ + ".bias", + ".audio_embeddings.weight", + ".text_embeddings.weight", + ".norm.weight", + ".norm1.weight", + ".norm2.weight", + ] optimizer_grouped_parameters = [ { - "params": [p for n, p in model.named_parameters() if not any(nd in n for nd in no_decay) and p.requires_grad], + "params": [ + p + for n, p in model.named_parameters() + if not any(nd in n for nd in no_decay) and p.requires_grad + ], "weight_decay": self.args.weight_decay, }, { - "params": [p for n, p in model.named_parameters() if any(nd in n for nd in no_decay) and p.requires_grad], + "params": [ + p + for n, p in model.named_parameters() + if any(nd in n for nd in no_decay) and p.requires_grad + ], "weight_decay": 0.0, }, ] - if len(optimizer_grouped_parameters[1]['params']) == 0: - logging.info("there is no embedding weights, bias, and layernorm parameters in the model, which should be True, check model parameter names") + if len(optimizer_grouped_parameters[1]["params"]) == 0: + logging.info( + "there is no embedding weights, bias, and layernorm parameters in the model, which should be True, check model parameter names" + ) trainables = optimizer_grouped_parameters[0] else: trainables = optimizer_grouped_parameters @@ -664,12 +1005,17 @@ def _setup_models(self): return model, trainables, optim_states, scheduler_states, phn2num - def _setup_optimizer(self): if self.args.optimizer_name == "ScaledAdam": parameters_names = [] - _model = self.model.module if isinstance(self.model, torch.nn.parallel.DistributedDataParallel) else self.model - parameters_names.append([n for n,p in self.model.named_parameters() if p.requires_grad]) + _model = ( + self.model.module + if isinstance(self.model, torch.nn.parallel.DistributedDataParallel) + else self.model + ) + parameters_names.append( + [n for n, p in self.model.named_parameters() if p.requires_grad] + ) optimizer = ScaledAdam( self.trainables, lr=self.args.lr, @@ -679,22 +1025,30 @@ def _setup_optimizer(self): show_dominant_parameters=False, clipping_update_period=self.args.clipping_update_period, ) - scheduler = Eden(optimizer, self.args.reduce_lr_start_step, self.args.reduce_lr_start_epoch, warmup_batches=self.total_step * self.args.warmup_fraction) # NOTE: if using ScaledAdam, we will use the Eden scheduler! + scheduler = Eden( + optimizer, + self.args.reduce_lr_start_step, + self.args.reduce_lr_start_epoch, + warmup_batches=self.total_step * self.args.warmup_fraction, + ) # NOTE: if using ScaledAdam, we will use the Eden scheduler! else: optimizer = AdamW(self.trainables, lr=self.args.lr) warmup_steps = self.total_step * self.args.warmup_fraction + def lr_lambda(current_step: int): if current_step < warmup_steps: return float(current_step) / float(max(1, warmup_steps)) return max( - 0.0, float(self.total_step - current_step) / float(max(1, self.total_step - warmup_steps)) + 0.0, + float(self.total_step - current_step) + / float(max(1, self.total_step - warmup_steps)), ) scheduler = LambdaLR(optimizer, lr_lambda, last_epoch=-1) - + # if resume - if self.progress['step'] > 1: + if self.progress["step"] > 1: optimizer.load_state_dict(self.optim_states) for state in optimizer.state.values(): for k, v in state.items(): @@ -706,12 +1060,12 @@ def lr_lambda(current_step: int): optimizer.zero_grad() return optimizer, scheduler - + def seed_everything(self, seed=1): - os.environ['PYTHONHASHSEED'] = str(seed) + os.environ["PYTHONHASHSEED"] = str(seed) random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) torch.cuda.manual_seed(seed) torch.backends.cudnn.benchmark = False - torch.backends.cudnn.deterministic = True \ No newline at end of file + torch.backends.cudnn.deterministic = True diff --git a/steps/trainer_utils.py b/steps/trainer_utils.py index 51162ec..349770d 100644 --- a/steps/trainer_utils.py +++ b/steps/trainer_utils.py @@ -1,3 +1,11 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" import torch import math @@ -9,8 +17,18 @@ from scipy.stats import lognorm import logging + class StatefulDistributedSampler(Sampler[int]): - def __init__(self, dataset, batch_size, num_replicas = None, rank = None, shuffle = True, seed = 0, drop_last = False): + def __init__( + self, + dataset, + batch_size, + num_replicas=None, + rank=None, + shuffle=True, + seed=0, + drop_last=False, + ): if num_replicas is None: if not dist.is_available(): raise RuntimeError("Requires distributed package to be available") @@ -22,7 +40,8 @@ def __init__(self, dataset, batch_size, num_replicas = None, rank = None, shuffl if rank >= num_replicas or rank < 0: raise ValueError( "Invalid rank {}, rank should be in the interval" - " [0, {}]".format(rank, num_replicas - 1)) + " [0, {}]".format(rank, num_replicas - 1) + ) self.dataset = dataset self.batch_size = batch_size self.num_replicas = num_replicas @@ -45,6 +64,7 @@ def __init__(self, dataset, batch_size, num_replicas = None, rank = None, shuffl self.shuffle = shuffle self.seed = seed self.continue_flag = False + def __len__(self): return self.num_samples @@ -73,25 +93,27 @@ def set_epoch(self, epoch): if padding_size <= len(indices): indices += indices[:padding_size] else: - indices += (indices * math.ceil(padding_size / len(indices)))[:padding_size] + indices += (indices * math.ceil(padding_size / len(indices)))[ + :padding_size + ] else: # remove tail of data to make it evenly divisible. - indices = indices[:self.total_size] + indices = indices[: self.total_size] assert len(indices) == self.total_size # subsample - indices = indices[self.rank:self.total_size:self.num_replicas] + indices = indices[self.rank : self.total_size : self.num_replicas] assert len(indices) == self.num_samples self.indices = indices if self.continue_flag: - self.indices = self.indices[int(self.cur_step*self.batch_size):] + self.indices = self.indices[int(self.cur_step * self.batch_size) :] self.num_samples = len(self.indices) self.continue_flag = False - + def __iter__(self): for idx in self.indices: - yield idx + yield idx def set_epoch_resume(self, epoch, cur_step): self.epoch = epoch @@ -100,7 +122,9 @@ def set_epoch_resume(self, epoch, cur_step): class StatefulSampler(Sampler): - def __init__(self, data_source_length, batch_size, use_random=True, seed=1, epoch=0): + def __init__( + self, data_source_length, batch_size, use_random=True, seed=1, epoch=0 + ): self.use_random = use_random self.data_source_length = data_source_length self.num_samples = self.data_source_length @@ -129,10 +153,10 @@ def set_epoch(self, epoch): self.indices = list(range(self.data_source_length)) # type: ignore[arg-type] if self.continue_flag == True: self.continue_flag = False - self.indices = self.indices[int(self.cur_step*self.batch_size):] - + self.indices = self.indices[int(self.cur_step * self.batch_size) :] + self.num_samples = len(self.indices) - + def set_epoch_resume(self, epoch, cur_step): self.epoch = epoch self.cur_step = cur_step @@ -141,6 +165,7 @@ def set_epoch_resume(self, epoch, cur_step): class AverageMeter: """Computes and stores the average and current value""" + def __init__(self): self.reset() @@ -156,7 +181,8 @@ def update(self, val, n=1): self.count += n self.avg = self.sum / self.count -def print_model_info(model, print_model = False, print_params = True): + +def print_model_info(model, print_model=False, print_params=True): if print_model: logging.info(model) if print_params: @@ -284,11 +310,11 @@ def __init__( self, dataset, args, - num_replicas = None, - rank = None, - shuffle = True, - seed = 0, - drop_last = False, + num_replicas=None, + rank=None, + shuffle=True, + seed=0, + drop_last=False, length_func=lambda x: x["duration"], batch_ordering: str = "random", max_batch_ex: int = None, @@ -309,20 +335,26 @@ def __init__( if rank >= num_replicas or rank < 0: raise ValueError( "Invalid rank {}, rank should be in the interval" - " [0, {}]".format(rank, num_replicas - 1)) + " [0, {}]".format(rank, num_replicas - 1) + ) self.num_replicas = num_replicas self.rank = rank - max_batch_length = self.args.max_num_tokens if dataset.split == "train" else self.args.val_max_num_tokens + max_batch_length = ( + self.args.max_num_tokens + if dataset.split == "train" + else self.args.val_max_num_tokens + ) if type(lengths_list[0]) == float: max_batch_length = float(max_batch_length) / self.args.encodec_sr - logging.info(f"max_num_seconds per GPU for {dataset.split} split: {max_batch_length} seconds") + logging.info( + f"max_num_seconds per GPU for {dataset.split} split: {max_batch_length} seconds" + ) else: - logging.info(f"max_num_tokens per GPU for {dataset.split} split: {max_batch_length}") + logging.info( + f"max_num_tokens per GPU for {dataset.split} split: {max_batch_length}" + ) num_buckets = self.args.num_buckets ############# - - - self._dataset = dataset self._ex_lengths = {} @@ -336,8 +368,14 @@ def __init__( "Check the docs, and/or the tutorial !" ) assert lengths_list != None - max_len = int(self.args.audio_max_length * self.args.encodec_sr) if type(lengths_list[0]) == int else self.args.audio_max_length # if the length is in float, that means it's in seconds, otherwise it's in number of frames - lengths_list = [min(l, max_len) for l in lengths_list] # replace all utt whose length is longer than max_len to max_len, will also do this in __getitem__ in dataset + max_len = ( + int(self.args.audio_max_length * self.args.encodec_sr) + if type(lengths_list[0]) == int + else self.args.audio_max_length + ) # if the length is in float, that means it's in seconds, otherwise it's in number of frames + lengths_list = [ + min(l, max_len) for l in lengths_list + ] # replace all utt whose length is longer than max_len to max_len, will also do this in __getitem__ in dataset for indx in range(len(lengths_list)): self._ex_lengths[str(indx)] = lengths_list[indx] # if lengths_list is not None: @@ -361,9 +399,7 @@ def __init__( "All elements in bucket boundaries should be non-negative (>= 0)." ) if not len(set(bucket_boundaries)) == len(bucket_boundaries): - raise ValueError( - "Bucket_boundaries should not contain duplicates." - ) + raise ValueError("Bucket_boundaries should not contain duplicates.") np.testing.assert_array_equal( np.array(bucket_boundaries), np.array(sorted(bucket_boundaries)), @@ -399,21 +435,29 @@ def __init__( self._generate_batches() self.num_samples = int(math.floor(len(self._batches) / self.num_replicas)) self.total_size = int(self.num_samples * self.num_replicas) - self._replica_batches = self._batches[self.rank:self.total_size:self.num_replicas] - assert len(self._replica_batches) == self.num_samples, f"len(self._batches): {len(self._batches)}, self.total_size: {self.total_size}, self.num_samples: {self.num_samples},len(self._replica_batches): {len(self._replica_batches)}" - logging.info(f"len(self._batches): {len(self._batches)}") # 285773 - logging.info(f"self.total_size: {self.total_size}") # 285768 - logging.info(f"self.num_samples: {self.num_samples}") # 35721 - logging.info(f"len(self._replica_batches): {len(self._replica_batches)}") # 35721 - logging.info(f"self.num_replicas: {self.num_replicas}") # 8 - #logging.info(f"num of batches on each replica: {self.num_samples}") # 35721 + self._replica_batches = self._batches[ + self.rank : self.total_size : self.num_replicas + ] + assert ( + len(self._replica_batches) == self.num_samples + ), f"len(self._batches): {len(self._batches)}, self.total_size: {self.total_size}, self.num_samples: {self.num_samples},len(self._replica_batches): {len(self._replica_batches)}" + logging.info(f"len(self._batches): {len(self._batches)}") # 285773 + logging.info(f"self.total_size: {self.total_size}") # 285768 + logging.info(f"self.num_samples: {self.num_samples}") # 35721 + logging.info( + f"len(self._replica_batches): {len(self._replica_batches)}" + ) # 35721 + logging.info(f"self.num_replicas: {self.num_replicas}") # 8 + # logging.info(f"num of batches on each replica: {self.num_samples}") # 35721 def get_durations(self, batch): """Gets durations of the elements in the batch.""" return [self._ex_lengths[str(idx)] for idx in batch] def _get_boundaries_through_warping( - self, max_batch_length: int, num_quantiles: int, + self, + max_batch_length: int, + num_quantiles: int, ) -> List[int]: # NOTE: the following lines do not cover that there is only one example in the dataset @@ -423,7 +467,9 @@ def _get_boundaries_through_warping( num_boundaries = num_quantiles + 1 # create latent linearly equal spaced buckets latent_boundaries = np.linspace( - 1 / num_boundaries, num_quantiles / num_boundaries, num_quantiles, + 1 / num_boundaries, + num_quantiles / num_boundaries, + num_quantiles, ) # get quantiles using lognormal distribution quantiles = lognorm.ppf(latent_boundaries, 1) @@ -448,7 +494,9 @@ def _permute_batches(self): if self._batch_ordering == "random": # deterministically shuffle based on epoch and seed g = torch.Generator() - g.manual_seed(self._seed + self._epoch) # since the random seed is based on self._seed and self._epoch, it should be the same for different processes when using DDP, and therefore the generated order should be the same across different process, this is important, because each replica will only take a portion of it, we want to make sure they take a non-overlapping portion, and all of them constitute the entire dataset + g.manual_seed( + self._seed + self._epoch + ) # since the random seed is based on self._seed and self._epoch, it should be the same for different processes when using DDP, and therefore the generated order should be the same across different process, this is important, because each replica will only take a portion of it, we want to make sure they take a non-overlapping portion, and all of them constitute the entire dataset sampler = torch.randperm( len(self._batches), generator=g ).tolist() # type: ignore @@ -476,8 +524,10 @@ def _generate_batches(self): if self._shuffle_ex: # deterministically shuffle based on epoch and seed g = torch.Generator() - g.manual_seed(self._seed + self._epoch) # since the random seed is based on self._seed and self._epoch, it should be the same for different processes when using DDP, and therefore the generated order should be the same across different process, this is important, because each replica will only take a portion of it, we want to make sure they take a non-overlapping portion, and all of them constitute the entire dataset - sampler = torch.randperm(len(self._dataset), generator=g).tolist() # type: ignore + g.manual_seed( + self._seed + self._epoch + ) # since the random seed is based on self._seed and self._epoch, it should be the same for different processes when using DDP, and therefore the generated order should be the same across different process, this is important, because each replica will only take a portion of it, we want to make sure they take a non-overlapping portion, and all of them constitute the entire dataset + sampler = torch.randperm(len(self._dataset), generator=g).tolist() # type: ignore # pyp note: this is actually randomly permoted indices else: # take examples as they are: e.g. they have been sorted @@ -530,16 +580,23 @@ def _generate_batches(self): # put the 5 longest batches in the beginning # find 5 longest from self._ex_lengths, which is a dict of lengths, with key being index (in str), and value being length # sort the dict by value, and get the first 5 keys - self._batches = sorted( - self._batches, - key=lambda x: max([self._ex_lengths[str(idx)] for idx in x]), - reverse=True, - )[:5] + self._batches[5:] + self._batches = ( + sorted( + self._batches, + key=lambda x: max([self._ex_lengths[str(idx)] for idx in x]), + reverse=True, + )[:5] + + self._batches[5:] + ) if not dist.is_initialized() or dist.get_rank() == 0: - logging.info(f"replace the first 5 samples in the batch with the 5 longest samples: ") + logging.info( + f"replace the first 5 samples in the batch with the 5 longest samples: " + ) logging.info(f"their lengths: ") for i in range(5): - logging.info(f"{[self._ex_lengths[str(idx)] for idx in self._batches[i]]}") + logging.info( + f"{[self._ex_lengths[str(idx)] for idx in self._batches[i]]}" + ) # frames per batch & their padding remaining boundaries = [0] + self._bucket_boundaries.tolist() @@ -582,18 +639,11 @@ def _generate_batches(self): "pad_%": [], } for batch in self._batches: - tot_frames = sum( - [self._ex_lengths[str(idx)] for idx in batch] - ) + tot_frames = sum([self._ex_lengths[str(idx)] for idx in batch]) batch_stats["tot_frames"].append(tot_frames) - max_frames = max( - [self._ex_lengths[str(idx)] for idx in batch] - ) + max_frames = max([self._ex_lengths[str(idx)] for idx in batch]) tot_pad = sum( - [ - max_frames - self._ex_lengths[str(idx)] - for idx in batch - ] + [max_frames - self._ex_lengths[str(idx)] for idx in batch] ) batch_stats["tot_pad_frames"].append(tot_pad) batch_stats["pad_%"].append(tot_pad / tot_frames * 100) @@ -616,7 +666,6 @@ def __iter__(self): for batch in self._replica_batches: yield batch - # if self._shuffle_ex: # re-generate examples if ex_ordering == "random" # self._generate_batches() # if self._batch_ordering == "random": @@ -630,19 +679,22 @@ def set_epoch(self, epoch): """ self._epoch = epoch self._generate_batches() - self._replica_batches = self._batches[self.rank:self.total_size:self.num_replicas] + self._replica_batches = self._batches[ + self.rank : self.total_size : self.num_replicas + ] self.num_samples = int(math.floor(len(self._batches) / self.num_replicas)) - assert len(self._replica_batches) == self.num_samples, f"len(self._batches): {len(self._batches)}, self.total_size: {self.total_size}, self.num_samples: {self.num_samples},len(self._replica_batches): {len(self._replica_batches)}" + assert ( + len(self._replica_batches) == self.num_samples + ), f"len(self._batches): {len(self._batches)}, self.total_size: {self.total_size}, self.num_samples: {self.num_samples},len(self._replica_batches): {len(self._replica_batches)}" if self.continue_flag: self.continue_flag = False - self._replica_batches = self._replica_batches[self._cur_step:] + self._replica_batches = self._replica_batches[self._cur_step :] self.num_samples = len(self._replica_batches) - def __len__(self): return self.num_samples - + def set_epoch_resume(self, epoch, cur_step): self.continue_flag = True self._epoch = epoch diff --git a/main.py b/train/train.py similarity index 69% rename from main.py rename to train/train.py index 1e5bbe0..add785e 100644 --- a/main.py +++ b/train/train.py @@ -10,29 +10,32 @@ from steps import trainer from copy_codebase import copy_codebase + def world_info_from_env(): local_rank = int(os.environ["LOCAL_RANK"]) global_rank = int(os.environ["RANK"]) world_size = int(os.environ["WORLD_SIZE"]) return local_rank, global_rank, world_size + if __name__ == "__main__": - formatter = ( - "%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d || %(message)s" - ) + formatter = "%(asctime)s [%(levelname)s] %(filename)s:%(lineno)d || %(message)s" logging.basicConfig(format=formatter, level=logging.INFO) - + torch.cuda.empty_cache() args = MyParser().parse_args() exp_dir = Path(args.exp_dir) exp_dir.mkdir(exist_ok=True, parents=True) logging.info(f"exp_dir: {str(exp_dir)}") - if args.resume and (os.path.exists("%s/bundle.pth" % args.exp_dir) or os.path.exists("%s/bundle_prev.pth" % args.exp_dir)): + if args.resume and ( + os.path.exists("%s/bundle.pth" % args.exp_dir) + or os.path.exists("%s/bundle_prev.pth" % args.exp_dir) + ): if not os.path.exists("%s/bundle.pth" % args.exp_dir): os.system(f"cp {args.exp_dir}/bundle_prev.pth {args.exp_dir}/bundle.pth") resume = args.resume - assert(bool(args.exp_dir)) + assert bool(args.exp_dir) with open("%s/args.pkl" % args.exp_dir, "rb") as f: old_args = pickle.load(f) new_args = vars(args) @@ -46,15 +49,17 @@ def world_info_from_env(): args.resume = False with open("%s/args.pkl" % args.exp_dir, "wb") as f: pickle.dump(args, f) - + # make timeout longer (for generation) timeout = datetime.timedelta(seconds=7200) # 60 minutes if args.multinodes: _local_rank, _, _ = world_info_from_env() - dist.init_process_group(backend=args.dist_backend, init_method=args.dist_url, timeout=timeout) + dist.init_process_group( + backend=args.dist_backend, init_method=args.dist_url, timeout=timeout + ) else: - dist.init_process_group(backend='nccl', init_method='env://', timeout=timeout) + dist.init_process_group(backend="nccl", init_method="env://", timeout=timeout) if args.local_wandb: os.environ["WANDB_MODE"] = "offline" @@ -66,8 +71,10 @@ def world_info_from_env(): world_size = dist.get_world_size() local_rank = int(_local_rank) if args.multinodes else rank - num_devices= torch.cuda.device_count() - logging.info(f"{local_rank=}, {rank=}, {world_size=}, {type(local_rank)=}, {type(rank)=}, {type(world_size)=}") + num_devices = torch.cuda.device_count() + logging.info( + f"{local_rank=}, {rank=}, {world_size=}, {type(local_rank)=}, {type(rank)=}, {type(world_size)=}" + ) for device_idx in range(num_devices): device_name = torch.cuda.get_device_name(device_idx) logging.info(f"Device {device_idx}: {device_name}") @@ -76,7 +83,12 @@ def world_info_from_env(): if rank == 0: user_dir = os.path.expanduser("~") codebase_name = "VoiceStar" - now = datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S') - copy_codebase(os.path.join(user_dir, codebase_name), os.path.join(exp_dir, f"{codebase_name}_{now}"), max_size_mb=5, gitignore_path=os.path.join(user_dir, codebase_name, ".gitignore")) + now = datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S") + copy_codebase( + os.path.join(user_dir, codebase_name), + os.path.join(exp_dir, f"{codebase_name}_{now}"), + max_size_mb=5, + gitignore_path=os.path.join(user_dir, codebase_name, ".gitignore"), + ) my_trainer = trainer.Trainer(args, world_size, rank, local_rank) - my_trainer.train() \ No newline at end of file + my_trainer.train() diff --git a/voicestar/__init__.py b/voicestar/__init__.py new file mode 100644 index 0000000..79d8734 --- /dev/null +++ b/voicestar/__init__.py @@ -0,0 +1,202 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" + +__version__ = "0.1.0" + +class VoiceStar: + """ + VoiceStar API - Easy-to-use Python API for VoiceStar model. + + This class provides an easy-to-use interface to the VoiceStar TTS model, + allowing you to generate speech in the voice of a reference audio sample. + + Example: + ```python + from voicestar import VoiceStar + + # Initialize the model (downloads from HF Hub if needed) + tts = VoiceStar(model_name="VoiceStar_840M_30s") + + # Generate speech in the voice of the reference audio + audio = tts.generate( + reference_speech="path/to/reference.wav", + text="This is the text I want to synthesize.", + target_duration=5.0 # Optional: specify desired duration in seconds + ) + + # Save the generated audio + audio.save("output.wav") + ``` + """ + + def __init__( + self, + model_name="VoiceStar_840M_30s", + device=None, + top_k=10, + top_p=1.0, + temperature=1.0, + repeat_prompt=1, + ): + """ + Initialize the VoiceStar TTS model. + + Args: + model_name (str): Model name to use. Options: + - "VoiceStar_840M_30s" (default): 840M parameter model that can generate up to 30s + - "VoiceStar_840M_40s": 840M parameter model that can generate up to 40s + device (str, optional): Device to run inference on. If None, will use CUDA if available, + then MPS (for Apple Silicon), then CPU. + top_k (int): Top-k sampling parameter. Higher values = more diversity. + top_p (float): Top-p sampling parameter (nucleus sampling). + temperature (float): Sampling temperature. Higher values = more diversity. + repeat_prompt (int): Number of times to repeat the prompt to improve speaker similarity. + """ + import os + import torch + from huggingface_hub import hf_hub_download + from argparse import Namespace + import voicestar.voicestar as voice_star + from data.tokenizer import AudioTokenizer, TextTokenizer + from voicestar.api import VoiceStarAPI + + # Set device + if device is None: + self.device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" + else: + self.device = device + + # Download and load model + torch.serialization.add_safe_globals([Namespace]) + ckpt_fn = hf_hub_download(repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth") + + bundle = torch.load(ckpt_fn, map_location=self.device, weights_only=True) + self.args = bundle["args"] + self.phn2num = bundle["phn2num"] + self.model = voice_star.VoiceStarModel(self.args) + self.model.load_state_dict(bundle["model"]) + self.model.to(self.device) + self.model.eval() + + # Load tokenizers + if self.args.n_codebooks == 4: + signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_4cb2048_giga.th") + elif self.args.n_codebooks == 8: + signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_8cb1024_giga.th") + else: + raise ValueError(f"Invalid number of codebooks: {self.args.n_codebooks}") + + self.audio_tokenizer = AudioTokenizer(signature=signature) + self.text_tokenizer = TextTokenizer(backend="espeak") + + # Create API instance + self.api = VoiceStarAPI( + model=self.model, + model_args=self.args, + phn2num=self.phn2num, + text_tokenizer=self.text_tokenizer, + audio_tokenizer=self.audio_tokenizer, + device=self.device, + top_k=top_k, + top_p=top_p, + temperature=temperature, + ) + + # Store parameters + self.repeat_prompt = repeat_prompt + + def generate( + self, + reference_speech, + text, + reference_text=None, + target_duration=None, + output_path=None, + ): + """ + Generate speech in the voice of the reference audio. + + Args: + reference_speech (str): Path to reference speech audio file + text (str): Text to synthesize + reference_text (str, optional): Reference text transcript. If None, will use + Whisper to automatically transcribe the reference speech. + target_duration (float, optional): Target duration in seconds. If None, + will estimate based on reference speech and text length. + output_path (str, optional): If provided, saves the generated audio to this path + + Returns: + AudioSegment: The generated audio (can be saved with .save() method) + """ + import os + import torch + import torchaudio + import whisper + from voicestar.utils import estimate_duration + + # Transcribe reference speech if needed + if reference_text is None: + print("[Info] No reference_text provided, transcribing reference_speech with Whisper.") + wh_model = whisper.load_model("large-v3-turbo") + result = wh_model.transcribe(reference_speech) + reference_text = result["text"] + print(f"[Info] Whisper transcribed text: {reference_text}") + + # Estimate duration if not provided + if target_duration is None: + target_duration = estimate_duration(reference_speech, text) + print(f"[Info] Estimated target duration: {target_duration:.2f} seconds") + + # Get audio info for prompt_end_frame + info = torchaudio.info(reference_speech) + prompt_end_frame = int(100 * info.sample_rate) # 100 seconds max + + # Set delay pattern increment + delay_pattern_increment = self.args.n_codebooks + 1 + + # Generate audio + _, generated_audio = self.api.generate( + audio_fn=reference_speech, + target_text=text, + prompt_end_frame=prompt_end_frame, + target_generation_length=target_duration, + delay_pattern_increment=delay_pattern_increment, + prefix_transcript=reference_text, + repeat_prompt=self.repeat_prompt, + ) + + # Save if output_path provided + if output_path: + os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True) + torchaudio.save(output_path, generated_audio[0].cpu(), 16000) + print(f"[Success] Generated audio saved to {output_path}") + + # Return audio segment for further manipulation + from dataclasses import dataclass + + @dataclass + class AudioSegment: + waveform: torch.Tensor + sample_rate: int = 16000 + + def save(self, path): + """Save audio to file""" + os.makedirs(os.path.dirname(os.path.abspath(path)), exist_ok=True) + torchaudio.save(path, self.waveform.cpu(), self.sample_rate) + return path + + def play(self): + """Play audio (if in notebook environment)""" + try: + from IPython.display import Audio, display + display(Audio(self.waveform.cpu().numpy().T, rate=self.sample_rate)) + except ImportError: + print("Audio playback requires IPython. Use .save() method instead.") + + return AudioSegment(generated_audio[0].cpu()) \ No newline at end of file diff --git a/voicestar/api.py b/voicestar/api.py new file mode 100644 index 0000000..ecc2c31 --- /dev/null +++ b/voicestar/api.py @@ -0,0 +1,380 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" +import argparse, pickle +import logging +import os, random +import numpy as np +import torch +import torchaudio + +from data.tokenizer import AudioTokenizer, TextTokenizer, tokenize_audio, tokenize_text +import argparse, time, tqdm + + +class VoiceStarAPI: + def __init__( + self, + model, + model_args, + phn2num, + text_tokenizer, + audio_tokenizer, + device="cuda", + codec_sr=50, + top_k=0, + top_p=0.8, + min_p=0.0, + temperature=1.0, + stop_repetition=-1, + kvcache=1, + silence_tokens="[1388,1898,131]", + quiet=False, + ): + """ + Initialize the VoiceStar API with model and configuration. + + Args: + model: The VoiceStar model + model_args: Model arguments + phn2num: Phoneme to number mapping + text_tokenizer: Text tokenizer + audio_tokenizer: Audio tokenizer + device: Device to run inference on + codec_sr: Codec sample rate + top_k, top_p, min_p, temperature: Sampling parameters + stop_repetition: Stop generation when token repeats this many times + kvcache: Whether to use KV cache for faster inference + silence_tokens: Tokens representing silence + quiet: Whether to suppress logging + """ + self.model = model + self.model_args = model_args + self.phn2num = phn2num + self.text_tokenizer = text_tokenizer + self.audio_tokenizer = audio_tokenizer + self.device = device + self.quiet = quiet + + # Default decode config + self.decode_config = { + "codec_sr": codec_sr, + "top_k": top_k, + "top_p": top_p, + "min_p": min_p, + "temperature": temperature, + "stop_repetition": stop_repetition, + "kvcache": kvcache, + "silence_tokens": silence_tokens, + "sample_batch_size": 1, + } + + @torch.no_grad() + def generate( + self, + audio_fn, + target_text, + prompt_end_frame, + target_generation_length, + delay_pattern_increment, + prefix_transcript=None, + repeat_prompt=0, + decode_config=None, + multi_trial=[], + ): + """ + Generate speech for the given text using the reference audio. + + Args: + audio_fn: Path to reference audio file + target_text: Text to synthesize + prompt_end_frame: Number of frames to use from reference audio + target_generation_length: Target length of generated audio in seconds + delay_pattern_increment: Delay pattern increment + prefix_transcript: Optional transcript of the reference audio + repeat_prompt: Number of times to repeat the prompt (or "max") + decode_config: Optional custom decoding configuration + multi_trial: List for multi-trial inference (usually empty) + + Returns: + tuple: (concatenated_sample, generated_sample) + """ + # Use custom decode config if provided, otherwise use default + if decode_config is None: + decode_config = self.decode_config + + # encode audio + encoded_frames = tokenize_audio( + self.audio_tokenizer, audio_fn, offset=0, num_frames=prompt_end_frame + ) + single_encoded_frames = encoded_frames + + if isinstance(repeat_prompt, int) and repeat_prompt > 0: + cur_repeat_prompt = repeat_prompt + while cur_repeat_prompt > 0: + encoded_frames = torch.cat([encoded_frames, single_encoded_frames], dim=2) + cur_repeat_prompt -= 1 + elif isinstance(repeat_prompt, str) and repeat_prompt.lower() == "max": + repeat_prompt = 0 + while ( + encoded_frames.shape[2] + + decode_config["codec_sr"] * target_generation_length + + delay_pattern_increment + + single_encoded_frames.shape[2] + < self.model_args.audio_max_length * decode_config["codec_sr"] + ): + encoded_frames = torch.cat([encoded_frames, single_encoded_frames], dim=2) + repeat_prompt += 1 + if getattr(self.model_args, "y_sep_token", None) != None: + encoded_frames = torch.cat( + [ + encoded_frames, + torch.LongTensor([self.model_args.y_sep_token] * self.model_args.n_codebooks) + .unsqueeze(0) + .unsqueeze(2) + .to(encoded_frames.device), + ], + dim=2, + ) + original_audio = encoded_frames.transpose(2, 1) # [1,T,K] + assert ( + original_audio.ndim == 3 + and original_audio.shape[0] == 1 + and original_audio.shape[2] == self.model_args.n_codebooks + ), original_audio.shape + + # phonemize + if isinstance(target_text, list): + text_tokens = [self.phn2num[phn] for phn in target_text if phn in self.phn2num] + else: + text_tokens = [ + self.phn2num[phn] + for phn in tokenize_text(self.text_tokenizer, text=target_text.strip()) + if phn in self.phn2num + ] + if getattr(self.model_args, "x_sep_token", None) != None: + assert ( + prefix_transcript != None + ), "prefix_transcript must be provided if x_sep_token is not None" + if prefix_transcript is not None: + if isinstance(prefix_transcript, list): + prefix_tokens = [ + self.phn2num[phn] for phn in prefix_transcript if phn in self.phn2num + ] + else: + prefix_tokens = [ + self.phn2num[phn] + for phn in tokenize_text(self.text_tokenizer, text=prefix_transcript.strip()) + if phn in self.phn2num + ] + single_prefix_tokens = prefix_tokens + repeat_prompt_count = repeat_prompt + while repeat_prompt_count > 0: + prefix_tokens = prefix_tokens + single_prefix_tokens + repeat_prompt_count -= 1 + if getattr(self.model_args, "x_sep_token", None) != None: + text_tokens = ( + prefix_tokens + [getattr(self.model_args, "x_sep_token", None)] + text_tokens + ) + else: + text_tokens = prefix_tokens + text_tokens + if getattr(self.model_args, "add_eos_to_text", 0) != 0: + text_tokens.append(self.model_args.add_eos_to_text) + if getattr(self.model_args, "add_bos_to_text", 0) != 0: + text_tokens = [self.model_args.add_bos_to_text] + text_tokens + text_tokens = torch.LongTensor(text_tokens).unsqueeze(0) + text_tokens_lens = torch.LongTensor([text_tokens.shape[-1]]) + + if not self.quiet: + logging.info( + f"original audio length: {original_audio.shape[1]} codec frames, which is {original_audio.shape[1]/decode_config['codec_sr']:.2f} sec." + ) + + if getattr(self.model_args, "parallel_pattern", 0) != 0: + tgt_y_lens = torch.LongTensor( + [ + int( + original_audio.shape[1] + + decode_config["codec_sr"] * target_generation_length + + 2 + ) + ] + ) # parallel pattern, therefore only add the empty_token (i.e. the sos token) and eos (i.e. 2 more tokens). Note that the delayed pattern between, both sos and eos is counted (sos is counted in the n_codebooks, eos is counted in the 1) + else: + tgt_y_lens = torch.LongTensor( + [ + int( + original_audio.shape[1] + + decode_config["codec_sr"] * target_generation_length + + delay_pattern_increment + ) + ] + ) # delay pattern increment has accounted for the added eos + + # forward + assert decode_config["sample_batch_size"] <= 1 + stime = time.time() + assert multi_trial == [] + if not self.quiet: + logging.info(f"running inference with batch size 1") + concat_frames, gen_frames = self.model.inference_tts( + text_tokens.to(self.device), + text_tokens_lens.to(self.device), + original_audio[..., : self.model_args.n_codebooks].to(self.device), # [1,T,8] + tgt_y_lens=tgt_y_lens.to(self.device), + top_k=decode_config["top_k"], + top_p=decode_config["top_p"], + min_p=decode_config["min_p"], + temperature=decode_config["temperature"], + stop_repetition=decode_config["stop_repetition"], + kvcache=decode_config["kvcache"], + silence_tokens=( + eval(decode_config["silence_tokens"]) + if type(decode_config["silence_tokens"]) == str + else decode_config["silence_tokens"] + ), + ) # output is [1,K,T] + if not self.quiet: + logging.info(f"inference on one sample take: {time.time() - stime:.4f} sec.") + logging.info( + f"generated encoded_frames.shape: {gen_frames.shape}, which is {gen_frames.shape[-1]/decode_config['codec_sr']} sec." + ) + + if getattr(self.model_args, "y_sep_token", None) != None: + concat_frames = torch.cat( + [ + concat_frames[:, :, : original_audio.shape[1] - 1], + concat_frames[:, :, original_audio.shape[1] :], + ], + dim=2, + ) + # Handle MPS device compatibility + if self.device == "mps": + # Move tensors to CPU before decoding to avoid MPS placeholder storage error + concat_frames = concat_frames.cpu() + gen_frames = gen_frames.cpu() + concat_sample = self.audio_tokenizer.decode(concat_frames) # [1,8,T] + gen_sample = self.audio_tokenizer.decode(gen_frames) + + # Empty cuda cache between runs + if torch.cuda.is_available(): + torch.cuda.empty_cache() + + return concat_sample, gen_sample + + +# this script only works for the musicgen architecture +def get_args(): + parser = argparse.ArgumentParser( + formatter_class=argparse.ArgumentDefaultsHelpFormatter + ) + parser.add_argument("--manifest_fn", type=str, default="path/to/eval_metadata_file") + parser.add_argument("--audio_root", type=str, default="path/to/audio_folder") + parser.add_argument("--exp_dir", type=str, default="path/to/model_folder") + parser.add_argument("--seed", type=int, default=1) + parser.add_argument( + "--codec_audio_sr", + type=int, + default=16000, + help="the sample rate of audio that the codec is trained for", + ) + parser.add_argument( + "--codec_sr", type=int, default=50, help="the sample rate of the codec codes" + ) + parser.add_argument("--top_k", type=int, default=0, help="sampling param") + parser.add_argument("--top_p", type=float, default=0.8, help="sampling param") + parser.add_argument("--temperature", type=float, default=1.0, help="sampling param") + parser.add_argument("--output_dir", type=str, default=None) + parser.add_argument("--device", type=str, default="cuda") + parser.add_argument( + "--signature", type=str, default=None, help="path to the encodec model" + ) + parser.add_argument("--crop_concat", type=int, default=0) + parser.add_argument( + "--stop_repetition", + type=int, + default=-1, + help="used for inference, when the number of consecutive repetition of a token is bigger than this, stop it", + ) + parser.add_argument( + "--kvcache", + type=int, + default=1, + help="if true, use kv cache, which is 4-8x faster than without", + ) + parser.add_argument( + "--sample_batch_size", + type=int, + default=1, + help="batch size for sampling, NOTE that it's not running inference for several samples, but duplicate one input sample batch_size times, and during inference, we only return the shortest generation", + ) + parser.add_argument( + "--silence_tokens", + type=str, + default="[1388,1898,131]", + help="note that if you are not using the pretrained encodec 6f79c6a8, make sure you specified it yourself, rather than using the default", + ) + return parser.parse_args() + + +@torch.no_grad() +def inference_one_sample( + model, + model_args, + phn2num, + text_tokenizer, + audio_tokenizer, + audio_fn, + target_text, + device, + decode_config, + prompt_end_frame, + target_generation_length, + delay_pattern_increment, + prefix_transcript=None, + quiet=False, + repeat_prompt=0, + multi_trial=[], +): + """ + Backward compatibility function that uses the VoiceStarAPI class. + + This function has the same signature as the original inference_one_sample + but internally uses the new VoiceStarAPI class. + """ + # Create API instance + api = VoiceStarAPI( + model=model, + model_args=model_args, + phn2num=phn2num, + text_tokenizer=text_tokenizer, + audio_tokenizer=audio_tokenizer, + device=device, + codec_sr=decode_config.get("codec_sr", 50), + top_k=decode_config.get("top_k", 0), + top_p=decode_config.get("top_p", 0.8), + min_p=decode_config.get("min_p", 0.0), + temperature=decode_config.get("temperature", 1.0), + stop_repetition=decode_config.get("stop_repetition", -1), + kvcache=decode_config.get("kvcache", 1), + silence_tokens=decode_config.get("silence_tokens", "[1388,1898,131]"), + quiet=quiet, + ) + + # Call the generate method + return api.generate( + audio_fn=audio_fn, + target_text=target_text, + prompt_end_frame=prompt_end_frame, + target_generation_length=target_generation_length, + delay_pattern_increment=delay_pattern_increment, + prefix_transcript=prefix_transcript, + repeat_prompt=repeat_prompt, + decode_config=decode_config, + multi_trial=multi_trial, + ) diff --git a/inference_commandline.py b/voicestar/cli.py similarity index 52% rename from inference_commandline.py rename to voicestar/cli.py index a0429d5..75b1e68 100644 --- a/inference_commandline.py +++ b/voicestar/cli.py @@ -4,7 +4,7 @@ import numpy as np import random import whisper -import fire +import click from argparse import Namespace from data.tokenizer import ( @@ -12,91 +12,81 @@ TextTokenizer, ) -from models import voice_star -from inference_tts_utils import inference_one_sample - -############################################################ -# Utility Functions -############################################################ - -def seed_everything(seed=1): - os.environ['PYTHONHASHSEED'] = str(seed) - random.seed(seed) - np.random.seed(seed) - torch.manual_seed(seed) - torch.cuda.manual_seed(seed) - torch.backends.cudnn.benchmark = False - torch.backends.cudnn.deterministic = True +import voicestar.voicestar as voice_star +from voicestar.api import inference_one_sample +from huggingface_hub import hf_hub_download +from transformers import pipeline - -def estimate_duration(ref_audio_path, text): - """ - Estimate duration based on seconds per character from the reference audio. - """ - info = torchaudio.info(ref_audio_path) - audio_duration = info.num_frames / info.sample_rate - length_text = max(len(text), 1) - spc = audio_duration / length_text # seconds per character - return len(text) * spc +from voicestar.utils import seed_everything, estimate_duration ############################################################ # Main Inference Function ############################################################ +@click.command() +@click.option('--reference-speech', default="./demo/5895_34622_000026_000002.wav", help="Path to reference speech audio file") +@click.option('--target-text', default="I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long.", help="Text to synthesize") +@click.option('--model-name', default="VoiceStar_840M_30s", help="Model name (VoiceStar_840M_30s or VoiceStar_840M_40s)") +@click.option('--reference-text', default=None, help="Reference text (if None, will use Whisper to transcribe)") +@click.option('--target-duration', default=None, type=float, help="Target duration in seconds (if None, will estimate)") +@click.option('--codec-audio-sr', default=16000, help="Codec audio sample rate (do not change)") +@click.option('--codec-sr', default=50, help="Codec sample rate (do not change)") +@click.option('--top-k', default=10, help="Top-k sampling parameter (try 10, 20, 30, 40)") +@click.option('--top-p', default=1.0, help="Top-p sampling parameter (do not change)") +@click.option('--min-p', default=1.0, help="Min-p sampling parameter (do not change)") +@click.option('--temperature', default=1.0, help="Sampling temperature") +@click.option('--kvcache', default=1, help="Use KV cache (set to 0 if OOM)") +@click.option('--repeat-prompt', default=1, help="Repeat prompt to improve speaker similarity") +@click.option('--stop-repetition', default=3, help="Stop repetition parameter (will not use it)") +@click.option('--sample-batch-size', default=1, help="Sample batch size (do not change)") +@click.option('--seed', default=1, help="Random seed") +@click.option('--output-dir', default="./generated_tts", help="Output directory") +@click.option('--cut-off-sec', default=100, help="Cut-off seconds (do not adjust)") def run_inference( - reference_speech="./demo/5895_34622_000026_000002.wav", - target_text="I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long.", - # Model - model_name="VoiceStar_840M_30s", # or VoiceStar_840M_40s, the later model is trained on maximally 40s long speech - model_root="./pretrained", - # Additional optional - reference_text=None, # if None => run whisper on reference_speech - target_duration=None, # if None => estimate from reference_speech and target_text - # Default hyperparameters from snippet - codec_audio_sr=16000, # do not change - codec_sr=50, # do not change - top_k=10, # try 10, 20, 30, 40 - top_p=1, # do not change - min_p=1, # do not change - temperature=1, - silence_tokens=None, # do not change it - kvcache=1, # if OOM, set to 0 - multi_trial=None, # do not change it - repeat_prompt=1, # increase this to improve speaker similarity, but it reference speech duration in total adding target duration is longer than maximal training duration, quality may drop - stop_repetition=3, # will not use it - sample_batch_size=1, # do not change - # Others - seed=1, - output_dir="./generated_tts", - # Some snippet-based defaults - cut_off_sec=100, # do not adjust this, we always use the entire reference speech. If you wish to change, also make sure to change the reference_transcript, so that it's only the trasnscript of the speech remained + reference_speech, + target_text, + model_name, + reference_text, + target_duration, + codec_audio_sr, + codec_sr, + top_k, + top_p, + min_p, + temperature, + kvcache, + repeat_prompt, + stop_repetition, + sample_batch_size, + seed, + output_dir, + cut_off_sec, ): """ - Inference script using Fire. + VoiceStar TTS inference CLI. Example: - python inference_commandline.py \ - --reference_speech "./demo/5895_34622_000026_000002.wav" \ - --target_text "I cannot believe ... this audio is 10 seconds long." \ - --reference_text "(optional) text to use as prefix" \ - --target_duration (optional float) + voicestar --reference-speech "./demo/5895_34622_000026_000002.wav" \ + --target-text "I cannot believe ... this audio is 10 seconds long." \ + --reference-text "Optional text to use as prefix" \ + --target-duration 10.0 """ + # Default values for parameters not exposed in click options + silence_tokens = None + multi_trial = None # Seed everything seed_everything(seed) # Load model, phn2num, and args torch.serialization.add_safe_globals([Namespace]) - device = "cuda" if torch.cuda.is_available() else "cpu" - ckpt_fn = os.path.join(model_root, model_name+".pth") - if not os.path.exists(ckpt_fn): - # use wget to download - print(f"[Info] Downloading {model_name} checkpoint...") - os.system(f"wget https://huggingface.co/pyp1/VoiceStar/resolve/main/{model_name}.pth?download=true -O {ckpt_fn}") + device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" # MPS support + ckpt_fn = hf_hub_download(repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth") + bundle = torch.load(ckpt_fn, map_location=device, weights_only=True) args = bundle["args"] phn2num = bundle["phn2num"] - model = voice_star.VoiceStar(args) + model = voice_star.VoiceStarModel(args) model.load_state_dict(bundle["model"]) model.to(device) model.eval() @@ -120,12 +110,15 @@ def run_inference( # signature from snippet if args.n_codebooks == 4: - signature = "./pretrained/encodec_6f79c6a8.th" + # signature = "./pretrained/encodec_6f79c6a8.th" + signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_4cb2048_giga.th") # not sure if this is the right signature elif args.n_codebooks == 8: - signature = "./pretrained/encodec_8cb1024_giga.th" + signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_8cb1024_giga.th") else: # fallback, just use the 6-f79c6a8 - signature = "./pretrained/encodec_6f79c6a8.th" + raise ValueError(f"Invalid number of codebooks: {args.n_codebooks}") + # not sure where to download 6-f79c6a8 from + # signature = "./pretrained/encodec_6f79c6a8.th" if silence_tokens is None: # default from snippet @@ -186,7 +179,7 @@ def run_inference( def main(): - fire.Fire(run_inference) + run_inference() if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/models/modules/__init__.py b/voicestar/data/__init__.py similarity index 100% rename from models/modules/__init__.py rename to voicestar/data/__init__.py diff --git a/voicestar/data/encodec.py b/voicestar/data/encodec.py new file mode 100644 index 0000000..fdb9267 --- /dev/null +++ b/voicestar/data/encodec.py @@ -0,0 +1,1842 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# All rights reserved. +# +# This source code is licensed under the license found in the +# LICENSE file in the root directory of this source tree. +"""Compression models or wrapper around existing models. +Also defines the main interface that a model must follow to be usable as an audio tokenizer. +""" + +from abc import ABC, abstractmethod +from dataclasses import dataclass, field +import logging +import math +from pathlib import Path +import typing as tp + +import numpy as np +import torch +from torch import nn +from torch import einsum +import torch.nn.functional as F +from torch.nn.utils import spectral_norm, weight_norm + +import logging +import warnings +from einops import rearrange, repeat +import omegaconf + +# import flashy + +CONV_NORMALIZATIONS = frozenset( + ["none", "weight_norm", "spectral_norm", "time_group_norm"] +) + + +def dict_from_config(cfg: omegaconf.DictConfig) -> dict: + """Convenience function to map an omegaconf configuration to a dictionary. + + Args: + cfg (omegaconf.DictConfig): Original configuration to map to dict. + Returns: + dict: Config as dictionary object. + """ + dct = omegaconf.OmegaConf.to_container(cfg, resolve=True) + assert isinstance(dct, dict) + return dct + + +@dataclass +class QuantizedResult: + x: torch.Tensor + codes: torch.Tensor + bandwidth: torch.Tensor # bandwidth in kb/s used, per batch item. + penalty: tp.Optional[torch.Tensor] = None + metrics: dict = field(default_factory=dict) + + +class BaseQuantizer(nn.Module): + """Base class for quantizers.""" + + def forward(self, x: torch.Tensor, frame_rate: int) -> QuantizedResult: + """ + Given input tensor x, returns first the quantized (or approximately quantized) + representation along with quantized codes, bandwidth, and any penalty term for the loss. + Finally, this returns a dict of metrics to update logging etc. + Frame rate must be passed so that the bandwidth is properly computed. + """ + raise NotImplementedError() + + def encode(self, x: torch.Tensor) -> torch.Tensor: + """Encode a given input tensor with the specified sample rate at the given bandwidth.""" + raise NotImplementedError() + + def decode(self, codes: torch.Tensor) -> torch.Tensor: + """Decode the given codes to the quantized representation.""" + raise NotImplementedError() + + @property + def total_codebooks(self): + """Total number of codebooks.""" + raise NotImplementedError() + + @property + def num_codebooks(self): + """Number of active codebooks.""" + raise NotImplementedError() + + def set_num_codebooks(self, n: int): + """Set the number of active codebooks.""" + raise NotImplementedError() + + +class CompressionModel(ABC, nn.Module): + """Base API for all compression model that aim at being used as audio tokenizers + with a language model. + """ + + @abstractmethod + def forward(self, x: torch.Tensor) -> QuantizedResult: ... + + @abstractmethod + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + """See `EncodecModel.encode`.""" + ... + + @abstractmethod + def decode(self, codes: torch.Tensor, scale: tp.Optional[torch.Tensor] = None): + """See `EncodecModel.decode`.""" + ... + + @abstractmethod + def decode_latent(self, codes: torch.Tensor): + """Decode from the discrete codes to continuous latent space.""" + ... + + @property + @abstractmethod + def channels(self) -> int: ... + + @property + @abstractmethod + def frame_rate(self) -> float: ... + + @property + @abstractmethod + def sample_rate(self) -> int: ... + + @property + @abstractmethod + def cardinality(self) -> int: ... + + @property + @abstractmethod + def num_codebooks(self) -> int: ... + + @property + @abstractmethod + def total_codebooks(self) -> int: ... + + @abstractmethod + def set_num_codebooks(self, n: int): + """Set the active number of codebooks used by the quantizer.""" + ... + + +def apply_parametrization_norm(module: nn.Module, norm: str = "none"): + assert norm in CONV_NORMALIZATIONS + if norm == "weight_norm": + return weight_norm(module) + elif norm == "spectral_norm": + return spectral_norm(module) + else: + # We already check was in CONV_NORMALIZATION, so any other choice + # doesn't need reparametrization. + return module + + +def get_norm_module( + module: nn.Module, causal: bool = False, norm: str = "none", **norm_kwargs +): + """Return the proper normalization module. If causal is True, this will ensure the returned + module is causal, or return an error if the normalization doesn't support causal evaluation. + """ + assert norm in CONV_NORMALIZATIONS + if norm == "time_group_norm": + if causal: + raise ValueError("GroupNorm doesn't support causal evaluation.") + assert isinstance(module, nn.modules.conv._ConvNd) + return nn.GroupNorm(1, module.out_channels, **norm_kwargs) + else: + return nn.Identity() + + +def get_extra_padding_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +) -> int: + """See `pad_for_conv1d`.""" + length = x.shape[-1] + n_frames = (length - kernel_size + padding_total) / stride + 1 + ideal_length = (math.ceil(n_frames) - 1) * stride + (kernel_size - padding_total) + return ideal_length - length + + +def pad_for_conv1d( + x: torch.Tensor, kernel_size: int, stride: int, padding_total: int = 0 +): + """Pad for a convolution to make sure that the last window is full. + Extra padding is added at the end. This is required to ensure that we can rebuild + an output of the same length, as otherwise, even with padding, some time steps + might get removed. + For instance, with total padding = 4, kernel size = 4, stride = 2: + 0 0 1 2 3 4 5 0 0 # (0s are padding) + 1 2 3 # (output frames of a convolution, last 0 is never used) + 0 0 1 2 3 4 5 0 # (output of tr. conv., but pos. 5 is going to get removed as padding) + 1 2 3 4 # once you removed padding, we are missing one time step ! + """ + extra_padding = get_extra_padding_for_conv1d(x, kernel_size, stride, padding_total) + return F.pad(x, (0, extra_padding)) + + +def pad1d( + x: torch.Tensor, + paddings: tp.Tuple[int, int], + mode: str = "constant", + value: float = 0.0, +): + """Tiny wrapper around F.pad, just to allow for reflect padding on small input. + If this is the case, we insert extra 0 padding to the right before the reflection happen. + """ + length = x.shape[-1] + padding_left, padding_right = paddings + assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) + if mode == "reflect": + max_pad = max(padding_left, padding_right) + extra_pad = 0 + if length <= max_pad: + extra_pad = max_pad - length + 1 + x = F.pad(x, (0, extra_pad)) + padded = F.pad(x, paddings, mode, value) + end = padded.shape[-1] - extra_pad + return padded[..., :end] + else: + return F.pad(x, paddings, mode, value) + + +def unpad1d(x: torch.Tensor, paddings: tp.Tuple[int, int]): + """Remove padding from x, handling properly zero padding. Only for 1d!""" + padding_left, padding_right = paddings + assert padding_left >= 0 and padding_right >= 0, (padding_left, padding_right) + assert (padding_left + padding_right) <= x.shape[-1] + end = x.shape[-1] - padding_right + return x[..., padding_left:end] + + +class NormConv1d(nn.Module): + """Wrapper around Conv1d and normalization applied to this conv + to provide a uniform interface across normalization approaches. + """ + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): + super().__init__() + self.conv = apply_parametrization_norm(nn.Conv1d(*args, **kwargs), norm) + self.norm = get_norm_module(self.conv, causal, norm, **norm_kwargs) + self.norm_type = norm + + def forward(self, x): + x = self.conv(x) + x = self.norm(x) + return x + + +class NormConv2d(nn.Module): + """Wrapper around Conv2d and normalization applied to this conv + to provide a uniform interface across normalization approaches. + """ + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): + super().__init__() + self.conv = apply_parametrization_norm(nn.Conv2d(*args, **kwargs), norm) + self.norm = get_norm_module(self.conv, causal=False, norm=norm, **norm_kwargs) + self.norm_type = norm + + def forward(self, x): + x = self.conv(x) + x = self.norm(x) + return x + + +class NormConvTranspose1d(nn.Module): + """Wrapper around ConvTranspose1d and normalization applied to this conv + to provide a uniform interface across normalization approaches. + """ + + def __init__( + self, + *args, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): + super().__init__() + self.convtr = apply_parametrization_norm( + nn.ConvTranspose1d(*args, **kwargs), norm + ) + self.norm = get_norm_module(self.convtr, causal, norm, **norm_kwargs) + self.norm_type = norm + + def forward(self, x): + x = self.convtr(x) + x = self.norm(x) + return x + + +class NormConvTranspose2d(nn.Module): + """Wrapper around ConvTranspose2d and normalization applied to this conv + to provide a uniform interface across normalization approaches. + """ + + def __init__( + self, + *args, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + **kwargs, + ): + super().__init__() + self.convtr = apply_parametrization_norm( + nn.ConvTranspose2d(*args, **kwargs), norm + ) + self.norm = get_norm_module(self.convtr, causal=False, norm=norm, **norm_kwargs) + + def forward(self, x): + x = self.convtr(x) + x = self.norm(x) + return x + + +class StreamableConv1d(nn.Module): + """Conv1d with some builtin handling of asymmetric or causal padding + and normalization. + """ + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + dilation: int = 1, + groups: int = 1, + bias: bool = True, + causal: bool = False, + norm: str = "none", + norm_kwargs: tp.Dict[str, tp.Any] = {}, + pad_mode: str = "reflect", + ): + super().__init__() + # warn user on unusual setup between dilation and stride + if stride > 1 and dilation > 1: + warnings.warn( + "StreamableConv1d has been initialized with stride > 1 and dilation > 1" + f" (kernel_size={kernel_size} stride={stride}, dilation={dilation})." + ) + self.conv = NormConv1d( + in_channels, + out_channels, + kernel_size, + stride, + dilation=dilation, + groups=groups, + bias=bias, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) + self.causal = causal + self.pad_mode = pad_mode + + def forward(self, x): + B, C, T = x.shape + kernel_size = self.conv.conv.kernel_size[0] + stride = self.conv.conv.stride[0] + dilation = self.conv.conv.dilation[0] + kernel_size = ( + kernel_size - 1 + ) * dilation + 1 # effective kernel size with dilations + padding_total = kernel_size - stride + extra_padding = get_extra_padding_for_conv1d( + x, kernel_size, stride, padding_total + ) + if self.causal: + # Left padding for causal + x = pad1d(x, (padding_total, extra_padding), mode=self.pad_mode) + else: + # Asymmetric padding required for odd strides + padding_right = padding_total // 2 + padding_left = padding_total - padding_right + x = pad1d( + x, (padding_left, padding_right + extra_padding), mode=self.pad_mode + ) + return self.conv(x) + + +class StreamableConvTranspose1d(nn.Module): + """ConvTranspose1d with some builtin handling of asymmetric or causal padding + and normalization. + """ + + def __init__( + self, + in_channels: int, + out_channels: int, + kernel_size: int, + stride: int = 1, + causal: bool = False, + norm: str = "none", + trim_right_ratio: float = 1.0, + norm_kwargs: tp.Dict[str, tp.Any] = {}, + ): + super().__init__() + self.convtr = NormConvTranspose1d( + in_channels, + out_channels, + kernel_size, + stride, + causal=causal, + norm=norm, + norm_kwargs=norm_kwargs, + ) + self.causal = causal + self.trim_right_ratio = trim_right_ratio + assert ( + self.causal or self.trim_right_ratio == 1.0 + ), "`trim_right_ratio` != 1.0 only makes sense for causal convolutions" + assert self.trim_right_ratio >= 0.0 and self.trim_right_ratio <= 1.0 + + def forward(self, x): + kernel_size = self.convtr.convtr.kernel_size[0] + stride = self.convtr.convtr.stride[0] + padding_total = kernel_size - stride + + y = self.convtr(x) + + # We will only trim fixed padding. Extra padding from `pad_for_conv1d` would be + # removed at the very end, when keeping only the right length for the output, + # as removing it here would require also passing the length at the matching layer + # in the encoder. + if self.causal: + # Trim the padding on the right according to the specified ratio + # if trim_right_ratio = 1.0, trim everything from right + padding_right = math.ceil(padding_total * self.trim_right_ratio) + padding_left = padding_total - padding_right + y = unpad1d(y, (padding_left, padding_right)) + else: + # Asymmetric padding required for odd strides + padding_right = padding_total // 2 + padding_left = padding_total - padding_right + y = unpad1d(y, (padding_left, padding_right)) + return y + + +class StreamableLSTM(nn.Module): + """LSTM without worrying about the hidden state, nor the layout of the data. + Expects input as convolutional layout. + """ + + def __init__(self, dimension: int, num_layers: int = 2, skip: bool = True): + super().__init__() + self.skip = skip + self.lstm = nn.LSTM(dimension, dimension, num_layers) + + def forward(self, x): + x = x.permute(2, 0, 1) + y, _ = self.lstm(x) + if self.skip: + y = y + x + y = y.permute(1, 2, 0) + return y + + +class SEANetResnetBlock(nn.Module): + """Residual block from SEANet model. + + Args: + dim (int): Dimension of the input/output. + kernel_sizes (list): List of kernel sizes for the convolutions. + dilations (list): List of dilations for the convolutions. + activation (str): Activation function. + activation_params (dict): Parameters to provide to the activation function. + norm (str): Normalization method. + norm_params (dict): Parameters to provide to the underlying normalization used along with the convolution. + causal (bool): Whether to use fully causal convolution. + pad_mode (str): Padding mode for the convolutions. + compress (int): Reduced dimensionality in residual branches (from Demucs v3). + true_skip (bool): Whether to use true skip connection or a simple + (streamable) convolution as the skip connection. + """ + + def __init__( + self, + dim: int, + kernel_sizes: tp.List[int] = [3, 1], + dilations: tp.List[int] = [1, 1], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + causal: bool = False, + pad_mode: str = "reflect", + compress: int = 2, + true_skip: bool = True, + ): + super().__init__() + assert len(kernel_sizes) == len( + dilations + ), "Number of kernel sizes should match number of dilations" + act = getattr(nn, activation) + hidden = dim // compress + block = [] + for i, (kernel_size, dilation) in enumerate(zip(kernel_sizes, dilations)): + in_chs = dim if i == 0 else hidden + out_chs = dim if i == len(kernel_sizes) - 1 else hidden + block += [ + act(**activation_params), + StreamableConv1d( + in_chs, + out_chs, + kernel_size=kernel_size, + dilation=dilation, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), + ] + self.block = nn.Sequential(*block) + self.shortcut: nn.Module + if true_skip: + self.shortcut = nn.Identity() + else: + self.shortcut = StreamableConv1d( + dim, + dim, + kernel_size=1, + norm=norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) + + def forward(self, x): + return self.shortcut(x) + self.block(x) + + +class SEANetEncoder(nn.Module): + """SEANet encoder. + + Args: + channels (int): Audio channels. + dimension (int): Intermediate representation dimension. + n_filters (int): Base width for the model. + n_residual_layers (int): nb of residual layers. + ratios (Sequence[int]): kernel size and stride ratios. The encoder uses downsampling ratios instead of + upsampling ratios, hence it will use the ratios in the reverse order to the ones specified here + that must match the decoder order. We use the decoder order as some models may only employ the decoder. + activation (str): Activation function. + activation_params (dict): Parameters to provide to the activation function. + norm (str): Normalization method. + norm_params (dict): Parameters to provide to the underlying normalization used along with the convolution. + kernel_size (int): Kernel size for the initial convolution. + last_kernel_size (int): Kernel size for the initial convolution. + residual_kernel_size (int): Kernel size for the residual layers. + dilation_base (int): How much to increase the dilation with each layer. + causal (bool): Whether to use fully causal convolution. + pad_mode (str): Padding mode for the convolutions. + true_skip (bool): Whether to use true skip connection or a simple + (streamable) convolution as the skip connection in the residual network blocks. + compress (int): Reduced dimensionality in residual branches (from Demucs v3). + lstm (int): Number of LSTM layers at the end of the encoder. + disable_norm_outer_blocks (int): Number of blocks for which we don't apply norm. + For the encoder, it corresponds to the N first blocks. + """ + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + ): + super().__init__() + self.channels = channels + self.dimension = dimension + self.n_filters = n_filters + self.ratios = list(reversed(ratios)) + del ratios + self.n_residual_layers = n_residual_layers + self.hop_length = np.prod(self.ratios) + self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks + self.disable_norm_outer_blocks = disable_norm_outer_blocks + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." + "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) + + act = getattr(nn, activation) + mult = 1 + model: tp.List[nn.Module] = [ + StreamableConv1d( + channels, + mult * n_filters, + kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) + ] + # Downsample to raw audio scale + for i, ratio in enumerate(self.ratios): + block_norm = "none" if self.disable_norm_outer_blocks >= i + 2 else norm + # Add residual layers + for j in range(n_residual_layers): + model += [ + SEANetResnetBlock( + mult * n_filters, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + norm=block_norm, + norm_params=norm_params, + activation=activation, + activation_params=activation_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] + + # Add downsampling layers + model += [ + act(**activation_params), + StreamableConv1d( + mult * n_filters, + mult * n_filters * 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), + ] + mult *= 2 + + if lstm: + model += [StreamableLSTM(mult * n_filters, num_layers=lstm)] + + model += [ + act(**activation_params), + StreamableConv1d( + mult * n_filters, + dimension, + last_kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), + ] + + self.model = nn.Sequential(*model) + + def forward(self, x): + return self.model(x) + + +class SEANetDecoder(nn.Module): + """SEANet decoder. + + Args: + channels (int): Audio channels. + dimension (int): Intermediate representation dimension. + n_filters (int): Base width for the model. + n_residual_layers (int): nb of residual layers. + ratios (Sequence[int]): kernel size and stride ratios. + activation (str): Activation function. + activation_params (dict): Parameters to provide to the activation function. + final_activation (str): Final activation function after all convolutions. + final_activation_params (dict): Parameters to provide to the activation function. + norm (str): Normalization method. + norm_params (dict): Parameters to provide to the underlying normalization used along with the convolution. + kernel_size (int): Kernel size for the initial convolution. + last_kernel_size (int): Kernel size for the initial convolution. + residual_kernel_size (int): Kernel size for the residual layers. + dilation_base (int): How much to increase the dilation with each layer. + causal (bool): Whether to use fully causal convolution. + pad_mode (str): Padding mode for the convolutions. + true_skip (bool): Whether to use true skip connection or a simple. + (streamable) convolution as the skip connection in the residual network blocks. + compress (int): Reduced dimensionality in residual branches (from Demucs v3). + lstm (int): Number of LSTM layers at the end of the encoder. + disable_norm_outer_blocks (int): Number of blocks for which we don't apply norm. + For the decoder, it corresponds to the N last blocks. + trim_right_ratio (float): Ratio for trimming at the right of the transposed convolution under the causal setup. + If equal to 1.0, it means that all the trimming is done at the right. + """ + + def __init__( + self, + channels: int = 1, + dimension: int = 128, + n_filters: int = 32, + n_residual_layers: int = 3, + ratios: tp.List[int] = [8, 5, 4, 2], + activation: str = "ELU", + activation_params: dict = {"alpha": 1.0}, + final_activation: tp.Optional[str] = None, + final_activation_params: tp.Optional[dict] = None, + norm: str = "none", + norm_params: tp.Dict[str, tp.Any] = {}, + kernel_size: int = 7, + last_kernel_size: int = 7, + residual_kernel_size: int = 3, + dilation_base: int = 2, + causal: bool = False, + pad_mode: str = "reflect", + true_skip: bool = True, + compress: int = 2, + lstm: int = 0, + disable_norm_outer_blocks: int = 0, + trim_right_ratio: float = 1.0, + ): + super().__init__() + self.dimension = dimension + self.channels = channels + self.n_filters = n_filters + self.ratios = ratios + del ratios + self.n_residual_layers = n_residual_layers + self.hop_length = np.prod(self.ratios) + self.n_blocks = len(self.ratios) + 2 # first and last conv + residual blocks + self.disable_norm_outer_blocks = disable_norm_outer_blocks + assert ( + self.disable_norm_outer_blocks >= 0 + and self.disable_norm_outer_blocks <= self.n_blocks + ), ( + "Number of blocks for which to disable norm is invalid." + "It should be lower or equal to the actual number of blocks in the network and greater or equal to 0." + ) + + act = getattr(nn, activation) + mult = int(2 ** len(self.ratios)) + model: tp.List[nn.Module] = [ + StreamableConv1d( + dimension, + mult * n_filters, + kernel_size, + norm=( + "none" if self.disable_norm_outer_blocks == self.n_blocks else norm + ), + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ) + ] + + if lstm: + model += [StreamableLSTM(mult * n_filters, num_layers=lstm)] + + # Upsample to raw audio scale + for i, ratio in enumerate(self.ratios): + block_norm = ( + "none" + if self.disable_norm_outer_blocks >= self.n_blocks - (i + 1) + else norm + ) + # Add upsampling layers + model += [ + act(**activation_params), + StreamableConvTranspose1d( + mult * n_filters, + mult * n_filters // 2, + kernel_size=ratio * 2, + stride=ratio, + norm=block_norm, + norm_kwargs=norm_params, + causal=causal, + trim_right_ratio=trim_right_ratio, + ), + ] + # Add residual layers + for j in range(n_residual_layers): + model += [ + SEANetResnetBlock( + mult * n_filters // 2, + kernel_sizes=[residual_kernel_size, 1], + dilations=[dilation_base**j, 1], + activation=activation, + activation_params=activation_params, + norm=block_norm, + norm_params=norm_params, + causal=causal, + pad_mode=pad_mode, + compress=compress, + true_skip=true_skip, + ) + ] + + mult //= 2 + + # Add final layers + model += [ + act(**activation_params), + StreamableConv1d( + n_filters, + channels, + last_kernel_size, + norm="none" if self.disable_norm_outer_blocks >= 1 else norm, + norm_kwargs=norm_params, + causal=causal, + pad_mode=pad_mode, + ), + ] + # Add optional final activation to decoder (eg. tanh) + if final_activation is not None: + final_act = getattr(nn, final_activation) + final_activation_params = final_activation_params or {} + model += [final_act(**final_activation_params)] + self.model = nn.Sequential(*model) + + def forward(self, z): + y = self.model(z) + return y + + +def exists(val: tp.Optional[tp.Any]) -> bool: + return val is not None + + +def default(val: tp.Any, d: tp.Any) -> tp.Any: + return val if exists(val) else d + + +def l2norm(t): + return F.normalize(t, p=2, dim=-1) + + +def ema_inplace(moving_avg, new, decay: float): + moving_avg.data.mul_(decay).add_(new, alpha=(1 - decay)) + + +def laplace_smoothing(x, n_categories: int, epsilon: float = 1e-5): + return (x + epsilon) / (x.sum() + n_categories * epsilon) + + +def uniform_init(*shape: int): + t = torch.empty(shape) + nn.init.kaiming_uniform_(t) + return t + + +def sample_vectors(samples, num: int): + num_samples, device = samples.shape[0], samples.device + + if num_samples >= num: + indices = torch.randperm(num_samples, device=device)[:num] + else: + indices = torch.randint(0, num_samples, (num,), device=device) + + return samples[indices] + + +def kmeans(samples, num_clusters: int, num_iters: int = 10): + dim, dtype = samples.shape[-1], samples.dtype + + means = sample_vectors(samples, num_clusters) + + for _ in range(num_iters): + diffs = rearrange(samples, "n d -> n () d") - rearrange(means, "c d -> () c d") + dists = -(diffs**2).sum(dim=-1) + + buckets = dists.max(dim=-1).indices + bins = torch.bincount(buckets, minlength=num_clusters) + zero_mask = bins == 0 + bins_min_clamped = bins.masked_fill(zero_mask, 1) + + new_means = buckets.new_zeros(num_clusters, dim, dtype=dtype) + new_means.scatter_add_(0, repeat(buckets, "n -> n d", d=dim), samples) + new_means = new_means / bins_min_clamped[..., None] + + means = torch.where(zero_mask[..., None], means, new_means) + + return means, bins + + +def orthogonal_loss_fn(t): + # eq (2) from https://arxiv.org/abs/2112.00384 + n = t.shape[0] + normed_codes = l2norm(t) + identity = torch.eye(n, device=t.device) + cosine_sim = einsum("i d, j d -> i j", normed_codes, normed_codes) + return ((cosine_sim - identity) ** 2).sum() / (n**2) + + +class EuclideanCodebook(nn.Module): + """Codebook with Euclidean distance. + + Args: + dim (int): Dimension. + codebook_size (int): Codebook size. + kmeans_init (bool): Whether to use k-means to initialize the codebooks. + If set to true, run the k-means algorithm on the first training batch and use + the learned centroids as initialization. + kmeans_iters (int): Number of iterations used for k-means algorithm at initialization. + decay (float): Decay for exponential moving average over the codebooks. + epsilon (float): Epsilon value for numerical stability. + threshold_ema_dead_code (int): Threshold for dead code expiration. Replace any codes + that have an exponential moving average cluster size less than the specified threshold with + randomly selected vector from the current batch. + """ + + def __init__( + self, + dim: int, + codebook_size: int, + kmeans_init: int = False, + kmeans_iters: int = 10, + decay: float = 0.8, + epsilon: float = 1e-5, + threshold_ema_dead_code: int = 2, + ): + super().__init__() + self.decay = decay + init_fn: tp.Union[tp.Callable[..., torch.Tensor], tp.Any] = ( + uniform_init if not kmeans_init else torch.zeros + ) + embed = init_fn(codebook_size, dim) + + self.codebook_size = codebook_size + + self.kmeans_iters = kmeans_iters + self.epsilon = epsilon + self.threshold_ema_dead_code = threshold_ema_dead_code + + self.register_buffer("inited", torch.Tensor([not kmeans_init])) + self.register_buffer("cluster_size", torch.zeros(codebook_size)) + self.register_buffer("embed", embed) + self.register_buffer("embed_avg", embed.clone()) + + @torch.jit.ignore + def init_embed_(self, data): + if self.inited: + return + + embed, cluster_size = kmeans(data, self.codebook_size, self.kmeans_iters) + self.embed.data.copy_(embed) + self.embed_avg.data.copy_(embed.clone()) + self.cluster_size.data.copy_(cluster_size) + self.inited.data.copy_(torch.Tensor([True])) + # Make sure all buffers across workers are in sync after initialization + flashy.distrib.broadcast_tensors(self.buffers()) + + def replace_(self, samples, mask): + modified_codebook = torch.where( + mask[..., None], sample_vectors(samples, self.codebook_size), self.embed + ) + self.embed.data.copy_(modified_codebook) + + def expire_codes_(self, batch_samples): + if self.threshold_ema_dead_code == 0: + return + + expired_codes = self.cluster_size < self.threshold_ema_dead_code + if not torch.any(expired_codes): + return + + batch_samples = rearrange(batch_samples, "... d -> (...) d") + self.replace_(batch_samples, mask=expired_codes) + flashy.distrib.broadcast_tensors(self.buffers()) + + def preprocess(self, x): + x = rearrange(x, "... d -> (...) d") + return x + + def quantize(self, x): + embed = self.embed.t() + dist = -( + x.pow(2).sum(1, keepdim=True) + - 2 * x @ embed + + embed.pow(2).sum(0, keepdim=True) + ) + embed_ind = dist.max(dim=-1).indices + return embed_ind + + def postprocess_emb(self, embed_ind, shape): + return embed_ind.view(*shape[:-1]) + + def dequantize(self, embed_ind): + quantize = F.embedding(embed_ind, self.embed) + return quantize + + def encode(self, x): + shape = x.shape + # pre-process + x = self.preprocess(x) + # quantize + embed_ind = self.quantize(x) + # post-process + embed_ind = self.postprocess_emb(embed_ind, shape) + return embed_ind + + def decode(self, embed_ind): + quantize = self.dequantize(embed_ind) + return quantize + + def forward(self, x): + raise NotImplementedError() + shape, dtype = x.shape, x.dtype + x = self.preprocess(x) + self.init_embed_(x) + + embed_ind = self.quantize(x) + embed_onehot = F.one_hot(embed_ind, self.codebook_size).type(dtype) + embed_ind = self.postprocess_emb(embed_ind, shape) + quantize = self.dequantize(embed_ind) + + if self.training: + # We do the expiry of code at that point as buffers are in sync + # and all the workers will take the same decision. + self.expire_codes_(x) + ema_inplace(self.cluster_size, embed_onehot.sum(0), self.decay) + embed_sum = x.t() @ embed_onehot + ema_inplace(self.embed_avg, embed_sum.t(), self.decay) + cluster_size = ( + laplace_smoothing(self.cluster_size, self.codebook_size, self.epsilon) + * self.cluster_size.sum() + ) + embed_normalized = self.embed_avg / cluster_size.unsqueeze(1) + self.embed.data.copy_(embed_normalized) + + return quantize, embed_ind + + +class VectorQuantization(nn.Module): + """Vector quantization implementation. + Currently supports only euclidean distance. + + Args: + dim (int): Dimension + codebook_size (int): Codebook size + codebook_dim (int): Codebook dimension. If not defined, uses the specified dimension in dim. + decay (float): Decay for exponential moving average over the codebooks. + epsilon (float): Epsilon value for numerical stability. + kmeans_init (bool): Whether to use kmeans to initialize the codebooks. + kmeans_iters (int): Number of iterations used for kmeans initialization. + threshold_ema_dead_code (int): + channels_last (bool): Channels are the last dimension in the input tensors. + commitment_weight (float): Weight for commitment loss. + orthogonal_reg_weight (float): Orthogonal regularization weights. + orthogonal_reg_active_codes_only (bool): Apply orthogonal regularization only on active codes. + orthogonal_reg_max_codes (optional int): Maximum number of codes to consider + for orthogonal regularization. + threshold_ema_dead_code (int): Threshold for dead code expiration. Replace any codes + that have an exponential moving average cluster size less than the specified threshold with + randomly selected vector from the current batch. + """ + + def __init__( + self, + dim: int, + codebook_size: int, + codebook_dim: tp.Optional[int] = None, + decay: float = 0.8, + epsilon: float = 1e-5, + kmeans_init: bool = False, + kmeans_iters: int = 10, + threshold_ema_dead_code: int = 2, + channels_last: bool = False, + commitment_weight: float = 1.0, + orthogonal_reg_weight: float = 0.0, + orthogonal_reg_active_codes_only: bool = False, + orthogonal_reg_max_codes: tp.Optional[int] = None, + ): + super().__init__() + _codebook_dim: int = default(codebook_dim, dim) + + requires_projection = _codebook_dim != dim + self.project_in = ( + nn.Linear(dim, _codebook_dim) if requires_projection else nn.Identity() + ) + self.project_out = ( + nn.Linear(_codebook_dim, dim) if requires_projection else nn.Identity() + ) + + self.epsilon = epsilon + self.commitment_weight = commitment_weight + + self.orthogonal_reg_weight = orthogonal_reg_weight + self.orthogonal_reg_active_codes_only = orthogonal_reg_active_codes_only + self.orthogonal_reg_max_codes = orthogonal_reg_max_codes + + self._codebook = EuclideanCodebook( + dim=_codebook_dim, + codebook_size=codebook_size, + kmeans_init=kmeans_init, + kmeans_iters=kmeans_iters, + decay=decay, + epsilon=epsilon, + threshold_ema_dead_code=threshold_ema_dead_code, + ) + self.codebook_size = codebook_size + + self.channels_last = channels_last + + @property + def codebook(self): + return self._codebook.embed + + @property + def inited(self): + return self._codebook.inited + + def _preprocess(self, x): + if not self.channels_last: + x = rearrange(x, "b d n -> b n d") + return x + + def _postprocess(self, quantize): + if not self.channels_last: + quantize = rearrange(quantize, "b n d -> b d n") + return quantize + + def encode(self, x): + x = self._preprocess(x) + x = self.project_in(x) + embed_in = self._codebook.encode(x) + return embed_in + + def decode(self, embed_ind): + quantize = self._codebook.decode(embed_ind) + quantize = self.project_out(quantize) + quantize = self._postprocess(quantize) + return quantize + + def forward(self, x): + device = x.device + x = self._preprocess(x) + + x = self.project_in(x) + quantize, embed_ind = self._codebook(x) + + if self.training: + quantize = x + (quantize - x).detach() + + loss = torch.tensor([0.0], device=device, requires_grad=self.training) + + if self.training: + if self.commitment_weight > 0: + commit_loss = F.mse_loss(quantize.detach(), x) + loss = loss + commit_loss * self.commitment_weight + + if self.orthogonal_reg_weight > 0: + codebook = self.codebook + + if self.orthogonal_reg_active_codes_only: + # only calculate orthogonal loss for the activated codes for this batch + unique_code_ids = torch.unique(embed_ind) + codebook = codebook[unique_code_ids] + + num_codes = codebook.shape[0] + if ( + exists(self.orthogonal_reg_max_codes) + and num_codes > self.orthogonal_reg_max_codes + ): + rand_ids = torch.randperm(num_codes, device=device)[ + : self.orthogonal_reg_max_codes + ] + codebook = codebook[rand_ids] + + orthogonal_reg_loss = orthogonal_loss_fn(codebook) + loss = loss + orthogonal_reg_loss * self.orthogonal_reg_weight + + quantize = self.project_out(quantize) + quantize = self._postprocess(quantize) + + return quantize, embed_ind, loss + + +class ResidualVectorQuantization(nn.Module): + """Residual vector quantization implementation. + + Follows Algorithm 1. in https://arxiv.org/pdf/2107.03312.pdf + """ + + def __init__(self, *, num_quantizers, **kwargs): + super().__init__() + codebook_size = kwargs.pop("codebook_size", None) + if codebook_size is None: + raise ValueError("codebook_size must be provided in kwargs") + if type(codebook_size) != list: + codebook_size = [codebook_size] * num_quantizers + self.layers = nn.ModuleList( + [ + VectorQuantization(codebook_size=cur_codebook_size, **kwargs) + for _, cur_codebook_size in zip(range(num_quantizers), codebook_size) + ] + ) + + # self.layers = nn.ModuleList( + # [VectorQuantization(**kwargs) for _ in range(num_quantizers)] + # ) + + def forward(self, x, n_q: tp.Optional[int] = None): + quantized_out = 0.0 + residual = x + + all_losses = [] + all_indices = [] + + n_q = n_q or len(self.layers) + + for i, layer in enumerate(self.layers[:n_q]): + quantized, indices, loss = layer(residual) + residual = residual - quantized + quantized_out = quantized_out + quantized + all_indices.append(indices) + all_losses.append(loss) + + out_losses, out_indices = map(torch.stack, (all_losses, all_indices)) + return quantized_out, out_indices, out_losses + + def encode(self, x: torch.Tensor, n_q: tp.Optional[int] = None) -> torch.Tensor: + residual = x + all_indices = [] + n_q = n_q or len(self.layers) + for layer in self.layers[:n_q]: + indices = layer.encode(residual) + quantized = layer.decode(indices) + # the original code is below + # since quantize has the gradient of residual, according to line 321 + # quantize = x + (quantize - x).detach() + # the code below will make commitment loss to be 0 for all codebooks except for codebook1 + # https://github.com/facebookresearch/encodec/issues/25 + # therefore we change it + + residual = residual - quantized + # residual = residual - quantized.detach() + # since commitment loss is averaged, the scale of the loss won't get change (not as said in the issue above) + all_indices.append(indices) + out_indices = torch.stack(all_indices) + return out_indices + + def decode(self, q_indices: torch.Tensor) -> torch.Tensor: + quantized_out = torch.tensor(0.0, device=q_indices.device) + for i, indices in enumerate(q_indices): + layer = self.layers[i] + quantized = layer.decode(indices) + quantized_out = quantized_out + quantized + return quantized_out + + +class ResidualVectorQuantizer(BaseQuantizer): + """Residual Vector Quantizer. + + Args: + dimension (int): Dimension of the codebooks. + n_q (int): Number of residual vector quantizers used. + q_dropout (bool): Random quantizer drop out at train time. + bins (int): Codebook size. + decay (float): Decay for exponential moving average over the codebooks. + kmeans_init (bool): Whether to use kmeans to initialize the codebooks. + kmeans_iters (int): Number of iterations used for kmeans initialization. + threshold_ema_dead_code (int): Threshold for dead code expiration. Replace any codes + that have an exponential moving average cluster size less than the specified threshold with + randomly selected vector from the current batch. + orthogonal_reg_weight (float): Orthogonal regularization weights. + orthogonal_reg_active_codes_only (bool): Apply orthogonal regularization only on active codes. + orthogonal_reg_max_codes (optional int): Maximum number of codes to consider. + for orthogonal regularization. + """ + + def __init__( + self, + dimension: int = 256, + n_q: int = 8, + q_dropout: bool = False, + bins: tp.Union[int, tp.List[int]] = 1024, + decay: float = 0.99, + kmeans_init: bool = True, + kmeans_iters: int = 10, + threshold_ema_dead_code: int = 2, + orthogonal_reg_weight: float = 0.0, + orthogonal_reg_active_codes_only: bool = False, + orthogonal_reg_max_codes: tp.Optional[int] = None, + ): + super().__init__() + self.max_n_q = n_q + self.n_q = n_q + self.q_dropout = q_dropout + self.dimension = dimension + self.bins = bins + self.decay = decay + self.kmeans_init = kmeans_init + self.kmeans_iters = kmeans_iters + self.threshold_ema_dead_code = threshold_ema_dead_code + self.orthogonal_reg_weight = orthogonal_reg_weight + self.orthogonal_reg_active_codes_only = orthogonal_reg_active_codes_only + self.orthogonal_reg_max_codes = orthogonal_reg_max_codes + self.vq = ResidualVectorQuantization( + dim=self.dimension, + codebook_size=self.bins, + num_quantizers=self.n_q, + decay=self.decay, + kmeans_init=self.kmeans_init, + kmeans_iters=self.kmeans_iters, + threshold_ema_dead_code=self.threshold_ema_dead_code, + orthogonal_reg_weight=self.orthogonal_reg_weight, + orthogonal_reg_active_codes_only=self.orthogonal_reg_active_codes_only, + orthogonal_reg_max_codes=self.orthogonal_reg_max_codes, + channels_last=False, + ) + + def forward(self, x: torch.Tensor, frame_rate: int): + n_q = self.n_q + if self.training and self.q_dropout: + n_q = int(torch.randint(1, self.n_q + 1, (1,)).item()) + if type(self.bins) == list: + bins = self.bins + else: + bins = [self.bins] * self.n_q + bw_per_q = [math.log2(bin) * frame_rate / 1000 for bin in bins] + bw = torch.tensor(sum(bw_per_q)).to(x) + quantized, codes, commit_loss = self.vq(x, n_q=n_q) + codes = codes.transpose(0, 1) + # codes is [B, K, T], with T frames, K nb of codebooks. + return QuantizedResult(quantized, codes, bw, penalty=torch.mean(commit_loss)) + + def encode(self, x: torch.Tensor) -> torch.Tensor: + """Encode a given input tensor with the specified frame rate at the given bandwidth. + The RVQ encode method sets the appropriate number of quantizer to use + and returns indices for each quantizer. + """ + n_q = self.n_q + codes = self.vq.encode(x, n_q=n_q) + codes = codes.transpose(0, 1) + # codes is [B, K, T], with T frames, K nb of codebooks. + return codes + + def decode(self, codes: torch.Tensor) -> torch.Tensor: + """Decode the given codes to the quantized representation.""" + # codes is [B, K, T], with T frames, K nb of codebooks, vq.decode expects [K, B, T]. + codes = codes.transpose(0, 1) + quantized = self.vq.decode(codes) + return quantized + + @property + def total_codebooks(self): + return self.max_n_q + + @property + def num_codebooks(self): + return self.n_q + + def set_num_codebooks(self, n: int): + assert n > 0 and n <= self.max_n_q + self.n_q = n + + +class DummyQuantizer(BaseQuantizer): + """Fake quantizer that actually does not perform any quantization.""" + + def __init__(self): + super().__init__() + + def forward(self, x: torch.Tensor, frame_rate: int): + q = x.unsqueeze(1) + return QuantizedResult( + x, q, torch.tensor(q.numel() * 32 * frame_rate / 1000 / len(x)).to(x) + ) + + def encode(self, x: torch.Tensor) -> torch.Tensor: + """Encode a given input tensor with the specified sample rate at the given bandwidth. + In the case of the DummyQuantizer, the codes are actually identical + to the input and resulting quantized representation as no quantization is done. + """ + return x.unsqueeze(1) + + def decode(self, codes: torch.Tensor) -> torch.Tensor: + """Decode the given codes to the quantized representation. + In the case of the DummyQuantizer, the codes are actually identical + to the input and resulting quantized representation as no quantization is done. + """ + return codes.squeeze(1) + + @property + def total_codebooks(self): + """Total number of codebooks.""" + return 1 + + @property + def num_codebooks(self): + """Total number of codebooks.""" + return self.total_codebooks + + def set_num_codebooks(self, n: int): + """Set the number of active codebooks.""" + raise AttributeError( + "Cannot override the number of codebooks for the dummy quantizer" + ) + + +class EncodecModel(CompressionModel): + """Encodec model operating on the raw waveform. + + Args: + encoder (nn.Module): Encoder network. + decoder (nn.Module): Decoder network. + quantizer (BaseQuantizer): Quantizer network. + frame_rate (int): Frame rate for the latent representation. + sample_rate (int): Audio sample rate. + channels (int): Number of audio channels. + causal (bool): Whether to use a causal version of the model. + renormalize (bool): Whether to renormalize the audio before running the model. + """ + + # we need assignment to override the property in the abstract class, + # I couldn't find a better way... + frame_rate: float = 0 + sample_rate: int = 0 + channels: int = 0 + + def __init__( + self, + encoder: nn.Module, + decoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): + super().__init__() + self.encoder = encoder + self.decoder = decoder + self.quantizer = quantizer + self.frame_rate = frame_rate + self.sample_rate = sample_rate + self.channels = channels + self.renormalize = renormalize + self.causal = causal + if self.causal: + # we force disabling here to avoid handling linear overlap of segments + # as supported in original EnCodec codebase. + assert not self.renormalize, "Causal model does not support renormalize" + + @property + def total_codebooks(self): + """Total number of quantizer codebooks available.""" + return self.quantizer.total_codebooks + + @property + def num_codebooks(self): + """Active number of codebooks used by the quantizer.""" + return self.quantizer.num_codebooks + + def set_num_codebooks(self, n: int): + """Set the active number of codebooks used by the quantizer.""" + self.quantizer.set_num_codebooks(n) + + @property + def cardinality(self): + """Cardinality of each codebook.""" + return self.quantizer.bins + + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + scale: tp.Optional[torch.Tensor] + if self.renormalize: + mono = x.mean(dim=1, keepdim=True) + volume = mono.pow(2).mean(dim=2, keepdim=True).sqrt() + scale = 1e-8 + volume + x = x / scale + scale = scale.view(-1, 1) + else: + scale = None + return x, scale + + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: + if scale is not None: + assert self.renormalize + x = x * scale.view(-1, 1, 1) + return x + + def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: + if encode: + return self.encode(x) + else: + raise NotImplementedError("model forward and training is not supported.") + assert x.dim() == 3 + length = x.shape[-1] + x, scale = self.preprocess(x) + + emb = self.encoder(x) + q_res = self.quantizer(emb, self.frame_rate) + out = self.decoder(q_res.x) + + # remove extra padding added by the encoder and decoder + assert out.shape[-1] >= length, (out.shape[-1], length) + out = out[..., :length] + + q_res.x = self.postprocess(out, scale) + + return q_res + + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + """Encode the given input tensor to quantized representation along with scale parameter. + + Args: + x (torch.Tensor): Float tensor of shape [B, C, T] + + Returns: + codes, scale (tuple of torch.Tensor, torch.Tensor): Tuple composed of: + codes a float tensor of shape [B, K, T] with K the number of codebooks used and T the timestep. + scale a float tensor containing the scale for audio renormalizealization. + """ + assert x.dim() == 3 + x, scale = self.preprocess(x) + emb = self.encoder(x) + codes = self.quantizer.encode(emb) + return codes, scale + + def decode(self, codes: torch.Tensor, scale: tp.Optional[torch.Tensor] = None): + """Decode the given codes to a reconstructed representation, using the scale to perform + audio denormalization if needed. + + Args: + codes (torch.Tensor): Int tensor of shape [B, K, T] + scale (torch.Tensor, optional): Float tensor containing the scale value. + + Returns: + out (torch.Tensor): Float tensor of shape [B, C, T], the reconstructed audio. + """ + emb = self.decode_latent(codes) + out = self.decoder(emb) + out = self.postprocess(out, scale) + # out contains extra padding added by the encoder and decoder + return out + + def decode_latent(self, codes: torch.Tensor): + """Decode from the discrete codes to continuous latent space.""" + return self.quantizer.decode(codes) + + +class EncodecModel_encode_only(CompressionModel): + """Encodec model operating on the raw waveform. Encode only, so no decoder + + Args: + encoder (nn.Module): Encoder network. + quantizer (BaseQuantizer): Quantizer network. + frame_rate (int): Frame rate for the latent representation. + sample_rate (int): Audio sample rate. + channels (int): Number of audio channels. + causal (bool): Whether to use a causal version of the model. + renormalize (bool): Whether to renormalize the audio before running the model. + """ + + # we need assignment to override the property in the abstract class, + # I couldn't find a better way... + frame_rate: float = 0 + sample_rate: int = 0 + channels: int = 0 + + def __init__( + self, + encoder: nn.Module, + quantizer: BaseQuantizer, + frame_rate: int, + sample_rate: int, + channels: int, + causal: bool = False, + renormalize: bool = False, + ): + super().__init__() + self.encoder = encoder + self.quantizer = quantizer + self.frame_rate = frame_rate + self.sample_rate = sample_rate + self.channels = channels + self.renormalize = renormalize + self.causal = causal + if self.causal: + # we force disabling here to avoid handling linear overlap of segments + # as supported in original EnCodec codebase. + assert not self.renormalize, "Causal model does not support renormalize" + + @property + def total_codebooks(self): + """Total number of quantizer codebooks available.""" + return self.quantizer.total_codebooks + + @property + def num_codebooks(self): + """Active number of codebooks used by the quantizer.""" + return self.quantizer.num_codebooks + + def set_num_codebooks(self, n: int): + """Set the active number of codebooks used by the quantizer.""" + self.quantizer.set_num_codebooks(n) + + @property + def cardinality(self): + """Cardinality of each codebook.""" + return self.quantizer.bins + + def preprocess( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + scale: tp.Optional[torch.Tensor] + if self.renormalize: + mono = x.mean(dim=1, keepdim=True) + volume = mono.pow(2).mean(dim=2, keepdim=True).sqrt() + scale = 1e-8 + volume + x = x / scale + scale = scale.view(-1, 1) + else: + scale = None + return x, scale + + def postprocess( + self, x: torch.Tensor, scale: tp.Optional[torch.Tensor] = None + ) -> torch.Tensor: + if scale is not None: + assert self.renormalize + x = x * scale.view(-1, 1, 1) + return x + + def forward(self, x: torch.Tensor, encode=False) -> QuantizedResult: + if encode: + return self.encode(x) + else: + raise NotImplementedError("model forward and training is not supported.") + assert x.dim() == 3 + length = x.shape[-1] + x, scale = self.preprocess(x) + + emb = self.encoder(x) + q_res = self.quantizer(emb, self.frame_rate) + out = self.decoder(q_res.x) + + # remove extra padding added by the encoder and decoder + assert out.shape[-1] >= length, (out.shape[-1], length) + out = out[..., :length] + + q_res.x = self.postprocess(out, scale) + + return q_res + + def encode( + self, x: torch.Tensor + ) -> tp.Tuple[torch.Tensor, tp.Optional[torch.Tensor]]: + """Encode the given input tensor to quantized representation along with scale parameter. + + Args: + x (torch.Tensor): Float tensor of shape [B, C, T] + + Returns: + codes, scale (tuple of torch.Tensor, torch.Tensor): Tuple composed of: + codes a float tensor of shape [B, K, T] with K the number of codebooks used and T the timestep. + scale a float tensor containing the scale for audio renormalizealization. + """ + assert x.dim() == 3 + x, scale = self.preprocess(x) + emb = self.encoder(x) + codes = self.quantizer.encode(emb) + return codes, scale + + def decode(self, codes: torch.Tensor, scale: tp.Optional[torch.Tensor] = None): + """Decode the given codes to a reconstructed representation, using the scale to perform + audio denormalization if needed. + + Args: + codes (torch.Tensor): Int tensor of shape [B, K, T] + scale (torch.Tensor, optional): Float tensor containing the scale value. + + Returns: + out (torch.Tensor): Float tensor of shape [B, C, T], the reconstructed audio. + """ + raise NotImplementedError("Decode is not supported for encode only model") + emb = self.decode_latent(codes) + out = self.decoder(emb) + out = self.postprocess(out, scale) + # out contains extra padding added by the encoder and decoder + return out + + def decode_latent(self, codes: torch.Tensor): + """Decode from the discrete codes to continuous latent space.""" + raise NotImplementedError("Decode is not supported for encode only model") + return self.quantizer.decode(codes) + + +def get_quantizer( + quantizer: str, cfg: omegaconf.DictConfig, dimension: int +) -> BaseQuantizer: + klass = {"no_quant": DummyQuantizer, "rvq": ResidualVectorQuantizer}[quantizer] + kwargs = dict_from_config(getattr(cfg, quantizer)) + if quantizer != "no_quant": + kwargs["dimension"] = dimension + return klass(**kwargs) + + +def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): + if encoder_name == "seanet": + kwargs = dict_from_config(getattr(cfg, "seanet")) + encoder_override_kwargs = kwargs.pop("encoder") + decoder_override_kwargs = kwargs.pop("decoder") + encoder_kwargs = {**kwargs, **encoder_override_kwargs} + decoder_kwargs = {**kwargs, **decoder_override_kwargs} + encoder = SEANetEncoder(**encoder_kwargs) + decoder = SEANetDecoder(**decoder_kwargs) + return encoder, decoder + else: + raise KeyError(f"Unexpected compression model {cfg.compression_model}") + + +def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: + """Instantiate a compression model.""" + if device == None: + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + state = torch.load(ckpt_fn, map_location="cpu", weights_only=False) # TODO: Convert to SafeTensors + cfg = state["xp.cfg"] + cfg.device = str(device) + weights = state["best_state"]["model"] + assert ( + cfg.compression_model == "encodec" + ), "Only Encodec model is supported for now." + if encode_only: + all_keys = list(weights.keys()) + for key in all_keys: + if key.startswith("decoder"): + del weights[key] + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") + encoder, _ = get_encodec_autoencoder(encoder_name, cfg) + quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) + # deprecated params + kwargs.pop("renorm", None) + compression_model = EncodecModel_encode_only( + encoder, quantizer, frame_rate=frame_rate, renormalize=renormalize, **kwargs + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" + compression_model.load_state_dict(weights) + compression_model.eval() + return compression_model + + else: + kwargs = dict_from_config(getattr(cfg, "encodec")) + encoder_name = kwargs.pop("autoencoder") + quantizer_name = kwargs.pop("quantizer") + encoder, decoder = get_encodec_autoencoder(encoder_name, cfg) + quantizer = get_quantizer(quantizer_name, cfg, encoder.dimension) + frame_rate = kwargs["sample_rate"] // encoder.hop_length + renormalize = kwargs.pop("renormalize", False) + # deprecated params + kwargs.pop("renorm", None) + compression_model = EncodecModel( + encoder, + decoder, + quantizer, + frame_rate=frame_rate, + renormalize=renormalize, + **kwargs, + ).to(cfg.device) + assert ( + compression_model.sample_rate == cfg.sample_rate + ), "Compression model sample rate should match" + compression_model.load_state_dict(weights) + compression_model.eval() + return compression_model + + +if __name__ == "__main__": + import torchaudio + + ckpt_fn = "/home/pyp/BoostedVoiceEditor/pretrained/encodec_6f79c6a8.th" + audio_in_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley.wav", + ] + audio_out_fns = [ + "/home/pyp/BoostedVoiceEditor/demo/pam_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/ray_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/84_121550_000074_000000_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/caribbean_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", + "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", + ] + device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + model = get_compression_model(ckpt_fn, device=device) + + for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): + audio_in, sr = torchaudio.load(audio_in_fn) + if sr != model.sample_rate: + audio_in = torchaudio.transforms.Resample(sr, model.sample_rate)(audio_in) + if audio_in.shape[0] == 2: + audio_in = audio_in.mean(dim=0, keepdim=True) + audio_in = audio_in.unsqueeze(0) + audio_in = audio_in.to(torch.float32).to(device) + codes = model.encode(audio_in)[0] + audio_out = model.decode(codes)[0].cpu() + torchaudio.save(audio_out_fn, audio_out, model.sample_rate) diff --git a/pretrained/.gitkeep b/voicestar/modules/__init__.py similarity index 100% rename from pretrained/.gitkeep rename to voicestar/modules/__init__.py diff --git a/models/modules/activation.py b/voicestar/modules/activation.py similarity index 83% rename from models/modules/activation.py rename to voicestar/modules/activation.py index 46d6074..de2fcfe 100644 --- a/models/modules/activation.py +++ b/voicestar/modules/activation.py @@ -1,4 +1,4 @@ -# cp from https://github.com/lifeiteng/vall-e/blob/main/valle/modules/activation.py +# From https://github.com/lifeiteng/vall-e/blob/main/valle/modules/activation.py (Apache 2.0 license) from typing import Optional, Tuple import torch @@ -11,19 +11,21 @@ import logging from typing import Callable, List, Optional, Tuple, Union from typing import TYPE_CHECKING + if TYPE_CHECKING: from torch.types import _dtype as DType else: # The JIT doesn't understand Union, nor torch.dtype here DType = int + def _canonical_mask( - mask: Optional[Tensor], - mask_name: str, - other_type: Optional[DType], - other_name: str, - target_type: DType, - check_other: bool = True, + mask: Optional[Tensor], + mask_name: str, + other_type: Optional[DType], + other_name: str, + target_type: DType, + check_other: bool = True, ) -> Optional[Tensor]: if mask is not None: @@ -31,7 +33,8 @@ def _canonical_mask( _mask_is_float = torch.is_floating_point(mask) if _mask_dtype != torch.bool and not _mask_is_float: raise AssertionError( - f"only bool and floating types of {mask_name} are supported") + f"only bool and floating types of {mask_name} are supported" + ) if check_other and other_type is not None: if _mask_dtype != other_type: warnings.warn( @@ -39,12 +42,12 @@ def _canonical_mask( "is deprecated. Use same type for both instead." ) if not _mask_is_float: - mask = ( - torch.zeros_like(mask, dtype=target_type) - .masked_fill_(mask, float("-inf")) + mask = torch.zeros_like(mask, dtype=target_type).masked_fill_( + mask, float("-inf") ) return mask + def _in_projection_packed( q: Tensor, k: Tensor, @@ -85,7 +88,13 @@ def _in_projection_packed( # self-attention proj = F.linear(q, w, b) # reshape to 3, E and not E, 3 is deliberate for better memory coalescing and keeping same order as chunk() - proj = proj.unflatten(-1, (3, E)).unsqueeze(0).transpose(0, -2).squeeze(-2).contiguous() + proj = ( + proj.unflatten(-1, (3, E)) + .unsqueeze(0) + .transpose(0, -2) + .squeeze(-2) + .contiguous() + ) return proj[0], proj[1], proj[2] else: # encoder-decoder attention @@ -97,7 +106,13 @@ def _in_projection_packed( q_proj = F.linear(q, w_q, b_q) kv_proj = F.linear(k, w_kv, b_kv) # reshape to 2, E and not E, 2 is deliberate for better memory coalescing and keeping same order as chunk() - kv_proj = kv_proj.unflatten(-1, (2, E)).unsqueeze(0).transpose(0, -2).squeeze(-2).contiguous() + kv_proj = ( + kv_proj.unflatten(-1, (2, E)) + .unsqueeze(0) + .transpose(0, -2) + .squeeze(-2) + .contiguous() + ) return (q_proj, kv_proj[0], kv_proj[1]) else: w_q, w_k, w_v = w.chunk(3) @@ -107,6 +122,7 @@ def _in_projection_packed( b_q, b_k, b_v = b.chunk(3) return F.linear(q, w_q, b_q), F.linear(k, w_k, b_k), F.linear(v, w_v, b_v) + def _none_or_dtype(input: Optional[Tensor]) -> Optional[DType]: if input is None: return None @@ -114,19 +130,35 @@ def _none_or_dtype(input: Optional[Tensor]) -> Optional[DType]: return input.dtype raise RuntimeError("input to _none_or_dtype() must be None or torch.Tensor") + def rotate_half(x): - x1 = x[..., :x.shape[-1] // 2] - x2 = x[..., x.shape[-1] // 2:] + x1 = x[..., : x.shape[-1] // 2] + x2 = x[..., x.shape[-1] // 2 :] return torch.cat([-x2, x1], dim=-1) -def apply_rotary_pos_emb(q, k, q_sinu=None, k_sinu=None, sinu=None, unsqueeze_dim=1, args=None, q_offset=0): + +def apply_rotary_pos_emb( + q, k, q_sinu=None, k_sinu=None, sinu=None, unsqueeze_dim=1, args=None, q_offset=0 +): if sinu is not None: - q_emb = q * sinu['cos'][:, q_offset:q_offset+q.shape[2]].unsqueeze(unsqueeze_dim) + rotate_half(q) * sinu['sin'][:, q_offset:q_offset+q.shape[2]].unsqueeze(unsqueeze_dim) - k_emb = k * sinu['cos'][:, :k.shape[2]].unsqueeze(unsqueeze_dim) + rotate_half(k) * sinu['sin'][:, :k.shape[2]].unsqueeze(unsqueeze_dim) + q_emb = q * sinu["cos"][:, q_offset : q_offset + q.shape[2]].unsqueeze( + unsqueeze_dim + ) + rotate_half(q) * sinu["sin"][:, q_offset : q_offset + q.shape[2]].unsqueeze( + unsqueeze_dim + ) + k_emb = k * sinu["cos"][:, : k.shape[2]].unsqueeze(unsqueeze_dim) + rotate_half( + k + ) * sinu["sin"][:, : k.shape[2]].unsqueeze(unsqueeze_dim) if q_sinu is not None: assert sinu is None, "sinu must be None" - q_emb = q * q_sinu['cos'][:, :, q_offset:q_offset+q.shape[2]] + rotate_half(q) * q_sinu['sin'][:, :, q_offset:q_offset+q.shape[2]] - k_emb = k * k_sinu['cos'][:, :, :k.shape[2]] + rotate_half(k) * k_sinu['sin'][:, :, :k.shape[2]] + q_emb = ( + q * q_sinu["cos"][:, :, q_offset : q_offset + q.shape[2]] + + rotate_half(q) * q_sinu["sin"][:, :, q_offset : q_offset + q.shape[2]] + ) + k_emb = ( + k * k_sinu["cos"][:, :, : k.shape[2]] + + rotate_half(k) * k_sinu["sin"][:, :, : k.shape[2]] + ) # else: # assert freqs is not None, "freqs must be provided" # assert key_lens is not None, "key_lens must be provided" @@ -243,6 +275,7 @@ class MultiheadAttention(Module): >>> attn_output, attn_output_weights = multihead_attn(query, key, value) """ + __constants__ = ["batch_first"] bias_k: Optional[torch.Tensor] bias_v: Optional[torch.Tensor] @@ -268,9 +301,7 @@ def __init__( self.embed_dim = embed_dim self.kdim = kdim if kdim is not None else embed_dim self.vdim = vdim if vdim is not None else embed_dim - self._qkv_same_embed_dim = ( - self.kdim == embed_dim and self.vdim == embed_dim - ) + self._qkv_same_embed_dim = self.kdim == embed_dim and self.vdim == embed_dim self.num_heads = num_heads self.dropout = dropout @@ -281,12 +312,8 @@ def __init__( ), "embed_dim must be divisible by num_heads" if add_bias_kv: - self.bias_k = Parameter( - torch.empty((1, 1, embed_dim), **factory_kwargs) - ) - self.bias_v = Parameter( - torch.empty((1, 1, embed_dim), **factory_kwargs) - ) + self.bias_k = Parameter(torch.empty((1, 1, embed_dim), **factory_kwargs)) + self.bias_v = Parameter(torch.empty((1, 1, embed_dim), **factory_kwargs)) else: self.bias_k = self.bias_v = None @@ -311,7 +338,7 @@ def __init__( self.register_parameter("k_proj_weight", None) self.register_parameter("v_proj_weight", None) - if bias: # True by default + if bias: # True by default self.in_proj_bias = Parameter( torch.empty(3 * embed_dim, **factory_kwargs) ) @@ -385,11 +412,11 @@ def forward( attn_mask: Optional[Tensor] = None, average_attn_weights: bool = True, past: Optional[Tensor] = None, - q_sinu = None, - k_sinu = None, - sinu = None, - args = None, - q_offset = 0, + q_sinu=None, + k_sinu=None, + sinu=None, + args=None, + q_offset=0, ) -> Tuple[Tensor, Optional[Tensor]]: r""" Args: @@ -453,20 +480,18 @@ def forward( ) why_not_fast_path = "" if not is_batched: - why_not_fast_path = f"input not batched; expected query.dim() of 3 but got {query.dim()}" + why_not_fast_path = ( + f"input not batched; expected query.dim() of 3 but got {query.dim()}" + ) elif query is not key or key is not value: # When lifting this restriction, don't forget to either # enforce that the dtypes all match or test cases where # they don't! why_not_fast_path = "non-self attention was used (query, key, and value are not the same Tensor)" - elif ( - self.in_proj_bias is not None - and query.dtype != self.in_proj_bias.dtype - ): + elif self.in_proj_bias is not None and query.dtype != self.in_proj_bias.dtype: why_not_fast_path = f"dtypes of query ({query.dtype}) and self.in_proj_bias ({self.in_proj_bias.dtype}) don't match" elif ( - self.in_proj_weight is not None - and query.dtype != self.in_proj_weight.dtype + self.in_proj_weight is not None and query.dtype != self.in_proj_weight.dtype ): # this case will fail anyway, but at least they'll get a useful error message. why_not_fast_path = f"dtypes of query ({query.dtype}) and self.in_proj_weight ({self.in_proj_weight.dtype}) don't match" @@ -515,9 +540,7 @@ def forward( for x in tensor_args ] ): - why_not_fast_path = ( - "some Tensor argument is neither CUDA nor CPU" - ) + why_not_fast_path = "some Tensor argument is neither CUDA nor CPU" elif torch.is_grad_enabled() and any( [x is not None and x.requires_grad for x in tensor_args] ): @@ -536,16 +559,14 @@ def forward( self.in_proj_bias, self.out_proj.weight, self.out_proj.bias, - key_padding_mask - if key_padding_mask is not None - else attn_mask, + key_padding_mask if key_padding_mask is not None else attn_mask, need_weights, average_attn_weights, - 1 - if key_padding_mask is not None - else 0 - if attn_mask is not None - else None, + ( + 1 + if key_padding_mask is not None + else 0 if attn_mask is not None else None + ), ) any_nested = query.is_nested or key.is_nested or value.is_nested @@ -563,9 +584,7 @@ def forward( query, key = [x.transpose(1, 0) for x in (query, key)] value = key else: - query, key, value = [ - x.transpose(1, 0) for x in (query, key, value) - ] + query, key, value = [x.transpose(1, 0) for x in (query, key, value)] if not self._qkv_same_embed_dim: attn_output, attn_output_weights = F.multi_head_attention_forward( @@ -624,62 +643,78 @@ def forward( mask_name="key_padding_mask", other_type=_none_or_dtype(attn_mask), other_name="attn_mask", - target_type=query.dtype + target_type=query.dtype, ) attn_mask = _canonical_mask( - mask=attn_mask, - mask_name="attn_mask", - other_type=None, - other_name="", - target_type=query.dtype, - check_other=False, - ) + mask=attn_mask, + mask_name="attn_mask", + other_type=None, + other_name="", + target_type=query.dtype, + check_other=False, + ) head_dim = self.embed_dim // self.num_heads - assert head_dim * self.num_heads == self.embed_dim, f"embed_dim {self.embed_dim} not divisible by num_heads {self.num_heads}" - assert key.shape == value.shape, f"key shape {key.shape} does not match value shape {value.shape}" - q, k, v = _in_projection_packed(query, key, value, self.in_proj_weight, self.in_proj_bias) + assert ( + head_dim * self.num_heads == self.embed_dim + ), f"embed_dim {self.embed_dim} not divisible by num_heads {self.num_heads}" + assert ( + key.shape == value.shape + ), f"key shape {key.shape} does not match value shape {value.shape}" + q, k, v = _in_projection_packed( + query, key, value, self.in_proj_weight, self.in_proj_bias + ) # k_present, v_present = k, v - + # # reshape q, k, v for multihead attention and make em batch first # - - q = q.view(tgt_len, bsz * num_heads, head_dim).transpose(0, 1) k = k.view(k.shape[0], bsz * num_heads, head_dim).transpose(0, 1) - v = v.view(v.shape[0], bsz * num_heads, head_dim).transpose(0, 1) # (bsz * num_heads, src_len, head_dim) + v = v.view(v.shape[0], bsz * num_heads, head_dim).transpose( + 0, 1 + ) # (bsz * num_heads, src_len, head_dim) src_len = k.size(1) if past is not None and past.ndim > 2: expected_src_len = src_len + past[0].shape[-2] else: expected_src_len = src_len - # ensure attn_mask's dim is 3 if attn_mask is not None: if attn_mask.dim() == 2: correct_2d_size = (tgt_len, expected_src_len) if attn_mask.shape != correct_2d_size: - raise RuntimeError(f"The shape of the 2D attn_mask is {attn_mask.shape}, but should be {correct_2d_size}.") + raise RuntimeError( + f"The shape of the 2D attn_mask is {attn_mask.shape}, but should be {correct_2d_size}." + ) attn_mask = attn_mask.unsqueeze(0) elif attn_mask.dim() == 3: correct_3d_size = (bsz * num_heads, tgt_len, expected_src_len) if attn_mask.shape != correct_3d_size: - raise RuntimeError(f"The shape of the 3D attn_mask is {attn_mask.shape}, but should be {correct_3d_size}.") + raise RuntimeError( + f"The shape of the 3D attn_mask is {attn_mask.shape}, but should be {correct_3d_size}." + ) else: - raise RuntimeError(f"attn_mask's dimension {attn_mask.dim()} is not supported") - + raise RuntimeError( + f"attn_mask's dimension {attn_mask.dim()} is not supported" + ) + if key_padding_mask is not None: - assert key_padding_mask.shape == (bsz, expected_src_len), \ - f"expecting key_padding_mask shape of {(bsz, expected_src_len)}, but got {key_padding_mask.shape}" - key_padding_mask = key_padding_mask.view(bsz, 1, 1, expected_src_len). \ - expand(-1, num_heads, -1, -1).reshape(bsz * num_heads, 1, expected_src_len) + assert key_padding_mask.shape == ( + bsz, + expected_src_len, + ), f"expecting key_padding_mask shape of {(bsz, expected_src_len)}, but got {key_padding_mask.shape}" + key_padding_mask = ( + key_padding_mask.view(bsz, 1, 1, expected_src_len) + .expand(-1, num_heads, -1, -1) + .reshape(bsz * num_heads, 1, expected_src_len) + ) if attn_mask is None: attn_mask = key_padding_mask else: attn_mask = attn_mask + key_padding_mask - + if not self.training: dropout_p = 0.0 else: @@ -731,8 +766,12 @@ def forward( v = v.view(bsz, num_heads, src_len, head_dim) # logging.info(f"shape of past: {past.shape}") if past is not None: - present = torch.stack([k, v], dim=0) # (2, bsz, num_heads, src_len, head_dim) - if past.ndim > 2: # this means we use kvcache, otherwise we just pass in a placeholder, but not actually using kvcache + present = torch.stack( + [k, v], dim=0 + ) # (2, bsz, num_heads, src_len, head_dim) + if ( + past.ndim > 2 + ): # this means we use kvcache, otherwise we just pass in a placeholder, but not actually using kvcache pk, pv = past k = torch.cat([pk, k], dim=-2) v = torch.cat([pv, v], dim=-2) @@ -742,23 +781,40 @@ def forward( # here we assume that this kvcache is only used in self-attention, and therefore k and q always have the same seq_len # rope positional encoding if sinu is not None: - # direct rotary + # direct rotary # logging.info("perform rotary positional encoding") - q, k = apply_rotary_pos_emb(q, k, sinu=sinu, args = args, q_offset=q_offset) + q, k = apply_rotary_pos_emb( + q, k, sinu=sinu, args=args, q_offset=q_offset + ) if q_sinu is not None: assert sinu is None, "sinu and q_sinu cannot be used together" assert k_sinu is not None, "k_sinu must be provided" - q, k = apply_rotary_pos_emb(q, k, q_sinu=q_sinu, k_sinu=k_sinu, args = args, q_offset=q_offset) - + q, k = apply_rotary_pos_emb( + q, k, q_sinu=q_sinu, k_sinu=k_sinu, args=args, q_offset=q_offset + ) + # if self.training and it's cross attention, will get attention_weights - if args != None and self.training and getattr(args, "attention_alignment_loss", 0) and not (query is key): + if ( + args != None + and self.training + and getattr(args, "attention_alignment_loss", 0) + and not (query is key) + ): attention_weights = q @ k.transpose(-1, -2) else: attention_weights = None - attn_output = F.scaled_dot_product_attention(q, k, v, attn_mask, dropout_p, is_causal=False) - attn_output = attn_output.permute(2, 0, 1, 3).contiguous().view(bsz * tgt_len, embed_dim) + attn_output = F.scaled_dot_product_attention( + q, k, v, attn_mask, dropout_p, is_causal=False + ) + attn_output = ( + attn_output.permute(2, 0, 1, 3) + .contiguous() + .view(bsz * tgt_len, embed_dim) + ) - attn_output = F.linear(attn_output, self.out_proj.weight, self.out_proj.bias) + attn_output = F.linear( + attn_output, self.out_proj.weight, self.out_proj.bias + ) attn_output = attn_output.view(tgt_len, bsz, attn_output.size(1)) if not is_batched: # squeeze the output if input was unbatched @@ -769,13 +825,18 @@ def forward( # return (attn_output, present), None # harded coded, the code do not support returning attn weigths yet - attn_output_weights=None + attn_output_weights = None if self.batch_first and is_batched: if attention_weights != None: - return {"attn_output": attn_output.transpose(1, 0), "attention_weights": attention_weights}, present + return { + "attn_output": attn_output.transpose(1, 0), + "attention_weights": attention_weights, + }, present return attn_output.transpose(1, 0), present else: if attention_weights != None: - return {"attn_output": attn_output, "attention_weights": attention_weights}, present + return { + "attn_output": attn_output, + "attention_weights": attention_weights, + }, present return attn_output, present - diff --git a/models/modules/embedding.py b/voicestar/modules/embedding.py similarity index 79% rename from models/modules/embedding.py rename to voicestar/modules/embedding.py index 92e36da..25f2507 100644 --- a/models/modules/embedding.py +++ b/voicestar/modules/embedding.py @@ -1,5 +1,5 @@ -# cp from https://github.com/lifeiteng/vall-e/blob/main/valle/modules/embedding.py -# Copyright 2023 (authors: Feiteng Li) +# From https://github.com/lifeiteng/vall-e/blob/main/valle/modules/embedding.py (Apache 2.0 license) +# Copyright 2023 (authors: Feiteng Li) # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -79,9 +79,7 @@ def extend_pe(self, x): x.size(1) - 1, -1, -1.0, dtype=torch.float32 ).unsqueeze(1) else: - position = torch.arange( - 0, x.size(1), dtype=torch.float32 - ).unsqueeze(1) + position = torch.arange(0, x.size(1), dtype=torch.float32).unsqueeze(1) div_term = torch.exp( torch.arange(0, self.dim_model, 2, dtype=torch.float32) * -(math.log(10000.0) / self.dim_model) @@ -105,7 +103,7 @@ def __init__( dropout: float = 0.0, scale: bool = False, alpha: bool = False, - args = None + args=None, ): super().__init__() self.args = args @@ -115,10 +113,14 @@ def __init__( self.dropout = torch.nn.Dropout(p=dropout) self.reverse = False - self.div_term = torch.exp( - torch.arange(0, self.dim_model, 2, dtype=torch.float32) - * -(math.log(args.sinusoidal_base) / self.dim_model) - ).unsqueeze(0).unsqueeze(0) # [1, 1, dim_model//2] + self.div_term = ( + torch.exp( + torch.arange(0, self.dim_model, 2, dtype=torch.float32) + * -(math.log(args.sinusoidal_base) / self.dim_model) + ) + .unsqueeze(0) + .unsqueeze(0) + ) # [1, 1, dim_model//2] self.position = None self.extend_position(torch.tensor(0.0).expand(1, 10000)) self.progress_scale = getattr(args, "progress_scale", 1.0) @@ -133,26 +135,34 @@ def extend_position(self, x): self.position = self.position.to(dtype=x.dtype, device=x.device) return if self.reverse: - self.position = torch.arange( - x.size(1) - 1, -1, -1.0, dtype=torch.float32 - ).unsqueeze(0).unsqueeze(2).to(x) + self.position = ( + torch.arange(x.size(1) - 1, -1, -1.0, dtype=torch.float32) + .unsqueeze(0) + .unsqueeze(2) + .to(x) + ) else: - self.position = torch.arange( - 0, x.size(1), dtype=torch.float32 - ).unsqueeze(0).unsqueeze(2).to(x) # [1, seq_len, 1] + self.position = ( + torch.arange(0, x.size(1), dtype=torch.float32) + .unsqueeze(0) + .unsqueeze(2) + .to(x) + ) # [1, seq_len, 1] def forward(self, x: torch.Tensor, x_lens: torch.Tensor) -> torch.Tensor: assert x.ndim == 3, x.shape self.extend_position(x) - x_lens = x_lens.unsqueeze(1).unsqueeze(2) # [B, 1, 1] + x_lens = x_lens.unsqueeze(1).unsqueeze(2) # [B, 1, 1] multiple = x_lens / (x_lens - 1) - progress = self.position[:, :x.shape[1]] * multiple / x_lens * self.progress_scale + progress = ( + self.position[:, : x.shape[1]] * multiple / x_lens * self.progress_scale + ) # torch.set_printoptions(edgeitems=100) # for i in range(x_lens.shape[0]): # logging.info(f"{progress[i, :x_lens[i,0,0], 0]}") - invfreq = self.div_term * progress # might want to use a scale term here + invfreq = self.div_term * progress # might want to use a scale term here pe = torch.zeros_like(x) pe[..., 0::2] = torch.sin(invfreq) pe[..., 1::2] = torch.cos(invfreq) output = x * self.x_scale + self.alpha * pe - return self.dropout(output) \ No newline at end of file + return self.dropout(output) diff --git a/models/modules/sampling.py b/voicestar/modules/sampling.py similarity index 88% rename from models/modules/sampling.py rename to voicestar/modules/sampling.py index 7acdcd4..db6c165 100644 --- a/models/modules/sampling.py +++ b/voicestar/modules/sampling.py @@ -1,6 +1,16 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" + import torch import torch.nn.functional as F + def top_k_top_p_filtering( logits, top_k=0, top_p=1.0, filter_value=-float("Inf"), min_tokens_to_keep=1 ): @@ -14,18 +24,14 @@ def top_k_top_p_filtering( From: https://gist.github.com/thomwolf/1a5a29f6962089e871b94cbd09daf317 """ if top_k > 0: - top_k = min( - max(top_k, min_tokens_to_keep), logits.size(-1) - ) # Safety check + top_k = min(max(top_k, min_tokens_to_keep), logits.size(-1)) # Safety check # Remove all tokens with a probability less than the last token of the top-k indices_to_remove = logits < torch.topk(logits, top_k)[0][..., -1, None] logits[indices_to_remove] = filter_value if top_p < 1.0: sorted_logits, sorted_indices = torch.sort(logits, descending=True) - cumulative_probs = torch.cumsum( - F.softmax(sorted_logits, dim=-1), dim=-1 - ) + cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1) # Remove tokens with cumulative probability above the threshold (token with 0 are kept) sorted_indices_to_remove = cumulative_probs > top_p @@ -33,9 +39,7 @@ def top_k_top_p_filtering( # Keep at least min_tokens_to_keep (set to min_tokens_to_keep-1 because we add the first one below) sorted_indices_to_remove[..., :min_tokens_to_keep] = 0 # Shift the indices to the right to keep also the first token above the threshold - sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[ - ..., :-1 - ].clone() + sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone() sorted_indices_to_remove[..., 0] = 0 # scatter sorted tensors to original indexing @@ -44,7 +48,8 @@ def top_k_top_p_filtering( ) logits[indices_to_remove] = filter_value return logits - + + def topk_sampling(logits, top_k=10, top_p=1.0, temperature=1.0): # temperature: (`optional`) float # The value used to module the next token probabilities. Must be strictly positive. Default to 1.0. @@ -60,4 +65,4 @@ def topk_sampling(logits, top_k=10, top_p=1.0, temperature=1.0): logits = top_k_top_p_filtering(logits, top_k=top_k, top_p=top_p) # Sample token = torch.multinomial(F.softmax(logits, dim=-1), num_samples=1) - return token \ No newline at end of file + return token diff --git a/models/modules/scaling.py b/voicestar/modules/scaling.py similarity index 94% rename from models/modules/scaling.py rename to voicestar/modules/scaling.py index cd245ea..d5d0c9a 100644 --- a/models/modules/scaling.py +++ b/voicestar/modules/scaling.py @@ -1,5 +1,5 @@ -# cp from https://github.com/lifeiteng/vall-e/blob/main/valle/modules/scaling.py -# Copyright 2022 Xiaomi Corp. (authors: Daniel Povey) +# From https://github.com/lifeiteng/vall-e/blob/main/valle/modules/scaling.py (Apache 2.0 license) +# Copyright 2022 Xiaomi Corp. (authors: Daniel Povey) # # See ../../../../LICENSE for clarification regarding multiple authors # @@ -32,12 +32,14 @@ # from valle.utils import Transpose + class Transpose(nn.Identity): """(N, T, D) -> (N, D, T)""" def forward(self, input: torch.Tensor) -> torch.Tensor: return input.transpose(1, 2) - + + class ActivationBalancerFunction(torch.autograd.Function): @staticmethod def forward( @@ -97,9 +99,9 @@ def _compute_scale_factor( else: # below_threshold is 0 if x_abs_mean > min_abs, can be at most max_factor if # x_abs)_mean , min_abs. - below_threshold = ( - (min_abs - x_abs_mean) * (gain_factor / min_abs) - ).clamp(min=0, max=max_factor) + below_threshold = ((min_abs - x_abs_mean) * (gain_factor / min_abs)).clamp( + min=0, max=max_factor + ) above_threshold = ((x_abs_mean - max_abs) * (gain_factor / max_abs)).clamp( min=0, max=max_factor @@ -135,8 +137,7 @@ def _compute_sign_factor( # 0 if self.proportion_positive <= max_positive, else can be # as large as -max_factor. factor2 = ( - (proportion_positive - max_positive) - * (gain_factor / (1.0 - max_positive)) + (proportion_positive - max_positive) * (gain_factor / (1.0 - max_positive)) ).clamp_(min=0, max=max_factor) sign_factor = factor1 - factor2 # require min_positive != 0 or max_positive != 1: @@ -204,9 +205,7 @@ def forward( return ans @staticmethod - def backward( - ctx, ans_grad: Tensor - ) -> Tuple[Tensor, None, None, None, None]: + def backward(ctx, ans_grad: Tensor) -> Tuple[Tensor, None, None, None, None]: (is_same,) = ctx.saved_tensors x_grad = ans_grad * is_same.to(ans_grad.dtype) reflect = ctx.reflect @@ -255,9 +254,7 @@ def forward(ctx, x: Tensor, min_abs: float) -> Tensor: def backward(ctx, ans_grad: Tensor) -> Tuple[Tensor, None]: if ans_grad.dtype == torch.float16: return ( - random_cast_to_half( - ans_grad.to(torch.float32), min_abs=ctx.min_abs - ), + random_cast_to_half(ans_grad.to(torch.float32), min_abs=ctx.min_abs), None, ) else: @@ -275,11 +272,7 @@ def __init__(self, min_abs: float = 5.0e-06): self.min_abs = min_abs def forward(self, x: Tensor): - if ( - torch.jit.is_scripting() - or not self.training - or torch.jit.is_tracing() - ): + if torch.jit.is_scripting() or not self.training or torch.jit.is_tracing(): return x else: return RandomGradFunction.apply(x, self.min_abs) @@ -346,9 +339,9 @@ def backward(ctx, x_grad, *args): x = x_orig.transpose(ctx.channel_dim, -1).reshape(-1, num_channels) new_direction.requires_grad = False x = x - x.mean(dim=0) - x_var = (x ** 2).mean() + x_var = (x**2).mean() x_residual = x - coeffs * new_direction - x_residual_var = (x_residual ** 2).mean() + x_residual_var = (x_residual**2).mean() # `variance_proportion` is the proportion of the variance accounted for # by the top eigen-direction. This is to be minimized. variance_proportion = (x_var - x_residual_var) / (x_var + 1.0e-20) @@ -424,7 +417,7 @@ def forward(self, x: Tensor) -> Tensor: # gradients to allow the parameter to get back into the allowed region if it happens to exit it. eps = eps.clamp(min=self.eps_min, max=self.eps_max) scales = ( - torch.mean(x ** 2, dim=self.channel_dim, keepdim=True) + eps.exp() + torch.mean(x**2, dim=self.channel_dim, keepdim=True) + eps.exp() ) ** -0.5 return x * scales @@ -448,9 +441,7 @@ def ScaledLinear(*args, initial_scale: float = 1.0, **kwargs) -> nn.Linear: with torch.no_grad(): ans.weight[:] *= initial_scale if ans.bias is not None: - torch.nn.init.uniform_( - ans.bias, -0.1 * initial_scale, 0.1 * initial_scale - ) + torch.nn.init.uniform_(ans.bias, -0.1 * initial_scale, 0.1 * initial_scale) return ans @@ -479,9 +470,7 @@ def ScaledConv1d( with torch.no_grad(): ans.weight[:] *= initial_scale if ans.bias is not None: - torch.nn.init.uniform_( - ans.bias, -0.1 * initial_scale, 0.1 * initial_scale - ) + torch.nn.init.uniform_(ans.bias, -0.1 * initial_scale, 0.1 * initial_scale) return ans @@ -713,11 +702,7 @@ def __init__( self.register_buffer("count", torch.tensor(0, dtype=torch.int64)) def forward(self, x: Tensor) -> Tensor: - if ( - torch.jit.is_scripting() - or not x.requires_grad - or torch.jit.is_tracing() - ): + if torch.jit.is_scripting() or not x.requires_grad or torch.jit.is_tracing(): return _no_op(x) count = self.cpu_count @@ -835,11 +820,9 @@ def _whitening_metric(x: Tensor, num_groups: int): # the following expression is what we'd get if we took the matrix product # of each covariance and measured the mean of its trace, i.e. # the same as _diag(torch.matmul(x_covar, x_covar)).mean(). - x_covarsq_mean_diag = (x_covar ** 2).sum() / ( - num_groups * channels_per_group - ) + x_covarsq_mean_diag = (x_covar**2).sum() / (num_groups * channels_per_group) # this metric will be >= 1.0; the larger it is, the less 'white' the data was. - metric = x_covarsq_mean_diag / (x_covar_mean_diag ** 2 + 1.0e-20) + metric = x_covarsq_mean_diag / (x_covar_mean_diag**2 + 1.0e-20) return metric @@ -877,8 +860,7 @@ def backward(ctx, x_grad: Tensor): (metric - ctx.whitening_limit).relu().backward() penalty_grad = x_detached.grad scale = ctx.grad_scale * ( - x_grad.to(torch.float32).norm() - / (penalty_grad.norm() + 1.0e-20) + x_grad.to(torch.float32).norm() / (penalty_grad.norm() + 1.0e-20) ) penalty_grad = penalty_grad * scale return x_grad + penalty_grad.to(x_grad.dtype), None, None, None @@ -943,11 +925,7 @@ def forward(self, x: Tensor) -> Tensor: you use the returned value, or the graph will be freed and nothing will happen in backprop. """ - if ( - not x.requires_grad - or random.random() > self.prob - or self.grad_scale == 0 - ): + if not x.requires_grad or random.random() > self.prob or self.grad_scale == 0: return _no_op(x) else: if hasattr(self, "min_prob") and random.random() < 0.25: @@ -1069,27 +1047,21 @@ def forward(self, x: Tensor) -> Tensor: orig_x = x x = x.to(torch.float32) with torch.no_grad(): - x = x.transpose(self.channel_dim, -1).reshape( - -1, self.num_channels - ) + x = x.transpose(self.channel_dim, -1).reshape(-1, self.num_channels) x = x - x.mean(dim=0) new_direction, coeffs = self._find_direction_coeffs( x, self.max_eig_direction ) - x_var = (x ** 2).mean() + x_var = (x**2).mean() x_residual = x - coeffs * new_direction - x_residual_var = (x_residual ** 2).mean() + x_residual_var = (x_residual**2).mean() # `variance_proportion` is the proportion of the variance accounted for # by the top eigen-direction. - variance_proportion = (x_var - x_residual_var) / ( - x_var + 1.0e-20 - ) + variance_proportion = (x_var - x_residual_var) / (x_var + 1.0e-20) # ensure new direction is nonzero even if x == 0, by including `direction`. - self._set_direction( - 0.1 * self.max_eig_direction + new_direction - ) + self._set_direction(0.1 * self.max_eig_direction + new_direction) if random.random() < 0.01 or __name__ == "__main__": logging.info( @@ -1101,9 +1073,7 @@ def forward(self, x: Tensor) -> Tensor: # reach here, only near the beginning of training if we are # starting to diverge, should this constraint be active. cur_prob = self.cur_prob - self.cur_prob = ( - 1.0 # next time, do the update with probability 1.0. - ) + self.cur_prob = 1.0 # next time, do the update with probability 1.0. return MaxEigLimiterFunction.apply( orig_x, coeffs, new_direction, self.channel_dim, self.scale ) @@ -1152,9 +1122,7 @@ def _find_direction_coeffs( # `coeffs` are the coefficients of `prev_direction` in x. # actually represent the coeffs up to a constant positive factor. coeffs = (x * prev_direction).sum(dim=1, keepdim=True) + 1.0e-10 - cur_direction = (x * coeffs).sum(dim=0) / ( - (coeffs ** 2).sum() + 1.0e-20 - ) + cur_direction = (x * coeffs).sum(dim=0) / ((coeffs**2).sum() + 1.0e-20) return cur_direction, coeffs @@ -1194,9 +1162,9 @@ def forward(ctx, x: Tensor) -> Tensor: # floors), should be expectation-preserving. floor = -0.043637 ceil = 1.2 - d_scaled = (deriv - floor) * ( - 255.0 / (ceil - floor) - ) + torch.rand_like(deriv) + d_scaled = (deriv - floor) * (255.0 / (ceil - floor)) + torch.rand_like( + deriv + ) if __name__ == "__main__": # for self-testing only. assert d_scaled.min() >= 0.0 @@ -1299,9 +1267,7 @@ def _test_whiten(): def _test_activation_balancer_sign(): probs = torch.arange(0, 1, 0.01) N = 1000 - x = 1.0 * ( - (2.0 * (torch.rand(probs.numel(), N) < probs.unsqueeze(-1))) - 1.0 - ) + x = 1.0 * ((2.0 * (torch.rand(probs.numel(), N) < probs.unsqueeze(-1))) - 1.0) x = x.detach() x.requires_grad = True m = ActivationBalancer( @@ -1325,9 +1291,7 @@ def _test_activation_balancer_sign(): def _test_activation_balancer_magnitude(): magnitudes = torch.arange(0, 1, 0.01) N = 1000 - x = torch.sign(torch.randn(magnitudes.numel(), N)) * magnitudes.unsqueeze( - -1 - ) + x = torch.sign(torch.randn(magnitudes.numel(), N)) * magnitudes.unsqueeze(-1) x = x.detach() x.requires_grad = True m = ActivationBalancer( @@ -1359,8 +1323,8 @@ def _test_basic_norm(): y = m(x) assert y.shape == x.shape - x_rms = (x ** 2).mean().sqrt() - y_rms = (y ** 2).mean().sqrt() + x_rms = (x**2).mean().sqrt() + y_rms = (y**2).mean().sqrt() print("x rms = ", x_rms) print("y rms = ", y_rms) assert y_rms < x_rms @@ -1403,4 +1367,4 @@ def _test_softmax(): _test_activation_balancer_sign() _test_activation_balancer_magnitude() _test_basic_norm() - _test_double_swish_deriv() \ No newline at end of file + _test_double_swish_deriv() diff --git a/models/modules/transformer.py b/voicestar/modules/transformer.py similarity index 75% rename from models/modules/transformer.py rename to voicestar/modules/transformer.py index 3cbc70b..f152b48 100644 --- a/models/modules/transformer.py +++ b/voicestar/modules/transformer.py @@ -1,3 +1,12 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" + import copy, logging import numbers from functools import partial @@ -242,13 +251,9 @@ def __init__( norm1 = layer_norm_cls(d_model, eps=layer_norm_eps, **factory_kwargs) if layer_norm_cls == IdentityNorm: - norm2 = BalancedBasicNorm( - d_model, eps=layer_norm_eps, **factory_kwargs - ) + norm2 = BalancedBasicNorm(d_model, eps=layer_norm_eps, **factory_kwargs) else: - norm2 = layer_norm_cls( - d_model, eps=layer_norm_eps, **factory_kwargs - ) + norm2 = layer_norm_cls(d_model, eps=layer_norm_eps, **factory_kwargs) if adaptive_layer_norm: self.norm1 = AdaptiveLayerNorm(d_model, norm1) @@ -292,7 +297,7 @@ def forward( if isinstance(src, tuple): x, stage_embedding = src is_src_tuple = True - + if src_key_padding_mask is not None: _skpm_dtype = src_key_padding_mask.dtype if _skpm_dtype != torch.bool and not torch.is_floating_point( @@ -308,41 +313,52 @@ def forward( self.norm1(x, stage_embedding), src_mask, src_key_padding_mask, - past, sinu = sinu + past, + sinu=sinu, ) - out, present = out # present is the kvcache of the present timestep + out, present = out # present is the kvcache of the present timestep x = x + out x = x + self._ff_block(self.norm2(x, stage_embedding)) else: - out, attn = self._sa_block_attn(x, src_mask, src_key_padding_mask, past, sinu = sinu) - out, present = out # present is the kvcache of the present timestep + out, attn = self._sa_block_attn( + x, src_mask, src_key_padding_mask, past, sinu=sinu + ) + out, present = out # present is the kvcache of the present timestep x = self.norm1( x + out, stage_embedding, ) x = self.norm2(x + self._ff_block(x), stage_embedding) assert not is_src_tuple - # return (x, stage_embedding) + # return (x, stage_embedding) return (x, attn) else: if self.norm_first: out = self._sa_block( self.norm1(x, stage_embedding), src_mask, - src_key_padding_mask, past, sinu = sinu, q_sinu=pm_sinu['q'], k_sinu=pm_sinu['q'] + src_key_padding_mask, + past, + sinu=sinu, + q_sinu=pm_sinu["q"], + k_sinu=pm_sinu["q"], ) - out, present = out # present is the kvcache of the present timestep + out, present = out # present is the kvcache of the present timestep x = x + out x = x + self._ff_block(self.norm2(x, stage_embedding)) else: - out = self._sa_block(x, src_mask, src_key_padding_mask, sinu = sinu, q_sinu=pm_sinu['q'], k_sinu=pm_sinu['q']) - out, present = out # present is the kvcache of the present timestep - x = self.norm1( - x + out, - stage_embedding, past + out = self._sa_block( + x, + src_mask, + src_key_padding_mask, + sinu=sinu, + q_sinu=pm_sinu["q"], + k_sinu=pm_sinu["q"], ) + out, present = out # present is the kvcache of the present timestep + x = self.norm1(x + out, stage_embedding, past) x = self.norm2(x + self._ff_block(x), stage_embedding) - + if is_src_tuple: x = (x, stage_embedding) if present != None: @@ -356,9 +372,9 @@ def _sa_block( attn_mask: Optional[Tensor], key_padding_mask: Optional[Tensor], past: Optional[Tensor] = None, - sinu = None, - q_sinu = None, - k_sinu = None + sinu=None, + q_sinu=None, + k_sinu=None, ) -> Tensor: x = self.self_attn( x, @@ -368,9 +384,9 @@ def _sa_block( key_padding_mask=key_padding_mask, need_weights=False, past=past, - sinu = sinu, - q_sinu = q_sinu, - k_sinu = k_sinu + sinu=sinu, + q_sinu=q_sinu, + k_sinu=k_sinu, ) x, present = x return self.dropout1(x), present @@ -390,7 +406,7 @@ def _sa_block_attn( attn_mask=attn_mask, key_padding_mask=key_padding_mask, need_weights=True, - past=past + past=past, ) x, present = x return (self.dropout1(x), present), attn @@ -400,22 +416,37 @@ def _ff_block(self, x: Tensor) -> Tensor: x = self.linear2(self.dropout(self.activation(self.linear1(x)))) return self.dropout2(x) -def pre_compute_sinusoidal(dim, base, max_len = 10000): # 4000 max length equivalent of mimi code is 320s, as mimi is 12.5hz - inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2, dtype=torch.int64).float() / dim)) - position_ids_expanded = torch.arange(0, max_len, dtype=torch.float32).unsqueeze(1) # [x_len_max, 1] - inv_freq_expanded = inv_freq.unsqueeze(0).float() # [1, d//2] - freqs = position_ids_expanded @ inv_freq_expanded # [x_len_max, d//2] - freqs = torch.cat((freqs, freqs), dim=-1).unsqueeze(0) # [1, x_len_max, d] + +def pre_compute_sinusoidal( + dim, base, max_len=10000 +): # 4000 max length equivalent of mimi code is 320s, as mimi is 12.5hz + inv_freq = 1.0 / ( + base ** (torch.arange(0, dim, 2, dtype=torch.int64).float() / dim) + ) + position_ids_expanded = torch.arange(0, max_len, dtype=torch.float32).unsqueeze( + 1 + ) # [x_len_max, 1] + inv_freq_expanded = inv_freq.unsqueeze(0).float() # [1, d//2] + freqs = position_ids_expanded @ inv_freq_expanded # [x_len_max, d//2] + freqs = torch.cat((freqs, freqs), dim=-1).unsqueeze(0) # [1, x_len_max, d] return {"sin": freqs.sin(), "cos": freqs.cos()} -def pre_compute_freqs(dim, base, max_len = 10000): # 4000 max length equivalent of mimi code is 320s, as mimi is 12.5hz - inv_freq = 1.0 / (base ** (torch.arange(0, dim, 2, dtype=torch.int64).float() / dim)) - position_ids_expanded = torch.arange(0, max_len, dtype=torch.float32).unsqueeze(1) # [x_len_max, 1] - inv_freq_expanded = inv_freq.unsqueeze(0).float() # [1, d//2] - freqs = position_ids_expanded @ inv_freq_expanded # [x_len_max, d//2] - freqs = torch.cat((freqs, freqs), dim=-1).unsqueeze(0) # [1, x_len_max, d] + +def pre_compute_freqs( + dim, base, max_len=10000 +): # 4000 max length equivalent of mimi code is 320s, as mimi is 12.5hz + inv_freq = 1.0 / ( + base ** (torch.arange(0, dim, 2, dtype=torch.int64).float() / dim) + ) + position_ids_expanded = torch.arange(0, max_len, dtype=torch.float32).unsqueeze( + 1 + ) # [x_len_max, 1] + inv_freq_expanded = inv_freq.unsqueeze(0).float() # [1, d//2] + freqs = position_ids_expanded @ inv_freq_expanded # [x_len_max, d//2] + freqs = torch.cat((freqs, freqs), dim=-1).unsqueeze(0) # [1, x_len_max, d] return freqs + class TransformerEncoder(nn.Module): r"""TransformerEncoder is a stack of N encoder layers. Users can build the BERT(https://arxiv.org/abs/1810.04805) model with corresponding parameters. @@ -434,9 +465,19 @@ class TransformerEncoder(nn.Module): >>> src = torch.rand(10, 32, 512) >>> out = transformer_encoder(src) """ + __constants__ = ["norm"] - def __init__(self, encoder_layer, num_layers, norm=None, rope_base=None, d_model=None, nhead=None, args=None): + def __init__( + self, + encoder_layer, + num_layers, + norm=None, + rope_base=None, + d_model=None, + nhead=None, + args=None, + ): super(TransformerEncoder, self).__init__() self.layers = _get_clones(encoder_layer, num_layers) self.num_layers = num_layers @@ -450,10 +491,10 @@ def __init__(self, encoder_layer, num_layers, norm=None, rope_base=None, d_model if rope_base is not None: if self.progress_no_multiple: - self.pm_freqs = pre_compute_freqs(d_model//nhead, rope_base) + self.pm_freqs = pre_compute_freqs(d_model // nhead, rope_base) self.sinu = None else: - self.sinu = pre_compute_sinusoidal(d_model/nhead, rope_base) + self.sinu = pre_compute_sinusoidal(d_model / nhead, rope_base) self.pm_freqs = None # logging.info(f"get precomputed sinusoidal for {rope_base=}: {self.sinu=}") else: @@ -466,7 +507,7 @@ def forward( mask: Optional[Tensor] = None, src_key_padding_mask: Optional[Tensor] = None, return_layer_states: bool = False, - need_weights:Optional[bool] = False, + need_weights: Optional[bool] = False, past: Optional[Tensor] = None, ) -> Tensor: r"""Pass the input through the encoder layers in turn. @@ -490,7 +531,7 @@ def forward( output, src_mask=mask, src_key_padding_mask=src_key_padding_mask, - past=past + past=past, ) layer_states.append(output[0]) @@ -509,7 +550,7 @@ def forward( src_mask=mask, src_key_padding_mask=src_key_padding_mask, need_weights=True, - past=past + past=past, ) layer_attn.append(output[1]) @@ -517,7 +558,7 @@ def forward( output = self.norm(output) return layer_attn, output - + output = src all_present = [] if self.sinu is not None: @@ -531,13 +572,15 @@ def forward( if src_key_padding_mask != None: query_lens = (~src_key_padding_mask).int().sum(-1).to(output.device) else: - query_lens = torch.tensor([output.shape[1]]*output.shape[0]).to(output.device) - assert query_lens.ndim==1, query_lens - q_lens_expanded = query_lens.unsqueeze(-1).unsqueeze(-1) # [B, 1, 1] + query_lens = torch.tensor([output.shape[1]] * output.shape[0]).to( + output.device + ) + assert query_lens.ndim == 1, query_lens + q_lens_expanded = query_lens.unsqueeze(-1).unsqueeze(-1) # [B, 1, 1] query_ids_multiple = q_lens_expanded / (q_lens_expanded - 1) - q_emb = self.pm_freqs * query_ids_multiple # [B, q_len_max, d] + q_emb = self.pm_freqs * query_ids_multiple # [B, q_len_max, d] q_emb = q_emb / q_lens_expanded * self.progress_scale - q_cos = q_emb.cos().unsqueeze(1) # [B, 1, q_len_max, d] # 1 is for nhead + q_cos = q_emb.cos().unsqueeze(1) # [B, 1, q_len_max, d] # 1 is for nhead q_sin = q_emb.sin().unsqueeze(1) self.pm_sinu = {"q": {"cos": q_cos, "sin": q_sin}} else: @@ -546,7 +589,10 @@ def forward( output = {"input": output, "sinu": self.sinu, "pm_sinu": self.pm_sinu} for n_layer, mod in enumerate(self.layers): output = mod( - output, src_mask=mask, src_key_padding_mask=src_key_padding_mask, past=None if past is None else past[n_layer] + output, + src_mask=mask, + src_key_padding_mask=src_key_padding_mask, + past=None if past is None else past[n_layer], ) if isinstance(output, list): output, present = output @@ -558,7 +604,9 @@ def forward( if self.norm is not None: output = self.norm(output) if all_present != []: - all_present = torch.stack(all_present, dim=0) # (num_layers, 2, batch_size, num_heads, seq_len, head_dim) + all_present = torch.stack( + all_present, dim=0 + ) # (num_layers, 2, batch_size, num_heads, seq_len, head_dim) output = [output, all_present] return output @@ -630,26 +678,16 @@ def __init__( self.activation = activation if adaptive_layer_norm: - norm1 = layer_norm_cls( - d_model, eps=layer_norm_eps, **factory_kwargs - ) - norm2 = layer_norm_cls( - d_model, eps=layer_norm_eps, **factory_kwargs - ) - norm3 = layer_norm_cls( - d_model, eps=layer_norm_eps, **factory_kwargs - ) + norm1 = layer_norm_cls(d_model, eps=layer_norm_eps, **factory_kwargs) + norm2 = layer_norm_cls(d_model, eps=layer_norm_eps, **factory_kwargs) + norm3 = layer_norm_cls(d_model, eps=layer_norm_eps, **factory_kwargs) self.norm1 = AdaptiveLayerNorm(d_model, norm1) self.norm2 = AdaptiveLayerNorm(d_model, norm2) self.norm3 = AdaptiveLayerNorm(d_model, norm3) else: - self.norm1 = layer_norm_cls( - d_model, eps=layer_norm_eps, **factory_kwargs - ) - self.norm2 = layer_norm_cls( - d_model, eps=layer_norm_eps, **factory_kwargs - ) + self.norm1 = layer_norm_cls(d_model, eps=layer_norm_eps, **factory_kwargs) + self.norm2 = layer_norm_cls(d_model, eps=layer_norm_eps, **factory_kwargs) if layer_norm_cls == IdentityNorm: self.norm3 = BalancedBasicNorm( d_model, eps=layer_norm_eps, **factory_kwargs @@ -667,8 +705,12 @@ def forward( memory_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, memory_key_padding_mask: Optional[Tensor] = None, - tgt_is_causal: Optional[bool] = False, # for compatibility with the nn.TransformerDecoder, not used - memory_is_causal: Optional[bool] = False, # for compatibility with the nn.TransformerDecoder, not used + tgt_is_causal: Optional[ + bool + ] = False, # for compatibility with the nn.TransformerDecoder, not used + memory_is_causal: Optional[ + bool + ] = False, # for compatibility with the nn.TransformerDecoder, not used past: Optional[Tensor] = None, ) -> Tensor: r"""Pass the inputs (and mask) through the decoder layer. @@ -706,14 +748,23 @@ def forward( # past stores the kvcache for self-attention, and it can also be used to infer q_offset if past is not None and past.ndim > 2: - q_offset = past[0].shape[-2] # past is (2, batch_size, num_heads, seq_len, head_dim), 2 contains [k, v], these are for self-attn, therefore also reflect the length of q + q_offset = past[0].shape[ + -2 + ] # past is (2, batch_size, num_heads, seq_len, head_dim), 2 contains [k, v], these are for self-attn, therefore also reflect the length of q else: q_offset = 0 - if self.norm_first: temp = self._sa_block( - self.norm1(x, stage_embedding), tgt_mask, tgt_key_padding_mask, q_sinu=pm_sinu['q'], k_sinu=pm_sinu['q'], sinu=sinu, args = args, past=past, q_offset=q_offset + self.norm1(x, stage_embedding), + tgt_mask, + tgt_key_padding_mask, + q_sinu=pm_sinu["q"], + k_sinu=pm_sinu["q"], + sinu=sinu, + args=args, + past=past, + q_offset=q_offset, ) present = temp[1] x = x + temp[0] @@ -721,7 +772,12 @@ def forward( self.norm2(x, stage_embedding), memory, memory_mask, - memory_key_padding_mask, q_sinu=pm_sinu['q'], k_sinu=pm_sinu['k'], sinu=sinu, args = args, q_offset=q_offset + memory_key_padding_mask, + q_sinu=pm_sinu["q"], + k_sinu=pm_sinu["k"], + sinu=sinu, + args=args, + q_offset=q_offset, ) if isinstance(cross_out, dict): attention_weights = cross_out["attention_weights"] @@ -731,27 +787,44 @@ def forward( x = x + cross_out x = x + self._ff_block(self.norm3(x, stage_embedding)) else: - temp = self._sa_block(x, tgt_mask, tgt_key_padding_mask, q_sinu=pm_sinu['q'], k_sinu=pm_sinu['q'], sinu=sinu, args = args, past=past, q_offset=q_offset) + temp = self._sa_block( + x, + tgt_mask, + tgt_key_padding_mask, + q_sinu=pm_sinu["q"], + k_sinu=pm_sinu["q"], + sinu=sinu, + args=args, + past=past, + q_offset=q_offset, + ) present = temp[1] x = self.norm1( x + temp[0], stage_embedding, ) cross_out = self._mha_block( - x, memory, memory_mask, memory_key_padding_mask, q_sinu=pm_sinu['q'], k_sinu=pm_sinu['k'], sinu=sinu, args=args, q_offset=q_offset - ) + x, + memory, + memory_mask, + memory_key_padding_mask, + q_sinu=pm_sinu["q"], + k_sinu=pm_sinu["k"], + sinu=sinu, + args=args, + q_offset=q_offset, + ) if isinstance(cross_out, dict): attention_weights = cross_out["attention_weights"] cross_out = cross_out["x"] else: - attention_weights = None + attention_weights = None x = self.norm2( - x - + cross_out, + x + cross_out, stage_embedding, ) x = self.norm3(x + self._ff_block(x), stage_embedding) - + if attention_weights is not None: x = {"x": x, "attention_weights": attention_weights} if tgt_is_tuple: @@ -768,10 +841,10 @@ def _sa_block( key_padding_mask: Optional[Tensor], q_sinu=None, k_sinu=None, - sinu = None, - args = None, - past = None, - q_offset = 0 + sinu=None, + args=None, + past=None, + q_offset=0, ) -> Tensor: # if past is not None and past.ndim > 2: # print(f"self-attn, k len: {past[0].shape[-2] + x.shape[-2]}, q len: {x.shape[-2]} q_offset: {q_offset}") @@ -784,11 +857,11 @@ def _sa_block( attn_mask=attn_mask, key_padding_mask=key_padding_mask, need_weights=False, - q_sinu = q_sinu, - k_sinu = k_sinu, - sinu = sinu, - past = past, - q_offset = q_offset + q_sinu=q_sinu, + k_sinu=k_sinu, + sinu=sinu, + past=past, + q_offset=q_offset, ) x, present = x return self.dropout1(x), present @@ -800,11 +873,11 @@ def _mha_block( mem: Tensor, attn_mask: Optional[Tensor], key_padding_mask: Optional[Tensor], - q_sinu = None, - k_sinu = None, - sinu = None, - args = None, - q_offset = 0 + q_sinu=None, + k_sinu=None, + sinu=None, + args=None, + q_offset=0, ) -> Tensor: # print(f"cross-attn, k len: {mem.shape[-2]}, q len: {x.shape[-2]} q_offset: {q_offset}") x = self.multihead_attn( @@ -814,16 +887,16 @@ def _mha_block( attn_mask=attn_mask, key_padding_mask=key_padding_mask, need_weights=False, - q_sinu = q_sinu, - k_sinu = k_sinu, - sinu = sinu, - args = args, - q_offset = q_offset + q_sinu=q_sinu, + k_sinu=k_sinu, + sinu=sinu, + args=args, + q_offset=q_offset, ) if len(x) == 2 and isinstance(x[0], dict) and "attention_weights" in x[0]: x, present = x - attention_weights = x['attention_weights'] - x = x['attn_output'] + attention_weights = x["attention_weights"] + x = x["attn_output"] return {"x": self.dropout2(x), "attention_weights": attention_weights} elif len(x) == 2: x = x[0] @@ -845,30 +918,29 @@ def _get_activation_fn(activation: str) -> Callable[[Tensor], Tensor]: elif activation == "gelu": return F.gelu - raise RuntimeError( - "activation should be relu/gelu, not {}".format(activation) - ) + raise RuntimeError("activation should be relu/gelu, not {}".format(activation)) + + def _generate_square_subsequent_mask( - sz: int, - device: Optional[torch.device] = None, - dtype: Optional[torch.dtype] = None, + sz: int, + device: Optional[torch.device] = None, + dtype: Optional[torch.dtype] = None, ) -> Tensor: r"""Generate a square causal mask for the sequence. The masked positions are filled with float('-inf'). Unmasked positions are filled with float(0.0). """ if device is None: - device = torch.device('cpu') + device = torch.device("cpu") if dtype is None: dtype = torch.float32 return torch.triu( - torch.full((sz, sz), float('-inf'), dtype=dtype, device=device), + torch.full((sz, sz), float("-inf"), dtype=dtype, device=device), diagonal=1, ) -def _get_seq_len( - src: Tensor, - batch_first: bool -) -> Optional[int]: + + +def _get_seq_len(src: Tensor, batch_first: bool) -> Optional[int]: if src.is_nested: return None @@ -882,10 +954,11 @@ def _get_seq_len( seq_len_pos = 1 if batch_first else 0 return src_size[seq_len_pos] + def _detect_is_causal_mask( - mask: Optional[Tensor], - is_causal: Optional[bool] = None, - size: Optional[int] = None, + mask: Optional[Tensor], + is_causal: Optional[bool] = None, + size: Optional[int] = None, ) -> bool: """Return whether the given attention mask is causal. @@ -907,12 +980,13 @@ def _detect_is_causal_mask( Otherwise, checks for any causal mask. """ # Prevent type refinement - make_causal = (is_causal is True) + make_causal = is_causal is True if is_causal is None and mask is not None: sz = size if size is not None else mask.size(-2) causal_comparison = _generate_square_subsequent_mask( - sz, device=mask.device, dtype=mask.dtype) + sz, device=mask.device, dtype=mask.dtype + ) # Do not use `torch.equal` so we handle batched masks by # broadcasting the comparison. @@ -923,6 +997,7 @@ def _detect_is_causal_mask( return make_causal + class TransformerDecoder(nn.Module): r"""TransformerDecoder is a stack of N decoder layers. @@ -939,17 +1014,17 @@ class TransformerDecoder(nn.Module): >>> out = transformer_decoder(tgt, memory) """ - __constants__ = ['norm'] + __constants__ = ["norm"] def __init__( self, decoder_layer: "TransformerDecoderLayer", num_layers: int, norm: Optional[nn.Module] = None, - rope_base=None, - d_model=None, + rope_base=None, + d_model=None, nhead=None, - args=None + args=None, ) -> None: super().__init__() torch._C._log_api_usage_once(f"torch.nn.modules.{self.__class__.__name__}") @@ -957,22 +1032,32 @@ def __init__( self.num_layers = num_layers self.norm = norm self.args = args - if getattr(self.args, 'decoder_regular_rope', False): - self.sinu = pre_compute_sinusoidal(d_model/nhead, rope_base) + if getattr(self.args, "decoder_regular_rope", False): + self.sinu = pre_compute_sinusoidal(d_model / nhead, rope_base) self.pm_freqs = None else: self.sinu = None if rope_base is not None: - self.pm_freqs = pre_compute_freqs(d_model/nhead, rope_base) + self.pm_freqs = pre_compute_freqs(d_model / nhead, rope_base) # logging.info(f"get precomputed freqs for {rope_base=}: {self.freqs=}") else: self.pm_freqs = None self.progress_scale = getattr(self.args, "progress_scale", 1.0) - def forward(self, tgt: Tensor, memory: Tensor, tgt_mask: Optional[Tensor] = None, - memory_mask: Optional[Tensor] = None, tgt_key_padding_mask: Optional[Tensor] = None, - memory_key_padding_mask: Optional[Tensor] = None, tgt_is_causal: Optional[bool] = None, - memory_is_causal: bool = False, query_lens: Optional[Tensor] = None, key_lens: Optional[Tensor] = None, past: Optional[Tensor] = None) -> Tensor: + def forward( + self, + tgt: Tensor, + memory: Tensor, + tgt_mask: Optional[Tensor] = None, + memory_mask: Optional[Tensor] = None, + tgt_key_padding_mask: Optional[Tensor] = None, + memory_key_padding_mask: Optional[Tensor] = None, + tgt_is_causal: Optional[bool] = None, + memory_is_causal: bool = False, + query_lens: Optional[Tensor] = None, + key_lens: Optional[Tensor] = None, + past: Optional[Tensor] = None, + ) -> Tensor: r"""Pass the inputs (and mask) through the decoder layer in turn. Args: @@ -1011,21 +1096,42 @@ def forward(self, tgt: Tensor, memory: Tensor, tgt_mask: Optional[Tensor] = None self.sinu[key] = self.sinu[key].to(output.device) if self.pm_freqs is not None: assert self.sinu is None - if not self.training and hasattr(self, "pm_sinu") and past is not None and past[0].ndim > 2: # inference mode, will use cached sinu for the same example - assert self.pm_sinu['q'] is not None and self.pm_sinu['k'] is not None + if ( + not self.training + and hasattr(self, "pm_sinu") + and past is not None + and past[0].ndim > 2 + ): # inference mode, will use cached sinu for the same example + assert self.pm_sinu["q"] is not None and self.pm_sinu["k"] is not None # check batch size, need to modify the batch size if we use multi_trial during inference - if self.pm_sinu['q']['cos'].shape[0] != tgt.shape[0]: - if self.pm_sinu['q']['cos'].shape[0] > tgt.shape[0]: - self.pm_sinu['q']['cos'] = self.pm_sinu['q']['cos'][:tgt.shape[0]] - self.pm_sinu['q']['sin'] = self.pm_sinu['q']['sin'][:tgt.shape[0]] - self.pm_sinu['k']['cos'] = self.pm_sinu['k']['cos'][:tgt.shape[0]] - self.pm_sinu['k']['sin'] = self.pm_sinu['k']['sin'][:tgt.shape[0]] + if self.pm_sinu["q"]["cos"].shape[0] != tgt.shape[0]: + if self.pm_sinu["q"]["cos"].shape[0] > tgt.shape[0]: + self.pm_sinu["q"]["cos"] = self.pm_sinu["q"]["cos"][ + : tgt.shape[0] + ] + self.pm_sinu["q"]["sin"] = self.pm_sinu["q"]["sin"][ + : tgt.shape[0] + ] + self.pm_sinu["k"]["cos"] = self.pm_sinu["k"]["cos"][ + : tgt.shape[0] + ] + self.pm_sinu["k"]["sin"] = self.pm_sinu["k"]["sin"][ + : tgt.shape[0] + ] else: - assert self.pm_sinu['q']['cos'].shape[0] == 1 - self.pm_sinu['q']['cos'] = self.pm_sinu['q']['cos'].repeat(tgt.shape[0], 1, 1, 1) - self.pm_sinu['q']['sin'] = self.pm_sinu['q']['sin'].repeat(tgt.shape[0], 1, 1, 1) - self.pm_sinu['k']['cos'] = self.pm_sinu['k']['cos'].repeat(tgt.shape[0], 1, 1, 1) - self.pm_sinu['k']['sin'] = self.pm_sinu['k']['sin'].repeat(tgt.shape[0], 1, 1, 1) + assert self.pm_sinu["q"]["cos"].shape[0] == 1 + self.pm_sinu["q"]["cos"] = self.pm_sinu["q"]["cos"].repeat( + tgt.shape[0], 1, 1, 1 + ) + self.pm_sinu["q"]["sin"] = self.pm_sinu["q"]["sin"].repeat( + tgt.shape[0], 1, 1, 1 + ) + self.pm_sinu["k"]["cos"] = self.pm_sinu["k"]["cos"].repeat( + tgt.shape[0], 1, 1, 1 + ) + self.pm_sinu["k"]["sin"] = self.pm_sinu["k"]["sin"].repeat( + tgt.shape[0], 1, 1, 1 + ) pass else: self.pm_freqs = self.pm_freqs.to(output.device) @@ -1033,38 +1139,51 @@ def forward(self, tgt: Tensor, memory: Tensor, tgt_mask: Optional[Tensor] = None query_lens = (~tgt_key_padding_mask).int().sum(-1).to(tgt.device) if key_lens is None: key_lens = (~memory_key_padding_mask).int().sum(-1).to(tgt.device) - assert key_lens.ndim==1, key_lens - assert query_lens.ndim==1, query_lens - q_lens_expanded = query_lens.unsqueeze(-1).unsqueeze(-1) # [B, 1, 1] - k_lens_expanded = key_lens.unsqueeze(-1).unsqueeze(-1) # [B, 1, 1] + assert key_lens.ndim == 1, key_lens + assert query_lens.ndim == 1, query_lens + q_lens_expanded = query_lens.unsqueeze(-1).unsqueeze(-1) # [B, 1, 1] + k_lens_expanded = key_lens.unsqueeze(-1).unsqueeze(-1) # [B, 1, 1] query_ids_multiple = q_lens_expanded / (q_lens_expanded - 1) key_ids_multiple = k_lens_expanded / (k_lens_expanded - 1) - q_emb = self.pm_freqs * query_ids_multiple # [B, q_len_max, d] - k_emb = self.pm_freqs * key_ids_multiple # [B, k_len_max, d] + q_emb = self.pm_freqs * query_ids_multiple # [B, q_len_max, d] + k_emb = self.pm_freqs * key_ids_multiple # [B, k_len_max, d] q_emb = q_emb / q_lens_expanded * self.progress_scale k_emb = k_emb / k_lens_expanded * self.progress_scale - q_cos = q_emb.cos().unsqueeze(1) # [B, 1, q_len_max, d] # 1 is for nhead + q_cos = q_emb.cos().unsqueeze( + 1 + ) # [B, 1, q_len_max, d] # 1 is for nhead q_sin = q_emb.sin().unsqueeze(1) k_cos = k_emb.cos().unsqueeze(1) k_sin = k_emb.sin().unsqueeze(1) - self.pm_sinu = {"q": {"cos": q_cos, "sin": q_sin}, "k": {"cos": k_cos, "sin": k_sin}} + self.pm_sinu = { + "q": {"cos": q_cos, "sin": q_sin}, + "k": {"cos": k_cos, "sin": k_sin}, + } else: self.pm_sinu = {"q": None, "k": None} - output = {"input": output, "pm_sinu": self.pm_sinu, "sinu": self.sinu, "args": self.args} + output = { + "input": output, + "pm_sinu": self.pm_sinu, + "sinu": self.sinu, + "args": self.args, + } if past != None: all_present = [] if self.training and getattr(self.args, "attention_alignment_loss", 0): all_attn_weights = [] for i, mod in enumerate(self.layers): - output = mod(output, memory, tgt_mask=tgt_mask, - memory_mask=memory_mask, - tgt_key_padding_mask=tgt_key_padding_mask, - memory_key_padding_mask=memory_key_padding_mask, - past=past[i] if past != None else None - # tgt_is_causal=tgt_is_causal, - # memory_is_causal=memory_is_causal - ) + output = mod( + output, + memory, + tgt_mask=tgt_mask, + memory_mask=memory_mask, + tgt_key_padding_mask=tgt_key_padding_mask, + memory_key_padding_mask=memory_key_padding_mask, + past=past[i] if past != None else None, + # tgt_is_causal=tgt_is_causal, + # memory_is_causal=memory_is_causal + ) if past != None: output, cur_present = output all_present.append(cur_present) @@ -1073,17 +1192,24 @@ def forward(self, tgt: Tensor, memory: Tensor, tgt_mask: Optional[Tensor] = None all_attn_weights.append(current_attn_weights) output = output["x"] if self.sinu is not None or self.pm_sinu is not None: - output = {"input": output, "pm_sinu": self.pm_sinu, "sinu": self.sinu, "args": self.args} + output = { + "input": output, + "pm_sinu": self.pm_sinu, + "sinu": self.sinu, + "args": self.args, + } if self.pm_sinu is not None or self.sinu is not None: output = output["input"] if self.norm is not None: output = self.norm(output) if self.training and getattr(self.args, "attention_alignment_loss", 0): - assert len(all_attn_weights) == self.num_layers, f"{len(all_attn_weights)=}, {self.num_layers=}" + assert ( + len(all_attn_weights) == self.num_layers + ), f"{len(all_attn_weights)=}, {self.num_layers=}" output = {"output": output, "attention_weights": all_attn_weights} if past != None: all_present = torch.stack(all_present, dim=0) output = [output, all_present] else: output = [output, None] - return output \ No newline at end of file + return output diff --git a/models/modules/utils.py b/voicestar/modules/utils.py similarity index 79% rename from models/modules/utils.py rename to voicestar/modules/utils.py index c8e8788..e074cd3 100644 --- a/models/modules/utils.py +++ b/voicestar/modules/utils.py @@ -1,5 +1,13 @@ -import torch +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT +Copyright (c) 2025 Puyuan Peng +""" + +import torch def make_pad_mask(lengths: torch.Tensor, max_len: int = 0) -> torch.Tensor: """ @@ -28,9 +36,12 @@ def make_pad_mask(lengths: torch.Tensor, max_len: int = 0) -> torch.Tensor: return expaned_lengths >= lengths.unsqueeze(-1) + def generate_partial_autoregressive_mask(sz, start, end): mask = torch.zeros(sz, sz).bool() - mask[start:end, start:end] = torch.triu(torch.ones(end-start, end-start,dtype=torch.bool), diagonal=1) + mask[start:end, start:end] = torch.triu( + torch.ones(end - start, end - start, dtype=torch.bool), diagonal=1 + ) mask[:start, start:end] = True mask[end:, start:end] = True return mask diff --git a/models/modules/visualizer.py b/voicestar/modules/visualizer.py similarity index 88% rename from models/modules/visualizer.py rename to voicestar/modules/visualizer.py index f8ac5bc..cab289c 100644 --- a/models/modules/visualizer.py +++ b/voicestar/modules/visualizer.py @@ -1,6 +1,5 @@ -# cp from https://github.com/lifeiteng/vall-e/blob/main/valle/models/visualizer.py -#!/usr/bin/env python3 -# Copyright 2023 (authors: Feiteng Li) +# From https://github.com/lifeiteng/vall-e/blob/main/valle/models/visualizer.py (Apache 2.0 license) +# Copyright 2023 (authors: Feiteng Li) # # See ../../../../LICENSE for clarification regarding multiple authors # @@ -33,9 +32,7 @@ def visualize( text_tokens = batch["text_tokens"].to("cpu").detach().numpy() text_tokens_lens = batch["text_tokens_lens"].to("cpu").detach().numpy() audio_features = batch["audio_features"].to("cpu").detach().numpy() - audio_features_lens = ( - batch["audio_features_lens"].to("cpu").detach().numpy() - ) + audio_features_lens = batch["audio_features_lens"].to("cpu").detach().numpy() assert text_tokens.ndim == 2 utt_ids, texts = batch["utt_id"], batch["text"] @@ -44,9 +41,7 @@ def visualize( decoder_outputs = predicts[1] if isinstance(decoder_outputs, list): decoder_outputs = decoder_outputs[-1] - decoder_outputs = ( - decoder_outputs.to("cpu").type(torch.float32).detach().numpy() - ) + decoder_outputs = decoder_outputs.to("cpu").type(torch.float32).detach().numpy() vmin, vmax = 0, 1024 # Encodec if decoder_outputs.dtype == np.float32: @@ -104,4 +99,4 @@ def visualize( plt.colorbar() plt.savefig(f"{output_dir}/{utt_id}.png") - plt.close() \ No newline at end of file + plt.close() diff --git a/voicestar/utils.py b/voicestar/utils.py new file mode 100644 index 0000000..15b51d5 --- /dev/null +++ b/voicestar/utils.py @@ -0,0 +1,32 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" +import os +import random +import numpy as np +import torch +import torchaudio + +def seed_everything(seed=1): + os.environ['PYTHONHASHSEED'] = str(seed) + random.seed(seed) + np.random.seed(seed) + torch.manual_seed(seed) + torch.cuda.manual_seed(seed) + torch.backends.cudnn.benchmark = False + torch.backends.cudnn.deterministic = True + +def estimate_duration(ref_audio_path, text): + """ + Estimate duration based on seconds per character from the reference audio. + """ + info = torchaudio.info(ref_audio_path) + audio_duration = info.num_frames / info.sample_rate + length_text = max(len(text), 1) + spc = audio_duration / length_text # seconds per character + return len(text) * spc diff --git a/voicestar/voicestar.py b/voicestar/voicestar.py new file mode 100644 index 0000000..1b57f9d --- /dev/null +++ b/voicestar/voicestar.py @@ -0,0 +1,1042 @@ +""" +VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate + +GitHub: https://github.com/jasonppy/VoiceStar +License: MIT + +Copyright (c) 2025 Puyuan Peng +""" +import random, os, copy +from typing import Dict, Iterator, List, Tuple, Union +import logging +import numpy as np + +import torch +import torch.nn as nn +import torch.nn.functional as F +from torchmetrics.classification import MulticlassAccuracy +import torch.distributed as dist + +from voicestar.modules.utils import make_pad_mask, generate_partial_autoregressive_mask + +from voicestar.modules.embedding import ( + SinePositionalEmbedding, + TokenEmbedding, + SinePositionalEmbedding_progress, +) +from voicestar.modules.transformer import ( + AdaptiveLayerNorm, + LayerNorm, + TransformerDecoderLayer, + TransformerDecoder, + TransformerEncoder, + TransformerEncoderLayer, +) + + +def top_k_top_p_filtering( + logits, + top_k=0, + top_p=1.0, + min_p=1.0, + filter_value=-float("Inf"), + min_tokens_to_keep=1, +): + """Filter a distribution of logits using top-k and/or nucleus (top-p) filtering + Args: + logits: logits distribution shape (batch size, vocabulary size) + if top_k > 0: keep only top k tokens with highest probability (top-k filtering). + if top_p < 1.0: keep the top tokens with cumulative probability >= top_p (nucleus filtering). + Nucleus filtering is described in Holtzman et al. (http://arxiv.org/abs/1904.09751) + Make sure we keep at least min_tokens_to_keep per batch example in the output + From: https://gist.github.com/thomwolf/1a5a29f6962089e871b94cbd09daf317 + """ + if min_p < 1.0: + probs = F.softmax(logits, dim=-1) + indices_to_remove = probs < min_p + if not torch.any(indices_to_remove.sum(-1) == logits.size(-1)): + logits[indices_to_remove] = filter_value + top_k = 0 + top_p = 1.0 + # else will use other types of sampling, or no filtering + + # If top_k is a single integer + if isinstance(top_k, int) and top_k > 0: + # Safety check to ensure we don't ask for more than available + top_k = min(max(top_k, min_tokens_to_keep), logits.size(-1)) + + # Remove all tokens with a probability less than the last token of the top-k + threshold = torch.topk(logits, top_k, dim=-1)[0][..., -1, None] + indices_to_remove = logits < threshold + logits[indices_to_remove] = filter_value + + # If top_k is a list, assume it has the same length as M + elif isinstance(top_k, list): + # Ensure the length matches the first dimension + assert len(top_k) == logits.size( + 0 + ), f"top_k list length ({len(top_k)}) must match logits.size(0) ({logits.size(0)})" + + for i in range(logits.size(0)): + k_i = top_k[i] + if k_i > 0: + # Safety check + k_i = min(max(k_i, min_tokens_to_keep), logits.size(-1)) + row_threshold = torch.topk(logits[i], k_i, dim=-1)[0][-1] + indices_to_remove_i = logits[i] < row_threshold + logits[i, indices_to_remove_i] = filter_value + + if top_p < 1.0: + sorted_logits, sorted_indices = torch.sort(logits, descending=True) + cumulative_probs = torch.cumsum(F.softmax(sorted_logits, dim=-1), dim=-1) + + # Remove tokens with cumulative probability above the threshold (token with 0 are kept) + sorted_indices_to_remove = cumulative_probs > top_p + if min_tokens_to_keep > 1: + # Keep at least min_tokens_to_keep (set to min_tokens_to_keep-1 because we add the first one below) + sorted_indices_to_remove[..., :min_tokens_to_keep] = 0 + # Shift the indices to the right to keep also the first token above the threshold + sorted_indices_to_remove[..., 1:] = sorted_indices_to_remove[..., :-1].clone() + sorted_indices_to_remove[..., 0] = 0 + + return logits + + +def topk_sampling(logits, top_k=10, top_p=1.0, min_p=1.0, temperature=1.0): + # temperature: (`optional`) float + # The value used to module the next token probabilities. Must be strictly positive. Default to 1.0. + # top_k: (`optional`) int + # The number of highest probability vocabulary tokens to keep for top-k-filtering. Between 1 and infinity. Default to 50. + # top_p: (`optional`) float + # The cumulative probability of parameter highest probability vocabulary tokens to keep for nucleus sampling. Must be between 0 and 1. Default to 1. + + # Temperature (higher temperature => more likely to sample low probability tokens) + if temperature != 1.0: + logits = logits / temperature + # Top-p/top-k filtering + logits = top_k_top_p_filtering(logits, top_k=top_k, top_p=top_p, min_p=min_p) + # Sample + token = torch.multinomial(F.softmax(logits, dim=-1), num_samples=1) + return token + + +class VoiceStarModel(nn.Module): + def __init__(self, args): + super().__init__() + self.args = args + assert ( + self.args.enc_dec ^ self.args.dec + ), f"self.args.enc_dec: {self.args.enc_dec}, self.args.dec: {self.args.dec}" + if not getattr(self.args, "special_first", False): + self.args.special_first = 0 + if not getattr(self.args, "n_special", False): + self.args.n_special = 3 + self.args.eos = getattr(self.args, "eos", -1) + self.eog = nn.Parameter( + torch.full((self.args.n_codebooks, 1), self.args.eog, dtype=torch.long), + requires_grad=False, + ) # [K 1] + if self.args.eos > 0: + assert ( + self.args.eos != self.args.audio_pad_token + and self.args.eos != self.args.empty_token + ), self.args.eos + self.eos = nn.Parameter( + torch.full((self.args.n_codebooks, 1), self.args.eos, dtype=torch.long), + requires_grad=False, + ) # [K 1] + if type(self.args.audio_vocab_size) == str: + self.args.audio_vocab_size = eval(self.args.audio_vocab_size) + if type(self.args.audio_vocab_size) == list: # otherwise they are all lists + assert self.args.special_first + + self.n_text_tokens = self.args.text_vocab_size + 1 + assert ( + self.args.text_pad_token == self.args.text_vocab_size + ), f"self.args.text_vocab_size: {self.args.text_vocab_size}, self.args.text_pad_token: {self.args.text_pad_token}" + + if self.args.special_first and type(self.args.audio_vocab_size) == list: + self.n_audio_tokens = [ + tok + self.args.n_special for tok in self.args.audio_vocab_size + ] # special tokens: empty token, EOG token, audio pad token + assert self.args.empty_token == 0, self.args.empty_token + assert self.args.eog == 1, self.args.eog + assert self.args.audio_pad_token == 2, self.args.audio_pad_token + else: + self.n_audio_tokens = [ + self.args.audio_vocab_size + self.args.n_special + ] * self.args.n_codebooks # special tokens: empty token, EOG token, audio pad token + assert ( + self.args.audio_vocab_size == self.args.empty_token + ), self.args.empty_token + assert self.args.eog == self.args.audio_vocab_size + 1, self.args.eog + assert ( + self.args.audio_pad_token == self.args.audio_vocab_size + 2 + ), self.args.audio_pad_token + + self.text_embedding = TokenEmbedding( + dim_model=self.args.d_model, + vocab_size=self.n_text_tokens, + dropout=self.args.text_embedding_dropout, + ) + + self.audio_embedding = nn.ModuleList( + [ + TokenEmbedding( + dim_model=self.args.audio_embedding_dim, + vocab_size=self.n_audio_tokens[k], + dropout=self.args.audio_embedding_dropout, + ) + for k in range(self.args.n_codebooks) + ] + ) + + rope_base = getattr(self.args, "rope_base", None) + use_sinusoidal = getattr(self.args, "use_sinusoidal", False) + use_sinusoidal_progress = getattr(self.args, "use_sinusoidal_progress", False) + logging.info(f"rope_base: {rope_base}, use_sinusoidal: {use_sinusoidal}") + if use_sinusoidal: + self.text_positional_embedding = SinePositionalEmbedding( + self.args.d_model, + dropout=self.args.text_positional_embedding_dropout, + scale=False, + alpha=True, # learnable scaler, scale the volume of positional embedding + ) + self.audio_positional_embedding = SinePositionalEmbedding( + self.args.d_model, + dropout=self.args.audio_positional_embedding_dropout, + scale=False, + alpha=True, # learnable scaler, scale the volume of positional embedding + ) + elif use_sinusoidal_progress: + self.text_positional_embedding = SinePositionalEmbedding_progress( + self.args.d_model, + dropout=self.args.text_positional_embedding_dropout, + scale=False, + alpha=True, # learnable scaler, scale the volume of positional embedding + args=self.args, + ) + self.audio_positional_embedding = SinePositionalEmbedding_progress( + self.args.d_model, + dropout=self.args.audio_positional_embedding_dropout, + scale=False, + alpha=True, # learnable scaler, scale the volume of positional embedding + args=self.args, + ) + + else: + + class NoOp: + def __init__(self): + pass + + def __call__(self, *args, **kwargs): + return args[0] + + self.text_positional_embedding = NoOp() + self.audio_positional_embedding = NoOp() + + if self.args.enc_dec: + enc_layer = TransformerEncoderLayer( + d_model=self.args.d_model, + nhead=self.args.nhead, + dim_feedforward=self.args.d_model * 4, + dropout=self.args.trm_dropout, + batch_first=True, + norm_first=True, + layer_norm_cls=LayerNorm, + ) # use the pre-norm arch + + self.encoder = TransformerEncoder( + encoder_layer=enc_layer, + num_layers=self.args.num_encoder_layers, + norm=LayerNorm(self.args.d_model), + rope_base=self.args.rope_base, + d_model=self.args.d_model, + nhead=self.args.nhead, + args=self.args, + ) # use the pre-norm arch + + dec_layer = TransformerDecoderLayer( + d_model=self.args.d_model, + nhead=self.args.nhead, + dim_feedforward=self.args.d_model * 4, + dropout=self.args.trm_dropout, + batch_first=True, + norm_first=True, + layer_norm_cls=LayerNorm, + ) + + self.decoder = TransformerDecoder( + decoder_layer=dec_layer, + num_layers=self.args.num_decoder_layers, + norm=LayerNorm(self.args.d_model), + rope_base=self.args.rope_base, + d_model=self.args.d_model, + nhead=self.args.nhead, + args=self.args, + ) # NOTE: this one I use torch.nn native implementation, as it's not implemented in .modules + + else: + dec_layer = TransformerEncoderLayer( + self.args.d_model, + self.args.nhead, + dim_feedforward=self.args.d_model * 4, + dropout=self.args.trm_dropout, + batch_first=True, + norm_first=True, + layer_norm_cls=LayerNorm, + ) + self.decoder = TransformerEncoder( + dec_layer, + num_layers=self.args.num_decoder_layers, + norm=LayerNorm(self.args.d_model), + ) + + if type(self.args.audio_vocab_size) == int: + self.predict_layer = nn.ModuleList( + [ + nn.Sequential( + nn.Linear(self.args.d_model, self.args.audio_vocab_size // 2), + nn.GELU(), + nn.Linear( + self.args.audio_vocab_size // 2, self.n_audio_tokens[k] + ), + ) + for k in range(self.args.n_codebooks) + ] + ) + else: + self.predict_layer = nn.ModuleList( + [ + nn.Sequential( + nn.Linear(self.args.d_model, self.args.d_model // 2), + nn.GELU(), + nn.Linear(self.args.d_model // 2, self.n_audio_tokens[k]), + ) + for k in range(self.args.n_codebooks) + ] + ) + + self.accuracy_metrics = nn.ModuleList( + [ + MulticlassAccuracy( + self.n_audio_tokens[k], + top_k=10, + average="micro", + multidim_average="global", + ignore_index=None, + ) + for k in range(self.args.n_codebooks) + ] + ) + + if self.args.eog_weight != 1: + raise NotImplementedError( + "now have different vocab_size for different codebooks, therefore currently don't support eog_weight" + ) + self.class_weight = nn.Parameter( + torch.ones(self.n_audio_tokens), requires_grad=False + ) + self.class_weight.data[self.args.eog] = self.args.eog_weight + + def dec_forward( + self, + x_input, + x_lens, + x_attention_mask, + x_padding_mask, + y_input, + new_y_lens, + y_attention_mask, + y_padding_mask, + need_weights=False, + past=None, + last_3_tokens=False, + ): + x_attn_mask = F.pad( + x_attention_mask, + (0, new_y_lens.max()), + value=True, + ) # x attn to all x, doesn't attn to any y, this follow figure 3 of the valle paper + y_attn_mask = F.pad( + y_attention_mask, + (x_lens.max(), 0), # y is padded at the front + value=False, + ) # y attn to all x, for y itself use lower triangle mask to ensure autoregressive + xy_attn_mask = torch.concat([x_attn_mask, y_attn_mask], dim=0) + + # merge key padding and attention masks + bsz, src_len = x_input.shape[0], x_lens.max() + new_y_lens.max() + xy_padding_mask = torch.concat([x_padding_mask, y_padding_mask], dim=1) + _xy_padding_mask = ( + xy_padding_mask.view(bsz, 1, 1, src_len) + .expand(-1, self.args.nhead, -1, -1) + .reshape(bsz * self.args.nhead, 1, src_len) + ) + xy_attn_mask = xy_attn_mask.logical_or(_xy_padding_mask) + + new_attn_mask = torch.zeros_like(xy_attn_mask) + new_attn_mask.masked_fill_(xy_attn_mask, float("-inf")) + xy_attn_mask = new_attn_mask + + xy_input = torch.cat([x_input, y_input], dim=1) + if need_weights: + raise NotImplementedError("not implemented yet") + out, layer_attn_weights = self.decoder( + (xy_input, None), mask=xy_attn_mask, need_weights=True + ) + return layer_attn_weights + + if past == None: # do not use kvcache + out, _ = self.decoder((xy_input, None), mask=xy_attn_mask) + return out[:, x_lens.max() :], None + else: # use kvcache + if ( + past.ndim > 3 + ): # uses kvcache, only need to pass the last tokens, this doesn't work with multi-span speech editing yet + if last_3_tokens: + xy_input = xy_input[:, -3:] + xy_attn_mask = xy_attn_mask[:, -3:] + else: + xy_input = xy_input[:, -1:] + xy_attn_mask = xy_attn_mask[:, -1:] + + out, present = self.decoder((xy_input, None), mask=xy_attn_mask, past=past) + if isinstance(out, tuple): # get rid of stage_embedding + out = out[0] + + if out.shape[1] > x_lens.max(): # the first pass, not kvcache yet + return out[:, x_lens.max() :], present + else: # used kvcache + return out, present + + def enc_dec_forward( + self, + xa, + x_attention_mask, + x_padding_mask, + y_input, + new_y_lens, + y_attention_mask, + y_padding_mask, + tgt_y_lens=None, + need_weights=False, + past=None, + last_3_tokens=False, + ): + assert not need_weights + if past != None and past.ndim > 3: + y_input = y_input[:, -1:] + y_attention_mask = y_attention_mask[-1:] + yhat, present = self.decoder( + tgt=y_input, + memory=xa, + tgt_mask=y_attention_mask, + tgt_key_padding_mask=y_padding_mask, + memory_key_padding_mask=x_padding_mask, + query_lens=tgt_y_lens, + past=past, + ) + return yhat, present + + def forward(self, batch, calc_loss=False): + """ + Args: + x: + A 2-D tensor of shape (N, S). + x_lens: + A 1-D tensor of shape (N,). It contains the number of tokens in `x` + before padding. + y: + A 3-D tensor of shape (N, K, T). + where K is the number of codebooks + y_lens: + A 1-D tensor of shape (N,). It contains the number of tokens in `x` + before padding. + """ + x, x_lens, y, y_lens = batch["x"], batch["x_lens"], batch["y"], batch["y_lens"] + if len(x) == 0: + return None + x = x[ + :, : x_lens.max() + ] # this deal with gradient accumulation, where x_lens.max() might not be longer than the length of the current slice of x + y = y[..., : y_lens.max()] + assert x.ndim == 2, x.shape + assert x_lens.ndim == 1, x_lens.shape + assert y.ndim == 3 and y.shape[1] == self.args.n_codebooks, y.shape + assert y_lens.ndim == 1, y_lens.shape + x_padding_mask = make_pad_mask(x_lens).to(x.device) + x_attention_mask = ( + torch.triu(torch.ones(x.shape[1], x.shape[1]), diagonal=1) + .bool() + .to(x_padding_mask.device) + ) + x_input = self.text_embedding(x) + x_input = self.text_positional_embedding(x_input, x_lens) + y_with_eos = [ + torch.cat([item[:, : y_lens[i]], self.eos], dim=-1) + for i, item in enumerate(y) + ] + targets = y_with_eos + # apply delayed stacking on y + shifted_y = [] + patterns = [] + new_y_lens = [] + if getattr(self, "empty_tokens", None) == None: + self.empty_tokens = torch.full( + (self.args.n_codebooks, self.args.n_codebooks), + self.args.empty_token, + dtype=torch.long, + ).to( + y.device + ) # [K, K] + for i in range(len(y)): + tmp = torch.cat( + [y_with_eos[i], self.empty_tokens], dim=-1 + ) # [K, T+n_codebooks] + for ii in range(self.args.n_codebooks): + tmp[ii] = torch.roll(tmp[ii], shifts=ii + 1, dims=0) + shifted_y.append( + tmp.transpose(1, 0) + ) # [K, T+n_codebooks] -> [T+n_codebooks, K] + new_y_lens.append(y_with_eos[i].shape[1] + self.empty_tokens.shape[1]) + + new_y_lens = torch.LongTensor(new_y_lens).to(y.device) + + cated_y = torch.nn.utils.rnn.pad_sequence( + shifted_y, batch_first=False, padding_value=self.args.audio_pad_token + ) + assert cated_y.shape == torch.Size( + [max(new_y_lens), len(y), self.args.n_codebooks] + ), cated_y.shape + cated_y = cated_y.permute(2, 0, 1) # [T,B,K]->[K,T,B] + stacked_embedded_y = torch.stack( + [self.audio_embedding[k](cated_y[k]) for k in range(self.args.n_codebooks)], + dim=0, + ) # [K, T, B, D] + assert ( + stacked_embedded_y.shape[0] == self.args.n_codebooks + and stacked_embedded_y.shape[2] == len(y) + and stacked_embedded_y.shape[-1] == self.args.d_model + ), stacked_embedded_y.shape + embedded_y = stacked_embedded_y.sum(dim=0) # [K,T,B,D]->[T,B,D] + embedded_y = embedded_y.transpose(1, 0) # [T,B,D]->[B,T,D] + assert embedded_y.shape[1:] == torch.Size( + [max(new_y_lens), self.args.d_model] + ), embedded_y.shape + y_input = self.audio_positional_embedding(embedded_y, new_y_lens) + y_padding_mask = make_pad_mask(new_y_lens).to(y.device) + y_attention_mask = ( + torch.triu(torch.ones(y_input.shape[1], y_input.shape[1]), diagonal=1) + .bool() + .to(y_padding_mask.device) + ) + if self.args.dec: + y_out = self.dec_forward( + x_input, + x_lens, + x_attention_mask, + x_padding_mask, + y_input, + new_y_lens, + y_attention_mask, + y_padding_mask, + ) + else: + xa = self.encoder(src=x_input, src_key_padding_mask=x_padding_mask) + y_out = self.enc_dec_forward( + xa, + x_attention_mask, + x_padding_mask, + y_input, + new_y_lens, + y_attention_mask, + y_padding_mask, + ) + y_out = y_out[0] # no kv-caching during training + assert ( + y_out.shape == y_input.shape + ), f"y_out.shape: {y_out.shape}, y_input.shape: {y_input.shape}" # [B S D] + logits = torch.stack( + [self.predict_layer[i](y_out) for i in range(self.args.n_codebooks)], dim=1 + ) # [B K S card] + assert ( + logits.shape[1] == self.args.n_codebooks + and logits.shape[3] == self.n_audio_tokens[0] + ), logits.shape + logits_use = [ + logit[:, : new_y_lens[i]] for i, logit in enumerate(logits) + ] # each of shape [K, T, card] + logits_final = [] + for i, logit in enumerate(logits_use): + logit_copy = logit.clone() + for ii in range(self.args.n_codebooks): + logit_copy[ii] = torch.roll(logit_copy[ii], shifts=-ii, dims=0) + logit = logit_copy[ + :, : -self.args.n_codebooks + ] # [K, T, card] -> [K, T-n_codebooks, card] + logits_final.append(logit) + if self.args.no_loss_on_prefix: + assert ( + "y_sep_token_position" in batch + ), f"y_sep_token_position should be in batch, but it's not" + logit_temp = [] + target_temp = [] + for jj, (logit, target) in enumerate(zip(logits_final, targets)): + # TODO already taken into consideration in depth transformer + logit_temp.append(logit[:, batch["y_sep_token_position"][jj] :]) + target_temp.append(target[:, batch["y_sep_token_position"][jj] :]) + logits_final = logit_temp + targets = target_temp + logits = torch.cat(logits_final, dim=1) # [K, T1+T2+T3+..., card] + targets = torch.cat(targets, dim=1) # [K, T1+T2+T3+...] + + assert targets.shape[:2] == logits.shape[:2], f"{targets.shape}, {logits.shape}" + loss = [] + ntokens = [] + top10acc = [] + for k, (logit, target) in enumerate( + zip(logits, targets) + ): # even though the loss and top10acc is calculated in a loop (loop through n_codebooks), validation is still taking a lot of mem, need to optimize this a little more + loss.append( + F.cross_entropy( + logit, + target, + reduction="mean", + weight=( + self.class_weight.data if self.args.eog_weight != 1 else None + ), + ignore_index=( + self.args.y_sep_token if self.args.y_sep_token != None else -100 + ), + ) + ) # ignore audio sep token as it's unpredictable (like the random early stop bug happened in 2023) + # NOTE have to ignore the sep token in the loss calculation + top10acc.append(self.accuracy_metrics[k](logit.detach(), target)) + ntokens.append(len(logit)) + + all_ntokens = sum(ntokens) + if self.args.codebook_weight != None: + codebook_weight = ( + eval(self.args.codebook_weight) + if isinstance(self.args.codebook_weight, str) + else self.args.codebook_weight + ) + else: + codebook_weight = [1.0] * self.args.n_codebooks + perplexity_by_codebook = [torch.exp(l) for l in loss] + loss = sum([l * nt * cw for l, nt, cw in zip(loss, ntokens, codebook_weight)]) + + top10acc_by_codebook = [t10a * nt for t10a, nt in zip(top10acc, ntokens)] + top10acc = sum(top10acc_by_codebook) + + ntokens = torch.tensor(all_ntokens).to(logits.device) + + ret = { + "loss": loss, + "perplexity_by_codebook": perplexity_by_codebook, + "top10acc": top10acc, + "top10acc_by_codebook": top10acc_by_codebook, + "effective_ntoken": ntokens, + } + + return ret + + def inference_tts( + self, + x: torch.Tensor, + x_lens: torch.Tensor, + y: torch.Tensor, + tgt_y_lens: torch.Tensor, # + top_k: Union[int, list[int]] = -100, + top_p: float = 1.0, + min_p: float = 1.0, + temperature: float = 1.0, + stop_repetition: int = 3, + kvcache: int = 1, + silence_tokens: list[int] = [], + multi_trial: list[int] = [], + *kargs, + ) -> torch.Tensor: + """ + This implementation uses kvcache, which should have significant speed up + Args: + x: + A 2-D tensor of shape (1, L). + x_lens: + A 1-D tensor of shape (1,). It contains the number of tokens in `x` + before padding. + y: + A 3-D tensor of shape (1, T, K). + tgt_y_lens: + *new arg* this specify the target length of y + top_k: (`optional`) int + The number of highest probability tokens to keep for top-k-filtering. Default to -100. + top_p: (`optional`) float + For Neucleus sampling + min_p: (`optional`) float + For min_p filtered sampling + temperature: (`optional`) float + The value used to module the next token probabilities. Must be strictly positive. Default to 1.0. + multi_trial: (`optional`) list[int] + If not empty, it will be [n_trials, beam_size, trial_interval] + from the start and begining trial_interval, we duplicate the current sample by beam_size, + at the end of every trial_interval, we choose the sample with the highest log likelihood to keep and throw away the rest + """ + eog_inference = self.args.eos if self.args.eos > 0 else self.args.eog + assert x.ndim == 2, x.shape + assert x_lens.ndim == 1, x_lens.shape + assert y.ndim == 3, y.shape + if self.args.special_first: + y = y + int(self.args.n_special) + y = y.transpose(2, 1) # [1,T,K] -> [1,K,T] + assert ( + y.shape[0] == 1 and y.shape[1] == self.args.n_codebooks + ), y.shape # there is no padding + + # make x attention mask and x_input + x_attention_mask = ( + torch.triu(torch.ones(x.shape[1], x.shape[1]), diagonal=1) + .bool() + .to(x.device) + ) + # x_attention_mask = torch.zeros(x.shape[1], x.shape[1]).bool().to(x.device) + x_input = self.text_embedding(x) + x_input = self.text_positional_embedding(x_input, x_lens) + + y_len = y.shape[2] + y_lens = torch.LongTensor([y_len]).to(y.device) + + # rearrange y, we don't add eog to the end, this doesn't actually do anything in the tts scenario + rearranged_y = [[y[0]]] + assert rearranged_y[0][0].shape[0] == self.args.n_codebooks, rearranged_y[0][ + 0 + ].shape + + # # shift y to create the delayed pattern + if getattr(self, "empty_tokens", None) == None: + self.empty_tokens = torch.full( + (self.args.n_codebooks, self.args.n_codebooks), + self.args.empty_token, + dtype=torch.long, + ).to( + y.device + ) # [K, K] + temp = rearranged_y[0][0] + assert temp.ndim == 2 and temp.shape[0] == self.args.n_codebooks, temp.shape + temp = torch.cat([temp, self.empty_tokens], dim=-1) # [K, T+n_codebooks] + for ii in range(self.args.n_codebooks): + temp[ii] = torch.roll(temp[ii], shifts=ii + 1, dims=0) + shifted_y = [[temp]] + + # below is different from forward or inference + # where we cut this shifted part + shifted_y[0][0] = shifted_y[0][0][:, : -(self.args.n_codebooks - 1)] + assert ( + not ( + shifted_y[0][0][self.args.n_codebooks :] == self.args.empty_token + ).any() + and not (shifted_y[0][0][self.args.n_codebooks :] == self.args.eog).any() + ), shifted_y[0][0] + # next section in inference is insert mask at the intersection of each tensor in a sample, but we don't need to do that + # next section is concate tensors of each sample to one tensor, which we also don't need + cated_y = shifted_y[0][0].unsqueeze(-1) # [K,S]->[K,S,B] + new_y_lens = torch.LongTensor([cated_y.shape[1]]).to(cated_y.device) + assert cated_y.shape == torch.Size((self.args.n_codebooks, cated_y.shape[1], 1)) + assert not (cated_y == self.args.audio_pad_token).any(), cated_y + + # replace tokens in y with the embeddings, add sum codebooks up + embedded_y = torch.stack( + [self.audio_embedding[k](cated_y[k]) for k in range(self.args.n_codebooks)], + dim=0, + ) # [K, S, B, D] + assert embedded_y.shape[0] == self.args.n_codebooks, embedded_y.shape + assert embedded_y.shape[-1] == self.args.d_model, embedded_y.shape + embedded_y = embedded_y.sum(dim=0) # [K,S,B,D]->[S,B,D] + embedded_y = embedded_y.transpose(1, 0) # [S,B,D]->[B,S,D] + + # positional embedding + y_input = self.audio_positional_embedding(embedded_y, tgt_y_lens) + + # make attention mask and padding mask + y_attention_mask = ( + torch.triu(torch.ones(y_input.shape[1], y_input.shape[1]), diagonal=1) + .bool() + .to(y.device) + ) + + x_padding_mask = torch.full((1, x_lens[0]), False).to(x.device) + y_padding_mask = torch.full((1, new_y_lens[0]), False).to(y.device) + + # entering the generation stage + # starting from line 708 + codebook_eog = [False] * self.args.n_codebooks + generated = [] # doesn't contain any empty token, contain eog + cur_generated = [] + # say 0 is empty, 4 is eog + # tensor([[ 1, 2, 3, 4, 0, 0], + # [ 0, 1, 2, 3, 4, 0], + # [ 0, 0, 1, 2, 3, 4]]) + num_gen = [] + cur_num_gen = 0 + ##################### silence repetition handling ##################### + ##################### silence repetition handling ##################### + # silence_tokens = [1388,1898,131] # [1388, 2045, 2041, 1996] + # silence_tokens = [] + consec_silence_count = 0 + prev_token = None + ##################### silence repetition handling ##################### + ##################### silence repetition handling ##################### + + def sample_helper( + n_eog, + logits, + codebook_eog, + top_k, + top_p, + min_p, + temperature, + prev_token, + consec_silence_count, + stop_repetition, + silence_tokens, + cur_num_gen, + ): + if n_eog == 0: + logits_adjust = logits + for jj in range(1, self.args.n_codebooks): + logits_adjust[jj][eog_inference] = -10000 + logits_adjust[jj][self.args.empty_token] = -10000 + if ( + cur_num_gen <= self.args.encodec_sr // 5 + ): # this shouldn't happen, but just in case the model stopped too early + logits_adjust[0][eog_inference] = -10000 + ##################### silence repetition handling ##################### + if ( + stop_repetition > 0 + and prev_token in silence_tokens + and consec_silence_count > stop_repetition + ): + if logits_adjust[0, prev_token] < 0: + logits_adjust[0, prev_token] = logits_adjust[0, prev_token] * ( + consec_silence_count - (stop_repetition - 1) + ) + else: + logits_adjust[0, prev_token] = logits_adjust[0, prev_token] / ( + consec_silence_count - (stop_repetition - 1) + ) + ##################### silence repetition handling ##################### + samples = topk_sampling( + logits_adjust, + top_k=top_k, + top_p=top_p, + min_p=min_p, + temperature=temperature, + ) # [K, 1] + assert samples.shape == torch.Size( + (self.args.n_codebooks, 1) + ), f"samples.shape: {samples.shape}" + if cur_num_gen < self.args.n_codebooks - 1: + for jj in range(1, self.args.n_codebooks - cur_num_gen): + samples[-jj, 0] = self.args.empty_token + + if ( + ( + samples[0, 0] == eog_inference + or torch.argmax(logits[0], dim=-1) == eog_inference + or y_input.shape[1] > x_lens[0] * (self.args.encodec_sr // 4) + ) + or self.args.rope_base is not None + and not self.args.decoder_regular_rope + and self.args.progress_no_multiple + and cur_num_gen + > ( + tgt_y_lens[0] + + self.args.encodec_sr * getattr(self.args, "extra_cutoff", 5) + ) + ): + # last one condition in the first bracket means y is already too long, shouldn't happen, but put it here + # the second bracket means we are using progress-monitoring RoPE, but the model is generating excessively long sequence (5 seconds more than specified), in which case we terminate the generation + samples[0, 0] = eog_inference + codebook_eog[0] = True + ##################### silence repetition handling ##################### + if samples[0, 0] in silence_tokens and samples[0, 0] == prev_token: + consec_silence_count += 1 + else: + consec_silence_count = 0 + prev_token = samples[0, 0] + ##################### silence repetition handling ##################### + return samples, codebook_eog, prev_token, consec_silence_count + else: + assert ( + sum(codebook_eog[i] for i in range(n_eog)) == n_eog + ), f"codebook_eog: {codebook_eog}, but n_eog: {n_eog}" + logits_adjust = logits + for jj in range(n_eog + 1, self.args.n_codebooks): + logits_adjust[jj][eog_inference] = -10000 + logits_adjust[jj][self.args.empty_token] = -10000 + samples = topk_sampling( + logits_adjust, + top_k=top_k, + top_p=top_p, + min_p=min_p, + temperature=temperature, + ) # [K, 1] + for jj in range(n_eog): + samples[jj, 0] = self.args.empty_token + samples[n_eog, 0] = eog_inference + codebook_eog[n_eog] = True + return samples, codebook_eog, prev_token, consec_silence_count + + # prepare the cache placeholder + # n_layers, 2, bsz, num_heads, src_len, head_dim, 2 means [key, value] + past = ( + torch.ones( + [self.args.num_decoder_layers, 2, x.shape[0]], + device=x.device, + dtype=torch.float32, + ) + if kvcache + else None + ) + if self.args.enc_dec: + xa = self.encoder(src=x_input, src_key_padding_mask=x_padding_mask) + while True: + if self.args.dec: + y_out, present = self.dec_forward( + x_input, + x_lens, + x_attention_mask, + x_padding_mask, + y_input, + new_y_lens, + y_attention_mask, + y_padding_mask, + past=past, + ) + else: + y_out, present = self.enc_dec_forward( + xa, + x_attention_mask, + x_padding_mask, + y_input, + new_y_lens, + y_attention_mask, + y_padding_mask, + tgt_y_lens=tgt_y_lens, + past=past, + ) + if past != None: + past = ( + torch.cat([past, present.to(past.dtype)], dim=-2) + if past.ndim > 3 + else present.to(past.dtype) + ) + + y_out = y_out[:, -1:] # only take the last token + + logits = torch.stack( + [self.predict_layer[i](y_out) for i in range(self.args.n_codebooks)], + dim=1, + ) # [B K S card], B==S==1, so [1 K 1 card] + logits = logits.squeeze(0).squeeze(1) # [K card] + assert logits.shape == torch.Size( + (self.args.n_codebooks, self.n_audio_tokens[0]) + ), f"{logits.shape}" + + n_eog = sum(codebook_eog) + assert n_eog < self.args.n_codebooks + if ( + self.args.eos > 0 + ): # if we are using end-of-sentence token (which is used by default), eog shouldn't be used here, as there is no masked spans + for jj in range(self.args.n_codebooks): + logits[jj][self.args.eog] = -10000.0 + + samples, codebook_eog, prev_token, consec_silence_count = sample_helper( + n_eog, + logits, + codebook_eog, + top_k, + top_p, + min_p, + temperature, + prev_token, + consec_silence_count, + stop_repetition, + silence_tokens, + cur_num_gen, + ) + # samples.shape is [K,1] + # ge samples_emb + samples_emb = torch.stack( + [ + self.audio_embedding[k](samples[k]) + for k in range(self.args.n_codebooks) + ], + dim=0, + ) # [K,1,D] + samples_emb = samples_emb.sum(dim=0, keepdim=True) # [1,1,D] + + cur_num_gen += 1 + cur_generated.append(samples.squeeze(-1)) # [K,1] -> [K] + + if ( + sum(codebook_eog) == self.args.n_codebooks + ): # generation for the current span is done + codebook_eog = [False] * self.args.n_codebooks + num_gen.append(cur_num_gen) + cur_num_gen = 0 + generated.append(cur_generated) + cur_generated = [] + break + else: + assert samples_emb.shape == torch.Size( + (1, 1, self.args.d_model) + ), f"samples_emb.shape: {samples_emb.shape}" + + embedded_y = torch.cat([embedded_y, samples_emb], dim=1) + new_y_lens = torch.LongTensor([embedded_y.shape[1]]).to(y.device) + y_input = self.audio_positional_embedding(embedded_y, tgt_y_lens) # [B T D] + # make attention mask and padding mask + y_attention_mask = ( + torch.triu(torch.ones(y_input.shape[1], y_input.shape[1]), diagonal=1) + .bool() + .to(y.device) + ) + y_padding_mask = torch.full((1, new_y_lens[0]), False).to(y.device) + + assert len(generated) == 1, f"len(generated): {len(generated)}" + + # revert the pattern + flatten_gen = [] + for l, orig_span in enumerate(generated): + span = torch.stack(orig_span, dim=0) # [T, K] + span = span.transpose(1, 0) # [K, T] + assert span.shape[0] == self.args.n_codebooks, span.shape + unshifted_span = [] + for j, s in enumerate(span): + start_from = j + end_at = -(self.args.n_codebooks - start_from) + unshifted_span.append(s[start_from:end_at]) + unshifted_span = torch.stack(unshifted_span, dim=0) + + assert ( + unshifted_span.shape[1] == num_gen[l] - self.args.n_codebooks + ), f"len(unshifted_spans[0]): {len(unshifted_span[0])}, num_gen[l]: {num_gen[l]}" + + flatten_gen.append(unshifted_span) + assert len(flatten_gen) == 1, len(flatten_gen) + + # combine + res = [y[0], flatten_gen[0]] + res = torch.cat(res, dim=1).unsqueeze(0) # [K, new_t] -> [1, K, new_T] + expected_y_len = y_len + sum([item - self.args.n_codebooks for item in num_gen]) + assert res.shape == torch.Size( + (1, self.args.n_codebooks, expected_y_len) + ), f"res.shape: {res.shape}, expected_y_len: {expected_y_len}. y_len + sum([item - self.args.n_codebooks for item in num_gen]): {y_len} + {sum([item - self.args.n_codebooks for item in num_gen])}" + + if self.args.special_first: + res = res - int(self.args.n_special) + flatten_gen = flatten_gen - int(self.args.n_special) + return res, flatten_gen[0].unsqueeze(0) From 59233d8cdd2170663498f1b11ba8e742ef100852 Mon Sep 17 00:00:00 2001 From: mrfakename Date: Mon, 7 Apr 2025 18:58:41 -0700 Subject: [PATCH 2/7] Update Gradio demo, MPS support --- MODEL-LICENSE => LICENSE-MODEL | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename MODEL-LICENSE => LICENSE-MODEL (100%) diff --git a/MODEL-LICENSE b/LICENSE-MODEL similarity index 100% rename from MODEL-LICENSE rename to LICENSE-MODEL From e51b6c277635e41a93c09751a21f1c121f60227a Mon Sep 17 00:00:00 2001 From: mrfakename Date: Mon, 7 Apr 2025 18:58:47 -0700 Subject: [PATCH 3/7] Update Gradio demo --- README.md | 111 +++++++++++------------- app.py | 96 ++++++++++++++++++++ data/emilia_preprocessing/encodec.py | 12 ++- data/encodec.py | 16 +++- data/ll60k_preprocessing/encodec.py | 12 ++- docs/training.md | 66 ++++++++++++++ inference_gradio.py | 9 +- setup.py | 13 ++- steps/trainer.py | 2 +- train/train.py | 2 +- voicestar/__init__.py | 96 +++++++++++--------- voicestar/api.py | 55 ++++++++---- voicestar/cli.py | 125 +++++++++++++++++++-------- voicestar/data/encodec.py | 16 +++- voicestar/modules/utils.py | 1 + voicestar/scripts/__init__.py | 0 voicestar/scripts/copy_codebase.py | 57 ++++++++++++ voicestar/utils.py | 5 +- voicestar/voicestar.py | 1 + 19 files changed, 515 insertions(+), 180 deletions(-) create mode 100644 app.py create mode 100644 docs/training.md create mode 100644 voicestar/scripts/__init__.py create mode 100644 voicestar/scripts/copy_codebase.py diff --git a/README.md b/README.md index 5cccfc6..9e27e08 100644 --- a/README.md +++ b/README.md @@ -1,80 +1,69 @@ # VoiceStar: Robust, Duration-Controllable TTS that can Extrapolate -## TODO -- [x] Gradio demo ETA: 6 April 2025 -- [ ] Research Paper: 7 April 2025 - 14 April 2025 +VoiceStar is a robust, duration-controllable TTS model with support for test-time extrapolation, meaning it can generate speech longer than the duration it was trained on. + +## Features + +- **Duration control**: Specify the duration of the generated speech. +- **Zero-shot voice cloning**: Clone any voice with a short reference audio clip ([demo video](https://x.com/PuyuanPeng/status/1908822618167300419)). + +Coming soon: research paper (ETA: 7 April 2025 - 14 April 2025) + +## Quick Start + +### Install -## 1. Env setup -### Download model -```bash -# under VoiceStar root dir -mkdir pretrained -wget -O ./pretrained/encodec_6f79c6a8.th "https://huggingface.co/pyp1/VoiceCraft/resolve/main/encodec_4cb2048_giga.th" -wget -O ./pretrained/VoiceStar_840M_30s.pth "https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_30s.pth" -wget -O ./pretrained/VoiceStar_840M_40s.pth "https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_40s.pth" -``` -### Inference only: ```bash -conda create -n voicestar python=3.10 -conda activate voicestar # this seems to lead to much worse results in terms of wer and spksim (comparing e9_rerun and e9_rerun_newba_upgraded) -pip install torch==2.5.1 torchaudio==2.5.1 --index-url https://download.pytorch.org/whl/cu124 -pip install numpy, tqdm, fire -pip install phonemizer==3.2.1 -apt-get install espeak-ng # backend for the phonemizer -pip install torchmetrics -pip install einops -pip install omegaconf==2.3.0 -pip install openai-whisper -pip install gradio +pip install voicestar ``` -* avoid warnings likes -[WARNING] words_mismatch.py:88 || words count mismatch on 200.0% of the lines (2/1) -```python -# go to ~/miniconda3/envs/voicestar/lib/python3.10/site-packages/phonemizer/backend/espeak/words_mismatch.py -# pass the warning like this - def _resume(self, nmismatch: int, nlines: int): - """Logs a high level undetailed warning""" - pass - # if nmismatch: - # self._logger.warning( - # 'words count mismatch on %s%% of the lines (%s/%s)', - # round(nmismatch / nlines, 2) * 100, nmismatch, nlines) -``` +Make sure you also have `espeak-ng` installed. + +**Note:** If you run into issues installing VoiceStar with `uv`, try installing it with `pip` instead. + +### Usage + +Basic usage: -### Training and data processing -*additional packages*: ```bash -pip install huggingface_hub -pip install datasets -pip install tensorboard -pip install wandb -pip install matplotlib -pip install ffmpeg-python -pip install scipy -pip install soundfile +voicestar --reference-speech "./demo/5895_34622_000026_000002.wav" --target-text "I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long." --target-duration 8 ``` -## 2. example -### command line example -check signature of `run_inference` func in `inference_commandline.py` for adjustable hyperparameters +Please refer to the CLI and Python API documentation below for more advanced usage. + +## Training + +Please refer to the [training docs](docs/training.md) for more information. + +## Inference + +### CLI + ```bash -# under root dir -conda activate voicestar -python inference_commandline.py \ - --reference_speech "./demo/5895_34622_000026_000002.wav" \ - --target_text "I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long." \ - --target_duration 8 +voicestar --reference-speech "./demo/5895_34622_000026_000002.wav" --target-text "I cannot believe that the same model can also do text to speech synthesis too!" ``` -### Gradio +View all available options: + ```bash -conda activate voicestar -python inference_gradio.py +voicestar --help ``` +### Python API + +```python +from voicestar import VoiceStar + +# Initialize the model +model = VoiceStar() + +# Generate speech from text +audio = model.generate("I cannot believe that the same model can also do text to speech synthesis too!") +audio.save("output.wav") +``` ## License -Code license: MIT -Model Weights License: CC-BY-4.0 (as Emilia dataset we used is under this license) \ No newline at end of file +The code in this repo is licensed under the MIT license. The pretrained model weights available on Hugging Face are licensed under the CC-BY-4.0 license. + +This repository may contain third-party software which may be licensed under different licenses. \ No newline at end of file diff --git a/app.py b/app.py new file mode 100644 index 0000000..f49b9fa --- /dev/null +++ b/app.py @@ -0,0 +1,96 @@ +import gradio as gr +import torch +import os +from voicestar import VoiceStar +from voicestar.utils import seed_everything +from txtsplit import txtsplit +import numpy as np + +ABOUT = """ +# VoiceStar TTS + +Gradio demo for [VoiceStar](https://github.com/jasonppy/VoiceStar): robust, duration-controllable TTS that can extrapolate. +""" + +# Initialize model once outside the function for better performance +model = VoiceStar() + + +def generate_audio( + reference_speech, + text, + duration=0.0, + top_k=10, + temperature=1.0, + repeat_prompt=1, + seed=1, + progress=gr.Progress(), +): + # Set seed for reproducibility if provided + if seed > 0: + seed_everything(seed) + + # Update model parameters if needed + model.api.top_k = top_k + model.api.temperature = temperature + model.repeat_prompt = repeat_prompt + + # Generate speech + target_duration = None if duration <= 0 else duration + texts = txtsplit(text) + + audios = [] + for t in progress.tqdm(texts): + audio = model.generate( + reference_speech=reference_speech, text=t, target_duration=target_duration + ) + audios.append(audio.waveform.squeeze().numpy()) + + audio = np.concatenate(audios) + + # Return audio for gradio + return (16000, audio) + + +with gr.Blocks() as demo: + gr.Markdown(ABOUT) + inp_ref = gr.Audio(label="Reference Audio", type="filepath") + inp_text = gr.Textbox(label="Text to synthesize") + + with gr.Accordion("Advanced Settings", open=False): + inp_reference_text = gr.Textbox( + label="Reference Text", + info="Enter a transcription of the reference audio. This is optional - if not provided, the model will transcribe the audio automatically.", + ) + inp_duration = gr.Number( + label="Duration", + info="Set to 0 to automatically estimate duration", + value=0.0, + ) + inp_top_k = gr.Slider(label="Top-k", minimum=1, maximum=100, step=1, value=10) + inp_temp = gr.Slider( + label="Temperature", minimum=0.0, maximum=2.0, step=0.01, value=1.0 + ) + inp_repeat_prompt = gr.Slider( + label="Repeat prompt", minimum=1, maximum=10, step=1, value=1 + ) + inp_seed = gr.Number(label="Seed", info="Set to 0 to use random seed", value=1) + + btn_generate = gr.Button("Generate", variant="primary") + out_audio = gr.Audio(label="Generated Audio") + + btn_generate.click( + fn=generate_audio, + inputs=[ + inp_ref, + inp_text, + inp_duration, + inp_top_k, + inp_temp, + inp_repeat_prompt, + inp_seed, + ], + outputs=[out_audio], + ) + +demo.queue().launch() diff --git a/data/emilia_preprocessing/encodec.py b/data/emilia_preprocessing/encodec.py index 074fd69..5c7579d 100644 --- a/data/emilia_preprocessing/encodec.py +++ b/data/emilia_preprocessing/encodec.py @@ -1748,7 +1748,11 @@ def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: """Instantiate a compression model.""" if device == None: - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) state = torch.load(ckpt_fn, map_location="cpu") cfg = state["xp.cfg"] cfg.device = str(device) @@ -1826,7 +1830,11 @@ def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> Compressi "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", ] - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) model = get_compression_model(ckpt_fn, device=device) for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): diff --git a/data/encodec.py b/data/encodec.py index fdb9267..fc74ecc 100644 --- a/data/encodec.py +++ b/data/encodec.py @@ -1748,8 +1748,14 @@ def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: """Instantiate a compression model.""" if device == None: - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") - state = torch.load(ckpt_fn, map_location="cpu", weights_only=False) # TODO: Convert to SafeTensors + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) + state = torch.load( + ckpt_fn, map_location="cpu", weights_only=False + ) # TODO: Convert to SafeTensors cfg = state["xp.cfg"] cfg.device = str(device) weights = state["best_state"]["model"] @@ -1826,7 +1832,11 @@ def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> Compressi "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", ] - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) model = get_compression_model(ckpt_fn, device=device) for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): diff --git a/data/ll60k_preprocessing/encodec.py b/data/ll60k_preprocessing/encodec.py index 074fd69..5c7579d 100644 --- a/data/ll60k_preprocessing/encodec.py +++ b/data/ll60k_preprocessing/encodec.py @@ -1748,7 +1748,11 @@ def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: """Instantiate a compression model.""" if device == None: - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) state = torch.load(ckpt_fn, map_location="cpu") cfg = state["xp.cfg"] cfg.device = str(device) @@ -1826,7 +1830,11 @@ def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> Compressi "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", ] - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) model = get_compression_model(ckpt_fn, device=device) for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): diff --git a/docs/training.md b/docs/training.md new file mode 100644 index 0000000..0e5957c --- /dev/null +++ b/docs/training.md @@ -0,0 +1,66 @@ +# Training + +## Setup Environment + +First, setup the environment with the inference requirements: + +```bash +conda create -n voicestar python=3.10 +conda activate voicestar # this seems to lead to much worse results in terms of wer and spksim (comparing e9_rerun and e9_rerun_newba_upgraded) +pip install torch==2.5.1 torchaudio==2.5.1 --index-url https://download.pytorch.org/whl/cu124 +pip install numpy, tqdm, fire +pip install phonemizer==3.2.1 +apt-get install espeak-ng # backend for the phonemizer +pip install torchmetrics +pip install einops +pip install omegaconf==2.3.0 +pip install openai-whisper +pip install gradio +``` + + +* avoid warnings likes +[WARNING] words_mismatch.py:88 || words count mismatch on 200.0% of the lines (2/1) +```python +# go to ~/miniconda3/envs/voicestar/lib/python3.10/site-packages/phonemizer/backend/espeak/words_mismatch.py +# pass the warning like this + def _resume(self, nmismatch: int, nlines: int): + """Logs a high level undetailed warning""" + pass + # if nmismatch: + # self._logger.warning( + # 'words count mismatch on %s%% of the lines (%s/%s)', + # round(nmismatch / nlines, 2) * 100, nmismatch, nlines) +``` + + +Install additional packages required for training and data processing: + +```bash +pip install huggingface_hub +pip install datasets +pip install tensorboard +pip install wandb +pip install matplotlib +pip install ffmpeg-python +pip install scipy +pip install soundfile +``` + +## Download Models + +If you are training, you may need to download models manually: + +```bash +# under VoiceStar root dir +mkdir pretrained +wget -O ./pretrained/encodec_6f79c6a8.th "https://huggingface.co/pyp1/VoiceCraft/resolve/main/encodec_4cb2048_giga.th" +wget -O ./pretrained/VoiceStar_840M_30s.pth "https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_30s.pth" +wget -O ./pretrained/VoiceStar_840M_40s.pth "https://huggingface.co/pyp1/VoiceStar/resolve/main/VoiceStar_840M_40s.pth" +``` + +## Training + +TODO: Finish training docs + +Training scripts can be found in `train` folder. The data processing scripts can be found in `data` folder. An example training script can be found in `scripts/e1_840M_30s.sh`. \ No newline at end of file diff --git a/inference_gradio.py b/inference_gradio.py index bb58f04..7aa6260 100644 --- a/inference_gradio.py +++ b/inference_gradio.py @@ -26,7 +26,7 @@ # Adjust if needed. # --------------------------------------------------------------------- from data.tokenizer import AudioTokenizer, TextTokenizer -from voicestar import voicestar as voice_star # legacy compatability TODO: change +from voicestar import voicestar as voice_star # legacy compatability TODO: change from inference_tts_utils import inference_one_sample @@ -38,7 +38,6 @@ from voicestar.utils import seed_everything, estimate_duration - ############################################################ # Main Inference Function ############################################################ @@ -77,7 +76,11 @@ def run_inference( # 2. Load model checkpoint torch.serialization.add_safe_globals([Namespace]) - device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" # MPS support + device = ( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) # MPS support ckpt_fn = hf_hub_download(repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth") bundle = torch.load(ckpt_fn, map_location=device, weights_only=True) diff --git a/setup.py b/setup.py index 1b4778f..3429a83 100644 --- a/setup.py +++ b/setup.py @@ -25,7 +25,8 @@ "transformers[torch]", "huggingface_hub", "gradio", - "click" + "click", + "txtsplit", ], extras_require={ "train": [ @@ -36,12 +37,8 @@ "matplotlib", "ffmpeg-python", "scipy", - "soundfile" + "soundfile", ] }, - entry_points={ - "console_scripts": [ - "voicestar=voicestar.cli:run_inference" - ] - } -) \ No newline at end of file + entry_points={"console_scripts": ["voicestar=voicestar.cli:run_inference"]}, +) diff --git a/steps/trainer.py b/steps/trainer.py index 6f55278..953416a 100644 --- a/steps/trainer.py +++ b/steps/trainer.py @@ -26,7 +26,7 @@ # from data import librilight, gigaspeech, gigaspeech_waveform from data import combined_dataset -from voicestar import voicestar as voice_star # legacy compatability TODO: change +from voicestar import voicestar as voice_star # legacy compatability TODO: change from .trainer_utils import ( DistributedDynamicBatchSampler, diff --git a/train/train.py b/train/train.py index add785e..438bd84 100644 --- a/train/train.py +++ b/train/train.py @@ -8,7 +8,7 @@ import torch.distributed as dist from config import MyParser from steps import trainer -from copy_codebase import copy_codebase +from voicestar.scripts.copy_codebase import copy_codebase def world_info_from_env(): diff --git a/voicestar/__init__.py b/voicestar/__init__.py index 79d8734..f9ca486 100644 --- a/voicestar/__init__.py +++ b/voicestar/__init__.py @@ -9,35 +9,36 @@ __version__ = "0.1.0" + class VoiceStar: """ VoiceStar API - Easy-to-use Python API for VoiceStar model. - + This class provides an easy-to-use interface to the VoiceStar TTS model, allowing you to generate speech in the voice of a reference audio sample. - + Example: ```python from voicestar import VoiceStar - + # Initialize the model (downloads from HF Hub if needed) tts = VoiceStar(model_name="VoiceStar_840M_30s") - + # Generate speech in the voice of the reference audio audio = tts.generate( reference_speech="path/to/reference.wav", text="This is the text I want to synthesize.", target_duration=5.0 # Optional: specify desired duration in seconds ) - + # Save the generated audio audio.save("output.wav") ``` """ - + def __init__( - self, - model_name="VoiceStar_840M_30s", + self, + model_name="VoiceStar_840M_30s", device=None, top_k=10, top_p=1.0, @@ -46,7 +47,7 @@ def __init__( ): """ Initialize the VoiceStar TTS model. - + Args: model_name (str): Model name to use. Options: - "VoiceStar_840M_30s" (default): 840M parameter model that can generate up to 30s @@ -65,17 +66,23 @@ def __init__( import voicestar.voicestar as voice_star from data.tokenizer import AudioTokenizer, TextTokenizer from voicestar.api import VoiceStarAPI - + # Set device if device is None: - self.device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" + self.device = ( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) else: self.device = device - + # Download and load model torch.serialization.add_safe_globals([Namespace]) - ckpt_fn = hf_hub_download(repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth") - + ckpt_fn = hf_hub_download( + repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth" + ) + bundle = torch.load(ckpt_fn, map_location=self.device, weights_only=True) self.args = bundle["args"] self.phn2num = bundle["phn2num"] @@ -83,18 +90,22 @@ def __init__( self.model.load_state_dict(bundle["model"]) self.model.to(self.device) self.model.eval() - + # Load tokenizers if self.args.n_codebooks == 4: - signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_4cb2048_giga.th") + signature = hf_hub_download( + repo_id="pyp1/VoiceCraft", filename="encodec_4cb2048_giga.th" + ) elif self.args.n_codebooks == 8: - signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_8cb1024_giga.th") + signature = hf_hub_download( + repo_id="pyp1/VoiceCraft", filename="encodec_8cb1024_giga.th" + ) else: raise ValueError(f"Invalid number of codebooks: {self.args.n_codebooks}") - + self.audio_tokenizer = AudioTokenizer(signature=signature) self.text_tokenizer = TextTokenizer(backend="espeak") - + # Create API instance self.api = VoiceStarAPI( model=self.model, @@ -107,21 +118,21 @@ def __init__( top_p=top_p, temperature=temperature, ) - + # Store parameters self.repeat_prompt = repeat_prompt - + def generate( - self, - reference_speech, - text, + self, + reference_speech, + text, reference_text=None, target_duration=None, output_path=None, ): """ Generate speech in the voice of the reference audio. - + Args: reference_speech (str): Path to reference speech audio file text (str): Text to synthesize @@ -130,7 +141,7 @@ def generate( target_duration (float, optional): Target duration in seconds. If None, will estimate based on reference speech and text length. output_path (str, optional): If provided, saves the generated audio to this path - + Returns: AudioSegment: The generated audio (can be saved with .save() method) """ @@ -139,27 +150,29 @@ def generate( import torchaudio import whisper from voicestar.utils import estimate_duration - + # Transcribe reference speech if needed if reference_text is None: - print("[Info] No reference_text provided, transcribing reference_speech with Whisper.") + print( + "[Info] No reference_text provided, transcribing reference_speech with Whisper." + ) wh_model = whisper.load_model("large-v3-turbo") result = wh_model.transcribe(reference_speech) reference_text = result["text"] print(f"[Info] Whisper transcribed text: {reference_text}") - + # Estimate duration if not provided if target_duration is None: target_duration = estimate_duration(reference_speech, text) print(f"[Info] Estimated target duration: {target_duration:.2f} seconds") - + # Get audio info for prompt_end_frame info = torchaudio.info(reference_speech) prompt_end_frame = int(100 * info.sample_rate) # 100 seconds max - + # Set delay pattern increment delay_pattern_increment = self.args.n_codebooks + 1 - + # Generate audio _, generated_audio = self.api.generate( audio_fn=reference_speech, @@ -170,33 +183,36 @@ def generate( prefix_transcript=reference_text, repeat_prompt=self.repeat_prompt, ) - + # Save if output_path provided if output_path: os.makedirs(os.path.dirname(os.path.abspath(output_path)), exist_ok=True) torchaudio.save(output_path, generated_audio[0].cpu(), 16000) print(f"[Success] Generated audio saved to {output_path}") - + # Return audio segment for further manipulation from dataclasses import dataclass - + @dataclass class AudioSegment: waveform: torch.Tensor sample_rate: int = 16000 - + def save(self, path): """Save audio to file""" os.makedirs(os.path.dirname(os.path.abspath(path)), exist_ok=True) torchaudio.save(path, self.waveform.cpu(), self.sample_rate) return path - + def play(self): """Play audio (if in notebook environment)""" try: from IPython.display import Audio, display + display(Audio(self.waveform.cpu().numpy().T, rate=self.sample_rate)) except ImportError: - print("Audio playback requires IPython. Use .save() method instead.") - - return AudioSegment(generated_audio[0].cpu()) \ No newline at end of file + print( + "Audio playback requires IPython. Use .save() method instead." + ) + + return AudioSegment(generated_audio[0].cpu()) diff --git a/voicestar/api.py b/voicestar/api.py index ecc2c31..9ca7067 100644 --- a/voicestar/api.py +++ b/voicestar/api.py @@ -6,6 +6,7 @@ Copyright (c) 2025 Puyuan Peng """ + import argparse, pickle import logging import os, random @@ -38,7 +39,7 @@ def __init__( ): """ Initialize the VoiceStar API with model and configuration. - + Args: model: The VoiceStar model model_args: Model arguments @@ -60,7 +61,7 @@ def __init__( self.audio_tokenizer = audio_tokenizer self.device = device self.quiet = quiet - + # Default decode config self.decode_config = { "codec_sr": codec_sr, @@ -89,7 +90,7 @@ def generate( ): """ Generate speech for the given text using the reference audio. - + Args: audio_fn: Path to reference audio file target_text: Text to synthesize @@ -100,14 +101,14 @@ def generate( repeat_prompt: Number of times to repeat the prompt (or "max") decode_config: Optional custom decoding configuration multi_trial: List for multi-trial inference (usually empty) - + Returns: tuple: (concatenated_sample, generated_sample) """ # Use custom decode config if provided, otherwise use default if decode_config is None: decode_config = self.decode_config - + # encode audio encoded_frames = tokenize_audio( self.audio_tokenizer, audio_fn, offset=0, num_frames=prompt_end_frame @@ -117,7 +118,9 @@ def generate( if isinstance(repeat_prompt, int) and repeat_prompt > 0: cur_repeat_prompt = repeat_prompt while cur_repeat_prompt > 0: - encoded_frames = torch.cat([encoded_frames, single_encoded_frames], dim=2) + encoded_frames = torch.cat( + [encoded_frames, single_encoded_frames], dim=2 + ) cur_repeat_prompt -= 1 elif isinstance(repeat_prompt, str) and repeat_prompt.lower() == "max": repeat_prompt = 0 @@ -128,13 +131,17 @@ def generate( + single_encoded_frames.shape[2] < self.model_args.audio_max_length * decode_config["codec_sr"] ): - encoded_frames = torch.cat([encoded_frames, single_encoded_frames], dim=2) + encoded_frames = torch.cat( + [encoded_frames, single_encoded_frames], dim=2 + ) repeat_prompt += 1 if getattr(self.model_args, "y_sep_token", None) != None: encoded_frames = torch.cat( [ encoded_frames, - torch.LongTensor([self.model_args.y_sep_token] * self.model_args.n_codebooks) + torch.LongTensor( + [self.model_args.y_sep_token] * self.model_args.n_codebooks + ) .unsqueeze(0) .unsqueeze(2) .to(encoded_frames.device), @@ -150,7 +157,9 @@ def generate( # phonemize if isinstance(target_text, list): - text_tokens = [self.phn2num[phn] for phn in target_text if phn in self.phn2num] + text_tokens = [ + self.phn2num[phn] for phn in target_text if phn in self.phn2num + ] else: text_tokens = [ self.phn2num[phn] @@ -164,12 +173,16 @@ def generate( if prefix_transcript is not None: if isinstance(prefix_transcript, list): prefix_tokens = [ - self.phn2num[phn] for phn in prefix_transcript if phn in self.phn2num + self.phn2num[phn] + for phn in prefix_transcript + if phn in self.phn2num ] else: prefix_tokens = [ self.phn2num[phn] - for phn in tokenize_text(self.text_tokenizer, text=prefix_transcript.strip()) + for phn in tokenize_text( + self.text_tokenizer, text=prefix_transcript.strip() + ) if phn in self.phn2num ] single_prefix_tokens = prefix_tokens @@ -179,7 +192,9 @@ def generate( repeat_prompt_count -= 1 if getattr(self.model_args, "x_sep_token", None) != None: text_tokens = ( - prefix_tokens + [getattr(self.model_args, "x_sep_token", None)] + text_tokens + prefix_tokens + + [getattr(self.model_args, "x_sep_token", None)] + + text_tokens ) else: text_tokens = prefix_tokens + text_tokens @@ -225,7 +240,9 @@ def generate( concat_frames, gen_frames = self.model.inference_tts( text_tokens.to(self.device), text_tokens_lens.to(self.device), - original_audio[..., : self.model_args.n_codebooks].to(self.device), # [1,T,8] + original_audio[..., : self.model_args.n_codebooks].to( + self.device + ), # [1,T,8] tgt_y_lens=tgt_y_lens.to(self.device), top_k=decode_config["top_k"], top_p=decode_config["top_p"], @@ -240,7 +257,9 @@ def generate( ), ) # output is [1,K,T] if not self.quiet: - logging.info(f"inference on one sample take: {time.time() - stime:.4f} sec.") + logging.info( + f"inference on one sample take: {time.time() - stime:.4f} sec." + ) logging.info( f"generated encoded_frames.shape: {gen_frames.shape}, which is {gen_frames.shape[-1]/decode_config['codec_sr']} sec." ) @@ -260,11 +279,11 @@ def generate( gen_frames = gen_frames.cpu() concat_sample = self.audio_tokenizer.decode(concat_frames) # [1,8,T] gen_sample = self.audio_tokenizer.decode(gen_frames) - + # Empty cuda cache between runs if torch.cuda.is_available(): torch.cuda.empty_cache() - + return concat_sample, gen_sample @@ -343,7 +362,7 @@ def inference_one_sample( ): """ Backward compatibility function that uses the VoiceStarAPI class. - + This function has the same signature as the original inference_one_sample but internally uses the new VoiceStarAPI class. """ @@ -365,7 +384,7 @@ def inference_one_sample( silence_tokens=decode_config.get("silence_tokens", "[1388,1898,131]"), quiet=quiet, ) - + # Call the generate method return api.generate( audio_fn=audio_fn, diff --git a/voicestar/cli.py b/voicestar/cli.py index 75b1e68..ab80402 100644 --- a/voicestar/cli.py +++ b/voicestar/cli.py @@ -23,25 +23,57 @@ # Main Inference Function ############################################################ + @click.command() -@click.option('--reference-speech', default="./demo/5895_34622_000026_000002.wav", help="Path to reference speech audio file") -@click.option('--target-text', default="I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long.", help="Text to synthesize") -@click.option('--model-name', default="VoiceStar_840M_30s", help="Model name (VoiceStar_840M_30s or VoiceStar_840M_40s)") -@click.option('--reference-text', default=None, help="Reference text (if None, will use Whisper to transcribe)") -@click.option('--target-duration', default=None, type=float, help="Target duration in seconds (if None, will estimate)") -@click.option('--codec-audio-sr', default=16000, help="Codec audio sample rate (do not change)") -@click.option('--codec-sr', default=50, help="Codec sample rate (do not change)") -@click.option('--top-k', default=10, help="Top-k sampling parameter (try 10, 20, 30, 40)") -@click.option('--top-p', default=1.0, help="Top-p sampling parameter (do not change)") -@click.option('--min-p', default=1.0, help="Min-p sampling parameter (do not change)") -@click.option('--temperature', default=1.0, help="Sampling temperature") -@click.option('--kvcache', default=1, help="Use KV cache (set to 0 if OOM)") -@click.option('--repeat-prompt', default=1, help="Repeat prompt to improve speaker similarity") -@click.option('--stop-repetition', default=3, help="Stop repetition parameter (will not use it)") -@click.option('--sample-batch-size', default=1, help="Sample batch size (do not change)") -@click.option('--seed', default=1, help="Random seed") -@click.option('--output-dir', default="./generated_tts", help="Output directory") -@click.option('--cut-off-sec', default=100, help="Cut-off seconds (do not adjust)") +@click.option( + "--reference-speech", + default="./demo/5895_34622_000026_000002.wav", + help="Path to reference speech audio file", +) +@click.option( + "--target-text", + default="I cannot believe that the same model can also do text to speech synthesis too! And you know what? this audio is 8 seconds long.", + help="Text to synthesize", +) +@click.option( + "--model-name", + default="VoiceStar_840M_30s", + help="Model name (VoiceStar_840M_30s or VoiceStar_840M_40s)", +) +@click.option( + "--reference-text", + default=None, + help="Reference text (if None, will use Whisper to transcribe)", +) +@click.option( + "--target-duration", + default=None, + type=float, + help="Target duration in seconds (if None, will estimate)", +) +@click.option( + "--codec-audio-sr", default=16000, help="Codec audio sample rate (do not change)" +) +@click.option("--codec-sr", default=50, help="Codec sample rate (do not change)") +@click.option( + "--top-k", default=10, help="Top-k sampling parameter (try 10, 20, 30, 40)" +) +@click.option("--top-p", default=1.0, help="Top-p sampling parameter (do not change)") +@click.option("--min-p", default=1.0, help="Min-p sampling parameter (do not change)") +@click.option("--temperature", default=1.0, help="Sampling temperature") +@click.option("--kvcache", default=1, help="Use KV cache (set to 0 if OOM)") +@click.option( + "--repeat-prompt", default=1, help="Repeat prompt to improve speaker similarity" +) +@click.option( + "--stop-repetition", default=3, help="Stop repetition parameter (will not use it)" +) +@click.option( + "--sample-batch-size", default=1, help="Sample batch size (do not change)" +) +@click.option("--seed", default=1, help="Random seed") +@click.option("--output-dir", default="./generated_tts", help="Output directory") +@click.option("--cut-off-sec", default=100, help="Cut-off seconds (do not adjust)") def run_inference( reference_speech, target_text, @@ -80,7 +112,11 @@ def run_inference( # Load model, phn2num, and args torch.serialization.add_safe_globals([Namespace]) - device = "cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu" # MPS support + device = ( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) # MPS support ckpt_fn = hf_hub_download(repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth") bundle = torch.load(ckpt_fn, map_location=device, weights_only=True) @@ -93,7 +129,9 @@ def run_inference( # If reference_text not provided, use whisper large-v3-turbo if reference_text is None: - print("[Info] No reference_text provided, transcribing reference_speech with Whisper.") + print( + "[Info] No reference_text provided, transcribing reference_speech with Whisper." + ) wh_model = whisper.load_model("large-v3-turbo") result = wh_model.transcribe(reference_speech) prefix_transcript = result["text"] @@ -104,16 +142,22 @@ def run_inference( # If target_duration not provided, estimate from reference speech + target_text if target_duration is None: target_generation_length = estimate_duration(reference_speech, target_text) - print(f"[Info] target_duration not provided, estimated as {target_generation_length:.2f} seconds. If not desired, please provide a target_duration.") + print( + f"[Info] target_duration not provided, estimated as {target_generation_length:.2f} seconds. If not desired, please provide a target_duration." + ) else: target_generation_length = float(target_duration) # signature from snippet if args.n_codebooks == 4: # signature = "./pretrained/encodec_6f79c6a8.th" - signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_4cb2048_giga.th") # not sure if this is the right signature + signature = hf_hub_download( + repo_id="pyp1/VoiceCraft", filename="encodec_4cb2048_giga.th" + ) # not sure if this is the right signature elif args.n_codebooks == 8: - signature = hf_hub_download(repo_id="pyp1/VoiceCraft", filename="encodec_8cb1024_giga.th") + signature = hf_hub_download( + repo_id="pyp1/VoiceCraft", filename="encodec_8cb1024_giga.th" + ) else: # fallback, just use the 6-f79c6a8 raise ValueError(f"Invalid number of codebooks: {args.n_codebooks}") @@ -140,24 +184,30 @@ def run_inference( # decode_config from snippet decode_config = { - 'top_k': top_k, - 'top_p': top_p, - 'min_p': min_p, - 'temperature': temperature, - 'stop_repetition': stop_repetition, - 'kvcache': kvcache, - 'codec_audio_sr': codec_audio_sr, - 'codec_sr': codec_sr, - 'silence_tokens': silence_tokens, - 'sample_batch_size': sample_batch_size + "top_k": top_k, + "top_p": top_p, + "min_p": min_p, + "temperature": temperature, + "stop_repetition": stop_repetition, + "kvcache": kvcache, + "codec_audio_sr": codec_audio_sr, + "codec_sr": codec_sr, + "silence_tokens": silence_tokens, + "sample_batch_size": sample_batch_size, } # Run inference print("[Info] Running TTS inference...") concated_audio, gen_audio = inference_one_sample( - model, args, phn2num, text_tokenizer, audio_tokenizer, - reference_speech, target_text, - device, decode_config, + model, + args, + phn2num, + text_tokenizer, + audio_tokenizer, + reference_speech, + target_text, + device, + decode_config, prompt_end_frame=prompt_end_frame, target_generation_length=target_generation_length, delay_pattern_increment=delay_pattern_increment, @@ -181,5 +231,6 @@ def run_inference( def main(): run_inference() + if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/voicestar/data/encodec.py b/voicestar/data/encodec.py index fdb9267..fc74ecc 100644 --- a/voicestar/data/encodec.py +++ b/voicestar/data/encodec.py @@ -1748,8 +1748,14 @@ def get_encodec_autoencoder(encoder_name: str, cfg: omegaconf.DictConfig): def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> CompressionModel: """Instantiate a compression model.""" if device == None: - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") - state = torch.load(ckpt_fn, map_location="cpu", weights_only=False) # TODO: Convert to SafeTensors + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) + state = torch.load( + ckpt_fn, map_location="cpu", weights_only=False + ) # TODO: Convert to SafeTensors cfg = state["xp.cfg"] cfg.device = str(device) weights = state["best_state"]["model"] @@ -1826,7 +1832,11 @@ def get_compression_model(ckpt_fn, encode_only=False, device="cpu") -> Compressi "/home/pyp/BoostedVoiceEditor/demo/bible_encodecTest.wav", "/home/pyp/BoostedVoiceEditor/demo/miley_encodecTest.wav", ] - device = torch.device("cuda" if torch.cuda.is_available() else "mps" if torch.backends.mps.is_available() else "cpu") + device = torch.device( + "cuda" + if torch.cuda.is_available() + else "mps" if torch.backends.mps.is_available() else "cpu" + ) model = get_compression_model(ckpt_fn, device=device) for audio_in_fn, audio_out_fn in zip(audio_in_fns, audio_out_fns): diff --git a/voicestar/modules/utils.py b/voicestar/modules/utils.py index e074cd3..f3dab55 100644 --- a/voicestar/modules/utils.py +++ b/voicestar/modules/utils.py @@ -9,6 +9,7 @@ import torch + def make_pad_mask(lengths: torch.Tensor, max_len: int = 0) -> torch.Tensor: """ Args: diff --git a/voicestar/scripts/__init__.py b/voicestar/scripts/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/voicestar/scripts/copy_codebase.py b/voicestar/scripts/copy_codebase.py new file mode 100644 index 0000000..ea2fcc5 --- /dev/null +++ b/voicestar/scripts/copy_codebase.py @@ -0,0 +1,57 @@ +import os +import shutil +import fnmatch + + +def parse_gitignore(gitignore_path): + """Parse a .gitignore file and return a list of patterns.""" + patterns = [] + with open(gitignore_path, "r") as f: + for line in f: + # Ignore comments and blank lines + line = line.strip() + if not line or line.startswith("#"): + continue + # Handle wildcards and directory separators + patterns.append(line) + return patterns + + +def file_matches_patterns(file_path, patterns): + """Check if a file matches any of the patterns in .gitignore.""" + for pattern in patterns: + if fnmatch.fnmatch(file_path, pattern): + return True + return False + + +def copy_codebase(src, dst, max_size_mb=5, gitignore_path=None): + """Copy files from src to dst, skipping files larger than max_size_mb and matching .gitignore patterns.""" + if gitignore_path and os.path.exists(gitignore_path): + patterns = parse_gitignore(gitignore_path) + else: + patterns = [] + print("patterns to ignore: ", patterns) + os.makedirs(dst, exist_ok=True) + for root, dirs, files in os.walk(src): + for file in files: + file_path = os.path.join(root, file) + relative_path = os.path.relpath(file_path, src) + dst_path = os.path.join(dst, relative_path) + # ignore .git because of permission issues + if "/.git/" in file_path: + continue + + # Check .gitignore patterns + if file_matches_patterns(file_path, patterns): + # print(f"Skipping {file_path} because it matches a pattern in .gitignore") + continue + + # Check file size + if os.path.getsize(file_path) > max_size_mb * 1024 * 1024: + print(f"Skipping {file_path} because it's larger than {max_size_mb}MB") + continue + + # Make sure the destination directory exists + os.makedirs(os.path.dirname(dst_path), exist_ok=True) + shutil.copy(file_path, dst_path) diff --git a/voicestar/utils.py b/voicestar/utils.py index 15b51d5..bb3f8bd 100644 --- a/voicestar/utils.py +++ b/voicestar/utils.py @@ -6,14 +6,16 @@ Copyright (c) 2025 Puyuan Peng """ + import os import random import numpy as np import torch import torchaudio + def seed_everything(seed=1): - os.environ['PYTHONHASHSEED'] = str(seed) + os.environ["PYTHONHASHSEED"] = str(seed) random.seed(seed) np.random.seed(seed) torch.manual_seed(seed) @@ -21,6 +23,7 @@ def seed_everything(seed=1): torch.backends.cudnn.benchmark = False torch.backends.cudnn.deterministic = True + def estimate_duration(ref_audio_path, text): """ Estimate duration based on seconds per character from the reference audio. diff --git a/voicestar/voicestar.py b/voicestar/voicestar.py index 1b57f9d..207d4ff 100644 --- a/voicestar/voicestar.py +++ b/voicestar/voicestar.py @@ -6,6 +6,7 @@ Copyright (c) 2025 Puyuan Peng """ + import random, os, copy from typing import Dict, Iterator, List, Tuple, Union import logging From e052ec5d69ec5d6e9def1f1b3b960184cb3f3b85 Mon Sep 17 00:00:00 2001 From: mrfakename Date: Mon, 7 Apr 2025 19:02:19 -0700 Subject: [PATCH 4/7] Update gradio app --- app.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app.py b/app.py index f49b9fa..c5d09e7 100644 --- a/app.py +++ b/app.py @@ -40,7 +40,7 @@ def generate_audio( texts = txtsplit(text) audios = [] - for t in progress.tqdm(texts): + for t in progress.tqdm(texts, desc=f"Generating audio in {len(texts)} chunks"): audio = model.generate( reference_speech=reference_speech, text=t, target_duration=target_duration ) From ec8e1ecdb2bef3847c695fb5066b040488f6e793 Mon Sep 17 00:00:00 2001 From: mrfakename Date: Mon, 7 Apr 2025 19:05:45 -0700 Subject: [PATCH 5/7] remove generated_tts --- generated_tts/generated.wav | Bin 503120 -> 0 bytes 1 file changed, 0 insertions(+), 0 deletions(-) delete mode 100644 generated_tts/generated.wav diff --git a/generated_tts/generated.wav b/generated_tts/generated.wav deleted file mode 100644 index ccd20bca4c75ec370e9589cf1779f376794bbc21..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 503120 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 z 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�B$I%<;+LBmmPre;lf- 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

1#EZO4AbQ|K+9-2R34iH5%Z@4(zS<-Fc%P& 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 Date: Mon, 7 Apr 2025 19:06:08 -0700 Subject: [PATCH 6/7] remove unnecessary files --- config.py | 929 ----------------------------------------- inference_gradio.py | 328 --------------- inference_tts_utils.py | 250 ----------- 3 files changed, 1507 deletions(-) delete mode 100644 config.py delete mode 100644 inference_gradio.py delete mode 100644 inference_tts_utils.py diff --git a/config.py b/config.py deleted file mode 100644 index 1338dfa..0000000 --- a/config.py +++ /dev/null @@ -1,929 +0,0 @@ -import argparse - - -def int_or_str(value): - """Custom function to allow both int and str types.""" - try: - return int(value) # Try converting to integer - except ValueError: - return value # If conversion fails, return as string - - -def MyParser(): - parser = argparse.ArgumentParser( - formatter_class=argparse.ArgumentDefaultsHelpFormatter - ) - # general training - parser.add_argument("--seed", type=int, default=1) - parser.add_argument("--debug", type=int, default=0) - parser.add_argument("--multinodes", type=int, default=0) - parser.add_argument("--dist_url", default="env://", type=str) - parser.add_argument("--dist_backend", default="nccl", type=str) - parser.add_argument( - "--precision", - type=str, - default="float16", - help="we might need float32 for NAR model", - ) - parser.add_argument("--num_workers", type=int, default=8, help="per gpu") - parser.add_argument("--resume", action="store_true", default=False) - parser.add_argument("--tb_write_every_n_steps", type=int, default=100) - parser.add_argument("--print_every_n_steps", type=int, default=250) - parser.add_argument("--val_every_n_steps", type=int, default=500) - parser.add_argument( - "--inference_every_n_steps", - type=int, - default=3000, - help="will only get to inference when model is saved, and therefore this needs to be multiple of val_every_n_steps", - ) - parser.add_argument( - "--save_every_n_steps", - type=int, - default=10000000, - help="save the model every n steps, will save the model as bundle_step$step.pth", - ) - parser.add_argument("--lr", type=float, default=1e-4) - parser.add_argument( - "--batch_size", - type=int, - default=100, - help="this is the effective batch size per gpu, no matter whether using gradient_accumulation_steps", - ) - parser.add_argument("--weight_decay", type=float, default=1e-2) - parser.add_argument( - "--warmup_fraction", - type=float, - default=0.1, - help="use linear warmup, the proportion of the training steps that are used for warming up", - ) - parser.add_argument("--num_epochs", type=int, default=10) - parser.add_argument( - "--num_steps", - type=int, - default=None, - help="if not None, will ignore n_epochs and use num_steps as the total number of amount of training, can try e.g. 400000 i.e. 400k steps", - ) - parser.add_argument("--gradient_accumulation_steps", type=int, default=1) - parser.add_argument( - "--gradient_clip_val", - type=float, - default=1.0, - help="the value for torch.nn.utils.clip_grad_norm_()", - ) - parser.add_argument( - "--early_stop_step", - type=int, - default=3200, - help="stop training after this many steps of non-improvement", - ) - parser.add_argument( - "--early_stop_threshold", - type=float, - default=-1.0, - help="early stop after the improvement is below this threshold for certain number of steps", - ) - - # path - parser.add_argument( - "--exp_dir", - type=str, - default="/saltpool0/scratch/pyp/VoiceEditor/", - help="will be combined with dataset name", - ) - parser.add_argument( - "--dataset", - type=str, - help="e.g. 'libritts', 'librilight', 'spotify', they are folder name in the data dir also", - ) - parser.add_argument( - "--dataset_dir", - type=str, - help="need to be compatible with corresponding dataset py file", - ) - parser.add_argument( - "--compact_folder_name", - type=str, - default=None, - help="if not None, will use compact_combined_dataset.py, and this is the folder name of the compact dataset", - ) - parser.add_argument( - "--inference_dataset_dir", - type=str, - default="/data/scratch/pyp/datasets/librilight/preprocessed", - help="need to be compatible with corresponding dataset py file", - ) - - parser.add_argument( - "--training_stage", - type=int, - default=1, - help="if 1, train VoiceEditor_one, if 2 train VoiceEditor_seven", - ) - parser.add_argument( - "--local_wandb", - type=int, - default=0, - help="if 1, will use local wandb, otherwise use the global one", - ) - parser.add_argument( - "--wandb_entity", - type=str, - default="puyuanpeng", - help="the entity (usually your username) for wandb", - ) - # data - parser.add_argument( - "--librilight_ratio", - type=float, - default=1, - help="the portion of lightlight compared to gigaspeech, 1 means equal, 2 means librilight data is twice as much as gigaspeech", - ) - parser.add_argument( - "--plus_librilight_root", - type=str, - default=None, - help="if not None, will combine gigaspeech and librilight, this is the root folder to librilight. Note that will need to merge the vocab.txt based on gigaspeech's, in order to be able to load a pretrained model", - ) - parser.add_argument( - "--plus_librilight_phn_folder_name", - type=str, - default=None, - help="if not None, will combine gigaspeech and librilight, this is the phoneme folder name of librilight", - ) - parser.add_argument( - "--plus_librilight_encodec_folder_name", - type=str, - default=None, - help="if not None, will combine gigaspeech and librilight, this is the encodec folder name of librilight", - ) - parser.add_argument( - "--plus_librilight_manifest_name", - type=str, - default=None, - help="if not None, will combine gigaspeech and librilight, this is the manifest folder name of librilight", - ) - parser.add_argument( - "--skip_us", - type=int, - default=0, - help="skip the giga utterances that contains 'j uː ɛ s' because of the tokenization issue", - ) - parser.add_argument( - "--pseudo_epoch_size", - type=int, - default=37901, - help="only use for Eden scheduler. 37901 is the epoch size in the default optim setting, this is probably too big", - ) - parser.add_argument( - "--switch_order", - type=int, - default=0, - help="this is only for hificodec, where we switch the order of 2 and 3nd codebook", - ) - parser.add_argument( - "--phn_folder_name", - type=str, - default="phoneme", - help="for libritts I also have arpa phns, in which case should be phonemes_arpa", - ) - parser.add_argument( - "--encodec_folder_name", - type=str, - default="mimi_8cb", - help="folder where encodec codes are stored", - ) - parser.add_argument( - "--manifest_name", - type=str, - default="manifest_final", - help="if using hificodec, it should be hificodec_menifest, if using encodec, it is the default", - ) - parser.add_argument( - "--pad_x", - type=int, - default=1, - help="whether or not always pad x to have text_max_length. select 1 to get the maximal memory consumption, but the actual case should be smaller, better to have it being 0", - ) - parser.add_argument( - "--max_num_tokens", - type=int, - default=18750, - help="max number of encodec tokens per gpu, this is only used when using dynamic batching, will ignore batch size. Note that batch size is the final effective batch size (sum of batch on each gpu), but max_num_tokens is per gpu", - ) - parser.add_argument( - "--val_max_num_tokens", - type=int, - default=6000, - help="FOR validation, this basically is for music-gen because of high mem consumption. max number of encodec tokens per gpu, this is only used when using dynamic batching, will ignore batch size. Note that batch size is the final effective batch size (sum of batch on each gpu), but max_num_tokens is per gpu", - ) - parser.add_argument("--num_buckets", type=int, default=10) - parser.add_argument("--dynamic_batching", type=int, default=1) - parser.add_argument( - "--audio_max_length", - type=float, - default=120, - help="in second, crop the audio is length is longer than this", - ) - parser.add_argument( - "--audio_min_length", - type=float, - default=2, - help="in second, drop the audio if length is shorter than this", - ) - parser.add_argument( - "--text_max_length", type=int, default=1000, help="if too long, we crop" - ) - parser.add_argument( - "--text_min_length", type=float, default=10, help="if too short, will drop" - ) - parser.add_argument( - "--encodec_sr", - type=float, - default=50, - help="for 24kHz mimi model, it produces 12.5 codes for 1 sec of audio", - ) - parser.add_argument( - "--mask_len_min", type=int, default=20, help="Minimum mask length" - ) - parser.add_argument( - "--mask_len_max", type=int, default=400, help="Maximum mask length" - ) - parser.add_argument( - "--extra_mask_len_min", type=int, default=2, help="Minimum extra mask length" - ) - parser.add_argument( - "--extra_mask_len_max", type=int, default=20, help="Maximum extra mask length" - ) - parser.add_argument( - "--final_audio_token_len", - type=int, - default=772, - help="this is only for stage 1 training, since we add eog, start_of_continue, and a random amount of extra mask, --audio_max_length won't be the final max length, the self.args.final_audio_token_len = self.args.audio_max_length*self.args.encodec_sr+self.args.extra_mask_len_max+2 ", - ) - - # model - parser.add_argument( - "--ttsonly", default=0, type=int, help="if 1, only train tts model, no CM3" - ) - parser.add_argument( - "--load_existing_text_embedding", - type=int, - default=0, - help="if 1, when load model and the text vocab doesn't match, will load the existing weights while the new weights will be initialized randomly", - ) - parser.add_argument( - "--fly", type=int, default=0, help="if 1, encode chunked audio on the fly" - ) - parser.add_argument( - "--encodec_ckpt", - type=str, - default="/data/scratch/pyp/exp_pyp/audiocraft/encodec/xps/6f79c6a8/checkpoint.th", - ) - parser.add_argument( - "--downsample_rate", - type=int, - default=320, - help="the downsample rate for the encodec model, 16000/320 = 50Hz", - ) - parser.add_argument( - "--segtts_mask", - type=int, - default=0, - help="if 1, use segtts_mask model, where we have a prefix and segment utterance into two and shifted separately for modeling, and use make use of mask:0, by insert two mask:0 in the middle of the two segments", - ) - parser.add_argument( - "--segtts", - type=int, - default=0, - help="if 1, use segtts model, where we have a prefix and segment utterance into two and shifted separately for modeling", - ) - parser.add_argument( - "--edge", - type=int, - default=0, - help="if 1, use edge prediction for the first codebook", - ) - parser.add_argument( - "--duration_loss_weight", - type=float, - default=1.0, - help="weight on the duration loss", - ) - parser.add_argument( - "--drop_long", - type=int, - default=1, - help="if this is true, will drop example whose encodec sequence or phone sequence is too long, rather than cropping as we did before, to avoid hellucination", - ) - parser.add_argument( - "--eos", - type=int, - default=2051, - help="this is to be used with reduced_eog, where we end the utterance with eos, and end the generated segment with eog, also when this is used, the n_special should be 4", - ) - parser.add_argument( - "--reduced_eog", - type=int, - default=1, - help="for the non-final segments, do not insert eog at the end, this could hopefully solve the early stopping issue when doing tts", - ) - - parser.add_argument( - "--valle_orig", - type=int, - default=0, - help="the original valle model, trained for TTS", - ) - parser.add_argument("--valle_max_prompt_len", type=float, default=6, help="in sec.") - # randomly choose a portion as tts examples during training - parser.add_argument( - "--tts_portion", - type=float, - default=0, - help="randomly choose a portion of the training examples as tts examples, where no mask and rearrangement is used", - ) - - # put special tokens first to handle different vocab_size - parser.add_argument( - "--special_first", - type=int, - default=0, - help="if 1, need to have special tokens to be the first few tokens, e.g. 0, 1, 2, which means we need to adjust the preprocessing and postprocessing of the encodec codes. note that we hard coded to have 3 special tokens", - ) - parser.add_argument("--n_special", type=int, default=4, help="empty, eog, pad, eos") - - # weight codebook differently - parser.add_argument( - "--codebook_weight", type=str, default=None, help="e.g. ['5','1','0.5','0.1']" - ) - - # args for MusicGen - parser.add_argument( - "--mask_span_weight", - default=1.0, - type=float, - help="the weight on the tokens in masked span", - ) - parser.add_argument( - "--unmask_span_weight", - default=1.0, - type=float, - help="the weight on unmasked span", - ) - parser.add_argument( - "--start_end_weight", - default=None, - type=str, - help="weight the start x tokens and end x tokens differently, e.g. (10,2.0), means x == 10, weight==2.0", - ) - # for now not consider the two weights above, only consider eog_weight, which is defined below somewhere, as the above two are not super principled - - parser.add_argument( - "--musicgen", - type=int, - default=0, - help="whether or not use this model, will also have an impact on the output shape of the dataset", - ) - parser.add_argument( - "--enc_dec", - default=0, - type=int, - help="use enc-dec architecture, text is from the enc, only for musicgen", - ) - parser.add_argument( - "--dec", - default=0, - type=int, - help="use dec only architecture, text is from the enc, only for musicgen. Exclusive with --enc_dec", - ) - parser.add_argument( - "--empty_token", - default=2048, - type=int, - help="indicating the no token at the position for the codebook", - ) - # args for the optimizer and scheduler from Feiteng - # original setup for the 3 params are 5000 4 and 1000 - # but that's because set_epoch is run on num_gradient_accumulation_step*step (with 4 being the accumulation step) - # so I scaled down them a little bit - # will try scaling them back if this doesn't work - parser.add_argument( - "--optimizer_name", - type=str, - default="AdamW", - help="can also use ScaledAdam, in which case we'll also use the Eden scheduler", - ) - parser.add_argument( - "--reduce_lr_start_step", - type=int, - default=3000, - help="after which significantly reduce the lr. a param for the eden optimizer", - ) - parser.add_argument("--reduce_lr_start_epoch", type=int, default=4) - parser.add_argument("--clipping_update_period", type=int, default=600) - - # below are args for valle - # below are args for valle - parser.add_argument( - "--valle", type=int, default=0, help="if 1, use valle model (cm3)" - ) - parser.add_argument("--decoder_dim", type=int, default=1024) - parser.add_argument("--norm_first", action="store_true", default=True) - parser.add_argument("--add_prenet", action="store_true", default=False) - parser.add_argument( - "--prefix_mode", - type=int, - default=5, - help="this is for NAR, we only do 5, which is CM3", - ) - parser.add_argument("--share_embedding", action="store_true", default=False) - parser.add_argument("--nar_scale_factor", type=float, default=1.0) - parser.add_argument("--prepend_bos", action="store_true", default=False) - parser.add_argument( - "--sync_nar", - type=int, - default=0, - help="whether to choose the same NAR model to run for training_stage==2 across different process (this is only for DDP)", - ) - # above are args for valle - # above are args for valle - - # add parallel_pattern - parser.add_argument( - "--parallel_pattern", - type=int, - default=0, - help="if 1, use parallel pattern, we also use LFSC codec", - ) - parser.add_argument( - "--full_prediction", - type=int, - default=0, - help="this is for ve1, if 1, use full autoregressive mask, and calculate loss over all tokens, except for mask_tokens", - ) - parser.add_argument( - "--multicm3", - type=int, - default=0, - help="cm3 model but allows multiple mask spans", - ) - parser.add_argument( - "--max_mask_portion", - type=float, - default=0.7, - help="should mask a utterance for more than this portion", - ) - parser.add_argument( - "--max_n_spans", - type=int, - default=8, - help="maximal number of spans, only use when using multicm3, this is used to decide number of mask_embedding, and max clamp value if use Poisson distribution, if use uniform distribution to sample number of spans if will be uniform(1,max_n_spans)", - ) - parser.add_argument( - "--shuffle_mask_embedding", - type=int, - default=0, - help="whether shuffle the mask embedding, so that mask:0 is not the most well trained, default is not shuffling. The default has it's benefit, as it make sure that mask:0 always appear the first", - ) - parser.add_argument( - "--mask_sample_dist", - type=str, - default="uniform", - help="uniform or poissonx, e.g. poisson1, meaning the parameter lambda is 1, it will most likely sample 1 masks", - ) - parser.add_argument( - "--min_gap", - type=int, - default=10, - help="after sampled starts, delete later one if it closer to the former start than the min_gap", - ) - - parser.add_argument( - "--cm3", - type=int, - default=0, - help="use cm3 style for ve1, the input from dataloader is going to be just raw data, all masking and rearrangement will happen whin the model", - ) - - parser.add_argument( - "--sep_special_token", - type=int, - default=0, - help="remove text/audio pad token, set audio_mask_token and start of continue to be separately learned embeddings. Therefore, for ve1 self.n_text_tokens == self.args.text_vocab_size, self.n_audio_tokens == self.args.audio_vocab_size + 2, for ve7, self.n_text_tokens == self.args.text_vocab_size, self.n_audio_tokens == self.args.audio_vocab_size", - ) - parser.add_argument( - "--one_causal", - type=int, - default=0, - help="whether model VE_one generation as autoregressive gen or non-autoregressive gen", - ) - parser.add_argument("--n_codebooks", type=int, default=8) - parser.add_argument( - "--weight_sharing", - type=int, - default=0, - help="sharing weights between VE_seven predict layer and embedding layer", - ) - parser.add_argument( - "--text_vocab_size", type=int, default=86, help="Size of text vocabulary" - ) - parser.add_argument( - "--text_pad_token", - type=int, - default=86, - help="padding of the text tokens, not attended", - ) - # parser.add_argument('--audio_vocab_size', type=int, default=1024, help='Size of audio vocabulary') - parser.add_argument( - "--audio_vocab_size", - type=str, - default="2048", - help="Size of audio vocabulary, can be specified as '[128,512,1024,2048]'", - ) - parser.add_argument( - "--audio_mask_token", - type=int, - default=1024, - help="Audio mask token, this the the extra mask used in the masked region for AR, for NAR, the entire masked region will be filled with it", - ) - parser.add_argument( - "--bog", type=int, default=1025, help="Begin of generation token" - ) - parser.add_argument("--eog", type=int, default=2049, help="End of generation token") - parser.add_argument( - "--start_of_continue", - type=int, - default=1027, - help="this token follows the masked region, proceeds the first unmasked token, to indicate that gt tokens starts", - ) - parser.add_argument( - "--audio_pad_token", - type=int, - default=2050, - help="padding of the encodec codes, not attended", - ) - parser.add_argument("--d_model", type=int, default=1024, help="Model dimension") - parser.add_argument( - "--audio_embedding_dim", - type=int, - default=128, - help="dimension for encodec continues embedding (before being quantized)", - ) - parser.add_argument( - "--text_embedding_dropout", - type=float, - default=0.1, - help="Dropout for text embedding", - ) - parser.add_argument( - "--audio_embedding_dropout", - type=float, - default=0, - help="Dropout for audio embedding", - ) - parser.add_argument( - "--text_positional_embedding_dropout", - type=float, - default=0.1, - help="Dropout for text positional embedding", - ) - parser.add_argument( - "--audio_positional_embedding_dropout", - type=float, - default=0.1, - help="Dropout for audio positional embedding", - ) - parser.add_argument( - "--trm_dropout", type=float, default=0.1, help="Dropout for transformer" - ) - parser.add_argument( - "--nhead", type=int, default=16, help="Number of attention heads" - ) - parser.add_argument( - "--num_encoder_layers", type=int, default=12, help="Number of encoder layers" - ) - parser.add_argument( - "--num_decoder_layers", type=int, default=12, help="Number of decoder layers" - ) - parser.add_argument( - "--eog_weight", - type=float, - default=1.0, - help="Weight for End of generation token", - ) - parser.add_argument( - "--stage_one_load_encodec_embedding", - type=str, - default=None, - help="Path to load encodec embedding for stage one. On our lab machine it is /saltpool0/scratch/pyp/VoiceEditor/encodec_embedding/24khz_8codebooks.pth, 8 is the n_codebooks", - ) - parser.add_argument( - "--stage_two_load_encodec_embedding", - type=str, - default=None, - help="Path to load encodec embedding for stage two。 On our lab machine it is /saltpool0/scratch/pyp/VoiceEditor/encodec_embedding/24khz_8codebooks.pth, 8 is the n_codebooks", - ) - parser.add_argument( - "--stage_two_load_ve_one_embedding", - type=str, - default=None, - help="Path to load VoiceEditor_one audio embedding for stage two", - ) - parser.add_argument( - "--load_model_from", - type=str, - default=None, - help="Path to load model from, this will be effective last, so will overwrite all previous load, including resume", - ) - parser.add_argument( - "--load_model_from_ve1", - type=str, - default=None, - help="Path to load ve1 model weights from, this will be effective last, designed for loading the encoder weights of the VE7 from a pretrained VE1", - ) - - ## below are args for the new long model - parser.add_argument( - "--target_time_stretch_prob", - type=float, - default=0, - help="the probability of time stretching the target audio", - ) - parser.add_argument( - "--target_time_stretch_bound", - type=float, - default=0.1, - help="the bound of the time stretching target audio, e.g. 0.1 means the audio will be stretched by 0.9 to 1.1", - ) - parser.add_argument( - "--time_stretch_prob", - type=float, - default=0, - help="the probability of time stretching the audio", - ) - parser.add_argument( - "--time_stretch_bound", - type=float, - default=0.3, - help="the bound of the time stretching, e.g. 0.3 means the audio will be stretched by 0.7 to 1.3", - ) - parser.add_argument( - "--no_loss_on_prefix", - type=int, - default=0, - help="if 1, will not calculate loss on the prefix acoustic tokens", - ) - parser.add_argument( - "--x_sep_token", - type=int, - default=None, - help="if not None, will use this token in between prompt text and target generation text", - ) - parser.add_argument( - "--y_sep_token", - type=int, - default=None, - help="if not None, will use this token in between prompt codec tokens and target codec tokens", - ) - parser.add_argument( - "--neighbor_prompt_prob", - type=float, - default=0, - help="the probability of using the prompt from the neighbor", - ) - parser.add_argument( - "--neighbor_folder_name", - type=str, - default="neighbors", - help="folder where the neighbors of the current audio files are stored, each row contains three tab separated entries: neighbor_fn, neighbor_temporal_distance, neighbor_duration", - ) - parser.add_argument( - "--alignment_folder_name", - type=str, - default="alignment", - help="folder where the forced alignment of the current audio files are stored, in csv format, each row contains five comma separated entries: begin, end, label, type, speaker, the first row is header", - ) - parser.add_argument( - "--ipa_alignment_folder_name", - type=str, - default="ipa_alignment", - help="folder where the forced alignment of the current audio files are stored, in txt format, each row contains three tab separated entries: begin, end, ipa phn sequence, generated using data/ll60k_preprocessing/step7_ipa_alignment.py", - ) - parser.add_argument( - "--max_prompt_len", - type=float, - default=30, - help="in sec., maximal prompt length selected from some neighboring file", - ) - parser.add_argument( - "--min_prompt_len", - type=float, - default=0.5, - help="in sec., minimal prompt length selected from some neighboring file", - ) - parser.add_argument( - "--neighbor_selection_method", - type=str, - default="maxdist_60", - help="maxdist_60 means uniformly select a neighbor that's within 60 sec of the current audio file", - ) - parser.add_argument( - "--num_trial", type=int, default=5, help="number of tries to select a neighbor" - ) - parser.add_argument( - "--prompt_start_from_begining_prob", - type=float, - default=0.5, - help="the probability of starting the prompt from the beginning of the neighbor", - ) - parser.add_argument( - "--min_alignment_len", type=int, default=5, help="in number of words" - ) - parser.add_argument( - "--audio_folder_name", - type=str, - default="audio", - help="folder where the audio files are stored", - ) - - # rope parameters - parser.add_argument( - "--decoder_regular_rope", - type=int, - default=0, - help="if 1, will use regular rope for the decoder (note that we always use regular rope for encoder). ", - ) - parser.add_argument( - "--progress_no_multiple", - type=int, - default=0, - help="if 1, will not multiple the percentage progress by the length of the key, see apply_rotary_pos_emb in models/modules/activation.py, this applies to both rope and sinusoidal positional encoding. Note that progress scale is still applied, i.e. when we only apply progress scale, but not multiple, the scaling factor is constant for every sample, rather than sample dependent", - ) - parser.add_argument( - "--add_eos_to_text", - type=int, - default=0, - help="if not 0, use this number as eos and add to the end of text token, usually use the second to last token in the vocab size", - ) - parser.add_argument( - "--add_bos_to_text", - type=int, - default=0, - help="if not 0, use this number as bos and add to the begining of text token, usually use the third to last token in the vocab size", - ) - parser.add_argument( - "--use_sinusoidal", - type=int, - default=0, - help="if 1, will use sinusoidal positional encoding, otherwise use rope. BUT if rope_base is None, will use sinusoidal", - ) - parser.add_argument( - "--sinusoidal_base", - type=int, - default=1e4, - help="the base of the exponential function, default is 1e4", - ) - parser.add_argument( - "--use_sinusoidal_progress", - type=int, - default=0, - help="if 1, will use sinusoidal positional encoding for progress, otherwise use rope", - ) - parser.add_argument( - "--rope_base", - type=int, - default=None, - help="the base of the exponential function, default is 1e4, if None, will not use rope", - ) - parser.add_argument( - "--multiple_key_length", - type=int, - default=0, - help="if 1, during progress calculation, will multiple the precentage progress by the length of the key, otherwise multiple with length of query. see models/rope_playground.ipynb", - ) - parser.add_argument( - "--progress_scale", - type=float, - default=1.0, - help="scale the progress, the smaller the value, the bigger the diagonal in attention score, see models/rope_playground.ipynb", - ) - - # attention alignment loss - parser.add_argument( - "--attention_alignment_loss", - type=float, - default=0.0, - help="the weight on the attention alignment loss, if 0, will not calculate the loss", - ) - parser.add_argument( - "--alignment_loss_layer", - type=str, - default="['0-1', '2', '3']", - help='the layers to calculate the alignment loss, e.g. ["0-1", "2", "3"]', - ) - parser.add_argument( - "--alignment_loss_head", - type=str, - default="['0-1', '2', '3']", - help='the attention heads to calculate the alignment loss, e.g. ["0-1", "2", "3"]', - ) - parser.add_argument( - "--alignment_blank_logit", - type=float, - default=-1.0, - help="the logit for the blank token added to the attention weights", - ) - - # inference parameters - parser.add_argument( - "--metrics", - type=str, - default="['spk_sim','wer','mcd','pitch','energy','pesq','utmos']", - ) - parser.add_argument( - "--res_jsonl_root", type=str, default="/home/pyp/BoostedVoiceEditor/res" - ) - parser.add_argument("--res_name", type=str, default="2jan25.jsonl") - parser.add_argument("--inference_seed", type=int, default=1) - parser.add_argument("--codec_audio_sr", type=int, default=16000) - parser.add_argument("--codec_sr", type=float, default=50) - parser.add_argument("--top_k", type=int, default=0) - parser.add_argument("--top_p", type=float, default=0.9) - parser.add_argument("--temperature", type=float, default=1) - parser.add_argument("--silence_tokens", type=list, default=[]) - parser.add_argument("--kvcache", type=int, default=0) - parser.add_argument("--stop_repetition", type=int, default=3) - parser.add_argument("--sample_batch_size", type=int, default=1) - parser.add_argument( - "--inference_manifest_fns", - type=str, - default="['/home/pyp/BoostedVoiceEditor/manifests/debug.jsonl']", - ) - parser.add_argument("--use_gt_duration", type=int, default=1) - parser.add_argument( - "--save_root", - type=str, - default="/data/scratch/pyp/exp_pyp/BoostedVoiceEditor/gens", - ) - parser.add_argument( - "--encodec_signature", - type=str, - default="/data/scratch/pyp/exp_pyp/audiocraft/encodec/xps/6f79c6a8/checkpoint.th", - ) - parser.add_argument( - "--extra_cutoff", - type=float, - default=5, - help="in rare cases where the model doesn't follow specified target duration (only happened in extrapolation cases), we will terminate generation once the extra duration exceeds this value", - ) - parser.add_argument( - "--duration_margin", - type=float, - default=0.04, - help="used along with extra_cutoff, when extra_cutoff is used (i.e. model doesn't follow specified target_duration), we terminate the generate, and cut the results to target_duration + duration_margin", - ) - # add repeat_prompt and asr_model_name - parser.add_argument( - "--repeat_prompt", - type=int_or_str, - default=0, - help="if 1, will repeat the prompt for each segment", - ) - parser.add_argument( - "--asr_model_name", - type=str, - default="w2v2", - help="the name of the asr model, if not None, will use the asr model to generate the prompt", - ) - - # depth transformer parameters - parser.add_argument("--depth_dec_num_layers", type=int, default=0) - parser.add_argument("--depth_dec_d_model", type=int, default=768) - parser.add_argument("--depth_dec_nhead", type=int, default=12) - parser.add_argument( - "--moshi_depth", - type=int, - default=0, - help="if 1, will use the same parameterization as moshi, i.e. temporal trm output will gets added to every transformed token embedding", - ) - - parser.add_argument( - "--validation_sample_cap", - type=int, - default=None, - help="cap the validation data to this number", - ) - parser.add_argument( - "--no_libri_in_training", - type=int, - default=None, - help="if 1, will not use librilight in training, only use in validation", - ) - parser.add_argument( - "--uniform_weight_start_step", - type=int, - default=1e50, - help="set all codebook weight to be uniform starting from this step", - ) - - return parser diff --git a/inference_gradio.py b/inference_gradio.py deleted file mode 100644 index 7aa6260..0000000 --- a/inference_gradio.py +++ /dev/null @@ -1,328 +0,0 @@ -#!/usr/bin/env python3 -""" -gradio_tts_app.py - -Run: - python gradio_tts_app.py - -Then open the printed local or public URL in your browser. -""" - -import os -import random -import numpy as np -import torch -import torchaudio -import whisper -import gradio as gr -from argparse import Namespace -from huggingface_hub import hf_hub_download - -# --------------------------------------------------------------------- -# The following imports assume your local project structure: -# data/tokenizer.py -# models/voice_star.py -# inference_tts_utils.py -# Adjust if needed. -# --------------------------------------------------------------------- -from data.tokenizer import AudioTokenizer, TextTokenizer -from voicestar import voicestar as voice_star # legacy compatability TODO: change -from inference_tts_utils import inference_one_sample - - -############################################################ -# Utility Functions -############################################################ - - -from voicestar.utils import seed_everything, estimate_duration - - -############################################################ -# Main Inference Function -############################################################ - - -def run_inference( - # User-adjustable parameters (no "# do not change" in snippet) - reference_speech="./demo/5895_34622_000026_000002.wav", - target_text="VoiceStar is a very interesting model, it's duration controllable and can extrapolate", - model_name="VoiceStar_840M_40s", - model_root="./pretrained", - reference_text=None, # optional - target_duration=None, # optional - top_k=10, # can try 10, 20, 30, 40 - temperature=1, - kvcache=1, # if OOM, set to 0 - repeat_prompt=1, # use higher to improve speaker similarity - stop_repetition=3, # snippet says "will not use it" but not "do not change" - seed=1, - output_dir="./generated_tts", - # Non-adjustable parameters (based on snippet instructions) - codec_audio_sr=16000, # do not change - codec_sr=50, # do not change - top_p=1, # do not change - min_p=1, # do not change - silence_tokens=None, # do not change it - multi_trial=None, # do not change it - sample_batch_size=1, # do not change - cut_off_sec=100, # do not adjust -): - """ - Inference script for VoiceStar TTS. - """ - # 1. Set seed - seed_everything(seed) - - # 2. Load model checkpoint - torch.serialization.add_safe_globals([Namespace]) - device = ( - "cuda" - if torch.cuda.is_available() - else "mps" if torch.backends.mps.is_available() else "cpu" - ) # MPS support - ckpt_fn = hf_hub_download(repo_id="pyp1/VoiceStar", filename=f"{model_name}.pth") - - bundle = torch.load(ckpt_fn, map_location=device, weights_only=True) - args = bundle["args"] - phn2num = bundle["phn2num"] - - model = voice_star.VoiceStarModel(args) - model.load_state_dict(bundle["model"]) - model.to(device) - model.eval() - - # 3. If reference_text not provided, transcribe reference speech with Whisper - if reference_text is None: - print( - "[Info] No reference_text provided. Transcribing reference_speech with Whisper (large-v3-turbo)." - ) - wh_model = whisper.load_model("large-v3-turbo") - result = wh_model.transcribe(reference_speech) - prefix_transcript = result["text"] - print(f"[Info] Whisper transcribed text: {prefix_transcript}") - else: - prefix_transcript = reference_text - - # 4. If target_duration not provided, estimate from reference speech + target_text - if target_duration is None: - target_generation_length = estimate_duration(reference_speech, target_text) - print( - f"[Info] target_duration not provided, estimated as {target_generation_length:.2f}s. Provide --target_duration if needed." - ) - else: - target_generation_length = float(target_duration) - - # 5. Prepare signature from snippet - if args.n_codebooks == 4: - signature = "./pretrained/encodec_6f79c6a8.th" - elif args.n_codebooks == 8: - signature = "./pretrained/encodec_8cb1024_giga.th" - else: - signature = "./pretrained/encodec_6f79c6a8.th" - - if silence_tokens is None: - silence_tokens = [] - - if multi_trial is None: - multi_trial = [] - - delay_pattern_increment = args.n_codebooks + 1 # from snippet - - info = torchaudio.info(reference_speech) - prompt_end_frame = int(cut_off_sec * info.sample_rate) - - # 6. Tokenizers - audio_tokenizer = AudioTokenizer(signature=signature) - text_tokenizer = TextTokenizer(backend="espeak") - - # 7. decode_config - decode_config = { - "top_k": top_k, - "top_p": top_p, - "min_p": min_p, - "temperature": temperature, - "stop_repetition": stop_repetition, - "kvcache": kvcache, - "codec_audio_sr": codec_audio_sr, - "codec_sr": codec_sr, - "silence_tokens": silence_tokens, - "sample_batch_size": sample_batch_size, - } - - # 8. Run inference - print("[Info] Running TTS inference...") - concated_audio, gen_audio = inference_one_sample( - model, - args, - phn2num, - text_tokenizer, - audio_tokenizer, - reference_speech, - target_text, - device, - decode_config, - prompt_end_frame=prompt_end_frame, - target_generation_length=target_generation_length, - delay_pattern_increment=delay_pattern_increment, - prefix_transcript=prefix_transcript, - multi_trial=multi_trial, - repeat_prompt=repeat_prompt, - ) - - # The model returns a list of waveforms, pick the first - concated_audio, gen_audio = concated_audio[0].cpu(), gen_audio[0].cpu() - - # 9. Save generated audio - os.makedirs(output_dir, exist_ok=True) - out_filename = "generated.wav" - out_path = os.path.join(output_dir, out_filename) - torchaudio.save(out_path, gen_audio, codec_audio_sr) - - print(f"[Success] Generated audio saved to {out_path}") - return out_path # Return the path for Gradio to load - - -############################ -# Transcription function -############################ - - -def transcribe_audio(reference_speech): - """ - Transcribe uploaded reference audio with Whisper, return text. - If no file, return empty string. - """ - if reference_speech is None: - return "" - audio_path = reference_speech # Because type="filepath" - - if not os.path.exists(audio_path): - return "File not found." - - print("[Info] Transcribing with Whisper...") - model = whisper.load_model("medium") # or "large-v2" etc. - result = model.transcribe(audio_path) - return result["text"] - - -############################ -# Gradio UI -############################ - - -def main(): - with gr.Blocks() as demo: - gr.Markdown("## VoiceStar TTS with Editable Reference Text") - - with gr.Row(): - reference_speech_input = gr.Audio( - label="Reference Speech", type="filepath", elem_id="ref_speech" - ) - transcribe_button = gr.Button("Transcribe") - - # The transcribed text appears here and can be edited - reference_text_box = gr.Textbox( - label="Reference Text (Editable)", - placeholder="Click 'Transcribe' to auto-fill from reference speech...", - lines=2, - ) - - target_text_box = gr.Textbox( - label="Target Text", - value="VoiceStar is a very interesting model, it's duration controllable and can extrapolate to unseen duration.", - lines=3, - ) - - model_name_box = gr.Textbox(label="Model Name", value="VoiceStar_840M_40s") - - model_root_box = gr.Textbox( - label="Model Root Directory", - value="/data1/scratch/pyp/BoostedVoiceEditor/runs", - ) - - reference_duration_box = gr.Textbox( - label="Target Duration (Optional)", - placeholder="Leave empty for auto-estimate.", - ) - - top_k_box = gr.Number(label="top_k", value=10) - temperature_box = gr.Number(label="temperature", value=1.0) - kvcache_box = gr.Number(label="kvcache (1 or 0)", value=1) - repeat_prompt_box = gr.Number(label="repeat_prompt", value=1) - stop_repetition_box = gr.Number(label="stop_repetition", value=3) - seed_box = gr.Number(label="Random Seed", value=1) - output_dir_box = gr.Textbox(label="Output Directory", value="./generated_tts") - - generate_button = gr.Button("Generate TTS") - output_audio = gr.Audio(label="Generated Audio", type="filepath") - - # 1) When user clicks "Transcribe", we call `transcribe_audio` - transcribe_button.click( - fn=transcribe_audio, - inputs=[reference_speech_input], - outputs=[reference_text_box], - ) - - # 2) The actual TTS generation function. - def gradio_inference( - reference_speech, - reference_text, - target_text, - model_name, - model_root, - target_duration, - top_k, - temperature, - kvcache, - repeat_prompt, - stop_repetition, - seed, - output_dir, - ): - # Convert any empty strings to None for optional fields - dur = float(target_duration) if target_duration else None - - out_path = run_inference( - reference_speech=reference_speech, - reference_text=reference_text if reference_text else None, - target_text=target_text, - model_name=model_name, - model_root=model_root, - target_duration=dur, - top_k=int(top_k), - temperature=float(temperature), - kvcache=int(kvcache), - repeat_prompt=int(repeat_prompt), - stop_repetition=int(stop_repetition), - seed=int(seed), - output_dir=output_dir, - ) - return out_path - - # 3) Link the "Generate TTS" button - generate_button.click( - fn=gradio_inference, - inputs=[ - reference_speech_input, - reference_text_box, - target_text_box, - model_name_box, - model_root_box, - reference_duration_box, - top_k_box, - temperature_box, - kvcache_box, - repeat_prompt_box, - stop_repetition_box, - seed_box, - output_dir_box, - ], - outputs=[output_audio], - ) - - demo.launch(server_name="0.0.0.0", server_port=7860, debug=True) - - -if __name__ == "__main__": - main() diff --git a/inference_tts_utils.py b/inference_tts_utils.py deleted file mode 100644 index 8c3e305..0000000 --- a/inference_tts_utils.py +++ /dev/null @@ -1,250 +0,0 @@ -import argparse, pickle -import logging -import os, random -import numpy as np -import torch -import torchaudio - -from data.tokenizer import AudioTokenizer, TextTokenizer, tokenize_audio, tokenize_text -import argparse, time, tqdm - - -# this script only works for the musicgen architecture -def get_args(): - parser = argparse.ArgumentParser( - formatter_class=argparse.ArgumentDefaultsHelpFormatter - ) - parser.add_argument("--manifest_fn", type=str, default="path/to/eval_metadata_file") - parser.add_argument("--audio_root", type=str, default="path/to/audio_folder") - parser.add_argument("--exp_dir", type=str, default="path/to/model_folder") - parser.add_argument("--seed", type=int, default=1) - parser.add_argument( - "--codec_audio_sr", - type=int, - default=16000, - help="the sample rate of audio that the codec is trained for", - ) - parser.add_argument( - "--codec_sr", type=int, default=50, help="the sample rate of the codec codes" - ) - parser.add_argument("--top_k", type=int, default=0, help="sampling param") - parser.add_argument("--top_p", type=float, default=0.8, help="sampling param") - parser.add_argument("--temperature", type=float, default=1.0, help="sampling param") - parser.add_argument("--output_dir", type=str, default=None) - parser.add_argument("--device", type=str, default="cuda") - parser.add_argument( - "--signature", type=str, default=None, help="path to the encodec model" - ) - parser.add_argument("--crop_concat", type=int, default=0) - parser.add_argument( - "--stop_repetition", - type=int, - default=-1, - help="used for inference, when the number of consecutive repetition of a token is bigger than this, stop it", - ) - parser.add_argument( - "--kvcache", - type=int, - default=1, - help="if true, use kv cache, which is 4-8x faster than without", - ) - parser.add_argument( - "--sample_batch_size", - type=int, - default=1, - help="batch size for sampling, NOTE that it's not running inference for several samples, but duplicate one input sample batch_size times, and during inference, we only return the shortest generation", - ) - parser.add_argument( - "--silence_tokens", - type=str, - default="[1388,1898,131]", - help="note that if you are not using the pretrained encodec 6f79c6a8, make sure you specified it yourself, rather than using the default", - ) - return parser.parse_args() - - -@torch.no_grad() -def inference_one_sample( - model, - model_args, - phn2num, - text_tokenizer, - audio_tokenizer, - audio_fn, - target_text, - device, - decode_config, - prompt_end_frame, - target_generation_length, - delay_pattern_increment, - prefix_transcript=None, - quiet=False, - repeat_prompt=0, - multi_trial=[], -): - # seq_len_thres = 500 # 10s, 26% of the data in seed tts - # encode audio - encoded_frames = tokenize_audio( - audio_tokenizer, audio_fn, offset=0, num_frames=prompt_end_frame - ) - # if sequence length is shorter than seq_len_thres, repeat the audio - # if encoded_frames.shape[2] < seq_len_thres: - # encoded_frames = torch.cat([encoded_frames, encoded_frames, encoded_frames], dim=2) - # doubled = True - single_encoded_frames = encoded_frames - - if isinstance(repeat_prompt, int) and repeat_prompt > 0: - cur_repeat_prompt = repeat_prompt - while cur_repeat_prompt > 0: - encoded_frames = torch.cat([encoded_frames, single_encoded_frames], dim=2) - cur_repeat_prompt -= 1 - elif isinstance(repeat_prompt, str) and repeat_prompt.lower() == "max": - repeat_prompt = 0 - while ( - encoded_frames.shape[2] - + decode_config["codec_sr"] * target_generation_length - + delay_pattern_increment - + single_encoded_frames.shape[2] - < model_args.audio_max_length * decode_config["codec_sr"] - ): - encoded_frames = torch.cat([encoded_frames, single_encoded_frames], dim=2) - repeat_prompt += 1 - if getattr(model_args, "y_sep_token", None) != None: - encoded_frames = torch.cat( - [ - encoded_frames, - torch.LongTensor([model_args.y_sep_token] * model_args.n_codebooks) - .unsqueeze(0) - .unsqueeze(2) - .to(encoded_frames.device), - ], - dim=2, - ) - # print(encoded_frames.shape) - original_audio = encoded_frames.transpose(2, 1) # [1,T,K] - assert ( - original_audio.ndim == 3 - and original_audio.shape[0] == 1 - and original_audio.shape[2] == model_args.n_codebooks - ), original_audio.shape - - # phonemize - if isinstance(target_text, list): - text_tokens = [phn2num[phn] for phn in target_text if phn in phn2num] - else: - text_tokens = [ - phn2num[phn] - for phn in tokenize_text(text_tokenizer, text=target_text.strip()) - if phn in phn2num - ] - if getattr(model_args, "x_sep_token", None) != None: - assert ( - prefix_transcript != None - ), "prefix_transcript must be provided if x_sep_token is not None" - if prefix_transcript is not None: - if isinstance(prefix_transcript, list): - prefix_tokens = [ - phn2num[phn] for phn in prefix_transcript if phn in phn2num - ] - else: - prefix_tokens = [ - phn2num[phn] - for phn in tokenize_text(text_tokenizer, text=prefix_transcript.strip()) - if phn in phn2num - ] - # if doubled: - # prefix_tokens = prefix_tokens + prefix_tokens + prefix_tokens - single_prefix_tokens = prefix_tokens - while repeat_prompt > 0: - prefix_tokens = prefix_tokens + single_prefix_tokens - repeat_prompt -= 1 - if getattr(model_args, "x_sep_token", None) != None: - text_tokens = ( - prefix_tokens + [getattr(model_args, "x_sep_token", None)] + text_tokens - ) - else: - text_tokens = prefix_tokens + text_tokens - if getattr(model_args, "add_eos_to_text", 0) != 0: - text_tokens.append(model_args.add_eos_to_text) - if getattr(model_args, "add_bos_to_text", 0) != 0: - text_tokens = [model_args.add_bos_to_text] + text_tokens - text_tokens = torch.LongTensor(text_tokens).unsqueeze(0) - text_tokens_lens = torch.LongTensor([text_tokens.shape[-1]]) - - if not quiet: - logging.info( - f"original audio length: {original_audio.shape[1]} codec frames, which is {original_audio.shape[1]/decode_config['codec_sr']:.2f} sec." - ) - - if getattr(model_args, "parallel_pattern", 0) != 0: - tgt_y_lens = torch.LongTensor( - [ - int( - original_audio.shape[1] - + decode_config["codec_sr"] * target_generation_length - + 2 - ) - ] - ) # parallel pattern, therefore only add the empty_token (i.e. the sos token) and eos (i.e. 2 more tokens). Note that the delayed pattern between, both sos and eos is counted (sos is counted in the n_codebooks, eos is counted in the 1) - else: - tgt_y_lens = torch.LongTensor( - [ - int( - original_audio.shape[1] - + decode_config["codec_sr"] * target_generation_length - + delay_pattern_increment - ) - ] - ) # delay pattern increment has accounted for the added eos - - # forward - assert decode_config["sample_batch_size"] <= 1 - stime = time.time() - assert multi_trial == [] - if not quiet: - logging.info(f"running inference with batch size 1") - concat_frames, gen_frames = model.inference_tts( - text_tokens.to(device), - text_tokens_lens.to(device), - original_audio[..., : model_args.n_codebooks].to(device), # [1,T,8] - tgt_y_lens=tgt_y_lens.to(device), - top_k=decode_config["top_k"], - top_p=decode_config["top_p"], - min_p=decode_config["min_p"], - temperature=decode_config["temperature"], - stop_repetition=decode_config["stop_repetition"], - kvcache=decode_config["kvcache"], - silence_tokens=( - eval(decode_config["silence_tokens"]) - if type(decode_config["silence_tokens"]) == str - else decode_config["silence_tokens"] - ), - ) # output is [1,K,T] - if not quiet: - logging.info(f"inference on one sample take: {time.time() - stime:.4f} sec.") - - logging.info( - f"generated encoded_frames.shape: {gen_frames.shape}, which is {gen_frames.shape[-1]/decode_config['codec_sr']} sec." - ) - - # for timestamp, codes in enumerate(gen_frames[0].transpose(1,0)): - # logging.info(f"{timestamp}: {codes.tolist()}") - # decode (both original and generated) - # concat_sample = audio_tokenizer.decode( - # [(concat_frames, None)] # [1,T,8] -> [1,8,T] - # ) - if getattr(model_args, "y_sep_token", None) != None: - concat_frames = torch.cat( - [ - concat_frames[:, :, : original_audio.shape[1] - 1], - concat_frames[:, :, original_audio.shape[1] :], - ], - dim=2, - ) - concat_sample = audio_tokenizer.decode(concat_frames) # [1,8,T] - gen_sample = audio_tokenizer.decode(gen_frames) - # Empty cuda cache between runs - if torch.cuda.is_available(): - torch.cuda.empty_cache() - # return - return concat_sample, gen_sample From 8af4a8fd1cce832de387f4721e2c1997b547e398 Mon Sep 17 00:00:00 2001 From: mrfakename Date: Mon, 7 Apr 2025 19:07:32 -0700 Subject: [PATCH 7/7] Add note about device --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9e27e08..234222a 100644 --- a/README.md +++ b/README.md @@ -31,6 +31,8 @@ voicestar --reference-speech "./demo/5895_34622_000026_000002.wav" --target-text Please refer to the CLI and Python API documentation below for more advanced usage. +_Note: Both CUDA, CPU, and MPS (Apple Silicon) are supported._ + ## Training Please refer to the [training docs](docs/training.md) for more information.