Added OG Repo need to make some more modifications

This commit is contained in:
arensc
2024-03-08 23:40:11 -05:00
parent 772832eed6
commit 7137a25cf7
303 changed files with 168961 additions and 0 deletions
+1
View File
@@ -0,0 +1 @@
__pycache__
@@ -0,0 +1,486 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"gpuType": "T4",
"authorship_tag": "ABX9TyM1x2mx2VnkYNFVlD+DFzmy",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/yl4579/StyleTTS2/blob/main/Colab/StyleTTS2_Demo_LJSpeech.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"### Install packages and download models"
],
"metadata": {
"id": "nm653VK4CG9F"
}
},
{
"cell_type": "code",
"source": [
"%%shell\n",
"git clone https://github.com/yl4579/StyleTTS2.git\n",
"cd StyleTTS2\n",
"pip install SoundFile torchaudio munch torch pydub pyyaml librosa nltk matplotlib accelerate transformers phonemizer einops einops-exts tqdm typing-extensions git+https://github.com/resemble-ai/monotonic_align.git\n",
"sudo apt-get install espeak-ng\n",
"git-lfs clone https://huggingface.co/yl4579/StyleTTS2-LJSpeech\n",
"mv StyleTTS2-LJSpeech/Models ."
],
"metadata": {
"id": "gciBKMqCCLvT"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Load models"
],
"metadata": {
"id": "OAA8lx-XCQnM"
}
},
{
"cell_type": "code",
"source": [
"%cd StyleTTS2\n",
"\n",
"import torch\n",
"torch.manual_seed(0)\n",
"torch.backends.cudnn.benchmark = False\n",
"torch.backends.cudnn.deterministic = True\n",
"\n",
"import random\n",
"random.seed(0)\n",
"\n",
"import numpy as np\n",
"np.random.seed(0)\n",
"\n",
"import nltk\n",
"nltk.download('punkt')\n",
"\n",
"# load packages\n",
"import time\n",
"import random\n",
"import yaml\n",
"from munch import Munch\n",
"import numpy as np\n",
"import torch\n",
"from torch import nn\n",
"import torch.nn.functional as F\n",
"import torchaudio\n",
"import librosa\n",
"from nltk.tokenize import word_tokenize\n",
"\n",
"from models import *\n",
"from utils import *\n",
"from text_utils import TextCleaner\n",
"textclenaer = TextCleaner()\n",
"\n",
"%matplotlib inline\n",
"\n",
"device = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
"\n",
"to_mel = torchaudio.transforms.MelSpectrogram(\n",
" n_mels=80, n_fft=2048, win_length=1200, hop_length=300)\n",
"mean, std = -4, 4\n",
"\n",
"def length_to_mask(lengths):\n",
" mask = torch.arange(lengths.max()).unsqueeze(0).expand(lengths.shape[0], -1).type_as(lengths)\n",
" mask = torch.gt(mask+1, lengths.unsqueeze(1))\n",
" return mask\n",
"\n",
"def preprocess(wave):\n",
" wave_tensor = torch.from_numpy(wave).float()\n",
" mel_tensor = to_mel(wave_tensor)\n",
" mel_tensor = (torch.log(1e-5 + mel_tensor.unsqueeze(0)) - mean) / std\n",
" return mel_tensor\n",
"\n",
"def compute_style(ref_dicts):\n",
" reference_embeddings = {}\n",
" for key, path in ref_dicts.items():\n",
" wave, sr = librosa.load(path, sr=24000)\n",
" audio, index = librosa.effects.trim(wave, top_db=30)\n",
" if sr != 24000:\n",
" audio = librosa.resample(audio, sr, 24000)\n",
" mel_tensor = preprocess(audio).to(device)\n",
"\n",
" with torch.no_grad():\n",
" ref = model.style_encoder(mel_tensor.unsqueeze(1))\n",
" reference_embeddings[key] = (ref.squeeze(1), audio)\n",
"\n",
" return reference_embeddings\n",
"\n",
"# load phonemizer\n",
"import phonemizer\n",
"global_phonemizer = phonemizer.backend.EspeakBackend(language='en-us', preserve_punctuation=True, with_stress=True, words_mismatch='ignore')\n",
"\n",
"config = yaml.safe_load(open(\"Models/LJSpeech/config.yml\"))\n",
"\n",
"# load pretrained ASR model\n",
"ASR_config = config.get('ASR_config', False)\n",
"ASR_path = config.get('ASR_path', False)\n",
"text_aligner = load_ASR_models(ASR_path, ASR_config)\n",
"\n",
"# load pretrained F0 model\n",
"F0_path = config.get('F0_path', False)\n",
"pitch_extractor = load_F0_models(F0_path)\n",
"\n",
"# load BERT model\n",
"from Utils.PLBERT.util import load_plbert\n",
"BERT_path = config.get('PLBERT_dir', False)\n",
"plbert = load_plbert(BERT_path)\n",
"\n",
"model = build_model(recursive_munch(config['model_params']), text_aligner, pitch_extractor, plbert)\n",
"_ = [model[key].eval() for key in model]\n",
"_ = [model[key].to(device) for key in model]\n",
"\n",
"params_whole = torch.load(\"Models/LJSpeech/epoch_2nd_00100.pth\", map_location='cpu')\n",
"params = params_whole['net']\n",
"\n",
"for key in model:\n",
" if key in params:\n",
" print('%s loaded' % key)\n",
" try:\n",
" model[key].load_state_dict(params[key])\n",
" except:\n",
" from collections import OrderedDict\n",
" state_dict = params[key]\n",
" new_state_dict = OrderedDict()\n",
" for k, v in state_dict.items():\n",
" name = k[7:] # remove `module.`\n",
" new_state_dict[name] = v\n",
" # load params\n",
" model[key].load_state_dict(new_state_dict, strict=False)\n",
"# except:\n",
"# _load(params[key], model[key])\n",
"_ = [model[key].eval() for key in model]\n",
"\n",
"from Modules.diffusion.sampler import DiffusionSampler, ADPM2Sampler, KarrasSchedule\n",
"\n",
"sampler = DiffusionSampler(\n",
" model.diffusion.diffusion,\n",
" sampler=ADPM2Sampler(),\n",
" sigma_schedule=KarrasSchedule(sigma_min=0.0001, sigma_max=3.0, rho=9.0), # empirical parameters\n",
" clamp=False\n",
")\n",
"\n",
"def inference(text, noise, diffusion_steps=5, embedding_scale=1):\n",
" text = text.strip()\n",
" text = text.replace('\"', '')\n",
" ps = global_phonemizer.phonemize([text])\n",
" ps = word_tokenize(ps[0])\n",
" ps = ' '.join(ps)\n",
"\n",
" tokens = textclenaer(ps)\n",
" tokens.insert(0, 0)\n",
" tokens = torch.LongTensor(tokens).to(device).unsqueeze(0)\n",
"\n",
" with torch.no_grad():\n",
" input_lengths = torch.LongTensor([tokens.shape[-1]]).to(tokens.device)\n",
" text_mask = length_to_mask(input_lengths).to(tokens.device)\n",
"\n",
" t_en = model.text_encoder(tokens, input_lengths, text_mask)\n",
" bert_dur = model.bert(tokens, attention_mask=(~text_mask).int())\n",
" d_en = model.bert_encoder(bert_dur).transpose(-1, -2)\n",
"\n",
" s_pred = sampler(noise,\n",
" embedding=bert_dur[0].unsqueeze(0), num_steps=diffusion_steps,\n",
" embedding_scale=embedding_scale).squeeze(0)\n",
"\n",
" s = s_pred[:, 128:]\n",
" ref = s_pred[:, :128]\n",
"\n",
" d = model.predictor.text_encoder(d_en, s, input_lengths, text_mask)\n",
"\n",
" x, _ = model.predictor.lstm(d)\n",
" duration = model.predictor.duration_proj(x)\n",
" duration = torch.sigmoid(duration).sum(axis=-1)\n",
" pred_dur = torch.round(duration.squeeze()).clamp(min=1)\n",
"\n",
" pred_dur[-1] += 5\n",
"\n",
" pred_aln_trg = torch.zeros(input_lengths, int(pred_dur.sum().data))\n",
" c_frame = 0\n",
" for i in range(pred_aln_trg.size(0)):\n",
" pred_aln_trg[i, c_frame:c_frame + int(pred_dur[i].data)] = 1\n",
" c_frame += int(pred_dur[i].data)\n",
"\n",
" # encode prosody\n",
" en = (d.transpose(-1, -2) @ pred_aln_trg.unsqueeze(0).to(device))\n",
" F0_pred, N_pred = model.predictor.F0Ntrain(en, s)\n",
" out = model.decoder((t_en @ pred_aln_trg.unsqueeze(0).to(device)),\n",
" F0_pred, N_pred, ref.squeeze().unsqueeze(0))\n",
"\n",
" return out.squeeze().cpu().numpy()\n",
"\n",
"def LFinference(text, s_prev, noise, alpha=0.7, diffusion_steps=5, embedding_scale=1):\n",
" text = text.strip()\n",
" text = text.replace('\"', '')\n",
" ps = global_phonemizer.phonemize([text])\n",
" ps = word_tokenize(ps[0])\n",
" ps = ' '.join(ps)\n",
"\n",
" tokens = textclenaer(ps)\n",
" tokens.insert(0, 0)\n",
" tokens = torch.LongTensor(tokens).to(device).unsqueeze(0)\n",
"\n",
" with torch.no_grad():\n",
" input_lengths = torch.LongTensor([tokens.shape[-1]]).to(tokens.device)\n",
" text_mask = length_to_mask(input_lengths).to(tokens.device)\n",
"\n",
" t_en = model.text_encoder(tokens, input_lengths, text_mask)\n",
" bert_dur = model.bert(tokens, attention_mask=(~text_mask).int())\n",
" d_en = model.bert_encoder(bert_dur).transpose(-1, -2)\n",
"\n",
" s_pred = sampler(noise,\n",
" embedding=bert_dur[0].unsqueeze(0), num_steps=diffusion_steps,\n",
" embedding_scale=embedding_scale).squeeze(0)\n",
"\n",
" if s_prev is not None:\n",
" # convex combination of previous and current style\n",
" s_pred = alpha * s_prev + (1 - alpha) * s_pred\n",
"\n",
" s = s_pred[:, 128:]\n",
" ref = s_pred[:, :128]\n",
"\n",
" d = model.predictor.text_encoder(d_en, s, input_lengths, text_mask)\n",
"\n",
" x, _ = model.predictor.lstm(d)\n",
" duration = model.predictor.duration_proj(x)\n",
" duration = torch.sigmoid(duration).sum(axis=-1)\n",
" pred_dur = torch.round(duration.squeeze()).clamp(min=1)\n",
"\n",
" pred_aln_trg = torch.zeros(input_lengths, int(pred_dur.sum().data))\n",
" c_frame = 0\n",
" for i in range(pred_aln_trg.size(0)):\n",
" pred_aln_trg[i, c_frame:c_frame + int(pred_dur[i].data)] = 1\n",
" c_frame += int(pred_dur[i].data)\n",
"\n",
" # encode prosody\n",
" en = (d.transpose(-1, -2) @ pred_aln_trg.unsqueeze(0).to(device))\n",
" F0_pred, N_pred = model.predictor.F0Ntrain(en, s)\n",
" out = model.decoder((t_en @ pred_aln_trg.unsqueeze(0).to(device)),\n",
" F0_pred, N_pred, ref.squeeze().unsqueeze(0))\n",
"\n",
" return out.squeeze().cpu().numpy(), s_pred"
],
"metadata": {
"id": "m0XRpbxSCSix"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Synthesize speech"
],
"metadata": {
"id": "vuCbS0gdArgJ"
}
},
{
"cell_type": "code",
"source": [
"# @title Input Text { display-mode: \"form\" }\n",
"# synthesize a text\n",
"text = \"StyleTTS 2 is a text-to-speech model that leverages style diffusion and adversarial training with large speech language models to achieve human-level text-to-speech synthesis.\" # @param {type:\"string\"}\n"
],
"metadata": {
"id": "7Ud1Y-kbBPTw"
},
"execution_count": 3,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"#### Basic synthesis (5 diffusion steps)"
],
"metadata": {
"id": "TM2NjuM7B6sz"
}
},
{
"cell_type": "code",
"source": [
"start = time.time()\n",
"noise = torch.randn(1,1,256).to(device)\n",
"wav = inference(text, noise, diffusion_steps=5, embedding_scale=1)\n",
"rtf = (time.time() - start) / (len(wav) / 24000)\n",
"print(f\"RTF = {rtf:5f}\")\n",
"import IPython.display as ipd\n",
"display(ipd.Audio(wav, rate=24000))"
],
"metadata": {
"id": "KILqC-V-Ay5e"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"#### With higher diffusion steps (more diverse)\n",
"Since the sampler is ancestral, the higher the stpes, the more diverse the samples are, with the cost of slower synthesis speed."
],
"metadata": {
"id": "oZk9o-EzCBVx"
}
},
{
"cell_type": "code",
"source": [
"start = time.time()\n",
"noise = torch.randn(1,1,256).to(device)\n",
"wav = inference(text, noise, diffusion_steps=10, embedding_scale=1)\n",
"rtf = (time.time() - start) / (len(wav) / 24000)\n",
"print(f\"RTF = {rtf:5f}\")\n",
"import IPython.display as ipd\n",
"display(ipd.Audio(wav, rate=24000))"
],
"metadata": {
"id": "9_OHtzMbB9gL"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Speech expressiveness\n",
"The following section recreates the samples shown in [Section 6](https://styletts2.github.io/#emo) of the demo page."
],
"metadata": {
"id": "NyDACd-0CaqL"
}
},
{
"cell_type": "markdown",
"source": [
"#### With embedding_scale=1\n",
"This is the classifier-free guidance scale. The higher the scale, the more conditional the style is to the input text and hence more emotional."
],
"metadata": {
"id": "cRkS5VWxCck4"
}
},
{
"cell_type": "code",
"source": [
"texts = {}\n",
"texts['Happy'] = \"We are happy to invite you to join us on a journey to the past, where we will visit the most amazing monuments ever built by human hands.\"\n",
"texts['Sad'] = \"I am sorry to say that we have suffered a severe setback in our efforts to restore prosperity and confidence.\"\n",
"texts['Angry'] = \"The field of astronomy is a joke! Its theories are based on flawed observations and biased interpretations!\"\n",
"texts['Surprised'] = \"I can't believe it! You mean to tell me that you have discovered a new species of bacteria in this pond?\"\n",
"\n",
"for k,v in texts.items():\n",
" noise = torch.randn(1,1,256).to(device)\n",
" wav = inference(v, noise, diffusion_steps=10, embedding_scale=1)\n",
" print(k + \": \")\n",
" display(ipd.Audio(wav, rate=24000, normalize=False))"
],
"metadata": {
"id": "H5g5RO-mCbZB"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"#### With embedding_scale=2"
],
"metadata": {
"id": "f4S8TXSpCgpA"
}
},
{
"cell_type": "code",
"source": [
"texts = {}\n",
"texts['Happy'] = \"We are happy to invite you to join us on a journey to the past, where we will visit the most amazing monuments ever built by human hands.\"\n",
"texts['Sad'] = \"I am sorry to say that we have suffered a severe setback in our efforts to restore prosperity and confidence.\"\n",
"texts['Angry'] = \"The field of astronomy is a joke! Its theories are based on flawed observations and biased interpretations!\"\n",
"texts['Surprised'] = \"I can't believe it! You mean to tell me that you have discovered a new species of bacteria in this pond?\"\n",
"\n",
"for k,v in texts.items():\n",
" noise = torch.randn(1,1,256).to(device)\n",
" wav = inference(v, noise, diffusion_steps=10, embedding_scale=2) # embedding_scale=2 for more pronounced emotion\n",
" print(k + \": \")\n",
" display(ipd.Audio(wav, rate=24000, normalize=False))"
],
"metadata": {
"id": "xHHIdeNrCezC"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Long-form generation\n",
"This section includes basic implementation of Algorithm 1 in the paper for consistent longform audio generation. The example passage is taken from [Section 5](https://styletts2.github.io/#long) of the demo page."
],
"metadata": {
"id": "nAh7Tov4CkuH"
}
},
{
"cell_type": "code",
"source": [
"passage = '''If the supply of fruit is greater than the family needs, it may be made a source of income by sending the fresh fruit to the market if there is one near enough, or by preserving, canning, and making jelly for sale. To make such an enterprise a success the fruit and work must be first class. There is magic in the word \"Homemade,\" when the product appeals to the eye and the palate; but many careless and incompetent people have found to their sorrow that this word has not magic enough to float inferior goods on the market. As a rule large canning and preserving establishments are clean and have the best appliances, and they employ chemists and skilled labor. The home product must be very good to compete with the attractive goods that are sent out from such establishments. Yet for first-class homemade products there is a market in all large cities. All first-class grocers have customers who purchase such goods.''' # @param {type:\"string\"}"
],
"metadata": {
"cellView": "form",
"id": "IJwUbgvACoDu"
},
"execution_count": 8,
"outputs": []
},
{
"cell_type": "code",
"source": [
"sentences = passage.split('.') # simple split by comma\n",
"wavs = []\n",
"s_prev = None\n",
"for text in sentences:\n",
" if text.strip() == \"\": continue\n",
" text += '.' # add it back\n",
" noise = torch.randn(1,1,256).to(device)\n",
" wav, s_prev = LFinference(text, s_prev, noise, alpha=0.7, diffusion_steps=10, embedding_scale=1.5)\n",
" wavs.append(wav)\n",
"display(ipd.Audio(np.concatenate(wavs), rate=24000, normalize=False))"
],
"metadata": {
"id": "nP-7i2QAC0JT"
},
"execution_count": null,
"outputs": []
}
]
}
File diff suppressed because it is too large Load Diff
@@ -0,0 +1,480 @@
{
"nbformat": 4,
"nbformat_minor": 0,
"metadata": {
"colab": {
"provenance": [],
"gpuType": "T4",
"authorship_tag": "ABX9TyNiDU9ykIeYxO86Lmuid+ph",
"include_colab_link": true
},
"kernelspec": {
"name": "python3",
"display_name": "Python 3"
},
"language_info": {
"name": "python"
},
"accelerator": "GPU"
},
"cells": [
{
"cell_type": "markdown",
"metadata": {
"id": "view-in-github",
"colab_type": "text"
},
"source": [
"<a href=\"https://colab.research.google.com/github/yl4579/StyleTTS2/blob/main/Colab/StyleTTS2_Finetune_Demo.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
]
},
{
"cell_type": "markdown",
"source": [
"### Install packages and download models"
],
"metadata": {
"id": "yLqBa4uYPrqE"
}
},
{
"cell_type": "code",
"source": [
"%%shell\n",
"git clone https://github.com/yl4579/StyleTTS2.git\n",
"cd StyleTTS2\n",
"pip install SoundFile torchaudio munch torch pydub pyyaml librosa nltk matplotlib accelerate transformers phonemizer einops einops-exts tqdm typing-extensions git+https://github.com/resemble-ai/monotonic_align.git\n",
"sudo apt-get install espeak-ng\n",
"git-lfs clone https://huggingface.co/yl4579/StyleTTS2-LibriTTS\n",
"mv StyleTTS2-LibriTTS/Models ."
],
"metadata": {
"id": "H72WF06ZPrTF"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Download dataset (LJSpeech, 200 samples, ~15 minutes of data)\n",
"\n",
"You can definitely do it with fewer samples. This is just a proof of concept with 200 smaples."
],
"metadata": {
"id": "G398sL8wPzTB"
}
},
{
"cell_type": "code",
"source": [
"%cd StyleTTS2\n",
"!rm -rf Data"
],
"metadata": {
"id": "kJuQUBrEPy5C"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"!gdown --id 1vqz26D3yn7OXS2vbfYxfSnpLS6m6tOFP\n",
"!unzip Data.zip"
],
"metadata": {
"id": "mDXW8ZZePuSb"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Change the finetuning config\n",
"\n",
"Depending on the GPU you got, you may want to change the bacth size, max audio length, epiochs and so on."
],
"metadata": {
"id": "_AlBQREWU8ud"
}
},
{
"cell_type": "code",
"source": [
"config_path = \"Configs/config_ft.yml\"\n",
"\n",
"import yaml\n",
"config = yaml.safe_load(open(config_path))"
],
"metadata": {
"id": "7uEITi0hU4I2"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"config['data_params']['root_path'] = \"Data/wavs\"\n",
"\n",
"config['batch_size'] = 2 # not enough RAM\n",
"config['max_len'] = 100 # not enough RAM\n",
"config['loss_params']['joint_epoch'] = 110 # we do not do SLM adversarial training due to not enough RAM\n",
"\n",
"with open(config_path, 'w') as outfile:\n",
" yaml.dump(config, outfile, default_flow_style=True)"
],
"metadata": {
"id": "TPTRgOKSVT4K"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Start finetuning\n"
],
"metadata": {
"id": "uUuB_19NWj2Y"
}
},
{
"cell_type": "code",
"source": [
"!python train_finetune.py --config_path ./Configs/config_ft.yml"
],
"metadata": {
"id": "HZVAD5GKWm-O"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Test the model quality\n",
"\n",
"Note that this mainly serves as a proof of concept due to RAM limitation of free Colab instances. A lot of settings are suboptimal. In the future when DDP works for train_second.py, we will also add mixed precision finetuning to save time and RAM. You can also add SLM adversarial training run if you have paid Colab services (such as A100 with 40G of RAM)."
],
"metadata": {
"id": "I0_7wsGkXGfc"
}
},
{
"cell_type": "code",
"source": [
"import nltk\n",
"nltk.download('punkt')"
],
"metadata": {
"id": "OPLphjbncE7p"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"import torch\n",
"torch.manual_seed(0)\n",
"torch.backends.cudnn.benchmark = False\n",
"torch.backends.cudnn.deterministic = True\n",
"\n",
"import random\n",
"random.seed(0)\n",
"\n",
"import numpy as np\n",
"np.random.seed(0)\n",
"\n",
"# load packages\n",
"import time\n",
"import random\n",
"import yaml\n",
"from munch import Munch\n",
"import numpy as np\n",
"import torch\n",
"from torch import nn\n",
"import torch.nn.functional as F\n",
"import torchaudio\n",
"import librosa\n",
"from nltk.tokenize import word_tokenize\n",
"\n",
"from models import *\n",
"from utils import *\n",
"from text_utils import TextCleaner\n",
"textclenaer = TextCleaner()\n",
"\n",
"%matplotlib inline\n",
"\n",
"to_mel = torchaudio.transforms.MelSpectrogram(\n",
" n_mels=80, n_fft=2048, win_length=1200, hop_length=300)\n",
"mean, std = -4, 4\n",
"\n",
"def length_to_mask(lengths):\n",
" mask = torch.arange(lengths.max()).unsqueeze(0).expand(lengths.shape[0], -1).type_as(lengths)\n",
" mask = torch.gt(mask+1, lengths.unsqueeze(1))\n",
" return mask\n",
"\n",
"def preprocess(wave):\n",
" wave_tensor = torch.from_numpy(wave).float()\n",
" mel_tensor = to_mel(wave_tensor)\n",
" mel_tensor = (torch.log(1e-5 + mel_tensor.unsqueeze(0)) - mean) / std\n",
" return mel_tensor\n",
"\n",
"def compute_style(path):\n",
" wave, sr = librosa.load(path, sr=24000)\n",
" audio, index = librosa.effects.trim(wave, top_db=30)\n",
" if sr != 24000:\n",
" audio = librosa.resample(audio, sr, 24000)\n",
" mel_tensor = preprocess(audio).to(device)\n",
"\n",
" with torch.no_grad():\n",
" ref_s = model.style_encoder(mel_tensor.unsqueeze(1))\n",
" ref_p = model.predictor_encoder(mel_tensor.unsqueeze(1))\n",
"\n",
" return torch.cat([ref_s, ref_p], dim=1)\n",
"\n",
"device = 'cuda' if torch.cuda.is_available() else 'cpu'\n",
"\n",
"# load phonemizer\n",
"import phonemizer\n",
"global_phonemizer = phonemizer.backend.EspeakBackend(language='en-us', preserve_punctuation=True, with_stress=True)\n",
"\n",
"config = yaml.safe_load(open(\"Models/LJSpeech/config_ft.yml\"))\n",
"\n",
"# load pretrained ASR model\n",
"ASR_config = config.get('ASR_config', False)\n",
"ASR_path = config.get('ASR_path', False)\n",
"text_aligner = load_ASR_models(ASR_path, ASR_config)\n",
"\n",
"# load pretrained F0 model\n",
"F0_path = config.get('F0_path', False)\n",
"pitch_extractor = load_F0_models(F0_path)\n",
"\n",
"# load BERT model\n",
"from Utils.PLBERT.util import load_plbert\n",
"BERT_path = config.get('PLBERT_dir', False)\n",
"plbert = load_plbert(BERT_path)\n",
"\n",
"model_params = recursive_munch(config['model_params'])\n",
"model = build_model(model_params, text_aligner, pitch_extractor, plbert)\n",
"_ = [model[key].eval() for key in model]\n",
"_ = [model[key].to(device) for key in model]"
],
"metadata": {
"id": "jIIAoDACXJL0"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"files = [f for f in os.listdir(\"Models/LJSpeech/\") if f.endswith('.pth')]\n",
"sorted_files = sorted(files, key=lambda x: int(x.split('_')[-1].split('.')[0]))"
],
"metadata": {
"id": "eKXRAyyzcMpQ"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"params_whole = torch.load(\"Models/LJSpeech/\" + sorted_files[-1], map_location='cpu')\n",
"params = params_whole['net']"
],
"metadata": {
"id": "ULuU9-VDb9Pk"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"for key in model:\n",
" if key in params:\n",
" print('%s loaded' % key)\n",
" try:\n",
" model[key].load_state_dict(params[key])\n",
" except:\n",
" from collections import OrderedDict\n",
" state_dict = params[key]\n",
" new_state_dict = OrderedDict()\n",
" for k, v in state_dict.items():\n",
" name = k[7:] # remove `module.`\n",
" new_state_dict[name] = v\n",
" # load params\n",
" model[key].load_state_dict(new_state_dict, strict=False)\n",
"# except:\n",
"# _load(params[key], model[key])\n",
"_ = [model[key].eval() for key in model]"
],
"metadata": {
"id": "J-U29yIYc2ea"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"from Modules.diffusion.sampler import DiffusionSampler, ADPM2Sampler, KarrasSchedule"
],
"metadata": {
"id": "jrPQ_Yrwc3n6"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"sampler = DiffusionSampler(\n",
" model.diffusion.diffusion,\n",
" sampler=ADPM2Sampler(),\n",
" sigma_schedule=KarrasSchedule(sigma_min=0.0001, sigma_max=3.0, rho=9.0), # empirical parameters\n",
" clamp=False\n",
")"
],
"metadata": {
"id": "n2CWYNoqc455"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"def inference(text, ref_s, alpha = 0.3, beta = 0.7, diffusion_steps=5, embedding_scale=1):\n",
" text = text.strip()\n",
" ps = global_phonemizer.phonemize([text])\n",
" ps = word_tokenize(ps[0])\n",
" ps = ' '.join(ps)\n",
" tokens = textclenaer(ps)\n",
" tokens.insert(0, 0)\n",
" tokens = torch.LongTensor(tokens).to(device).unsqueeze(0)\n",
"\n",
" with torch.no_grad():\n",
" input_lengths = torch.LongTensor([tokens.shape[-1]]).to(device)\n",
" text_mask = length_to_mask(input_lengths).to(device)\n",
"\n",
" t_en = model.text_encoder(tokens, input_lengths, text_mask)\n",
" bert_dur = model.bert(tokens, attention_mask=(~text_mask).int())\n",
" d_en = model.bert_encoder(bert_dur).transpose(-1, -2)\n",
"\n",
" s_pred = sampler(noise = torch.randn((1, 256)).unsqueeze(1).to(device),\n",
" embedding=bert_dur,\n",
" embedding_scale=embedding_scale,\n",
" features=ref_s, # reference from the same speaker as the embedding\n",
" num_steps=diffusion_steps).squeeze(1)\n",
"\n",
"\n",
" s = s_pred[:, 128:]\n",
" ref = s_pred[:, :128]\n",
"\n",
" ref = alpha * ref + (1 - alpha) * ref_s[:, :128]\n",
" s = beta * s + (1 - beta) * ref_s[:, 128:]\n",
"\n",
" d = model.predictor.text_encoder(d_en,\n",
" s, input_lengths, text_mask)\n",
"\n",
" x, _ = model.predictor.lstm(d)\n",
" duration = model.predictor.duration_proj(x)\n",
"\n",
" duration = torch.sigmoid(duration).sum(axis=-1)\n",
" pred_dur = torch.round(duration.squeeze()).clamp(min=1)\n",
"\n",
" pred_aln_trg = torch.zeros(input_lengths, int(pred_dur.sum().data))\n",
" c_frame = 0\n",
" for i in range(pred_aln_trg.size(0)):\n",
" pred_aln_trg[i, c_frame:c_frame + int(pred_dur[i].data)] = 1\n",
" c_frame += int(pred_dur[i].data)\n",
"\n",
" # encode prosody\n",
" en = (d.transpose(-1, -2) @ pred_aln_trg.unsqueeze(0).to(device))\n",
" if model_params.decoder.type == \"hifigan\":\n",
" asr_new = torch.zeros_like(en)\n",
" asr_new[:, :, 0] = en[:, :, 0]\n",
" asr_new[:, :, 1:] = en[:, :, 0:-1]\n",
" en = asr_new\n",
"\n",
" F0_pred, N_pred = model.predictor.F0Ntrain(en, s)\n",
"\n",
" asr = (t_en @ pred_aln_trg.unsqueeze(0).to(device))\n",
" if model_params.decoder.type == \"hifigan\":\n",
" asr_new = torch.zeros_like(asr)\n",
" asr_new[:, :, 0] = asr[:, :, 0]\n",
" asr_new[:, :, 1:] = asr[:, :, 0:-1]\n",
" asr = asr_new\n",
"\n",
" out = model.decoder(asr,\n",
" F0_pred, N_pred, ref.squeeze().unsqueeze(0))\n",
"\n",
"\n",
" return out.squeeze().cpu().numpy()[..., :-50] # weird pulse at the end of the model, need to be fixed later"
],
"metadata": {
"id": "2x5kVb3nc_eY"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "markdown",
"source": [
"### Synthesize speech"
],
"metadata": {
"id": "O159JnwCc6CC"
}
},
{
"cell_type": "code",
"source": [
"text = '''Maltby and Company would issue warrants on them deliverable to the importer, and the goods were then passed to be stored in neighboring warehouses.\n",
"'''"
],
"metadata": {
"id": "ThciXQ6rc9Eq"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"# get a random reference in the training set, note that it doesn't matter which one you use\n",
"path = \"Data/wavs/LJ001-0110.wav\"\n",
"# this style vector ref_s can be saved as a parameter together with the model weights\n",
"ref_s = compute_style(path)"
],
"metadata": {
"id": "jldPkJyCc83a"
},
"execution_count": null,
"outputs": []
},
{
"cell_type": "code",
"source": [
"start = time.time()\n",
"wav = inference(text, ref_s, alpha=0.9, beta=0.9, diffusion_steps=10, embedding_scale=1)\n",
"rtf = (time.time() - start) / (len(wav) / 24000)\n",
"print(f\"RTF = {rtf:5f}\")\n",
"import IPython.display as ipd\n",
"display(ipd.Audio(wav, rate=24000, normalize=False))"
],
"metadata": {
"id": "_mIU0jqDdQ-c"
},
"execution_count": null,
"outputs": []
}
]
}
+116
View File
@@ -0,0 +1,116 @@
log_dir: "Models/LJSpeech"
first_stage_path: "first_stage.pth"
save_freq: 2
log_interval: 10
device: "cuda"
epochs_1st: 200 # number of epochs for first stage training (pre-training)
epochs_2nd: 100 # number of peochs for second stage training (joint training)
batch_size: 16
max_len: 400 # maximum number of frames
pretrained_model: ""
second_stage_load_pretrained: true # set to true if the pre-trained model is for 2nd stage
load_only_params: false # set to true if do not want to load epoch numbers and optimizer parameters
F0_path: "Utils/JDC/bst.t7"
ASR_config: "Utils/ASR/config.yml"
ASR_path: "Utils/ASR/epoch_00080.pth"
PLBERT_dir: 'Utils/PLBERT/'
data_params:
train_data: "Data/train_list.txt"
val_data: "Data/val_list.txt"
root_path: "/local/LJSpeech-1.1/wavs"
OOD_data: "Data/OOD_texts.txt"
min_length: 50 # sample until texts with this size are obtained for OOD texts
preprocess_params:
sr: 24000
spect_params:
n_fft: 2048
win_length: 1200
hop_length: 300
model_params:
multispeaker: false
dim_in: 64
hidden_dim: 512
max_conv_dim: 512
n_layer: 3
n_mels: 80
n_token: 178 # number of phoneme tokens
max_dur: 50 # maximum duration of a single phoneme
style_dim: 128 # style vector size
dropout: 0.2
# config for decoder
decoder:
type: 'istftnet' # either hifigan or istftnet
resblock_kernel_sizes: [3,7,11]
upsample_rates : [10, 6]
upsample_initial_channel: 512
resblock_dilation_sizes: [[1,3,5], [1,3,5], [1,3,5]]
upsample_kernel_sizes: [20, 12]
gen_istft_n_fft: 20
gen_istft_hop_size: 5
# speech language model config
slm:
model: 'microsoft/wavlm-base-plus'
sr: 16000 # sampling rate of SLM
hidden: 768 # hidden size of SLM
nlayers: 13 # number of layers of SLM
initial_channel: 64 # initial channels of SLM discriminator head
# style diffusion model config
diffusion:
embedding_mask_proba: 0.1
# transformer config
transformer:
num_layers: 3
num_heads: 8
head_features: 64
multiplier: 2
# diffusion distribution config
dist:
sigma_data: 0.2 # placeholder for estimate_sigma_data set to false
estimate_sigma_data: true # estimate sigma_data from the current batch if set to true
mean: -3.0
std: 1.0
loss_params:
lambda_mel: 5. # mel reconstruction loss
lambda_gen: 1. # generator loss
lambda_slm: 1. # slm feature matching loss
lambda_mono: 1. # monotonic alignment loss (1st stage, TMA)
lambda_s2s: 1. # sequence-to-sequence loss (1st stage, TMA)
TMA_epoch: 50 # TMA starting epoch (1st stage)
lambda_F0: 1. # F0 reconstruction loss (2nd stage)
lambda_norm: 1. # norm reconstruction loss (2nd stage)
lambda_dur: 1. # duration loss (2nd stage)
lambda_ce: 20. # duration predictor probability output CE loss (2nd stage)
lambda_sty: 1. # style reconstruction loss (2nd stage)
lambda_diff: 1. # score matching loss (2nd stage)
diff_epoch: 20 # style diffusion starting epoch (2nd stage)
joint_epoch: 50 # joint training starting epoch (2nd stage)
optimizer_params:
lr: 0.0001 # general learning rate
bert_lr: 0.00001 # learning rate for PLBERT
ft_lr: 0.00001 # learning rate for acoustic modules
slmadv_params:
min_len: 400 # minimum length of samples
max_len: 500 # maximum length of samples
batch_percentage: 0.5 # to prevent out of memory, only use half of the original batch size
iter: 10 # update the discriminator every this iterations of generator update
thresh: 5 # gradient norm above which the gradient is scaled
scale: 0.01 # gradient scaling factor for predictors from SLM discriminators
sig: 1.5 # sigma for differentiable duration modeling
+111
View File
@@ -0,0 +1,111 @@
log_dir: "Models/LJSpeech"
save_freq: 5
log_interval: 10
device: "cuda"
epochs: 50 # number of finetuning epoch (1 hour of data)
batch_size: 8
max_len: 400 # maximum number of frames
pretrained_model: "Models/LibriTTS/epochs_2nd_00020.pth"
second_stage_load_pretrained: true # set to true if the pre-trained model is for 2nd stage
load_only_params: true # set to true if do not want to load epoch numbers and optimizer parameters
F0_path: "Utils/JDC/bst.t7"
ASR_config: "Utils/ASR/config.yml"
ASR_path: "Utils/ASR/epoch_00080.pth"
PLBERT_dir: 'Utils/PLBERT/'
data_params:
train_data: "Data/train_list.txt"
val_data: "Data/val_list.txt"
root_path: "/local/LJSpeech-1.1/wavs"
OOD_data: "Data/OOD_texts.txt"
min_length: 50 # sample until texts with this size are obtained for OOD texts
preprocess_params:
sr: 24000
spect_params:
n_fft: 2048
win_length: 1200
hop_length: 300
model_params:
multispeaker: true
dim_in: 64
hidden_dim: 512
max_conv_dim: 512
n_layer: 3
n_mels: 80
n_token: 178 # number of phoneme tokens
max_dur: 50 # maximum duration of a single phoneme
style_dim: 128 # style vector size
dropout: 0.2
# config for decoder
decoder:
type: 'hifigan' # either hifigan or istftnet
resblock_kernel_sizes: [3,7,11]
upsample_rates : [10,5,3,2]
upsample_initial_channel: 512
resblock_dilation_sizes: [[1,3,5], [1,3,5], [1,3,5]]
upsample_kernel_sizes: [20,10,6,4]
# speech language model config
slm:
model: 'microsoft/wavlm-base-plus'
sr: 16000 # sampling rate of SLM
hidden: 768 # hidden size of SLM
nlayers: 13 # number of layers of SLM
initial_channel: 64 # initial channels of SLM discriminator head
# style diffusion model config
diffusion:
embedding_mask_proba: 0.1
# transformer config
transformer:
num_layers: 3
num_heads: 8
head_features: 64
multiplier: 2
# diffusion distribution config
dist:
sigma_data: 0.2 # placeholder for estimate_sigma_data set to false
estimate_sigma_data: true # estimate sigma_data from the current batch if set to true
mean: -3.0
std: 1.0
loss_params:
lambda_mel: 5. # mel reconstruction loss
lambda_gen: 1. # generator loss
lambda_slm: 1. # slm feature matching loss
lambda_mono: 1. # monotonic alignment loss (TMA)
lambda_s2s: 1. # sequence-to-sequence loss (TMA)
lambda_F0: 1. # F0 reconstruction loss
lambda_norm: 1. # norm reconstruction loss
lambda_dur: 1. # duration loss
lambda_ce: 20. # duration predictor probability output CE loss
lambda_sty: 1. # style reconstruction loss
lambda_diff: 1. # score matching loss
diff_epoch: 10 # style diffusion starting epoch
joint_epoch: 30 # joint training starting epoch
optimizer_params:
lr: 0.0001 # general learning rate
bert_lr: 0.00001 # learning rate for PLBERT
ft_lr: 0.0001 # learning rate for acoustic modules
slmadv_params:
min_len: 400 # minimum length of samples
max_len: 500 # maximum length of samples
batch_percentage: 0.5 # to prevent out of memory, only use half of the original batch size
iter: 10 # update the discriminator every this iterations of generator update
thresh: 5 # gradient norm above which the gradient is scaled
scale: 0.01 # gradient scaling factor for predictors from SLM discriminators
sig: 1.5 # sigma for differentiable duration modeling
@@ -0,0 +1,110 @@
log_dir: "Models/LJSpeech"
save_freq: 5
log_interval: 10
device: "cuda"
epochs: 50 # number of finetuning epoch (1 hour of data)
batch_size: 8
max_len: 400 # maximum number of frames
pretrained_model: "Models/LibriTTS/epochs_2nd_00020.pth"
second_stage_load_pretrained: true # set to true if the pre-trained model is for 2nd stage
load_only_params: true # set to true if do not want to load epoch numbers and optimizer parameters
F0_path: "Utils/JDC/bst.t7"
ASR_config: "Utils/ASR/config.yml"
ASR_path: "Utils/ASR/epoch_00080.pth"
PLBERT_dir: 'Utils/PLBERT/'
data_params:
train_data: "Data/train_harness.txt"
val_data: "Data/val_harness.txt"
root_path: ""
OOD_data: "Data/OOD_harness.txt"
min_length: 50 # sample until texts with this size are obtained for OOD texts
preprocess_params:
sr: 24000
spect_params:
n_fft: 2048
win_length: 1200
hop_length: 300
model_params:
multispeaker: true
dim_in: 64
hidden_dim: 512
max_conv_dim: 512
n_layer: 3
n_mels: 80
n_token: 178 # number of phoneme tokens
max_dur: 50 # maximum duration of a single phoneme
style_dim: 128 # style vector size
dropout: 0.2
# config for decoder
decoder:
type: 'hifigan' # either hifigan or istftnet
resblock_kernel_sizes: [3,7,11]
upsample_rates : [10,5,3,2]
upsample_initial_channel: 512
resblock_dilation_sizes: [[1,3,5], [1,3,5], [1,3,5]]
upsample_kernel_sizes: [20,10,6,4]
# speech language model config
slm:
model: 'microsoft/wavlm-base-plus'
sr: 16000 # sampling rate of SLM
hidden: 768 # hidden size of SLM
nlayers: 13 # number of layers of SLM
initial_channel: 64 # initial channels of SLM discriminator head
# style diffusion model config
diffusion:
embedding_mask_proba: 0.1
# transformer config
transformer:
num_layers: 3
num_heads: 8
head_features: 64
multiplier: 2
# diffusion distribution config
dist:
sigma_data: 0.2 # placeholder for estimate_sigma_data set to false
estimate_sigma_data: true # estimate sigma_data from the current batch if set to true
mean: -3.0
std: 1.0
loss_params:
lambda_mel: 5. # mel reconstruction loss
lambda_gen: 1. # generator loss
lambda_slm: 1. # slm feature matching loss
lambda_mono: 1. # monotonic alignment loss (TMA)
lambda_s2s: 1. # sequence-to-sequence loss (TMA)
lambda_F0: 1. # F0 reconstruction loss
lambda_norm: 1. # norm reconstruction loss
lambda_dur: 1. # duration loss
lambda_ce: 20. # duration predictor probability output CE loss
lambda_sty: 1. # style reconstruction loss
lambda_diff: 1. # score matching loss
diff_epoch: 10 # style diffusion starting epoch
joint_epoch: 30 # joint training starting epoch
optimizer_params:
lr: 0.0001 # general learning rate
bert_lr: 0.00001 # learning rate for PLBERT
ft_lr: 0.0001 # learning rate for acoustic modules
slmadv_params:
min_len: 400 # minimum length of samples
max_len: 500 # maximum length of samples
batch_percentage: 0.5 # to prevent out of memory, only use half of the original batch size
iter: 10 # update the discriminator every this iterations of generator update
thresh: 5 # gradient norm above which the gradient is scaled
scale: 0.01 # gradient scaling factor for predictors from SLM discriminators
sig: 1.5 # sigma for differentiable duration modeling
@@ -0,0 +1,113 @@
log_dir: "Models/LibriTTS"
first_stage_path: "first_stage.pth"
save_freq: 1
log_interval: 10
device: "cuda"
epochs_1st: 50 # number of epochs for first stage training (pre-training)
epochs_2nd: 30 # number of peochs for second stage training (joint training)
batch_size: 16
max_len: 300 # maximum number of frames
pretrained_model: ""
second_stage_load_pretrained: true # set to true if the pre-trained model is for 2nd stage
load_only_params: false # set to true if do not want to load epoch numbers and optimizer parameters
F0_path: "Utils/JDC/bst.t7"
ASR_config: "Utils/ASR/config.yml"
ASR_path: "Utils/ASR/epoch_00080.pth"
PLBERT_dir: 'Utils/PLBERT/'
data_params:
train_data: "Data/train_list.txt"
val_data: "Data/val_list.txt"
root_path: ""
OOD_data: "Data/OOD_texts.txt"
min_length: 50 # sample until texts with this size are obtained for OOD texts
preprocess_params:
sr: 24000
spect_params:
n_fft: 2048
win_length: 1200
hop_length: 300
model_params:
multispeaker: true
dim_in: 64
hidden_dim: 512
max_conv_dim: 512
n_layer: 3
n_mels: 80
n_token: 178 # number of phoneme tokens
max_dur: 50 # maximum duration of a single phoneme
style_dim: 128 # style vector size
dropout: 0.2
# config for decoder
decoder:
type: 'hifigan' # either hifigan or istftnet
resblock_kernel_sizes: [3,7,11]
upsample_rates : [10,5,3,2]
upsample_initial_channel: 512
resblock_dilation_sizes: [[1,3,5], [1,3,5], [1,3,5]]
upsample_kernel_sizes: [20,10,6,4]
# speech language model config
slm:
model: 'microsoft/wavlm-base-plus'
sr: 16000 # sampling rate of SLM
hidden: 768 # hidden size of SLM
nlayers: 13 # number of layers of SLM
initial_channel: 64 # initial channels of SLM discriminator head
# style diffusion model config
diffusion:
embedding_mask_proba: 0.1
# transformer config
transformer:
num_layers: 3
num_heads: 8
head_features: 64
multiplier: 2
# diffusion distribution config
dist:
sigma_data: 0.2 # placeholder for estimate_sigma_data set to false
estimate_sigma_data: true # estimate sigma_data from the current batch if set to true
mean: -3.0
std: 1.0
loss_params:
lambda_mel: 5. # mel reconstruction loss
lambda_gen: 1. # generator loss
lambda_slm: 1. # slm feature matching loss
lambda_mono: 1. # monotonic alignment loss (1st stage, TMA)
lambda_s2s: 1. # sequence-to-sequence loss (1st stage, TMA)
TMA_epoch: 5 # TMA starting epoch (1st stage)
lambda_F0: 1. # F0 reconstruction loss (2nd stage)
lambda_norm: 1. # norm reconstruction loss (2nd stage)
lambda_dur: 1. # duration loss (2nd stage)
lambda_ce: 20. # duration predictor probability output CE loss (2nd stage)
lambda_sty: 1. # style reconstruction loss (2nd stage)
lambda_diff: 1. # score matching loss (2nd stage)
diff_epoch: 10 # style diffusion starting epoch (2nd stage)
joint_epoch: 15 # joint training starting epoch (2nd stage)
optimizer_params:
lr: 0.0001 # general learning rate
bert_lr: 0.00001 # learning rate for PLBERT
ft_lr: 0.00001 # learning rate for acoustic modules
slmadv_params:
min_len: 400 # minimum length of samples
max_len: 500 # maximum length of samples
batch_percentage: 0.5 # to prevent out of memory, only use half of the original batch size
iter: 20 # update the discriminator every this iterations of generator update
thresh: 5 # gradient norm above which the gradient is scaled
scale: 0.01 # gradient scaling factor for predictors from SLM discriminators
sig: 1.5 # sigma for differentiable duration modeling
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+100
View File
@@ -0,0 +1,100 @@
LJ022-0023.wav|ðɪ ˌoʊvɚwˈɛlmɪŋ mədʒˈɔːɹᵻɾi ʌv pˈiːpəl ɪn ðɪs kˈʌntɹi nˈoʊ hˌaʊ tə sˈɪft ðə wˈiːt fɹʌmðə tʃˈæf ɪn wʌt ðeɪ hˈɪɹ ænd wʌt ðeɪ ɹˈiːd .|0
LJ043-0030.wav|ɪf sˈʌmbɑːdi dˈɪd ðˈæt tə mˌiː , ɐ lˈaʊsi tɹˈɪk lˈaɪk ðˈæt , tə tˈeɪk maɪ wˈaɪf ɐwˈeɪ , ænd ˈɔːl ðə fˈɜːnɪtʃɚ , aɪ wʊd biː mˈæd æz hˈɛl , tˈuː .|0
LJ005-0201.wav|ˌæzˌɪz ʃˈoʊn baɪ ðə ɹᵻpˈoːɹt ʌvðə kəmˈɪʃənɚz tʊ ɪŋkwˈaɪɚɹ ˌɪntʊ ðə stˈeɪt ʌvðə mjuːnˈɪsɪpəl kˌɔːɹpɚɹˈeɪʃənz ɪn ˈeɪtiːn θˈɜːɾi fˈaɪv .|0
LJ001-0110.wav|ˈiːvən ðə kˈæslɑːn tˈaɪp wɛn ɛnlˈɑːɹdʒd ʃˈoʊz ɡɹˈeɪt ʃˈɔːɹtkʌmɪŋz ɪn ðɪs ɹᵻspˈɛkt :|0
LJ003-0345.wav|ˈɔːl ðə kəmˈɪɾi kʊd dˈuː ɪn ðɪs ɹᵻspˈɛkt wʌz tə θɹˈoʊ ðə ɹᵻspˌɑːnsəbˈɪlɪɾi ˌɔn ˈʌðɚz .|0
LJ007-0154.wav|ðiːz pˈʌndʒənt ænd wˈɛl ɡɹˈaʊndᵻd stɹˈɪktʃɚz ɐplˈaɪd wɪð stˈɪl ɡɹˈeɪɾɚ fˈoːɹs tə ðɪ ʌŋkənvˈɪktᵻd pɹˈɪzənɚ , ðə mˈæn hˌuː kˈeɪm tə ðə pɹˈɪzən ˈɪnəsənt , ænd stˈɪl ʌŋkəntˈæmᵻnˌeɪɾᵻd ,|0
LJ018-0098.wav|ænd ɹˈɛkəɡnˌaɪzd æz wˈʌn ʌvðə fɹˈiːkwɛntɚz ʌvðə bˈoʊɡəs lˈɔː stˈeɪʃənɚz . hɪz ɚɹˈɛst lˈɛd tə ðæt ʌv ˈʌðɚz .|0
LJ047-0044.wav|ˈɑːswəld wʌz , haʊˈɛvɚ , wˈɪlɪŋ tə dɪskˈʌs hɪz kˈɑːntækts wɪð sˈoʊviət ɐθˈɔːɹɪɾiz . hiː dᵻnˈaɪd hˌævɪŋ ˌɛni ɪnvˈɑːlvmənt wɪð sˈoʊviət ɪntˈɛlɪdʒəns ˈeɪdʒənsiz|0
LJ031-0038.wav|ðə fˈɜːst fɪzˈɪʃən tə sˈiː ðə pɹˈɛzɪdənt æt pˈɑːɹklənd hˈɑːspɪɾəl wʌz dˈɑːktɚ . tʃˈɑːɹlz dʒˈeɪ . kˈæɹɪkˌoʊ , ɐ ɹˈɛzᵻdənt ɪn dʒˈɛnɚɹəl sˈɜːdʒɚɹi .|0
LJ048-0194.wav|dˈʊɹɹɪŋ ðə mˈɔːɹnɪŋ ʌv noʊvˈɛmbɚ twˈɛnti tˈuː pɹˈaɪɚ tə ðə mˈoʊɾɚkˌeɪd .|0
LJ049-0026.wav|ˌɔn əkˈeɪʒən ðə sˈiːkɹᵻt sˈɜːvɪs hɐzbɪn pɚmˈɪɾᵻd tə hæv ɐn ˈeɪdʒənt ɹˈaɪdɪŋ ɪnðə pˈæsɪndʒɚ kəmpˈɑːɹtmənt wɪððə pɹˈɛzɪdənt .|0
LJ004-0152.wav|ɔːlðˈoʊ æt mˈɪstɚ . bˈʌkstənz vˈɪzɪt ɐ nˈuː dʒˈeɪl wʌz ɪn pɹˈɑːsɛs ʌv ɪɹˈɛkʃən , ðə fˈɜːst stˈɛp təwˈɔːɹdz ɹᵻfˈɔːɹm sˈɪns hˈaʊɚdz vˌɪzɪtˈeɪʃən ɪn sˈɛvəntˌiːn sˈɛvənti fˈoːɹ .|0
LJ008-0278.wav|ɔːɹ ðˈɛɹz mˌaɪt biː wˈʌn ʌv mˈɛni , ænd ɪt mˌaɪt biː kənsˈɪdɚd nˈɛsᵻsɚɹi tə dˈɑːlɚ mˌeɪk ɐn ɛɡzˈæmpəl.dˈɑːlɚ|0
LJ043-0002.wav|ðə wˈɔːɹəŋ kəmˈɪʃən ɹᵻpˈoːɹt . baɪ ðə pɹˈɛzɪdənts kəmˈɪʃən ɔnðɪ ɐsˌæsᵻnˈeɪʃən ʌv pɹˈɛzɪdənt kˈɛnədi . tʃˈæptɚ sˈɛvən . lˈiː hˈɑːɹvi ˈɑːswəld :|0
LJ009-0114.wav|mˈɪstɚ . wˈeɪkfiːld wˈaɪndz ˈʌp hɪz ɡɹˈæfɪk bˌʌt sˈʌmwʌt sɛnsˈeɪʃənəl ɐkˈaʊnt baɪ dᵻskɹˈaɪbɪŋ ɐnˈʌðɚ ɹᵻlˈɪdʒəs sˈɜːvɪs , wˌɪtʃ mˈeɪ ɐpɹˈoʊpɹɪˌeɪtli biː ɪnsˈɜːɾᵻd hˈɪɹ .|0
LJ028-0506.wav|ɐ mˈɑːdɚn ˈɑːɹɾɪst wʊdhɐv dˈɪfɪkˌʌlti ɪn dˌuːɪŋ sˈʌtʃ ˈækjʊɹət wˈɜːk .|0
LJ050-0168.wav|wɪððə pɚtˈɪkjʊlɚ pˈɜːpəsᵻz ʌvðɪ ˈeɪdʒənsi ɪnvˈɑːlvd . ðə kəmˈɪʃən ɹˈɛkəɡnˌaɪzᵻz ðæt ðɪs ɪz ɐ kˌɑːntɹəvˈɜːʃəl ˈɛɹiə|0
LJ039-0223.wav|ˈɑːswəldz mɚɹˈiːn tɹˈeɪnɪŋ ɪn mˈɑːɹksmənʃˌɪp , hɪz ˈʌðɚ ɹˈaɪfəl ɛkspˈiəɹɪəns ænd hɪz ɪstˈæblɪʃt fəmˌɪliˈæɹɪɾi wɪð ðɪs pɚtˈɪkjʊlɚ wˈɛpən|0
LJ029-0032.wav|ɐkˈoːɹdɪŋ tʊ oʊdˈɑːnəl , kwˈoʊt , wiː hæd ɐ mˈoʊɾɚkˌeɪd wɛɹˈɛvɚ kplˈʌsplʌs wˌɪtʃ hɐdbɪn bˌɪn hˈeɪstili sˈʌmənd fɚðə ðə pˈɜːpəs wiː wˈɛnt , ˈɛnd kwˈoʊt .|0
LJ031-0070.wav|dˈɑːktɚ . klˈɑːɹk , hˌuː mˈoʊst klˈoʊsli əbzˈɜːvd ðə hˈɛd wˈuːnd ,|0
LJ034-0198.wav|jˈuːɪnz , hˌuː wʌz ɔnðə saʊθwˈɛst kˈɔːɹnɚɹ ʌv ˈɛlm ænd hjˈuːstən stɹˈiːts tˈɛstᵻfˌaɪd ðæt hiː kʊd nˌɑːt dᵻskɹˈaɪb ðə mˈæn hiː sˈɔː ɪnðə wˈɪndoʊ .|0
LJ026-0068.wav|ˈɛnɚdʒi ˈɛntɚz ðə plˈænt , tʊ ɐ smˈɔːl ɛkstˈɛnt ,|0
LJ039-0075.wav|wˈʌns juː nˈoʊ ðæt juː mˈʌst pˌʊt ðə kɹˈɔshɛɹz ɔnðə tˈɑːɹɡɪt ænd ðæt ɪz ˈɔːl ðæt ɪz nˈɛsᵻsɚɹi .|0
LJ004-0096.wav|ðə fˈeɪɾəl kˈɑːnsɪkwənsᵻz wˈɛɹɑːf mˌaɪt biː pɹɪvˈɛntᵻd ɪf ðə dʒˈʌstɪsᵻz ʌvðə pˈiːs wɜː djˈuːli ˈɔːθɚɹˌaɪzd|0
LJ005-0014.wav|spˈiːkɪŋ ˌɔn ɐ dᵻbˈeɪt ˌɔn pɹˈɪzən mˈæɾɚz , hiː dᵻklˈɛɹd ðˈæt|0
LJ012-0161.wav|hiː wʌz ɹᵻpˈoːɹɾᵻd tə hæv fˈɔːlən ɐwˈeɪ tʊ ɐ ʃˈædoʊ .|0
LJ018-0239.wav|hɪz dˌɪsɐpˈɪɹəns ɡˈeɪv kˈʌlɚ ænd sˈʌbstəns tʊ ˈiːvəl ɹᵻpˈoːɹts ɔːlɹˌɛdi ɪn sˌɜːkjʊlˈeɪʃən ðætðə wɪl ænd kənvˈeɪəns əbˌʌv ɹᵻfˈɜːd tuː|0
LJ019-0257.wav|hˈɪɹ ðə tɹˈɛd wˈiːl wʌz ɪn jˈuːs , ðɛɹ sˈɛljʊlɚ kɹˈæŋks , ɔːɹ hˈɑːɹd lˈeɪbɚ məʃˈiːnz .|0
LJ028-0008.wav|juː tˈæp dʒˈɛntli wɪð jʊɹ hˈiːl əpˌɑːn ðə ʃˈoʊldɚɹ ʌvðə dɹˈoʊmdɚɹi tʊ ˈɜːdʒ hɜːɹ ˈɔn .|0
LJ024-0083.wav|ðɪs plˈæn ʌv mˈaɪn ɪz nˈoʊ ɐtˈæk ɔnðə kˈoːɹt ;|0
LJ042-0129.wav|nˈoʊ nˈaɪt klˈʌbz ɔːɹ bˈoʊlɪŋ ˈælɪz , nˈoʊ plˈeɪsᵻz ʌv ɹˌɛkɹiːˈeɪʃən ɛksˈɛpt ðə tɹˈeɪd jˈuːniən dˈænsᵻz . aɪ hæv hæd ɪnˈʌf .|0
LJ036-0103.wav|ðə pəlˈiːs ˈæskt hˌɪm wˈɛðɚ hiː kʊd pˈɪk ˈaʊt hɪz pˈæsɪndʒɚ fɹʌmðə lˈaɪnʌp .|0
LJ046-0058.wav|dˈʊɹɹɪŋ hɪz pɹˈɛzɪdənsi , fɹˈæŋklɪn dˈiː . ɹˈoʊzəvˌɛlt mˌeɪd ˈɔːlmoʊst fˈoːɹ hˈʌndɹɪd dʒˈɜːniz ænd tɹˈævəld mˈoːɹ ðɐn θɹˈiː hˈʌndɹɪd fˈɪfti θˈaʊzənd mˈaɪlz .|0
LJ014-0076.wav|hiː wʌz sˈiːn ˈæftɚwɚdz smˈoʊkɪŋ ænd tˈɔːkɪŋ wɪð hɪz hˈoʊsts ɪn ðɛɹ bˈæk pˈɑːɹlɚ , ænd nˈɛvɚ sˈiːn ɐɡˈɛn ɐlˈaɪv .|0
LJ002-0043.wav|lˈɔŋ nˈæɹoʊ ɹˈuːmz wˈʌn θˈɜːɾi sˈɪks fˈiːt , sˈɪks twˈɛnti θɹˈiː fˈiːt , ænd ðɪ ˈeɪtθ ˈeɪtiːn ,|0
LJ009-0076.wav|wiː kˈʌm tə ðə sˈɜːmən .|0
LJ017-0131.wav|ˈiːvən wɛn ðə hˈaɪ ʃˈɛɹɪf hæd tˈoʊld hˌɪm ðɛɹwˌʌz nˈoʊ pˌɑːsəbˈɪlɪɾi əvɚ ɹᵻpɹˈiːv , ænd wɪðˌɪn ɐ fjˈuː ˈaʊɚz ʌv ˌɛksɪkjˈuːʃən .|0
LJ046-0184.wav|bˌʌt ðɛɹ ɪz ɐ sˈɪstəm fɚðɪ ɪmˈiːdɪət nˌoʊɾɪfɪkˈeɪʃən ʌvðə sˈiːkɹᵻt sˈɜːvɪs baɪ ðə kənfˈaɪnɪŋ ˌɪnstɪtˈuːʃən wɛn ɐ sˈʌbdʒɛkt ɪz ɹᵻlˈiːst ɔːɹ ɛskˈeɪps .|0
LJ014-0263.wav|wˌɛn ˈʌðɚ plˈɛʒɚz pˈɔːld hiː tˈʊk ɐ θˈiəɾɚ , ænd pˈoʊzd æz ɐ mjuːnˈɪfɪsənt pˈeɪtɹən ʌvðə dɹəmˈæɾɪk ˈɑːɹt .|0
LJ042-0096.wav|ˈoʊld ɛkstʃˈeɪndʒ ɹˈeɪt ɪn ɐdˈɪʃən tə hɪz fˈæktɚɹi sˈælɚɹi ʌv ɐpɹˈɑːksɪmətli ˈiːkwəl ɐmˈaʊnt|0
LJ049-0050.wav|hˈɪl hæd bˈoʊθ fˈiːt ɔnðə kˈɑːɹ ænd wʌz klˈaɪmɪŋ ɐbˈoːɹd tʊ ɐsˈɪst pɹˈɛzɪdənt ænd mˈɪsɪz . kˈɛnədi .|0
LJ019-0186.wav|sˈiːɪŋ ðæt sˈɪns ðɪ ɪstˈæblɪʃmənt ʌvðə sˈɛntɹəl kɹˈɪmɪnəl kˈoːɹt , nˈuːɡeɪt ɹᵻsˈiːvd pɹˈɪzənɚz fɔːɹ tɹˈaɪəl fɹʌm sˈɛvɹəl kˈaʊntiz ,|0
LJ028-0307.wav|ðˈɛn lˈɛt twˈɛnti dˈeɪz pˈæs , ænd æt ðɪ ˈɛnd ʌv ðæt tˈaɪm stˈeɪʃən nˌɪɹ ðə tʃˈældæsəŋ ɡˈeɪts ɐ bˈɑːdi ʌv fˈoːɹ θˈaʊzənd .|0
LJ012-0235.wav|wˌaɪl ðeɪ wɜːɹ ɪn ɐ stˈeɪt ʌv ɪnsˌɛnsəbˈɪlɪɾi ðə mˈɜːdɚ wʌz kəmˈɪɾᵻd .|0
LJ034-0053.wav|ɹˈiːtʃt ðə sˈeɪm kəŋklˈuːʒən æz lætˈoʊnə ðætðə pɹˈɪnts fˈaʊnd ɔnðə kˈɑːɹtənz wɜː ðoʊz ʌv lˈiː hˈɑːɹvi ˈɑːswəld .|0
LJ014-0030.wav|ðiːz wɜː dˈæmnətˌoːɹi fˈækts wˌɪtʃ wˈɛl səpˈoːɹɾᵻd ðə pɹˌɑːsɪkjˈuːʃən .|0
LJ015-0203.wav|bˌʌt wɜː ðə pɹɪkˈɔːʃənz tˈuː mˈɪnɪt , ðə vˈɪdʒɪləns tˈuː klˈoʊs təbi ᵻlˈuːdᵻd ɔːɹ ˌoʊvɚkˈʌm ?|0
LJ028-0093.wav|bˌʌt hɪz skɹˈaɪb ɹˈoʊt ɪɾ ɪnðə mˈænɚ kˈʌstəmˌɛɹi fɚðə skɹˈaɪbz ʌv ðoʊz dˈeɪz tə ɹˈaɪt ʌv ðɛɹ ɹˈɔɪəl mˈæstɚz .|0
LJ002-0018.wav|ðɪ ɪnˈædɪkwəsi ʌvðə dʒˈeɪl wʌz nˈoʊɾɪst ænd ɹᵻpˈoːɹɾᵻd əpˌɑːn ɐɡˈɛn ænd ɐɡˈɛn baɪ ðə ɡɹˈænd dʒˈʊɹɹiz ʌvðə sˈɪɾi ʌv lˈʌndən ,|0
LJ028-0275.wav|æt lˈæst , ɪnðə twˈɛntiəθ mˈʌnθ ,|0
LJ012-0042.wav|wˌɪtʃ hiː kˈɛpt kənsˈiːld ɪn ɐ hˈaɪdɪŋ plˈeɪs wɪð ɐ tɹˈæp dˈoːɹ dʒˈʌst ˌʌndɚ hɪz bˈɛd .|0
LJ011-0096.wav|hiː mˈæɹid ɐ lˈeɪdi ˈɔːlsoʊ bᵻlˈɔŋɪŋ tə ðə səsˈaɪəɾi ʌv fɹˈɛndz , hˌuː bɹˈɔːt hˌɪm ɐ lˈɑːɹdʒ fˈɔːɹtʃʊn , wˈɪtʃ , ænd hɪz ˈoʊn mˈʌni , hiː pˌʊt ˌɪntʊ ɐ sˈɪɾi fˈɜːm ,|0
LJ036-0077.wav|ɹˈɑːdʒɚ dˈiː . kɹˈeɪɡ , ɐ dˈɛpjuːɾi ʃˈɛɹɪf ʌv dˈæləs kˈaʊnti ,|0
LJ016-0318.wav|ˈʌðɚɹ əfˈɪʃəlz , ɡɹˈeɪt lˈɔɪɚz , ɡˈʌvɚnɚz ʌv pɹˈɪzənz , ænd tʃˈæplɪnz səpˈoːɹɾᵻd ðɪs vjˈuː .|0
LJ013-0164.wav|hˌuː kˈeɪm fɹʌm hɪz ɹˈuːm ɹˈɛdi dɹˈɛst , ɐ səspˈɪʃəs sˈɜːkəmstˌæns , æz hiː wʌz ˈɔːlweɪz lˈeɪt ɪnðə mˈɔːɹnɪŋ .|0
LJ027-0141.wav|ɪz klˈoʊsli ɹᵻpɹədˈuːst ɪnðə lˈaɪf hˈɪstɚɹi ʌv ɛɡzˈɪstɪŋ dˈɪɹ . ɔːɹ , ɪn ˈʌðɚ wˈɜːdz ,|0
LJ028-0335.wav|ɐkˈoːɹdɪŋli ðeɪ kəmˈɪɾᵻd tə hˌɪm ðə kəmˈænd ʌv ðɛɹ hˈoʊl ˈɑːɹmi , ænd pˌʊt ðə kˈiːz ʌv ðɛɹ sˈɪɾi ˌɪntʊ hɪz hˈændz .|0
LJ031-0202.wav|mˈɪsɪz . kˈɛnədi tʃˈoʊz ðə hˈɑːspɪɾəl ɪn bəθˈɛzdə fɚðɪ ˈɔːtɑːpsi bɪkˈʌz ðə pɹˈɛzɪdənt hæd sˈɜːvd ɪnðə nˈeɪvi .|0
LJ021-0145.wav|fɹʌm ðoʊz wˈɪlɪŋ tə dʒˈɔɪn ɪn ɪstˈæblɪʃɪŋ ðɪs hˈoʊpt fɔːɹ pˈiəɹɪəd ʌv pˈiːs ,|0
LJ016-0288.wav|dˈɑːlɚ mˈuːlɚ , mˈuːlɚ , hiːz ðə mˈæn , dˈɑːlɚ tˈɪl ɐ daɪvˈɜːʒən wʌz kɹiːˈeɪɾᵻd baɪ ðɪ ɐpˈɪɹəns ʌvðə ɡˈæloʊz , wˌɪtʃ wʌz ɹᵻsˈiːvd wɪð kəntˈɪnjuːəs jˈɛlz .|0
LJ028-0081.wav|jˈɪɹz lˈeɪɾɚ , wˌɛn ðɪ ˌɑːɹkiːˈɑːlədʒˌɪsts kʊd ɹˈɛdili dɪstˈɪŋɡwɪʃ ðə fˈɔls fɹʌmðə tɹˈuː ,|0
LJ018-0081.wav|hɪz dᵻfˈɛns bˌiːɪŋ ðæt hiː hæd ɪntˈɛndᵻd tə kəmˈɪt sˈuːɪsˌaɪd , bˌʌt ðˈæt , ɔnðɪ ɐpˈɪɹəns ʌv ðɪs ˈɑːfɪsɚ hˌuː hæd ɹˈɔŋd hˌɪm ,|0
LJ021-0066.wav|təɡˌɛðɚ wɪð ɐ ɡɹˈeɪt ˈɪŋkɹiːs ɪnðə pˈeɪɹoʊlz , ðɛɹ hɐz kˈʌm ɐ səbstˈænʃəl ɹˈaɪz ɪnðə tˈoʊɾəl ʌv ɪndˈʌstɹɪəl pɹˈɑːfɪts|0
LJ009-0238.wav|ˈæftɚ ðɪs ðə ʃˈɛɹɪfs sˈɛnt fɔːɹ ɐnˈʌðɚ ɹˈoʊp , bˌʌt ðə spɛktˈeɪɾɚz ˌɪntəfˈɪɹd , ænd ðə mˈæn wʌz kˈæɹid bˈæk tə dʒˈeɪl .|0
LJ005-0079.wav|ænd ɪmpɹˈuːv ðə mˈɔːɹəlz ʌvðə pɹˈɪzənɚz , ænd ʃˌæl ɪnʃˈʊɹ ðə pɹˈɑːpɚ mˈɛʒɚɹ ʌv pˈʌnɪʃmənt tə kənvˈɪktᵻd əfˈɛndɚz .|0
LJ035-0019.wav|dɹˈoʊv tə ðə nɔːɹθwˈɛst kˈɔːɹnɚɹ ʌv ˈɛlm ænd hjˈuːstən , ænd pˈɑːɹkt ɐpɹˈɑːksɪmətli tˈɛn fˈiːt fɹʌmðə tɹˈæfɪk sˈɪɡnəl .|0
LJ036-0174.wav|ðɪs ɪz ðɪ ɐpɹˈɑːksɪmət tˈaɪm hiː ˈɛntɚd ðə ɹˈuːmɪŋhˌaʊs , ɐkˈoːɹdɪŋ tʊ ˈɜːliːn ɹˈɑːbɚts , ðə hˈaʊskiːpɚ ðˈɛɹ .|0
LJ046-0146.wav|ðə kɹaɪtˈiəɹɪə ɪn ɪfˈɛkt pɹˈaɪɚ tə noʊvˈɛmbɚ twˈɛnti tˈuː , nˈaɪntiːn sˈɪksti θɹˈiː , fɔːɹ dɪtˈɜːmɪnɪŋ wˈɛðɚ tʊ ɐksˈɛpt mətˈɪɹiəl fɚðə pˌiːˌɑːɹɹˈɛs dʒˈɛnɚɹəl fˈaɪlz|0
LJ017-0044.wav|ænd ðə dˈiːpɪst æŋzˈaɪəɾi wʌz fˈɛlt ðætðə kɹˈaɪm , ɪf kɹˈaɪm ðˈɛɹ hɐdbɪn , ʃˌʊd biː bɹˈɔːt hˈoʊm tʊ ɪts pˈɜːpɪtɹˌeɪɾɚ .|0
LJ017-0070.wav|bˌʌt hɪz spˈoːɹɾɪŋ ˌɑːpɚɹˈeɪʃənz dɪdnˌɑːt pɹˈɑːspɚ , ænd hiː bɪkˌeɪm ɐ nˈiːdi mˈæn , ˈɔːlweɪz dɹˈɪvən tə dˈɛspɚɹət stɹˈeɪts fɔːɹ kˈæʃ .|0
LJ014-0020.wav|hiː wʌz sˈuːn ˈæftɚwɚdz ɚɹˈɛstᵻd ˌɔn səspˈɪʃən , ænd ɐ sˈɜːtʃ ʌv hɪz lˈɑːdʒɪŋz bɹˈɔːt tə lˈaɪt sˈɛvɹəl ɡˈɑːɹmənts sˈætʃɚɹˌeɪɾᵻd wɪð blˈʌd ;|0
LJ016-0020.wav|hiː nˈɛvɚ ɹˈiːtʃt ðə sˈɪstɚn , bˌʌt fˈɛl bˈæk ˌɪntʊ ðə jˈɑːɹd , ˈɪndʒɚɹɪŋ hɪz lˈɛɡz sᵻvˈɪɹli .|0
LJ045-0230.wav|wˌɛn hiː wʌz fˈaɪnəli ˌæpɹihˈɛndᵻd ɪnðə tˈɛksəs θˈiəɾɚ . ɔːlðˈoʊ ɪɾ ɪz nˌɑːt fˈʊli kɚɹˈɑːbɚɹˌeɪɾᵻd baɪ ˈʌðɚz hˌuː wɜː pɹˈɛzənt ,|0
LJ035-0129.wav|ænd ʃiː mˈʌstɐv ɹˈʌn dˌaʊn ðə stˈɛɹz ɐhˈɛd ʌv ˈɑːswəld ænd wʊd pɹˈɑːbəbli hæv sˈiːn ɔːɹ hˈɜːd hˌɪm .|0
LJ008-0307.wav|ˈæftɚwɚdz ɛkspɹˈɛs ɐ wˈɪʃ tə mˈɜːdɚ ðə ɹᵻkˈoːɹdɚ fɔːɹ hˌævɪŋ kˈɛpt ðˌɛm sˌoʊ lˈɔŋ ɪn səspˈɛns .|0
LJ008-0294.wav|nˌɪɹli ɪndˈɛfɪnətli dᵻfˈɜːd .|0
LJ047-0148.wav|ˌɔn ɑːktˈoʊbɚ twˈɛnti fˈaɪv ,|0
LJ008-0111.wav|ðeɪ ˈɛntɚd ɐ dˈɑːlɚ stˈoʊŋ kˈoʊld ɹˈuːm , dˈɑːlɚɹ ænd wɜː pɹˈɛzəntli dʒˈɔɪnd baɪ ðə pɹˈɪzənɚ .|0
LJ034-0042.wav|ðæt hiː kʊd ˈoʊnli tˈɛstᵻfˌaɪ wɪð sˈɜːtənti ðætðə pɹˈɪnt wʌz lˈɛs ðɐn θɹˈiː dˈeɪz ˈoʊld .|0
LJ037-0234.wav|mˈɪsɪz . mˈɛɹi bɹˈɑːk , ðə wˈaɪf əvə mɪkˈænɪk hˌuː wˈɜːkt æt ðə stˈeɪʃən , wʌz ðɛɹ æt ðə tˈaɪm ænd ʃiː sˈɔː ɐ wˈaɪt mˈeɪl ,|0
LJ040-0002.wav|tʃˈæptɚ sˈɛvən . lˈiː hˈɑːɹvi ˈɑːswəld : bˈækɡɹaʊnd ænd pˈɑːsᵻbəl mˈoʊɾɪvz , pˈɑːɹt wˌʌn .|0
LJ045-0140.wav|ðɪ ˈɑːɹɡjuːmənts hiː jˈuːzd tə dʒˈʌstᵻfˌaɪ hɪz jˈuːs ʌvðɪ ˈeɪliəs sədʒˈɛst ðæt ˈɑːswəld mˌeɪhɐv kˈʌm tə θˈɪŋk ðætðə hˈoʊl wˈɜːld wʌz bᵻkˈʌmɪŋ ɪnvˈɑːlvd|0
LJ012-0035.wav|ðə nˈʌmbɚ ænd nˈeɪmz ˌɔn wˈɑːtʃᵻz , wɜː kˈɛɹfəli ɹᵻmˈuːvd ɔːɹ əblˈɪɾɚɹˌeɪɾᵻd ˈæftɚ ðə ɡˈʊdz pˈæst ˌaʊɾəv hɪz hˈændz .|0
LJ012-0250.wav|ɔnðə sˈɛvənθ dʒuːlˈaɪ , ˈeɪtiːn θˈɜːɾi sˈɛvən ,|0
LJ016-0179.wav|kəntɹˈæktᵻd wɪð ʃˈɛɹɪfs ænd kənvˈiːnɚz tə wˈɜːk baɪ ðə dʒˈɑːb .|0
LJ016-0138.wav|æɾə dˈɪstəns fɹʌmðə pɹˈɪzən .|0
LJ027-0052.wav|ðiːz pɹˈɪnsɪpəlz ʌv həmˈɑːlədʒi ɑːɹ ᵻsˈɛnʃəl tʊ ɐ kɚɹˈɛkt ɪntˌɜːpɹɪtˈeɪʃən ʌvðə fˈækts ʌv mɔːɹfˈɑːlədʒi .|0
LJ031-0134.wav|ˌɔn wˈʌn əkˈeɪʒən mˈɪsɪz . dʒˈɑːnsən , ɐkˈʌmpənid baɪ tˈuː sˈiːkɹᵻt sˈɜːvɪs ˈeɪdʒənts , lˈɛft ðə ɹˈuːm tə sˈiː mˈɪsɪz . kˈɛnədi ænd mˈɪsɪz . kˈɑːnæli .|0
LJ019-0273.wav|wˌɪtʃ sˌɜː dʒˈɑːʃjuːə dʒˈɛb tˈoʊld ðə kəmˈɪɾi hiː kənsˈɪdɚd ðə pɹˈɑːpɚɹ ˈɛlɪmənts ʌv pˈiːnəl dˈɪsɪplˌɪn .|0
LJ014-0110.wav|æt ðə fˈɜːst ðə bˈɑːksᵻz wɜːɹ ɪmpˈaʊndᵻd , ˈoʊpənd , ænd fˈaʊnd tə kəntˈeɪn mˈɛnɪəv oʊkˈɑːnɚz ɪfˈɛkts .|0
LJ034-0160.wav|ˌɔn bɹˈɛnənz sˈʌbsᵻkwənt sˈɜːʔn̩ aɪdˈɛntɪfɪkˈeɪʃən ʌv lˈiː hˈɑːɹvi ˈɑːswəld æz ðə mˈæn hiː sˈɔː fˈaɪɚ ðə ɹˈaɪfəl .|0
LJ038-0199.wav|ᵻlˈɛvən . ɪf aɪɐm ɐlˈaɪv ænd tˈeɪkən pɹˈɪzənɚ ,|0
LJ014-0010.wav|jˈɛt hiː kʊd nˌɑːt ˌoʊvɚkˈʌm ðə stɹˈeɪndʒ fˌæsᵻnˈeɪʃən ɪt hˈæd fɔːɹ hˌɪm , ænd ɹᵻmˈeɪnd baɪ ðə sˈaɪd ʌvðə kˈɔːɹps tˈɪl ðə stɹˈɛtʃɚ kˈeɪm .|0
LJ033-0047.wav|aɪ nˈoʊɾɪst wɛn aɪ wɛnt ˈaʊt ðætðə lˈaɪt wʌz ˈɔn , ˈɛnd kwˈoʊt ,|0
LJ040-0027.wav|hiː wʌz nˈɛvɚ sˈæɾɪsfˌaɪd wɪð ˈɛnɪθˌɪŋ .|0
LJ048-0228.wav|ænd ˈʌðɚz hˌuː wɜː pɹˈɛzənt sˈeɪ ðæt nˈoʊ ˈeɪdʒənt wʌz ɪnˈiːbɹɪˌeɪɾᵻd ɔːɹ ˈæktᵻd ɪmpɹˈɑːpɚli .|0
LJ003-0111.wav|hiː wʌz ɪŋ kˈɑːnsɪkwəns pˌʊt ˌaʊɾəv ðə pɹətˈɛkʃən ʌv ðɛɹ ɪntˈɜːnəl lˈɔː , ˈɛnd kwˈoʊt . ðɛɹ kˈoʊd wʌzɐ sˈʌbdʒɛkt ʌv sˌʌm kjˌʊɹɹɪˈɔsɪɾi .|0
LJ008-0258.wav|lˈɛt mˌiː ɹᵻtɹˈeɪs maɪ stˈɛps , ænd spˈiːk mˈoːɹ ɪn diːtˈeɪl ʌvðə tɹˈiːtmənt ʌvðə kəndˈɛmd ɪn ðoʊz blˈʌdθɜːsti ænd bɹˈuːɾəli ɪndˈɪfɹənt dˈeɪz ,|0
LJ029-0022.wav|ðɪ ɚɹˈɪdʒɪnəl plˈæŋ kˈɔːld fɚðə pɹˈɛzɪdənt tə spˈɛnd ˈoʊnli wˈʌn dˈeɪ ɪnðə stˈeɪt , mˌeɪkɪŋ wˈɜːlwɪnd vˈɪzɪts tə dˈæləs , fˈɔːɹt wˈɜːθ , sˌæn æntˈoʊnɪˌoʊ , ænd hjˈuːstən .|0
LJ004-0045.wav|mˈɪstɚ . stˈɜːdʒᵻz bˈoːɹn , sˌɜː dʒˈeɪmz mˈækɪntˌɑːʃ , sˌɜː dʒˈeɪmz skˈɑːɹlɪt , ænd wˈɪljəm wˈɪlbɚfˌoːɹs .|0
@@ -0,0 +1,554 @@
{
"cells": [
{
"cell_type": "markdown",
"id": "9adb7bd1",
"metadata": {},
"source": [
"# StyleTTS 2 Demo (LJSpeech)\n"
]
},
{
"cell_type": "markdown",
"id": "6108384d",
"metadata": {},
"source": [
"### Utils"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "96e173bf",
"metadata": {},
"outputs": [],
"source": [
"import torch\n",
"torch.manual_seed(0)\n",
"torch.backends.cudnn.benchmark = False\n",
"torch.backends.cudnn.deterministic = True\n",
"\n",
"import random\n",
"random.seed(0)\n",
"\n",
"import numpy as np\n",
"np.random.seed(0)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "da84c60f",
"metadata": {},
"outputs": [],
"source": [
"%cd .."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "5a3ddcc8",
"metadata": {},
"outputs": [],
"source": [
"# load packages\n",
"import time\n",
"import random\n",
"import yaml\n",
"from munch import Munch\n",
"import numpy as np\n",
"import torch\n",
"from torch import nn\n",
"import torch.nn.functional as F\n",
"import torchaudio\n",
"import librosa\n",
"from nltk.tokenize import word_tokenize\n",
"\n",
"from models import *\n",
"from utils import *\n",
"from text_utils import TextCleaner\n",
"textclenaer = TextCleaner()\n",
"\n",
"%matplotlib inline"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "bbdc04c0",
"metadata": {},
"outputs": [],
"source": [
"device = 'cuda' if torch.cuda.is_available() else 'cpu'"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "00ee05e1",
"metadata": {},
"outputs": [],
"source": [
"to_mel = torchaudio.transforms.MelSpectrogram(\n",
" n_mels=80, n_fft=2048, win_length=1200, hop_length=300)\n",
"mean, std = -4, 4\n",
"\n",
"def length_to_mask(lengths):\n",
" mask = torch.arange(lengths.max()).unsqueeze(0).expand(lengths.shape[0], -1).type_as(lengths)\n",
" mask = torch.gt(mask+1, lengths.unsqueeze(1))\n",
" return mask\n",
"\n",
"def preprocess(wave):\n",
" wave_tensor = torch.from_numpy(wave).float()\n",
" mel_tensor = to_mel(wave_tensor)\n",
" mel_tensor = (torch.log(1e-5 + mel_tensor.unsqueeze(0)) - mean) / std\n",
" return mel_tensor\n",
"\n",
"def compute_style(ref_dicts):\n",
" reference_embeddings = {}\n",
" for key, path in ref_dicts.items():\n",
" wave, sr = librosa.load(path, sr=24000)\n",
" audio, index = librosa.effects.trim(wave, top_db=30)\n",
" if sr != 24000:\n",
" audio = librosa.resample(audio, sr, 24000)\n",
" mel_tensor = preprocess(audio).to(device)\n",
"\n",
" with torch.no_grad():\n",
" ref = model.style_encoder(mel_tensor.unsqueeze(1))\n",
" reference_embeddings[key] = (ref.squeeze(1), audio)\n",
" \n",
" return reference_embeddings"
]
},
{
"cell_type": "markdown",
"id": "7b9cecbe",
"metadata": {},
"source": [
"### Load models"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "64fc4c0f",
"metadata": {},
"outputs": [],
"source": [
"# load phonemizer\n",
"import phonemizer\n",
"global_phonemizer = phonemizer.backend.EspeakBackend(language='en-us', preserve_punctuation=True, with_stress=True)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "48e7b644",
"metadata": {},
"outputs": [],
"source": [
"config = yaml.safe_load(open(\"Models/LJSpeech/config.yml\"))\n",
"\n",
"# load pretrained ASR model\n",
"ASR_config = config.get('ASR_config', False)\n",
"ASR_path = config.get('ASR_path', False)\n",
"text_aligner = load_ASR_models(ASR_path, ASR_config)\n",
"\n",
"# load pretrained F0 model\n",
"F0_path = config.get('F0_path', False)\n",
"pitch_extractor = load_F0_models(F0_path)\n",
"\n",
"# load BERT model\n",
"from Utils.PLBERT.util import load_plbert\n",
"BERT_path = config.get('PLBERT_dir', False)\n",
"plbert = load_plbert(BERT_path)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ffc18cf7",
"metadata": {},
"outputs": [],
"source": [
"model = build_model(recursive_munch(config['model_params']), text_aligner, pitch_extractor, plbert)\n",
"_ = [model[key].eval() for key in model]\n",
"_ = [model[key].to(device) for key in model]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "64529d5c",
"metadata": {},
"outputs": [],
"source": [
"params_whole = torch.load(\"Models/LJSpeech/epoch_2nd_00100.pth\", map_location='cpu')\n",
"params = params_whole['net']"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "895d9706",
"metadata": {},
"outputs": [],
"source": [
"for key in model:\n",
" if key in params:\n",
" print('%s loaded' % key)\n",
" try:\n",
" model[key].load_state_dict(params[key])\n",
" except:\n",
" from collections import OrderedDict\n",
" state_dict = params[key]\n",
" new_state_dict = OrderedDict()\n",
" for k, v in state_dict.items():\n",
" name = k[7:] # remove `module.`\n",
" new_state_dict[name] = v\n",
" # load params\n",
" model[key].load_state_dict(new_state_dict, strict=False)\n",
"# except:\n",
"# _load(params[key], model[key])\n",
"_ = [model[key].eval() for key in model]"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c1a59db2",
"metadata": {},
"outputs": [],
"source": [
"from Modules.diffusion.sampler import DiffusionSampler, ADPM2Sampler, KarrasSchedule"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "e30985ab",
"metadata": {},
"outputs": [],
"source": [
"sampler = DiffusionSampler(\n",
" model.diffusion.diffusion,\n",
" sampler=ADPM2Sampler(),\n",
" sigma_schedule=KarrasSchedule(sigma_min=0.0001, sigma_max=3.0, rho=9.0), # empirical parameters\n",
" clamp=False\n",
")"
]
},
{
"cell_type": "markdown",
"id": "b803110e",
"metadata": {},
"source": [
"### Synthesize speech"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "24655f46",
"metadata": {},
"outputs": [],
"source": [
"# synthesize a text\n",
"text = ''' StyleTTS 2 is a text-to-speech model that leverages style diffusion and adversarial training with large speech language models to achieve human-level text-to-speech synthesis. '''"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ca57469c",
"metadata": {},
"outputs": [],
"source": [
"def inference(text, noise, diffusion_steps=5, embedding_scale=1):\n",
" text = text.strip()\n",
" text = text.replace('\"', '')\n",
" ps = global_phonemizer.phonemize([text])\n",
" ps = word_tokenize(ps[0])\n",
" ps = ' '.join(ps)\n",
"\n",
" tokens = textclenaer(ps)\n",
" tokens.insert(0, 0)\n",
" tokens = torch.LongTensor(tokens).to(device).unsqueeze(0)\n",
" \n",
" with torch.no_grad():\n",
" input_lengths = torch.LongTensor([tokens.shape[-1]]).to(tokens.device)\n",
" text_mask = length_to_mask(input_lengths).to(tokens.device)\n",
"\n",
" t_en = model.text_encoder(tokens, input_lengths, text_mask)\n",
" bert_dur = model.bert(tokens, attention_mask=(~text_mask).int())\n",
" d_en = model.bert_encoder(bert_dur).transpose(-1, -2) \n",
"\n",
" s_pred = sampler(noise, \n",
" embedding=bert_dur[0].unsqueeze(0), num_steps=diffusion_steps,\n",
" embedding_scale=embedding_scale).squeeze(0)\n",
"\n",
" s = s_pred[:, 128:]\n",
" ref = s_pred[:, :128]\n",
"\n",
" d = model.predictor.text_encoder(d_en, s, input_lengths, text_mask)\n",
"\n",
" x, _ = model.predictor.lstm(d)\n",
" duration = model.predictor.duration_proj(x)\n",
" duration = torch.sigmoid(duration).sum(axis=-1)\n",
" pred_dur = torch.round(duration.squeeze()).clamp(min=1)\n",
"\n",
" pred_dur[-1] += 5\n",
"\n",
" pred_aln_trg = torch.zeros(input_lengths, int(pred_dur.sum().data))\n",
" c_frame = 0\n",
" for i in range(pred_aln_trg.size(0)):\n",
" pred_aln_trg[i, c_frame:c_frame + int(pred_dur[i].data)] = 1\n",
" c_frame += int(pred_dur[i].data)\n",
"\n",
" # encode prosody\n",
" en = (d.transpose(-1, -2) @ pred_aln_trg.unsqueeze(0).to(device))\n",
" F0_pred, N_pred = model.predictor.F0Ntrain(en, s)\n",
" out = model.decoder((t_en @ pred_aln_trg.unsqueeze(0).to(device)), \n",
" F0_pred, N_pred, ref.squeeze().unsqueeze(0))\n",
" \n",
" return out.squeeze().cpu().numpy()"
]
},
{
"cell_type": "markdown",
"id": "d438ef4f",
"metadata": {},
"source": [
"#### Basic synthesis (5 diffusion steps)"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "d3d7f7d5",
"metadata": {
"scrolled": true
},
"outputs": [],
"source": [
"start = time.time()\n",
"noise = torch.randn(1,1,256).to(device)\n",
"wav = inference(text, noise, diffusion_steps=5, embedding_scale=1)\n",
"rtf = (time.time() - start) / (len(wav) / 24000)\n",
"print(f\"RTF = {rtf:5f}\")\n",
"import IPython.display as ipd\n",
"display(ipd.Audio(wav, rate=24000))"
]
},
{
"cell_type": "markdown",
"id": "2d5d9df0",
"metadata": {},
"source": [
"#### With higher diffusion steps (more diverse)\n",
"Since the sampler is ancestral, the higher the stpes, the more diverse the samples are, with the cost of slower synthesis speed."
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "a10129fd",
"metadata": {},
"outputs": [],
"source": [
"start = time.time()\n",
"noise = torch.randn(1,1,256).to(device)\n",
"wav = inference(text, noise, diffusion_steps=10, embedding_scale=1)\n",
"rtf = (time.time() - start) / (len(wav) / 24000)\n",
"print(f\"RTF = {rtf:5f}\")\n",
"import IPython.display as ipd\n",
"display(ipd.Audio(wav, rate=24000))"
]
},
{
"cell_type": "markdown",
"id": "1877ea15",
"metadata": {},
"source": [
"### Speech expressiveness\n",
"The following section recreates the samples shown in [Section 6](https://styletts2.github.io/#emo) of the demo page."
]
},
{
"cell_type": "markdown",
"id": "4c4777b7",
"metadata": {},
"source": [
"#### With embedding_scale=1\n",
"This is the classifier-free guidance scale. The higher the scale, the more conditional the style is to the input text and hence more emotional. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "c29ea2f0",
"metadata": {},
"outputs": [],
"source": [
"texts = {}\n",
"texts['Happy'] = \"We are happy to invite you to join us on a journey to the past, where we will visit the most amazing monuments ever built by human hands.\"\n",
"texts['Sad'] = \"I am sorry to say that we have suffered a severe setback in our efforts to restore prosperity and confidence.\"\n",
"texts['Angry'] = \"The field of astronomy is a joke! Its theories are based on flawed observations and biased interpretations!\"\n",
"texts['Surprised'] = \"I can't believe it! You mean to tell me that you have discovered a new species of bacteria in this pond?\"\n",
"\n",
"for k,v in texts.items():\n",
" noise = torch.randn(1,1,256).to(device)\n",
" wav = inference(v, noise, diffusion_steps=10, embedding_scale=1)\n",
" print(k + \": \")\n",
" display(ipd.Audio(wav, rate=24000, normalize=False))"
]
},
{
"cell_type": "markdown",
"id": "3c89499f",
"metadata": {},
"source": [
"#### With embedding_scale=2"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "f73be3aa",
"metadata": {},
"outputs": [],
"source": [
"texts = {}\n",
"texts['Happy'] = \"We are happy to invite you to join us on a journey to the past, where we will visit the most amazing monuments ever built by human hands.\"\n",
"texts['Sad'] = \"I am sorry to say that we have suffered a severe setback in our efforts to restore prosperity and confidence.\"\n",
"texts['Angry'] = \"The field of astronomy is a joke! Its theories are based on flawed observations and biased interpretations!\"\n",
"texts['Surprised'] = \"I can't believe it! You mean to tell me that you have discovered a new species of bacteria in this pond?\"\n",
"\n",
"for k,v in texts.items():\n",
" noise = torch.randn(1,1,256).to(device)\n",
" wav = inference(v, noise, diffusion_steps=10, embedding_scale=2) # embedding_scale=2 for more pronounced emotion\n",
" print(k + \": \")\n",
" display(ipd.Audio(wav, rate=24000, normalize=False))"
]
},
{
"cell_type": "markdown",
"id": "9320da63",
"metadata": {},
"source": [
"### Long-form generation\n",
"This section includes basic implementation of Algorithm 1 in the paper for consistent longform audio generation. The example passage is taken from [Section 5](https://styletts2.github.io/#long) of the demo page. "
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "cdd4db51",
"metadata": {},
"outputs": [],
"source": [
"passage = '''If the supply of fruit is greater than the family needs, it may be made a source of income by sending the fresh fruit to the market if there is one near enough, or by preserving, canning, and making jelly for sale. To make such an enterprise a success the fruit and work must be first class. There is magic in the word \"Homemade,\" when the product appeals to the eye and the palate; but many careless and incompetent people have found to their sorrow that this word has not magic enough to float inferior goods on the market. As a rule large canning and preserving establishments are clean and have the best appliances, and they employ chemists and skilled labor. The home product must be very good to compete with the attractive goods that are sent out from such establishments. Yet for first-class homemade products there is a market in all large cities. All first-class grocers have customers who purchase such goods.'''"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "ebb941c8",
"metadata": {},
"outputs": [],
"source": [
"def LFinference(text, s_prev, noise, alpha=0.7, diffusion_steps=5, embedding_scale=1):\n",
" text = text.strip()\n",
" text = text.replace('\"', '')\n",
" ps = global_phonemizer.phonemize([text])\n",
" ps = word_tokenize(ps[0])\n",
" ps = ' '.join(ps)\n",
"\n",
" tokens = textclenaer(ps)\n",
" tokens.insert(0, 0)\n",
" tokens = torch.LongTensor(tokens).to(device).unsqueeze(0)\n",
" \n",
" with torch.no_grad():\n",
" input_lengths = torch.LongTensor([tokens.shape[-1]]).to(tokens.device)\n",
" text_mask = length_to_mask(input_lengths).to(tokens.device)\n",
"\n",
" t_en = model.text_encoder(tokens, input_lengths, text_mask)\n",
" bert_dur = model.bert(tokens, attention_mask=(~text_mask).int())\n",
" d_en = model.bert_encoder(bert_dur).transpose(-1, -2) \n",
"\n",
" s_pred = sampler(noise, \n",
" embedding=bert_dur[0].unsqueeze(0), num_steps=diffusion_steps,\n",
" embedding_scale=embedding_scale).squeeze(0)\n",
" \n",
" if s_prev is not None:\n",
" # convex combination of previous and current style\n",
" s_pred = alpha * s_prev + (1 - alpha) * s_pred\n",
" \n",
" s = s_pred[:, 128:]\n",
" ref = s_pred[:, :128]\n",
"\n",
" d = model.predictor.text_encoder(d_en, s, input_lengths, text_mask)\n",
"\n",
" x, _ = model.predictor.lstm(d)\n",
" duration = model.predictor.duration_proj(x)\n",
" duration = torch.sigmoid(duration).sum(axis=-1)\n",
" pred_dur = torch.round(duration.squeeze()).clamp(min=1)\n",
"\n",
" pred_aln_trg = torch.zeros(input_lengths, int(pred_dur.sum().data))\n",
" c_frame = 0\n",
" for i in range(pred_aln_trg.size(0)):\n",
" pred_aln_trg[i, c_frame:c_frame + int(pred_dur[i].data)] = 1\n",
" c_frame += int(pred_dur[i].data)\n",
"\n",
" # encode prosody\n",
" en = (d.transpose(-1, -2) @ pred_aln_trg.unsqueeze(0).to(device))\n",
" F0_pred, N_pred = model.predictor.F0Ntrain(en, s)\n",
" out = model.decoder((t_en @ pred_aln_trg.unsqueeze(0).to(device)), \n",
" F0_pred, N_pred, ref.squeeze().unsqueeze(0))\n",
" \n",
" return out.squeeze().cpu().numpy(), s_pred"
]
},
{
"cell_type": "code",
"execution_count": null,
"id": "7ca0ef2e",
"metadata": {},
"outputs": [],
"source": [
"sentences = passage.split('.') # simple split by comma\n",
"wavs = []\n",
"s_prev = None\n",
"for text in sentences:\n",
" if text.strip() == \"\": continue\n",
" text += '.' # add it back\n",
" noise = torch.randn(1,1,256).to(device)\n",
" wav, s_prev = LFinference(text, s_prev, noise, alpha=0.7, diffusion_steps=10, embedding_scale=1.5)\n",
" wavs.append(wav)\n",
"display(ipd.Audio(np.concatenate(wavs), rate=24000, normalize=False))"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "NLP",
"language": "python",
"name": "nlp"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.9.7"
}
},
"nbformat": 4,
"nbformat_minor": 5
}
File diff suppressed because it is too large Load Diff
+21
View File
@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2023 Aaron (Yinghao) Li
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
@@ -0,0 +1,110 @@
log_dir: "Models/LJSpeech"
save_freq: 5
log_interval: 10
device: "cuda"
epochs: 50 # number of finetuning epoch (1 hour of data)
batch_size: 8
max_len: 400 # maximum number of frames
pretrained_model: "Models/LibriTTS/epochs_2nd_00020.pth"
second_stage_load_pretrained: true # set to true if the pre-trained model is for 2nd stage
load_only_params: true # set to true if do not want to load epoch numbers and optimizer parameters
F0_path: "Utils/JDC/bst.t7"
ASR_config: "Utils/ASR/config.yml"
ASR_path: "Utils/ASR/epoch_00080.pth"
PLBERT_dir: 'Utils/PLBERT/'
data_params:
train_data: "Data/train_harness.txt"
val_data: "Data/val_harness.txt"
root_path: ""
OOD_data: "Data/OOD_harness.txt"
min_length: 50 # sample until texts with this size are obtained for OOD texts
preprocess_params:
sr: 24000
spect_params:
n_fft: 2048
win_length: 1200
hop_length: 300
model_params:
multispeaker: true
dim_in: 64
hidden_dim: 512
max_conv_dim: 512
n_layer: 3
n_mels: 80
n_token: 178 # number of phoneme tokens
max_dur: 50 # maximum duration of a single phoneme
style_dim: 128 # style vector size
dropout: 0.2
# config for decoder
decoder:
type: 'hifigan' # either hifigan or istftnet
resblock_kernel_sizes: [3,7,11]
upsample_rates : [10,5,3,2]
upsample_initial_channel: 512
resblock_dilation_sizes: [[1,3,5], [1,3,5], [1,3,5]]
upsample_kernel_sizes: [20,10,6,4]
# speech language model config
slm:
model: 'microsoft/wavlm-base-plus'
sr: 16000 # sampling rate of SLM
hidden: 768 # hidden size of SLM
nlayers: 13 # number of layers of SLM
initial_channel: 64 # initial channels of SLM discriminator head
# style diffusion model config
diffusion:
embedding_mask_proba: 0.1
# transformer config
transformer:
num_layers: 3
num_heads: 8
head_features: 64
multiplier: 2
# diffusion distribution config
dist:
sigma_data: 0.2 # placeholder for estimate_sigma_data set to false
estimate_sigma_data: true # estimate sigma_data from the current batch if set to true
mean: -3.0
std: 1.0
loss_params:
lambda_mel: 5. # mel reconstruction loss
lambda_gen: 1. # generator loss
lambda_slm: 1. # slm feature matching loss
lambda_mono: 1. # monotonic alignment loss (TMA)
lambda_s2s: 1. # sequence-to-sequence loss (TMA)
lambda_F0: 1. # F0 reconstruction loss
lambda_norm: 1. # norm reconstruction loss
lambda_dur: 1. # duration loss
lambda_ce: 20. # duration predictor probability output CE loss
lambda_sty: 1. # style reconstruction loss
lambda_diff: 1. # score matching loss
diff_epoch: 10 # style diffusion starting epoch
joint_epoch: 30 # joint training starting epoch
optimizer_params:
lr: 0.0001 # general learning rate
bert_lr: 0.00001 # learning rate for PLBERT
ft_lr: 0.0001 # learning rate for acoustic modules
slmadv_params:
min_len: 400 # minimum length of samples
max_len: 500 # maximum length of samples
batch_percentage: 0.5 # to prevent out of memory, only use half of the original batch size
iter: 10 # update the discriminator every this iterations of generator update
thresh: 5 # gradient norm above which the gradient is scaled
scale: 0.01 # gradient scaling factor for predictors from SLM discriminators
sig: 1.5 # sigma for differentiable duration modeling
@@ -0,0 +1 @@
epochs_2nd_00020.pth filter=lfs diff=lfs merge=lfs -text
@@ -0,0 +1,21 @@
{ASR_config: Utils/ASR/config.yml, ASR_path: Utils/ASR/epoch_00080.pth, F0_path: Utils/JDC/bst.t7,
PLBERT_dir: Utils/PLBERT/, batch_size: 8, data_params: {OOD_data: Data/OOD_texts.txt,
min_length: 50, root_path: '', train_data: Data/train_list.txt, val_data: Data/val_list.txt},
device: cuda, epochs_1st: 40, epochs_2nd: 25, first_stage_path: first_stage.pth,
load_only_params: false, log_dir: Models/LibriTTS, log_interval: 10, loss_params: {
TMA_epoch: 4, diff_epoch: 0, joint_epoch: 0, lambda_F0: 1.0, lambda_ce: 20.0,
lambda_diff: 1.0, lambda_dur: 1.0, lambda_gen: 1.0, lambda_mel: 5.0, lambda_mono: 1.0,
lambda_norm: 1.0, lambda_s2s: 1.0, lambda_slm: 1.0, lambda_sty: 1.0}, max_len: 300,
model_params: {decoder: {resblock_dilation_sizes: [[1, 3, 5], [1, 3, 5], [1, 3,
5]], resblock_kernel_sizes: [3, 7, 11], type: hifigan, upsample_initial_channel: 512,
upsample_kernel_sizes: [20, 10, 6, 4], upsample_rates: [10, 5, 3, 2]}, diffusion: {
dist: {estimate_sigma_data: true, mean: -3.0, sigma_data: 0.19926648961191362,
std: 1.0}, embedding_mask_proba: 0.1, transformer: {head_features: 64, multiplier: 2,
num_heads: 8, num_layers: 3}}, dim_in: 64, dropout: 0.2, hidden_dim: 512,
max_conv_dim: 512, max_dur: 50, multispeaker: true, n_layer: 3, n_mels: 80, n_token: 178,
slm: {hidden: 768, initial_channel: 64, model: microsoft/wavlm-base-plus, nlayers: 13,
sr: 16000}, style_dim: 128}, optimizer_params: {bert_lr: 1.0e-05, ft_lr: 1.0e-05,
lr: 0.0001}, preprocess_params: {spect_params: {hop_length: 300, n_fft: 2048,
win_length: 1200}, sr: 24000}, pretrained_model: Models/LibriTTS/epoch_2nd_00002.pth,
save_freq: 1, second_stage_load_pretrained: true, slmadv_params: {batch_percentage: 0.5,
iter: 20, max_len: 500, min_len: 400, scale: 0.01, sig: 1.5, thresh: 5}}
@@ -0,0 +1,111 @@
log_dir: "Models/LJSpeech"
save_freq: 5
log_interval: 10
device: "cuda"
epochs: 50 # number of finetuning epoch (1 hour of data)
batch_size: 1
max_len: 400 # maximum number of frames
pretrained_model: "Models/LibriTTS/epochs_2nd_00020.pth"
second_stage_load_pretrained: true # set to true if the pre-trained model is for 2nd stage
load_only_params: true # set to true if do not want to load epoch numbers and optimizer parameters
F0_path: "Utils/JDC/bst.t7"
ASR_config: "Utils/ASR/config.yml"
ASR_path: "Utils/ASR/epoch_00080.pth"
PLBERT_dir: 'Utils/PLBERT/'
data_params:
train_data: "Data/train_harness.txt"
val_data: "Data/val_harness.txt"
root_path: ""
OOD_data: "Data/OOD_harness.txt"
min_length: 50 # sample until texts with this size are obtained for OOD texts
preprocess_params:
sr: 24000
spect_params:
n_fft: 2048
win_length: 1200
hop_length: 300
model_params:
multispeaker: true
dim_in: 64
hidden_dim: 512
max_conv_dim: 512
n_layer: 3
n_mels: 80
n_token: 178 # number of phoneme tokens
max_dur: 50 # maximum duration of a single phoneme
style_dim: 128 # style vector size
dropout: 0.2
# config for decoder
decoder:
type: 'hifigan' # either hifigan or istftnet
resblock_kernel_sizes: [3,7,11]
upsample_rates : [10,5,3,2]
upsample_initial_channel: 512
resblock_dilation_sizes: [[1,3,5], [1,3,5], [1,3,5]]
upsample_kernel_sizes: [20,10,6,4]
# speech language model config
slm:
model: 'microsoft/wavlm-base-plus'
sr: 16000 # sampling rate of SLM
hidden: 768 # hidden size of SLM
nlayers: 13 # number of layers of SLM
initial_channel: 64 # initial channels of SLM discriminator head
# style diffusion model config
diffusion:
embedding_mask_proba: 0.1
# transformer config
transformer:
num_layers: 3
num_heads: 8
head_features: 64
multiplier: 2
# diffusion distribution config
dist:
sigma_data: 0.2 # placeholder for estimate_sigma_data set to false
estimate_sigma_data: true # estimate sigma_data from the current batch if set to true
mean: -3.0
std: 1.0
loss_params:
lambda_mel: 5. # mel reconstruction loss
lambda_gen: 1. # generator loss
lambda_slm: 1. # slm feature matching loss
lambda_mono: 1. # monotonic alignment loss (TMA)
lambda_s2s: 1. # sequence-to-sequence loss (TMA)
lambda_F0: 1. # F0 reconstruction loss
lambda_norm: 1. # norm reconstruction loss
lambda_dur: 1. # duration loss
lambda_ce: 20. # duration predictor probability output CE loss
lambda_sty: 1. # style reconstruction loss
lambda_diff: 1. # score matching loss
diff_epoch: 10 # style diffusion starting epoch
joint_epoch: 30 # joint training starting epoch
optimizer_params:
lr: 0.0001 # general learning rate
bert_lr: 0.00001 # learning rate for PLBERT
ft_lr: 0.0001 # learning rate for acoustic modules
slmadv_params:
min_len: 400 # minimum length of samples
max_len: 500 # maximum length of samples
batch_percentage: 0.5 # to prevent out of memory, only use half of the original batch size
iter: 10 # update the discriminator every this iterations of generator update
thresh: 5 # gradient norm above which the gradient is scaled
scale: 0.01 # gradient scaling factor for predictors from SLM discriminators
sig: 1.5 # sigma for differentiable duration modeling
Binary file not shown.
+1
View File
@@ -0,0 +1 @@
@@ -0,0 +1 @@
@@ -0,0 +1,94 @@
from math import pi
from random import randint
from typing import Any, Optional, Sequence, Tuple, Union
import torch
from einops import rearrange
from torch import Tensor, nn
from tqdm import tqdm
from .utils import *
from .sampler import *
"""
Diffusion Classes (generic for 1d data)
"""
class Model1d(nn.Module):
def __init__(self, unet_type: str = "base", **kwargs):
super().__init__()
diffusion_kwargs, kwargs = groupby("diffusion_", kwargs)
self.unet = None
self.diffusion = None
def forward(self, x: Tensor, **kwargs) -> Tensor:
return self.diffusion(x, **kwargs)
def sample(self, *args, **kwargs) -> Tensor:
return self.diffusion.sample(*args, **kwargs)
"""
Audio Diffusion Classes (specific for 1d audio data)
"""
def get_default_model_kwargs():
return dict(
channels=128,
patch_size=16,
multipliers=[1, 2, 4, 4, 4, 4, 4],
factors=[4, 4, 4, 2, 2, 2],
num_blocks=[2, 2, 2, 2, 2, 2],
attentions=[0, 0, 0, 1, 1, 1, 1],
attention_heads=8,
attention_features=64,
attention_multiplier=2,
attention_use_rel_pos=False,
diffusion_type="v",
diffusion_sigma_distribution=UniformDistribution(),
)
def get_default_sampling_kwargs():
return dict(sigma_schedule=LinearSchedule(), sampler=VSampler(), clamp=True)
class AudioDiffusionModel(Model1d):
def __init__(self, **kwargs):
super().__init__(**{**get_default_model_kwargs(), **kwargs})
def sample(self, *args, **kwargs):
return super().sample(*args, **{**get_default_sampling_kwargs(), **kwargs})
class AudioDiffusionConditional(Model1d):
def __init__(
self,
embedding_features: int,
embedding_max_length: int,
embedding_mask_proba: float = 0.1,
**kwargs,
):
self.embedding_mask_proba = embedding_mask_proba
default_kwargs = dict(
**get_default_model_kwargs(),
unet_type="cfg",
context_embedding_features=embedding_features,
context_embedding_max_length=embedding_max_length,
)
super().__init__(**{**default_kwargs, **kwargs})
def forward(self, *args, **kwargs):
default_kwargs = dict(embedding_mask_proba=self.embedding_mask_proba)
return super().forward(*args, **{**default_kwargs, **kwargs})
def sample(self, *args, **kwargs):
default_kwargs = dict(
**get_default_sampling_kwargs(),
embedding_scale=5.0,
)
return super().sample(*args, **{**default_kwargs, **kwargs})
@@ -0,0 +1,693 @@
from math import floor, log, pi
from typing import Any, List, Optional, Sequence, Tuple, Union
from .utils import *
import torch
import torch.nn as nn
from einops import rearrange, reduce, repeat
from einops.layers.torch import Rearrange
from einops_exts import rearrange_many
from torch import Tensor, einsum
"""
Utils
"""
class AdaLayerNorm(nn.Module):
def __init__(self, style_dim, channels, eps=1e-5):
super().__init__()
self.channels = channels
self.eps = eps
self.fc = nn.Linear(style_dim, channels*2)
def forward(self, x, s):
x = x.transpose(-1, -2)
x = x.transpose(1, -1)
h = self.fc(s)
h = h.view(h.size(0), h.size(1), 1)
gamma, beta = torch.chunk(h, chunks=2, dim=1)
gamma, beta = gamma.transpose(1, -1), beta.transpose(1, -1)
x = F.layer_norm(x, (self.channels,), eps=self.eps)
x = (1 + gamma) * x + beta
return x.transpose(1, -1).transpose(-1, -2)
class StyleTransformer1d(nn.Module):
def __init__(
self,
num_layers: int,
channels: int,
num_heads: int,
head_features: int,
multiplier: int,
use_context_time: bool = True,
use_rel_pos: bool = False,
context_features_multiplier: int = 1,
rel_pos_num_buckets: Optional[int] = None,
rel_pos_max_distance: Optional[int] = None,
context_features: Optional[int] = None,
context_embedding_features: Optional[int] = None,
embedding_max_length: int = 512,
):
super().__init__()
self.blocks = nn.ModuleList(
[
StyleTransformerBlock(
features=channels + context_embedding_features,
head_features=head_features,
num_heads=num_heads,
multiplier=multiplier,
style_dim=context_features,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
for i in range(num_layers)
]
)
self.to_out = nn.Sequential(
Rearrange("b t c -> b c t"),
nn.Conv1d(
in_channels=channels + context_embedding_features,
out_channels=channels,
kernel_size=1,
),
)
use_context_features = exists(context_features)
self.use_context_features = use_context_features
self.use_context_time = use_context_time
if use_context_time or use_context_features:
context_mapping_features = channels + context_embedding_features
self.to_mapping = nn.Sequential(
nn.Linear(context_mapping_features, context_mapping_features),
nn.GELU(),
nn.Linear(context_mapping_features, context_mapping_features),
nn.GELU(),
)
if use_context_time:
assert exists(context_mapping_features)
self.to_time = nn.Sequential(
TimePositionalEmbedding(
dim=channels, out_features=context_mapping_features
),
nn.GELU(),
)
if use_context_features:
assert exists(context_features) and exists(context_mapping_features)
self.to_features = nn.Sequential(
nn.Linear(
in_features=context_features, out_features=context_mapping_features
),
nn.GELU(),
)
self.fixed_embedding = FixedEmbedding(
max_length=embedding_max_length, features=context_embedding_features
)
def get_mapping(
self, time: Optional[Tensor] = None, features: Optional[Tensor] = None
) -> Optional[Tensor]:
"""Combines context time features and features into mapping"""
items, mapping = [], None
# Compute time features
if self.use_context_time:
assert_message = "use_context_time=True but no time features provided"
assert exists(time), assert_message
items += [self.to_time(time)]
# Compute features
if self.use_context_features:
assert_message = "context_features exists but no features provided"
assert exists(features), assert_message
items += [self.to_features(features)]
# Compute joint mapping
if self.use_context_time or self.use_context_features:
mapping = reduce(torch.stack(items), "n b m -> b m", "sum")
mapping = self.to_mapping(mapping)
return mapping
def run(self, x, time, embedding, features):
mapping = self.get_mapping(time, features)
x = torch.cat([x.expand(-1, embedding.size(1), -1), embedding], axis=-1)
mapping = mapping.unsqueeze(1).expand(-1, embedding.size(1), -1)
for block in self.blocks:
x = x + mapping
x = block(x, features)
x = x.mean(axis=1).unsqueeze(1)
x = self.to_out(x)
x = x.transpose(-1, -2)
return x
def forward(self, x: Tensor,
time: Tensor,
embedding_mask_proba: float = 0.0,
embedding: Optional[Tensor] = None,
features: Optional[Tensor] = None,
embedding_scale: float = 1.0) -> Tensor:
b, device = embedding.shape[0], embedding.device
fixed_embedding = self.fixed_embedding(embedding)
if embedding_mask_proba > 0.0:
# Randomly mask embedding
batch_mask = rand_bool(
shape=(b, 1, 1), proba=embedding_mask_proba, device=device
)
embedding = torch.where(batch_mask, fixed_embedding, embedding)
if embedding_scale != 1.0:
# Compute both normal and fixed embedding outputs
out = self.run(x, time, embedding=embedding, features=features)
out_masked = self.run(x, time, embedding=fixed_embedding, features=features)
# Scale conditional output using classifier-free guidance
return out_masked + (out - out_masked) * embedding_scale
else:
return self.run(x, time, embedding=embedding, features=features)
return x
class StyleTransformerBlock(nn.Module):
def __init__(
self,
features: int,
num_heads: int,
head_features: int,
style_dim: int,
multiplier: int,
use_rel_pos: bool,
rel_pos_num_buckets: Optional[int] = None,
rel_pos_max_distance: Optional[int] = None,
context_features: Optional[int] = None,
):
super().__init__()
self.use_cross_attention = exists(context_features) and context_features > 0
self.attention = StyleAttention(
features=features,
style_dim=style_dim,
num_heads=num_heads,
head_features=head_features,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
if self.use_cross_attention:
self.cross_attention = StyleAttention(
features=features,
style_dim=style_dim,
num_heads=num_heads,
head_features=head_features,
context_features=context_features,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
self.feed_forward = FeedForward(features=features, multiplier=multiplier)
def forward(self, x: Tensor, s: Tensor, *, context: Optional[Tensor] = None) -> Tensor:
x = self.attention(x, s) + x
if self.use_cross_attention:
x = self.cross_attention(x, s, context=context) + x
x = self.feed_forward(x) + x
return x
class StyleAttention(nn.Module):
def __init__(
self,
features: int,
*,
style_dim: int,
head_features: int,
num_heads: int,
context_features: Optional[int] = None,
use_rel_pos: bool,
rel_pos_num_buckets: Optional[int] = None,
rel_pos_max_distance: Optional[int] = None,
):
super().__init__()
self.context_features = context_features
mid_features = head_features * num_heads
context_features = default(context_features, features)
self.norm = AdaLayerNorm(style_dim, features)
self.norm_context = AdaLayerNorm(style_dim, context_features)
self.to_q = nn.Linear(
in_features=features, out_features=mid_features, bias=False
)
self.to_kv = nn.Linear(
in_features=context_features, out_features=mid_features * 2, bias=False
)
self.attention = AttentionBase(
features,
num_heads=num_heads,
head_features=head_features,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
def forward(self, x: Tensor, s: Tensor, *, context: Optional[Tensor] = None) -> Tensor:
assert_message = "You must provide a context when using context_features"
assert not self.context_features or exists(context), assert_message
# Use context if provided
context = default(context, x)
# Normalize then compute q from input and k,v from context
x, context = self.norm(x, s), self.norm_context(context, s)
q, k, v = (self.to_q(x), *torch.chunk(self.to_kv(context), chunks=2, dim=-1))
# Compute and return attention
return self.attention(q, k, v)
class Transformer1d(nn.Module):
def __init__(
self,
num_layers: int,
channels: int,
num_heads: int,
head_features: int,
multiplier: int,
use_context_time: bool = True,
use_rel_pos: bool = False,
context_features_multiplier: int = 1,
rel_pos_num_buckets: Optional[int] = None,
rel_pos_max_distance: Optional[int] = None,
context_features: Optional[int] = None,
context_embedding_features: Optional[int] = None,
embedding_max_length: int = 512,
):
super().__init__()
self.blocks = nn.ModuleList(
[
TransformerBlock(
features=channels + context_embedding_features,
head_features=head_features,
num_heads=num_heads,
multiplier=multiplier,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
for i in range(num_layers)
]
)
self.to_out = nn.Sequential(
Rearrange("b t c -> b c t"),
nn.Conv1d(
in_channels=channels + context_embedding_features,
out_channels=channels,
kernel_size=1,
),
)
use_context_features = exists(context_features)
self.use_context_features = use_context_features
self.use_context_time = use_context_time
if use_context_time or use_context_features:
context_mapping_features = channels + context_embedding_features
self.to_mapping = nn.Sequential(
nn.Linear(context_mapping_features, context_mapping_features),
nn.GELU(),
nn.Linear(context_mapping_features, context_mapping_features),
nn.GELU(),
)
if use_context_time:
assert exists(context_mapping_features)
self.to_time = nn.Sequential(
TimePositionalEmbedding(
dim=channels, out_features=context_mapping_features
),
nn.GELU(),
)
if use_context_features:
assert exists(context_features) and exists(context_mapping_features)
self.to_features = nn.Sequential(
nn.Linear(
in_features=context_features, out_features=context_mapping_features
),
nn.GELU(),
)
self.fixed_embedding = FixedEmbedding(
max_length=embedding_max_length, features=context_embedding_features
)
def get_mapping(
self, time: Optional[Tensor] = None, features: Optional[Tensor] = None
) -> Optional[Tensor]:
"""Combines context time features and features into mapping"""
items, mapping = [], None
# Compute time features
if self.use_context_time:
assert_message = "use_context_time=True but no time features provided"
assert exists(time), assert_message
items += [self.to_time(time)]
# Compute features
if self.use_context_features:
assert_message = "context_features exists but no features provided"
assert exists(features), assert_message
items += [self.to_features(features)]
# Compute joint mapping
if self.use_context_time or self.use_context_features:
mapping = reduce(torch.stack(items), "n b m -> b m", "sum")
mapping = self.to_mapping(mapping)
return mapping
def run(self, x, time, embedding, features):
mapping = self.get_mapping(time, features)
x = torch.cat([x.expand(-1, embedding.size(1), -1), embedding], axis=-1)
mapping = mapping.unsqueeze(1).expand(-1, embedding.size(1), -1)
for block in self.blocks:
x = x + mapping
x = block(x)
x = x.mean(axis=1).unsqueeze(1)
x = self.to_out(x)
x = x.transpose(-1, -2)
return x
def forward(self, x: Tensor,
time: Tensor,
embedding_mask_proba: float = 0.0,
embedding: Optional[Tensor] = None,
features: Optional[Tensor] = None,
embedding_scale: float = 1.0) -> Tensor:
b, device = embedding.shape[0], embedding.device
fixed_embedding = self.fixed_embedding(embedding)
if embedding_mask_proba > 0.0:
# Randomly mask embedding
batch_mask = rand_bool(
shape=(b, 1, 1), proba=embedding_mask_proba, device=device
)
embedding = torch.where(batch_mask, fixed_embedding, embedding)
if embedding_scale != 1.0:
# Compute both normal and fixed embedding outputs
out = self.run(x, time, embedding=embedding, features=features)
out_masked = self.run(x, time, embedding=fixed_embedding, features=features)
# Scale conditional output using classifier-free guidance
return out_masked + (out - out_masked) * embedding_scale
else:
return self.run(x, time, embedding=embedding, features=features)
return x
"""
Attention Components
"""
class RelativePositionBias(nn.Module):
def __init__(self, num_buckets: int, max_distance: int, num_heads: int):
super().__init__()
self.num_buckets = num_buckets
self.max_distance = max_distance
self.num_heads = num_heads
self.relative_attention_bias = nn.Embedding(num_buckets, num_heads)
@staticmethod
def _relative_position_bucket(
relative_position: Tensor, num_buckets: int, max_distance: int
):
num_buckets //= 2
ret = (relative_position >= 0).to(torch.long) * num_buckets
n = torch.abs(relative_position)
max_exact = num_buckets // 2
is_small = n < max_exact
val_if_large = (
max_exact
+ (
torch.log(n.float() / max_exact)
/ log(max_distance / max_exact)
* (num_buckets - max_exact)
).long()
)
val_if_large = torch.min(
val_if_large, torch.full_like(val_if_large, num_buckets - 1)
)
ret += torch.where(is_small, n, val_if_large)
return ret
def forward(self, num_queries: int, num_keys: int) -> Tensor:
i, j, device = num_queries, num_keys, self.relative_attention_bias.weight.device
q_pos = torch.arange(j - i, j, dtype=torch.long, device=device)
k_pos = torch.arange(j, dtype=torch.long, device=device)
rel_pos = rearrange(k_pos, "j -> 1 j") - rearrange(q_pos, "i -> i 1")
relative_position_bucket = self._relative_position_bucket(
rel_pos, num_buckets=self.num_buckets, max_distance=self.max_distance
)
bias = self.relative_attention_bias(relative_position_bucket)
bias = rearrange(bias, "m n h -> 1 h m n")
return bias
def FeedForward(features: int, multiplier: int) -> nn.Module:
mid_features = features * multiplier
return nn.Sequential(
nn.Linear(in_features=features, out_features=mid_features),
nn.GELU(),
nn.Linear(in_features=mid_features, out_features=features),
)
class AttentionBase(nn.Module):
def __init__(
self,
features: int,
*,
head_features: int,
num_heads: int,
use_rel_pos: bool,
out_features: Optional[int] = None,
rel_pos_num_buckets: Optional[int] = None,
rel_pos_max_distance: Optional[int] = None,
):
super().__init__()
self.scale = head_features ** -0.5
self.num_heads = num_heads
self.use_rel_pos = use_rel_pos
mid_features = head_features * num_heads
if use_rel_pos:
assert exists(rel_pos_num_buckets) and exists(rel_pos_max_distance)
self.rel_pos = RelativePositionBias(
num_buckets=rel_pos_num_buckets,
max_distance=rel_pos_max_distance,
num_heads=num_heads,
)
if out_features is None:
out_features = features
self.to_out = nn.Linear(in_features=mid_features, out_features=out_features)
def forward(self, q: Tensor, k: Tensor, v: Tensor) -> Tensor:
# Split heads
q, k, v = rearrange_many((q, k, v), "b n (h d) -> b h n d", h=self.num_heads)
# Compute similarity matrix
sim = einsum("... n d, ... m d -> ... n m", q, k)
sim = (sim + self.rel_pos(*sim.shape[-2:])) if self.use_rel_pos else sim
sim = sim * self.scale
# Get attention matrix with softmax
attn = sim.softmax(dim=-1)
# Compute values
out = einsum("... n m, ... m d -> ... n d", attn, v)
out = rearrange(out, "b h n d -> b n (h d)")
return self.to_out(out)
class Attention(nn.Module):
def __init__(
self,
features: int,
*,
head_features: int,
num_heads: int,
out_features: Optional[int] = None,
context_features: Optional[int] = None,
use_rel_pos: bool,
rel_pos_num_buckets: Optional[int] = None,
rel_pos_max_distance: Optional[int] = None,
):
super().__init__()
self.context_features = context_features
mid_features = head_features * num_heads
context_features = default(context_features, features)
self.norm = nn.LayerNorm(features)
self.norm_context = nn.LayerNorm(context_features)
self.to_q = nn.Linear(
in_features=features, out_features=mid_features, bias=False
)
self.to_kv = nn.Linear(
in_features=context_features, out_features=mid_features * 2, bias=False
)
self.attention = AttentionBase(
features,
out_features=out_features,
num_heads=num_heads,
head_features=head_features,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
def forward(self, x: Tensor, *, context: Optional[Tensor] = None) -> Tensor:
assert_message = "You must provide a context when using context_features"
assert not self.context_features or exists(context), assert_message
# Use context if provided
context = default(context, x)
# Normalize then compute q from input and k,v from context
x, context = self.norm(x), self.norm_context(context)
q, k, v = (self.to_q(x), *torch.chunk(self.to_kv(context), chunks=2, dim=-1))
# Compute and return attention
return self.attention(q, k, v)
"""
Transformer Blocks
"""
class TransformerBlock(nn.Module):
def __init__(
self,
features: int,
num_heads: int,
head_features: int,
multiplier: int,
use_rel_pos: bool,
rel_pos_num_buckets: Optional[int] = None,
rel_pos_max_distance: Optional[int] = None,
context_features: Optional[int] = None,
):
super().__init__()
self.use_cross_attention = exists(context_features) and context_features > 0
self.attention = Attention(
features=features,
num_heads=num_heads,
head_features=head_features,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
if self.use_cross_attention:
self.cross_attention = Attention(
features=features,
num_heads=num_heads,
head_features=head_features,
context_features=context_features,
use_rel_pos=use_rel_pos,
rel_pos_num_buckets=rel_pos_num_buckets,
rel_pos_max_distance=rel_pos_max_distance,
)
self.feed_forward = FeedForward(features=features, multiplier=multiplier)
def forward(self, x: Tensor, *, context: Optional[Tensor] = None) -> Tensor:
x = self.attention(x) + x
if self.use_cross_attention:
x = self.cross_attention(x, context=context) + x
x = self.feed_forward(x) + x
return x
"""
Time Embeddings
"""
class SinusoidalEmbedding(nn.Module):
def __init__(self, dim: int):
super().__init__()
self.dim = dim
def forward(self, x: Tensor) -> Tensor:
device, half_dim = x.device, self.dim // 2
emb = torch.tensor(log(10000) / (half_dim - 1), device=device)
emb = torch.exp(torch.arange(half_dim, device=device) * -emb)
emb = rearrange(x, "i -> i 1") * rearrange(emb, "j -> 1 j")
return torch.cat((emb.sin(), emb.cos()), dim=-1)
class LearnedPositionalEmbedding(nn.Module):
"""Used for continuous time"""
def __init__(self, dim: int):
super().__init__()
assert (dim % 2) == 0
half_dim = dim // 2
self.weights = nn.Parameter(torch.randn(half_dim))
def forward(self, x: Tensor) -> Tensor:
x = rearrange(x, "b -> b 1")
freqs = x * rearrange(self.weights, "d -> 1 d") * 2 * pi
fouriered = torch.cat((freqs.sin(), freqs.cos()), dim=-1)
fouriered = torch.cat((x, fouriered), dim=-1)
return fouriered
def TimePositionalEmbedding(dim: int, out_features: int) -> nn.Module:
return nn.Sequential(
LearnedPositionalEmbedding(dim),
nn.Linear(in_features=dim + 1, out_features=out_features),
)
class FixedEmbedding(nn.Module):
def __init__(self, max_length: int, features: int):
super().__init__()
self.max_length = max_length
self.embedding = nn.Embedding(max_length, features)
def forward(self, x: Tensor) -> Tensor:
batch_size, length, device = *x.shape[0:2], x.device
assert_message = "Input sequence length must be <= max_length"
assert length <= self.max_length, assert_message
position = torch.arange(length, device=device)
fixed_embedding = self.embedding(position)
fixed_embedding = repeat(fixed_embedding, "n d -> b n d", b=batch_size)
return fixed_embedding
@@ -0,0 +1,691 @@
from math import atan, cos, pi, sin, sqrt
from typing import Any, Callable, List, Optional, Tuple, Type
import torch
import torch.nn as nn
import torch.nn.functional as F
from einops import rearrange, reduce
from torch import Tensor
from .utils import *
"""
Diffusion Training
"""
""" Distributions """
class Distribution:
def __call__(self, num_samples: int, device: torch.device):
raise NotImplementedError()
class LogNormalDistribution(Distribution):
def __init__(self, mean: float, std: float):
self.mean = mean
self.std = std
def __call__(
self, num_samples: int, device: torch.device = torch.device("cpu")
) -> Tensor:
normal = self.mean + self.std * torch.randn((num_samples,), device=device)
return normal.exp()
class UniformDistribution(Distribution):
def __call__(self, num_samples: int, device: torch.device = torch.device("cpu")):
return torch.rand(num_samples, device=device)
class VKDistribution(Distribution):
def __init__(
self,
min_value: float = 0.0,
max_value: float = float("inf"),
sigma_data: float = 1.0,
):
self.min_value = min_value
self.max_value = max_value
self.sigma_data = sigma_data
def __call__(
self, num_samples: int, device: torch.device = torch.device("cpu")
) -> Tensor:
sigma_data = self.sigma_data
min_cdf = atan(self.min_value / sigma_data) * 2 / pi
max_cdf = atan(self.max_value / sigma_data) * 2 / pi
u = (max_cdf - min_cdf) * torch.randn((num_samples,), device=device) + min_cdf
return torch.tan(u * pi / 2) * sigma_data
""" Diffusion Classes """
def pad_dims(x: Tensor, ndim: int) -> Tensor:
# Pads additional ndims to the right of the tensor
return x.view(*x.shape, *((1,) * ndim))
def clip(x: Tensor, dynamic_threshold: float = 0.0):
if dynamic_threshold == 0.0:
return x.clamp(-1.0, 1.0)
else:
# Dynamic thresholding
# Find dynamic threshold quantile for each batch
x_flat = rearrange(x, "b ... -> b (...)")
scale = torch.quantile(x_flat.abs(), dynamic_threshold, dim=-1)
# Clamp to a min of 1.0
scale.clamp_(min=1.0)
# Clamp all values and scale
scale = pad_dims(scale, ndim=x.ndim - scale.ndim)
x = x.clamp(-scale, scale) / scale
return x
def to_batch(
batch_size: int,
device: torch.device,
x: Optional[float] = None,
xs: Optional[Tensor] = None,
) -> Tensor:
assert exists(x) ^ exists(xs), "Either x or xs must be provided"
# If x provided use the same for all batch items
if exists(x):
xs = torch.full(size=(batch_size,), fill_value=x).to(device)
assert exists(xs)
return xs
class Diffusion(nn.Module):
alias: str = ""
"""Base diffusion class"""
def denoise_fn(
self,
x_noisy: Tensor,
sigmas: Optional[Tensor] = None,
sigma: Optional[float] = None,
**kwargs,
) -> Tensor:
raise NotImplementedError("Diffusion class missing denoise_fn")
def forward(self, x: Tensor, noise: Tensor = None, **kwargs) -> Tensor:
raise NotImplementedError("Diffusion class missing forward function")
class VDiffusion(Diffusion):
alias = "v"
def __init__(self, net: nn.Module, *, sigma_distribution: Distribution):
super().__init__()
self.net = net
self.sigma_distribution = sigma_distribution
def get_alpha_beta(self, sigmas: Tensor) -> Tuple[Tensor, Tensor]:
angle = sigmas * pi / 2
alpha = torch.cos(angle)
beta = torch.sin(angle)
return alpha, beta
def denoise_fn(
self,
x_noisy: Tensor,
sigmas: Optional[Tensor] = None,
sigma: Optional[float] = None,
**kwargs,
) -> Tensor:
batch_size, device = x_noisy.shape[0], x_noisy.device
sigmas = to_batch(x=sigma, xs=sigmas, batch_size=batch_size, device=device)
return self.net(x_noisy, sigmas, **kwargs)
def forward(self, x: Tensor, noise: Tensor = None, **kwargs) -> Tensor:
batch_size, device = x.shape[0], x.device
# Sample amount of noise to add for each batch element
sigmas = self.sigma_distribution(num_samples=batch_size, device=device)
sigmas_padded = rearrange(sigmas, "b -> b 1 1")
# Get noise
noise = default(noise, lambda: torch.randn_like(x))
# Combine input and noise weighted by half-circle
alpha, beta = self.get_alpha_beta(sigmas_padded)
x_noisy = x * alpha + noise * beta
x_target = noise * alpha - x * beta
# Denoise and return loss
x_denoised = self.denoise_fn(x_noisy, sigmas, **kwargs)
return F.mse_loss(x_denoised, x_target)
class KDiffusion(Diffusion):
"""Elucidated Diffusion (Karras et al. 2022): https://arxiv.org/abs/2206.00364"""
alias = "k"
def __init__(
self,
net: nn.Module,
*,
sigma_distribution: Distribution,
sigma_data: float, # data distribution standard deviation
dynamic_threshold: float = 0.0,
):
super().__init__()
self.net = net
self.sigma_data = sigma_data
self.sigma_distribution = sigma_distribution
self.dynamic_threshold = dynamic_threshold
def get_scale_weights(self, sigmas: Tensor) -> Tuple[Tensor, ...]:
sigma_data = self.sigma_data
c_noise = torch.log(sigmas) * 0.25
sigmas = rearrange(sigmas, "b -> b 1 1")
c_skip = (sigma_data ** 2) / (sigmas ** 2 + sigma_data ** 2)
c_out = sigmas * sigma_data * (sigma_data ** 2 + sigmas ** 2) ** -0.5
c_in = (sigmas ** 2 + sigma_data ** 2) ** -0.5
return c_skip, c_out, c_in, c_noise
def denoise_fn(
self,
x_noisy: Tensor,
sigmas: Optional[Tensor] = None,
sigma: Optional[float] = None,
**kwargs,
) -> Tensor:
batch_size, device = x_noisy.shape[0], x_noisy.device
sigmas = to_batch(x=sigma, xs=sigmas, batch_size=batch_size, device=device)
# Predict network output and add skip connection
c_skip, c_out, c_in, c_noise = self.get_scale_weights(sigmas)
x_pred = self.net(c_in * x_noisy, c_noise, **kwargs)
x_denoised = c_skip * x_noisy + c_out * x_pred
return x_denoised
def loss_weight(self, sigmas: Tensor) -> Tensor:
# Computes weight depending on data distribution
return (sigmas ** 2 + self.sigma_data ** 2) * (sigmas * self.sigma_data) ** -2
def forward(self, x: Tensor, noise: Tensor = None, **kwargs) -> Tensor:
batch_size, device = x.shape[0], x.device
from einops import rearrange, reduce
# Sample amount of noise to add for each batch element
sigmas = self.sigma_distribution(num_samples=batch_size, device=device)
sigmas_padded = rearrange(sigmas, "b -> b 1 1")
# Add noise to input
noise = default(noise, lambda: torch.randn_like(x))
x_noisy = x + sigmas_padded * noise
# Compute denoised values
x_denoised = self.denoise_fn(x_noisy, sigmas=sigmas, **kwargs)
# Compute weighted loss
losses = F.mse_loss(x_denoised, x, reduction="none")
losses = reduce(losses, "b ... -> b", "mean")
losses = losses * self.loss_weight(sigmas)
loss = losses.mean()
return loss
class VKDiffusion(Diffusion):
alias = "vk"
def __init__(self, net: nn.Module, *, sigma_distribution: Distribution):
super().__init__()
self.net = net
self.sigma_distribution = sigma_distribution
def get_scale_weights(self, sigmas: Tensor) -> Tuple[Tensor, ...]:
sigma_data = 1.0
sigmas = rearrange(sigmas, "b -> b 1 1")
c_skip = (sigma_data ** 2) / (sigmas ** 2 + sigma_data ** 2)
c_out = -sigmas * sigma_data * (sigma_data ** 2 + sigmas ** 2) ** -0.5
c_in = (sigmas ** 2 + sigma_data ** 2) ** -0.5
return c_skip, c_out, c_in
def sigma_to_t(self, sigmas: Tensor) -> Tensor:
return sigmas.atan() / pi * 2
def t_to_sigma(self, t: Tensor) -> Tensor:
return (t * pi / 2).tan()
def denoise_fn(
self,
x_noisy: Tensor,
sigmas: Optional[Tensor] = None,
sigma: Optional[float] = None,
**kwargs,
) -> Tensor:
batch_size, device = x_noisy.shape[0], x_noisy.device
sigmas = to_batch(x=sigma, xs=sigmas, batch_size=batch_size, device=device)
# Predict network output and add skip connection
c_skip, c_out, c_in = self.get_scale_weights(sigmas)
x_pred = self.net(c_in * x_noisy, self.sigma_to_t(sigmas), **kwargs)
x_denoised = c_skip * x_noisy + c_out * x_pred
return x_denoised
def forward(self, x: Tensor, noise: Tensor = None, **kwargs) -> Tensor:
batch_size, device = x.shape[0], x.device
# Sample amount of noise to add for each batch element
sigmas = self.sigma_distribution(num_samples=batch_size, device=device)
sigmas_padded = rearrange(sigmas, "b -> b 1 1")
# Add noise to input
noise = default(noise, lambda: torch.randn_like(x))
x_noisy = x + sigmas_padded * noise
# Compute model output
c_skip, c_out, c_in = self.get_scale_weights(sigmas)
x_pred = self.net(c_in * x_noisy, self.sigma_to_t(sigmas), **kwargs)
# Compute v-objective target
v_target = (x - c_skip * x_noisy) / (c_out + 1e-7)
# Compute loss
loss = F.mse_loss(x_pred, v_target)
return loss
"""
Diffusion Sampling
"""
""" Schedules """
class Schedule(nn.Module):
"""Interface used by different sampling schedules"""
def forward(self, num_steps: int, device: torch.device) -> Tensor:
raise NotImplementedError()
class LinearSchedule(Schedule):
def forward(self, num_steps: int, device: Any) -> Tensor:
sigmas = torch.linspace(1, 0, num_steps + 1)[:-1]
return sigmas
class KarrasSchedule(Schedule):
"""https://arxiv.org/abs/2206.00364 equation 5"""
def __init__(self, sigma_min: float, sigma_max: float, rho: float = 7.0):
super().__init__()
self.sigma_min = sigma_min
self.sigma_max = sigma_max
self.rho = rho
def forward(self, num_steps: int, device: Any) -> Tensor:
rho_inv = 1.0 / self.rho
steps = torch.arange(num_steps, device=device, dtype=torch.float32)
sigmas = (
self.sigma_max ** rho_inv
+ (steps / (num_steps - 1))
* (self.sigma_min ** rho_inv - self.sigma_max ** rho_inv)
) ** self.rho
sigmas = F.pad(sigmas, pad=(0, 1), value=0.0)
return sigmas
""" Samplers """
class Sampler(nn.Module):
diffusion_types: List[Type[Diffusion]] = []
def forward(
self, noise: Tensor, fn: Callable, sigmas: Tensor, num_steps: int
) -> Tensor:
raise NotImplementedError()
def inpaint(
self,
source: Tensor,
mask: Tensor,
fn: Callable,
sigmas: Tensor,
num_steps: int,
num_resamples: int,
) -> Tensor:
raise NotImplementedError("Inpainting not available with current sampler")
class VSampler(Sampler):
diffusion_types = [VDiffusion]
def get_alpha_beta(self, sigma: float) -> Tuple[float, float]:
angle = sigma * pi / 2
alpha = cos(angle)
beta = sin(angle)
return alpha, beta
def forward(
self, noise: Tensor, fn: Callable, sigmas: Tensor, num_steps: int
) -> Tensor:
x = sigmas[0] * noise
alpha, beta = self.get_alpha_beta(sigmas[0].item())
for i in range(num_steps - 1):
is_last = i == num_steps - 1
x_denoised = fn(x, sigma=sigmas[i])
x_pred = x * alpha - x_denoised * beta
x_eps = x * beta + x_denoised * alpha
if not is_last:
alpha, beta = self.get_alpha_beta(sigmas[i + 1].item())
x = x_pred * alpha + x_eps * beta
return x_pred
class KarrasSampler(Sampler):
"""https://arxiv.org/abs/2206.00364 algorithm 1"""
diffusion_types = [KDiffusion, VKDiffusion]
def __init__(
self,
s_tmin: float = 0,
s_tmax: float = float("inf"),
s_churn: float = 0.0,
s_noise: float = 1.0,
):
super().__init__()
self.s_tmin = s_tmin
self.s_tmax = s_tmax
self.s_noise = s_noise
self.s_churn = s_churn
def step(
self, x: Tensor, fn: Callable, sigma: float, sigma_next: float, gamma: float
) -> Tensor:
"""Algorithm 2 (step)"""
# Select temporarily increased noise level
sigma_hat = sigma + gamma * sigma
# Add noise to move from sigma to sigma_hat
epsilon = self.s_noise * torch.randn_like(x)
x_hat = x + sqrt(sigma_hat ** 2 - sigma ** 2) * epsilon
# Evaluate ∂x/∂sigma at sigma_hat
d = (x_hat - fn(x_hat, sigma=sigma_hat)) / sigma_hat
# Take euler step from sigma_hat to sigma_next
x_next = x_hat + (sigma_next - sigma_hat) * d
# Second order correction
if sigma_next != 0:
model_out_next = fn(x_next, sigma=sigma_next)
d_prime = (x_next - model_out_next) / sigma_next
x_next = x_hat + 0.5 * (sigma - sigma_hat) * (d + d_prime)
return x_next
def forward(
self, noise: Tensor, fn: Callable, sigmas: Tensor, num_steps: int
) -> Tensor:
x = sigmas[0] * noise
# Compute gammas
gammas = torch.where(
(sigmas >= self.s_tmin) & (sigmas <= self.s_tmax),
min(self.s_churn / num_steps, sqrt(2) - 1),
0.0,
)
# Denoise to sample
for i in range(num_steps - 1):
x = self.step(
x, fn=fn, sigma=sigmas[i], sigma_next=sigmas[i + 1], gamma=gammas[i] # type: ignore # noqa
)
return x
class AEulerSampler(Sampler):
diffusion_types = [KDiffusion, VKDiffusion]
def get_sigmas(self, sigma: float, sigma_next: float) -> Tuple[float, float]:
sigma_up = sqrt(sigma_next ** 2 * (sigma ** 2 - sigma_next ** 2) / sigma ** 2)
sigma_down = sqrt(sigma_next ** 2 - sigma_up ** 2)
return sigma_up, sigma_down
def step(self, x: Tensor, fn: Callable, sigma: float, sigma_next: float) -> Tensor:
# Sigma steps
sigma_up, sigma_down = self.get_sigmas(sigma, sigma_next)
# Derivative at sigma (∂x/∂sigma)
d = (x - fn(x, sigma=sigma)) / sigma
# Euler method
x_next = x + d * (sigma_down - sigma)
# Add randomness
x_next = x_next + torch.randn_like(x) * sigma_up
return x_next
def forward(
self, noise: Tensor, fn: Callable, sigmas: Tensor, num_steps: int
) -> Tensor:
x = sigmas[0] * noise
# Denoise to sample
for i in range(num_steps - 1):
x = self.step(x, fn=fn, sigma=sigmas[i], sigma_next=sigmas[i + 1]) # type: ignore # noqa
return x
class ADPM2Sampler(Sampler):
"""https://www.desmos.com/calculator/jbxjlqd9mb"""
diffusion_types = [KDiffusion, VKDiffusion]
def __init__(self, rho: float = 1.0):
super().__init__()
self.rho = rho
def get_sigmas(self, sigma: float, sigma_next: float) -> Tuple[float, float, float]:
r = self.rho
sigma_up = sqrt(sigma_next ** 2 * (sigma ** 2 - sigma_next ** 2) / sigma ** 2)
sigma_down = sqrt(sigma_next ** 2 - sigma_up ** 2)
sigma_mid = ((sigma ** (1 / r) + sigma_down ** (1 / r)) / 2) ** r
return sigma_up, sigma_down, sigma_mid
def step(self, x: Tensor, fn: Callable, sigma: float, sigma_next: float) -> Tensor:
# Sigma steps
sigma_up, sigma_down, sigma_mid = self.get_sigmas(sigma, sigma_next)
# Derivative at sigma (∂x/∂sigma)
d = (x - fn(x, sigma=sigma)) / sigma
# Denoise to midpoint
x_mid = x + d * (sigma_mid - sigma)
# Derivative at sigma_mid (∂x_mid/∂sigma_mid)
d_mid = (x_mid - fn(x_mid, sigma=sigma_mid)) / sigma_mid
# Denoise to next
x = x + d_mid * (sigma_down - sigma)
# Add randomness
x_next = x + torch.randn_like(x) * sigma_up
return x_next
def forward(
self, noise: Tensor, fn: Callable, sigmas: Tensor, num_steps: int
) -> Tensor:
x = sigmas[0] * noise
# Denoise to sample
for i in range(num_steps - 1):
x = self.step(x, fn=fn, sigma=sigmas[i], sigma_next=sigmas[i + 1]) # type: ignore # noqa
return x
def inpaint(
self,
source: Tensor,
mask: Tensor,
fn: Callable,
sigmas: Tensor,
num_steps: int,
num_resamples: int,
) -> Tensor:
x = sigmas[0] * torch.randn_like(source)
for i in range(num_steps - 1):
# Noise source to current noise level
source_noisy = source + sigmas[i] * torch.randn_like(source)
for r in range(num_resamples):
# Merge noisy source and current then denoise
x = source_noisy * mask + x * ~mask
x = self.step(x, fn=fn, sigma=sigmas[i], sigma_next=sigmas[i + 1]) # type: ignore # noqa
# Renoise if not last resample step
if r < num_resamples - 1:
sigma = sqrt(sigmas[i] ** 2 - sigmas[i + 1] ** 2)
x = x + sigma * torch.randn_like(x)
return source * mask + x * ~mask
""" Main Classes """
class DiffusionSampler(nn.Module):
def __init__(
self,
diffusion: Diffusion,
*,
sampler: Sampler,
sigma_schedule: Schedule,
num_steps: Optional[int] = None,
clamp: bool = True,
):
super().__init__()
self.denoise_fn = diffusion.denoise_fn
self.sampler = sampler
self.sigma_schedule = sigma_schedule
self.num_steps = num_steps
self.clamp = clamp
# Check sampler is compatible with diffusion type
sampler_class = sampler.__class__.__name__
diffusion_class = diffusion.__class__.__name__
message = f"{sampler_class} incompatible with {diffusion_class}"
assert diffusion.alias in [t.alias for t in sampler.diffusion_types], message
def forward(
self, noise: Tensor, num_steps: Optional[int] = None, **kwargs
) -> Tensor:
device = noise.device
num_steps = default(num_steps, self.num_steps) # type: ignore
assert exists(num_steps), "Parameter `num_steps` must be provided"
# Compute sigmas using schedule
sigmas = self.sigma_schedule(num_steps, device)
# Append additional kwargs to denoise function (used e.g. for conditional unet)
fn = lambda *a, **ka: self.denoise_fn(*a, **{**ka, **kwargs}) # noqa
# Sample using sampler
x = self.sampler(noise, fn=fn, sigmas=sigmas, num_steps=num_steps)
x = x.clamp(-1.0, 1.0) if self.clamp else x
return x
class DiffusionInpainter(nn.Module):
def __init__(
self,
diffusion: Diffusion,
*,
num_steps: int,
num_resamples: int,
sampler: Sampler,
sigma_schedule: Schedule,
):
super().__init__()
self.denoise_fn = diffusion.denoise_fn
self.num_steps = num_steps
self.num_resamples = num_resamples
self.inpaint_fn = sampler.inpaint
self.sigma_schedule = sigma_schedule
@torch.no_grad()
def forward(self, inpaint: Tensor, inpaint_mask: Tensor) -> Tensor:
x = self.inpaint_fn(
source=inpaint,
mask=inpaint_mask,
fn=self.denoise_fn,
sigmas=self.sigma_schedule(self.num_steps, inpaint.device),
num_steps=self.num_steps,
num_resamples=self.num_resamples,
)
return x
def sequential_mask(like: Tensor, start: int) -> Tensor:
length, device = like.shape[2], like.device
mask = torch.ones_like(like, dtype=torch.bool)
mask[:, :, start:] = torch.zeros((length - start,), device=device)
return mask
class SpanBySpanComposer(nn.Module):
def __init__(
self,
inpainter: DiffusionInpainter,
*,
num_spans: int,
):
super().__init__()
self.inpainter = inpainter
self.num_spans = num_spans
def forward(self, start: Tensor, keep_start: bool = False) -> Tensor:
half_length = start.shape[2] // 2
spans = list(start.chunk(chunks=2, dim=-1)) if keep_start else []
# Inpaint second half from first half
inpaint = torch.zeros_like(start)
inpaint[:, :, :half_length] = start[:, :, half_length:]
inpaint_mask = sequential_mask(like=start, start=half_length)
for i in range(self.num_spans):
# Inpaint second half
span = self.inpainter(inpaint=inpaint, inpaint_mask=inpaint_mask)
# Replace first half with generated second half
second_half = span[:, :, half_length:]
inpaint[:, :, :half_length] = second_half
# Save generated span
spans.append(second_half)
return torch.cat(spans, dim=2)
class XDiffusion(nn.Module):
def __init__(self, type: str, net: nn.Module, **kwargs):
super().__init__()
diffusion_classes = [VDiffusion, KDiffusion, VKDiffusion]
aliases = [t.alias for t in diffusion_classes] # type: ignore
message = f"type='{type}' must be one of {*aliases,}"
assert type in aliases, message
self.net = net
for XDiffusion in diffusion_classes:
if XDiffusion.alias == type: # type: ignore
self.diffusion = XDiffusion(net=net, **kwargs)
def forward(self, *args, **kwargs) -> Tensor:
return self.diffusion(*args, **kwargs)
def sample(
self,
noise: Tensor,
num_steps: int,
sigma_schedule: Schedule,
sampler: Sampler,
clamp: bool,
**kwargs,
) -> Tensor:
diffusion_sampler = DiffusionSampler(
diffusion=self.diffusion,
sampler=sampler,
sigma_schedule=sigma_schedule,
num_steps=num_steps,
clamp=clamp,
)
return diffusion_sampler(noise, **kwargs)
@@ -0,0 +1,82 @@
from functools import reduce
from inspect import isfunction
from math import ceil, floor, log2, pi
from typing import Callable, Dict, List, Optional, Sequence, Tuple, TypeVar, Union
import torch
import torch.nn.functional as F
from einops import rearrange
from torch import Generator, Tensor
from typing_extensions import TypeGuard
T = TypeVar("T")
def exists(val: Optional[T]) -> TypeGuard[T]:
return val is not None
def iff(condition: bool, value: T) -> Optional[T]:
return value if condition else None
def is_sequence(obj: T) -> TypeGuard[Union[list, tuple]]:
return isinstance(obj, list) or isinstance(obj, tuple)
def default(val: Optional[T], d: Union[Callable[..., T], T]) -> T:
if exists(val):
return val
return d() if isfunction(d) else d
def to_list(val: Union[T, Sequence[T]]) -> List[T]:
if isinstance(val, tuple):
return list(val)
if isinstance(val, list):
return val
return [val] # type: ignore
def prod(vals: Sequence[int]) -> int:
return reduce(lambda x, y: x * y, vals)
def closest_power_2(x: float) -> int:
exponent = log2(x)
distance_fn = lambda z: abs(x - 2 ** z) # noqa
exponent_closest = min((floor(exponent), ceil(exponent)), key=distance_fn)
return 2 ** int(exponent_closest)
def rand_bool(shape, proba, device = None):
if proba == 1:
return torch.ones(shape, device=device, dtype=torch.bool)
elif proba == 0:
return torch.zeros(shape, device=device, dtype=torch.bool)
else:
return torch.bernoulli(torch.full(shape, proba, device=device)).to(torch.bool)
"""
Kwargs Utils
"""
def group_dict_by_prefix(prefix: str, d: Dict) -> Tuple[Dict, Dict]:
return_dicts: Tuple[Dict, Dict] = ({}, {})
for key in d.keys():
no_prefix = int(not key.startswith(prefix))
return_dicts[no_prefix][key] = d[key]
return return_dicts
def groupby(prefix: str, d: Dict, keep_prefix: bool = False) -> Tuple[Dict, Dict]:
kwargs_with_prefix, kwargs = group_dict_by_prefix(prefix, d)
if keep_prefix:
return kwargs_with_prefix, kwargs
kwargs_no_prefix = {k[len(prefix) :]: v for k, v in kwargs_with_prefix.items()}
return kwargs_no_prefix, kwargs
def prefix_dict(prefix: str, d: Dict) -> Dict:
return {prefix + str(k): v for k, v in d.items()}
@@ -0,0 +1,188 @@
import torch
import torch.nn.functional as F
import torch.nn as nn
from torch.nn import Conv1d, AvgPool1d, Conv2d
from torch.nn.utils import weight_norm, spectral_norm
from .utils import get_padding
LRELU_SLOPE = 0.1
def stft(x, fft_size, hop_size, win_length, window):
"""Perform STFT and convert to magnitude spectrogram.
Args:
x (Tensor): Input signal tensor (B, T).
fft_size (int): FFT size.
hop_size (int): Hop size.
win_length (int): Window length.
window (str): Window function type.
Returns:
Tensor: Magnitude spectrogram (B, #frames, fft_size // 2 + 1).
"""
x_stft = torch.stft(x, fft_size, hop_size, win_length, window,
return_complex=True)
real = x_stft[..., 0]
imag = x_stft[..., 1]
return torch.abs(x_stft).transpose(2, 1)
class SpecDiscriminator(nn.Module):
"""docstring for Discriminator."""
def __init__(self, fft_size=1024, shift_size=120, win_length=600, window="hann_window", use_spectral_norm=False):
super(SpecDiscriminator, self).__init__()
norm_f = weight_norm if use_spectral_norm == False else spectral_norm
self.fft_size = fft_size
self.shift_size = shift_size
self.win_length = win_length
self.window = getattr(torch, window)(win_length)
self.discriminators = nn.ModuleList([
norm_f(nn.Conv2d(1, 32, kernel_size=(3, 9), padding=(1, 4))),
norm_f(nn.Conv2d(32, 32, kernel_size=(3, 9), stride=(1,2), padding=(1, 4))),
norm_f(nn.Conv2d(32, 32, kernel_size=(3, 9), stride=(1,2), padding=(1, 4))),
norm_f(nn.Conv2d(32, 32, kernel_size=(3, 9), stride=(1,2), padding=(1, 4))),
norm_f(nn.Conv2d(32, 32, kernel_size=(3, 3), stride=(1,1), padding=(1, 1))),
])
self.out = norm_f(nn.Conv2d(32, 1, 3, 1, 1))
def forward(self, y):
fmap = []
y = y.squeeze(1)
y = stft(y, self.fft_size, self.shift_size, self.win_length, self.window.to(y.get_device()))
y = y.unsqueeze(1)
for i, d in enumerate(self.discriminators):
y = d(y)
y = F.leaky_relu(y, LRELU_SLOPE)
fmap.append(y)
y = self.out(y)
fmap.append(y)
return torch.flatten(y, 1, -1), fmap
class MultiResSpecDiscriminator(torch.nn.Module):
def __init__(self,
fft_sizes=[1024, 2048, 512],
hop_sizes=[120, 240, 50],
win_lengths=[600, 1200, 240],
window="hann_window"):
super(MultiResSpecDiscriminator, self).__init__()
self.discriminators = nn.ModuleList([
SpecDiscriminator(fft_sizes[0], hop_sizes[0], win_lengths[0], window),
SpecDiscriminator(fft_sizes[1], hop_sizes[1], win_lengths[1], window),
SpecDiscriminator(fft_sizes[2], hop_sizes[2], win_lengths[2], window)
])
def forward(self, y, y_hat):
y_d_rs = []
y_d_gs = []
fmap_rs = []
fmap_gs = []
for i, d in enumerate(self.discriminators):
y_d_r, fmap_r = d(y)
y_d_g, fmap_g = d(y_hat)
y_d_rs.append(y_d_r)
fmap_rs.append(fmap_r)
y_d_gs.append(y_d_g)
fmap_gs.append(fmap_g)
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
class DiscriminatorP(torch.nn.Module):
def __init__(self, period, kernel_size=5, stride=3, use_spectral_norm=False):
super(DiscriminatorP, self).__init__()
self.period = period
norm_f = weight_norm if use_spectral_norm == False else spectral_norm
self.convs = nn.ModuleList([
norm_f(Conv2d(1, 32, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))),
norm_f(Conv2d(32, 128, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))),
norm_f(Conv2d(128, 512, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))),
norm_f(Conv2d(512, 1024, (kernel_size, 1), (stride, 1), padding=(get_padding(5, 1), 0))),
norm_f(Conv2d(1024, 1024, (kernel_size, 1), 1, padding=(2, 0))),
])
self.conv_post = norm_f(Conv2d(1024, 1, (3, 1), 1, padding=(1, 0)))
def forward(self, x):
fmap = []
# 1d to 2d
b, c, t = x.shape
if t % self.period != 0: # pad first
n_pad = self.period - (t % self.period)
x = F.pad(x, (0, n_pad), "reflect")
t = t + n_pad
x = x.view(b, c, t // self.period, self.period)
for l in self.convs:
x = l(x)
x = F.leaky_relu(x, LRELU_SLOPE)
fmap.append(x)
x = self.conv_post(x)
fmap.append(x)
x = torch.flatten(x, 1, -1)
return x, fmap
class MultiPeriodDiscriminator(torch.nn.Module):
def __init__(self):
super(MultiPeriodDiscriminator, self).__init__()
self.discriminators = nn.ModuleList([
DiscriminatorP(2),
DiscriminatorP(3),
DiscriminatorP(5),
DiscriminatorP(7),
DiscriminatorP(11),
])
def forward(self, y, y_hat):
y_d_rs = []
y_d_gs = []
fmap_rs = []
fmap_gs = []
for i, d in enumerate(self.discriminators):
y_d_r, fmap_r = d(y)
y_d_g, fmap_g = d(y_hat)
y_d_rs.append(y_d_r)
fmap_rs.append(fmap_r)
y_d_gs.append(y_d_g)
fmap_gs.append(fmap_g)
return y_d_rs, y_d_gs, fmap_rs, fmap_gs
class WavLMDiscriminator(nn.Module):
"""docstring for Discriminator."""
def __init__(self, slm_hidden=768,
slm_layers=13,
initial_channel=64,
use_spectral_norm=False):
super(WavLMDiscriminator, self).__init__()
norm_f = weight_norm if use_spectral_norm == False else spectral_norm
self.pre = norm_f(Conv1d(slm_hidden * slm_layers, initial_channel, 1, 1, padding=0))
self.convs = nn.ModuleList([
norm_f(nn.Conv1d(initial_channel, initial_channel * 2, kernel_size=5, padding=2)),
norm_f(nn.Conv1d(initial_channel * 2, initial_channel * 4, kernel_size=5, padding=2)),
norm_f(nn.Conv1d(initial_channel * 4, initial_channel * 4, 5, 1, padding=2)),
])
self.conv_post = norm_f(Conv1d(initial_channel * 4, 1, 3, 1, padding=1))
def forward(self, x):
x = self.pre(x)
fmap = []
for l in self.convs:
x = l(x)
x = F.leaky_relu(x, LRELU_SLOPE)
fmap.append(x)
x = self.conv_post(x)
x = torch.flatten(x, 1, -1)
return x
+477
View File
@@ -0,0 +1,477 @@
import torch
import torch.nn.functional as F
import torch.nn as nn
from torch.nn import Conv1d, ConvTranspose1d, AvgPool1d, Conv2d
from torch.nn.utils import weight_norm, remove_weight_norm, spectral_norm
from .utils import init_weights, get_padding
import math
import random
import numpy as np
LRELU_SLOPE = 0.1
class AdaIN1d(nn.Module):
def __init__(self, style_dim, num_features):
super().__init__()
self.norm = nn.InstanceNorm1d(num_features, affine=False)
self.fc = nn.Linear(style_dim, num_features*2)
def forward(self, x, s):
h = self.fc(s)
h = h.view(h.size(0), h.size(1), 1)
gamma, beta = torch.chunk(h, chunks=2, dim=1)
return (1 + gamma) * self.norm(x) + beta
class AdaINResBlock1(torch.nn.Module):
def __init__(self, channels, kernel_size=3, dilation=(1, 3, 5), style_dim=64):
super(AdaINResBlock1, self).__init__()
self.convs1 = nn.ModuleList([
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=dilation[0],
padding=get_padding(kernel_size, dilation[0]))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=dilation[1],
padding=get_padding(kernel_size, dilation[1]))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=dilation[2],
padding=get_padding(kernel_size, dilation[2])))
])
self.convs1.apply(init_weights)
self.convs2 = nn.ModuleList([
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=1,
padding=get_padding(kernel_size, 1))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=1,
padding=get_padding(kernel_size, 1))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=1,
padding=get_padding(kernel_size, 1)))
])
self.convs2.apply(init_weights)
self.adain1 = nn.ModuleList([
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
])
self.adain2 = nn.ModuleList([
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
])
self.alpha1 = nn.ParameterList([nn.Parameter(torch.ones(1, channels, 1)) for i in range(len(self.convs1))])
self.alpha2 = nn.ParameterList([nn.Parameter(torch.ones(1, channels, 1)) for i in range(len(self.convs2))])
def forward(self, x, s):
for c1, c2, n1, n2, a1, a2 in zip(self.convs1, self.convs2, self.adain1, self.adain2, self.alpha1, self.alpha2):
xt = n1(x, s)
xt = xt + (1 / a1) * (torch.sin(a1 * xt) ** 2) # Snake1D
xt = c1(xt)
xt = n2(xt, s)
xt = xt + (1 / a2) * (torch.sin(a2 * xt) ** 2) # Snake1D
xt = c2(xt)
x = xt + x
return x
def remove_weight_norm(self):
for l in self.convs1:
remove_weight_norm(l)
for l in self.convs2:
remove_weight_norm(l)
class SineGen(torch.nn.Module):
""" Definition of sine generator
SineGen(samp_rate, harmonic_num = 0,
sine_amp = 0.1, noise_std = 0.003,
voiced_threshold = 0,
flag_for_pulse=False)
samp_rate: sampling rate in Hz
harmonic_num: number of harmonic overtones (default 0)
sine_amp: amplitude of sine-wavefrom (default 0.1)
noise_std: std of Gaussian noise (default 0.003)
voiced_thoreshold: F0 threshold for U/V classification (default 0)
flag_for_pulse: this SinGen is used inside PulseGen (default False)
Note: when flag_for_pulse is True, the first time step of a voiced
segment is always sin(np.pi) or cos(0)
"""
def __init__(self, samp_rate, upsample_scale, harmonic_num=0,
sine_amp=0.1, noise_std=0.003,
voiced_threshold=0,
flag_for_pulse=False):
super(SineGen, self).__init__()
self.sine_amp = sine_amp
self.noise_std = noise_std
self.harmonic_num = harmonic_num
self.dim = self.harmonic_num + 1
self.sampling_rate = samp_rate
self.voiced_threshold = voiced_threshold
self.flag_for_pulse = flag_for_pulse
self.upsample_scale = upsample_scale
def _f02uv(self, f0):
# generate uv signal
uv = (f0 > self.voiced_threshold).type(torch.float32)
return uv
def _f02sine(self, f0_values):
""" f0_values: (batchsize, length, dim)
where dim indicates fundamental tone and overtones
"""
# convert to F0 in rad. The interger part n can be ignored
# because 2 * np.pi * n doesn't affect phase
rad_values = (f0_values / self.sampling_rate) % 1
# initial phase noise (no noise for fundamental component)
rand_ini = torch.rand(f0_values.shape[0], f0_values.shape[2], \
device=f0_values.device)
rand_ini[:, 0] = 0
rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini
# instantanouse phase sine[t] = sin(2*pi \sum_i=1 ^{t} rad)
if not self.flag_for_pulse:
# # for normal case
# # To prevent torch.cumsum numerical overflow,
# # it is necessary to add -1 whenever \sum_k=1^n rad_value_k > 1.
# # Buffer tmp_over_one_idx indicates the time step to add -1.
# # This will not change F0 of sine because (x-1) * 2*pi = x * 2*pi
# tmp_over_one = torch.cumsum(rad_values, 1) % 1
# tmp_over_one_idx = (padDiff(tmp_over_one)) < 0
# cumsum_shift = torch.zeros_like(rad_values)
# cumsum_shift[:, 1:, :] = tmp_over_one_idx * -1.0
# phase = torch.cumsum(rad_values, dim=1) * 2 * np.pi
rad_values = torch.nn.functional.interpolate(rad_values.transpose(1, 2),
scale_factor=1/self.upsample_scale,
mode="linear").transpose(1, 2)
# tmp_over_one = torch.cumsum(rad_values, 1) % 1
# tmp_over_one_idx = (padDiff(tmp_over_one)) < 0
# cumsum_shift = torch.zeros_like(rad_values)
# cumsum_shift[:, 1:, :] = tmp_over_one_idx * -1.0
phase = torch.cumsum(rad_values, dim=1) * 2 * np.pi
phase = torch.nn.functional.interpolate(phase.transpose(1, 2) * self.upsample_scale,
scale_factor=self.upsample_scale, mode="linear").transpose(1, 2)
sines = torch.sin(phase)
else:
# If necessary, make sure that the first time step of every
# voiced segments is sin(pi) or cos(0)
# This is used for pulse-train generation
# identify the last time step in unvoiced segments
uv = self._f02uv(f0_values)
uv_1 = torch.roll(uv, shifts=-1, dims=1)
uv_1[:, -1, :] = 1
u_loc = (uv < 1) * (uv_1 > 0)
# get the instantanouse phase
tmp_cumsum = torch.cumsum(rad_values, dim=1)
# different batch needs to be processed differently
for idx in range(f0_values.shape[0]):
temp_sum = tmp_cumsum[idx, u_loc[idx, :, 0], :]
temp_sum[1:, :] = temp_sum[1:, :] - temp_sum[0:-1, :]
# stores the accumulation of i.phase within
# each voiced segments
tmp_cumsum[idx, :, :] = 0
tmp_cumsum[idx, u_loc[idx, :, 0], :] = temp_sum
# rad_values - tmp_cumsum: remove the accumulation of i.phase
# within the previous voiced segment.
i_phase = torch.cumsum(rad_values - tmp_cumsum, dim=1)
# get the sines
sines = torch.cos(i_phase * 2 * np.pi)
return sines
def forward(self, f0):
""" sine_tensor, uv = forward(f0)
input F0: tensor(batchsize=1, length, dim=1)
f0 for unvoiced steps should be 0
output sine_tensor: tensor(batchsize=1, length, dim)
output uv: tensor(batchsize=1, length, 1)
"""
f0_buf = torch.zeros(f0.shape[0], f0.shape[1], self.dim,
device=f0.device)
# fundamental component
fn = torch.multiply(f0, torch.FloatTensor([[range(1, self.harmonic_num + 2)]]).to(f0.device))
# generate sine waveforms
sine_waves = self._f02sine(fn) * self.sine_amp
# generate uv signal
# uv = torch.ones(f0.shape)
# uv = uv * (f0 > self.voiced_threshold)
uv = self._f02uv(f0)
# noise: for unvoiced should be similar to sine_amp
# std = self.sine_amp/3 -> max value ~ self.sine_amp
# . for voiced regions is self.noise_std
noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
noise = noise_amp * torch.randn_like(sine_waves)
# first: set the unvoiced part to 0 by uv
# then: additive noise
sine_waves = sine_waves * uv + noise
return sine_waves, uv, noise
class SourceModuleHnNSF(torch.nn.Module):
""" SourceModule for hn-nsf
SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1,
add_noise_std=0.003, voiced_threshod=0)
sampling_rate: sampling_rate in Hz
harmonic_num: number of harmonic above F0 (default: 0)
sine_amp: amplitude of sine source signal (default: 0.1)
add_noise_std: std of additive Gaussian noise (default: 0.003)
note that amplitude of noise in unvoiced is decided
by sine_amp
voiced_threshold: threhold to set U/V given F0 (default: 0)
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
F0_sampled (batchsize, length, 1)
Sine_source (batchsize, length, 1)
noise_source (batchsize, length 1)
uv (batchsize, length, 1)
"""
def __init__(self, sampling_rate, upsample_scale, harmonic_num=0, sine_amp=0.1,
add_noise_std=0.003, voiced_threshod=0):
super(SourceModuleHnNSF, self).__init__()
self.sine_amp = sine_amp
self.noise_std = add_noise_std
# to produce sine waveforms
self.l_sin_gen = SineGen(sampling_rate, upsample_scale, harmonic_num,
sine_amp, add_noise_std, voiced_threshod)
# to merge source harmonics into a single excitation
self.l_linear = torch.nn.Linear(harmonic_num + 1, 1)
self.l_tanh = torch.nn.Tanh()
def forward(self, x):
"""
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
F0_sampled (batchsize, length, 1)
Sine_source (batchsize, length, 1)
noise_source (batchsize, length 1)
"""
# source for harmonic branch
with torch.no_grad():
sine_wavs, uv, _ = self.l_sin_gen(x)
sine_merge = self.l_tanh(self.l_linear(sine_wavs))
# source for noise branch, in the same shape as uv
noise = torch.randn_like(uv) * self.sine_amp / 3
return sine_merge, noise, uv
def padDiff(x):
return F.pad(F.pad(x, (0,0,-1,1), 'constant', 0) - x, (0,0,0,-1), 'constant', 0)
class Generator(torch.nn.Module):
def __init__(self, style_dim, resblock_kernel_sizes, upsample_rates, upsample_initial_channel, resblock_dilation_sizes, upsample_kernel_sizes):
super(Generator, self).__init__()
self.num_kernels = len(resblock_kernel_sizes)
self.num_upsamples = len(upsample_rates)
resblock = AdaINResBlock1
self.m_source = SourceModuleHnNSF(
sampling_rate=24000,
upsample_scale=np.prod(upsample_rates),
harmonic_num=8, voiced_threshod=10)
self.f0_upsamp = torch.nn.Upsample(scale_factor=np.prod(upsample_rates))
self.noise_convs = nn.ModuleList()
self.ups = nn.ModuleList()
self.noise_res = nn.ModuleList()
for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
c_cur = upsample_initial_channel // (2 ** (i + 1))
self.ups.append(weight_norm(ConvTranspose1d(upsample_initial_channel//(2**i),
upsample_initial_channel//(2**(i+1)),
k, u, padding=(u//2 + u%2), output_padding=u%2)))
if i + 1 < len(upsample_rates): #
stride_f0 = np.prod(upsample_rates[i + 1:])
self.noise_convs.append(Conv1d(
1, c_cur, kernel_size=stride_f0 * 2, stride=stride_f0, padding=(stride_f0+1) // 2))
self.noise_res.append(resblock(c_cur, 7, [1,3,5], style_dim))
else:
self.noise_convs.append(Conv1d(1, c_cur, kernel_size=1))
self.noise_res.append(resblock(c_cur, 11, [1,3,5], style_dim))
self.resblocks = nn.ModuleList()
self.alphas = nn.ParameterList()
self.alphas.append(nn.Parameter(torch.ones(1, upsample_initial_channel, 1)))
for i in range(len(self.ups)):
ch = upsample_initial_channel//(2**(i+1))
self.alphas.append(nn.Parameter(torch.ones(1, ch, 1)))
for j, (k, d) in enumerate(zip(resblock_kernel_sizes, resblock_dilation_sizes)):
self.resblocks.append(resblock(ch, k, d, style_dim))
self.conv_post = weight_norm(Conv1d(ch, 1, 7, 1, padding=3))
self.ups.apply(init_weights)
self.conv_post.apply(init_weights)
def forward(self, x, s, f0):
f0 = self.f0_upsamp(f0[:, None]).transpose(1, 2) # bs,n,t
har_source, noi_source, uv = self.m_source(f0)
har_source = har_source.transpose(1, 2)
for i in range(self.num_upsamples):
x = x + (1 / self.alphas[i]) * (torch.sin(self.alphas[i] * x) ** 2)
x_source = self.noise_convs[i](har_source)
x_source = self.noise_res[i](x_source, s)
x = self.ups[i](x)
x = x + x_source
xs = None
for j in range(self.num_kernels):
if xs is None:
xs = self.resblocks[i*self.num_kernels+j](x, s)
else:
xs += self.resblocks[i*self.num_kernels+j](x, s)
x = xs / self.num_kernels
x = x + (1 / self.alphas[i+1]) * (torch.sin(self.alphas[i+1] * x) ** 2)
x = self.conv_post(x)
x = torch.tanh(x)
return x
def remove_weight_norm(self):
print('Removing weight norm...')
for l in self.ups:
remove_weight_norm(l)
for l in self.resblocks:
l.remove_weight_norm()
remove_weight_norm(self.conv_pre)
remove_weight_norm(self.conv_post)
class AdainResBlk1d(nn.Module):
def __init__(self, dim_in, dim_out, style_dim=64, actv=nn.LeakyReLU(0.2),
upsample='none', dropout_p=0.0):
super().__init__()
self.actv = actv
self.upsample_type = upsample
self.upsample = UpSample1d(upsample)
self.learned_sc = dim_in != dim_out
self._build_weights(dim_in, dim_out, style_dim)
self.dropout = nn.Dropout(dropout_p)
if upsample == 'none':
self.pool = nn.Identity()
else:
self.pool = weight_norm(nn.ConvTranspose1d(dim_in, dim_in, kernel_size=3, stride=2, groups=dim_in, padding=1, output_padding=1))
def _build_weights(self, dim_in, dim_out, style_dim):
self.conv1 = weight_norm(nn.Conv1d(dim_in, dim_out, 3, 1, 1))
self.conv2 = weight_norm(nn.Conv1d(dim_out, dim_out, 3, 1, 1))
self.norm1 = AdaIN1d(style_dim, dim_in)
self.norm2 = AdaIN1d(style_dim, dim_out)
if self.learned_sc:
self.conv1x1 = weight_norm(nn.Conv1d(dim_in, dim_out, 1, 1, 0, bias=False))
def _shortcut(self, x):
x = self.upsample(x)
if self.learned_sc:
x = self.conv1x1(x)
return x
def _residual(self, x, s):
x = self.norm1(x, s)
x = self.actv(x)
x = self.pool(x)
x = self.conv1(self.dropout(x))
x = self.norm2(x, s)
x = self.actv(x)
x = self.conv2(self.dropout(x))
return x
def forward(self, x, s):
out = self._residual(x, s)
out = (out + self._shortcut(x)) / math.sqrt(2)
return out
class UpSample1d(nn.Module):
def __init__(self, layer_type):
super().__init__()
self.layer_type = layer_type
def forward(self, x):
if self.layer_type == 'none':
return x
else:
return F.interpolate(x, scale_factor=2, mode='nearest')
class Decoder(nn.Module):
def __init__(self, dim_in=512, F0_channel=512, style_dim=64, dim_out=80,
resblock_kernel_sizes = [3,7,11],
upsample_rates = [10,5,3,2],
upsample_initial_channel=512,
resblock_dilation_sizes=[[1,3,5], [1,3,5], [1,3,5]],
upsample_kernel_sizes=[20,10,6,4]):
super().__init__()
self.decode = nn.ModuleList()
self.encode = AdainResBlk1d(dim_in + 2, 1024, style_dim)
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 1024, style_dim))
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 1024, style_dim))
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 1024, style_dim))
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 512, style_dim, upsample=True))
self.F0_conv = weight_norm(nn.Conv1d(1, 1, kernel_size=3, stride=2, groups=1, padding=1))
self.N_conv = weight_norm(nn.Conv1d(1, 1, kernel_size=3, stride=2, groups=1, padding=1))
self.asr_res = nn.Sequential(
weight_norm(nn.Conv1d(512, 64, kernel_size=1)),
)
self.generator = Generator(style_dim, resblock_kernel_sizes, upsample_rates, upsample_initial_channel, resblock_dilation_sizes, upsample_kernel_sizes)
def forward(self, asr, F0_curve, N, s):
if self.training:
downlist = [0, 3, 7]
F0_down = downlist[random.randint(0, 2)]
downlist = [0, 3, 7, 15]
N_down = downlist[random.randint(0, 3)]
if F0_down:
F0_curve = nn.functional.conv1d(F0_curve.unsqueeze(1), torch.ones(1, 1, F0_down).to('cuda'), padding=F0_down//2).squeeze(1) / F0_down
if N_down:
N = nn.functional.conv1d(N.unsqueeze(1), torch.ones(1, 1, N_down).to('cuda'), padding=N_down//2).squeeze(1) / N_down
F0 = self.F0_conv(F0_curve.unsqueeze(1))
N = self.N_conv(N.unsqueeze(1))
x = torch.cat([asr, F0, N], axis=1)
x = self.encode(x, s)
asr_res = self.asr_res(asr)
res = True
for block in self.decode:
if res:
x = torch.cat([x, asr_res, F0, N], axis=1)
x = block(x, s)
if block.upsample_type != "none":
res = False
x = self.generator(x, s, F0_curve)
return x
+530
View File
@@ -0,0 +1,530 @@
import torch
import torch.nn.functional as F
import torch.nn as nn
from torch.nn import Conv1d, ConvTranspose1d, AvgPool1d, Conv2d
from torch.nn.utils import weight_norm, remove_weight_norm, spectral_norm
from .utils import init_weights, get_padding
import math
import random
import numpy as np
from scipy.signal import get_window
LRELU_SLOPE = 0.1
class AdaIN1d(nn.Module):
def __init__(self, style_dim, num_features):
super().__init__()
self.norm = nn.InstanceNorm1d(num_features, affine=False)
self.fc = nn.Linear(style_dim, num_features*2)
def forward(self, x, s):
h = self.fc(s)
h = h.view(h.size(0), h.size(1), 1)
gamma, beta = torch.chunk(h, chunks=2, dim=1)
return (1 + gamma) * self.norm(x) + beta
class AdaINResBlock1(torch.nn.Module):
def __init__(self, channels, kernel_size=3, dilation=(1, 3, 5), style_dim=64):
super(AdaINResBlock1, self).__init__()
self.convs1 = nn.ModuleList([
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=dilation[0],
padding=get_padding(kernel_size, dilation[0]))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=dilation[1],
padding=get_padding(kernel_size, dilation[1]))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=dilation[2],
padding=get_padding(kernel_size, dilation[2])))
])
self.convs1.apply(init_weights)
self.convs2 = nn.ModuleList([
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=1,
padding=get_padding(kernel_size, 1))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=1,
padding=get_padding(kernel_size, 1))),
weight_norm(Conv1d(channels, channels, kernel_size, 1, dilation=1,
padding=get_padding(kernel_size, 1)))
])
self.convs2.apply(init_weights)
self.adain1 = nn.ModuleList([
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
])
self.adain2 = nn.ModuleList([
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
AdaIN1d(style_dim, channels),
])
self.alpha1 = nn.ParameterList([nn.Parameter(torch.ones(1, channels, 1)) for i in range(len(self.convs1))])
self.alpha2 = nn.ParameterList([nn.Parameter(torch.ones(1, channels, 1)) for i in range(len(self.convs2))])
def forward(self, x, s):
for c1, c2, n1, n2, a1, a2 in zip(self.convs1, self.convs2, self.adain1, self.adain2, self.alpha1, self.alpha2):
xt = n1(x, s)
xt = xt + (1 / a1) * (torch.sin(a1 * xt) ** 2) # Snake1D
xt = c1(xt)
xt = n2(xt, s)
xt = xt + (1 / a2) * (torch.sin(a2 * xt) ** 2) # Snake1D
xt = c2(xt)
x = xt + x
return x
def remove_weight_norm(self):
for l in self.convs1:
remove_weight_norm(l)
for l in self.convs2:
remove_weight_norm(l)
class TorchSTFT(torch.nn.Module):
def __init__(self, filter_length=800, hop_length=200, win_length=800, window='hann'):
super().__init__()
self.filter_length = filter_length
self.hop_length = hop_length
self.win_length = win_length
self.window = torch.from_numpy(get_window(window, win_length, fftbins=True).astype(np.float32))
def transform(self, input_data):
forward_transform = torch.stft(
input_data,
self.filter_length, self.hop_length, self.win_length, window=self.window.to(input_data.device),
return_complex=True)
return torch.abs(forward_transform), torch.angle(forward_transform)
def inverse(self, magnitude, phase):
inverse_transform = torch.istft(
magnitude * torch.exp(phase * 1j),
self.filter_length, self.hop_length, self.win_length, window=self.window.to(magnitude.device))
return inverse_transform.unsqueeze(-2) # unsqueeze to stay consistent with conv_transpose1d implementation
def forward(self, input_data):
self.magnitude, self.phase = self.transform(input_data)
reconstruction = self.inverse(self.magnitude, self.phase)
return reconstruction
class SineGen(torch.nn.Module):
""" Definition of sine generator
SineGen(samp_rate, harmonic_num = 0,
sine_amp = 0.1, noise_std = 0.003,
voiced_threshold = 0,
flag_for_pulse=False)
samp_rate: sampling rate in Hz
harmonic_num: number of harmonic overtones (default 0)
sine_amp: amplitude of sine-wavefrom (default 0.1)
noise_std: std of Gaussian noise (default 0.003)
voiced_thoreshold: F0 threshold for U/V classification (default 0)
flag_for_pulse: this SinGen is used inside PulseGen (default False)
Note: when flag_for_pulse is True, the first time step of a voiced
segment is always sin(np.pi) or cos(0)
"""
def __init__(self, samp_rate, upsample_scale, harmonic_num=0,
sine_amp=0.1, noise_std=0.003,
voiced_threshold=0,
flag_for_pulse=False):
super(SineGen, self).__init__()
self.sine_amp = sine_amp
self.noise_std = noise_std
self.harmonic_num = harmonic_num
self.dim = self.harmonic_num + 1
self.sampling_rate = samp_rate
self.voiced_threshold = voiced_threshold
self.flag_for_pulse = flag_for_pulse
self.upsample_scale = upsample_scale
def _f02uv(self, f0):
# generate uv signal
uv = (f0 > self.voiced_threshold).type(torch.float32)
return uv
def _f02sine(self, f0_values):
""" f0_values: (batchsize, length, dim)
where dim indicates fundamental tone and overtones
"""
# convert to F0 in rad. The interger part n can be ignored
# because 2 * np.pi * n doesn't affect phase
rad_values = (f0_values / self.sampling_rate) % 1
# initial phase noise (no noise for fundamental component)
rand_ini = torch.rand(f0_values.shape[0], f0_values.shape[2], \
device=f0_values.device)
rand_ini[:, 0] = 0
rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini
# instantanouse phase sine[t] = sin(2*pi \sum_i=1 ^{t} rad)
if not self.flag_for_pulse:
# # for normal case
# # To prevent torch.cumsum numerical overflow,
# # it is necessary to add -1 whenever \sum_k=1^n rad_value_k > 1.
# # Buffer tmp_over_one_idx indicates the time step to add -1.
# # This will not change F0 of sine because (x-1) * 2*pi = x * 2*pi
# tmp_over_one = torch.cumsum(rad_values, 1) % 1
# tmp_over_one_idx = (padDiff(tmp_over_one)) < 0
# cumsum_shift = torch.zeros_like(rad_values)
# cumsum_shift[:, 1:, :] = tmp_over_one_idx * -1.0
# phase = torch.cumsum(rad_values, dim=1) * 2 * np.pi
rad_values = torch.nn.functional.interpolate(rad_values.transpose(1, 2),
scale_factor=1/self.upsample_scale,
mode="linear").transpose(1, 2)
# tmp_over_one = torch.cumsum(rad_values, 1) % 1
# tmp_over_one_idx = (padDiff(tmp_over_one)) < 0
# cumsum_shift = torch.zeros_like(rad_values)
# cumsum_shift[:, 1:, :] = tmp_over_one_idx * -1.0
phase = torch.cumsum(rad_values, dim=1) * 2 * np.pi
phase = torch.nn.functional.interpolate(phase.transpose(1, 2) * self.upsample_scale,
scale_factor=self.upsample_scale, mode="linear").transpose(1, 2)
sines = torch.sin(phase)
else:
# If necessary, make sure that the first time step of every
# voiced segments is sin(pi) or cos(0)
# This is used for pulse-train generation
# identify the last time step in unvoiced segments
uv = self._f02uv(f0_values)
uv_1 = torch.roll(uv, shifts=-1, dims=1)
uv_1[:, -1, :] = 1
u_loc = (uv < 1) * (uv_1 > 0)
# get the instantanouse phase
tmp_cumsum = torch.cumsum(rad_values, dim=1)
# different batch needs to be processed differently
for idx in range(f0_values.shape[0]):
temp_sum = tmp_cumsum[idx, u_loc[idx, :, 0], :]
temp_sum[1:, :] = temp_sum[1:, :] - temp_sum[0:-1, :]
# stores the accumulation of i.phase within
# each voiced segments
tmp_cumsum[idx, :, :] = 0
tmp_cumsum[idx, u_loc[idx, :, 0], :] = temp_sum
# rad_values - tmp_cumsum: remove the accumulation of i.phase
# within the previous voiced segment.
i_phase = torch.cumsum(rad_values - tmp_cumsum, dim=1)
# get the sines
sines = torch.cos(i_phase * 2 * np.pi)
return sines
def forward(self, f0):
""" sine_tensor, uv = forward(f0)
input F0: tensor(batchsize=1, length, dim=1)
f0 for unvoiced steps should be 0
output sine_tensor: tensor(batchsize=1, length, dim)
output uv: tensor(batchsize=1, length, 1)
"""
f0_buf = torch.zeros(f0.shape[0], f0.shape[1], self.dim,
device=f0.device)
# fundamental component
fn = torch.multiply(f0, torch.FloatTensor([[range(1, self.harmonic_num + 2)]]).to(f0.device))
# generate sine waveforms
sine_waves = self._f02sine(fn) * self.sine_amp
# generate uv signal
# uv = torch.ones(f0.shape)
# uv = uv * (f0 > self.voiced_threshold)
uv = self._f02uv(f0)
# noise: for unvoiced should be similar to sine_amp
# std = self.sine_amp/3 -> max value ~ self.sine_amp
# . for voiced regions is self.noise_std
noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
noise = noise_amp * torch.randn_like(sine_waves)
# first: set the unvoiced part to 0 by uv
# then: additive noise
sine_waves = sine_waves * uv + noise
return sine_waves, uv, noise
class SourceModuleHnNSF(torch.nn.Module):
""" SourceModule for hn-nsf
SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1,
add_noise_std=0.003, voiced_threshod=0)
sampling_rate: sampling_rate in Hz
harmonic_num: number of harmonic above F0 (default: 0)
sine_amp: amplitude of sine source signal (default: 0.1)
add_noise_std: std of additive Gaussian noise (default: 0.003)
note that amplitude of noise in unvoiced is decided
by sine_amp
voiced_threshold: threhold to set U/V given F0 (default: 0)
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
F0_sampled (batchsize, length, 1)
Sine_source (batchsize, length, 1)
noise_source (batchsize, length 1)
uv (batchsize, length, 1)
"""
def __init__(self, sampling_rate, upsample_scale, harmonic_num=0, sine_amp=0.1,
add_noise_std=0.003, voiced_threshod=0):
super(SourceModuleHnNSF, self).__init__()
self.sine_amp = sine_amp
self.noise_std = add_noise_std
# to produce sine waveforms
self.l_sin_gen = SineGen(sampling_rate, upsample_scale, harmonic_num,
sine_amp, add_noise_std, voiced_threshod)
# to merge source harmonics into a single excitation
self.l_linear = torch.nn.Linear(harmonic_num + 1, 1)
self.l_tanh = torch.nn.Tanh()
def forward(self, x):
"""
Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
F0_sampled (batchsize, length, 1)
Sine_source (batchsize, length, 1)
noise_source (batchsize, length 1)
"""
# source for harmonic branch
with torch.no_grad():
sine_wavs, uv, _ = self.l_sin_gen(x)
sine_merge = self.l_tanh(self.l_linear(sine_wavs))
# source for noise branch, in the same shape as uv
noise = torch.randn_like(uv) * self.sine_amp / 3
return sine_merge, noise, uv
def padDiff(x):
return F.pad(F.pad(x, (0,0,-1,1), 'constant', 0) - x, (0,0,0,-1), 'constant', 0)
class Generator(torch.nn.Module):
def __init__(self, style_dim, resblock_kernel_sizes, upsample_rates, upsample_initial_channel, resblock_dilation_sizes, upsample_kernel_sizes, gen_istft_n_fft, gen_istft_hop_size):
super(Generator, self).__init__()
self.num_kernels = len(resblock_kernel_sizes)
self.num_upsamples = len(upsample_rates)
resblock = AdaINResBlock1
self.m_source = SourceModuleHnNSF(
sampling_rate=24000,
upsample_scale=np.prod(upsample_rates) * gen_istft_hop_size,
harmonic_num=8, voiced_threshod=10)
self.f0_upsamp = torch.nn.Upsample(scale_factor=np.prod(upsample_rates) * gen_istft_hop_size)
self.noise_convs = nn.ModuleList()
self.noise_res = nn.ModuleList()
self.ups = nn.ModuleList()
for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
self.ups.append(weight_norm(
ConvTranspose1d(upsample_initial_channel//(2**i), upsample_initial_channel//(2**(i+1)),
k, u, padding=(k-u)//2)))
self.resblocks = nn.ModuleList()
for i in range(len(self.ups)):
ch = upsample_initial_channel//(2**(i+1))
for j, (k, d) in enumerate(zip(resblock_kernel_sizes,resblock_dilation_sizes)):
self.resblocks.append(resblock(ch, k, d, style_dim))
c_cur = upsample_initial_channel // (2 ** (i + 1))
if i + 1 < len(upsample_rates): #
stride_f0 = np.prod(upsample_rates[i + 1:])
self.noise_convs.append(Conv1d(
gen_istft_n_fft + 2, c_cur, kernel_size=stride_f0 * 2, stride=stride_f0, padding=(stride_f0+1) // 2))
self.noise_res.append(resblock(c_cur, 7, [1,3,5], style_dim))
else:
self.noise_convs.append(Conv1d(gen_istft_n_fft + 2, c_cur, kernel_size=1))
self.noise_res.append(resblock(c_cur, 11, [1,3,5], style_dim))
self.post_n_fft = gen_istft_n_fft
self.conv_post = weight_norm(Conv1d(ch, self.post_n_fft + 2, 7, 1, padding=3))
self.ups.apply(init_weights)
self.conv_post.apply(init_weights)
self.reflection_pad = torch.nn.ReflectionPad1d((1, 0))
self.stft = TorchSTFT(filter_length=gen_istft_n_fft, hop_length=gen_istft_hop_size, win_length=gen_istft_n_fft)
def forward(self, x, s, f0):
with torch.no_grad():
f0 = self.f0_upsamp(f0[:, None]).transpose(1, 2) # bs,n,t
har_source, noi_source, uv = self.m_source(f0)
har_source = har_source.transpose(1, 2).squeeze(1)
har_spec, har_phase = self.stft.transform(har_source)
har = torch.cat([har_spec, har_phase], dim=1)
for i in range(self.num_upsamples):
x = F.leaky_relu(x, LRELU_SLOPE)
x_source = self.noise_convs[i](har)
x_source = self.noise_res[i](x_source, s)
x = self.ups[i](x)
if i == self.num_upsamples - 1:
x = self.reflection_pad(x)
x = x + x_source
xs = None
for j in range(self.num_kernels):
if xs is None:
xs = self.resblocks[i*self.num_kernels+j](x, s)
else:
xs += self.resblocks[i*self.num_kernels+j](x, s)
x = xs / self.num_kernels
x = F.leaky_relu(x)
x = self.conv_post(x)
spec = torch.exp(x[:,:self.post_n_fft // 2 + 1, :])
phase = torch.sin(x[:, self.post_n_fft // 2 + 1:, :])
return self.stft.inverse(spec, phase)
def fw_phase(self, x, s):
for i in range(self.num_upsamples):
x = F.leaky_relu(x, LRELU_SLOPE)
x = self.ups[i](x)
xs = None
for j in range(self.num_kernels):
if xs is None:
xs = self.resblocks[i*self.num_kernels+j](x, s)
else:
xs += self.resblocks[i*self.num_kernels+j](x, s)
x = xs / self.num_kernels
x = F.leaky_relu(x)
x = self.reflection_pad(x)
x = self.conv_post(x)
spec = torch.exp(x[:,:self.post_n_fft // 2 + 1, :])
phase = torch.sin(x[:, self.post_n_fft // 2 + 1:, :])
return spec, phase
def remove_weight_norm(self):
print('Removing weight norm...')
for l in self.ups:
remove_weight_norm(l)
for l in self.resblocks:
l.remove_weight_norm()
remove_weight_norm(self.conv_pre)
remove_weight_norm(self.conv_post)
class AdainResBlk1d(nn.Module):
def __init__(self, dim_in, dim_out, style_dim=64, actv=nn.LeakyReLU(0.2),
upsample='none', dropout_p=0.0):
super().__init__()
self.actv = actv
self.upsample_type = upsample
self.upsample = UpSample1d(upsample)
self.learned_sc = dim_in != dim_out
self._build_weights(dim_in, dim_out, style_dim)
self.dropout = nn.Dropout(dropout_p)
if upsample == 'none':
self.pool = nn.Identity()
else:
self.pool = weight_norm(nn.ConvTranspose1d(dim_in, dim_in, kernel_size=3, stride=2, groups=dim_in, padding=1, output_padding=1))
def _build_weights(self, dim_in, dim_out, style_dim):
self.conv1 = weight_norm(nn.Conv1d(dim_in, dim_out, 3, 1, 1))
self.conv2 = weight_norm(nn.Conv1d(dim_out, dim_out, 3, 1, 1))
self.norm1 = AdaIN1d(style_dim, dim_in)
self.norm2 = AdaIN1d(style_dim, dim_out)
if self.learned_sc:
self.conv1x1 = weight_norm(nn.Conv1d(dim_in, dim_out, 1, 1, 0, bias=False))
def _shortcut(self, x):
x = self.upsample(x)
if self.learned_sc:
x = self.conv1x1(x)
return x
def _residual(self, x, s):
x = self.norm1(x, s)
x = self.actv(x)
x = self.pool(x)
x = self.conv1(self.dropout(x))
x = self.norm2(x, s)
x = self.actv(x)
x = self.conv2(self.dropout(x))
return x
def forward(self, x, s):
out = self._residual(x, s)
out = (out + self._shortcut(x)) / math.sqrt(2)
return out
class UpSample1d(nn.Module):
def __init__(self, layer_type):
super().__init__()
self.layer_type = layer_type
def forward(self, x):
if self.layer_type == 'none':
return x
else:
return F.interpolate(x, scale_factor=2, mode='nearest')
class Decoder(nn.Module):
def __init__(self, dim_in=512, F0_channel=512, style_dim=64, dim_out=80,
resblock_kernel_sizes = [3,7,11],
upsample_rates = [10, 6],
upsample_initial_channel=512,
resblock_dilation_sizes=[[1,3,5], [1,3,5], [1,3,5]],
upsample_kernel_sizes=[20, 12],
gen_istft_n_fft=20, gen_istft_hop_size=5):
super().__init__()
self.decode = nn.ModuleList()
self.encode = AdainResBlk1d(dim_in + 2, 1024, style_dim)
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 1024, style_dim))
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 1024, style_dim))
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 1024, style_dim))
self.decode.append(AdainResBlk1d(1024 + 2 + 64, 512, style_dim, upsample=True))
self.F0_conv = weight_norm(nn.Conv1d(1, 1, kernel_size=3, stride=2, groups=1, padding=1))
self.N_conv = weight_norm(nn.Conv1d(1, 1, kernel_size=3, stride=2, groups=1, padding=1))
self.asr_res = nn.Sequential(
weight_norm(nn.Conv1d(512, 64, kernel_size=1)),
)
self.generator = Generator(style_dim, resblock_kernel_sizes, upsample_rates,
upsample_initial_channel, resblock_dilation_sizes,
upsample_kernel_sizes, gen_istft_n_fft, gen_istft_hop_size)
def forward(self, asr, F0_curve, N, s):
if self.training:
downlist = [0, 3, 7]
F0_down = downlist[random.randint(0, 2)]
downlist = [0, 3, 7, 15]
N_down = downlist[random.randint(0, 3)]
if F0_down:
F0_curve = nn.functional.conv1d(F0_curve.unsqueeze(1), torch.ones(1, 1, F0_down).to('cuda'), padding=F0_down//2).squeeze(1) / F0_down
if N_down:
N = nn.functional.conv1d(N.unsqueeze(1), torch.ones(1, 1, N_down).to('cuda'), padding=N_down//2).squeeze(1) / N_down
F0 = self.F0_conv(F0_curve.unsqueeze(1))
N = self.N_conv(N.unsqueeze(1))
x = torch.cat([asr, F0, N], axis=1)
x = self.encode(x, s)
asr_res = self.asr_res(asr)
res = True
for block in self.decode:
if res:
x = torch.cat([x, asr_res, F0, N], axis=1)
x = block(x, s)
if block.upsample_type != "none":
res = False
x = self.generator(x, s, F0_curve)
return x
+195
View File
@@ -0,0 +1,195 @@
import torch
import numpy as np
import torch.nn.functional as F
class SLMAdversarialLoss(torch.nn.Module):
def __init__(self, model, wl, sampler, min_len, max_len, batch_percentage=0.5, skip_update=10, sig=1.5):
super(SLMAdversarialLoss, self).__init__()
self.model = model
self.wl = wl
self.sampler = sampler
self.min_len = min_len
self.max_len = max_len
self.batch_percentage = batch_percentage
self.sig = sig
self.skip_update = skip_update
def forward(self, iters, y_rec_gt, y_rec_gt_pred, waves, mel_input_length, ref_text, ref_lengths, use_ind, s_trg, ref_s=None):
text_mask = length_to_mask(ref_lengths).to(ref_text.device)
bert_dur = self.model.bert(ref_text, attention_mask=(~text_mask).int())
d_en = self.model.bert_encoder(bert_dur).transpose(-1, -2)
if use_ind and np.random.rand() < 0.5:
s_preds = s_trg
else:
num_steps = np.random.randint(3, 5)
if ref_s is not None:
s_preds = self.sampler(noise = torch.randn_like(s_trg).unsqueeze(1).to(ref_text.device),
embedding=bert_dur,
embedding_scale=1,
features=ref_s, # reference from the same speaker as the embedding
embedding_mask_proba=0.1,
num_steps=num_steps).squeeze(1)
else:
s_preds = self.sampler(noise = torch.randn_like(s_trg).unsqueeze(1).to(ref_text.device),
embedding=bert_dur,
embedding_scale=1,
embedding_mask_proba=0.1,
num_steps=num_steps).squeeze(1)
s_dur = s_preds[:, 128:]
s = s_preds[:, :128]
d, _ = self.model.predictor(d_en, s_dur,
ref_lengths,
torch.randn(ref_lengths.shape[0], ref_lengths.max(), 2).to(ref_text.device),
text_mask)
bib = 0
output_lengths = []
attn_preds = []
# differentiable duration modeling
for _s2s_pred, _text_length in zip(d, ref_lengths):
_s2s_pred_org = _s2s_pred[:_text_length, :]
_s2s_pred = torch.sigmoid(_s2s_pred_org)
_dur_pred = _s2s_pred.sum(axis=-1)
l = int(torch.round(_s2s_pred.sum()).item())
t = torch.arange(0, l).expand(l)
t = torch.arange(0, l).unsqueeze(0).expand((len(_s2s_pred), l)).to(ref_text.device)
loc = torch.cumsum(_dur_pred, dim=0) - _dur_pred / 2
h = torch.exp(-0.5 * torch.square(t - (l - loc.unsqueeze(-1))) / (self.sig)**2)
out = torch.nn.functional.conv1d(_s2s_pred_org.unsqueeze(0),
h.unsqueeze(1),
padding=h.shape[-1] - 1, groups=int(_text_length))[..., :l]
attn_preds.append(F.softmax(out.squeeze(), dim=0))
output_lengths.append(l)
max_len = max(output_lengths)
with torch.no_grad():
t_en = self.model.text_encoder(ref_text, ref_lengths, text_mask)
s2s_attn = torch.zeros(len(ref_lengths), int(ref_lengths.max()), max_len).to(ref_text.device)
for bib in range(len(output_lengths)):
s2s_attn[bib, :ref_lengths[bib], :output_lengths[bib]] = attn_preds[bib]
asr_pred = t_en @ s2s_attn
_, p_pred = self.model.predictor(d_en, s_dur,
ref_lengths,
s2s_attn,
text_mask)
mel_len = max(int(min(output_lengths) / 2 - 1), self.min_len // 2)
mel_len = min(mel_len, self.max_len // 2)
# get clips
en = []
p_en = []
sp = []
F0_fakes = []
N_fakes = []
wav = []
for bib in range(len(output_lengths)):
mel_length_pred = output_lengths[bib]
mel_length_gt = int(mel_input_length[bib].item() / 2)
if mel_length_gt <= mel_len or mel_length_pred <= mel_len:
continue
sp.append(s_preds[bib])
random_start = np.random.randint(0, mel_length_pred - mel_len)
en.append(asr_pred[bib, :, random_start:random_start+mel_len])
p_en.append(p_pred[bib, :, random_start:random_start+mel_len])
# get ground truth clips
random_start = np.random.randint(0, mel_length_gt - mel_len)
y = waves[bib][(random_start * 2) * 300:((random_start+mel_len) * 2) * 300]
wav.append(torch.from_numpy(y).to(ref_text.device))
if len(wav) >= self.batch_percentage * len(waves): # prevent OOM due to longer lengths
break
if len(sp) <= 1:
return None
sp = torch.stack(sp)
wav = torch.stack(wav).float()
en = torch.stack(en)
p_en = torch.stack(p_en)
F0_fake, N_fake = self.model.predictor.F0Ntrain(p_en, sp[:, 128:])
y_pred = self.model.decoder(en, F0_fake, N_fake, sp[:, :128])
# discriminator loss
if (iters + 1) % self.skip_update == 0:
if np.random.randint(0, 2) == 0:
wav = y_rec_gt_pred
use_rec = True
else:
use_rec = False
crop_size = min(wav.size(-1), y_pred.size(-1))
if use_rec: # use reconstructed (shorter lengths), do length invariant regularization
if wav.size(-1) > y_pred.size(-1):
real_GP = wav[:, : , :crop_size]
out_crop = self.wl.discriminator_forward(real_GP.detach().squeeze())
out_org = self.wl.discriminator_forward(wav.detach().squeeze())
loss_reg = F.l1_loss(out_crop, out_org[..., :out_crop.size(-1)])
if np.random.randint(0, 2) == 0:
d_loss = self.wl.discriminator(real_GP.detach().squeeze(), y_pred.detach().squeeze()).mean()
else:
d_loss = self.wl.discriminator(wav.detach().squeeze(), y_pred.detach().squeeze()).mean()
else:
real_GP = y_pred[:, : , :crop_size]
out_crop = self.wl.discriminator_forward(real_GP.detach().squeeze())
out_org = self.wl.discriminator_forward(y_pred.detach().squeeze())
loss_reg = F.l1_loss(out_crop, out_org[..., :out_crop.size(-1)])
if np.random.randint(0, 2) == 0:
d_loss = self.wl.discriminator(wav.detach().squeeze(), real_GP.detach().squeeze()).mean()
else:
d_loss = self.wl.discriminator(wav.detach().squeeze(), y_pred.detach().squeeze()).mean()
# regularization (ignore length variation)
d_loss += loss_reg
out_gt = self.wl.discriminator_forward(y_rec_gt.detach().squeeze())
out_rec = self.wl.discriminator_forward(y_rec_gt_pred.detach().squeeze())
# regularization (ignore reconstruction artifacts)
d_loss += F.l1_loss(out_gt, out_rec)
else:
d_loss = self.wl.discriminator(wav.detach().squeeze(), y_pred.detach().squeeze()).mean()
else:
d_loss = 0
# generator loss
gen_loss = self.wl.generator(y_pred.squeeze())
gen_loss = gen_loss.mean()
return d_loss, gen_loss, y_pred.detach().cpu().numpy()
def length_to_mask(lengths):
mask = torch.arange(lengths.max()).unsqueeze(0).expand(lengths.shape[0], -1).type_as(lengths)
mask = torch.gt(mask+1, lengths.unsqueeze(1))
return mask
+14
View File
@@ -0,0 +1,14 @@
def init_weights(m, mean=0.0, std=0.01):
classname = m.__class__.__name__
if classname.find("Conv") != -1:
m.weight.data.normal_(mean, std)
def apply_weight_norm(m):
classname = m.__class__.__name__
if classname.find("Conv") != -1:
weight_norm(m)
def get_padding(kernel_size, dilation=1):
return int((kernel_size*dilation - dilation)/2)
+125
View File
@@ -0,0 +1,125 @@
# StyleTTS 2: Towards Human-Level Text-to-Speech through Style Diffusion and Adversarial Training with Large Speech Language Models
### Yinghao Aaron Li, Cong Han, Vinay S. Raghavan, Gavin Mischler, Nima Mesgarani
> In this paper, we present StyleTTS 2, a text-to-speech (TTS) model that leverages style diffusion and adversarial training with large speech language models (SLMs) to achieve human-level TTS synthesis. StyleTTS 2 differs from its predecessor by modeling styles as a latent random variable through diffusion models to generate the most suitable style for the text without requiring reference speech, achieving efficient latent diffusion while benefiting from the diverse speech synthesis offered by diffusion models. Furthermore, we employ large pre-trained SLMs, such as WavLM, as discriminators with our novel differentiable duration modeling for end-to-end training, resulting in improved speech naturalness. StyleTTS 2 surpasses human recordings on the single-speaker LJSpeech dataset and matches it on the multispeaker VCTK dataset as judged by native English speakers. Moreover, when trained on the LibriTTS dataset, our model outperforms previous publicly available models for zero-shot speaker adaptation. This work achieves the first human-level TTS synthesis on both single and multispeaker datasets, showcasing the potential of style diffusion and adversarial training with large SLMs.
Paper: [https://arxiv.org/abs/2306.07691](https://arxiv.org/abs/2306.07691)
Audio samples: [https://styletts2.github.io/](https://styletts2.github.io/)
Online demo: [Hugging Face](https://huggingface.co/spaces/styletts2/styletts2) (thank [@fakerybakery](https://github.com/fakerybakery) for the wonderful online demo)
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/yl4579/StyleTTS2/blob/main/) [![Discord](https://img.shields.io/discord/1197679063150637117?logo=discord&logoColor=white&label=Join%20our%20Community)](https://discord.gg/ha8sxdG2K4)
## TODO
- [x] Training and inference demo code for single-speaker models (LJSpeech)
- [x] Test training code for multi-speaker models (VCTK and LibriTTS)
- [x] Finish demo code for multispeaker model and upload pre-trained models
- [x] Add a finetuning script for new speakers with base pre-trained multispeaker models
- [ ] Fix DDP (accelerator) for `train_second.py` **(I have tried everything I could to fix this but had no success, so if you are willing to help, please see [#7](https://github.com/yl4579/StyleTTS2/issues/7))**
## Pre-requisites
1. Python >= 3.7
2. Clone this repository:
```bash
git clone https://github.com/yl4579/StyleTTS2.git
cd StyleTTS2
```
3. Install python requirements:
```bash
pip install -r requirements.txt
```
On Windows add:
```bash
pip install torch torchvision torchaudio --index-url https://download.pytorch.org/whl/cu118 -U
```
Also install phonemizer and espeak if you want to run the demo:
```bash
pip install phonemizer
sudo apt-get install espeak-ng
```
4. Download and extract the [LJSpeech dataset](https://keithito.com/LJ-Speech-Dataset/), unzip to the data folder and upsample the data to 24 kHz. The text aligner and pitch extractor are pre-trained on 24 kHz data, but you can easily change the preprocessing and re-train them using your own preprocessing.
For LibriTTS, you will need to combine train-clean-360 with train-clean-100 and rename the folder train-clean-460 (see [val_list_libritts.txt](https://github.com/yl4579/StyleTTS/blob/main/Data/val_list_libritts.txt) as an example).
## Training
First stage training:
```bash
accelerate launch train_first.py --config_path ./Configs/config.yml
```
Second stage training **(DDP version not working, so the current version uses DP, again see [#7](https://github.com/yl4579/StyleTTS2/issues/7) if you want to help)**:
```bash
python train_second.py --config_path ./Configs/config.yml
```
You can run both consecutively and it will train both the first and second stages. The model will be saved in the format "epoch_1st_%05d.pth" and "epoch_2nd_%05d.pth". Checkpoints and Tensorboard logs will be saved at `log_dir`.
The data list format needs to be `filename.wav|transcription|speaker`, see [val_list.txt](https://github.com/yl4579/StyleTTS2/blob/main/Data/val_list.txt) as an example. The speaker labels are needed for multi-speaker models because we need to sample reference audio for style diffusion model training.
### Important Configurations
In [config.yml](https://github.com/yl4579/StyleTTS2/blob/main/Configs/config.yml), there are a few important configurations to take care of:
- `OOD_data`: The path for out-of-distribution texts for SLM adversarial training. The format should be `text|anything`.
- `min_length`: Minimum length of OOD texts for training. This is to make sure the synthesized speech has a minimum length.
- `max_len`: Maximum length of audio for training. The unit is frame. Since the default hop size is 300, one frame is approximately `300 / 24000` (0.0125) second. Lowering this if you encounter the out-of-memory issue.
- `multispeaker`: Set to true if you want to train a multispeaker model. This is needed because the architecture of the denoiser is different for single and multispeaker models.
- `batch_percentage`: This is to make sure during SLM adversarial training there are no out-of-memory (OOM) issues. If you encounter OOM problem, please set a lower number for this.
### Pre-trained modules
In [Utils](https://github.com/yl4579/StyleTTS2/tree/main/Utils) folder, there are three pre-trained models:
- **[ASR](https://github.com/yl4579/StyleTTS2/tree/main/Utils/ASR) folder**: It contains the pre-trained text aligner, which was pre-trained on English (LibriTTS), Japanese (JVS), and Chinese (AiShell) corpus. It works well for most other languages without fine-tuning, but you can always train your own text aligner with the code here: [yl4579/AuxiliaryASR](https://github.com/yl4579/AuxiliaryASR).
- **[JDC](https://github.com/yl4579/StyleTTS2/tree/main/Utils/JDC) folder**: It contains the pre-trained pitch extractor, which was pre-trained on English (LibriTTS) corpus only. However, it works well for other languages too because F0 is independent of language. If you want to train on singing corpus, it is recommended to train a new pitch extractor with the code here: [yl4579/PitchExtractor](https://github.com/yl4579/PitchExtractor).
- **[PLBERT](https://github.com/yl4579/StyleTTS2/tree/main/Utils/PLBERT) folder**: It contains the pre-trained [PL-BERT](https://arxiv.org/abs/2301.08810) model, which was pre-trained on English (Wikipedia) corpus only. It probably does not work very well on other languages, so you will need to train a different PL-BERT for different languages using the repo here: [yl4579/PL-BERT](https://github.com/yl4579/PL-BERT). You can also use the [multilingual PL-BERT](https://huggingface.co/papercup-ai/multilingual-pl-bert) which supports 14 languages.
### Common Issues
- **Loss becomes NaN**: If it is the first stage, please make sure you do not use mixed precision, as it can cause loss becoming NaN for some particular datasets when the batch size is not set properly (need to be more than 16 to work well). For the second stage, please also experiment with different batch sizes, with higher batch sizes being more likely to cause NaN loss values. We recommend the batch size to be 16. You can refer to issues [#10](https://github.com/yl4579/StyleTTS2/issues/10) and [#11](https://github.com/yl4579/StyleTTS2/issues/11) for more details.
- **Out of memory**: Please either use lower `batch_size` or `max_len`. You may refer to issue [#10](https://github.com/yl4579/StyleTTS2/issues/10) for more information.
- **Non-English dataset**: You can train on any language you want, but you will need to use a pre-trained PL-BERT model for that language. We have a pre-trained [multilingual PL-BERT](https://huggingface.co/papercup-ai/multilingual-pl-bert) that supports 14 languages. You may refer to [yl4579/StyleTTS#10](https://github.com/yl4579/StyleTTS/issues/10) and [#70](https://github.com/yl4579/StyleTTS2/issues/70) for some examples to train on Chinese datasets.
## Finetuning
The script is modified from `train_second.py` which uses DP, as DDP does not work for `train_second.py`. Please see the bold section above if you are willing to help with this problem.
```bash
python train_finetune.py --config_path ./Configs/config_ft.yml
```
Please make sure you have the LibriTTS checkpoint downloaded and unzipped under the folder. The default configuration `config_ft.yml` finetunes on LJSpeech with 1 hour of speech data (around 1k samples) for 50 epochs. This took about 4 hours to finish on four NVidia A100. The quality is slightly worse (similar to NaturalSpeech on LJSpeech) than LJSpeech model trained from scratch with 24 hours of speech data, which took around 2.5 days to finish on four A100. The samples can be found at [#65 (comment)](https://github.com/yl4579/StyleTTS2/discussions/65#discussioncomment-7668393).
If you are using a **single GPU** (because the script doesn't work with DDP) and want to save training speed and VRAM, you can do (thank [@korakoe](https://github.com/korakoe) for making the script at [#100](https://github.com/yl4579/StyleTTS2/pull/100)):
```bash
accelerate launch --mixed_precision=fp16 --num_processes=1 train_finetune_accelerate.py --config_path ./Configs/config_ft.yml
```
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/yl4579/StyleTTS2/blob/main/Colab/StyleTTS2_Finetune_Demo.ipynb)
### Common Issues
[@Kreevoz](https://github.com/Kreevoz) has made detailed notes on common issues in finetuning, with suggestions in maximizing audio quality: [#81](https://github.com/yl4579/StyleTTS2/discussions/81). Some of these also apply to training from scratch. [@IIEleven11](https://github.com/IIEleven11) has also made a guideline for fine-tuning: [#128](https://github.com/yl4579/StyleTTS2/discussions/128).
- **Out of memory after `joint_epoch`**: This is likely because your GPU RAM is not big enough for SLM adversarial training run. You may skip that but the quality could be worse. Setting `joint_epoch` a larger number than `epochs` could skip the SLM advesariral training.
## Inference
Please refer to [Inference_LJSpeech.ipynb](https://github.com/yl4579/StyleTTS2/blob/main/Demo/Inference_LJSpeech.ipynb) (single-speaker) and [Inference_LibriTTS.ipynb](https://github.com/yl4579/StyleTTS2/blob/main/Demo/Inference_LibriTTS.ipynb) (multi-speaker) for details. For LibriTTS, you will also need to download [reference_audio.zip](https://huggingface.co/yl4579/StyleTTS2-LibriTTS/resolve/main/reference_audio.zip) and unzip it under the `demo` before running the demo.
- The pretrained StyleTTS 2 on LJSpeech corpus in 24 kHz can be downloaded at [https://huggingface.co/yl4579/StyleTTS2-LJSpeech/tree/main](https://huggingface.co/yl4579/StyleTTS2-LJSpeech/tree/main).
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/yl4579/StyleTTS2/blob/main/Colab/StyleTTS2_Demo_LJSpeech.ipynb)
- The pretrained StyleTTS 2 model on LibriTTS can be downloaded at [https://huggingface.co/yl4579/StyleTTS2-LibriTTS/tree/main](https://huggingface.co/yl4579/StyleTTS2-LibriTTS/tree/main).
[![Open In Colab](https://colab.research.google.com/assets/colab-badge.svg)](https://colab.research.google.com/github/yl4579/StyleTTS2/blob/main/Colab/StyleTTS2_Demo_LibriTTS.ipynb)
You can import StyleTTS 2 and run it in your own code. However, the inference depends on a GPL-licensed package, so it is not included directly in this repository. A [GPL-licensed fork](https://github.com/NeuralVox/StyleTTS2) has an importable script, as well as an experimental streaming API, etc. A [fully MIT-licensed package](https://pypi.org/project/styletts2/) that uses gruut (albeit lower quality due to mismatch between phonemizer and gruut) is also available.
***Before using these pre-trained models, you agree to inform the listeners that the speech samples are synthesized by the pre-trained models, unless you have the permission to use the voice you synthesize. That is, you agree to only use voices whose speakers grant the permission to have their voice cloned, either directly or by license before making synthesized voices public, or you have to publicly announce that these voices are synthesized if you do not have the permission to use these voices.***
### Common Issues
- **High-pitched background noise**: This is caused by numerical float differences in older GPUs. For more details, please refer to issue [#13](https://github.com/yl4579/StyleTTS2/issues/13). Basically, you will need to use more modern GPUs or do inference on CPUs.
- **Pre-trained model license**: You only need to abide by the above rules if you use **the pre-trained models** and the voices are **NOT** in the training set, i.e., your reference speakers are not from any open access dataset. For more details of rules to use the pre-trained models, please see [#37](https://github.com/yl4579/StyleTTS2/issues/37).
## References
- [archinetai/audio-diffusion-pytorch](https://github.com/archinetai/audio-diffusion-pytorch)
- [jik876/hifi-gan](https://github.com/jik876/hifi-gan)
- [rishikksh20/iSTFTNet-pytorch](https://github.com/rishikksh20/iSTFTNet-pytorch)
- [nii-yamagishilab/project-NN-Pytorch-scripts/project/01-nsf](https://github.com/nii-yamagishilab/project-NN-Pytorch-scripts/tree/master/project/01-nsf)
## License
Code: MIT License
Pre-Trained Models: Before using these pre-trained models, you agree to inform the listeners that the speech samples are synthesized by the pre-trained models, unless you have the permission to use the voice you synthesize. That is, you agree to only use voices whose speakers grant the permission to have their voice cloned, either directly or by license before making synthesized voices public, or you have to publicly announce that these voices are synthesized if you do not have the permission to use these voices.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
wavs/27.wav|I will catch up! It's game over, Yugi! I completely obliterated you!
wavs/71.wav|But that's the last move you'll ever make! I activate my trap! I activate my spell card! Raigeki! Change of Heart!
wavs/115.wav|Combine into one! X Y Zee Dragon Cannon! X Y Zee Dragon Cannons effect activates!
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,109 @@
wavs/1.wav|Don't you realize it's your bedtime? Staying up late is bad for your skin, and it makes you irritable, and it ruins your appetite. I won't allow it!
wavs/2.wav|Now get to bed this instant!
wavs/4.wav|All of the Pokemon are better, but this one's still holding its head! Then maybe you can help it!
wavs/5.wav|Do you kids have any idea just what time it is? Don't you know that you should be sleeping now? I'm sorry, but there's something really wrong with my Pikachu!
wavs/6.wav|There's no need to get excited, look! Sparks are coming from its cheeks, right? That's an early symptom of a cold in Electric Rodent Pokemon.
wavs/7.wav|If you leave it here overnight, I'm sure it'll be fine in the morning. Oh, no. It's all my other relatives that are odd. They're in intensive care.
wavs/8.wav|If we don't get the power back soon, well I just don't want to think about what would happen. I don't know what to do.
wavs/9.wav|You worked so hard to make sure all these Pokemon survived, you've inspired me to become a better nurse.
wavs/10.wav|We will, and please come back and visit us. Bye! Have you ever heard of the mysterious garden?
wavs/11.wav|Yes, it's perfect for people whose age or health keeps them from traveling around, and it's also nice for people like me who can't ever seem to get away from work!
wavs/12.wav|They already left! They're on their way to the next gym! What's wrong with that Meowth? Yeah, I'm sorry.
wavs/13.wav|I couldn't help but overhear you talking. Are you Professor Oak and D J Mary? Then who's over there having breakfast?
wavs/14.wav|Guess after all the game shows I've watched, I can probably fake it. Right. Here is the first question. What is the evolved form of Slowpoke?
wavs/15.wav|Sorry, there was more to the question. You were correct in saying Slowpoke evolves into Slowbro, but.
wavs/16.wav|But what is the name of the psychic attack that Slowbro learns upon reaching level forty six? The answer is Aipom's Tail. Professor A is correct.
wavs/17.wav|That's right, Professor B is correct. The attack is amnesia. This question deals with a silhouette. Examine this silhouette and tell me which Pokemon it is.
wavs/18.wav|Fine! Wobbuffet will be the theme of our two poems. Contestant A is the one and only true Professor Oak.
wavs/19.wav|Not true! Your work showed no understanding of Pokemon poetry! I oughta know since I'm a fifth level master of Pokemon poetry!
wavs/20.wav|All of Professor Oak's poems have one thing in common, the ability to reassure and relax people.
wavs/21.wav|Such as, Blastoise fight or hide away to fight again some other day. Obviously, one meaning is literally to be careful.
wavs/22.wav|But the deeper message is for all people to save their strength for those difficult times in life when they will really need it.
wavs/23.wav|And to give another example, Sandslash rolls into a spiny ball, three meals a day, and eats them all!
wavs/24.wav|On the surface, this poem sounds like just a description of Sandslash and its lifestyle, but it also carries a lesson for us. Oh no! The catered lunch!
wavs/25.wav|I'm sure you'll treat it very well. Goodbye! Take care now! We'd also like to find out if there's any truth to the claims about Kabuto oil.
wavs/26.wav|One of the main reasons we've come here is to learn everything we can about the habitat of the extinct Pokemon, Kabuto.
wavs/27.wav|Well, legend has it that the oil from Kabuto shells not only brings good health, but it can make people live forever.
wavs/28.wav|Of course we know that's impossible, but there could be some basis to the legend, and kabuto oil may prove to be of great historic importance to medical science.
wavs/29.wav|Rhydon! Horn drill that rock now! Chansey, would you take Scyther to recovery?
wavs/30.wav|All I can say is that I'm so very sorry that I didn't believe the prophecy and the warnings you gave us.
wavs/31.wav|Scyther is still very weak. It's going to take a few days to get its strength back. You've got to relax or you won't heal properly, Scyther.
wavs/32.wav|I guess the old warrior finally lost a battle for leadership of its swarm. Excuse me, but what's going on here?
wavs/33.wav|Well, an older Scyther only could have gotten these kinds of injuries by battling another Scyther.
wavs/34.wav|Usually it's a younger, faster Scyther that challenges the leader. Sometimes speed and power can overcome even the most experienced Pokemon.
wavs/35.wav|Once a leader's defeated by another Scyther, it can't stay with the swarm. Unless it wins a new leadership battle, it has to live all by itself.
wavs/36.wav|Well, when was the last time your Snorlax ate? Well, that's why it won't wake up. Snorlax won't be battling tomorrow.
wavs/37.wav|Unless there's danger, it won't wake up until it's hungry again, and that could take days.
wavs/38.wav|Well, maybe if you got out of this lab once in a while, you'd start to notice what's going on around you. Now what are you going to tell that new trainer when she comes here to pick up her Totodile?
wavs/39.wav|Stop making excuses for yourself, Professor! Could someone tell me what's going on here? Well, I'm afraid someone has stolen a Pokemon!
wavs/40.wav|A new trainer's very first Pokemon is gone! That poor girl! That poor Totodile! I know that sometimes Professor Elm may sound like a hothead.
wavs/41.wav|But he's really very sweet, and he raises wonderful Pokemon. Oh, I'm so sorry, I was supposed to be back at the Pokemon Center by two, but when I got to the lab, I lost track of time.
wavs/42.wav|Where did Professor Elm go? He'll be a while. In the meantime, let's do what you came here to do and get you registered and approved for the Johto League!
wavs/43.wav|Congratulations, Ash! You're now fully qualified and approved to become an official participant in the Johto League. I just hope you can understand that Blissey only wants to help.
wavs/44.wav|You'll need a copy of the Johto League Guidebook, so make sure you don't lose it! Once he earns eight badges, he'll be qualified to enter and participate in the Johto Championship.
wavs/45.wav|I'd say the best place to start is the Violet Gym in Violet City. I can't tell you how sorry I am for all the trouble my Blissey has caused for you, Ash.
wavs/46.wav|I know how you must feel, but Blissey's heart's always in the right place. Anyway, I just want you to know that Blissey always tries very hard to be the best nurse it can be.
wavs/47.wav|Isn't that right? What's wrong? I don't believe it! The pantry was full just yesterday! Let's go to security!
wavs/48.wav|Maybe the camera can tell us who. Looks like our thief is Blissey. I can't believe you were behind this. What did you do with all that food?
wavs/49.wav|Blissey, if you tell me where the food is, maybe I can keep you out of trouble. Blissey, listen to me, this could end your career as a Pokemon nurse.
wavs/50.wav|They must be the ones who made Blissey steal all of the food! I'm sorry. Blissey, please forgive me for doubting you even for a minute.
wavs/51.wav|Does that Chikorita belong to you? And what's your name? Correct! And I have a degree in Pokemon Psychology from Celadon University.
wavs/52.wav|I provide innovative counseling techniques and new Pokemon therapy. I'm sorry, but I'm afraid I only deal with Pokemon.
wavs/53.wav|I have an idea, Ash. Why don't you and your Pokemon join me and we'll have a counseling session. Interesting. I think I know the problem.
wavs/54.wav|Maybe, but I'm going to need your help to explore the issues that may be causing your Chikorita's behavior. Chikorita was suffering from envy.
wavs/55.wav|You say Chikorita's refusal to return occurred while you were battling another trainer and his Raticate earlier this evening?
wavs/56.wav|You wanted to substitute Pikachu just when Chikorita thought it was on the verge of winning a battle for you. Don't worry, Ash. I think we can work through it.
wavs/57.wav|So it's understandable that Chikorita feels that you trust and care more for Pikachu and it's jealous. Chikorita is a Grass type Pokemon.
wavs/58.wav|Why don't you try to get Chikorita to return to its Pokeball now? Yes, I do. The new Pokemon therapies are quite effective.
wavs/59.wav|But I think it's best if your Chikorita stays here in the greenhouse tonight. Yep, this is a textbook case.
wavs/60.wav|That Chikorita craves your attention, and an excellent way to get it is by running away. I think you'd better hurry, Ash.
wavs/61.wav|This is a pretty tough neighborhood, and it's got some pretty rough Pokemon. Thanks, Ash. I'm glad I could help out. I just wish I had time to explore Chikorita's psyche.
wavs/62.wav|I'm glad that's over with. You saw through my suit? And who might you be? Hello, how are you, Pikachu? Would you like to come for treatment in my Pokemon Center?
wavs/63.wav|I was talking to Pikachu, but you can all come along if you'd like. Yes, but I didn't write that book, Brock. My grandmother did. It was about fifty years ago.
wavs/64.wav|In those days, the lake and this whole area were terribly polluted by the waste from nearby factories and towns. It was so bad even the Muk stayed away.
wavs/65.wav|But grandmother still loved this place, so she decided to do something. She dedicated her life to studying the effects of pollution on Pokemon.
wavs/66.wav|And she told the world about what she learned in a spring without Pokemon. I could sign my name, but it wouldn't be authentic if it's not from my grandmother.
wavs/67.wav|I'm sorry, but I didn't write that book either, Brock. My mother was inspired by my grandmother's work, so she decided to carry it further, after a lot of work.
wavs/68.wav|She managed to get the factories and towns to stop polluting the lake. Then she was put in charge of draining the toxic water, cleaning the lake bed, and refilling it.
wavs/69.wav|The Grimer and Muk returned first, but my mother kept working. Soon the lake was crystal clear and water Pokemon came here to live again.
wavs/70.wav|So many came that she decided to build the Lake Lucid Pokemon Center to take care of them, and now I'm here trying to carry on the family tradition.
wavs/71.wav|We specialize in water Pokemon, and they love to come here for our personalized treatments and because the lake is so clean. I haven't written a book yet Brock.
wavs/72.wav|Oh, they're not really battling each other. They're all just trying to get back into shape by practicing. Following in my grandmother's and my mother's footsteps, of course.
wavs/73.wav|We've all worked very hard to make the Lake Lucid Center a success. It's to honor my mom and my grandmother.
wavs/74.wav|But I'm planning to write one soon, and I think I'm gonna call it An Autumn Harvest of Pokemon. That oughta do the trick. Of course. I'd be very happy to.
wavs/75.wav|The lake's a place where the Water Pokemon can exercise and build up their strength physically and emotionally. Wait a minute, did you say they're Water Pokemon?
wavs/76.wav|Keep it away! Whatever you do, don't let those water Pokemon out of those Pokeballs! Don't let them near me, don't let them touch me! And whatever you do, please keep them away from me!
wavs/77.wav|I'm sorry, maybe I should have mentioned this before, but I... I hate those Pokemon! Sorry, please keep those things away from me!
wavs/78.wav|I absolutely can't stand the sight of those Pokemon! I can handle Electric Pokemon, Poison Pokemon, I even love Bug Pokemon! Just as long as I don't have to touch them!
wavs/79.wav|Any kind of Pokemon except those awful, horrible, terrible water Pokemon! I wouldn't even touch a water Pokemon, wearing this special protective suit!
wavs/80.wav|I don't dislike them! I hate them! I really wish you wouldn't feel that way, Misty. I'm very happy to treat every kind of water Pokemon who comes to the center.
wavs/81.wav|Don't be ridiculous! We provide the best water Pokemon care anywhere. Doesn't yours deserve the best?
wavs/82.wav|I hope you're not assuming that my personal preferences affect my job performance because I can assure you that they don't. I treat all patients equally.
wavs/83.wav|Thanks, Misty. I was hoping you'd say that. It's a little tough to handle those things with these things. You did a great job with those bandages, Chansey.
wavs/84.wav|Excellent as always.
wavs/85.wav|Thanks to my three assistants, I can treat water Pokemon without ever having to lay a hand on them.
wavs/86.wav|Water Pokemon can get many different kinds of injuries and illnesses, so over the years we've developed a number of different kinds of healing water baths to treat them with.
wavs/87.wav|Everybody has a certain Pokemon they like and a certain Pokemon they don't like, and when it comes to Gyarados, no way Jose!
wavs/88.wav|Gyarados have such large, heavy heads that it's quite common for them to experience neck and back problems. That's right. Why? What do you mean?
wavs/89.wav|I've studied all kinds of water Pokemon, and I've created special treatments, special diets, even special exercises that help each one overcome their illnesses and injuries.
wavs/90.wav|I understand water Pokemon, and I'm going to write a book so others can understand them, too. I never allow my feelings to interfere with my work!
wavs/91.wav|I'm a Pokemon nurse. I don't have to cuddle my patients to learn what I have to about them, but I do the best job I can to honor both of them.
wavs/92.wav|I did! I grew up and continued the work my mother and grandmother started. I may never be as great as they were.
wavs/93.wav|I don't hate my job, Misty. I love Lake Lucid, and I'm able to treat all kinds of sick and injured Pokemon, and that's what makes me happy.
wavs/94.wav|Unfortunately for me, there are always all kinds of water Pokemon. But a Pokemon nurse does what she has to. It's a fake! A fake Tentacruel!
wavs/95.wav|What's going on here? We have to do something before it injures itself even more! Gyarados is my responsibility!
wavs/96.wav|Neither of you has ever tried to calm a Gyarados in pain. You may be great Pokemon trainers, but neither of you is a trained nurse. All right, Chansey, let's get ready. Bring in the brace.
wavs/97.wav|That's why I have to be the one to deal with that Gyarados, and so I will. This is an emergency, and nurses don't get to pick and choose their patients.
wavs/98.wav|It's a nurse's duty to heal the sick, whoever they may be. I can't focus on how I feel about water Pokemon.
wavs/99.wav|But if I can just stay focused on the fact that I'm a nurse like my grandmother and my mother. I have to help this poor Gyarados!
wavs/100.wav|And no matter what my feelings are, I have a duty to help and heal all Pokemon. I can do this! If I touch it the right way, it'll calm down.
wavs/101.wav|Put it on, Chansey! There's no Pokemon that's better than any other. There's no Pokemon that's worse than any other. They're all precious creatures!
wavs/102.wav|The song of every Pokemon is sweet if you can hear it! You'll be just fine. You all did a wonderful job. Now take this Gyarados to another water tank, please.
wavs/103.wav|Well, Misty, I'd still like to give your Water Pokemon a full examination.
wavs/104.wav|Maybe. I'm sorry Misty, I wasn't able to touch your water Pokemon.
wavs/105.wavAall of them are in top physical condition. They have an excellent trainer. Yes, Misty. I still do and will for the rest of my life.
wavs/106.wav|But that won't stop me! I have a job to do, and a Pokemon Center to run, and a book to write!
wavs/107.wav|I'm sure I just closed that. It's okay! You don't need to fight with him, Shiftry! Yeah.
wavs/108.wav|Shiftry, you're a good friend to Nuzleaf. Nuzleaf is gonna be just fine. Thank you for all of your help.
wavs/109.wav|I'll take care of everything, but I don't have some of the supplies I need with me. Everything's okay now, Shiftry.
wavs/110.wav|We've done everything we can to keep Nuzleaf comfortable, but I need to get some of my medicines! So I have to go back to the Pokemon Center and get them!
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,377 @@
wavs/1.wav|It isn't supposed to be me. Padme stands in her office, waiting to stride into the Galactic Senate chamber.
wavs/10.wav|Just days before, it had seemed as if there might be hope, for the first time in so long. The Senate had convened an emergency session to discuss the disaster the war had become.
wavs/100.wav|and suddenly a giant hologram of Count Dooku appeared in the Senate chamber. Padme reflexively stiffened, he intoned. The news hit Padme like a slap.
wavs/101.wav|No. It couldn't be. There were cries around her. Other senators cheered. But Padme could barely hear them. Mina was dead.
wavs/102.wav|In the hallway outside the Senate chamber, Bail and Padme met. Padme's hand maiden, Tecla, at her side. Padme could barely speak.
wavs/103.wav|Everything had gone so terribly wrong, and now Mina was dead, and Republic forces had done it? I can't believe it, she said.
wavs/104.wav|Bail put his hand on her shoulder. Padme stopped. Of course. Dooku had killed her. He didn't want democracy. He didn't want peace.
wavs/105.wav|He let the Confederate Senate have its vote and then killed the senator who'd sponsored it. He did control the universe.
wavs/106.wav|Mina had been wrong, and it had killed her. What can we do? Padme asked, for once. She could see no way out.
wavs/107.wav|Bail proceeded to answer as if she was asking a practical question, but Tecla understood the helplessness underneath it. She touched Padme's elbow gently.
wavs/108.wav|Bail had a plan. Gather the information on the real cost of Bertone's proposal and try to talk sense into the other Senators before the vote.
wavs/109.wav|Fine. Padme would try. She went to the Banking Clan to find out exactly what these five million troops would cost. Free from regulation.
wavs/11.wav|And the fix on the table was the same fix as always, more troops. As if more troops had done anything thus far, the Republic ordered more clones.
wavs/110.wav|The banks had raised the interest rate from ten percent to twenty five. For every hundred credits borrowed, they'd owe a hundred twenty five.
wavs/111.wav|and that amount would only grow the longer it took to pay it back. Already social services were being cut everywhere. Education. Health care.
wavs/112.wav|infrastructure. And that meant people were suffering. If they passed the bill, they wouldn't even be able to meet people's basic needs.
wavs/113.wav|The bill would essentially destroy the republic. The separatists could just sit back and watch. To make matters worse, senators had started to receive threats.
wavs/114.wav|Senator Farr had been jumped by two bounty hunters in the night, and his arm was in a sling. The Viking clan would stop at nothing.
wavs/115.wav|you'd think that would outrage some of the senators, but instead, as Padme went from colleague to colleague, pleading her case.
wavs/116.wav|She found that even the ones who were against the bill before suddenly thought the Republic needed nothing more than more clones.
wavs/117.wav|Everyone cared about their own self preservation over the people of the Republic, and she could do nothing.
wavs/118.wav|Some minds can't be altered no matter what they hear, Bail said, when they met in his office. From my experience, Padme said.
wavs/119.wav|It depends a great deal on who's sending the message. No, they would not listen to her. That was clear. But they might listen to bail.
wavs/12.wav|The Separatists ordered more droids, and the war grew bigger. That was how it would go, on and on, until everything was destroyed.
wavs/120.wav|Bail was the best Speaker in the Senate. Everyone respected him. He had, dignity. Bail needed to give a speech before the whole Senate.
wavs/121.wav|He gazed at her, and then nodded his assent. He would do it. For the first time since Mina's death, Padme felt a spark of hope.
wavs/122.wav|Perhaps one great speech could change the course of the war. Perhaps one great speech could save the Republic. Maybe that hope.
wavs/123.wav|was what had made her so careless. Maybe it simply had never occurred to her that she might be in danger.
wavs/124.wav|After going to plea with Senator Christo at his house the evening before the vote, she decided to walk alone back to her speeder, but when she got to where her speeder was parked,
wavs/125.wav|The driver was gone, and the speeder along with it. She looked around. It was so dark. Were those foot steps?
wavs/126.wav|She slipped around a corner and ducked into an alleyway, blaster poised. Then someone grabbed her, a burly bounty hunter.
wavs/127.wav|who looked like a giant armored bug jumped in front of her and roared. Another one had taken hold of her from behind. Others had tried to kill Padme enough times by then.
wavs/128.wav|that she knew how to channel all her panic into fighting back. She was not going to let Banking Clan goons silence her.
wavs/129.wav|Find a way out. Get away! She thrashed. And struggled. Being small could be an advantage. People underestimated you.
wavs/13.wav|But this time, there was a new wrinkle. The Senate's war funds were nearly extinguished. They simply could not afford more clones.
wavs/130.wav|Armored Bug came at her with a knife, and she thrashed more, giving him no clear target. She slapped her blaster away, and she struggled against the one who held her.
wavs/131.wav|He smelled like the Leonorm's swamp, and burst free. She ducked ahead, but armored bug tripped her, and next thing she knew his knife was at her throat.
wavs/132.wav|And then two Coruscant police droids shone their lights in the alleyway. Padme pushed armored bug away and stood with the droids with one glance back.
wavs/133.wav|The swamp smelling one who had hold of her was a petroleum with an eyepatch. She sprinted away, and then the bounty hunters attacked the droids.
wavs/134.wav|Padme was not going to hang around and see who won that fight. She ran out of the alley and darted toward an empty speeder bike.
wavs/135.wav|Senators were not generally supposed to hijack speeders, but these were extenuating circumstances. Get away. Get away!
wavs/136.wav|The words repeated in her head as she charged forward, the bounty hunters close behind her. Then armored bug hit a button on his wrist and a cable shot out.
wavs/137.wav|Attaching itself to her speeder. He was hanging off her speeder, with swamp stink, following on another speeder. One problem at a time Padme.
wavs/138.wav|armored bug first. He wanted to go for a ride? Fine. Padme slammed her foot on the gas and sped forward.
wavs/139.wav|Bug pressed a button on his armor and, suddenly, the cable was retracting. He was getting closer. He wanted more, then? Hadn't I dared write?
wavs/14.wav|Padme had entertained a small hope that this, finally, might lead the Senate to discuss peace. But she should have known better. War is good business.
wavs/140.wav|then left, darting in and out of traffic while the bounty hunter banged and bounced against oncoming speeders stink was getting close enough to be a problem.
wavs/141.wav|She dragged Bug over a series of posts, then through a stack of crates. Did he like that? BAM!
wavs/142.wav|Swap sink slammed into her from the side. She slammed him back. Suddenly the cable tugged again. And Bug was on her bike.
wavs/143.wav|He grabbed for her, Hadme pulled at the fuel line, and fuel shot up into his face. They sped forward, fuel spraying into Bugs face.
wavs/144.wav|Stinks like ramming into her and then police sirens a police speeder chase them.
wavs/145.wav|while a giant metal bug person writhes on the back of one, out of the ordinary. But Padme did not have time for the police. She flammed stink hard.
wavs/146.wav|And he veered away. Bug was on her again. So she ducked under a bridge and then, BANG! Slammed him into a lamp. He was off.
wavs/147.wav|She sped forward, but somehow Stink was behind her again, with Bug now on his bike. She turned a corner, into a police blockade.
wavs/148.wav|She stopped the bike as police cruisers surrounded her. She never thought she'd be so happy to be arrested.
wavs/149.wav|Back in her apartment, Tecla fretted over Padme. Hello there, I'm Padme, from Naboo.
wavs/15.wav|The Senate should deregulate the bank so the Republic could borrow more money, whose techno union would profit from that same deregulation. Yes.
wavs/150.wav|The hand maiden asked, there's nothing they can do. I know who did it. You show it love, you show it light, and you hope it chooses the light.
wavs/151.wav|They were bounty hunters, paid to stop me from voting against the troop increase. What has happened to democracy? And why doesn't anyone seem to care?
wavs/152.wav|You do, Tecla said. You're not like most politicians. Padme nearly scoffed. If only that were enough.
wavs/153.wav|Padme turned to look at her hand maiden, her friend. It wasn't true. Maybe it had been true once, but in the chaos of war, she'd lost sight of everything.
wavs/154.wav|She'd been running all over Coruscant, trying to get the Senators to care about the suffering of their people, and she'd never asked her loyal friend.
wavs/155.wav|If her family was suffering, she was exactly like most politicians, but she wouldn't be anymore. She could have been killed that night, if they killed her.
wavs/156.wav|Let it be for being the person she wanted to be. Tecla, tell me, how is your family? Tecla tilted her head.
wavs/157.wav|Padme's heart nearly broke. Of course they weren't fine. How is the war affecting them? Tecla eyed her uncertainly.
wavs/158.wav|Patmay did not break her gaze. How? Please tell me. Tell me how it's been getting worse. She patted the couch next to her.
wavs/159.wav|She should have been asking these questions all along. But she would ask now. Maybe it was the end of the Republic. Maybe she would lose everything else.
wavs/16.wav|That would mean the Banking Clan could do whatever they wanted. But wasn't that a small price to pay for safety and freedom? Exhorted Holly Bertone.
wavs/160.wav|but she would not lose her soul. It was the morning of the vote. Her conversation with Tekla replaced the despair she'd been feeling with resolve.
wavs/161.wav|She would fight for her people, and she would not stop. They could send all the bounty hunters they wanted after her.
wavs/162.wav|She would not stop fighting. If she could find a way to survive with Armored Bug and Swamp Stink after her, she could survive the corruption of the Galactic Senate.
wavs/163.wav|She was ready, ready to stride into the Senate chamber and support Bail, and then the message came in. Bail had been attacked on his way to the Senate chamber.
wavs/164.wav|He sent a message to Padme on his way to the hospital. You must address the Senate. Padme shook her head. If they didn't listen to me before,
wavs/165.wav|Why would they listen to me now? Tekla gave her a small smile. Because you do listen. You understand.
wavs/166.wav|what the people are going through. Please, your people are waiting for you. It is not supposed to be me, but it is her.
wavs/167.wav|and she will fight. So Padme takes a deep breath and strides in. She hears me deechy proclaiming. Padme announces.
wavs/168.wav|The whole chamber goes quiet, all eyes are on her, and suddenly she is not afraid. She will speak for the people.
wavs/169.wav|She draws herself up and she begins. She has no mask. She has no strategy. All she can do is speak from the heart.
wavs/17.wav|the senator whose planet produced and sold the clones. It was astonishing to Padme that anyone took them seriously when their motives were so clear.
wavs/170.wav|So she tells them about Tecla, how Tecla's district rarely has electricity and running water as a result of the war.
wavs/171.wav|how children there can only bathe every two weeks, how they have no light by which to read or study at night. She feels her words reverberate through the chamber.
wavs/172.wav|The air crackles. No one is calling her traitor. When she finishes, there is a moment of silence. And then, cheers.
wavs/173.wav|She feels the change in the room. She feels every one of them thinking of the people back home. She feels the Republic and its strength.
wavs/174.wav|she feels it take one step back from the brink. The bill is defeated. She knows even before the vote is counted. Who knows what tomorrow will bring?
wavs/175.wav|But today, the Senate showed itself to be more concerned about the people of the Republic than its own coffers. This is why she is here.
wavs/176.wav|This is how things are supposed to be. And this is why she believes in the Republic. It is not without corruption.
wavs/177.wav|It is not without darkness, but there is good at its core, and just because something good has darkness in it.
wavs/178.wav|doesn't mean you abandon it. Just because there is darkness in something does not mean you do not love it.
wavs/18.wav|But it was wartime, and profiteers masqueraded as patriots. Padme knew all about masks. When you were queen.
wavs/180.wav|Ha ha ha ha. has fairly Dogsai.
wavs/181.wav|The five besteston.
wavs/182.wav|Ha ha ha ha ha ha ha ha ha ha!
wavs/183.wav|The Republic needs your help. Could you please help me? I could use your assistance, please. Hello, I am Padme Amidala of the Republic Senate.
wavs/184.wav|It is nice to see you. I'm pleased to meet you. Hello there. How are you? It's nice to meet you. I'm Senator Padme Amidala.
wavs/186.wav|Where are you from? Greetings from the Republic Senate. It's nice to see a friendly face.
wavs/187.wav|Hello! From which star system are you? I am here representing the Republic Senate. Hi! Nice to see you!
wavs/188.wav|I am honored. It's a pleasure to get to know you. We'd better get going. The Republic's diplomatic issues aren't going to resolve by themselves.
wavs/189.wav|This place would make a lovely retreat. I sure miss Annie. I'm sure I could use this time to compose a speech for the Galactic Senate.
wavs/19.wav|You must keep your face blank, as if you had never felt an emotion in your life. In the Senate, you wore a different kind of mask.
wavs/190.wav|I really ought to use this time to practice my blaster skills. I, mean my, diplomatic negotiations.
wavs/191.wav|Ah, it's nice to have a much needed rest. I believe negotiations are in order? Now seems as good a time as any to relax.
wavs/192.wav|It's hard for me to just wait for something to happen. I have things to do, really. I have better use for my time than this. I'll just wait here.
wavs/193.wav|Huh. It might be time for me to stir up a little, diplomatic unrest. Oh! Excuse me! Why would you do that?
wavs/194.wav|I beg your pardon? The nerve! That was uncalled for! Violence is rarely the answer. Oh, my. I didn't see you there.
wavs/195.wav|I'm sure we can resolve this peacefully. The Senate won't stand for this. This isn't very diplomatic. You would strike a senator?
wavs/196.wav|I'm going to write a very strongly worded letter about this. I'm sure you didn't mean it. Let's not do anything we'd regret.
wavs/197.wav|But I have diplomatic immunity! Is that what you call negotiating? Look out! We're surrounded! And I don't think they want to negotiate!
wavs/198.wav|Get your blaster ready. Here they come. Careful! Ah! What? Oh, my. Anakin, it is so good to see you.
wavs/199.wav|I've missed you, Anakin. Please tell me you're well. How goes the battle, Anakin? I have missed you, my love. Tell me you will return to my side soon, Annie.
wavs/2.wav|and try to convince her fellow senators to vote against a bill to commission more troops for the war against the separatists. And all she can think.
wavs/20.wav|If you were on the side of continual war, you could contort your face in all kinds of ways. Sorrow. Horror. Out rage.
wavs/200.wav|Anakin it pleases me to see you are doing well. Oh, Annie. I fear for you out in battle. Hello general Skywalker.
wavs/201.wav|Master Obi Wan, I'm so glad to see you. Hello, Master Kenobi. How are you, Master Kenobi? How are your dealings with the Separatists?
wavs/202.wav|It is good to see you Obi Wan. I'm so glad to see you master Kenobi. I always feel safe when the Jedi are near. Master Kenobi.
wavs/203.wav|Hello, Master Kenobi. Jedi Master Kenobi, greetings. Hello, Ahsoka. It is so good to see you. Hello, Padawan Tano.
wavs/204.wav|Ahsoka, Anakin tells me you will be a great Jedi someday. Hello Ahsoka my friend. it is so good to see you Ahsoka so I hope.
wavs/205.wav|Padawan Tano. Hello. Padawan Tano. Ahsoka! I'm always so glad to see you. Jedi Master Yoda, it is a pleasure to see you.
wavs/206.wav|Hello, Master Yoda. Master Yoda, how are you? I hear the Jedi are doing great things to help the Republic, Master Yoda. The Senate thanks you.
wavs/207.wav|Greetings, Jedi Master Yoda. Hello, Master Yoda. Master Yoda, Master Yoda, you're looking well. You! Get away from me!
wavs/208.wav|I thought you died on Naboo. What are you doing here, Sith? Maul! What do you want? You will pay for all the wrong you have done, Maul.
wavs/209.wav|What do you want, Sith? You will show respect to a Senator, Maul. State your reason for being here, Sith. I'm on my way to the starport now.
wavs/21.wav|And no one cared what was underneath the mask, if you were against the war, if you were a partisan, if you were young, if you were every thing Padme was.
wavs/210.wav|If you will excuse me, I'll be sure to call. You can't do this! We are here on a mission of hope! To end this destructive conflict before it!
wavs/211.wav|The Jedi are here. Please, you must help us. We're trapped. I knew the Jedi would come to aid us. Darth Maul is holding us hostage.
wavs/212.wav|Be careful. I fear we are the bait in Darth Maul's trap. Maul is here. He wants to destroy every one of us. Thank you, Master Jedi.
wavs/213.wav|Delegates from both the Republic and the Confederacy will be attending. Padawan Tano, without your help.
wavs/214.wav|Darth Maul would have ruined any chance for a peaceful end to the Clone Wars, but now we can try to work toward a ceasefire.
wavs/215.wav|Yes, the Supreme Chancellor has given me his blessing to host a peace conference in Theed. I thought my orders were clear, Master Jedi.
wavs/216.wav|Anakin I know me what about you, but he said there was no way we could stop it, but Anakin don't be late So were you.
wavs/217.wav|Sorry, Master Kenobi. That was me. Anakin directed me to a power regulator and I just pressed every button I could find.
wavs/218.wav|This is Senator Amidala. I've discovered a secret Separatist base on Before, near the Naboo Sun. There's a lot of activity. It looks like they're,
wavs/219.wav|Uh oh, I think I've been spotted. This is Senator Amidala. You must destroy this base at all costs. Do not,
wavs/22.wav|You had to keep your face calm, reserved. You could show a bit of passion, but just a bit. You were too much and you were too emotional.
wavs/220.wav|Yes, it was secretly given to him by the Supreme Executive of the Banking Clan himself. If they leave the Separatist Alliance, it will go a long way to shortening this war.
wavs/221.wav|This is Senator Amidala. I'm afraid it's much worse than that. I see now this whole thing was a trap, and I'm afraid I walked right into it.
wavs/222.wav|I've overloaded the power system. On the lower levels, I'm fine, but I don't know for how long. Droids are everywhere. I'll be there.
wavs/223.wav|This is where we're supposed to meet them. He's probably late again. Anakin! The bridge is out! Threepio! No! We can't leave yet!
wavs/224.wav|I overheard Grievous. Their hyperdrive is almost repaired. I suppose you have a plan. Ever since I've known you, you've been playing with droids.
wavs/225.wav|We came as soon as we could, my lady. Have you found any more droids? Finding a couple of battle droids will not be enough. Where'd they pick up all this mud?
wavs/226.wav|The Eastern Swamps. I think Jar Jar just found out the location of that lab. May I recommend General Kenobi and General Skywalker?
wavs/227.wav|Relations with the Gungans are a little tense right now, but they trust General Kenobi like one of their own. I want as much information as possible before the Jedi arrive.
wavs/228.wav|See if you and Three pee o can download any of the other battle droids memory. I'm going to find that lab. Come on Jar Jar, who are you?
wavs/229.wav|We think the virus that made your animals sick came from the trees. You stay here. You'll be going home soon, I promise. I'll send some soldiers to pick you up and take you back to your home.
wavs/23.wav|Too little, and you were a protocol droid. So Padme put on her senator mask and stood up. And there was some right on schedule.
wavs/230.wav|Keep your eyes open. Look for anything out of the ordinary. No way we're going to open this. Why are you holding us? I was about to ask you the same thing.
wavs/231.wav|The blue shadow virus? I thought that deadly disease was extinct. Are you insane? It's a deadly disease!
wavs/232.wav|No life forms are immune to it. That's why it was eradicated. Annie, how about the next time you rescue me?
wavs/233.wav|Before you kill all the battle droids. Missing bomb? I saw Dr. Vindy give a little droid a bomb. Hey there, little guy.
wavs/234.wav|How about you hand that over to me? Ahsoka, I found the last bomb. It looks like the chamber that holds the virus is missing.
wavs/235.wav|Sound the alarm! Don't blame yourself. These things tend to happen in a war zone. I hope that their sacrifice brings us closer to peace.
wavs/236.wav|I can't, Annie. I have to bring this bill before the Senate. It's important. Not more important, but important.
wavs/237.wav|The work we both do is in service to the Republic, to protect those who would otherwise be powerless to protect themselves. No, Anakin, I can't.
wavs/238.wav|A Jedi lightsaber is, wow, it's heavier than I thought. If all you want to do is make fun of me, Senator Organa, how good to see you. What is it?
wavs/239.wav|Privacy invasion, Bill. Of course. I can't let them search me. I have something they must not find. I am Padme.
wavs/24.wav|He intoned. She had to pretend it was a serious question, because somehow saying that he only cared about his own profit was against the rules.
wavs/240.wav|The Galactic Senate will not treat with terrorists. Another daring rescue, Master Jedi. Yes, of course, Senator. Worried about public opinion.
wavs/241.wav|But he wants us to know how very sorry he is. I hope you're right, Uncle. You've been doing an amazing job rallying votes to our side.
wavs/242.wav|Exciting isn't exactly the word I would use. I think terrifying is more appropriate. I learned it from you. See you inside, Senators.
wavs/243.wav|The creation of more warriors will not end this war. The financial costs alone will bankrupt and cripple the republic.
wavs/244.wav|By adding more clones to the conflict, we are only escalating the destruction. I understand. I'll do whatever is necessary to succeed in my mission.
wavs/245.wav|not winning the war, which is why we must vote for this resolution to promote more diplomacy.
wavs/246.wav|and to bring an end to this killing and hatred. Thank you. The only thing I find unpatriotic is your warmongering.
wavs/247.wav|Thank you. But perhaps we should wait till we actually win the vote before we make a victory speech. This is a private conversation.
wavs/248.wav|Committing more troops to the front lines will not allow diplomacy to resume. What we need is to get his resolution passed.
wavs/249.wav|I know. No one could ever take his place. What's happened? What makes you think it was murder? That's not it. Perhaps,
wavs/25.wav|And that set off more outrage. A building wave that threatened to crash through the chamber and drown them all. But then bail spoke.
wavs/250.wav|Someone was upset about the clone troop bill currently on the floor. It's very controversial. No one will give the vote their full attention until they know what's happened to them.
wavs/251.wav|Then we'll have time to conduct our own investigation. Well, he didn't exactly inspire confidence, did he?
wavs/252.wav|We did. We'll have a far easier time looking into this than, indeed, I am. I'd rather do this quietly. I don't need a Guardian.
wavs/253.wav|Very well. I have no objections. And I know exactly where to start. You both opposed Anno's ideas in the Senate. With enough at stake.
wavs/254.wav|Maybe you decided to silence his voice, for good. Fine, I will go look. But whatever we find, I'll have more questions for both of you.
wavs/255.wav|I had some information about a lead here at the docks. My friend was murdered. I don't care about rules. We alerted the killer.
wavs/256.wav|What if we were sent here on purpose? Yes! What if this was all a setup? Sent us here, just so he could kill us.
wavs/257.wav|Agreed. I think, in this instance, the Inspector is right. She was the only other one in the room with us. I had to try.
wavs/258.wav|If you see injustice, you can't wait for someone else to fix it. You must stand up and get involved. If the poison wasn't all our drinks,
wavs/259.wav|Lolo would have died too. She'd have been poisoned too. Unless she didn't drink. But you drank. You didn't drink.
wavs/26.wav|urging them to slow down, to research the bill and its consequences, and his steady voice worked its magic over the room.
wavs/260.wav|No! He made a mistake, Lolo! He was sorry! After all that, we lost. Of course, you were right, Chancellor.
wavs/261.wav|Master Kenobi explained the problem. I'm here to help. It has no voice to defend itself. Anakin, we have to be that voice.
wavs/262.wav|It's what we're capable of that frightens me. A creature's life, maybe even an entire species, is at stake. Doesn't that at least warrant a discussion?
wavs/263.wav|Isn't that precisely the point of a democracy? How is killing the last of a species, in secret and without debate, good for anyone?
wavs/264.wav|No, Mr. Speaker. I do not. Evacuate the staff to the underground shelters. Does it have to be destroyed? I wish we had never brought the beast here.
wavs/265.wav|Considering the circumstances, I'll take the risk. Duchess, it's good to see you. If your government has trade concerns, we can talk.
wavs/266.wav|Many systems have been affected. Everyone in the Republic has neglected Mandalore, and there are those of us who would still vote to give you any help you require.
wavs/267.wav|We are making progress in the Senate. Overwhelmed. Perhaps they will listen to a new voice. Ruling Council, may I speak?
wavs/268.wav|I hear your worries, your frustration, but the longer you argue the more your people suffer. You are right. New trade routes are essential to survival.
wavs/269.wav|But the black market is no substitute for legitimate and legal trade. The Republic can provide security.
wavs/27.wav|The air settled. The gathering calmed. The Senate was adjourned. Padme stalked into the hallway with Anakin and Ahsoka. Something had to be done.
wavs/270.wav|As you know, in the Senate, the Chancellor says it's going very well, but my sources say otherwise. There are times I wish I could follow Mandalore's lead.
wavs/271.wav|Neutrality, and not just in the war. There are still those of us who work to overcome the corruption and believe it to be possible.
wavs/272.wav|means of direct communication, and locations you should investigate. So, where do we start? It's not your fault. The school must have an import log, correct?
wavs/273.wav|So we should be able to find out where the tea came from. It looks like the school's import log has been erased. All this because you were greedy?
wavs/274.wav|and a customs official reports these to the government. I must say, when I came to visit, I hadn't pictured us in such an informal setting.
wavs/275.wav|But one can only survive the rigors of courtly formalities for so long. Impossible! We witnessed it with our own eyes! And what about when you're not watching?
wavs/276.wav|It wasn't Death Watch, Prime Minister. It was a group of black market smugglers. What they didn't count on was the process would make the drinks poisonous. You must have hope, Satine.
wavs/277.wav|I will speak with Master Yoda. Don't lose hope, my friend. Ahsoka! It's so good to see you. How have you been? What makes you believe that?
wavs/278.wav|This is troubling. Captain, please take all necessary precautions. Yes, Bail Organa and I are leading a conference concerning the refugees from the war.
wavs/279.wav|I leave for Alderaan in the morning. Ahsoka, the refugee situation is much too crucial to ignore. I called this conference.
wavs/28.wav|They needed another way, she turned to Anakin. You must ask the Jedi Council to speak with Chancellor Palpatine. Anakin threw up his hands.
wavs/280.wav|It could make an enormous difference in policy. It's vital that I go. Well, I suppose it couldn't hurt. Besides, I enjoy your company.
wavs/281.wav|Of course you can join me as extra security. You'll learn to play in time, Ahsoka. Someday, you'll even beat me. What's on your mind?
wavs/282.wav|When I was queen, I felt the same insecurities as you do now. It was ultimately up to me to run the entire Naboo system.
wavs/283.wav|Oh yes. But I have learned to trust in myself, and you will too. Absolutely. Yes, Captain.
wavs/284.wav|I'm fine. Bail, it's so good to see you. Thank you so much for hosting this conference. Of course, Pato Antano. If you'll excuse me.
wavs/285.wav|I haven't lost faith in you, Ahsoka. We are taking all the necessary precautions, correct, Captain? Ahsoka, in your vision, does Ora succeed?
wavs/286.wav|Isn't it just beautiful? Ahsoka, I can't stop living my life. You forget, I'm a friend of the Jedi. I'm no stranger to taking risks.
wavs/287.wav|What is it? I wanted to first thank you all for coming. This is a cause that is very important to me. You did all you could.
wavs/288.wav|They will follow me wherever I go. It is the greatest weapon wielded against those who would stand up for truth and justice. And together we shall represent them.
wavs/289.wav|And I know there are those individuals in the galaxy who would seek to promote fear and spread chaos. Know that a chorus of thousands shall rise up in its place.
wavs/29.wav|Before Padme could respond, Ahsoka said, why not? Aren't we Jedi Knights? Isn't it our duty to advise the Chancellor?
wavs/290.wav|For you have no dominion over the righteous. We are the defenders of truth. Ahsoka, I told you.
wavs/291.wav|I'm no stranger to taking risks. Captain, she's stunned. His planet is in crisis. His people are starving. He's a very old family friend.
wavs/292.wav|I could not refuse his plea for help. This is a mission of peace. I put my faith in diplomacy.
wavs/293.wav|We can't solve all of our problems by throwing troops at them! Without Ahsoka's foresight, I fear things would have gone quite differently.
wavs/294.wav|I will follow your advice, Chancellor. Thank you. I've been thinking. Ara Singh said the person who hired her simply wanted revenge for something I did to them.
wavs/295.wav|Yes, but with Ahsoka's added details, I know someone who fits the description. Wait, no.
wavs/296.wav|The tendrils belong on the main table between Anakin and Senator Aang. Three pee o. It's so good to see you, Senator Aang. Three pee o, you've done a magnificent job.
wavs/297.wav|Members of the Senate, do you hear yourselves? More money. More clones. More war. Say nothing of fiscal responsibility.
wavs/298.wav|What about moral responsibility? Hasn't this war gone on long enough? Of course not! But negotiation might be a better course of action.
wavs/299.wav|You must ask the Jedi Council to speak with Chancellor Palpatine. A peaceful solution is the only way out of this morass of war.
wavs/3.wav|is that it's not supposed to be her. She's even convinced Bail Organa that she is the wrong person. She's still too new, too young.
wavs/30.wav|Anakin sniffed. After today's debate, Padme muttered darkly, I was hoping she learned a great deal. Truthfully, Ahsoka said.
wavs/300.wav|After today's debate I was hoping she learned a great deal. Maybe talking to the Jedi Council isn't the role for you after all. Thanks for your help. Come on Ahsoka.
wavs/301.wav|You told me to teach her about politics. So I'm going to. He is a she, a senator in the confederacy of independent systems.
wavs/302.wav|The Separatists used to be a part of the Republic. I was close with many of the Senators who left. I may not agree with them, but they're more than pawns.
wavs/303.wav|They say official meetings would only legitimize the Separatists. You just gave me an idea. You're a Jedi, and Jedi are allowed to travel to neutral worlds like Mandalore.
wavs/304.wav|Where we could then board a cargo ship to a Separatist system. It's just that you could get us through to meet with her and, I haven't seen her or her family in so long.
wavs/306.wav|She was my mentor when I was growing up on Naboo. Yes, how things have changed since the last time we met. I sense Dooku's dirty hand in all of this.
wavs/307.wav|I forgot. You actually admire the man. The Republic Senate is holding a critical vote on whether or not to escalate the war effort.
wavs/308.wav|However, many of the delegates are undecided as to what to do. I am certain if you could convince your representatives to extend an olive branch of peace towards the Republic,
wavs/309.wav|There might be enough sympathy in the Senate to finally open negotiations. That's all I ask. To hope. This is goodbye.
wavs/31.wav|I didn't understand any of it. I know the separatists are evil, but all anyone argued about was banking deregulation.
wavs/310.wav|Jar Jar, you would be doing me a great favor by staying with the ship. I need you to watch over Three pee o. You know how he always gets himself into trouble.
wavs/311.wav|I won't be long. We've been friends since I was a little girl, when you were my father's strongest ally in the Senate. And of course I'd come to help you.
wavs/312.wav|I'm sure the Republic Senate will approve a relief effort. The vote was postponed, but you will get your food, Your Excellency.
wavs/313.wav|We would be remiss, if not irresponsible, to reject the Separatist proposal. Cannot be trusted. He will bring war to your system just as he did to mine many years ago.
wavs/314.wav|I don't understand. If I might speak with you confidentially, I know that this is sincere. Does it matter, Chancellor, if the result is an end to the war?
wavs/315.wav|There's always a choice. To live in fear is no life at all, given that the separatists have put a call for negotiations on the table.
wavs/316.wav|The need for additional troops seems ill timed. But it was the Separatist Congress that issued the Bill of Peace! That's not true! It's not too late!
wavs/317.wav|You can stop this madness! I'm returning your Padawan. Chancellor Palpatine! One alternative might be to stop the war, not escalate it!
wavs/318.wav|May I remind the Senators that the peace proposal was made prior to their assault. Wants us to continue the fight.
wavs/319.wav|It's a calculated attempt to destroy the peace process. Not everyone in the Confederacy wants this. I know this for a fact. I can't believe it.
wavs/32.wav|interest rates and, well, almost nothing about what we're fighting in the first place. Padme smiled sadly.
wavs/320.wav|I just can't believe the Republic would target, Senator. What can we do? Right. Let's go, Uncle. You know these Banking Clan people.
wavs/321.wav|Plus, you owe me for telling such a bad joke. I'll see, this bill is shortsighted. Millions of clones won't win this war.
wavs/322.wav|The only winner will be the banking clan. They wanna pass this bill so badly, they're using scare tactics to sway votes.
wavs/323.wav|Then why are you voting for additional troops? As long as Senators are being threatened and attacked, I'm afraid we don't stand a chance.
wavs/324.wav|Even so, we're still at least six votes short of a majority. And you saw how effective my plea was today. You're the finest public speaker I know.
wavs/325.wav|If anyone can convince the Senate that voting for this bill will bankrupt the Republic, both financially and spiritually, I urge you to speak before the full Senate.
wavs/326.wav|Good. In the meantime, I'll pay another visit to those still undecided. Thank you. This way, uncle. They are people! Is there anything we can do to get you to change your mind?
wavs/327.wav|Senator Organa is preparing to speak before the full Senate, so you are open to voting with us. It's better than a no.
wavs/328.wav|I'm sure when Christo and the others hear what Bail has to say, they will vote our way. My driver's only a block away. I think I'd like to walk. I can take care of myself.
wavs/329.wav|Plus, I can use the fresh air. There's nothing they can do. I know who did it. They were bounty hunters.
wavs/33.wav|While Ahsoka's viewpoint on the Separatists had all the nuance of a Senate debate, she was exactly right on what had happened in that room.
wavs/330.wav|Paid to stop me from voting against the troop increase. He carries a certain weight. He's seen as a voice of reason. I've been against this bill from day one.
wavs/331.wav|If they didn't listen to me before, why would they listen now? Like so many of the people that we tell ourselves, we're here to serve.
wavs/332.wav|Tekla lives in a district that rarely has electricity and running water as a result of the war.
wavs/333.wav|Her children can now only bathe every two weeks, and they have no light in which to read or study at night.
wavs/334.wav|with no thought for what the people need to survive. This war is meant to save them from suffering, not increase it.
wavs/335.wav|It is not on the battlefield where Dooku will defeat us, but in our own homes. Therefore, it is our duty and our responsibility to defend our land.
wavs/336.wav|to preserve the lives of those around us by defeating this bill. Is Boss Leoni calling for a march on feed? Of course it's not.
wavs/337.wav|With all due respect, your course of action is based on lies. You must make your warriors stand down, or under someone's influence.
wavs/338.wav|Who are we? Boss Leoni, don't you remember anything? I know, Jar Jar. The bandages have stopped the bleeding, but he's unconscious.
wavs/339.wav|The resemblance is,remarkable. You! You look just like Boss Leone. I didn't realize it until you put the crown on.
wavs/34.wav|That was the Galactic Senate for you. People were dying across the galaxy, and the Senate made it sound like a banking problem.
wavs/340.wav|I'm not sure, Jar Jar. What do you want, Dooku? I can't do that. I can't, Jar Jar. With Grievous captured, we could win the war.
wavs/341.wav|I know, Jar Jar. What is going on? What have you done here, Clovis? All of your idealism was just a front.
wavs/342.wav|Why are you doing this? Listen to yourself. The Republic is sending its armada to take back the banks. You've brought war right where there cannot be war.
wavs/343.wav|Your actions have destroyed the banks once and for all! Clovis, you have to turn yourself in. Let me go, Clovis!
wavs/344.wav|No! Anakin, don't! I'm sorry, Anakin. I'm sorry. You know you will soon be destroyed.
wavs/345.wav|I can't tell you how many times I've seen battle droids sliced in half by a lone Jedi. You made it! I'm rescued at last!
wavs/346.wav|Hurry before the battle droids figure out what's happening. Thank you. Let's get out of here, Master Jedi. Three pee o, where's Jar Jar?
wavs/347.wav|What about the Jedi that's not good, but I need you to stay calm go back to the ship and call for help what? battle droids.
wavs/348.wav|Jar Jar, all right, then find a communications room and send out a distress signal. Hopefully there are some clone ships within range. I'll track down Jar Jar.
wavs/349.wav|Jar Jar! Jar Jar, no. I think Jar Jar's dead, Three pee o. Hold it right there, Viceroy.
wavs/35.wav|Anakin said, wars complicated Ahsoka, but let me simplify it. The Separatists believe the Republic is corrupt.
wavs/350.wav|I think it's time to tell the Viceroy about our little secret, how you never meant to leave the Republic, and how you truly care what's best for your people.
wavs/351.wav|It is the Republic that should be asking your forgiveness, my old friend. Far too often, we forget that our most important allies are our allies.
wavs/352.wav|I wanted to compliment you on your speech. You were very brave in these difficult times. I know the Separatists have approached you to offer their help. Please do not take it.
wavs/353.wav|The Senate will force the Trade Federation to resume trade. It reminds me far too much of Naboo's unscarred history. You certainly have a unique way of looking at things, Annie.
wavs/354.wav|What is it, Ahsoka? I was afraid something like this would happen. I'm not so sure local authorities can handle it. Should you really proceed without the Council's approval?
wavs/355.wav|Well, be careful, Ahsoka. I still can't believe they let you teach. I will do everything I can to prove your innocence, Ahsoka. Wait, where are you going?
wavs/356.wav|You can't leave now. Until we hear from Anakin, let's work on your defense. The Republic recognizes the tragedy of war.
wavs/357.wav|But there is nothing we can change that has already occurred. Anakin! That will be all, Threepio. Yes, Threepio. Now go!
wavs/358.wav|How did you manage this? What happened to your military transport? You called this, home. The Naboo ambassador gave me something, I think,
wavs/359.wav|I still have it here somewhere. It is. It'll be perfect. Five blossom bread. My specialty.
wavs/36.wav|but they're wrong, and we have to restore order. And that was Anakin. He needed to believe in right and wrong, good and evil.
wavs/360.wav|I know how to make lots of things. When I was little, I cooked every day. I've been saving it for a special occasion. I wish it could always be just like this.
wavs/361.wav|Right now? I understand. Don't think you can read my mind. You finally found some time for me. I already told Master Yoda.
wavs/362.wav|I don't want to spy on a colleague and an old friend. Why does that matter? That was before we were together. It's not your decision to make!
wavs/363.wav|It's mine. Actually, I just changed my mind. You've convinced me that it's vital to learn what Clovis is doing. I accept the mission to spy on him.
wavs/364.wav|Don't take it personally, Anakin. Duty comes first. Especially in wartime. At one point, Clovis and I were, close.
wavs/365.wav|It was my choice to return things to a strictly professional level. Clovis didn't take it well. But I know I can regain Clovis's trust.
wavs/367.wav|It's been good to see you again, Clovis. I didn't realize how lonely I was until tonight. Ah, you're taking a pleasure trip?
wavs/368.wav|Maybe you can say a few words on my behalf. It's every day asking for trade concessions, but, I can't ever seem to make progress.
wavs/369.wav|Are you inviting me for political reasons or because you want us to be friends again, I'll be happy to go with you.
wavs/37.wav|And if something was not all good, all right, then to him it was evil. It made him a good Jedi, but a terrible politician.
wavs/370.wav|It'll be like old times. Senator Clovis, please forgive me for arriving unannounced. I came here with the very same hope.
wavs/371.wav|I believe in second chances. Three pee o, after that long trip, I think I need a walk.
wavs/372.wav|Oh, I'm sorry to intrude. I was lonely, so I came looking for you, and I'm fine. I stood up too fast.
wavs/373.wav|A tour sounds perfect. Yes, I'm sure. Padme? That tastes so good. I guess I was just thirsty.
wavs/374.wav|You're so good to me, Clovis. I don't deserve your kindness. Because of you! I did it for the Republic!
wavs/375.wav|I didn't want to believe that you were involved with the Separatists, but you are. You're a traitor! It's on its way to the Senate.
wavs/376.wav|Your scheme is finished. We may never have a better chance to capture Count Dooku. We would like to send two Jedi to confirm you have Count Dooku.
wavs/377.wav|Before delivering the ransom. Impossible. The Senate completed its vote. They've decided in favor of occupation. It was during your meeting with the Chancellor.
wavs/378.wav|Your accident accelerated the Senate's decision. Republic forces are set to leave for Mandalore at sunrise tomorrow. Supreme Chancellor.
wavs/379.wav|I think this should cast a new light on the so called evidence we saw earlier. The person to thank is Duchess Satine. She found the proof.
wavs/38.wav|and no help to her at all. Padme headed to her office, motioning for Ahsoka to follow. There had to be a solution. There had to be another way.
wavs/380.wav|The Senate held an emergency session, and the Republic forces have been ordered to stand down. We have some logistics to discuss in order to ratify the Senate's decision.
wavs/381.wav|Welcome home, Chancellor. I'm thankful to the Jedi for bringing you here safely. Anakin, Ahsoka, welcome to the festival.
wavs/382.wav|Are you that certain an attack is imminent? Once again you have all distinguished yourselves in the eyes of the Republic, and the people of Naboo are in your debt.
wavs/39.wav|Surely the Separatists didn't want continual war, either. If only she could talk to Mina. Mina Bonteri was the enemy now.
wavs/4.wav|Too partisan. Proving herself. Will she ever not be proving herself? It is supposed to be bail. Trusted. Respected.
wavs/40.wav|A senator in the Confederacy, but once Mina was her friend, her mentor. Surely Mina wanted the war to end.
wavs/41.wav|But it was illegal to talk to Separatists, because that would be legitimizing them. Which made it impossible to negotiate peace.
wavs/42.wav|She spoke her thoughts out loud to Ahsoka, who couldn't believe it. Your friend is a Separatist? One of Dooku's pawns?
wavs/43.wav|It's not that simple, she wanted to say. This was the problem. This was why the war would never stop, back in the Senate chamber.
wavs/44.wav|Mott not Rab had called the Separatists, animals, Ahsoka, evil, and pawns. Anakin, wrong.
wavs/45.wav|But what if things weren't so black and white? What if she could find another way? And that was when Padme got an idea.
wavs/46.wav|Are you suggesting, Ahsoka asked after she explained her plan, that I use my status as a Jedi to smuggle you behind enemy lines?
wavs/47.wav|Padme blinked. Time to try a different tack. It's just, she said carefully, that you could get us through to meet with her.
wavs/48.wav|and I haven't seen her and her family for so long. But Ahsoka grinned. Relax, she said. I'll help you. Padme grinned back.
wavs/49.wav|It was simple, in the end. As a Jedi, Ahsoka could get Padme to neutral systems, so they went to Mandalore, and then took a cargo ship to Raxus.
wavs/5.wav|considered a voice of reason. Bail is the one they'll listen to, and the bill on the table is too important for them not to listen.
wavs/50.wav|Mina Bonteri's current home, and the sight of the Separatist capital, they wrapped themselves in hooded cloaks and strode by battle droids as if they belonged there.
wavs/51.wav|Padme had known that Raxxulan was a thriving city, but somehow she'd expected it to look different, shadowy and war torn.
wavs/52.wav|Even though the war had no more come to Raxus than it had to Coruscant, Coruscant hadn't been attacked in a thousand years, and walking its streets,
wavs/53.wav|You'd have no idea the galaxy around it was burning. Nonetheless, with a young Jedi at her side, if they were caught,
wavs/54.wav|A republic senator was not supposed to be strolling on a Raxulan landing platform swarming with battle droids.
wavs/55.wav|Well, it was better not to think about it, but they had a plan. The battle droids on Raxus were no less distractible than anywhere else in the galaxy.
wavs/56.wav|and suddenly Padme was standing in front of Mina Bonteri. Mina said. Padme had forgotten how warm Mina's voice was.
wavs/57.wav|How it could feel like an embrace, just when she needed one. In a moment, the rest of it all fell away. The Separatists. The war.
wavs/58.wav|And they were simply two old friends, beholding each other after all those years. When they got to the Bonteri house, they were greeted by Mina's son, Lux.
wavs/59.wav|who had been just a boy when Padme saw him last, Mina did not look that much older than she had. A little grayer, and something else too.
wavs/6.wav|There is no end to the war in sight. Clones are being slaughtered, and the Separatists are gaining ground. The Republic keeps throwing money at it. Throwing clones at it.
wavs/60.wav|Maybe a little sadder. But Lux was like an entirely different person. He's grown so much, Mina. Padme breathed when she and Ahsoka were inside the house.
wavs/61.wav|It was a foolish thing to say, of course he had, but right now she felt foolish, Mina said gently. With all due respect, Ahsoka said.
wavs/62.wav|As a Separatist, didn't you create this war? Padme turned to her. Ahsoka, Mina reassured. And then she turned her gaze to the young Jedi.
wavs/63.wav|and the Jedi? Ahsoka straightened. Maybe I could speak with him, she said. Padme heard the unsaid words in her old friend's voice.
wavs/64.wav|and looked at the rug, face burning. She hadn't known, Mina added. Ahsoka looked how Padme felt. She made an excuse and stepped outside.
wavs/65.wav|leaving Padme alone with Mina. I'm so sorry, Padme said after a moment. Mina said. I didn't, Padme began.
wavs/66.wav|Mina said. When Mina came back, carrying two glasses of wine, Padme was ready. They discussed the war in general terms, speaking like friendly politicians.
wavs/67.wav|And then, slowly, speaking like any pair of friends might, so much so that when talk returned to the republic's crisis,
wavs/68.wav|Padme said what she would to any other friend. I sensed Dooku's dirty hand in this. Mina's eyebrows quirked. She said dryly.
wavs/69.wav|I forgot Padme said voice sharp you actually admire the man the words were out of her mouth before she could stop them.
wavs/7.wav|Not realizing that the war is a fire that treats everything thrown at it as kindling. The bill on the table not only would expand the war,
wavs/70.wav|Before she could remember, she was supposed to put all those feelings aside and try to talk peace. But talking like friends made her remember what it was like to be friends.
wavs/71.wav|Before Mina had left the Republic, had sided with Dooku, had chosen betrayal, war takes everything from you.
wavs/72.wav|Mina said after a moment. The question is how. Padme straightened, gathered herself, put on her diplomat mask.
wavs/73.wav|That is why it was so urgent that I speak with you. The Republic Senate is holding a critical vote on whether or not to escalate the war effort.
wavs/74.wav|However, many of the delegates are undecided as to what to do. Mina nodded slowly. That was what Padme wanted to hear.
wavs/75.wav|I am certain if you could convince your representatives to extend an olive branch toward the Republic, there might be enough sympathy in the Senate to finally open negotiations.
wavs/76.wav|Thank you, Mina. That's all I ask, Mina said, raising her glass to hope.
wavs/77.wav|and hope was what she had when she and Ahsoka left Raxus. Thanks to Mina's efforts, the Confederate sent it with a hologram of Dooku presiding.
wavs/78.wav|Had passed a resolution to initiate peace talks, Padme had said goodbye to Mina like a diplomat after a successful negotiation, but a little like an old friend too.
wavs/79.wav|She would never understand why Mina Bonteri would side with Dooku, no matter what issues her friend had with the Republic. She would not try to understand.
wavs/8.wav|It would bankrupt the whole Republic. It is supposed to be Bail. He has spent days on his speech. But here Padme is.
wavs/80.wav|But right now, they were both on the side of peace. And maybe one day the war would end and they could really be on the same side again.
wavs/81.wav|and try to repair what had been broken. She had hope. She carried it with her back to Mandalore, then back to Coruscant, to the Senate building.
wavs/82.wav|and up to Chancellor Palpatine's office, where she told him about the Confederate proposal, omitting everything she had done to bring it about, he said.
wavs/83.wav|Your Excellency, Padme said, every bit the proper Senator, we would be remiss if not irresponsible.
wavs/84.wav|To reject the Separatist proposal, an end to the fighting would mean there's no need to borrow money for more clones. The Chancellor beckoned to her, then walked her away from the others.
wavs/86.wav|he said. Padme bristled. He still talked to her like she was a child. I don't understand. Yes, yes, they could.
wavs/87.wav|she weighed her options in a blink. If I might speak with you confidentially, she said. Chancellor Palpatine loved being in on secrets.
wavs/88.wav|I know that this is sincere. I've been in contact with my old friend, Mina Bonteri, and the origin of the proposal is with her.
wavs/89.wav|She smiled winningly. Does it matter, Chancellor, if the result is an end to the war? All the way up to her repulsor pod.
wavs/9.wav|with mere minutes to decide what she is going to say, and all she can think is, it is not supposed to be me.
wavs/90.wav|so she carried her hope with her to the Grand Convocation Chamber. Something was different. The other Senators felt it, too.
wavs/91.wav|The air crackled, Padme drew all the excitement to her, and addressed the chamber. Bail added, it was time to vote.
wavs/92.wav|Padme pressed her button. Nay, then there was a distant explosion. The whole building shook and the lights went out. Coruscant had been attacked.
wavs/93.wav|A power generator bombed. The Separatists were blamed. It made no sense to Padme. They just opened peace talks.
wavs/94.wav|But it was wartime, and no one cared about cents. Holly Bertone moved to immediately deregulate the banks, and the Senate approved in a flash.
wavs/95.wav|More troops. More fighting. More death. More war. Always more war. But Bertone was not done.
wavs/96.wav|Padme could not speak. Five million, Bail said. Of course, Bertone had an answer. Padme could not help herself.
wavs/97.wav|That did it, someone shouted, and in the blink of an eye, wanting peace had come to mean being a traitor, but Padme would not give up.
wavs/98.wav|hissed another senator. There was no point. She could say nothing. They were back to black and white, right and wrong, good and evil.
wavs/99.wav|And if she was not pro war, she might as well be the enemy. A traitor. Then a murmur from Palpatine. A blip in the air.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,3 @@
wavs/10.wav|You've been doing great! You do realize he's not a bear right?
wavs/283.wav|We're supposed to be hunting down the missing relics and catching the bad guy. And we're your friends. That's your answer for everything.
wavs/603.wav|Weather for the coronation is sunny skies! That tickles. Bring them up here would ya? Sky needs to build his strength. air drills, wing lifts, All that boring methodical stuff.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,87 @@
wavs/0.wav|such folly will haunt you save your lies and excuses.
wavs/1.wav|that is called entanglement this is not a test of your honor, my technique cannot be beaten.
wavs/10.wav|my cold fists are proof enough, that was a lifetime ago.
wavs/11.wav|you may battle for one, you are not ready frost. i do not recall accepting an offer. unfocused! first came my brother.
wavs/12.wav|Bi Han. the freezing point for blood. i doubt that i prefer him to you.
wavs/13.wav|get up buffoon! your combat must be perfected. a cold winter will.
wavs/14.wav|earth realm deserves better, you have the warrior spirit. defeat me to earn my mantle.
wavs/15.wav|are you offering Erron Black? here for the ultimate trial. but he was your father figure.
wavs/16.wav|this is not a test of your honor. demagogue! our combat is renewed, scorpion.
wavs/17.wav|cold is my birthright. you were a talented student once. the feeling is mutual, brother.
wavs/18.wav|you are no warrior! for the lin kuei! shirai ryu! this fight was your last.
wavs/19.wav|lin quay fight flawlessly. cut a chill! he corrupted the lin kuei.
wavs/2.wav|it will not last the winter, all the easier to freeze. the lin kuei defend earth realm.
wavs/20.wav|i'll rip out your spine! not yet! i'll ask again, after you cool down.
wavs/21.wav|surrender, kano. i escaped that grim fate. do you accept my challenge? you serve shao khan.
wavs/22.wav|johnny cage called you, ice queen. minus three degrees celsius.
wavs/23.wav|i know little of my ancestors. it will end today.
wavs/24.wav|i am grateful that you saved my life. your teeth chatter. afraid you will catch cold.
wavs/25.wav|she was unworthy. spineless! you will have to kill me first. find another realm to conquer!
wavs/26.wav|your soul will never rest. that is called entanglement.
wavs/27.wav|you are skating on thin ice. i will tolerate no interference, i will hold you to that promise, Kitana. he should have taught you humility.
wavs/28.wav|it will not last the winter. shame on you frost! i shall not live in your shadow, it will not survive the cold.
wavs/29.wav|we appear evenly matched. hanzo, please! save your lies and excuses, still learning.
wavs/3.wav|You espouse virtue. Can the kytinn survive cold? A cold wind blows. No.
wavs/30.wav|i demand you renounce it. with a dark knight and a caped wonder, your reputation precedes you.
wavs/31.wav|the ice cracks beneath you. brother, your forces are not special. die cold turn back!
wavs/32.wav|Kabal. a fool and his vice are soon departed. the cold puts out your flames, nomadic peoples don't achieve greatness.
wavs/33.wav|the tournament is over. fear freezes you! i vowed to hunt criminals like you.
wavs/34.wav|the special forces can restore him. they were not me, baraka. a man's never too old to learn.
wavs/35.wav|lin kuei style predates shaolin. savagery is no match for skill.
wavs/36.wav|a good general is hard to find. i see only my cracked reflection.
wavs/37.wav|ask for mercy! it's a long way from the tournament. you lack patience! love, gets in the way.
wavs/38.wav|how easily my point is proved. have a chill in your spine.
wavs/39.wav|this is for my scar! only if you survive. you are a revenant once more.
wavs/4.wav|Quan Chi did, we both know Bo Rai Cho, then we may both die today, come and join the lin kuei, not today.
wavs/40.wav|i asked a simple question. you'll not survive! you are talented but brash.
wavs/41.wav|the nether realm can have you. but only cowards lead with fear. my technique cannot be beaten.
wavs/42.wav|we owe nothing to him. i will keep you on ice for her. i fear no magic. as did you, Devorah.
wavs/43.wav|freeze! commander briggs or break your ankle. can Tarkatans be redeemed?
wavs/44.wav|one cannot serve two masters. i am the true grand master. it honors lin kuei tradition. lin kuei are not ninjas.
wavs/45.wav|snowed under, winter is here. running on ice is ill advised. you have no virtue, enough lin kuei blood has been shed.
wavs/46.wav|wealth without honor is pointless. i see no distinction. shivering! your thievery ends today.
wavs/47.wav|even iron rods can be ground to needles. try warmer clothing, princess. you're fluid like water.
wavs/48.wav|your blood runs cold, then tarkata is doomed to failure. for the lin kuei! you fought well in the snow forest.
wavs/49.wav|i held you to a higher standard. a poor craftsman blames his tools. our paths crossed years ago, kabal.
wavs/5.wav|beg for your life! you must answer for your crimes. ability, to freeze.
wavs/50.wav|what would that be? call me grandmaster. you will fail! finally, you are frivolous johnny cage.
wavs/51.wav|you do not command the lin kuei. your nephew aided us against shinnok. whose fault was that, kotel?
wavs/52.wav|combat is finished, but a cold heart feels no pain. prepare yourself, jacqueline briggs. a shaolin monk should be less boastful.
wavs/53.wav|outworld can learn from earth realm. in which i will exhibit superior skill. you will never find out. he led through lies and fear.
wavs/54.wav|you are one of sector's clones, our clans must unite against evil. the lin kuei are done with you.
wavs/55.wav|are you burning out? a lesson in failure, such folly will haunt you. do you know lin kuei history?
wavs/56.wav|do you serve humanity? demonstrate. your recruits need stronger discipline. you will scream.
wavs/57.wav|they call me grandmaster. only if you prove worthy. to find out whether you are dark or light.
wavs/58.wav|combat will resolve this. you are a chilling reflection, is a demonstration required? practice what you preach, cetrion.
wavs/59.wav|dragon fire! my blood runs cold. grandfather. how would you know that? diamonds do not fight back.
wavs/6.wav|one more time Hanzo, guns are dishonorable weapons. i'm not so cold as to mock your pain.
wavs/60.wav|those blades will snap, your soldiers are going to miss you. my brother deserves no such thing. cold justice! then i'll blind you to end your pain.
wavs/61.wav|can you aim while shivering? the lin kuei punish imposters. we will find him, hanzo. do not let loyalty stunt your growth.
wavs/62.wav|cold enough for you? after you cassandra cage. do not speak of my friends. what did kitana tell you?
wavs/63.wav|but it won't win a fight. you're out world's best, you are finished. can you prove your identity?
wavs/64.wav|back for another training mission? are you prepared to face a lin kuei? bi han tied long ago. you trust technology.
wavs/65.wav|you are cold blooded devorah. your father never taught you honor, our temple in arctica. of course qui liang. as honorable but vulnerable.
wavs/66.wav|getting colder! your fire won't burn me, liu kang. time has revealed your true character.
wavs/67.wav|was i such a poor mentor? you have been corrupted by power. what sort of ruler will you be?
wavs/68.wav|you are no lin kuei! did you come to inform me? you cannot win, combat is full of surprises.
wavs/69.wav|you aided the cyber initiative. if only you'd been more patient, frost. only the best are asked to be lin kuei. where's your master, servant? warmed up yet?
wavs/7.wav|i am assessing your weaknesses. i recall being quan chi's slave.
wavs/70.wav|your bones will freeze. learn your place undisciplined. our realms must remain separate. another outworld perversion.
wavs/71.wav|it's like looking in a mirror, then you know you can't win. how would i do that? because you are going to die.
wavs/72.wav|let us see who's colder? you are not worthy, scarlet. i am prepared. calm yourself! the danger is real.
wavs/73.wav|die a cold death! we are not enemies, then you require a lesson. you failed to protect earth realm. bi han, the lin quay do not worship the elder gods.
wavs/74.wav|a name you forsook long ago. it is my turn this is not one of your motion pictures. then we have a conflict, you have.
wavs/75.wav|passed my first test. i will end you you. honor me with your combat. let the cold be your tomb.
wavs/76.wav|this is for hanzo. i am the original quail yang, my clan is no bargaining chip. as the snow falls so will you.
wavs/77.wav|hell will freeze over first, sometimes is too often. how do you plan to defeat me? i disown you in every way which corrupts you, be han.
wavs/78.wav|you will never pillage earth realm, the cyber initiative! shaolin can't fight! cold feet liu kang? why not fight for earth realm?
wavs/79.wav|no power is worth trading your soul. you will share shinnok's fate, then prove yourself worthy. you know death is a cold hand.
wavs/8.wav|the cold will slow you down. allow me to cool your anger. that era will never come.
wavs/80.wav|even a child has more discipline. more often i win. you call that combat? want to know if it's cold proof?
wavs/81.wav|it also blinds you to never trust anyone. frosty! not much of a challenge, please do.
wavs/82.wav|i do not yet trust you as outworld's khan, that is a spurious claim, kung lao.
wavs/83.wav|freeze! i prefer to see your full strength, why should i pray to you? i have no words for you.
wavs/84.wav|you take nothing seriously. all tests are hard before they are easy. this time, i win! unfortunately.
wavs/85.wav|i have no wish to strike you. i come from another timeline, clear as ice, clean as jade. are you black dragon?
wavs/86.wav|he was my equal. i can ice those greedy hands. then it has no honor, the name was grandfather's first and i your honor liu kang.
wavs/9.wav|i have no time to socialize. earth realm stopped you before here to face the grand master.
Binary file not shown.
Binary file not shown.
Binary file not shown.

Some files were not shown because too many files have changed in this diff Show More