elitehacker commited on
Commit
e3dea0f
·
1 Parent(s): 47f1591
This view is limited to 50 files because it contains too many changes.   See raw diff
Files changed (50) hide show
  1. .gitignore +18 -0
  2. InferenceInterfaces/InferenceArchitectures/InferenceFastSpeech2.py +256 -0
  3. InferenceInterfaces/InferenceArchitectures/InferenceHiFiGAN.py +91 -0
  4. InferenceInterfaces/InferenceArchitectures/__init__.py +0 -0
  5. InferenceInterfaces/Meta_FastSpeech2.py +81 -0
  6. InferenceInterfaces/__init__.py +0 -0
  7. Layers/Attention.py +296 -0
  8. Layers/Conformer.py +144 -0
  9. Layers/Convolution.py +52 -0
  10. Layers/DurationPredictor.py +118 -0
  11. Layers/EncoderLayer.py +140 -0
  12. Layers/LayerNorm.py +33 -0
  13. Layers/LengthRegulator.py +47 -0
  14. Layers/MultiLayeredConv1d.py +75 -0
  15. Layers/MultiSequential.py +30 -0
  16. Layers/PositionalEncoding.py +145 -0
  17. Layers/PositionwiseFeedForward.py +22 -0
  18. Layers/PostNet.py +60 -0
  19. Layers/ResidualBlock.py +93 -0
  20. Layers/ResidualStack.py +49 -0
  21. Layers/STFT.py +118 -0
  22. Layers/Swish.py +15 -0
  23. Layers/VariancePredictor.py +53 -0
  24. Layers/__init__.py +0 -0
  25. Models/FastSpeech2_Meta/__init__.py +0 -0
  26. Models/HiFiGAN_combined/__init__.py +0 -0
  27. Models/SpeakerEmbedding/speechbrain_speaker_embedding_ecapa/hyperparams.yaml +59 -0
  28. Models/SpeakerEmbedding/speechbrain_speaker_embedding_xvector/hyperparams.yaml +64 -0
  29. Preprocessing/ArticulatoryCombinedTextFrontend.py +319 -0
  30. Preprocessing/AudioPreprocessor.py +163 -0
  31. Preprocessing/ProsodicConditionExtractor.py +40 -0
  32. Preprocessing/__init__.py +0 -0
  33. Preprocessing/papercup_features.py +637 -0
  34. Utility/__init__.py +0 -0
  35. Utility/utils.py +355 -0
  36. app.py +200 -0
  37. reference_audios/__init__.py +0 -0
  38. reference_audios/andrew-angry.mp3 +0 -0
  39. reference_audios/andrew-cheerful.mp3 +0 -0
  40. reference_audios/andrew-excited.mp3 +0 -0
  41. reference_audios/andrew-friendly.mp3 +0 -0
  42. reference_audios/andrew-hopeful.mp3 +0 -0
  43. reference_audios/andrew-normal.mp3 +0 -0
  44. reference_audios/andrew-sad.mp3 +0 -0
  45. reference_audios/andrew-shouting.mp3 +0 -0
  46. reference_audios/andrew-terrified.mp3 +0 -0
  47. reference_audios/andrew-unfriendly.mp3 +0 -0
  48. reference_audios/andrew-whispering.mp3 +0 -0
  49. reference_audios/italian.flac +0 -0
  50. reference_audios/polish.flac +0 -0
.gitignore ADDED
@@ -0,0 +1,18 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ .idea
2
+ *.pyc
3
+ *.png
4
+ *.pdf
5
+ tensorboard_logs
6
+ Corpora
7
+ *_graph
8
+ *.out
9
+ *.wav
10
+ audios/
11
+ *playground*
12
+ *.json
13
+ *.pt
14
+ *.ckpt
15
+ .tmp/
16
+ .vscode/
17
+ *.pt
18
+ *.ckpt
InferenceInterfaces/InferenceArchitectures/InferenceFastSpeech2.py ADDED
@@ -0,0 +1,256 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from abc import ABC
2
+
3
+ import torch
4
+
5
+ from Layers.Conformer import Conformer
6
+ from Layers.DurationPredictor import DurationPredictor
7
+ from Layers.LengthRegulator import LengthRegulator
8
+ from Layers.PostNet import PostNet
9
+ from Layers.VariancePredictor import VariancePredictor
10
+ from Utility.utils import make_non_pad_mask
11
+ from Utility.utils import make_pad_mask
12
+
13
+
14
+ class FastSpeech2(torch.nn.Module, ABC):
15
+
16
+ def __init__(self, # network structure related
17
+ weights,
18
+ idim=66,
19
+ odim=80,
20
+ adim=384,
21
+ aheads=4,
22
+ elayers=6,
23
+ eunits=1536,
24
+ dlayers=6,
25
+ dunits=1536,
26
+ postnet_layers=5,
27
+ postnet_chans=256,
28
+ postnet_filts=5,
29
+ positionwise_conv_kernel_size=1,
30
+ use_scaled_pos_enc=True,
31
+ use_batch_norm=True,
32
+ encoder_normalize_before=True,
33
+ decoder_normalize_before=True,
34
+ encoder_concat_after=False,
35
+ decoder_concat_after=False,
36
+ reduction_factor=1,
37
+ # encoder / decoder
38
+ use_macaron_style_in_conformer=True,
39
+ use_cnn_in_conformer=True,
40
+ conformer_enc_kernel_size=7,
41
+ conformer_dec_kernel_size=31,
42
+ # duration predictor
43
+ duration_predictor_layers=2,
44
+ duration_predictor_chans=256,
45
+ duration_predictor_kernel_size=3,
46
+ # energy predictor
47
+ energy_predictor_layers=2,
48
+ energy_predictor_chans=256,
49
+ energy_predictor_kernel_size=3,
50
+ energy_predictor_dropout=0.5,
51
+ energy_embed_kernel_size=1,
52
+ energy_embed_dropout=0.0,
53
+ stop_gradient_from_energy_predictor=True,
54
+ # pitch predictor
55
+ pitch_predictor_layers=5,
56
+ pitch_predictor_chans=256,
57
+ pitch_predictor_kernel_size=5,
58
+ pitch_predictor_dropout=0.5,
59
+ pitch_embed_kernel_size=1,
60
+ pitch_embed_dropout=0.0,
61
+ stop_gradient_from_pitch_predictor=True,
62
+ # training related
63
+ transformer_enc_dropout_rate=0.2,
64
+ transformer_enc_positional_dropout_rate=0.2,
65
+ transformer_enc_attn_dropout_rate=0.2,
66
+ transformer_dec_dropout_rate=0.2,
67
+ transformer_dec_positional_dropout_rate=0.2,
68
+ transformer_dec_attn_dropout_rate=0.2,
69
+ duration_predictor_dropout_rate=0.2,
70
+ postnet_dropout_rate=0.5,
71
+ # additional features
72
+ utt_embed_dim=704,
73
+ connect_utt_emb_at_encoder_out=True,
74
+ lang_embs=100):
75
+ super().__init__()
76
+ self.idim = idim
77
+ self.odim = odim
78
+ self.reduction_factor = reduction_factor
79
+ self.stop_gradient_from_pitch_predictor = stop_gradient_from_pitch_predictor
80
+ self.stop_gradient_from_energy_predictor = stop_gradient_from_energy_predictor
81
+ self.use_scaled_pos_enc = use_scaled_pos_enc
82
+ embed = torch.nn.Sequential(torch.nn.Linear(idim, 100),
83
+ torch.nn.Tanh(),
84
+ torch.nn.Linear(100, adim))
85
+ self.encoder = Conformer(idim=idim, attention_dim=adim, attention_heads=aheads, linear_units=eunits, num_blocks=elayers,
86
+ input_layer=embed, dropout_rate=transformer_enc_dropout_rate,
87
+ positional_dropout_rate=transformer_enc_positional_dropout_rate, attention_dropout_rate=transformer_enc_attn_dropout_rate,
88
+ normalize_before=encoder_normalize_before, concat_after=encoder_concat_after,
89
+ positionwise_conv_kernel_size=positionwise_conv_kernel_size, macaron_style=use_macaron_style_in_conformer,
90
+ use_cnn_module=use_cnn_in_conformer, cnn_module_kernel=conformer_enc_kernel_size, zero_triu=False,
91
+ utt_embed=utt_embed_dim, connect_utt_emb_at_encoder_out=connect_utt_emb_at_encoder_out, lang_embs=lang_embs)
92
+ self.duration_predictor = DurationPredictor(idim=adim, n_layers=duration_predictor_layers,
93
+ n_chans=duration_predictor_chans,
94
+ kernel_size=duration_predictor_kernel_size,
95
+ dropout_rate=duration_predictor_dropout_rate, )
96
+ self.pitch_predictor = VariancePredictor(idim=adim, n_layers=pitch_predictor_layers,
97
+ n_chans=pitch_predictor_chans,
98
+ kernel_size=pitch_predictor_kernel_size,
99
+ dropout_rate=pitch_predictor_dropout)
100
+ self.pitch_embed = torch.nn.Sequential(torch.nn.Conv1d(in_channels=1, out_channels=adim,
101
+ kernel_size=pitch_embed_kernel_size,
102
+ padding=(pitch_embed_kernel_size - 1) // 2),
103
+ torch.nn.Dropout(pitch_embed_dropout))
104
+ self.energy_predictor = VariancePredictor(idim=adim, n_layers=energy_predictor_layers,
105
+ n_chans=energy_predictor_chans,
106
+ kernel_size=energy_predictor_kernel_size,
107
+ dropout_rate=energy_predictor_dropout)
108
+ self.energy_embed = torch.nn.Sequential(torch.nn.Conv1d(in_channels=1, out_channels=adim,
109
+ kernel_size=energy_embed_kernel_size,
110
+ padding=(energy_embed_kernel_size - 1) // 2),
111
+ torch.nn.Dropout(energy_embed_dropout))
112
+ self.length_regulator = LengthRegulator()
113
+ self.decoder = Conformer(idim=0,
114
+ attention_dim=adim,
115
+ attention_heads=aheads,
116
+ linear_units=dunits,
117
+ num_blocks=dlayers,
118
+ input_layer=None,
119
+ dropout_rate=transformer_dec_dropout_rate,
120
+ positional_dropout_rate=transformer_dec_positional_dropout_rate,
121
+ attention_dropout_rate=transformer_dec_attn_dropout_rate,
122
+ normalize_before=decoder_normalize_before,
123
+ concat_after=decoder_concat_after,
124
+ positionwise_conv_kernel_size=positionwise_conv_kernel_size,
125
+ macaron_style=use_macaron_style_in_conformer,
126
+ use_cnn_module=use_cnn_in_conformer,
127
+ cnn_module_kernel=conformer_dec_kernel_size)
128
+ self.feat_out = torch.nn.Linear(adim, odim * reduction_factor)
129
+ self.postnet = PostNet(idim=idim,
130
+ odim=odim,
131
+ n_layers=postnet_layers,
132
+ n_chans=postnet_chans,
133
+ n_filts=postnet_filts,
134
+ use_batch_norm=use_batch_norm,
135
+ dropout_rate=postnet_dropout_rate)
136
+ self.load_state_dict(weights)
137
+
138
+ def _forward(self, text_tensors, text_lens, gold_speech=None, speech_lens=None,
139
+ gold_durations=None, gold_pitch=None, gold_energy=None,
140
+ is_inference=False, alpha=1.0, utterance_embedding=None, lang_ids=None):
141
+ # forward encoder
142
+ text_masks = self._source_mask(text_lens)
143
+
144
+ encoded_texts, _ = self.encoder(text_tensors, text_masks, utterance_embedding=utterance_embedding, lang_ids=lang_ids) # (B, Tmax, adim)
145
+
146
+ # forward duration predictor and variance predictors
147
+ duration_masks = make_pad_mask(text_lens, device=text_lens.device)
148
+
149
+ if self.stop_gradient_from_pitch_predictor:
150
+ pitch_predictions = self.pitch_predictor(encoded_texts.detach(), duration_masks.unsqueeze(-1))
151
+ else:
152
+ pitch_predictions = self.pitch_predictor(encoded_texts, duration_masks.unsqueeze(-1))
153
+
154
+ if self.stop_gradient_from_energy_predictor:
155
+ energy_predictions = self.energy_predictor(encoded_texts.detach(), duration_masks.unsqueeze(-1))
156
+ else:
157
+ energy_predictions = self.energy_predictor(encoded_texts, duration_masks.unsqueeze(-1))
158
+
159
+ if is_inference:
160
+ if gold_durations is not None:
161
+ duration_predictions = gold_durations
162
+ else:
163
+ duration_predictions = self.duration_predictor.inference(encoded_texts, duration_masks)
164
+ if gold_pitch is not None:
165
+ pitch_predictions = gold_pitch
166
+ if gold_energy is not None:
167
+ energy_predictions = gold_energy
168
+ pitch_embeddings = self.pitch_embed(pitch_predictions.transpose(1, 2)).transpose(1, 2)
169
+ energy_embeddings = self.energy_embed(energy_predictions.transpose(1, 2)).transpose(1, 2)
170
+ encoded_texts = encoded_texts + energy_embeddings + pitch_embeddings
171
+ encoded_texts = self.length_regulator(encoded_texts, duration_predictions, alpha)
172
+ else:
173
+ duration_predictions = self.duration_predictor(encoded_texts, duration_masks)
174
+
175
+ # use groundtruth in training
176
+ pitch_embeddings = self.pitch_embed(gold_pitch.transpose(1, 2)).transpose(1, 2)
177
+ energy_embeddings = self.energy_embed(gold_energy.transpose(1, 2)).transpose(1, 2)
178
+ encoded_texts = encoded_texts + energy_embeddings + pitch_embeddings
179
+ encoded_texts = self.length_regulator(encoded_texts, gold_durations) # (B, Lmax, adim)
180
+
181
+ # forward decoder
182
+ if speech_lens is not None and not is_inference:
183
+ if self.reduction_factor > 1:
184
+ olens_in = speech_lens.new([olen // self.reduction_factor for olen in speech_lens])
185
+ else:
186
+ olens_in = speech_lens
187
+ h_masks = self._source_mask(olens_in)
188
+ else:
189
+ h_masks = None
190
+ zs, _ = self.decoder(encoded_texts, h_masks) # (B, Lmax, adim)
191
+ before_outs = self.feat_out(zs).view(zs.size(0), -1, self.odim) # (B, Lmax, odim)
192
+
193
+ # postnet -> (B, Lmax//r * r, odim)
194
+ after_outs = before_outs + self.postnet(before_outs.transpose(1, 2)).transpose(1, 2)
195
+
196
+ return before_outs, after_outs, duration_predictions, pitch_predictions, energy_predictions
197
+
198
+ @torch.no_grad()
199
+ def forward(self,
200
+ text,
201
+ speech=None,
202
+ durations=None,
203
+ pitch=None,
204
+ energy=None,
205
+ utterance_embedding=None,
206
+ return_duration_pitch_energy=False,
207
+ lang_id=None):
208
+ """
209
+ Generate the sequence of features given the sequences of characters.
210
+
211
+ Args:
212
+ text: Input sequence of characters
213
+ speech: Feature sequence to extract style
214
+ durations: Groundtruth of duration
215
+ pitch: Groundtruth of token-averaged pitch
216
+ energy: Groundtruth of token-averaged energy
217
+ return_duration_pitch_energy: whether to return the list of predicted durations for nicer plotting
218
+ utterance_embedding: embedding of utterance wide parameters
219
+
220
+ Returns:
221
+ Mel Spectrogram
222
+
223
+ """
224
+ self.eval()
225
+ # setup batch axis
226
+ ilens = torch.tensor([text.shape[0]], dtype=torch.long, device=text.device)
227
+ if speech is not None:
228
+ gold_speech = speech.unsqueeze(0)
229
+ else:
230
+ gold_speech = None
231
+ if durations is not None:
232
+ durations = durations.unsqueeze(0)
233
+ if pitch is not None:
234
+ pitch = pitch.unsqueeze(0)
235
+ if energy is not None:
236
+ energy = energy.unsqueeze(0)
237
+ if lang_id is not None:
238
+ lang_id = lang_id.unsqueeze(0)
239
+
240
+ before_outs, after_outs, d_outs, pitch_predictions, energy_predictions = self._forward(text.unsqueeze(0),
241
+ ilens,
242
+ gold_speech=gold_speech,
243
+ gold_durations=durations,
244
+ is_inference=True,
245
+ gold_pitch=pitch,
246
+ gold_energy=energy,
247
+ utterance_embedding=utterance_embedding.unsqueeze(0),
248
+ lang_ids=lang_id)
249
+ self.train()
250
+ if return_duration_pitch_energy:
251
+ return after_outs[0], d_outs[0], pitch_predictions[0], energy_predictions[0]
252
+ return after_outs[0]
253
+
254
+ def _source_mask(self, ilens):
255
+ x_masks = make_non_pad_mask(ilens).to(next(self.parameters()).device)
256
+ return x_masks.unsqueeze(-2)
InferenceInterfaces/InferenceArchitectures/InferenceHiFiGAN.py ADDED
@@ -0,0 +1,91 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import torch
2
+
3
+ from Layers.ResidualBlock import HiFiGANResidualBlock as ResidualBlock
4
+
5
+
6
+ class HiFiGANGenerator(torch.nn.Module):
7
+
8
+ def __init__(self,
9
+ path_to_weights,
10
+ in_channels=80,
11
+ out_channels=1,
12
+ channels=512,
13
+ kernel_size=7,
14
+ upsample_scales=(8, 6, 4, 4),
15
+ upsample_kernel_sizes=(16, 12, 8, 8),
16
+ resblock_kernel_sizes=(3, 7, 11),
17
+ resblock_dilations=[(1, 3, 5), (1, 3, 5), (1, 3, 5)],
18
+ use_additional_convs=True,
19
+ bias=True,
20
+ nonlinear_activation="LeakyReLU",
21
+ nonlinear_activation_params={"negative_slope": 0.1},
22
+ use_weight_norm=True, ):
23
+ super().__init__()
24
+ assert kernel_size % 2 == 1, "Kernal size must be odd number."
25
+ assert len(upsample_scales) == len(upsample_kernel_sizes)
26
+ assert len(resblock_dilations) == len(resblock_kernel_sizes)
27
+ self.num_upsamples = len(upsample_kernel_sizes)
28
+ self.num_blocks = len(resblock_kernel_sizes)
29
+ self.input_conv = torch.nn.Conv1d(in_channels,
30
+ channels,
31
+ kernel_size,
32
+ 1,
33
+ padding=(kernel_size - 1) // 2, )
34
+ self.upsamples = torch.nn.ModuleList()
35
+ self.blocks = torch.nn.ModuleList()
36
+ for i in range(len(upsample_kernel_sizes)):
37
+ self.upsamples += [
38
+ torch.nn.Sequential(getattr(torch.nn, nonlinear_activation)(**nonlinear_activation_params),
39
+ torch.nn.ConvTranspose1d(channels // (2 ** i),
40
+ channels // (2 ** (i + 1)),
41
+ upsample_kernel_sizes[i],
42
+ upsample_scales[i],
43
+ padding=(upsample_kernel_sizes[i] - upsample_scales[i]) // 2, ), )]
44
+ for j in range(len(resblock_kernel_sizes)):
45
+ self.blocks += [ResidualBlock(kernel_size=resblock_kernel_sizes[j],
46
+ channels=channels // (2 ** (i + 1)),
47
+ dilations=resblock_dilations[j],
48
+ bias=bias,
49
+ use_additional_convs=use_additional_convs,
50
+ nonlinear_activation=nonlinear_activation,
51
+ nonlinear_activation_params=nonlinear_activation_params, )]
52
+ self.output_conv = torch.nn.Sequential(
53
+ torch.nn.LeakyReLU(),
54
+ torch.nn.Conv1d(channels // (2 ** (i + 1)),
55
+ out_channels,
56
+ kernel_size,
57
+ 1,
58
+ padding=(kernel_size - 1) // 2, ),
59
+ torch.nn.Tanh(), )
60
+ if use_weight_norm:
61
+ self.apply_weight_norm()
62
+ self.load_state_dict(torch.load(path_to_weights, map_location='cpu')["generator"])
63
+
64
+ def forward(self, c, normalize_before=False):
65
+ if normalize_before:
66
+ c = (c - self.mean) / self.scale
67
+ c = self.input_conv(c.unsqueeze(0))
68
+ for i in range(self.num_upsamples):
69
+ c = self.upsamples[i](c)
70
+ cs = 0.0 # initialize
71
+ for j in range(self.num_blocks):
72
+ cs = cs + self.blocks[i * self.num_blocks + j](c)
73
+ c = cs / self.num_blocks
74
+ c = self.output_conv(c)
75
+ return c.squeeze(0).squeeze(0)
76
+
77
+ def remove_weight_norm(self):
78
+ def _remove_weight_norm(m):
79
+ try:
80
+ torch.nn.utils.remove_weight_norm(m)
81
+ except ValueError:
82
+ return
83
+
84
+ self.apply(_remove_weight_norm)
85
+
86
+ def apply_weight_norm(self):
87
+ def _apply_weight_norm(m):
88
+ if isinstance(m, torch.nn.Conv1d) or isinstance(m, torch.nn.ConvTranspose1d):
89
+ torch.nn.utils.weight_norm(m)
90
+
91
+ self.apply(_apply_weight_norm)
InferenceInterfaces/InferenceArchitectures/__init__.py ADDED
File without changes
InferenceInterfaces/Meta_FastSpeech2.py ADDED
@@ -0,0 +1,81 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import librosa.display as lbd
4
+ import matplotlib.pyplot as plt
5
+ import soundfile
6
+ import torch
7
+
8
+ from InferenceInterfaces.InferenceArchitectures.InferenceFastSpeech2 import FastSpeech2
9
+ from InferenceInterfaces.InferenceArchitectures.InferenceHiFiGAN import HiFiGANGenerator
10
+ from Preprocessing.ArticulatoryCombinedTextFrontend import ArticulatoryCombinedTextFrontend
11
+ from Preprocessing.ArticulatoryCombinedTextFrontend import get_language_id
12
+ from Preprocessing.ProsodicConditionExtractor import ProsodicConditionExtractor
13
+
14
+
15
+ class Meta_FastSpeech2(torch.nn.Module):
16
+
17
+ def __init__(self, device="cpu"):
18
+ super().__init__()
19
+ model_name = "Meta"
20
+ language = "en"
21
+ self.device = device
22
+ self.text2phone = ArticulatoryCombinedTextFrontend(language=language, add_silence_to_end=True)
23
+ checkpoint = torch.load(os.path.join("Models", f"FastSpeech2_{model_name}", "best.pt"), map_location='cpu')
24
+ self.phone2mel = FastSpeech2(weights=checkpoint["model"]).to(torch.device(device))
25
+ self.mel2wav = HiFiGANGenerator(path_to_weights=os.path.join("Models", "HiFiGAN_combined", "best.pt")).to(torch.device(device))
26
+ self.default_utterance_embedding = checkpoint["default_emb"].to(self.device)
27
+ self.phone2mel.eval()
28
+ self.mel2wav.eval()
29
+ self.lang_id = get_language_id(language)
30
+ self.to(torch.device(device))
31
+
32
+ def set_utterance_embedding(self, path_to_reference_audio):
33
+ wave, sr = soundfile.read(path_to_reference_audio)
34
+ self.default_utterance_embedding = ProsodicConditionExtractor(sr=sr).extract_condition_from_reference_wave(wave).to(self.device)
35
+
36
+ def set_phonemizer_language(self, lang_id):
37
+ """
38
+ The id parameter actually refers to the shorthand. This has become ambiguous with the introduction of the actual language IDs
39
+ """
40
+ self.text2phone = ArticulatoryCombinedTextFrontend(language=lang_id, add_silence_to_end=True, silent=False)
41
+
42
+ def set_accent_language(self, lang_id):
43
+ """
44
+ The id parameter actually refers to the shorthand. This has become ambiguous with the introduction of the actual language IDs
45
+ """
46
+ self.lang_id = get_language_id(lang_id).to(self.device)
47
+
48
+ def forward(self, text, view=False, durations=None, pitch=None, energy=None):
49
+ with torch.no_grad():
50
+ phones = self.text2phone.string_to_tensor(text, input_phonemes=True).to(torch.device(self.device))
51
+ mel, durations, pitch, energy = self.phone2mel(phones,
52
+ return_duration_pitch_energy=True,
53
+ utterance_embedding=self.default_utterance_embedding,
54
+ durations=durations,
55
+ pitch=pitch,
56
+ energy=energy,
57
+ lang_id=self.lang_id)
58
+ mel = mel.transpose(0, 1)
59
+ wave = self.mel2wav(mel)
60
+ if view:
61
+ from Utility.utils import cumsum_durations
62
+ fig, ax = plt.subplots(nrows=2, ncols=1)
63
+ ax[0].plot(wave.cpu().numpy())
64
+ lbd.specshow(mel.cpu().numpy(),
65
+ ax=ax[1],
66
+ sr=16000,
67
+ cmap='GnBu',
68
+ y_axis='mel',
69
+ x_axis=None,
70
+ hop_length=256)
71
+ ax[0].yaxis.set_visible(False)
72
+ ax[1].yaxis.set_visible(False)
73
+ duration_splits, label_positions = cumsum_durations(durations.cpu().numpy())
74
+ ax[1].set_xticks(duration_splits, minor=True)
75
+ ax[1].xaxis.grid(True, which='minor')
76
+ ax[1].set_xticks(label_positions, minor=False)
77
+ ax[1].set_xticklabels(self.text2phone.get_phone_string(text))
78
+ ax[0].set_title(text)
79
+ plt.subplots_adjust(left=0.05, bottom=0.1, right=0.95, top=.9, wspace=0.0, hspace=0.0)
80
+ plt.show()
81
+ return wave
InferenceInterfaces/__init__.py ADDED
File without changes
Layers/Attention.py ADDED
@@ -0,0 +1,296 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ """Multi-Head Attention layer definition."""
4
+
5
+ import math
6
+
7
+ import numpy
8
+ import torch
9
+ from torch import nn
10
+
11
+ from Utility.utils import make_non_pad_mask
12
+
13
+
14
+ class MultiHeadedAttention(nn.Module):
15
+ """
16
+ Multi-Head Attention layer.
17
+
18
+ Args:
19
+ n_head (int): The number of heads.
20
+ n_feat (int): The number of features.
21
+ dropout_rate (float): Dropout rate.
22
+ """
23
+
24
+ def __init__(self, n_head, n_feat, dropout_rate):
25
+ """
26
+ Construct an MultiHeadedAttention object.
27
+ """
28
+ super(MultiHeadedAttention, self).__init__()
29
+ assert n_feat % n_head == 0
30
+ # We assume d_v always equals d_k
31
+ self.d_k = n_feat // n_head
32
+ self.h = n_head
33
+ self.linear_q = nn.Linear(n_feat, n_feat)
34
+ self.linear_k = nn.Linear(n_feat, n_feat)
35
+ self.linear_v = nn.Linear(n_feat, n_feat)
36
+ self.linear_out = nn.Linear(n_feat, n_feat)
37
+ self.attn = None
38
+ self.dropout = nn.Dropout(p=dropout_rate)
39
+
40
+ def forward_qkv(self, query, key, value):
41
+ """
42
+ Transform query, key and value.
43
+
44
+ Args:
45
+ query (torch.Tensor): Query tensor (#batch, time1, size).
46
+ key (torch.Tensor): Key tensor (#batch, time2, size).
47
+ value (torch.Tensor): Value tensor (#batch, time2, size).
48
+
49
+ Returns:
50
+ torch.Tensor: Transformed query tensor (#batch, n_head, time1, d_k).
51
+ torch.Tensor: Transformed key tensor (#batch, n_head, time2, d_k).
52
+ torch.Tensor: Transformed value tensor (#batch, n_head, time2, d_k).
53
+ """
54
+ n_batch = query.size(0)
55
+ q = self.linear_q(query).view(n_batch, -1, self.h, self.d_k)
56
+ k = self.linear_k(key).view(n_batch, -1, self.h, self.d_k)
57
+ v = self.linear_v(value).view(n_batch, -1, self.h, self.d_k)
58
+ q = q.transpose(1, 2) # (batch, head, time1, d_k)
59
+ k = k.transpose(1, 2) # (batch, head, time2, d_k)
60
+ v = v.transpose(1, 2) # (batch, head, time2, d_k)
61
+
62
+ return q, k, v
63
+
64
+ def forward_attention(self, value, scores, mask):
65
+ """
66
+ Compute attention context vector.
67
+
68
+ Args:
69
+ value (torch.Tensor): Transformed value (#batch, n_head, time2, d_k).
70
+ scores (torch.Tensor): Attention score (#batch, n_head, time1, time2).
71
+ mask (torch.Tensor): Mask (#batch, 1, time2) or (#batch, time1, time2).
72
+
73
+ Returns:
74
+ torch.Tensor: Transformed value (#batch, time1, d_model)
75
+ weighted by the attention score (#batch, time1, time2).
76
+ """
77
+ n_batch = value.size(0)
78
+ if mask is not None:
79
+ mask = mask.unsqueeze(1).eq(0) # (batch, 1, *, time2)
80
+ min_value = float(numpy.finfo(torch.tensor(0, dtype=scores.dtype).numpy().dtype).min)
81
+ scores = scores.masked_fill(mask, min_value)
82
+ self.attn = torch.softmax(scores, dim=-1).masked_fill(mask, 0.0) # (batch, head, time1, time2)
83
+ else:
84
+ self.attn = torch.softmax(scores, dim=-1) # (batch, head, time1, time2)
85
+
86
+ p_attn = self.dropout(self.attn)
87
+ x = torch.matmul(p_attn, value) # (batch, head, time1, d_k)
88
+ x = (x.transpose(1, 2).contiguous().view(n_batch, -1, self.h * self.d_k)) # (batch, time1, d_model)
89
+
90
+ return self.linear_out(x) # (batch, time1, d_model)
91
+
92
+ def forward(self, query, key, value, mask):
93
+ """
94
+ Compute scaled dot product attention.
95
+
96
+ Args:
97
+ query (torch.Tensor): Query tensor (#batch, time1, size).
98
+ key (torch.Tensor): Key tensor (#batch, time2, size).
99
+ value (torch.Tensor): Value tensor (#batch, time2, size).
100
+ mask (torch.Tensor): Mask tensor (#batch, 1, time2) or
101
+ (#batch, time1, time2).
102
+
103
+ Returns:
104
+ torch.Tensor: Output tensor (#batch, time1, d_model).
105
+ """
106
+ q, k, v = self.forward_qkv(query, key, value)
107
+ scores = torch.matmul(q, k.transpose(-2, -1)) / math.sqrt(self.d_k)
108
+ return self.forward_attention(v, scores, mask)
109
+
110
+
111
+ class RelPositionMultiHeadedAttention(MultiHeadedAttention):
112
+
113
+ def __init__(self, n_head, n_feat, dropout_rate, zero_triu=False):
114
+ """Construct an RelPositionMultiHeadedAttention object."""
115
+ super().__init__(n_head, n_feat, dropout_rate)
116
+ self.zero_triu = zero_triu
117
+ # linear transformation for positional encoding
118
+ self.linear_pos = nn.Linear(n_feat, n_feat, bias=False)
119
+ self.pos_bias_u = nn.Parameter(torch.Tensor(self.h, self.d_k))
120
+ self.pos_bias_v = nn.Parameter(torch.Tensor(self.h, self.d_k))
121
+ torch.nn.init.xavier_uniform_(self.pos_bias_u)
122
+ torch.nn.init.xavier_uniform_(self.pos_bias_v)
123
+
124
+ def rel_shift(self, x):
125
+ """
126
+ Compute relative positional encoding.
127
+ Args:
128
+ x (torch.Tensor): Input tensor (batch, head, time1, 2*time1-1).
129
+ time1 means the length of query vector.
130
+ Returns:
131
+ torch.Tensor: Output tensor.
132
+ """
133
+ zero_pad = torch.zeros((*x.size()[:3], 1), device=x.device, dtype=x.dtype)
134
+ x_padded = torch.cat([zero_pad, x], dim=-1)
135
+
136
+ x_padded = x_padded.view(*x.size()[:2], x.size(3) + 1, x.size(2))
137
+ x = x_padded[:, :, 1:].view_as(x)[:, :, :, : x.size(-1) // 2 + 1] # only keep the positions from 0 to time2
138
+
139
+ if self.zero_triu:
140
+ ones = torch.ones((x.size(2), x.size(3)), device=x.device)
141
+ x = x * torch.tril(ones, x.size(3) - x.size(2))[None, None, :, :]
142
+
143
+ return x
144
+
145
+ def forward(self, query, key, value, pos_emb, mask):
146
+ """
147
+ Compute 'Scaled Dot Product Attention' with rel. positional encoding.
148
+ Args:
149
+ query (torch.Tensor): Query tensor (#batch, time1, size).
150
+ key (torch.Tensor): Key tensor (#batch, time2, size).
151
+ value (torch.Tensor): Value tensor (#batch, time2, size).
152
+ pos_emb (torch.Tensor): Positional embedding tensor
153
+ (#batch, 2*time1-1, size).
154
+ mask (torch.Tensor): Mask tensor (#batch, 1, time2) or
155
+ (#batch, time1, time2).
156
+ Returns:
157
+ torch.Tensor: Output tensor (#batch, time1, d_model).
158
+ """
159
+ q, k, v = self.forward_qkv(query, key, value)
160
+ q = q.transpose(1, 2) # (batch, time1, head, d_k)
161
+
162
+ n_batch_pos = pos_emb.size(0)
163
+ p = self.linear_pos(pos_emb).view(n_batch_pos, -1, self.h, self.d_k)
164
+ p = p.transpose(1, 2) # (batch, head, 2*time1-1, d_k)
165
+
166
+ # (batch, head, time1, d_k)
167
+ q_with_bias_u = (q + self.pos_bias_u).transpose(1, 2)
168
+ # (batch, head, time1, d_k)
169
+ q_with_bias_v = (q + self.pos_bias_v).transpose(1, 2)
170
+
171
+
172
+ matrix_ac = torch.matmul(q_with_bias_u, k.transpose(-2, -1))
173
+
174
+ # compute matrix b and matrix d
175
+ # (batch, head, time1, 2*time1-1)
176
+ matrix_bd = torch.matmul(q_with_bias_v, p.transpose(-2, -1))
177
+ matrix_bd = self.rel_shift(matrix_bd)
178
+
179
+ scores = (matrix_ac + matrix_bd) / math.sqrt(self.d_k) # (batch, head, time1, time2)
180
+
181
+ return self.forward_attention(v, scores, mask)
182
+
183
+
184
+ class GuidedAttentionLoss(torch.nn.Module):
185
+
186
+
187
+ def __init__(self, sigma=0.4, alpha=1.0):
188
+ """
189
+ Initialize guided attention loss module.
190
+
191
+ Args:
192
+ sigma (float, optional): Standard deviation to control
193
+ how close attention to a diagonal.
194
+ alpha (float, optional): Scaling coefficient (lambda).
195
+ reset_always (bool, optional): Whether to always reset masks.
196
+ """
197
+ super(GuidedAttentionLoss, self).__init__()
198
+ self.sigma = sigma
199
+ self.alpha = alpha
200
+ self.guided_attn_masks = None
201
+ self.masks = None
202
+
203
+ def _reset_masks(self):
204
+ self.guided_attn_masks = None
205
+ self.masks = None
206
+
207
+ def forward(self, att_ws, ilens, olens):
208
+ """
209
+ Calculate forward propagation.
210
+
211
+ Args:
212
+ att_ws (Tensor): Batch of attention weights (B, T_max_out, T_max_in).
213
+ ilens (LongTensor): Batch of input lenghts (B,).
214
+ olens (LongTensor): Batch of output lenghts (B,).
215
+
216
+ Returns:
217
+ Tensor: Guided attention loss value.
218
+ """
219
+ self._reset_masks()
220
+ self.guided_attn_masks = self._make_guided_attention_masks(ilens, olens).to(att_ws.device)
221
+ self.masks = self._make_masks(ilens, olens).to(att_ws.device)
222
+ losses = self.guided_attn_masks * att_ws
223
+ loss = torch.mean(losses.masked_select(self.masks))
224
+ self._reset_masks()
225
+ return self.alpha * loss
226
+
227
+ def _make_guided_attention_masks(self, ilens, olens):
228
+ n_batches = len(ilens)
229
+ max_ilen = max(ilens)
230
+ max_olen = max(olens)
231
+ guided_attn_masks = torch.zeros((n_batches, max_olen, max_ilen), device=ilens.device)
232
+ for idx, (ilen, olen) in enumerate(zip(ilens, olens)):
233
+ guided_attn_masks[idx, :olen, :ilen] = self._make_guided_attention_mask(ilen, olen, self.sigma)
234
+ return guided_attn_masks
235
+
236
+ @staticmethod
237
+ def _make_guided_attention_mask(ilen, olen, sigma):
238
+ """
239
+ Make guided attention mask.
240
+ """
241
+ grid_x, grid_y = torch.meshgrid(torch.arange(olen, device=olen.device).float(), torch.arange(ilen, device=ilen.device).float())
242
+ return 1.0 - torch.exp(-((grid_y / ilen - grid_x / olen) ** 2) / (2 * (sigma ** 2)))
243
+
244
+ @staticmethod
245
+ def _make_masks(ilens, olens):
246
+ """
247
+ Make masks indicating non-padded part.
248
+
249
+ Args:
250
+ ilens (LongTensor or List): Batch of lengths (B,).
251
+ olens (LongTensor or List): Batch of lengths (B,).
252
+
253
+ Returns:
254
+ Tensor: Mask tensor indicating non-padded part.
255
+ dtype=torch.uint8 in PyTorch 1.2-
256
+ dtype=torch.bool in PyTorch 1.2+ (including 1.2)
257
+ """
258
+ in_masks = make_non_pad_mask(ilens, device=ilens.device) # (B, T_in)
259
+ out_masks = make_non_pad_mask(olens, device=olens.device) # (B, T_out)
260
+ return out_masks.unsqueeze(-1) & in_masks.unsqueeze(-2) # (B, T_out, T_in)
261
+
262
+
263
+ class GuidedMultiHeadAttentionLoss(GuidedAttentionLoss):
264
+ """
265
+ Guided attention loss function module for multi head attention.
266
+
267
+ Args:
268
+ sigma (float, optional): Standard deviation to control
269
+ how close attention to a diagonal.
270
+ alpha (float, optional): Scaling coefficient (lambda).
271
+ reset_always (bool, optional): Whether to always reset masks.
272
+ """
273
+
274
+ def forward(self, att_ws, ilens, olens):
275
+ """
276
+ Calculate forward propagation.
277
+
278
+ Args:
279
+ att_ws (Tensor):
280
+ Batch of multi head attention weights (B, H, T_max_out, T_max_in).
281
+ ilens (LongTensor): Batch of input lenghts (B,).
282
+ olens (LongTensor): Batch of output lenghts (B,).
283
+
284
+ Returns:
285
+ Tensor: Guided attention loss value.
286
+ """
287
+ if self.guided_attn_masks is None:
288
+ self.guided_attn_masks = (self._make_guided_attention_masks(ilens, olens).to(att_ws.device).unsqueeze(1))
289
+ if self.masks is None:
290
+ self.masks = self._make_masks(ilens, olens).to(att_ws.device).unsqueeze(1)
291
+ losses = self.guided_attn_masks * att_ws
292
+ loss = torch.mean(losses.masked_select(self.masks))
293
+ if self.reset_always:
294
+ self._reset_masks()
295
+
296
+ return self.alpha * loss
Layers/Conformer.py ADDED
@@ -0,0 +1,144 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Taken from ESPNet
3
+ """
4
+
5
+ import torch
6
+ import torch.nn.functional as F
7
+
8
+ from Layers.Attention import RelPositionMultiHeadedAttention
9
+ from Layers.Convolution import ConvolutionModule
10
+ from Layers.EncoderLayer import EncoderLayer
11
+ from Layers.LayerNorm import LayerNorm
12
+ from Layers.MultiLayeredConv1d import MultiLayeredConv1d
13
+ from Layers.MultiSequential import repeat
14
+ from Layers.PositionalEncoding import RelPositionalEncoding
15
+ from Layers.Swish import Swish
16
+
17
+
18
+ class Conformer(torch.nn.Module):
19
+ """
20
+ Conformer encoder module.
21
+
22
+ Args:
23
+ idim (int): Input dimension.
24
+ attention_dim (int): Dimension of attention.
25
+ attention_heads (int): The number of heads of multi head attention.
26
+ linear_units (int): The number of units of position-wise feed forward.
27
+ num_blocks (int): The number of decoder blocks.
28
+ dropout_rate (float): Dropout rate.
29
+ positional_dropout_rate (float): Dropout rate after adding positional encoding.
30
+ attention_dropout_rate (float): Dropout rate in attention.
31
+ input_layer (Union[str, torch.nn.Module]): Input layer type.
32
+ normalize_before (bool): Whether to use layer_norm before the first block.
33
+ concat_after (bool): Whether to concat attention layer's input and output.
34
+ if True, additional linear will be applied.
35
+ i.e. x -> x + linear(concat(x, att(x)))
36
+ if False, no additional linear will be applied. i.e. x -> x + att(x)
37
+ positionwise_layer_type (str): "linear", "conv1d", or "conv1d-linear".
38
+ positionwise_conv_kernel_size (int): Kernel size of positionwise conv1d layer.
39
+ macaron_style (bool): Whether to use macaron style for positionwise layer.
40
+ pos_enc_layer_type (str): Conformer positional encoding layer type.
41
+ selfattention_layer_type (str): Conformer attention layer type.
42
+ activation_type (str): Conformer activation function type.
43
+ use_cnn_module (bool): Whether to use convolution module.
44
+ cnn_module_kernel (int): Kernerl size of convolution module.
45
+ padding_idx (int): Padding idx for input_layer=embed.
46
+
47
+ """
48
+
49
+ def __init__(self, idim, attention_dim=256, attention_heads=4, linear_units=2048, num_blocks=6, dropout_rate=0.1, positional_dropout_rate=0.1,
50
+ attention_dropout_rate=0.0, input_layer="conv2d", normalize_before=True, concat_after=False, positionwise_conv_kernel_size=1,
51
+ macaron_style=False, use_cnn_module=False, cnn_module_kernel=31, zero_triu=False, utt_embed=None, connect_utt_emb_at_encoder_out=True,
52
+ spk_emb_bottleneck_size=128, lang_embs=None):
53
+ super(Conformer, self).__init__()
54
+
55
+ activation = Swish()
56
+ self.conv_subsampling_factor = 1
57
+
58
+ if isinstance(input_layer, torch.nn.Module):
59
+ self.embed = input_layer
60
+ self.pos_enc = RelPositionalEncoding(attention_dim, positional_dropout_rate)
61
+ elif input_layer is None:
62
+ self.embed = None
63
+ self.pos_enc = torch.nn.Sequential(RelPositionalEncoding(attention_dim, positional_dropout_rate))
64
+ else:
65
+ raise ValueError("unknown input_layer: " + input_layer)
66
+
67
+ self.normalize_before = normalize_before
68
+
69
+ self.connect_utt_emb_at_encoder_out = connect_utt_emb_at_encoder_out
70
+ if utt_embed is not None:
71
+ self.hs_emb_projection = torch.nn.Linear(attention_dim + spk_emb_bottleneck_size, attention_dim)
72
+
73
+ self.embedding_projection = torch.nn.Sequential(torch.nn.Linear(utt_embed, spk_emb_bottleneck_size),
74
+ torch.nn.Softsign())
75
+ if lang_embs is not None:
76
+ self.language_embedding = torch.nn.Embedding(num_embeddings=lang_embs, embedding_dim=attention_dim)
77
+
78
+ # self-attention module definition
79
+ encoder_selfattn_layer = RelPositionMultiHeadedAttention
80
+ encoder_selfattn_layer_args = (attention_heads, attention_dim, attention_dropout_rate, zero_triu)
81
+
82
+ # feed-forward module definition
83
+ positionwise_layer = MultiLayeredConv1d
84
+ positionwise_layer_args = (attention_dim, linear_units, positionwise_conv_kernel_size, dropout_rate,)
85
+
86
+ # convolution module definition
87
+ convolution_layer = ConvolutionModule
88
+ convolution_layer_args = (attention_dim, cnn_module_kernel, activation)
89
+
90
+ self.encoders = repeat(num_blocks, lambda lnum: EncoderLayer(attention_dim, encoder_selfattn_layer(*encoder_selfattn_layer_args),
91
+ positionwise_layer(*positionwise_layer_args),
92
+ positionwise_layer(*positionwise_layer_args) if macaron_style else None,
93
+ convolution_layer(*convolution_layer_args) if use_cnn_module else None, dropout_rate,
94
+ normalize_before, concat_after))
95
+ if self.normalize_before:
96
+ self.after_norm = LayerNorm(attention_dim)
97
+
98
+ def forward(self, xs, masks, utterance_embedding=None, lang_ids=None):
99
+ """
100
+ Encode input sequence.
101
+
102
+ Args:
103
+ utterance_embedding: embedding containing lots of conditioning signals
104
+ step: indicator for when to start updating the embedding function
105
+ xs (torch.Tensor): Input tensor (#batch, time, idim).
106
+ masks (torch.Tensor): Mask tensor (#batch, time).
107
+
108
+ Returns:
109
+ torch.Tensor: Output tensor (#batch, time, attention_dim).
110
+ torch.Tensor: Mask tensor (#batch, time).
111
+
112
+ """
113
+
114
+ if self.embed is not None:
115
+ xs = self.embed(xs)
116
+
117
+ if lang_ids is not None:
118
+ lang_embs = self.language_embedding(lang_ids)
119
+ xs = xs + lang_embs # offset the phoneme distribution of a language
120
+
121
+ if utterance_embedding is not None and not self.connect_utt_emb_at_encoder_out:
122
+ xs = self._integrate_with_utt_embed(xs, utterance_embedding)
123
+
124
+ xs = self.pos_enc(xs)
125
+
126
+ xs, masks = self.encoders(xs, masks)
127
+ if isinstance(xs, tuple):
128
+ xs = xs[0]
129
+
130
+ if self.normalize_before:
131
+ xs = self.after_norm(xs)
132
+
133
+ if utterance_embedding is not None and self.connect_utt_emb_at_encoder_out:
134
+ xs = self._integrate_with_utt_embed(xs, utterance_embedding)
135
+
136
+ return xs, masks
137
+
138
+ def _integrate_with_utt_embed(self, hs, utt_embeddings):
139
+ # project embedding into smaller space
140
+ speaker_embeddings_projected = self.embedding_projection(utt_embeddings)
141
+ # concat hidden states with spk embeds and then apply projection
142
+ speaker_embeddings_expanded = F.normalize(speaker_embeddings_projected).unsqueeze(1).expand(-1, hs.size(1), -1)
143
+ hs = self.hs_emb_projection(torch.cat([hs, speaker_embeddings_expanded], dim=-1))
144
+ return hs
Layers/Convolution.py ADDED
@@ -0,0 +1,52 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+
4
+ from torch import nn
5
+
6
+
7
+ class ConvolutionModule(nn.Module):
8
+ """
9
+ ConvolutionModule in Conformer model.
10
+
11
+ Args:
12
+ channels (int): The number of channels of conv layers.
13
+ kernel_size (int): Kernel size of conv layers.
14
+
15
+ """
16
+
17
+ def __init__(self, channels, kernel_size, activation=nn.ReLU(), bias=True):
18
+ super(ConvolutionModule, self).__init__()
19
+ # kernel_size should be an odd number for 'SAME' padding
20
+ assert (kernel_size - 1) % 2 == 0
21
+
22
+ self.pointwise_conv1 = nn.Conv1d(channels, 2 * channels, kernel_size=1, stride=1, padding=0, bias=bias, )
23
+ self.depthwise_conv = nn.Conv1d(channels, channels, kernel_size, stride=1, padding=(kernel_size - 1) // 2, groups=channels, bias=bias, )
24
+ self.norm = nn.GroupNorm(num_groups=32, num_channels=channels)
25
+ self.pointwise_conv2 = nn.Conv1d(channels, channels, kernel_size=1, stride=1, padding=0, bias=bias, )
26
+ self.activation = activation
27
+
28
+ def forward(self, x):
29
+ """
30
+ Compute convolution module.
31
+
32
+ Args:
33
+ x (torch.Tensor): Input tensor (#batch, time, channels).
34
+
35
+ Returns:
36
+ torch.Tensor: Output tensor (#batch, time, channels).
37
+
38
+ """
39
+ # exchange the temporal dimension and the feature dimension
40
+ x = x.transpose(1, 2)
41
+
42
+ # GLU mechanism
43
+ x = self.pointwise_conv1(x) # (batch, 2*channel, dim)
44
+ x = nn.functional.glu(x, dim=1) # (batch, channel, dim)
45
+
46
+ # 1D Depthwise Conv
47
+ x = self.depthwise_conv(x)
48
+ x = self.activation(self.norm(x))
49
+
50
+ x = self.pointwise_conv2(x)
51
+
52
+ return x.transpose(1, 2)
Layers/DurationPredictor.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ import torch
4
+
5
+ from Layers.LayerNorm import LayerNorm
6
+
7
+
8
+ class DurationPredictor(torch.nn.Module):
9
+
10
+ def __init__(self, idim, n_layers=2, n_chans=384, kernel_size=3, dropout_rate=0.1, offset=1.0):
11
+ """
12
+ Initialize duration predictor module.
13
+
14
+ Args:
15
+ idim (int): Input dimension.
16
+ n_layers (int, optional): Number of convolutional layers.
17
+ n_chans (int, optional): Number of channels of convolutional layers.
18
+ kernel_size (int, optional): Kernel size of convolutional layers.
19
+ dropout_rate (float, optional): Dropout rate.
20
+ offset (float, optional): Offset value to avoid nan in log domain.
21
+
22
+ """
23
+ super(DurationPredictor, self).__init__()
24
+ self.offset = offset
25
+ self.conv = torch.nn.ModuleList()
26
+ for idx in range(n_layers):
27
+ in_chans = idim if idx == 0 else n_chans
28
+ self.conv += [torch.nn.Sequential(torch.nn.Conv1d(in_chans, n_chans, kernel_size, stride=1, padding=(kernel_size - 1) // 2, ), torch.nn.ReLU(),
29
+ LayerNorm(n_chans, dim=1), torch.nn.Dropout(dropout_rate), )]
30
+ self.linear = torch.nn.Linear(n_chans, 1)
31
+
32
+ def _forward(self, xs, x_masks=None, is_inference=False):
33
+ xs = xs.transpose(1, -1) # (B, idim, Tmax)
34
+ for f in self.conv:
35
+ xs = f(xs) # (B, C, Tmax)
36
+
37
+ # NOTE: calculate in log domain
38
+ xs = self.linear(xs.transpose(1, -1)).squeeze(-1) # (B, Tmax)
39
+
40
+ if is_inference:
41
+ # NOTE: calculate in linear domain
42
+ xs = torch.clamp(torch.round(xs.exp() - self.offset), min=0).long() # avoid negative value
43
+
44
+ if x_masks is not None:
45
+ xs = xs.masked_fill(x_masks, 0.0)
46
+
47
+ return xs
48
+
49
+ def forward(self, xs, x_masks=None):
50
+ """
51
+ Calculate forward propagation.
52
+
53
+ Args:
54
+ xs (Tensor): Batch of input sequences (B, Tmax, idim).
55
+ x_masks (ByteTensor, optional):
56
+ Batch of masks indicating padded part (B, Tmax).
57
+
58
+ Returns:
59
+ Tensor: Batch of predicted durations in log domain (B, Tmax).
60
+
61
+ """
62
+ return self._forward(xs, x_masks, False)
63
+
64
+ def inference(self, xs, x_masks=None):
65
+ """
66
+ Inference duration.
67
+
68
+ Args:
69
+ xs (Tensor): Batch of input sequences (B, Tmax, idim).
70
+ x_masks (ByteTensor, optional):
71
+ Batch of masks indicating padded part (B, Tmax).
72
+
73
+ Returns:
74
+ LongTensor: Batch of predicted durations in linear domain (B, Tmax).
75
+
76
+ """
77
+ return self._forward(xs, x_masks, True)
78
+
79
+
80
+ class DurationPredictorLoss(torch.nn.Module):
81
+ """
82
+ Loss function module for duration predictor.
83
+
84
+ The loss value is Calculated in log domain to make it Gaussian.
85
+
86
+ """
87
+
88
+ def __init__(self, offset=1.0, reduction="mean"):
89
+ """
90
+ Args:
91
+ offset (float, optional): Offset value to avoid nan in log domain.
92
+ reduction (str): Reduction type in loss calculation.
93
+
94
+ """
95
+ super(DurationPredictorLoss, self).__init__()
96
+ self.criterion = torch.nn.MSELoss(reduction=reduction)
97
+ self.offset = offset
98
+
99
+ def forward(self, outputs, targets):
100
+ """
101
+ Calculate forward propagation.
102
+
103
+ Args:
104
+ (Tensor): Batch of prediction durations in log domain (B, T)
105
+ targets (LongTensor): Batch of groundtruth durations in linear domain (B, T)
106
+
107
+ Returns:
108
+ Tensor: Mean squared error loss value.
109
+
110
+ Note:
111
+ `` is in log domain but `targets` is in linear domain.
112
+
113
+ """
114
+ # NOTE: is in log domain while targets in linear
115
+ targets = torch.log(targets.float() + self.offset)
116
+ loss = self.criterion(outputs, targets)
117
+
118
+ return loss
Layers/EncoderLayer.py ADDED
@@ -0,0 +1,140 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ import torch
4
+ from torch import nn
5
+
6
+ from Layers.LayerNorm import LayerNorm
7
+
8
+
9
+ class EncoderLayer(nn.Module):
10
+ """
11
+ Encoder layer module.
12
+
13
+ Args:
14
+ size (int): Input dimension.
15
+ self_attn (torch.nn.Module): Self-attention module instance.
16
+ `MultiHeadedAttention` or `RelPositionMultiHeadedAttention` instance
17
+ can be used as the argument.
18
+ feed_forward (torch.nn.Module): Feed-forward module instance.
19
+ `PositionwiseFeedForward`, `MultiLayeredConv1d`, or `Conv1dLinear` instance
20
+ can be used as the argument.
21
+ feed_forward_macaron (torch.nn.Module): Additional feed-forward module instance.
22
+ `PositionwiseFeedForward`, `MultiLayeredConv1d`, or `Conv1dLinear` instance
23
+ can be used as the argument.
24
+ conv_module (torch.nn.Module): Convolution module instance.
25
+ `ConvlutionModule` instance can be used as the argument.
26
+ dropout_rate (float): Dropout rate.
27
+ normalize_before (bool): Whether to use layer_norm before the first block.
28
+ concat_after (bool): Whether to concat attention layer's input and output.
29
+ if True, additional linear will be applied.
30
+ i.e. x -> x + linear(concat(x, att(x)))
31
+ if False, no additional linear will be applied. i.e. x -> x + att(x)
32
+
33
+ """
34
+
35
+ def __init__(self, size, self_attn, feed_forward, feed_forward_macaron, conv_module, dropout_rate, normalize_before=True, concat_after=False, ):
36
+ super(EncoderLayer, self).__init__()
37
+ self.self_attn = self_attn
38
+ self.feed_forward = feed_forward
39
+ self.feed_forward_macaron = feed_forward_macaron
40
+ self.conv_module = conv_module
41
+ self.norm_ff = LayerNorm(size) # for the FNN module
42
+ self.norm_mha = LayerNorm(size) # for the MHA module
43
+ if feed_forward_macaron is not None:
44
+ self.norm_ff_macaron = LayerNorm(size)
45
+ self.ff_scale = 0.5
46
+ else:
47
+ self.ff_scale = 1.0
48
+ if self.conv_module is not None:
49
+ self.norm_conv = LayerNorm(size) # for the CNN module
50
+ self.norm_final = LayerNorm(size) # for the final output of the block
51
+ self.dropout = nn.Dropout(dropout_rate)
52
+ self.size = size
53
+ self.normalize_before = normalize_before
54
+ self.concat_after = concat_after
55
+ if self.concat_after:
56
+ self.concat_linear = nn.Linear(size + size, size)
57
+
58
+ def forward(self, x_input, mask, cache=None):
59
+ """
60
+ Compute encoded features.
61
+
62
+ Args:
63
+ x_input (Union[Tuple, torch.Tensor]): Input tensor w/ or w/o pos emb.
64
+ - w/ pos emb: Tuple of tensors [(#batch, time, size), (1, time, size)].
65
+ - w/o pos emb: Tensor (#batch, time, size).
66
+ mask (torch.Tensor): Mask tensor for the input (#batch, time).
67
+ cache (torch.Tensor): Cache tensor of the input (#batch, time - 1, size).
68
+
69
+ Returns:
70
+ torch.Tensor: Output tensor (#batch, time, size).
71
+ torch.Tensor: Mask tensor (#batch, time).
72
+
73
+ """
74
+ if isinstance(x_input, tuple):
75
+ x, pos_emb = x_input[0], x_input[1]
76
+ else:
77
+ x, pos_emb = x_input, None
78
+
79
+ # whether to use macaron style
80
+ if self.feed_forward_macaron is not None:
81
+ residual = x
82
+ if self.normalize_before:
83
+ x = self.norm_ff_macaron(x)
84
+ x = residual + self.ff_scale * self.dropout(self.feed_forward_macaron(x))
85
+ if not self.normalize_before:
86
+ x = self.norm_ff_macaron(x)
87
+
88
+ # multi-headed self-attention module
89
+ residual = x
90
+ if self.normalize_before:
91
+ x = self.norm_mha(x)
92
+
93
+ if cache is None:
94
+ x_q = x
95
+ else:
96
+ assert cache.shape == (x.shape[0], x.shape[1] - 1, self.size)
97
+ x_q = x[:, -1:, :]
98
+ residual = residual[:, -1:, :]
99
+ mask = None if mask is None else mask[:, -1:, :]
100
+
101
+ if pos_emb is not None:
102
+ x_att = self.self_attn(x_q, x, x, pos_emb, mask)
103
+ else:
104
+ x_att = self.self_attn(x_q, x, x, mask)
105
+
106
+ if self.concat_after:
107
+ x_concat = torch.cat((x, x_att), dim=-1)
108
+ x = residual + self.concat_linear(x_concat)
109
+ else:
110
+ x = residual + self.dropout(x_att)
111
+ if not self.normalize_before:
112
+ x = self.norm_mha(x)
113
+
114
+ # convolution module
115
+ if self.conv_module is not None:
116
+ residual = x
117
+ if self.normalize_before:
118
+ x = self.norm_conv(x)
119
+ x = residual + self.dropout(self.conv_module(x))
120
+ if not self.normalize_before:
121
+ x = self.norm_conv(x)
122
+
123
+ # feed forward module
124
+ residual = x
125
+ if self.normalize_before:
126
+ x = self.norm_ff(x)
127
+ x = residual + self.ff_scale * self.dropout(self.feed_forward(x))
128
+ if not self.normalize_before:
129
+ x = self.norm_ff(x)
130
+
131
+ if self.conv_module is not None:
132
+ x = self.norm_final(x)
133
+
134
+ if cache is not None:
135
+ x = torch.cat([cache, x], dim=1)
136
+
137
+ if pos_emb is not None:
138
+ return (x, pos_emb), mask
139
+
140
+ return x, mask
Layers/LayerNorm.py ADDED
@@ -0,0 +1,33 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch
3
+
4
+
5
+ class LayerNorm(torch.nn.LayerNorm):
6
+ """
7
+ Layer normalization module.
8
+
9
+ Args:
10
+ nout (int): Output dim size.
11
+ dim (int): Dimension to be normalized.
12
+ """
13
+
14
+ def __init__(self, nout, dim=-1):
15
+ """
16
+ Construct an LayerNorm object.
17
+ """
18
+ super(LayerNorm, self).__init__(nout, eps=1e-12)
19
+ self.dim = dim
20
+
21
+ def forward(self, x):
22
+ """
23
+ Apply layer normalization.
24
+
25
+ Args:
26
+ x (torch.Tensor): Input tensor.
27
+
28
+ Returns:
29
+ torch.Tensor: Normalized tensor.
30
+ """
31
+ if self.dim == -1:
32
+ return super(LayerNorm, self).forward(x)
33
+ return super(LayerNorm, self).forward(x.transpose(1, -1)).transpose(1, -1)
Layers/LengthRegulator.py ADDED
@@ -0,0 +1,47 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from abc import ABC
3
+
4
+ import torch
5
+
6
+ from Utility.utils import pad_list
7
+
8
+
9
+ class LengthRegulator(torch.nn.Module, ABC):
10
+
11
+
12
+ def __init__(self, pad_value=0.0):
13
+ """
14
+ Initialize length regulator module.
15
+
16
+ Args:
17
+ pad_value (float, optional): Value used for padding.
18
+ """
19
+ super(LengthRegulator, self).__init__()
20
+ self.pad_value = pad_value
21
+
22
+ def forward(self, xs, ds, alpha=1.0):
23
+ """
24
+ Calculate forward propagation.
25
+
26
+ Args:
27
+ xs (Tensor): Batch of sequences of char or phoneme embeddings (B, Tmax, D).
28
+ ds (LongTensor): Batch of durations of each frame (B, T).
29
+ alpha (float, optional): Alpha value to control speed of speech.
30
+
31
+ Returns:
32
+ Tensor: replicated input tensor based on durations (B, T*, D).
33
+ """
34
+ if alpha != 1.0:
35
+ assert alpha > 0
36
+ ds = torch.round(ds.float() * alpha).long()
37
+
38
+ if ds.sum() == 0:
39
+ ds[ds.sum(dim=1).eq(0)] = 1
40
+
41
+ return pad_list([self._repeat_one_sequence(x, d) for x, d in zip(xs, ds)], self.pad_value)
42
+
43
+ def _repeat_one_sequence(self, x, d):
44
+ """
45
+ Repeat each frame according to duration
46
+ """
47
+ return torch.repeat_interleave(x, d, dim=0)
Layers/MultiLayeredConv1d.py ADDED
@@ -0,0 +1,75 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ """
4
+ Layer modules for FFT block in FastSpeech (Feed-forward Transformer).
5
+ """
6
+
7
+ import torch
8
+
9
+
10
+ class MultiLayeredConv1d(torch.nn.Module):
11
+
12
+
13
+ def __init__(self, in_chans, hidden_chans, kernel_size, dropout_rate):
14
+ """
15
+ Initialize MultiLayeredConv1d module.
16
+
17
+ Args:
18
+ in_chans (int): Number of input channels.
19
+ hidden_chans (int): Number of hidden channels.
20
+ kernel_size (int): Kernel size of conv1d.
21
+ dropout_rate (float): Dropout rate.
22
+ """
23
+ super(MultiLayeredConv1d, self).__init__()
24
+ self.w_1 = torch.nn.Conv1d(in_chans, hidden_chans, kernel_size, stride=1, padding=(kernel_size - 1) // 2, )
25
+ self.w_2 = torch.nn.Conv1d(hidden_chans, in_chans, kernel_size, stride=1, padding=(kernel_size - 1) // 2, )
26
+ self.dropout = torch.nn.Dropout(dropout_rate)
27
+
28
+ def forward(self, x):
29
+ """
30
+ Calculate forward propagation.
31
+
32
+ Args:
33
+ x (torch.Tensor): Batch of input tensors (B, T, in_chans).
34
+
35
+ Returns:
36
+ torch.Tensor: Batch of output tensors (B, T, hidden_chans).
37
+ """
38
+ x = torch.relu(self.w_1(x.transpose(-1, 1))).transpose(-1, 1)
39
+ return self.w_2(self.dropout(x).transpose(-1, 1)).transpose(-1, 1)
40
+
41
+
42
+ class Conv1dLinear(torch.nn.Module):
43
+ """
44
+ Conv1D + Linear for Transformer block.
45
+
46
+ A variant of MultiLayeredConv1d, which replaces second conv-layer to linear.
47
+ """
48
+
49
+ def __init__(self, in_chans, hidden_chans, kernel_size, dropout_rate):
50
+ """
51
+ Initialize Conv1dLinear module.
52
+
53
+ Args:
54
+ in_chans (int): Number of input channels.
55
+ hidden_chans (int): Number of hidden channels.
56
+ kernel_size (int): Kernel size of conv1d.
57
+ dropout_rate (float): Dropout rate.
58
+ """
59
+ super(Conv1dLinear, self).__init__()
60
+ self.w_1 = torch.nn.Conv1d(in_chans, hidden_chans, kernel_size, stride=1, padding=(kernel_size - 1) // 2, )
61
+ self.w_2 = torch.nn.Linear(hidden_chans, in_chans)
62
+ self.dropout = torch.nn.Dropout(dropout_rate)
63
+
64
+ def forward(self, x):
65
+ """
66
+ Calculate forward propagation.
67
+
68
+ Args:
69
+ x (torch.Tensor): Batch of input tensors (B, T, in_chans).
70
+
71
+ Returns:
72
+ torch.Tensor: Batch of output tensors (B, T, hidden_chans).
73
+ """
74
+ x = torch.relu(self.w_1(x.transpose(-1, 1))).transpose(-1, 1)
75
+ return self.w_2(self.dropout(x))
Layers/MultiSequential.py ADDED
@@ -0,0 +1,30 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch
3
+
4
+
5
+ class MultiSequential(torch.nn.Sequential):
6
+ """
7
+ Multi-input multi-output torch.nn.Sequential.
8
+ """
9
+
10
+ def forward(self, *args):
11
+ """
12
+ Repeat.
13
+ """
14
+ for m in self:
15
+ args = m(*args)
16
+ return args
17
+
18
+
19
+ def repeat(N, fn):
20
+ """
21
+ Repeat module N times.
22
+
23
+ Args:
24
+ N (int): Number of repeat time.
25
+ fn (Callable): Function to generate module.
26
+
27
+ Returns:
28
+ MultiSequential: Repeated model instance.
29
+ """
30
+ return MultiSequential(*[fn(n) for n in range(N)])
Layers/PositionalEncoding.py ADDED
@@ -0,0 +1,145 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Taken from ESPNet
3
+ """
4
+
5
+ import math
6
+
7
+ import torch
8
+
9
+
10
+ class PositionalEncoding(torch.nn.Module):
11
+ """
12
+ Positional encoding.
13
+
14
+ Args:
15
+ d_model (int): Embedding dimension.
16
+ dropout_rate (float): Dropout rate.
17
+ max_len (int): Maximum input length.
18
+ reverse (bool): Whether to reverse the input position.
19
+ """
20
+
21
+ def __init__(self, d_model, dropout_rate, max_len=5000, reverse=False):
22
+ """
23
+ Construct an PositionalEncoding object.
24
+ """
25
+ super(PositionalEncoding, self).__init__()
26
+ self.d_model = d_model
27
+ self.reverse = reverse
28
+ self.xscale = math.sqrt(self.d_model)
29
+ self.dropout = torch.nn.Dropout(p=dropout_rate)
30
+ self.pe = None
31
+ self.extend_pe(torch.tensor(0.0, device=d_model.device).expand(1, max_len))
32
+
33
+ def extend_pe(self, x):
34
+ """
35
+ Reset the positional encodings.
36
+ """
37
+ if self.pe is not None:
38
+ if self.pe.size(1) >= x.size(1):
39
+ if self.pe.dtype != x.dtype or self.pe.device != x.device:
40
+ self.pe = self.pe.to(dtype=x.dtype, device=x.device)
41
+ return
42
+ pe = torch.zeros(x.size(1), self.d_model)
43
+ if self.reverse:
44
+ position = torch.arange(x.size(1) - 1, -1, -1.0, dtype=torch.float32).unsqueeze(1)
45
+ else:
46
+ position = torch.arange(0, x.size(1), dtype=torch.float32).unsqueeze(1)
47
+ div_term = torch.exp(torch.arange(0, self.d_model, 2, dtype=torch.float32) * -(math.log(10000.0) / self.d_model))
48
+ pe[:, 0::2] = torch.sin(position * div_term)
49
+ pe[:, 1::2] = torch.cos(position * div_term)
50
+ pe = pe.unsqueeze(0)
51
+ self.pe = pe.to(device=x.device, dtype=x.dtype)
52
+
53
+ def forward(self, x):
54
+ """
55
+ Add positional encoding.
56
+
57
+ Args:
58
+ x (torch.Tensor): Input tensor (batch, time, `*`).
59
+
60
+ Returns:
61
+ torch.Tensor: Encoded tensor (batch, time, `*`).
62
+ """
63
+ self.extend_pe(x)
64
+ x = x * self.xscale + self.pe[:, : x.size(1)]
65
+ return self.dropout(x)
66
+
67
+
68
+ class RelPositionalEncoding(torch.nn.Module):
69
+
70
+
71
+ def __init__(self, d_model, dropout_rate, max_len=5000):
72
+ """
73
+ Construct an PositionalEncoding object.
74
+ """
75
+ super(RelPositionalEncoding, self).__init__()
76
+ self.d_model = d_model
77
+ self.xscale = math.sqrt(self.d_model)
78
+ self.dropout = torch.nn.Dropout(p=dropout_rate)
79
+ self.pe = None
80
+ self.extend_pe(torch.tensor(0.0).expand(1, max_len))
81
+
82
+ def extend_pe(self, x):
83
+ """Reset the positional encodings."""
84
+ if self.pe is not None:
85
+ # self.pe contains both positive and negative parts
86
+ # the length of self.pe is 2 * input_len - 1
87
+ if self.pe.size(1) >= x.size(1) * 2 - 1:
88
+ if self.pe.dtype != x.dtype or self.pe.device != x.device:
89
+ self.pe = self.pe.to(dtype=x.dtype, device=x.device)
90
+ return
91
+ # Suppose `i` means to the position of query vecotr and `j` means the
92
+ # position of key vector. We use position relative positions when keys
93
+ # are to the left (i>j) and negative relative positions otherwise (i<j).
94
+ pe_positive = torch.zeros(x.size(1), self.d_model, device=x.device)
95
+ pe_negative = torch.zeros(x.size(1), self.d_model, device=x.device)
96
+ position = torch.arange(0, x.size(1), dtype=torch.float32, device=x.device).unsqueeze(1)
97
+ div_term = torch.exp(torch.arange(0, self.d_model, 2, dtype=torch.float32, device=x.device) * -(math.log(10000.0) / self.d_model))
98
+ pe_positive[:, 0::2] = torch.sin(position * div_term)
99
+ pe_positive[:, 1::2] = torch.cos(position * div_term)
100
+ pe_negative[:, 0::2] = torch.sin(-1 * position * div_term)
101
+ pe_negative[:, 1::2] = torch.cos(-1 * position * div_term)
102
+
103
+ pe_positive = torch.flip(pe_positive, [0]).unsqueeze(0)
104
+ pe_negative = pe_negative[1:].unsqueeze(0)
105
+ pe = torch.cat([pe_positive, pe_negative], dim=1)
106
+ self.pe = pe.to(dtype=x.dtype)
107
+
108
+ def forward(self, x):
109
+ """
110
+ Add positional encoding.
111
+ Args:
112
+ x (torch.Tensor): Input tensor (batch, time, `*`).
113
+ Returns:
114
+ torch.Tensor: Encoded tensor (batch, time, `*`).
115
+ """
116
+ self.extend_pe(x)
117
+ x = x * self.xscale
118
+ pos_emb = self.pe[:, self.pe.size(1) // 2 - x.size(1) + 1: self.pe.size(1) // 2 + x.size(1), ]
119
+ return self.dropout(x), self.dropout(pos_emb)
120
+
121
+
122
+ class ScaledPositionalEncoding(PositionalEncoding):
123
+
124
+
125
+ def __init__(self, d_model, dropout_rate, max_len=5000):
126
+ super().__init__(d_model=d_model, dropout_rate=dropout_rate, max_len=max_len)
127
+ self.alpha = torch.nn.Parameter(torch.tensor(1.0))
128
+
129
+ def reset_parameters(self):
130
+ self.alpha.data = torch.tensor(1.0)
131
+
132
+ def forward(self, x):
133
+ """
134
+ Add positional encoding.
135
+
136
+ Args:
137
+ x (torch.Tensor): Input tensor (batch, time, `*`).
138
+
139
+ Returns:
140
+ torch.Tensor: Encoded tensor (batch, time, `*`).
141
+
142
+ """
143
+ self.extend_pe(x)
144
+ x = x + self.alpha * self.pe[:, : x.size(1)]
145
+ return self.dropout(x)
Layers/PositionwiseFeedForward.py ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ import torch
3
+
4
+
5
+ class PositionwiseFeedForward(torch.nn.Module):
6
+ """
7
+ Args:
8
+ idim (int): Input dimenstion.
9
+ hidden_units (int): The number of hidden units.
10
+ dropout_rate (float): Dropout rate.
11
+
12
+ """
13
+
14
+ def __init__(self, idim, hidden_units, dropout_rate, activation=torch.nn.ReLU()):
15
+ super(PositionwiseFeedForward, self).__init__()
16
+ self.w_1 = torch.nn.Linear(idim, hidden_units)
17
+ self.w_2 = torch.nn.Linear(hidden_units, idim)
18
+ self.dropout = torch.nn.Dropout(dropout_rate)
19
+ self.activation = activation
20
+
21
+ def forward(self, x):
22
+ return self.w_2(self.dropout(self.activation(self.w_1(x))))
Layers/PostNet.py ADDED
@@ -0,0 +1,60 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Taken from ESPNet
3
+ """
4
+
5
+ import torch
6
+
7
+
8
+ class PostNet(torch.nn.Module):
9
+
10
+
11
+ def __init__(self, idim, odim, n_layers=5, n_chans=512, n_filts=5, dropout_rate=0.5, use_batch_norm=True):
12
+ """
13
+ Initialize postnet module.
14
+
15
+ Args:
16
+ idim (int): Dimension of the inputs.
17
+ odim (int): Dimension of the .
18
+ n_layers (int, optional): The number of layers.
19
+ n_filts (int, optional): The number of filter size.
20
+ n_units (int, optional): The number of filter channels.
21
+ use_batch_norm (bool, optional): Whether to use batch normalization..
22
+ dropout_rate (float, optional): Dropout rate..
23
+ """
24
+ super(PostNet, self).__init__()
25
+ self.postnet = torch.nn.ModuleList()
26
+ for layer in range(n_layers - 1):
27
+ ichans = odim if layer == 0 else n_chans
28
+ ochans = odim if layer == n_layers - 1 else n_chans
29
+ if use_batch_norm:
30
+ self.postnet += [torch.nn.Sequential(torch.nn.Conv1d(ichans, ochans, n_filts, stride=1, padding=(n_filts - 1) // 2, bias=False, ),
31
+ torch.nn.GroupNorm(num_groups=32, num_channels=ochans), torch.nn.Tanh(),
32
+ torch.nn.Dropout(dropout_rate), )]
33
+
34
+ else:
35
+ self.postnet += [
36
+ torch.nn.Sequential(torch.nn.Conv1d(ichans, ochans, n_filts, stride=1, padding=(n_filts - 1) // 2, bias=False, ), torch.nn.Tanh(),
37
+ torch.nn.Dropout(dropout_rate), )]
38
+ ichans = n_chans if n_layers != 1 else odim
39
+ if use_batch_norm:
40
+ self.postnet += [torch.nn.Sequential(torch.nn.Conv1d(ichans, odim, n_filts, stride=1, padding=(n_filts - 1) // 2, bias=False, ),
41
+ torch.nn.GroupNorm(num_groups=20, num_channels=odim),
42
+ torch.nn.Dropout(dropout_rate), )]
43
+
44
+ else:
45
+ self.postnet += [torch.nn.Sequential(torch.nn.Conv1d(ichans, odim, n_filts, stride=1, padding=(n_filts - 1) // 2, bias=False, ),
46
+ torch.nn.Dropout(dropout_rate), )]
47
+
48
+ def forward(self, xs):
49
+ """
50
+ Calculate forward propagation.
51
+
52
+ Args:
53
+ xs (Tensor): Batch of the sequences of padded input tensors (B, idim, Tmax).
54
+
55
+ Returns:
56
+ Tensor: Batch of padded output tensor. (B, odim, Tmax).
57
+ """
58
+ for i in range(len(self.postnet)):
59
+ xs = self.postnet[i](xs)
60
+ return xs
Layers/ResidualBlock.py ADDED
@@ -0,0 +1,93 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+
3
+
4
+ import torch
5
+
6
+
7
+ class Conv1d(torch.nn.Conv1d):
8
+ """
9
+ Conv1d module with customized initialization.
10
+ """
11
+
12
+ def __init__(self, *args, **kwargs):
13
+ super(Conv1d, self).__init__(*args, **kwargs)
14
+
15
+ def reset_parameters(self):
16
+ torch.nn.init.kaiming_normal_(self.weight, nonlinearity="relu")
17
+ if self.bias is not None:
18
+ torch.nn.init.constant_(self.bias, 0.0)
19
+
20
+
21
+ class Conv1d1x1(Conv1d):
22
+ """
23
+ 1x1 Conv1d with customized initialization.
24
+ """
25
+
26
+ def __init__(self, in_channels, out_channels, bias):
27
+ super(Conv1d1x1, self).__init__(in_channels, out_channels, kernel_size=1, padding=0, dilation=1, bias=bias)
28
+
29
+
30
+ class HiFiGANResidualBlock(torch.nn.Module):
31
+ """Residual block module in HiFiGAN."""
32
+
33
+ def __init__(self,
34
+ kernel_size=3,
35
+ channels=512,
36
+ dilations=(1, 3, 5),
37
+ bias=True,
38
+ use_additional_convs=True,
39
+ nonlinear_activation="LeakyReLU",
40
+ nonlinear_activation_params={"negative_slope": 0.1}, ):
41
+ """
42
+ Initialize HiFiGANResidualBlock module.
43
+
44
+ Args:
45
+ kernel_size (int): Kernel size of dilation convolution layer.
46
+ channels (int): Number of channels for convolution layer.
47
+ dilations (List[int]): List of dilation factors.
48
+ use_additional_convs (bool): Whether to use additional convolution layers.
49
+ bias (bool): Whether to add bias parameter in convolution layers.
50
+ nonlinear_activation (str): Activation function module name.
51
+ nonlinear_activation_params (dict): Hyperparameters for activation function.
52
+ """
53
+ super().__init__()
54
+ self.use_additional_convs = use_additional_convs
55
+ self.convs1 = torch.nn.ModuleList()
56
+ if use_additional_convs:
57
+ self.convs2 = torch.nn.ModuleList()
58
+ assert kernel_size % 2 == 1, "Kernel size must be odd number."
59
+ for dilation in dilations:
60
+ self.convs1 += [torch.nn.Sequential(getattr(torch.nn, nonlinear_activation)(**nonlinear_activation_params),
61
+ torch.nn.Conv1d(channels,
62
+ channels,
63
+ kernel_size,
64
+ 1,
65
+ dilation=dilation,
66
+ bias=bias,
67
+ padding=(kernel_size - 1) // 2 * dilation, ), )]
68
+ if use_additional_convs:
69
+ self.convs2 += [torch.nn.Sequential(getattr(torch.nn, nonlinear_activation)(**nonlinear_activation_params),
70
+ torch.nn.Conv1d(channels,
71
+ channels,
72
+ kernel_size,
73
+ 1,
74
+ dilation=1,
75
+ bias=bias,
76
+ padding=(kernel_size - 1) // 2, ), )]
77
+
78
+ def forward(self, x):
79
+ """
80
+ Calculate forward propagation.
81
+
82
+ Args:
83
+ x (Tensor): Input tensor (B, channels, T).
84
+
85
+ Returns:
86
+ Tensor: Output tensor (B, channels, T).
87
+ """
88
+ for idx in range(len(self.convs1)):
89
+ xt = self.convs1[idx](x)
90
+ if self.use_additional_convs:
91
+ xt = self.convs2[idx](xt)
92
+ x = xt + x
93
+ return x
Layers/ResidualStack.py ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+
4
+ import torch
5
+
6
+
7
+ class ResidualStack(torch.nn.Module):
8
+
9
+ def __init__(self, kernel_size=3, channels=32, dilation=1, bias=True, nonlinear_activation="LeakyReLU", nonlinear_activation_params={"negative_slope": 0.2},
10
+ pad="ReflectionPad1d", pad_params={}, ):
11
+ """
12
+ Initialize ResidualStack module.
13
+
14
+ Args:
15
+ kernel_size (int): Kernel size of dilation convolution layer.
16
+ channels (int): Number of channels of convolution layers.
17
+ dilation (int): Dilation factor.
18
+ bias (bool): Whether to add bias parameter in convolution layers.
19
+ nonlinear_activation (str): Activation function module name.
20
+ nonlinear_activation_params (dict): Hyperparameters for activation function.
21
+ pad (str): Padding function module name before dilated convolution layer.
22
+ pad_params (dict): Hyperparameters for padding function.
23
+
24
+ """
25
+ super(ResidualStack, self).__init__()
26
+
27
+ # defile residual stack part
28
+ assert (kernel_size - 1) % 2 == 0, "Not support even number kernel size."
29
+ self.stack = torch.nn.Sequential(getattr(torch.nn, nonlinear_activation)(**nonlinear_activation_params),
30
+ getattr(torch.nn, pad)((kernel_size - 1) // 2 * dilation, **pad_params),
31
+ torch.nn.Conv1d(channels, channels, kernel_size, dilation=dilation, bias=bias),
32
+ getattr(torch.nn, nonlinear_activation)(**nonlinear_activation_params),
33
+ torch.nn.Conv1d(channels, channels, 1, bias=bias), )
34
+
35
+ # defile extra layer for skip connection
36
+ self.skip_layer = torch.nn.Conv1d(channels, channels, 1, bias=bias)
37
+
38
+ def forward(self, c):
39
+ """
40
+ Calculate forward propagation.
41
+
42
+ Args:
43
+ c (Tensor): Input tensor (B, channels, T).
44
+
45
+ Returns:
46
+ Tensor: Output tensor (B, chennels, T).
47
+
48
+ """
49
+ return self.stack(c) + self.skip_layer(c)
Layers/STFT.py ADDED
@@ -0,0 +1,118 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Taken from ESPNet
3
+ """
4
+
5
+ import torch
6
+ from torch.functional import stft as torch_stft
7
+ from torch_complex.tensor import ComplexTensor
8
+
9
+ from Utility.utils import make_pad_mask
10
+
11
+
12
+ class STFT(torch.nn.Module):
13
+
14
+ def __init__(self, n_fft=512, win_length=None, hop_length=128, window="hann", center=True, normalized=False,
15
+ onesided=True):
16
+ super().__init__()
17
+ self.n_fft = n_fft
18
+ if win_length is None:
19
+ self.win_length = n_fft
20
+ else:
21
+ self.win_length = win_length
22
+ self.hop_length = hop_length
23
+ self.center = center
24
+ self.normalized = normalized
25
+ self.onesided = onesided
26
+ self.window = window
27
+
28
+ def extra_repr(self):
29
+ return (f"n_fft={self.n_fft}, "
30
+ f"win_length={self.win_length}, "
31
+ f"hop_length={self.hop_length}, "
32
+ f"center={self.center}, "
33
+ f"normalized={self.normalized}, "
34
+ f"onesided={self.onesided}")
35
+
36
+ def forward(self, input_wave, ilens=None):
37
+ """
38
+ STFT forward function.
39
+ Args:
40
+ input_wave: (Batch, Nsamples) or (Batch, Nsample, Channels)
41
+ ilens: (Batch)
42
+ Returns:
43
+ output: (Batch, Frames, Freq, 2) or (Batch, Frames, Channels, Freq, 2)
44
+ """
45
+ bs = input_wave.size(0)
46
+
47
+ if input_wave.dim() == 3:
48
+ multi_channel = True
49
+ # input: (Batch, Nsample, Channels) -> (Batch * Channels, Nsample)
50
+ input_wave = input_wave.transpose(1, 2).reshape(-1, input_wave.size(1))
51
+ else:
52
+ multi_channel = False
53
+
54
+ # output: (Batch, Freq, Frames, 2=real_imag)
55
+ # or (Batch, Channel, Freq, Frames, 2=real_imag)
56
+ if self.window is not None:
57
+ window_func = getattr(torch, f"{self.window}_window")
58
+ window = window_func(self.win_length, dtype=input_wave.dtype, device=input_wave.device)
59
+ else:
60
+ window = None
61
+
62
+ complex_output = torch_stft(input=input_wave,
63
+ n_fft=self.n_fft,
64
+ win_length=self.win_length,
65
+ hop_length=self.hop_length,
66
+ center=self.center,
67
+ window=window,
68
+ normalized=self.normalized,
69
+ onesided=self.onesided,
70
+ return_complex=True)
71
+ output = torch.view_as_real(complex_output)
72
+ # output: (Batch, Freq, Frames, 2=real_imag)
73
+ # -> (Batch, Frames, Freq, 2=real_imag)
74
+ output = output.transpose(1, 2)
75
+ if multi_channel:
76
+ # output: (Batch * Channel, Frames, Freq, 2=real_imag)
77
+ # -> (Batch, Frame, Channel, Freq, 2=real_imag)
78
+ output = output.view(bs, -1, output.size(1), output.size(2), 2).transpose(1, 2)
79
+
80
+ if ilens is not None:
81
+ if self.center:
82
+ pad = self.win_length // 2
83
+ ilens = ilens + 2 * pad
84
+
85
+ olens = (ilens - self.win_length) // self.hop_length + 1
86
+ output.masked_fill_(make_pad_mask(olens, output, 1), 0.0)
87
+ else:
88
+ olens = None
89
+
90
+ return output, olens
91
+
92
+ def inverse(self, input, ilens=None):
93
+ """
94
+ Inverse STFT.
95
+ Args:
96
+ input: Tensor(batch, T, F, 2) or ComplexTensor(batch, T, F)
97
+ ilens: (batch,)
98
+ Returns:
99
+ wavs: (batch, samples)
100
+ ilens: (batch,)
101
+ """
102
+ istft = torch.functional.istft
103
+
104
+ if self.window is not None:
105
+ window_func = getattr(torch, f"{self.window}_window")
106
+ window = window_func(self.win_length, dtype=input.dtype, device=input.device)
107
+ else:
108
+ window = None
109
+
110
+ if isinstance(input, ComplexTensor):
111
+ input = torch.stack([input.real, input.imag], dim=-1)
112
+ assert input.shape[-1] == 2
113
+ input = input.transpose(1, 2)
114
+
115
+ wavs = istft(input, n_fft=self.n_fft, hop_length=self.hop_length, win_length=self.win_length, window=window, center=self.center,
116
+ normalized=self.normalized, onesided=self.onesided, length=ilens.max() if ilens is not None else ilens)
117
+
118
+ return wavs, ilens
Layers/Swish.py ADDED
@@ -0,0 +1,15 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+
3
+ import torch
4
+
5
+
6
+ class Swish(torch.nn.Module):
7
+ """
8
+ Construct an Swish activation function for Conformer.
9
+ """
10
+
11
+ def forward(self, x):
12
+ """
13
+ Return Swish activation function.
14
+ """
15
+ return x * torch.sigmoid(x)
Layers/VariancePredictor.py ADDED
@@ -0,0 +1,53 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ from abc import ABC
3
+
4
+ import torch
5
+
6
+ from Layers.LayerNorm import LayerNorm
7
+
8
+
9
+ class VariancePredictor(torch.nn.Module, ABC):
10
+
11
+
12
+ def __init__(self, idim, n_layers=2, n_chans=384, kernel_size=3, bias=True, dropout_rate=0.5, ):
13
+ """
14
+ Initilize duration predictor module.
15
+
16
+ Args:
17
+ idim (int): Input dimension.
18
+ n_layers (int, optional): Number of convolutional layers.
19
+ n_chans (int, optional): Number of channels of convolutional layers.
20
+ kernel_size (int, optional): Kernel size of convolutional layers.
21
+ dropout_rate (float, optional): Dropout rate.
22
+ """
23
+ super().__init__()
24
+ self.conv = torch.nn.ModuleList()
25
+ for idx in range(n_layers):
26
+ in_chans = idim if idx == 0 else n_chans
27
+ self.conv += [
28
+ torch.nn.Sequential(torch.nn.Conv1d(in_chans, n_chans, kernel_size, stride=1, padding=(kernel_size - 1) // 2, bias=bias, ), torch.nn.ReLU(),
29
+ LayerNorm(n_chans, dim=1), torch.nn.Dropout(dropout_rate), )]
30
+ self.linear = torch.nn.Linear(n_chans, 1)
31
+
32
+ def forward(self, xs, x_masks=None):
33
+ """
34
+ Calculate forward propagation.
35
+
36
+ Args:
37
+ xs (Tensor): Batch of input sequences (B, Tmax, idim).
38
+ x_masks (ByteTensor, optional):
39
+ Batch of masks indicating padded part (B, Tmax).
40
+
41
+ Returns:
42
+ Tensor: Batch of predicted sequences (B, Tmax, 1).
43
+ """
44
+ xs = xs.transpose(1, -1) # (B, idim, Tmax)
45
+ for f in self.conv:
46
+ xs = f(xs) # (B, C, Tmax)
47
+
48
+ xs = self.linear(xs.transpose(1, 2)) # (B, Tmax, 1)
49
+
50
+ if x_masks is not None:
51
+ xs = xs.masked_fill(x_masks, 0.0)
52
+
53
+ return xs
Layers/__init__.py ADDED
File without changes
Models/FastSpeech2_Meta/__init__.py ADDED
File without changes
Models/HiFiGAN_combined/__init__.py ADDED
File without changes
Models/SpeakerEmbedding/speechbrain_speaker_embedding_ecapa/hyperparams.yaml ADDED
@@ -0,0 +1,59 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ############################################################################
2
+ # Model: ECAPA big for Speaker verification
3
+ # ############################################################################
4
+
5
+ # Feature parameters
6
+ n_mels: 80
7
+
8
+ # Pretrain folder (HuggingFace)
9
+ pretrained_path: speechbrain/spkrec-ecapa-voxceleb
10
+
11
+ # Output parameters
12
+ out_n_neurons: 7205
13
+
14
+ # Model params
15
+ compute_features: !new:speechbrain.lobes.features.Fbank
16
+ n_mels: !ref <n_mels>
17
+
18
+ mean_var_norm: !new:speechbrain.processing.features.InputNormalization
19
+ norm_type: sentence
20
+ std_norm: False
21
+
22
+ embedding_model: !new:speechbrain.lobes.models.ECAPA_TDNN.ECAPA_TDNN
23
+ input_size: !ref <n_mels>
24
+ channels: [1024, 1024, 1024, 1024, 3072]
25
+ kernel_sizes: [5, 3, 3, 3, 1]
26
+ dilations: [1, 2, 3, 4, 1]
27
+ attention_channels: 128
28
+ lin_neurons: 192
29
+
30
+ classifier: !new:speechbrain.lobes.models.ECAPA_TDNN.Classifier
31
+ input_size: 192
32
+ out_neurons: !ref <out_n_neurons>
33
+
34
+ mean_var_norm_emb: !new:speechbrain.processing.features.InputNormalization
35
+ norm_type: global
36
+ std_norm: False
37
+
38
+ modules:
39
+ compute_features: !ref <compute_features>
40
+ mean_var_norm: !ref <mean_var_norm>
41
+ embedding_model: !ref <embedding_model>
42
+ mean_var_norm_emb: !ref <mean_var_norm_emb>
43
+ classifier: !ref <classifier>
44
+
45
+ label_encoder: !new:speechbrain.dataio.encoder.CategoricalEncoder
46
+
47
+
48
+ pretrainer: !new:speechbrain.utils.parameter_transfer.Pretrainer
49
+ loadables:
50
+ embedding_model: !ref <embedding_model>
51
+ mean_var_norm_emb: !ref <mean_var_norm_emb>
52
+ classifier: !ref <classifier>
53
+ label_encoder: !ref <label_encoder>
54
+ paths:
55
+ embedding_model: !ref <pretrained_path>/embedding_model.ckpt
56
+ mean_var_norm_emb: !ref <pretrained_path>/mean_var_norm_emb.ckpt
57
+ classifier: !ref <pretrained_path>/classifier.ckpt
58
+ label_encoder: !ref <pretrained_path>/label_encoder.txt
59
+
Models/SpeakerEmbedding/speechbrain_speaker_embedding_xvector/hyperparams.yaml ADDED
@@ -0,0 +1,64 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # ############################################################################
2
+ # Model: xvector for Speaker verification
3
+ # ############################################################################
4
+
5
+ # Feature parameters
6
+ n_mels: 24
7
+
8
+ # Pretrain folder (HuggingFace)
9
+ pretrained_path: speechbrain/spkrec-xvect-voxceleb
10
+
11
+ # Output parameters
12
+ out_n_neurons: 7205
13
+
14
+
15
+ # Model params
16
+ compute_features: !new:speechbrain.lobes.features.Fbank
17
+ n_mels: !ref <n_mels>
18
+
19
+ mean_var_norm: !new:speechbrain.processing.features.InputNormalization
20
+ norm_type: sentence
21
+ std_norm: False
22
+
23
+ embedding_model: !new:speechbrain.lobes.models.Xvector.Xvector
24
+ in_channels: !ref <n_mels>
25
+ activation: !name:torch.nn.LeakyReLU
26
+ tdnn_blocks: 5
27
+ tdnn_channels: [512, 512, 512, 512, 1500]
28
+ tdnn_kernel_sizes: [5, 3, 3, 1, 1]
29
+ tdnn_dilations: [1, 2, 3, 1, 1]
30
+ lin_neurons: 512
31
+
32
+ classifier: !new:speechbrain.lobes.models.Xvector.Classifier
33
+ input_shape: [null, null, 512]
34
+ activation: !name:torch.nn.LeakyReLU
35
+ lin_blocks: 1
36
+ lin_neurons: 512
37
+ out_neurons: !ref <out_n_neurons>
38
+
39
+ mean_var_norm_emb: !new:speechbrain.processing.features.InputNormalization
40
+ norm_type: global
41
+ std_norm: False
42
+
43
+ modules:
44
+ compute_features: !ref <compute_features>
45
+ mean_var_norm: !ref <mean_var_norm>
46
+ embedding_model: !ref <embedding_model>
47
+ mean_var_norm_emb: !ref <mean_var_norm_emb>
48
+ classifier: !ref <classifier>
49
+
50
+ label_encoder: !new:speechbrain.dataio.encoder.CategoricalEncoder
51
+
52
+
53
+ pretrainer: !new:speechbrain.utils.parameter_transfer.Pretrainer
54
+ loadables:
55
+ embedding_model: !ref <embedding_model>
56
+ mean_var_norm_emb: !ref <mean_var_norm_emb>
57
+ classifier: !ref <classifier>
58
+ label_encoder: !ref <label_encoder>
59
+ paths:
60
+ embedding_model: !ref <pretrained_path>/embedding_model.ckpt
61
+ mean_var_norm_emb: !ref <pretrained_path>/mean_var_norm_emb.ckpt
62
+ classifier: !ref <pretrained_path>/classifier.ckpt
63
+ label_encoder: !ref <pretrained_path>/label_encoder.txt
64
+
Preprocessing/ArticulatoryCombinedTextFrontend.py ADDED
@@ -0,0 +1,319 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import re
2
+ import sys
3
+
4
+ import panphon
5
+ import phonemizer
6
+ import torch
7
+
8
+ from Preprocessing.papercup_features import generate_feature_table
9
+
10
+
11
+ class ArticulatoryCombinedTextFrontend:
12
+
13
+ def __init__(self,
14
+ language,
15
+ use_word_boundaries=False, # goes together well with
16
+ # parallel models and an aligner. Doesn't go together
17
+ # well with autoregressive models.
18
+ use_explicit_eos=True,
19
+ use_prosody=False, # unfortunately the non-segmental
20
+ # nature of prosodic markers mixed with the sequential
21
+ # phonemes hurts the performance of end-to-end models a
22
+ # lot, even though one might think enriching the input
23
+ # with such information would help.
24
+ use_lexical_stress=False,
25
+ silent=True,
26
+ allow_unknown=False,
27
+ add_silence_to_end=True,
28
+ strip_silence=True):
29
+ """
30
+ Mostly preparing ID lookups
31
+ """
32
+ self.strip_silence = strip_silence
33
+ self.use_word_boundaries = use_word_boundaries
34
+ self.allow_unknown = allow_unknown
35
+ self.use_explicit_eos = use_explicit_eos
36
+ self.use_prosody = use_prosody
37
+ self.use_stress = use_lexical_stress
38
+ self.add_silence_to_end = add_silence_to_end
39
+ self.feature_table = panphon.FeatureTable()
40
+
41
+ if language == "en":
42
+ self.g2p_lang = "en-us"
43
+ self.expand_abbreviations = english_text_expansion
44
+ if not silent:
45
+ print("Created an English Text-Frontend")
46
+
47
+ elif language == "de":
48
+ self.g2p_lang = "de"
49
+ self.expand_abbreviations = lambda x: x
50
+ if not silent:
51
+ print("Created a German Text-Frontend")
52
+
53
+ elif language == "el":
54
+ self.g2p_lang = "el"
55
+ self.expand_abbreviations = lambda x: x
56
+ if not silent:
57
+ print("Created a Greek Text-Frontend")
58
+
59
+ elif language == "es":
60
+ self.g2p_lang = "es"
61
+ self.expand_abbreviations = lambda x: x
62
+ if not silent:
63
+ print("Created a Spanish Text-Frontend")
64
+
65
+ elif language == "fi":
66
+ self.g2p_lang = "fi"
67
+ self.expand_abbreviations = lambda x: x
68
+ if not silent:
69
+ print("Created a Finnish Text-Frontend")
70
+
71
+ elif language == "ru":
72
+ self.g2p_lang = "ru"
73
+ self.expand_abbreviations = lambda x: x
74
+ if not silent:
75
+ print("Created a Russian Text-Frontend")
76
+
77
+ elif language == "hu":
78
+ self.g2p_lang = "hu"
79
+ self.expand_abbreviations = lambda x: x
80
+ if not silent:
81
+ print("Created a Hungarian Text-Frontend")
82
+
83
+ elif language == "nl":
84
+ self.g2p_lang = "nl"
85
+ self.expand_abbreviations = lambda x: x
86
+ if not silent:
87
+ print("Created a Dutch Text-Frontend")
88
+
89
+ elif language == "fr":
90
+ self.g2p_lang = "fr-fr"
91
+ self.expand_abbreviations = lambda x: x
92
+ if not silent:
93
+ print("Created a French Text-Frontend")
94
+
95
+ elif language == "it":
96
+ self.g2p_lang = "it"
97
+ self.expand_abbreviations = lambda x: x
98
+ if not silent:
99
+ print("Created a Italian Text-Frontend")
100
+
101
+ elif language == "pt":
102
+ self.g2p_lang = "pt"
103
+ self.expand_abbreviations = lambda x: x
104
+ if not silent:
105
+ print("Created a Portuguese Text-Frontend")
106
+
107
+ elif language == "pl":
108
+ self.g2p_lang = "pl"
109
+ self.expand_abbreviations = lambda x: x
110
+ if not silent:
111
+ print("Created a Polish Text-Frontend")
112
+
113
+ # remember to also update get_language_id() when adding something here
114
+
115
+ else:
116
+ print("Language not supported yet")
117
+ sys.exit()
118
+
119
+ self.phone_to_vector_papercup = generate_feature_table()
120
+
121
+ self.phone_to_vector = dict()
122
+ for phone in self.phone_to_vector_papercup:
123
+ panphon_features = self.feature_table.word_to_vector_list(phone, numeric=True)
124
+ if panphon_features == []:
125
+ panphon_features = [[0] * 24]
126
+ papercup_features = self.phone_to_vector_papercup[phone]
127
+ self.phone_to_vector[phone] = papercup_features + panphon_features[0]
128
+
129
+ self.phone_to_id = { # this lookup must be updated manually, because the only
130
+ # other way would be extracting them from a set, which can be non-deterministic
131
+ '~': 0,
132
+ '#': 1,
133
+ '?': 2,
134
+ '!': 3,
135
+ '.': 4,
136
+ 'ɜ': 5,
137
+ 'ɫ': 6,
138
+ 'ə': 7,
139
+ 'ɚ': 8,
140
+ 'a': 9,
141
+ 'ð': 10,
142
+ 'ɛ': 11,
143
+ 'ɪ': 12,
144
+ 'ᵻ': 13,
145
+ 'ŋ': 14,
146
+ 'ɔ': 15,
147
+ 'ɒ': 16,
148
+ 'ɾ': 17,
149
+ 'ʃ': 18,
150
+ 'θ': 19,
151
+ 'ʊ': 20,
152
+ 'ʌ': 21,
153
+ 'ʒ': 22,
154
+ 'æ': 23,
155
+ 'b': 24,
156
+ 'ʔ': 25,
157
+ 'd': 26,
158
+ 'e': 27,
159
+ 'f': 28,
160
+ 'g': 29,
161
+ 'h': 30,
162
+ 'i': 31,
163
+ 'j': 32,
164
+ 'k': 33,
165
+ 'l': 34,
166
+ 'm': 35,
167
+ 'n': 36,
168
+ 'ɳ': 37,
169
+ 'o': 38,
170
+ 'p': 39,
171
+ 'ɡ': 40,
172
+ 'ɹ': 41,
173
+ 'r': 42,
174
+ 's': 43,
175
+ 't': 44,
176
+ 'u': 45,
177
+ 'v': 46,
178
+ 'w': 47,
179
+ 'x': 48,
180
+ 'z': 49,
181
+ 'ʀ': 50,
182
+ 'ø': 51,
183
+ 'ç': 52,
184
+ 'ɐ': 53,
185
+ 'œ': 54,
186
+ 'y': 55,
187
+ 'ʏ': 56,
188
+ 'ɑ': 57,
189
+ 'c': 58,
190
+ 'ɲ': 59,
191
+ 'ɣ': 60,
192
+ 'ʎ': 61,
193
+ 'β': 62,
194
+ 'ʝ': 63,
195
+ 'ɟ': 64,
196
+ 'q': 65,
197
+ 'ɕ': 66,
198
+ 'ʲ': 67,
199
+ 'ɭ': 68,
200
+ 'ɵ': 69,
201
+ 'ʑ': 70,
202
+ 'ʋ': 71,
203
+ 'ʁ': 72,
204
+ 'ɨ': 73,
205
+ 'ʂ': 74,
206
+ 'ɬ': 75,
207
+ } # for the states of the ctc loss and dijkstra/mas in the aligner
208
+
209
+ self.id_to_phone = {v: k for k, v in self.phone_to_id.items()}
210
+
211
+ def string_to_tensor(self, text, view=False, device="cpu", handle_missing=True, input_phonemes=False):
212
+ """
213
+ Fixes unicode errors, expands some abbreviations,
214
+ turns graphemes into phonemes and then vectorizes
215
+ the sequence as articulatory features
216
+ """
217
+ if input_phonemes:
218
+ phones = text
219
+ else:
220
+ phones = self.get_phone_string(text=text, include_eos_symbol=True)
221
+ if view:
222
+ print("Phonemes: \n{}\n".format(phones))
223
+ phones_vector = list()
224
+ # turn into numeric vectors
225
+ for char in phones:
226
+ if handle_missing:
227
+ try:
228
+ phones_vector.append(self.phone_to_vector[char])
229
+ except KeyError:
230
+ print("unknown phoneme: {}".format(char))
231
+ else:
232
+ phones_vector.append(self.phone_to_vector[char]) # leave error handling to elsewhere
233
+
234
+ return torch.Tensor(phones_vector, device=device)
235
+
236
+ def get_phone_string(self, text, include_eos_symbol=True):
237
+ # expand abbreviations
238
+ utt = self.expand_abbreviations(text)
239
+ # phonemize
240
+ phones = phonemizer.phonemize(utt,
241
+ language_switch='remove-flags',
242
+ backend="espeak",
243
+ language=self.g2p_lang,
244
+ preserve_punctuation=True,
245
+ strip=True,
246
+ punctuation_marks=';:,.!?¡¿—…"«»“”~/',
247
+ with_stress=self.use_stress).replace(";", ",").replace("/", " ").replace("—", "") \
248
+ .replace(":", ",").replace('"', ",").replace("-", ",").replace("...", ",").replace("-", ",").replace("\n", " ") \
249
+ .replace("\t", " ").replace("¡", "").replace("¿", "").replace(",", "~").replace(" ̃", "").replace('̩', "").replace("̃", "").replace("̪", "")
250
+ # less than 1 wide characters hidden here
251
+ phones = re.sub("~+", "~", phones)
252
+ if not self.use_prosody:
253
+ # retain ~ as heuristic pause marker, even though all other symbols are removed with this option.
254
+ # also retain . ? and ! since they can be indicators for the stop token
255
+ phones = phones.replace("ˌ", "").replace("ː", "").replace("ˑ", "") \
256
+ .replace("˘", "").replace("|", "").replace("‖", "")
257
+ if not self.use_word_boundaries:
258
+ phones = phones.replace(" ", "")
259
+ else:
260
+ phones = re.sub(r"\s+", " ", phones)
261
+ phones = re.sub(" ", "~", phones)
262
+ if self.strip_silence:
263
+ phones = phones.lstrip("~").rstrip("~")
264
+ if self.add_silence_to_end:
265
+ phones += "~" # adding a silence in the end during add_silence_to_end produces more natural sounding prosody
266
+ if include_eos_symbol:
267
+ phones += "#"
268
+
269
+ phones = "~" + phones
270
+ phones = re.sub("~+", "~", phones)
271
+
272
+ return phones
273
+
274
+
275
+ def english_text_expansion(text):
276
+
277
+ _abbreviations = [(re.compile('\\b%s\\.' % x[0], re.IGNORECASE), x[1]) for x in
278
+ [('Mrs.', 'misess'), ('Mr.', 'mister'), ('Dr.', 'doctor'), ('St.', 'saint'), ('Co.', 'company'), ('Jr.', 'junior'), ('Maj.', 'major'),
279
+ ('Gen.', 'general'), ('Drs.', 'doctors'), ('Rev.', 'reverend'), ('Lt.', 'lieutenant'), ('Hon.', 'honorable'), ('Sgt.', 'sergeant'),
280
+ ('Capt.', 'captain'), ('Esq.', 'esquire'), ('Ltd.', 'limited'), ('Col.', 'colonel'), ('Ft.', 'fort')]]
281
+ for regex, replacement in _abbreviations:
282
+ text = re.sub(regex, replacement, text)
283
+ return text
284
+
285
+
286
+ def get_language_id(language):
287
+ if language == "en":
288
+ return torch.LongTensor([12])
289
+ elif language == "de":
290
+ return torch.LongTensor([1])
291
+ elif language == "el":
292
+ return torch.LongTensor([2])
293
+ elif language == "es":
294
+ return torch.LongTensor([3])
295
+ elif language == "fi":
296
+ return torch.LongTensor([4])
297
+ elif language == "ru":
298
+ return torch.LongTensor([5])
299
+ elif language == "hu":
300
+ return torch.LongTensor([6])
301
+ elif language == "nl":
302
+ return torch.LongTensor([7])
303
+ elif language == "fr":
304
+ return torch.LongTensor([8])
305
+ elif language == "pt":
306
+ return torch.LongTensor([9])
307
+ elif language == "pl":
308
+ return torch.LongTensor([10])
309
+ elif language == "it":
310
+ return torch.LongTensor([11])
311
+
312
+
313
+ if __name__ == '__main__':
314
+ # test an English utterance
315
+ tfr_en = ArticulatoryCombinedTextFrontend(language="en")
316
+ print(tfr_en.string_to_tensor("This is a complex sentence, it even has a pause! But can it do this? Nice.", view=True))
317
+
318
+ tfr_en = ArticulatoryCombinedTextFrontend(language="de")
319
+ print(tfr_en.string_to_tensor("Alles klar, jetzt testen wir einen deutschen Satz. Ich hoffe es gibt nicht mehr viele unspezifizierte Phoneme.", view=True))
Preprocessing/AudioPreprocessor.py ADDED
@@ -0,0 +1,163 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import librosa
2
+ import librosa.core as lb
3
+ import librosa.display as lbd
4
+ import matplotlib.pyplot as plt
5
+ import numpy
6
+ import numpy as np
7
+ import pyloudnorm as pyln
8
+ import torch
9
+ from torchaudio.transforms import Resample
10
+
11
+
12
+ class AudioPreprocessor:
13
+
14
+ def __init__(self, input_sr, output_sr=None, melspec_buckets=80, hop_length=256, n_fft=1024, cut_silence=False, device="cpu"):
15
+ """
16
+ The parameters are by default set up to do well
17
+ on a 16kHz signal. A different sampling rate may
18
+ require different hop_length and n_fft (e.g.
19
+ doubling frequency --> doubling hop_length and
20
+ doubling n_fft)
21
+ """
22
+ self.cut_silence = cut_silence
23
+ self.device = device
24
+ self.sr = input_sr
25
+ self.new_sr = output_sr
26
+ self.hop_length = hop_length
27
+ self.n_fft = n_fft
28
+ self.mel_buckets = melspec_buckets
29
+ self.meter = pyln.Meter(input_sr)
30
+ self.final_sr = input_sr
31
+ if cut_silence:
32
+ torch.hub._validate_not_a_forked_repo = lambda a, b, c: True # torch 1.9 has a bug in the hub loading, this is a workaround
33
+ # careful: assumes 16kHz or 8kHz audio
34
+ self.silero_model, utils = torch.hub.load(repo_or_dir='snakers4/silero-vad',
35
+ model='silero_vad',
36
+ force_reload=False,
37
+ onnx=False,
38
+ verbose=False)
39
+ (self.get_speech_timestamps,
40
+ self.save_audio,
41
+ self.read_audio,
42
+ self.VADIterator,
43
+ self.collect_chunks) = utils
44
+ self.silero_model = self.silero_model.to(self.device)
45
+ if output_sr is not None and output_sr != input_sr:
46
+ self.resample = Resample(orig_freq=input_sr, new_freq=output_sr).to(self.device)
47
+ self.final_sr = output_sr
48
+ else:
49
+ self.resample = lambda x: x
50
+
51
+ def cut_silence_from_audio(self, audio):
52
+ return self.collect_chunks(self.get_speech_timestamps(audio, self.silero_model, sampling_rate=self.final_sr), audio)
53
+
54
+ def to_mono(self, x):
55
+ """
56
+ make sure we deal with a 1D array
57
+ """
58
+ if len(x.shape) == 2:
59
+ return lb.to_mono(numpy.transpose(x))
60
+ else:
61
+ return x
62
+
63
+ def normalize_loudness(self, audio):
64
+ """
65
+ normalize the amplitudes according to
66
+ their decibels, so this should turn any
67
+ signal with different magnitudes into
68
+ the same magnitude by analysing loudness
69
+ """
70
+ loudness = self.meter.integrated_loudness(audio)
71
+ loud_normed = pyln.normalize.loudness(audio, loudness, -30.0)
72
+ peak = numpy.amax(numpy.abs(loud_normed))
73
+ peak_normed = numpy.divide(loud_normed, peak)
74
+ return peak_normed
75
+
76
+ def logmelfilterbank(self, audio, sampling_rate, fmin=40, fmax=8000, eps=1e-10):
77
+ """
78
+ Compute log-Mel filterbank
79
+
80
+ one day this could be replaced by torchaudio's internal log10(melspec(audio)), but
81
+ for some reason it gives slightly different results, so in order not to break backwards
82
+ compatibility, this is kept for now. If there is ever a reason to completely re-train
83
+ all models, this would be a good opportunity to make the switch.
84
+ """
85
+ if isinstance(audio, torch.Tensor):
86
+ audio = audio.numpy()
87
+ # get amplitude spectrogram
88
+ x_stft = librosa.stft(audio, n_fft=self.n_fft, hop_length=self.hop_length, win_length=None, window="hann", pad_mode="reflect")
89
+ spc = np.abs(x_stft).T
90
+ # get mel basis
91
+ fmin = 0 if fmin is None else fmin
92
+ fmax = sampling_rate / 2 if fmax is None else fmax
93
+ mel_basis = librosa.filters.mel(sampling_rate, self.n_fft, self.mel_buckets, fmin, fmax)
94
+ # apply log and return
95
+ return torch.Tensor(np.log10(np.maximum(eps, np.dot(spc, mel_basis.T)))).transpose(0, 1)
96
+
97
+ def normalize_audio(self, audio):
98
+ """
99
+ one function to apply them all in an
100
+ order that makes sense.
101
+ """
102
+ audio = self.to_mono(audio)
103
+ audio = self.normalize_loudness(audio)
104
+ audio = torch.Tensor(audio).to(self.device)
105
+ audio = self.resample(audio)
106
+ if self.cut_silence:
107
+ audio = self.cut_silence_from_audio(audio)
108
+ return audio.to("cpu")
109
+
110
+ def visualize_cleaning(self, unclean_audio):
111
+ """
112
+ displays Mel Spectrogram of unclean audio
113
+ and then displays Mel Spectrogram of the
114
+ cleaned version.
115
+ """
116
+ fig, ax = plt.subplots(nrows=2, ncols=1)
117
+ unclean_audio_mono = self.to_mono(unclean_audio)
118
+ unclean_spec = self.audio_to_mel_spec_tensor(unclean_audio_mono, normalize=False).numpy()
119
+ clean_spec = self.audio_to_mel_spec_tensor(unclean_audio_mono, normalize=True).numpy()
120
+ lbd.specshow(unclean_spec, sr=self.sr, cmap='GnBu', y_axis='mel', ax=ax[0], x_axis='time')
121
+ ax[0].set(title='Uncleaned Audio')
122
+ ax[0].label_outer()
123
+ if self.new_sr is not None:
124
+ lbd.specshow(clean_spec, sr=self.new_sr, cmap='GnBu', y_axis='mel', ax=ax[1], x_axis='time')
125
+ else:
126
+ lbd.specshow(clean_spec, sr=self.sr, cmap='GnBu', y_axis='mel', ax=ax[1], x_axis='time')
127
+ ax[1].set(title='Cleaned Audio')
128
+ ax[1].label_outer()
129
+ plt.show()
130
+
131
+ def audio_to_wave_tensor(self, audio, normalize=True):
132
+ if normalize:
133
+ return self.normalize_audio(audio)
134
+ else:
135
+ if isinstance(audio, torch.Tensor):
136
+ return audio
137
+ else:
138
+ return torch.Tensor(audio)
139
+
140
+ def audio_to_mel_spec_tensor(self, audio, normalize=True, explicit_sampling_rate=None):
141
+ """
142
+ explicit_sampling_rate is for when
143
+ normalization has already been applied
144
+ and that included resampling. No way
145
+ to detect the current sr of the incoming
146
+ audio
147
+ """
148
+ if explicit_sampling_rate is None:
149
+ if normalize:
150
+ audio = self.normalize_audio(audio)
151
+ return self.logmelfilterbank(audio=audio, sampling_rate=self.final_sr)
152
+ return self.logmelfilterbank(audio=audio, sampling_rate=self.sr)
153
+ if normalize:
154
+ audio = self.normalize_audio(audio)
155
+ return self.logmelfilterbank(audio=audio, sampling_rate=explicit_sampling_rate)
156
+
157
+
158
+ if __name__ == '__main__':
159
+ import soundfile
160
+
161
+ wav, sr = soundfile.read("../audios/test.wav")
162
+ ap = AudioPreprocessor(input_sr=sr, output_sr=16000)
163
+ ap.visualize_cleaning(wav)
Preprocessing/ProsodicConditionExtractor.py ADDED
@@ -0,0 +1,40 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import soundfile as sf
2
+ import torch
3
+ import torch.multiprocessing
4
+ import torch.multiprocessing
5
+ from numpy import trim_zeros
6
+ from speechbrain.pretrained import EncoderClassifier
7
+
8
+ from Preprocessing.AudioPreprocessor import AudioPreprocessor
9
+
10
+
11
+ class ProsodicConditionExtractor:
12
+
13
+ def __init__(self, sr, device=torch.device("cpu")):
14
+ self.ap = AudioPreprocessor(input_sr=sr, output_sr=16000, melspec_buckets=80, hop_length=256, n_fft=1024, cut_silence=False)
15
+
16
+ self.speaker_embedding_func_ecapa = EncoderClassifier.from_hparams(source="speechbrain/spkrec-ecapa-voxceleb",
17
+ run_opts={"device": str(device)},
18
+ savedir="Models/SpeakerEmbedding/speechbrain_speaker_embedding_ecapa")
19
+
20
+ self.speaker_embedding_func_xvector = EncoderClassifier.from_hparams(source="speechbrain/spkrec-xvect-voxceleb",
21
+ run_opts={"device": str(device)},
22
+ savedir="Models/SpeakerEmbedding/speechbrain_speaker_embedding_xvector")
23
+
24
+ def extract_condition_from_reference_wave(self, wave, already_normalized=False):
25
+ if already_normalized:
26
+ norm_wave = wave
27
+ else:
28
+ norm_wave = self.ap.audio_to_wave_tensor(normalize=True, audio=wave)
29
+ norm_wave = torch.tensor(trim_zeros(norm_wave.numpy()))
30
+ spk_emb_ecapa = self.speaker_embedding_func_ecapa.encode_batch(wavs=norm_wave.unsqueeze(0)).squeeze()
31
+ spk_emb_xvector = self.speaker_embedding_func_xvector.encode_batch(wavs=norm_wave.unsqueeze(0)).squeeze()
32
+ combined_utt_condition = torch.cat([spk_emb_ecapa.cpu(),
33
+ spk_emb_xvector.cpu()], dim=0)
34
+ return combined_utt_condition
35
+
36
+
37
+ if __name__ == '__main__':
38
+ wave, sr = sf.read("../audios/1.wav")
39
+ ext = ProsodicConditionExtractor(sr=sr)
40
+ print(ext.extract_condition_from_reference_wave(wave=wave).shape)
Preprocessing/__init__.py ADDED
File without changes
Preprocessing/papercup_features.py ADDED
@@ -0,0 +1,637 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # Derived from an open-source resource provided by Papercup Technologies Limited
2
+ # Resource-Author: Marlene Staib
3
+ # Modified by Florian Lux, 2021
4
+
5
+ def generate_feature_lookup():
6
+ return {
7
+ '~': {'symbol_type': 'silence'},
8
+ '#': {'symbol_type': 'end of sentence'},
9
+ '?': {'symbol_type': 'questionmark'},
10
+ '!': {'symbol_type': 'exclamationmark'},
11
+ '.': {'symbol_type': 'fullstop'},
12
+ 'ɜ': {
13
+ 'symbol_type' : 'phoneme',
14
+ 'vowel_consonant' : 'vowel',
15
+ 'VUV' : 'voiced',
16
+ 'vowel_frontness' : 'central',
17
+ 'vowel_openness' : 'open-mid',
18
+ 'vowel_roundedness': 'unrounded',
19
+ },
20
+ 'ɫ': {
21
+ 'symbol_type' : 'phoneme',
22
+ 'vowel_consonant' : 'consonant',
23
+ 'VUV' : 'voiced',
24
+ 'consonant_place' : 'alveolar',
25
+ 'consonant_manner': 'lateral-approximant',
26
+ },
27
+ 'ə': {
28
+ 'symbol_type' : 'phoneme',
29
+ 'vowel_consonant' : 'vowel',
30
+ 'VUV' : 'voiced',
31
+ 'vowel_frontness' : 'central',
32
+ 'vowel_openness' : 'mid',
33
+ 'vowel_roundedness': 'unrounded',
34
+ },
35
+ 'ɚ': {
36
+ 'symbol_type' : 'phoneme',
37
+ 'vowel_consonant' : 'vowel',
38
+ 'VUV' : 'voiced',
39
+ 'vowel_frontness' : 'central',
40
+ 'vowel_openness' : 'mid',
41
+ 'vowel_roundedness': 'unrounded',
42
+ },
43
+ 'a': {
44
+ 'symbol_type' : 'phoneme',
45
+ 'vowel_consonant' : 'vowel',
46
+ 'VUV' : 'voiced',
47
+ 'vowel_frontness' : 'front',
48
+ 'vowel_openness' : 'open',
49
+ 'vowel_roundedness': 'unrounded',
50
+ },
51
+ 'ð': {
52
+ 'symbol_type' : 'phoneme',
53
+ 'vowel_consonant' : 'consonant',
54
+ 'VUV' : 'voiced',
55
+ 'consonant_place' : 'dental',
56
+ 'consonant_manner': 'fricative'
57
+ },
58
+ 'ɛ': {
59
+ 'symbol_type' : 'phoneme',
60
+ 'vowel_consonant' : 'vowel',
61
+ 'VUV' : 'voiced',
62
+ 'vowel_frontness' : 'front',
63
+ 'vowel_openness' : 'open-mid',
64
+ 'vowel_roundedness': 'unrounded',
65
+ },
66
+ 'ɪ': {
67
+ 'symbol_type' : 'phoneme',
68
+ 'vowel_consonant' : 'vowel',
69
+ 'VUV' : 'voiced',
70
+ 'vowel_frontness' : 'front_central',
71
+ 'vowel_openness' : 'close_close-mid',
72
+ 'vowel_roundedness': 'unrounded',
73
+ },
74
+ 'ᵻ': {
75
+ 'symbol_type' : 'phoneme',
76
+ 'vowel_consonant' : 'vowel',
77
+ 'VUV' : 'voiced',
78
+ 'vowel_frontness' : 'central',
79
+ 'vowel_openness' : 'close',
80
+ 'vowel_roundedness': 'unrounded',
81
+ },
82
+ 'ŋ': {
83
+ 'symbol_type' : 'phoneme',
84
+ 'vowel_consonant' : 'consonant',
85
+ 'VUV' : 'voiced',
86
+ 'consonant_place' : 'velar',
87
+ 'consonant_manner': 'nasal'
88
+ },
89
+ 'ɔ': {
90
+ 'symbol_type' : 'phoneme',
91
+ 'vowel_consonant' : 'vowel',
92
+ 'VUV' : 'voiced',
93
+ 'vowel_frontness' : 'back',
94
+ 'vowel_openness' : 'open-mid',
95
+ 'vowel_roundedness': 'rounded',
96
+ },
97
+ 'ɒ': {
98
+ 'symbol_type' : 'phoneme',
99
+ 'vowel_consonant' : 'vowel',
100
+ 'VUV' : 'voiced',
101
+ 'vowel_frontness' : 'back',
102
+ 'vowel_openness' : 'open',
103
+ 'vowel_roundedness': 'rounded',
104
+ },
105
+ 'ɾ': {
106
+ 'symbol_type' : 'phoneme',
107
+ 'vowel_consonant' : 'consonant',
108
+ 'VUV' : 'voiced',
109
+ 'consonant_place' : 'alveolar',
110
+ 'consonant_manner': 'tap'
111
+ },
112
+ 'ʃ': {
113
+ 'symbol_type' : 'phoneme',
114
+ 'vowel_consonant' : 'consonant',
115
+ 'VUV' : 'unvoiced',
116
+ 'consonant_place' : 'postalveolar',
117
+ 'consonant_manner': 'fricative'
118
+ },
119
+ 'θ': {
120
+ 'symbol_type' : 'phoneme',
121
+ 'vowel_consonant' : 'consonant',
122
+ 'VUV' : 'unvoiced',
123
+ 'consonant_place' : 'dental',
124
+ 'consonant_manner': 'fricative'
125
+ },
126
+ 'ʊ': {
127
+ 'symbol_type' : 'phoneme',
128
+ 'vowel_consonant' : 'vowel',
129
+ 'VUV' : 'voiced',
130
+ 'vowel_frontness' : 'central_back',
131
+ 'vowel_openness' : 'close_close-mid',
132
+ 'vowel_roundedness': 'unrounded'
133
+ },
134
+ 'ʌ': {
135
+ 'symbol_type' : 'phoneme',
136
+ 'vowel_consonant' : 'vowel',
137
+ 'VUV' : 'voiced',
138
+ 'vowel_frontness' : 'back',
139
+ 'vowel_openness' : 'open-mid',
140
+ 'vowel_roundedness': 'unrounded'
141
+ },
142
+ 'ʒ': {
143
+ 'symbol_type' : 'phoneme',
144
+ 'vowel_consonant' : 'consonant',
145
+ 'VUV' : 'voiced',
146
+ 'consonant_place' : 'postalveolar',
147
+ 'consonant_manner': 'fricative'
148
+ },
149
+ 'æ': {
150
+ 'symbol_type' : 'phoneme',
151
+ 'vowel_consonant' : 'vowel',
152
+ 'VUV' : 'voiced',
153
+ 'vowel_frontness' : 'front',
154
+ 'vowel_openness' : 'open-mid_open',
155
+ 'vowel_roundedness': 'unrounded'
156
+ },
157
+ 'b': {
158
+ 'symbol_type' : 'phoneme',
159
+ 'vowel_consonant' : 'consonant',
160
+ 'VUV' : 'voiced',
161
+ 'consonant_place' : 'bilabial',
162
+ 'consonant_manner': 'stop'
163
+ },
164
+ 'ʔ': {
165
+ 'symbol_type' : 'phoneme',
166
+ 'vowel_consonant' : 'consonant',
167
+ 'VUV' : 'unvoiced',
168
+ 'consonant_place' : 'glottal',
169
+ 'consonant_manner': 'stop'
170
+ },
171
+ 'd': {
172
+ 'symbol_type' : 'phoneme',
173
+ 'vowel_consonant' : 'consonant',
174
+ 'VUV' : 'voiced',
175
+ 'consonant_place' : 'alveolar',
176
+ 'consonant_manner': 'stop'
177
+ },
178
+ 'e': {
179
+ 'symbol_type' : 'phoneme',
180
+ 'vowel_consonant' : 'vowel',
181
+ 'VUV' : 'voiced',
182
+ 'vowel_frontness' : 'front',
183
+ 'vowel_openness' : 'close-mid',
184
+ 'vowel_roundedness': 'unrounded'
185
+ },
186
+ 'f': {
187
+ 'symbol_type' : 'phoneme',
188
+ 'vowel_consonant' : 'consonant',
189
+ 'VUV' : 'unvoiced',
190
+ 'consonant_place' : 'labiodental',
191
+ 'consonant_manner': 'fricative'
192
+ },
193
+ 'g': {
194
+ 'symbol_type' : 'phoneme',
195
+ 'vowel_consonant' : 'consonant',
196
+ 'VUV' : 'voiced',
197
+ 'consonant_place' : 'velar',
198
+ 'consonant_manner': 'stop'
199
+ },
200
+ 'h': {
201
+ 'symbol_type' : 'phoneme',
202
+ 'vowel_consonant' : 'consonant',
203
+ 'VUV' : 'unvoiced',
204
+ 'consonant_place' : 'glottal',
205
+ 'consonant_manner': 'fricative'
206
+ },
207
+ 'i': {
208
+ 'symbol_type' : 'phoneme',
209
+ 'vowel_consonant' : 'vowel',
210
+ 'VUV' : 'voiced',
211
+ 'vowel_frontness' : 'front',
212
+ 'vowel_openness' : 'close',
213
+ 'vowel_roundedness': 'unrounded'
214
+ },
215
+ 'j': {
216
+ 'symbol_type' : 'phoneme',
217
+ 'vowel_consonant' : 'consonant',
218
+ 'VUV' : 'voiced',
219
+ 'consonant_place' : 'palatal',
220
+ 'consonant_manner': 'approximant'
221
+ },
222
+ 'k': {
223
+ 'symbol_type' : 'phoneme',
224
+ 'vowel_consonant' : 'consonant',
225
+ 'VUV' : 'unvoiced',
226
+ 'consonant_place' : 'velar',
227
+ 'consonant_manner': 'stop'
228
+ },
229
+ 'l': {
230
+ 'symbol_type' : 'phoneme',
231
+ 'vowel_consonant' : 'consonant',
232
+ 'VUV' : 'voiced',
233
+ 'consonant_place' : 'alveolar',
234
+ 'consonant_manner': 'lateral-approximant'
235
+ },
236
+ 'm': {
237
+ 'symbol_type' : 'phoneme',
238
+ 'vowel_consonant' : 'consonant',
239
+ 'VUV' : 'voiced',
240
+ 'consonant_place' : 'bilabial',
241
+ 'consonant_manner': 'nasal'
242
+ },
243
+ 'n': {
244
+ 'symbol_type' : 'phoneme',
245
+ 'vowel_consonant' : 'consonant',
246
+ 'VUV' : 'voiced',
247
+ 'consonant_place' : 'alveolar',
248
+ 'consonant_manner': 'nasal'
249
+ },
250
+ 'ɳ': {
251
+ 'symbol_type' : 'phoneme',
252
+ 'vowel_consonant' : 'consonant',
253
+ 'VUV' : 'voiced',
254
+ 'consonant_place' : 'palatal',
255
+ 'consonant_manner': 'nasal'
256
+ },
257
+ 'o': {
258
+ 'symbol_type' : 'phoneme',
259
+ 'vowel_consonant' : 'vowel',
260
+ 'VUV' : 'voiced',
261
+ 'vowel_frontness' : 'back',
262
+ 'vowel_openness' : 'close-mid',
263
+ 'vowel_roundedness': 'rounded'
264
+ },
265
+ 'p': {
266
+ 'symbol_type' : 'phoneme',
267
+ 'vowel_consonant' : 'consonant',
268
+ 'VUV' : 'unvoiced',
269
+ 'consonant_place' : 'bilabial',
270
+ 'consonant_manner': 'stop'
271
+ },
272
+ 'ɡ': {
273
+ 'symbol_type' : 'phoneme',
274
+ 'vowel_consonant' : 'consonant',
275
+ 'VUV' : 'voiced',
276
+ 'consonant_place' : 'velar',
277
+ 'consonant_manner': 'stop'
278
+ },
279
+ 'ɹ': {
280
+ 'symbol_type' : 'phoneme',
281
+ 'vowel_consonant' : 'consonant',
282
+ 'VUV' : 'voiced',
283
+ 'consonant_place' : 'alveolar',
284
+ 'consonant_manner': 'approximant'
285
+ },
286
+ 'r': {
287
+ 'symbol_type' : 'phoneme',
288
+ 'vowel_consonant' : 'consonant',
289
+ 'VUV' : 'voiced',
290
+ 'consonant_place' : 'alveolar',
291
+ 'consonant_manner': 'trill'
292
+ },
293
+ 's': {
294
+ 'symbol_type' : 'phoneme',
295
+ 'vowel_consonant' : 'consonant',
296
+ 'VUV' : 'unvoiced',
297
+ 'consonant_place' : 'alveolar',
298
+ 'consonant_manner': 'fricative'
299
+ },
300
+ 't': {
301
+ 'symbol_type' : 'phoneme',
302
+ 'vowel_consonant' : 'consonant',
303
+ 'VUV' : 'unvoiced',
304
+ 'consonant_place' : 'alveolar',
305
+ 'consonant_manner': 'stop'
306
+ },
307
+ 'u': {
308
+ 'symbol_type' : 'phoneme',
309
+ 'vowel_consonant' : 'vowel',
310
+ 'VUV' : 'voiced',
311
+ 'vowel_frontness' : 'back',
312
+ 'vowel_openness' : 'close',
313
+ 'vowel_roundedness': 'rounded',
314
+ },
315
+ 'v': {
316
+ 'symbol_type' : 'phoneme',
317
+ 'vowel_consonant' : 'consonant',
318
+ 'VUV' : 'voiced',
319
+ 'consonant_place' : 'labiodental',
320
+ 'consonant_manner': 'fricative'
321
+ },
322
+ 'w': {
323
+ 'symbol_type' : 'phoneme',
324
+ 'vowel_consonant' : 'consonant',
325
+ 'VUV' : 'voiced',
326
+ 'consonant_place' : 'labial-velar',
327
+ 'consonant_manner': 'approximant'
328
+ },
329
+ 'x': {
330
+ 'symbol_type' : 'phoneme',
331
+ 'vowel_consonant' : 'consonant',
332
+ 'VUV' : 'unvoiced',
333
+ 'consonant_place' : 'velar',
334
+ 'consonant_manner': 'fricative'
335
+ },
336
+ 'z': {
337
+ 'symbol_type' : 'phoneme',
338
+ 'vowel_consonant' : 'consonant',
339
+ 'VUV' : 'voiced',
340
+ 'consonant_place' : 'alveolar',
341
+ 'consonant_manner': 'fricative'
342
+ },
343
+ 'ʀ': {
344
+ 'symbol_type' : 'phoneme',
345
+ 'vowel_consonant' : 'consonant',
346
+ 'VUV' : 'voiced',
347
+ 'consonant_place' : 'uvular',
348
+ 'consonant_manner': 'trill'
349
+ },
350
+ 'ø': {
351
+ 'symbol_type' : 'phoneme',
352
+ 'vowel_consonant' : 'vowel',
353
+ 'VUV' : 'voiced',
354
+ 'vowel_frontness' : 'front',
355
+ 'vowel_openness' : 'close-mid',
356
+ 'vowel_roundedness': 'rounded'
357
+ },
358
+ 'ç': {
359
+ 'symbol_type' : 'phoneme',
360
+ 'vowel_consonant' : 'consonant',
361
+ 'VUV' : 'unvoiced',
362
+ 'consonant_place' : 'palatal',
363
+ 'consonant_manner': 'fricative'
364
+ },
365
+ 'ɐ': {
366
+ 'symbol_type' : 'phoneme',
367
+ 'vowel_consonant' : 'vowel',
368
+ 'VUV' : 'voiced',
369
+ 'vowel_frontness' : 'central',
370
+ 'vowel_openness' : 'open',
371
+ 'vowel_roundedness': 'unrounded'
372
+ },
373
+ 'œ': {
374
+ 'symbol_type' : 'phoneme',
375
+ 'vowel_consonant' : 'vowel',
376
+ 'VUV' : 'voiced',
377
+ 'vowel_frontness' : 'front',
378
+ 'vowel_openness' : 'open-mid',
379
+ 'vowel_roundedness': 'rounded'
380
+ },
381
+ 'y': {
382
+ 'symbol_type' : 'phoneme',
383
+ 'vowel_consonant' : 'vowel',
384
+ 'VUV' : 'voiced',
385
+ 'vowel_frontness' : 'front',
386
+ 'vowel_openness' : 'close',
387
+ 'vowel_roundedness': 'rounded'
388
+ },
389
+ 'ʏ': {
390
+ 'symbol_type' : 'phoneme',
391
+ 'vowel_consonant' : 'vowel',
392
+ 'VUV' : 'voiced',
393
+ 'vowel_frontness' : 'front_central',
394
+ 'vowel_openness' : 'close_close-mid',
395
+ 'vowel_roundedness': 'rounded'
396
+ },
397
+ 'ɑ': {
398
+ 'symbol_type' : 'phoneme',
399
+ 'vowel_consonant' : 'vowel',
400
+ 'VUV' : 'voiced',
401
+ 'vowel_frontness' : 'back',
402
+ 'vowel_openness' : 'open',
403
+ 'vowel_roundedness': 'unrounded'
404
+ },
405
+ 'c': {
406
+ 'symbol_type' : 'phoneme',
407
+ 'vowel_consonant' : 'consonant',
408
+ 'VUV' : 'unvoiced',
409
+ 'consonant_place' : 'palatal',
410
+ 'consonant_manner': 'stop'
411
+ },
412
+ 'ɲ': {
413
+ 'symbol_type' : 'phoneme',
414
+ 'vowel_consonant' : 'consonant',
415
+ 'VUV' : 'voiced',
416
+ 'consonant_place' : 'palatal',
417
+ 'consonant_manner': 'nasal'
418
+ },
419
+ 'ɣ': {
420
+ 'symbol_type' : 'phoneme',
421
+ 'vowel_consonant' : 'consonant',
422
+ 'VUV' : 'voiced',
423
+ 'consonant_place' : 'velar',
424
+ 'consonant_manner': 'fricative'
425
+ },
426
+ 'ʎ': {
427
+ 'symbol_type' : 'phoneme',
428
+ 'vowel_consonant' : 'consonant',
429
+ 'VUV' : 'voiced',
430
+ 'consonant_place' : 'palatal',
431
+ 'consonant_manner': 'lateral-approximant'
432
+ },
433
+ 'β': {
434
+ 'symbol_type' : 'phoneme',
435
+ 'vowel_consonant' : 'consonant',
436
+ 'VUV' : 'voiced',
437
+ 'consonant_place' : 'bilabial',
438
+ 'consonant_manner': 'fricative'
439
+ },
440
+ 'ʝ': {
441
+ 'symbol_type' : 'phoneme',
442
+ 'vowel_consonant' : 'consonant',
443
+ 'VUV' : 'voiced',
444
+ 'consonant_place' : 'palatal',
445
+ 'consonant_manner': 'fricative'
446
+ },
447
+ 'ɟ': {
448
+ 'symbol_type' : 'phoneme',
449
+ 'vowel_consonant' : 'consonant',
450
+ 'VUV' : 'voiced',
451
+ 'consonant_place' : 'palatal',
452
+ 'consonant_manner': 'stop'
453
+ },
454
+ 'q': {
455
+ 'symbol_type' : 'phoneme',
456
+ 'vowel_consonant' : 'consonant',
457
+ 'VUV' : 'unvoiced',
458
+ 'consonant_place' : 'uvular',
459
+ 'consonant_manner': 'stop'
460
+ },
461
+ 'ɕ': {
462
+ 'symbol_type' : 'phoneme',
463
+ 'vowel_consonant' : 'consonant',
464
+ 'VUV' : 'unvoiced',
465
+ 'consonant_place' : 'alveolopalatal',
466
+ 'consonant_manner': 'fricative'
467
+ },
468
+ 'ʲ': {
469
+ 'symbol_type' : 'phoneme',
470
+ 'vowel_consonant' : 'consonant',
471
+ 'VUV' : 'voiced',
472
+ 'consonant_place' : 'palatal',
473
+ 'consonant_manner': 'approximant'
474
+ },
475
+ 'ɭ': {
476
+ 'symbol_type' : 'phoneme',
477
+ 'vowel_consonant' : 'consonant',
478
+ 'VUV' : 'voiced',
479
+ 'consonant_place' : 'palatal', # should be retroflex, but palatal should be close enough
480
+ 'consonant_manner': 'lateral-approximant'
481
+ },
482
+ 'ɵ': {
483
+ 'symbol_type' : 'phoneme',
484
+ 'vowel_consonant' : 'vowel',
485
+ 'VUV' : 'voiced',
486
+ 'vowel_frontness' : 'central',
487
+ 'vowel_openness' : 'open-mid',
488
+ 'vowel_roundedness': 'rounded'
489
+ },
490
+ 'ʑ': {
491
+ 'symbol_type' : 'phoneme',
492
+ 'vowel_consonant' : 'consonant',
493
+ 'VUV' : 'voiced',
494
+ 'consonant_place' : 'alveolopalatal',
495
+ 'consonant_manner': 'fricative'
496
+ },
497
+ 'ʋ': {
498
+ 'symbol_type' : 'phoneme',
499
+ 'vowel_consonant' : 'consonant',
500
+ 'VUV' : 'voiced',
501
+ 'consonant_place' : 'labiodental',
502
+ 'consonant_manner': 'approximant'
503
+ },
504
+ 'ʁ': {
505
+ 'symbol_type' : 'phoneme',
506
+ 'vowel_consonant' : 'consonant',
507
+ 'VUV' : 'voiced',
508
+ 'consonant_place' : 'uvular',
509
+ 'consonant_manner': 'fricative'
510
+ },
511
+ 'ɨ': {
512
+ 'symbol_type' : 'phoneme',
513
+ 'vowel_consonant' : 'vowel',
514
+ 'VUV' : 'voiced',
515
+ 'vowel_frontness' : 'central',
516
+ 'vowel_openness' : 'close',
517
+ 'vowel_roundedness': 'unrounded'
518
+ },
519
+ 'ʂ': {
520
+ 'symbol_type' : 'phoneme',
521
+ 'vowel_consonant' : 'consonant',
522
+ 'VUV' : 'unvoiced',
523
+ 'consonant_place' : 'palatal', # should be retroflex, but palatal should be close enough
524
+ 'consonant_manner': 'fricative'
525
+ },
526
+ 'ɬ': {
527
+ 'symbol_type' : 'phoneme',
528
+ 'vowel_consonant' : 'consonant',
529
+ 'VUV' : 'unvoiced',
530
+ 'consonant_place' : 'alveolar', # should be noted it's also lateral, but should be close enough
531
+ 'consonant_manner': 'fricative'
532
+ },
533
+ } # REMEMBER to also add the phonemes added here to the ID lookup table in the TextFrontend as the new highest ID
534
+
535
+
536
+ def generate_feature_table():
537
+ ipa_to_phonemefeats = generate_feature_lookup()
538
+
539
+ feat_types = set()
540
+ for ipa in ipa_to_phonemefeats:
541
+ if len(ipa) == 1:
542
+ [feat_types.add(feat) for feat in ipa_to_phonemefeats[ipa].keys()]
543
+
544
+ feat_to_val_set = dict()
545
+ for feat in feat_types:
546
+ feat_to_val_set[feat] = set()
547
+ for ipa in ipa_to_phonemefeats:
548
+ if len(ipa) == 1:
549
+ for feat in ipa_to_phonemefeats[ipa]:
550
+ feat_to_val_set[feat].add(ipa_to_phonemefeats[ipa][feat])
551
+
552
+ # print(feat_to_val_set)
553
+
554
+ value_list = set()
555
+ for val_set in [feat_to_val_set[feat] for feat in feat_to_val_set]:
556
+ for value in val_set:
557
+ value_list.add(value)
558
+ # print("{")
559
+ # for index, value in enumerate(list(value_list)):
560
+ # print('"{}":{},'.format(value,index))
561
+ # print("}")
562
+
563
+ value_to_index = {
564
+ "dental" : 0,
565
+ "postalveolar" : 1,
566
+ "mid" : 2,
567
+ "close-mid" : 3,
568
+ "vowel" : 4,
569
+ "silence" : 5,
570
+ "consonant" : 6,
571
+ "close" : 7,
572
+ "velar" : 8,
573
+ "stop" : 9,
574
+ "palatal" : 10,
575
+ "nasal" : 11,
576
+ "glottal" : 12,
577
+ "central" : 13,
578
+ "back" : 14,
579
+ "approximant" : 15,
580
+ "uvular" : 16,
581
+ "open-mid" : 17,
582
+ "front_central" : 18,
583
+ "front" : 19,
584
+ "end of sentence" : 20,
585
+ "labiodental" : 21,
586
+ "close_close-mid" : 22,
587
+ "labial-velar" : 23,
588
+ "unvoiced" : 24,
589
+ "central_back" : 25,
590
+ "trill" : 26,
591
+ "rounded" : 27,
592
+ "open-mid_open" : 28,
593
+ "tap" : 29,
594
+ "alveolar" : 30,
595
+ "bilabial" : 31,
596
+ "phoneme" : 32,
597
+ "open" : 33,
598
+ "fricative" : 34,
599
+ "unrounded" : 35,
600
+ "lateral-approximant": 36,
601
+ "voiced" : 37,
602
+ "questionmark" : 38,
603
+ "exclamationmark" : 39,
604
+ "fullstop" : 40,
605
+ "alveolopalatal" : 41
606
+ }
607
+
608
+ phone_to_vector = dict()
609
+ for ipa in ipa_to_phonemefeats:
610
+ if len(ipa) == 1:
611
+ phone_to_vector[ipa] = [0] * sum([len(values) for values in [feat_to_val_set[feat] for feat in feat_to_val_set]])
612
+ for feat in ipa_to_phonemefeats[ipa]:
613
+ if ipa_to_phonemefeats[ipa][feat] in value_to_index:
614
+ phone_to_vector[ipa][value_to_index[ipa_to_phonemefeats[ipa][feat]]] = 1
615
+
616
+ for feat in feat_to_val_set:
617
+ for value in feat_to_val_set[feat]:
618
+ if value not in value_to_index:
619
+ print(f"Unknown feature value in featureset! {value}")
620
+
621
+ # print(f"{sum([len(values) for values in [feat_to_val_set[feat] for feat in feat_to_val_set]])} should be 42")
622
+
623
+ return phone_to_vector
624
+
625
+
626
+ def generate_phone_to_id_lookup():
627
+ ipa_to_phonemefeats = generate_feature_lookup()
628
+ count = 0
629
+ phone_to_id = dict()
630
+ for key in sorted(list(ipa_to_phonemefeats)): # careful: non-deterministic
631
+ phone_to_id[key] = count
632
+ count += 1
633
+ return phone_to_id
634
+
635
+
636
+ if __name__ == '__main__':
637
+ print(generate_phone_to_id_lookup())
Utility/__init__.py ADDED
File without changes
Utility/utils.py ADDED
@@ -0,0 +1,355 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """
2
+ Taken from ESPNet, modified by Florian Lux
3
+ """
4
+
5
+ import os
6
+ from abc import ABC
7
+ from pydub import AudioSegment
8
+ from pydub.effects import speedup
9
+ import torch
10
+ import numpy as np
11
+ import torchaudio
12
+
13
+ def cumsum_durations(durations):
14
+ out = [0]
15
+ for duration in durations:
16
+ out.append(duration + out[-1])
17
+ centers = list()
18
+ for index, _ in enumerate(out):
19
+ if index + 1 < len(out):
20
+ centers.append((out[index] + out[index + 1]) / 2)
21
+ return out, centers
22
+
23
+
24
+ def delete_old_checkpoints(checkpoint_dir, keep=5):
25
+ checkpoint_list = list()
26
+ for el in os.listdir(checkpoint_dir):
27
+ if el.endswith(".pt") and el != "best.pt":
28
+ checkpoint_list.append(int(el.split(".")[0].split("_")[1]))
29
+ if len(checkpoint_list) <= keep:
30
+ return
31
+ else:
32
+ checkpoint_list.sort(reverse=False)
33
+ checkpoints_to_delete = [os.path.join(checkpoint_dir, "checkpoint_{}.pt".format(step)) for step in checkpoint_list[:-keep]]
34
+ for old_checkpoint in checkpoints_to_delete:
35
+ os.remove(os.path.join(old_checkpoint))
36
+
37
+
38
+ def get_most_recent_checkpoint(checkpoint_dir, verbose=True):
39
+ checkpoint_list = list()
40
+ for el in os.listdir(checkpoint_dir):
41
+ if el.endswith(".pt") and el != "best.pt":
42
+ checkpoint_list.append(int(el.split(".")[0].split("_")[1]))
43
+ if len(checkpoint_list) == 0:
44
+ print("No previous checkpoints found, cannot reload.")
45
+ return None
46
+ checkpoint_list.sort(reverse=True)
47
+ if verbose:
48
+ print("Reloading checkpoint_{}.pt".format(checkpoint_list[0]))
49
+ return os.path.join(checkpoint_dir, "checkpoint_{}.pt".format(checkpoint_list[0]))
50
+
51
+
52
+ def make_pad_mask(lengths, xs=None, length_dim=-1, device=None):
53
+ """
54
+ Make mask tensor containing indices of padded part.
55
+
56
+ Args:
57
+ lengths (LongTensor or List): Batch of lengths (B,).
58
+ xs (Tensor, optional): The reference tensor.
59
+ If set, masks will be the same shape as this tensor.
60
+ length_dim (int, optional): Dimension indicator of the above tensor.
61
+ See the example.
62
+
63
+ Returns:
64
+ Tensor: Mask tensor containing indices of padded part.
65
+ dtype=torch.uint8 in PyTorch 1.2-
66
+ dtype=torch.bool in PyTorch 1.2+ (including 1.2)
67
+
68
+ """
69
+ if length_dim == 0:
70
+ raise ValueError("length_dim cannot be 0: {}".format(length_dim))
71
+
72
+ if not isinstance(lengths, list):
73
+ lengths = lengths.tolist()
74
+ bs = int(len(lengths))
75
+ if xs is None:
76
+ maxlen = int(max(lengths))
77
+ else:
78
+ maxlen = xs.size(length_dim)
79
+
80
+ if device is not None:
81
+ seq_range = torch.arange(0, maxlen, dtype=torch.int64, device=device)
82
+ else:
83
+ seq_range = torch.arange(0, maxlen, dtype=torch.int64)
84
+ seq_range_expand = seq_range.unsqueeze(0).expand(bs, maxlen)
85
+ seq_length_expand = seq_range_expand.new(lengths).unsqueeze(-1)
86
+ mask = seq_range_expand >= seq_length_expand
87
+
88
+ if xs is not None:
89
+ assert xs.size(0) == bs, (xs.size(0), bs)
90
+
91
+ if length_dim < 0:
92
+ length_dim = xs.dim() + length_dim
93
+ # ind = (:, None, ..., None, :, , None, ..., None)
94
+ ind = tuple(slice(None) if i in (0, length_dim) else None for i in range(xs.dim()))
95
+ mask = mask[ind].expand_as(xs).to(xs.device)
96
+ return mask
97
+
98
+
99
+ def make_non_pad_mask(lengths, xs=None, length_dim=-1, device=None):
100
+ """
101
+ Make mask tensor containing indices of non-padded part.
102
+
103
+ Args:
104
+ lengths (LongTensor or List): Batch of lengths (B,).
105
+ xs (Tensor, optional): The reference tensor.
106
+ If set, masks will be the same shape as this tensor.
107
+ length_dim (int, optional): Dimension indicator of the above tensor.
108
+ See the example.
109
+
110
+ Returns:
111
+ ByteTensor: mask tensor containing indices of padded part.
112
+ dtype=torch.uint8 in PyTorch 1.2-
113
+ dtype=torch.bool in PyTorch 1.2+ (including 1.2)
114
+
115
+ """
116
+ return ~make_pad_mask(lengths, xs, length_dim, device=device)
117
+
118
+ def emotion(wav, current_speaker):
119
+
120
+ if current_speaker[2:] == "Angry":
121
+ wav *= 1.5
122
+ elif current_speaker[2:] == "Sad":
123
+ wav *= 1
124
+ elif current_speaker[2:] == "Cheerful":
125
+ wav *= 2
126
+ elif current_speaker[2:] == "Excited":
127
+ wav *= 1.7
128
+ elif current_speaker[2:] == "Friendly":
129
+ wav *= 1.5
130
+ elif current_speaker[2:] == "Hopeful":
131
+ wav *= 1.5
132
+ elif current_speaker[2:] == "Normal":
133
+ wav *= 1
134
+ elif current_speaker[2:] == "Shouting":
135
+ wav *= 3
136
+ elif current_speaker[2:] == "Terrified":
137
+ wav *= 1.3
138
+ elif current_speaker[2:] == "Unfriendly":
139
+ wav *= 1.2
140
+ elif current_speaker[2:] == "Whispering":
141
+ wav *= .6
142
+
143
+ # torchaudio.save('temp.wav', wav, 48000)
144
+
145
+ # wav = np.asarray(wav.cpu().numpy())
146
+ # wav = AudioSegment(wav.tobytes(), frame_rate = 48000, sample_width=wav.dtype.itemsize, channels=1)
147
+ # wav = speedup(wav, playback_speed=1.5)
148
+
149
+
150
+ return wav
151
+
152
+ def initialize(model, init):
153
+ """
154
+ Initialize weights of a neural network module.
155
+
156
+ Parameters are initialized using the given method or distribution.
157
+
158
+ Args:
159
+ model: Target.
160
+ init: Method of initialization.
161
+ """
162
+
163
+ # weight init
164
+ for p in model.parameters():
165
+ if p.dim() > 1:
166
+ if init == "xavier_uniform":
167
+ torch.nn.init.xavier_uniform_(p.data)
168
+ elif init == "xavier_normal":
169
+ torch.nn.init.xavier_normal_(p.data)
170
+ elif init == "kaiming_uniform":
171
+ torch.nn.init.kaiming_uniform_(p.data, nonlinearity="relu")
172
+ elif init == "kaiming_normal":
173
+ torch.nn.init.kaiming_normal_(p.data, nonlinearity="relu")
174
+ else:
175
+ raise ValueError("Unknown initialization: " + init)
176
+ # bias init
177
+ for p in model.parameters():
178
+ if p.dim() == 1:
179
+ p.data.zero_()
180
+
181
+ # reset some modules with default init
182
+ for m in model.modules():
183
+ if isinstance(m, (torch.nn.Embedding, torch.nn.LayerNorm)):
184
+ m.reset_parameters()
185
+
186
+
187
+ def pad_list(xs, pad_value):
188
+ """
189
+ Perform padding for the list of tensors.
190
+
191
+ Args:
192
+ xs (List): List of Tensors [(T_1, `*`), (T_2, `*`), ..., (T_B, `*`)].
193
+ pad_value (float): Value for padding.
194
+
195
+ Returns:
196
+ Tensor: Padded tensor (B, Tmax, `*`).
197
+
198
+ """
199
+ n_batch = len(xs)
200
+ max_len = max(x.size(0) for x in xs)
201
+ pad = xs[0].new(n_batch, max_len, *xs[0].size()[1:]).fill_(pad_value)
202
+
203
+ for i in range(n_batch):
204
+ pad[i, : xs[i].size(0)] = xs[i]
205
+
206
+ return pad
207
+
208
+
209
+ def subsequent_mask(size, device="cpu", dtype=torch.bool):
210
+ """
211
+ Create mask for subsequent steps (size, size).
212
+
213
+ :param int size: size of mask
214
+ :param str device: "cpu" or "cuda" or torch.Tensor.device
215
+ :param torch.dtype dtype: result dtype
216
+ :rtype
217
+ """
218
+ ret = torch.ones(size, size, device=device, dtype=dtype)
219
+ return torch.tril(ret, out=ret)
220
+
221
+
222
+ class ScorerInterface:
223
+ """
224
+ Scorer interface for beam search.
225
+
226
+ The scorer performs scoring of the all tokens in vocabulary.
227
+
228
+ Examples:
229
+ * Search heuristics
230
+ * :class:`espnet.nets.scorers.length_bonus.LengthBonus`
231
+ * Decoder networks of the sequence-to-sequence models
232
+ * :class:`espnet.nets.pytorch_backend.nets.transformer.decoder.Decoder`
233
+ * :class:`espnet.nets.pytorch_backend.nets.rnn.decoders.Decoder`
234
+ * Neural language models
235
+ * :class:`espnet.nets.pytorch_backend.lm.transformer.TransformerLM`
236
+ * :class:`espnet.nets.pytorch_backend.lm.default.DefaultRNNLM`
237
+ * :class:`espnet.nets.pytorch_backend.lm.seq_rnn.SequentialRNNLM`
238
+
239
+ """
240
+
241
+ def init_state(self, x):
242
+ """
243
+ Get an initial state for decoding (optional).
244
+
245
+ Args:
246
+ x (torch.Tensor): The encoded feature tensor
247
+
248
+ Returns: initial state
249
+
250
+ """
251
+ return None
252
+
253
+ def select_state(self, state, i, new_id=None):
254
+ """
255
+ Select state with relative ids in the main beam search.
256
+
257
+ Args:
258
+ state: Decoder state for prefix tokens
259
+ i (int): Index to select a state in the main beam search
260
+ new_id (int): New label index to select a state if necessary
261
+
262
+ Returns:
263
+ state: pruned state
264
+
265
+ """
266
+ return None if state is None else state[i]
267
+
268
+ def score(self, y, state, x):
269
+ """
270
+ Score new token (required).
271
+
272
+ Args:
273
+ y (torch.Tensor): 1D torch.int64 prefix tokens.
274
+ state: Scorer state for prefix tokens
275
+ x (torch.Tensor): The encoder feature that generates ys.
276
+
277
+ Returns:
278
+ tuple[torch.Tensor, Any]: Tuple of
279
+ scores for next token that has a shape of `(n_vocab)`
280
+ and next state for ys
281
+
282
+ """
283
+ raise NotImplementedError
284
+
285
+ def final_score(self, state):
286
+ """
287
+ Score eos (optional).
288
+
289
+ Args:
290
+ state: Scorer state for prefix tokens
291
+
292
+ Returns:
293
+ float: final score
294
+
295
+ """
296
+ return 0.0
297
+
298
+
299
+ class BatchScorerInterface(ScorerInterface, ABC):
300
+
301
+ def batch_init_state(self, x):
302
+ """
303
+ Get an initial state for decoding (optional).
304
+
305
+ Args:
306
+ x (torch.Tensor): The encoded feature tensor
307
+
308
+ Returns: initial state
309
+
310
+ """
311
+ return self.init_state(x)
312
+
313
+ def batch_score(self, ys, states, xs):
314
+ """
315
+ Score new token batch (required).
316
+
317
+ Args:
318
+ ys (torch.Tensor): torch.int64 prefix tokens (n_batch, ylen).
319
+ states (List[Any]): Scorer states for prefix tokens.
320
+ xs (torch.Tensor):
321
+ The encoder feature that generates ys (n_batch, xlen, n_feat).
322
+
323
+ Returns:
324
+ tuple[torch.Tensor, List[Any]]: Tuple of
325
+ batchfied scores for next token with shape of `(n_batch, n_vocab)`
326
+ and next state list for ys.
327
+
328
+ """
329
+ scores = list()
330
+ outstates = list()
331
+ for i, (y, state, x) in enumerate(zip(ys, states, xs)):
332
+ score, outstate = self.score(y, state, x)
333
+ outstates.append(outstate)
334
+ scores.append(score)
335
+ scores = torch.cat(scores, 0).view(ys.shape[0], -1)
336
+ return scores, outstates
337
+
338
+
339
+ def to_device(m, x):
340
+ """Send tensor into the device of the module.
341
+ Args:
342
+ m (torch.nn.Module): Torch module.
343
+ x (Tensor): Torch tensor.
344
+ Returns:
345
+ Tensor: Torch tensor located in the same place as torch module.
346
+ """
347
+ if isinstance(m, torch.nn.Module):
348
+ device = next(m.parameters()).device
349
+ elif isinstance(m, torch.Tensor):
350
+ device = m.device
351
+ else:
352
+ raise TypeError(
353
+ "Expected torch.nn.Module or torch.tensor, " f"bot got: {type(m)}"
354
+ )
355
+ return x.to(device)
app.py ADDED
@@ -0,0 +1,200 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+
3
+ import gradio as gr
4
+ import numpy as np
5
+ import torch
6
+ from Utility.utils import emotion
7
+ from InferenceInterfaces.Meta_FastSpeech2 import Meta_FastSpeech2
8
+
9
+
10
+ def float2pcm(sig, dtype="int16"):
11
+ sig = np.asarray(sig)
12
+ if sig.dtype.kind != "f":
13
+ raise TypeError("'sig' must be a float array")
14
+ dtype = np.dtype(dtype)
15
+ if dtype.kind not in "iu":
16
+ raise TypeError("'dtype' must be an integer type")
17
+ i = np.iinfo(dtype)
18
+ abs_max = 2 ** (i.bits - 1)
19
+ offset = i.min + abs_max
20
+ return (sig * abs_max + offset).clip(i.min, i.max).astype(dtype)
21
+
22
+
23
+ class TTS_Interface:
24
+ def __init__(self):
25
+ self.device = "cuda" if torch.cuda.is_available() else "cpu"
26
+ self.model = Meta_FastSpeech2(device=self.device)
27
+ self.current_speaker = "M_Angry"
28
+ self.current_language = "English"
29
+ self.current_accent = "English"
30
+ self.language_id_lookup = {
31
+ "English": "en",
32
+ "German": "de",
33
+ "Greek": "el",
34
+ "Spanish": "es",
35
+ "Finnish": "fi",
36
+ "Russian": "ru",
37
+ "Hungarian": "hu",
38
+ "Dutch": "nl",
39
+ "French": "fr",
40
+ "Polish": "pl",
41
+ "Portuguese": "pt",
42
+ "Italian": "it",
43
+ }
44
+ self.speaker_path_lookup = {
45
+ "M_Angry": "voices/nate_angry.mp3",
46
+ "M_Sad": "output1.wav",
47
+ "M_Cheerful": "voices/nate_cheerful.mp3",
48
+ "M_Excited": "voices/nate_excited.mp3",
49
+ "M_Friendly": "voices/robert-friendly.mp3",
50
+ "M_Hopeful": "voices/robert-hopeful.mp3",
51
+ "M_Normal": "voices/robert-normal.mp3",
52
+ "M_Shouting": "output1.wav",
53
+ "M_Terrified": "voices/nate_terrified.mp3",
54
+ "M_Unfriendly": "voices/robert-unfriendly.mp3",
55
+ "M_Whispering": "voices/robert-whispering.mp3",
56
+ "F_Angry": "voices/cleo-angry.mp3",
57
+ "F_Sad": "voices/cleo-sad.mp3",
58
+ "F_Cheerful": "voices/cleo-cheerful.mp3",
59
+ "F_Excited": "voices/cleo-excited.mp3",
60
+ "F_Friendly": "voices/cleo-friendly.mp3",
61
+ "F_Hopeful": "voices/cleo-hopeful.mp3",
62
+ "F_Normal": "voices/cleo-normal.mp3",
63
+ "F_Shouting": "voices/cleo-shouting.mp3",
64
+ "F_Terrified": "voices/cleo-terrified.mp3",
65
+ "F_Unfriendly": "voices/cleo-unfriendly.mp3",
66
+ "F_Whispering": "voices/cleo-whispering.mp3",
67
+ }
68
+ self.model.set_utterance_embedding(
69
+ self.speaker_path_lookup[self.current_speaker]
70
+ )
71
+
72
+ def read(self, prompt, language, accent, speaker, gender):
73
+ language = language.split()[0]
74
+ accent = accent.split()[0]
75
+ if self.current_language != language:
76
+ self.model.set_phonemizer_language(self.language_id_lookup[language])
77
+ self.current_language = language
78
+ if self.current_accent != accent:
79
+ self.model.set_accent_language(self.language_id_lookup[accent])
80
+ self.current_accent = accent
81
+ speaker = (gender[0]) + "_" + speaker
82
+ if self.current_speaker != speaker:
83
+ self.model.set_utterance_embedding(self.speaker_path_lookup[speaker])
84
+ self.current_speaker = speaker
85
+
86
+ phones = self.model.text2phone.get_phone_string(prompt)
87
+ if len(phones) > 1800:
88
+ if language == "English":
89
+ prompt = "Your input was too long. Please try either a shorter text or split it into several parts."
90
+ elif language == "German":
91
+ prompt = "Deine Eingabe war zu lang. Bitte versuche es entweder mit einem kürzeren Text oder teile ihn in mehrere Teile auf."
92
+ elif language == "Greek":
93
+ prompt = "Η εισήγησή σας ήταν πολύ μεγάλη. Παρακαλώ δοκιμάστε είτε ένα μικρότερο κείμενο είτε χωρίστε το σε διάφορα μέρη."
94
+ elif language == "Spanish":
95
+ prompt = "Su entrada es demasiado larga. Por favor, intente un texto más corto o divídalo en varias partes."
96
+ elif language == "Finnish":
97
+ prompt = "Vastauksesi oli liian pitkä. Kokeile joko lyhyempää tekstiä tai jaa se useampaan osaan."
98
+ elif language == "Russian":
99
+ prompt = "Ваш текст слишком длинный. Пожалуйста, попробуйте либо сократить текст, либо разделить его на несколько частей."
100
+ elif language == "Hungarian":
101
+ prompt = "Túl hosszú volt a bevitele. Kérjük, próbáljon meg rövidebb szöveget írni, vagy ossza több részre."
102
+ elif language == "Dutch":
103
+ prompt = "Uw input was te lang. Probeer een kortere tekst of splits het in verschillende delen."
104
+ elif language == "French":
105
+ prompt = "Votre saisie était trop longue. Veuillez essayer un texte plus court ou le diviser en plusieurs parties."
106
+ elif language == "Polish":
107
+ prompt = "Twój wpis był zbyt długi. Spróbuj skrócić tekst lub podzielić go na kilka części."
108
+ elif language == "Portuguese":
109
+ prompt = "O seu contributo foi demasiado longo. Por favor, tente um texto mais curto ou divida-o em várias partes."
110
+ elif language == "Italian":
111
+ prompt = "Il tuo input era troppo lungo. Per favore, prova un testo più corto o dividilo in più parti."
112
+ phones = self.model.text2phone.get_phone_string(prompt)
113
+
114
+ wav = self.model(phones)
115
+
116
+ wav = emotion(wav, self.current_speaker)
117
+
118
+ return 48000, float2pcm(wav.cpu().numpy())
119
+
120
+
121
+ meta_model = TTS_Interface()
122
+ article = "<p style='text-align: left'></a></p>"
123
+
124
+ iface = gr.Interface(
125
+ fn=meta_model.read,
126
+ inputs=[
127
+ gr.inputs.Textbox(
128
+ lines=2,
129
+ placeholder="write what you want the synthesis to read here... \n(to prevent out of memory errors, too long inputs get replaced with a placeholder)",
130
+ label="Text input",
131
+ ),
132
+ gr.inputs.Dropdown(
133
+ [
134
+ "English Text",
135
+ "German Text",
136
+ "Greek Text",
137
+ "Spanish Text",
138
+ "Finnish Text",
139
+ "Russian Text",
140
+ "Hungarian Text",
141
+ "Dutch Text",
142
+ "French Text",
143
+ "Polish Text",
144
+ "Portuguese Text",
145
+ "Italian Text",
146
+ ],
147
+ type="value",
148
+ default="English Text",
149
+ label="Select the Language of the Text",
150
+ ),
151
+ gr.inputs.Dropdown(
152
+ [
153
+ "English Accent",
154
+ "German Accent",
155
+ "Greek Accent",
156
+ "Spanish Accent",
157
+ "Finnish Accent",
158
+ "Russian Accent",
159
+ "Hungarian Accent",
160
+ "Dutch Accent",
161
+ "French Accent",
162
+ "Polish Accent",
163
+ "Portuguese Accent",
164
+ "Italian Accent",
165
+ ],
166
+ type="value",
167
+ default="English Accent",
168
+ label="Select the Accent of the Speaker",
169
+ ),
170
+ gr.inputs.Dropdown(
171
+ [
172
+ "Angry",
173
+ "Sad",
174
+ "Cheerful",
175
+ "Excited",
176
+ "Friendly",
177
+ "Hopeful",
178
+ "Normal",
179
+ "Shouting",
180
+ "Terrified",
181
+ "Unfriendly",
182
+ "Whispering",
183
+ ],
184
+ type="value",
185
+ default="Angry",
186
+ label="Select the Voice of the Speaker",
187
+ ),
188
+ gr.inputs.Dropdown(
189
+ ["Male", "Female"], type="value", default="Male", label="Select the gender"
190
+ ),
191
+ ],
192
+ outputs=gr.outputs.Audio(type="numpy", label=None),
193
+ layout="vertical",
194
+ title="",
195
+ theme="default",
196
+ allow_flagging="never",
197
+ allow_screenshot=False,
198
+ article=article,
199
+ )
200
+ iface.launch(server_name="0.0.0.0", enable_queue=True)
reference_audios/__init__.py ADDED
File without changes
reference_audios/andrew-angry.mp3 ADDED
Binary file (139 kB). View file
 
reference_audios/andrew-cheerful.mp3 ADDED
Binary file (192 kB). View file
 
reference_audios/andrew-excited.mp3 ADDED
Binary file (113 kB). View file
 
reference_audios/andrew-friendly.mp3 ADDED
Binary file (119 kB). View file
 
reference_audios/andrew-hopeful.mp3 ADDED
Binary file (150 kB). View file
 
reference_audios/andrew-normal.mp3 ADDED
Binary file (121 kB). View file
 
reference_audios/andrew-sad.mp3 ADDED
Binary file (261 kB). View file
 
reference_audios/andrew-shouting.mp3 ADDED
Binary file (128 kB). View file
 
reference_audios/andrew-terrified.mp3 ADDED
Binary file (161 kB). View file
 
reference_audios/andrew-unfriendly.mp3 ADDED
Binary file (136 kB). View file
 
reference_audios/andrew-whispering.mp3 ADDED
Binary file (177 kB). View file
 
reference_audios/italian.flac ADDED
Binary file (281 kB). View file
 
reference_audios/polish.flac ADDED
Binary file (230 kB). View file