diff --git a/rvc/configs/__pycache__/config.cpython-39.pyc b/rvc/configs/__pycache__/config.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..85acb51da6fe06d7cc58cf6fe1e7b389d1444c5f
Binary files /dev/null and b/rvc/configs/__pycache__/config.cpython-39.pyc differ
diff --git a/rvc/infer/__pycache__/vc_infer_pipeline.cpython-39.pyc b/rvc/infer/__pycache__/vc_infer_pipeline.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..947225b730490f3b1c535c9c7428367c8bd21edb
Binary files /dev/null and b/rvc/infer/__pycache__/vc_infer_pipeline.cpython-39.pyc differ
diff --git a/rvc/lib/__pycache__/rmvpe.cpython-39.pyc b/rvc/lib/__pycache__/rmvpe.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..0060f03098719dad3dd09106c4b10579a916985c
Binary files /dev/null and b/rvc/lib/__pycache__/rmvpe.cpython-39.pyc differ
diff --git a/rvc/lib/__pycache__/utils.cpython-39.pyc b/rvc/lib/__pycache__/utils.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d2c82aaa8e272d3da9de6ddff6b0578fba818b3f
Binary files /dev/null and b/rvc/lib/__pycache__/utils.cpython-39.pyc differ
diff --git a/rvc/lib/infer_pack/__init__.py b/rvc/lib/infer_pack/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rvc/lib/infer_pack/__pycache__/__init__.cpython-39.pyc b/rvc/lib/infer_pack/__pycache__/__init__.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..6816c3fb68d24ccd53385f792e505169bd60866f
Binary files /dev/null and b/rvc/lib/infer_pack/__pycache__/__init__.cpython-39.pyc differ
diff --git a/rvc/lib/infer_pack/__pycache__/attentions.cpython-39.pyc b/rvc/lib/infer_pack/__pycache__/attentions.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..8a2cea32cc7281d428d6dbf4bde370bac2b27696
Binary files /dev/null and b/rvc/lib/infer_pack/__pycache__/attentions.cpython-39.pyc differ
diff --git a/rvc/lib/infer_pack/__pycache__/commons.cpython-39.pyc b/rvc/lib/infer_pack/__pycache__/commons.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ff5e366f204db5fce9fc42bd561c0ae88e95e886
Binary files /dev/null and b/rvc/lib/infer_pack/__pycache__/commons.cpython-39.pyc differ
diff --git a/rvc/lib/infer_pack/__pycache__/models.cpython-39.pyc b/rvc/lib/infer_pack/__pycache__/models.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bcf34a5faccab4ea447b7a2abc849282948711dd
Binary files /dev/null and b/rvc/lib/infer_pack/__pycache__/models.cpython-39.pyc differ
diff --git a/rvc/lib/infer_pack/__pycache__/modules.cpython-39.pyc b/rvc/lib/infer_pack/__pycache__/modules.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..430f0447cab62126a8b8a6c1cfb16a0c143100df
Binary files /dev/null and b/rvc/lib/infer_pack/__pycache__/modules.cpython-39.pyc differ
diff --git a/rvc/lib/infer_pack/__pycache__/transforms.cpython-39.pyc b/rvc/lib/infer_pack/__pycache__/transforms.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..476a784738e394f70788b570eedee9f5c2ff0588
Binary files /dev/null and b/rvc/lib/infer_pack/__pycache__/transforms.cpython-39.pyc differ
diff --git a/rvc/lib/infer_pack/attentions.py b/rvc/lib/infer_pack/attentions.py
new file mode 100644
index 0000000000000000000000000000000000000000..ea728e241c5c50fd516af78d0e7a059b5a6f6991
--- /dev/null
+++ b/rvc/lib/infer_pack/attentions.py
@@ -0,0 +1,398 @@
+import math
+import torch
+from torch import nn
+from torch.nn import functional as F
+
+from . import commons
+from .modules import LayerNorm
+
+
+class Encoder(nn.Module):
+ def __init__(
+ self,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size=1,
+ p_dropout=0.0,
+ window_size=10,
+ **kwargs
+ ):
+ super().__init__()
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = p_dropout
+ self.window_size = window_size
+
+ self.drop = nn.Dropout(p_dropout)
+ self.attn_layers = nn.ModuleList()
+ self.norm_layers_1 = nn.ModuleList()
+ self.ffn_layers = nn.ModuleList()
+ self.norm_layers_2 = nn.ModuleList()
+ for i in range(self.n_layers):
+ self.attn_layers.append(
+ MultiHeadAttention(
+ hidden_channels,
+ hidden_channels,
+ n_heads,
+ p_dropout=p_dropout,
+ window_size=window_size,
+ )
+ )
+ self.norm_layers_1.append(LayerNorm(hidden_channels))
+ self.ffn_layers.append(
+ FFN(
+ hidden_channels,
+ hidden_channels,
+ filter_channels,
+ kernel_size,
+ p_dropout=p_dropout,
+ )
+ )
+ self.norm_layers_2.append(LayerNorm(hidden_channels))
+
+ def forward(self, x, x_mask):
+ attn_mask = x_mask.unsqueeze(2) * x_mask.unsqueeze(-1)
+ x = x * x_mask
+ for i in range(self.n_layers):
+ y = self.attn_layers[i](x, x, attn_mask)
+ y = self.drop(y)
+ x = self.norm_layers_1[i](x + y)
+
+ y = self.ffn_layers[i](x, x_mask)
+ y = self.drop(y)
+ x = self.norm_layers_2[i](x + y)
+ x = x * x_mask
+ return x
+
+
+class Decoder(nn.Module):
+ def __init__(
+ self,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size=1,
+ p_dropout=0.0,
+ proximal_bias=False,
+ proximal_init=True,
+ **kwargs
+ ):
+ super().__init__()
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = p_dropout
+ self.proximal_bias = proximal_bias
+ self.proximal_init = proximal_init
+
+ self.drop = nn.Dropout(p_dropout)
+ self.self_attn_layers = nn.ModuleList()
+ self.norm_layers_0 = nn.ModuleList()
+ self.encdec_attn_layers = nn.ModuleList()
+ self.norm_layers_1 = nn.ModuleList()
+ self.ffn_layers = nn.ModuleList()
+ self.norm_layers_2 = nn.ModuleList()
+ for i in range(self.n_layers):
+ self.self_attn_layers.append(
+ MultiHeadAttention(
+ hidden_channels,
+ hidden_channels,
+ n_heads,
+ p_dropout=p_dropout,
+ proximal_bias=proximal_bias,
+ proximal_init=proximal_init,
+ )
+ )
+ self.norm_layers_0.append(LayerNorm(hidden_channels))
+ self.encdec_attn_layers.append(
+ MultiHeadAttention(
+ hidden_channels, hidden_channels, n_heads, p_dropout=p_dropout
+ )
+ )
+ self.norm_layers_1.append(LayerNorm(hidden_channels))
+ self.ffn_layers.append(
+ FFN(
+ hidden_channels,
+ hidden_channels,
+ filter_channels,
+ kernel_size,
+ p_dropout=p_dropout,
+ causal=True,
+ )
+ )
+ self.norm_layers_2.append(LayerNorm(hidden_channels))
+
+ def forward(self, x, x_mask, h, h_mask):
+ """
+ x: decoder input
+ h: encoder output
+ """
+ self_attn_mask = commons.subsequent_mask(x_mask.size(2)).to(
+ device=x.device, dtype=x.dtype
+ )
+ encdec_attn_mask = h_mask.unsqueeze(2) * x_mask.unsqueeze(-1)
+ x = x * x_mask
+ for i in range(self.n_layers):
+ y = self.self_attn_layers[i](x, x, self_attn_mask)
+ y = self.drop(y)
+ x = self.norm_layers_0[i](x + y)
+
+ y = self.encdec_attn_layers[i](x, h, encdec_attn_mask)
+ y = self.drop(y)
+ x = self.norm_layers_1[i](x + y)
+
+ y = self.ffn_layers[i](x, x_mask)
+ y = self.drop(y)
+ x = self.norm_layers_2[i](x + y)
+ x = x * x_mask
+ return x
+
+
+class MultiHeadAttention(nn.Module):
+ def __init__(
+ self,
+ channels,
+ out_channels,
+ n_heads,
+ p_dropout=0.0,
+ window_size=None,
+ heads_share=True,
+ block_length=None,
+ proximal_bias=False,
+ proximal_init=False,
+ ):
+ super().__init__()
+ assert channels % n_heads == 0
+
+ self.channels = channels
+ self.out_channels = out_channels
+ self.n_heads = n_heads
+ self.p_dropout = p_dropout
+ self.window_size = window_size
+ self.heads_share = heads_share
+ self.block_length = block_length
+ self.proximal_bias = proximal_bias
+ self.proximal_init = proximal_init
+ self.attn = None
+
+ self.k_channels = channels // n_heads
+ self.conv_q = nn.Conv1d(channels, channels, 1)
+ self.conv_k = nn.Conv1d(channels, channels, 1)
+ self.conv_v = nn.Conv1d(channels, channels, 1)
+ self.conv_o = nn.Conv1d(channels, out_channels, 1)
+ self.drop = nn.Dropout(p_dropout)
+
+ if window_size is not None:
+ n_heads_rel = 1 if heads_share else n_heads
+ rel_stddev = self.k_channels**-0.5
+ self.emb_rel_k = nn.Parameter(
+ torch.randn(n_heads_rel, window_size * 2 + 1, self.k_channels)
+ * rel_stddev
+ )
+ self.emb_rel_v = nn.Parameter(
+ torch.randn(n_heads_rel, window_size * 2 + 1, self.k_channels)
+ * rel_stddev
+ )
+
+ nn.init.xavier_uniform_(self.conv_q.weight)
+ nn.init.xavier_uniform_(self.conv_k.weight)
+ nn.init.xavier_uniform_(self.conv_v.weight)
+ if proximal_init:
+ with torch.no_grad():
+ self.conv_k.weight.copy_(self.conv_q.weight)
+ self.conv_k.bias.copy_(self.conv_q.bias)
+
+ def forward(self, x, c, attn_mask=None):
+ q = self.conv_q(x)
+ k = self.conv_k(c)
+ v = self.conv_v(c)
+
+ x, self.attn = self.attention(q, k, v, mask=attn_mask)
+
+ x = self.conv_o(x)
+ return x
+
+ def attention(self, query, key, value, mask=None):
+ b, d, t_s, t_t = (*key.size(), query.size(2))
+ query = query.view(b, self.n_heads, self.k_channels, t_t).transpose(2, 3)
+ key = key.view(b, self.n_heads, self.k_channels, t_s).transpose(2, 3)
+ value = value.view(b, self.n_heads, self.k_channels, t_s).transpose(2, 3)
+
+ scores = torch.matmul(query / math.sqrt(self.k_channels), key.transpose(-2, -1))
+ if self.window_size is not None:
+ assert (
+ t_s == t_t
+ ), "Relative attention is only available for self-attention."
+ key_relative_embeddings = self._get_relative_embeddings(self.emb_rel_k, t_s)
+ rel_logits = self._matmul_with_relative_keys(
+ query / math.sqrt(self.k_channels), key_relative_embeddings
+ )
+ scores_local = self._relative_position_to_absolute_position(rel_logits)
+ scores = scores + scores_local
+ if self.proximal_bias:
+ assert t_s == t_t, "Proximal bias is only available for self-attention."
+ scores = scores + self._attention_bias_proximal(t_s).to(
+ device=scores.device, dtype=scores.dtype
+ )
+ if mask is not None:
+ scores = scores.masked_fill(mask == 0, -1e4)
+ if self.block_length is not None:
+ assert (
+ t_s == t_t
+ ), "Local attention is only available for self-attention."
+ block_mask = (
+ torch.ones_like(scores)
+ .triu(-self.block_length)
+ .tril(self.block_length)
+ )
+ scores = scores.masked_fill(block_mask == 0, -1e4)
+ p_attn = F.softmax(scores, dim=-1)
+ p_attn = self.drop(p_attn)
+ output = torch.matmul(p_attn, value)
+ if self.window_size is not None:
+ relative_weights = self._absolute_position_to_relative_position(p_attn)
+ value_relative_embeddings = self._get_relative_embeddings(
+ self.emb_rel_v, t_s
+ )
+ output = output + self._matmul_with_relative_values(
+ relative_weights, value_relative_embeddings
+ )
+ output = output.transpose(2, 3).contiguous().view(b, d, t_t)
+ return output, p_attn
+
+ def _matmul_with_relative_values(self, x, y):
+ """
+ x: [b, h, l, m]
+ y: [h or 1, m, d]
+ ret: [b, h, l, d]
+ """
+ ret = torch.matmul(x, y.unsqueeze(0))
+ return ret
+
+ def _matmul_with_relative_keys(self, x, y):
+ """
+ x: [b, h, l, d]
+ y: [h or 1, m, d]
+ ret: [b, h, l, m]
+ """
+ ret = torch.matmul(x, y.unsqueeze(0).transpose(-2, -1))
+ return ret
+
+ def _get_relative_embeddings(self, relative_embeddings, length):
+ pad_length = max(length - (self.window_size + 1), 0)
+ slice_start_position = max((self.window_size + 1) - length, 0)
+ slice_end_position = slice_start_position + 2 * length - 1
+ if pad_length > 0:
+ padded_relative_embeddings = F.pad(
+ relative_embeddings,
+ commons.convert_pad_shape([[0, 0], [pad_length, pad_length], [0, 0]]),
+ )
+ else:
+ padded_relative_embeddings = relative_embeddings
+ used_relative_embeddings = padded_relative_embeddings[
+ :, slice_start_position:slice_end_position
+ ]
+ return used_relative_embeddings
+
+ def _relative_position_to_absolute_position(self, x):
+ """
+ x: [b, h, l, 2*l-1]
+ ret: [b, h, l, l]
+ """
+ batch, heads, length, _ = x.size()
+
+ x = F.pad(x, commons.convert_pad_shape([[0, 0], [0, 0], [0, 0], [0, 1]]))
+ x_flat = x.view([batch, heads, length * 2 * length])
+ x_flat = F.pad(
+ x_flat, commons.convert_pad_shape([[0, 0], [0, 0], [0, length - 1]])
+ )
+
+ x_final = x_flat.view([batch, heads, length + 1, 2 * length - 1])[
+ :, :, :length, length - 1 :
+ ]
+ return x_final
+
+ def _absolute_position_to_relative_position(self, x):
+ """
+ x: [b, h, l, l]
+ ret: [b, h, l, 2*l-1]
+ """
+ batch, heads, length, _ = x.size()
+ x = F.pad(
+ x, commons.convert_pad_shape([[0, 0], [0, 0], [0, 0], [0, length - 1]])
+ )
+ x_flat = x.view([batch, heads, length**2 + length * (length - 1)])
+ x_flat = F.pad(x_flat, commons.convert_pad_shape([[0, 0], [0, 0], [length, 0]]))
+ x_final = x_flat.view([batch, heads, length, 2 * length])[:, :, :, 1:]
+ return x_final
+
+ def _attention_bias_proximal(self, length):
+ r = torch.arange(length, dtype=torch.float32)
+ diff = torch.unsqueeze(r, 0) - torch.unsqueeze(r, 1)
+ return torch.unsqueeze(torch.unsqueeze(-torch.log1p(torch.abs(diff)), 0), 0)
+
+
+class FFN(nn.Module):
+ def __init__(
+ self,
+ in_channels,
+ out_channels,
+ filter_channels,
+ kernel_size,
+ p_dropout=0.0,
+ activation=None,
+ causal=False,
+ ):
+ super().__init__()
+ self.in_channels = in_channels
+ self.out_channels = out_channels
+ self.filter_channels = filter_channels
+ self.kernel_size = kernel_size
+ self.p_dropout = p_dropout
+ self.activation = activation
+ self.causal = causal
+
+ if causal:
+ self.padding = self._causal_padding
+ else:
+ self.padding = self._same_padding
+
+ self.conv_1 = nn.Conv1d(in_channels, filter_channels, kernel_size)
+ self.conv_2 = nn.Conv1d(filter_channels, out_channels, kernel_size)
+ self.drop = nn.Dropout(p_dropout)
+
+ def forward(self, x, x_mask):
+ x = self.conv_1(self.padding(x * x_mask))
+ if self.activation == "gelu":
+ x = x * torch.sigmoid(1.702 * x)
+ else:
+ x = torch.relu(x)
+ x = self.drop(x)
+ x = self.conv_2(self.padding(x * x_mask))
+ return x * x_mask
+
+ def _causal_padding(self, x):
+ if self.kernel_size == 1:
+ return x
+ pad_l = self.kernel_size - 1
+ pad_r = 0
+ padding = [[0, 0], [0, 0], [pad_l, pad_r]]
+ x = F.pad(x, commons.convert_pad_shape(padding))
+ return x
+
+ def _same_padding(self, x):
+ if self.kernel_size == 1:
+ return x
+ pad_l = (self.kernel_size - 1) // 2
+ pad_r = self.kernel_size // 2
+ padding = [[0, 0], [0, 0], [pad_l, pad_r]]
+ x = F.pad(x, commons.convert_pad_shape(padding))
+ return x
diff --git a/rvc/lib/infer_pack/commons.py b/rvc/lib/infer_pack/commons.py
new file mode 100644
index 0000000000000000000000000000000000000000..54470986f37825b35d90d7efa7437d1c26b87215
--- /dev/null
+++ b/rvc/lib/infer_pack/commons.py
@@ -0,0 +1,166 @@
+import math
+import numpy as np
+import torch
+from torch import nn
+from torch.nn import functional as F
+
+
+def init_weights(m, mean=0.0, std=0.01):
+ classname = m.__class__.__name__
+ if classname.find("Conv") != -1:
+ m.weight.data.normal_(mean, std)
+
+
+def get_padding(kernel_size, dilation=1):
+ return int((kernel_size * dilation - dilation) / 2)
+
+
+def convert_pad_shape(pad_shape):
+ l = pad_shape[::-1]
+ pad_shape = [item for sublist in l for item in sublist]
+ return pad_shape
+
+
+def kl_divergence(m_p, logs_p, m_q, logs_q):
+ """KL(P||Q)"""
+ kl = (logs_q - logs_p) - 0.5
+ kl += (
+ 0.5 * (torch.exp(2.0 * logs_p) + ((m_p - m_q) ** 2)) * torch.exp(-2.0 * logs_q)
+ )
+ return kl
+
+
+def rand_gumbel(shape):
+ """Sample from the Gumbel distribution, protect from overflows."""
+ uniform_samples = torch.rand(shape) * 0.99998 + 0.00001
+ return -torch.log(-torch.log(uniform_samples))
+
+
+def rand_gumbel_like(x):
+ g = rand_gumbel(x.size()).to(dtype=x.dtype, device=x.device)
+ return g
+
+
+def slice_segments(x, ids_str, segment_size=4):
+ ret = torch.zeros_like(x[:, :, :segment_size])
+ for i in range(x.size(0)):
+ idx_str = ids_str[i]
+ idx_end = idx_str + segment_size
+ ret[i] = x[i, :, idx_str:idx_end]
+ return ret
+
+
+def slice_segments2(x, ids_str, segment_size=4):
+ ret = torch.zeros_like(x[:, :segment_size])
+ for i in range(x.size(0)):
+ idx_str = ids_str[i]
+ idx_end = idx_str + segment_size
+ ret[i] = x[i, idx_str:idx_end]
+ return ret
+
+
+def rand_slice_segments(x, x_lengths=None, segment_size=4):
+ b, d, t = x.size()
+ if x_lengths is None:
+ x_lengths = t
+ ids_str_max = x_lengths - segment_size + 1
+ ids_str = (torch.rand([b]).to(device=x.device) * ids_str_max).to(dtype=torch.long)
+ ret = slice_segments(x, ids_str, segment_size)
+ return ret, ids_str
+
+
+def get_timing_signal_1d(length, channels, min_timescale=1.0, max_timescale=1.0e4):
+ position = torch.arange(length, dtype=torch.float)
+ num_timescales = channels // 2
+ log_timescale_increment = math.log(float(max_timescale) / float(min_timescale)) / (
+ num_timescales - 1
+ )
+ inv_timescales = min_timescale * torch.exp(
+ torch.arange(num_timescales, dtype=torch.float) * -log_timescale_increment
+ )
+ scaled_time = position.unsqueeze(0) * inv_timescales.unsqueeze(1)
+ signal = torch.cat([torch.sin(scaled_time), torch.cos(scaled_time)], 0)
+ signal = F.pad(signal, [0, 0, 0, channels % 2])
+ signal = signal.view(1, channels, length)
+ return signal
+
+
+def add_timing_signal_1d(x, min_timescale=1.0, max_timescale=1.0e4):
+ b, channels, length = x.size()
+ signal = get_timing_signal_1d(length, channels, min_timescale, max_timescale)
+ return x + signal.to(dtype=x.dtype, device=x.device)
+
+
+def cat_timing_signal_1d(x, min_timescale=1.0, max_timescale=1.0e4, axis=1):
+ b, channels, length = x.size()
+ signal = get_timing_signal_1d(length, channels, min_timescale, max_timescale)
+ return torch.cat([x, signal.to(dtype=x.dtype, device=x.device)], axis)
+
+
+def subsequent_mask(length):
+ mask = torch.tril(torch.ones(length, length)).unsqueeze(0).unsqueeze(0)
+ return mask
+
+
+@torch.jit.script
+def fused_add_tanh_sigmoid_multiply(input_a, input_b, n_channels):
+ n_channels_int = n_channels[0]
+ in_act = input_a + input_b
+ t_act = torch.tanh(in_act[:, :n_channels_int, :])
+ s_act = torch.sigmoid(in_act[:, n_channels_int:, :])
+ acts = t_act * s_act
+ return acts
+
+
+def convert_pad_shape(pad_shape):
+ l = pad_shape[::-1]
+ pad_shape = [item for sublist in l for item in sublist]
+ return pad_shape
+
+
+def shift_1d(x):
+ x = F.pad(x, convert_pad_shape([[0, 0], [0, 0], [1, 0]]))[:, :, :-1]
+ return x
+
+
+def sequence_mask(length, max_length=None):
+ if max_length is None:
+ max_length = length.max()
+ x = torch.arange(max_length, dtype=length.dtype, device=length.device)
+ return x.unsqueeze(0) < length.unsqueeze(1)
+
+
+def generate_path(duration, mask):
+ """
+ duration: [b, 1, t_x]
+ mask: [b, 1, t_y, t_x]
+ """
+ device = duration.device
+
+ b, _, t_y, t_x = mask.shape
+ cum_duration = torch.cumsum(duration, -1)
+
+ cum_duration_flat = cum_duration.view(b * t_x)
+ path = sequence_mask(cum_duration_flat, t_y).to(mask.dtype)
+ path = path.view(b, t_x, t_y)
+ path = path - F.pad(path, convert_pad_shape([[0, 0], [1, 0], [0, 0]]))[:, :-1]
+ path = path.unsqueeze(1).transpose(2, 3) * mask
+ return path
+
+
+def clip_grad_value_(parameters, clip_value, norm_type=2):
+ if isinstance(parameters, torch.Tensor):
+ parameters = [parameters]
+ parameters = list(filter(lambda p: p.grad is not None, parameters))
+ norm_type = float(norm_type)
+ if clip_value is not None:
+ clip_value = float(clip_value)
+
+ total_norm = 0
+ for p in parameters:
+ param_norm = p.grad.data.norm(norm_type)
+ total_norm += param_norm.item() ** norm_type
+ if clip_value is not None:
+ p.grad.data.clamp_(min=-clip_value, max=clip_value)
+ total_norm = total_norm ** (1.0 / norm_type)
+ return total_norm
diff --git a/rvc/lib/infer_pack/models.py b/rvc/lib/infer_pack/models.py
new file mode 100644
index 0000000000000000000000000000000000000000..880b53f7d2790caba572ecc83cd92987deefcf8b
--- /dev/null
+++ b/rvc/lib/infer_pack/models.py
@@ -0,0 +1,1393 @@
+import math
+import torch
+from torch import nn
+from torch.nn import functional as F
+from . import modules
+from . import attentions
+from . import commons
+from .commons import init_weights, get_padding
+from torch.nn import Conv1d, ConvTranspose1d, Conv2d
+from torch.nn.utils import remove_weight_norm
+from torch.nn.utils.parametrizations import spectral_norm, weight_norm
+from typing import Optional
+
+has_xpu = bool(hasattr(torch, "xpu") and torch.xpu.is_available())
+
+
+class TextEncoder256(nn.Module):
+ def __init__(
+ self,
+ out_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ p_dropout,
+ f0=True,
+ ):
+ super(TextEncoder256, self).__init__()
+ self.out_channels = out_channels
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = float(p_dropout)
+ self.emb_phone = nn.Linear(256, hidden_channels)
+ self.lrelu = nn.LeakyReLU(0.1, inplace=True)
+ if f0 == True:
+ self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
+ self.encoder = attentions.Encoder(
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ float(p_dropout),
+ )
+ self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
+
+ def forward(
+ self, phone: torch.Tensor, pitch: Optional[torch.Tensor], lengths: torch.Tensor
+ ):
+ if pitch is None:
+ x = self.emb_phone(phone)
+ else:
+ x = self.emb_phone(phone) + self.emb_pitch(pitch)
+ x = x * math.sqrt(self.hidden_channels) # [b, t, h]
+ x = self.lrelu(x)
+ x = torch.transpose(x, 1, -1) # [b, h, t]
+ x_mask = torch.unsqueeze(commons.sequence_mask(lengths, x.size(2)), 1).to(
+ x.dtype
+ )
+ x = self.encoder(x * x_mask, x_mask)
+ stats = self.proj(x) * x_mask
+
+ m, logs = torch.split(stats, self.out_channels, dim=1)
+ return m, logs, x_mask
+
+
+class TextEncoder768(nn.Module):
+ def __init__(
+ self,
+ out_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ p_dropout,
+ f0=True,
+ ):
+ super(TextEncoder768, self).__init__()
+ self.out_channels = out_channels
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = float(p_dropout)
+ self.emb_phone = nn.Linear(768, hidden_channels)
+ self.lrelu = nn.LeakyReLU(0.1, inplace=True)
+ if f0 == True:
+ self.emb_pitch = nn.Embedding(256, hidden_channels) # pitch 256
+ self.encoder = attentions.Encoder(
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ float(p_dropout),
+ )
+ self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
+
+ def forward(self, phone: torch.Tensor, pitch: torch.Tensor, lengths: torch.Tensor):
+ if pitch is None:
+ x = self.emb_phone(phone)
+ else:
+ x = self.emb_phone(phone) + self.emb_pitch(pitch)
+ x = x * math.sqrt(self.hidden_channels) # [b, t, h]
+ x = self.lrelu(x)
+ x = torch.transpose(x, 1, -1) # [b, h, t]
+ x_mask = torch.unsqueeze(commons.sequence_mask(lengths, x.size(2)), 1).to(
+ x.dtype
+ )
+ x = self.encoder(x * x_mask, x_mask)
+ stats = self.proj(x) * x_mask
+
+ m, logs = torch.split(stats, self.out_channels, dim=1)
+ return m, logs, x_mask
+
+
+class ResidualCouplingBlock(nn.Module):
+ def __init__(
+ self,
+ channels,
+ hidden_channels,
+ kernel_size,
+ dilation_rate,
+ n_layers,
+ n_flows=4,
+ gin_channels=0,
+ ):
+ super(ResidualCouplingBlock, self).__init__()
+ self.channels = channels
+ self.hidden_channels = hidden_channels
+ self.kernel_size = kernel_size
+ self.dilation_rate = dilation_rate
+ self.n_layers = n_layers
+ self.n_flows = n_flows
+ self.gin_channels = gin_channels
+
+ self.flows = nn.ModuleList()
+ for i in range(n_flows):
+ self.flows.append(
+ modules.ResidualCouplingLayer(
+ channels,
+ hidden_channels,
+ kernel_size,
+ dilation_rate,
+ n_layers,
+ gin_channels=gin_channels,
+ mean_only=True,
+ )
+ )
+ self.flows.append(modules.Flip())
+
+ def forward(
+ self,
+ x: torch.Tensor,
+ x_mask: torch.Tensor,
+ g: Optional[torch.Tensor] = None,
+ reverse: bool = False,
+ ):
+ if not reverse:
+ for flow in self.flows:
+ x, _ = flow(x, x_mask, g=g, reverse=reverse)
+ else:
+ for flow in self.flows[::-1]:
+ x = flow.forward(x, x_mask, g=g, reverse=reverse)
+ return x
+
+ def remove_weight_norm(self):
+ for i in range(self.n_flows):
+ self.flows[i * 2].remove_weight_norm()
+
+ def __prepare_scriptable__(self):
+ for i in range(self.n_flows):
+ for hook in self.flows[i * 2]._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.flows[i * 2])
+
+ return self
+
+
+class PosteriorEncoder(nn.Module):
+ def __init__(
+ self,
+ in_channels,
+ out_channels,
+ hidden_channels,
+ kernel_size,
+ dilation_rate,
+ n_layers,
+ gin_channels=0,
+ ):
+ super(PosteriorEncoder, self).__init__()
+ self.in_channels = in_channels
+ self.out_channels = out_channels
+ self.hidden_channels = hidden_channels
+ self.kernel_size = kernel_size
+ self.dilation_rate = dilation_rate
+ self.n_layers = n_layers
+ self.gin_channels = gin_channels
+
+ self.pre = nn.Conv1d(in_channels, hidden_channels, 1)
+ self.enc = modules.WN(
+ hidden_channels,
+ kernel_size,
+ dilation_rate,
+ n_layers,
+ gin_channels=gin_channels,
+ )
+ self.proj = nn.Conv1d(hidden_channels, out_channels * 2, 1)
+
+ def forward(
+ self, x: torch.Tensor, x_lengths: torch.Tensor, g: Optional[torch.Tensor] = None
+ ):
+ x_mask = torch.unsqueeze(commons.sequence_mask(x_lengths, x.size(2)), 1).to(
+ x.dtype
+ )
+ x = self.pre(x) * x_mask
+ x = self.enc(x, x_mask, g=g)
+ stats = self.proj(x) * x_mask
+ m, logs = torch.split(stats, self.out_channels, dim=1)
+ z = (m + torch.randn_like(m) * torch.exp(logs)) * x_mask
+ return z, m, logs, x_mask
+
+ def remove_weight_norm(self):
+ self.enc.remove_weight_norm()
+
+ def __prepare_scriptable__(self):
+ for hook in self.enc._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.enc)
+ return self
+
+
+class Generator(torch.nn.Module):
+ def __init__(
+ self,
+ initial_channel,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ gin_channels=0,
+ ):
+ super(Generator, self).__init__()
+ self.num_kernels = len(resblock_kernel_sizes)
+ self.num_upsamples = len(upsample_rates)
+ self.conv_pre = Conv1d(
+ initial_channel, upsample_initial_channel, 7, 1, padding=3
+ )
+ resblock = modules.ResBlock1 if resblock == "1" else modules.ResBlock2
+
+ self.ups = nn.ModuleList()
+ for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
+ self.ups.append(
+ weight_norm(
+ ConvTranspose1d(
+ upsample_initial_channel // (2**i),
+ upsample_initial_channel // (2 ** (i + 1)),
+ k,
+ u,
+ padding=(k - u) // 2,
+ )
+ )
+ )
+
+ self.resblocks = nn.ModuleList()
+ for i in range(len(self.ups)):
+ ch = upsample_initial_channel // (2 ** (i + 1))
+ for j, (k, d) in enumerate(
+ zip(resblock_kernel_sizes, resblock_dilation_sizes)
+ ):
+ self.resblocks.append(resblock(ch, k, d))
+
+ self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
+ self.ups.apply(init_weights)
+
+ if gin_channels != 0:
+ self.cond = nn.Conv1d(gin_channels, upsample_initial_channel, 1)
+
+ def forward(self, x: torch.Tensor, g: Optional[torch.Tensor] = None):
+ x = self.conv_pre(x)
+ if g is not None:
+ x = x + self.cond(g)
+
+ for i in range(self.num_upsamples):
+ x = F.leaky_relu(x, modules.LRELU_SLOPE)
+ x = self.ups[i](x)
+ xs = None
+ for j in range(self.num_kernels):
+ if xs is None:
+ xs = self.resblocks[i * self.num_kernels + j](x)
+ else:
+ xs += self.resblocks[i * self.num_kernels + j](x)
+ x = xs / self.num_kernels
+ x = F.leaky_relu(x)
+ x = self.conv_post(x)
+ x = torch.tanh(x)
+
+ return x
+
+ def __prepare_scriptable__(self):
+ for l in self.ups:
+ for hook in l._forward_pre_hooks.values():
+ # The hook we want to remove is an instance of WeightNorm class, so
+ # normally we would do `if isinstance(...)` but this class is not accessible
+ # because of shadowing, so we check the module name directly.
+ # https://github.com/pytorch/pytorch/blob/be0ca00c5ce260eb5bcec3237357f7a30cc08983/torch/nn/utils/__init__.py#L3
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(l)
+
+ for l in self.resblocks:
+ for hook in l._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(l)
+ return self
+
+ def remove_weight_norm(self):
+ for l in self.ups:
+ remove_weight_norm(l)
+ for l in self.resblocks:
+ l.remove_weight_norm()
+
+
+class SineGen(torch.nn.Module):
+ """Definition of sine generator
+ SineGen(samp_rate, harmonic_num = 0,
+ sine_amp = 0.1, noise_std = 0.003,
+ voiced_threshold = 0,
+ flag_for_pulse=False)
+ samp_rate: sampling rate in Hz
+ harmonic_num: number of harmonic overtones (default 0)
+ sine_amp: amplitude of sine-wavefrom (default 0.1)
+ noise_std: std of Gaussian noise (default 0.003)
+ voiced_thoreshold: F0 threshold for U/V classification (default 0)
+ flag_for_pulse: this SinGen is used inside PulseGen (default False)
+ Note: when flag_for_pulse is True, the first time step of a voiced
+ segment is always sin(torch.pi) or cos(0)
+ """
+
+ def __init__(
+ self,
+ samp_rate,
+ harmonic_num=0,
+ sine_amp=0.1,
+ noise_std=0.003,
+ voiced_threshold=0,
+ flag_for_pulse=False,
+ ):
+ super(SineGen, self).__init__()
+ self.sine_amp = sine_amp
+ self.noise_std = noise_std
+ self.harmonic_num = harmonic_num
+ self.dim = self.harmonic_num + 1
+ self.sampling_rate = samp_rate
+ self.voiced_threshold = voiced_threshold
+
+ def _f02uv(self, f0):
+ # generate uv signal
+ uv = torch.ones_like(f0)
+ uv = uv * (f0 > self.voiced_threshold)
+ if uv.device.type == "privateuseone": # for DirectML
+ uv = uv.float()
+ return uv
+
+ def forward(self, f0: torch.Tensor, upp: int):
+ """sine_tensor, uv = forward(f0)
+ input F0: tensor(batchsize=1, length, dim=1)
+ f0 for unvoiced steps should be 0
+ output sine_tensor: tensor(batchsize=1, length, dim)
+ output uv: tensor(batchsize=1, length, 1)
+ """
+ with torch.no_grad():
+ f0 = f0[:, None].transpose(1, 2)
+ f0_buf = torch.zeros(f0.shape[0], f0.shape[1], self.dim, device=f0.device)
+ # fundamental component
+ f0_buf[:, :, 0] = f0[:, :, 0]
+ for idx in range(self.harmonic_num):
+ f0_buf[:, :, idx + 1] = f0_buf[:, :, 0] * (
+ idx + 2
+ ) # idx + 2: the (idx+1)-th overtone, (idx+2)-th harmonic
+ rad_values = (f0_buf / float(self.sampling_rate)) % 1
+ rand_ini = torch.rand(
+ f0_buf.shape[0], f0_buf.shape[2], device=f0_buf.device
+ )
+ rand_ini[:, 0] = 0
+ rad_values[:, 0, :] = rad_values[:, 0, :] + rand_ini
+ tmp_over_one = torch.cumsum(rad_values, 1)
+ tmp_over_one *= upp
+ tmp_over_one = F.interpolate(
+ tmp_over_one.transpose(2, 1),
+ scale_factor=float(upp),
+ mode="linear",
+ align_corners=True,
+ ).transpose(2, 1)
+ rad_values = F.interpolate(
+ rad_values.transpose(2, 1), scale_factor=float(upp), mode="nearest"
+ ).transpose(
+ 2, 1
+ ) #######
+ tmp_over_one %= 1
+ tmp_over_one_idx = (tmp_over_one[:, 1:, :] - tmp_over_one[:, :-1, :]) < 0
+ cumsum_shift = torch.zeros_like(rad_values)
+ cumsum_shift[:, 1:, :] = tmp_over_one_idx * -1.0
+ sine_waves = torch.sin(
+ torch.cumsum(rad_values + cumsum_shift, dim=1) * 2 * torch.pi
+ )
+ sine_waves = sine_waves * self.sine_amp
+ uv = self._f02uv(f0)
+ uv = F.interpolate(
+ uv.transpose(2, 1), scale_factor=float(upp), mode="nearest"
+ ).transpose(2, 1)
+ noise_amp = uv * self.noise_std + (1 - uv) * self.sine_amp / 3
+ noise = noise_amp * torch.randn_like(sine_waves)
+ sine_waves = sine_waves * uv + noise
+ return sine_waves, uv, noise
+
+
+class SourceModuleHnNSF(torch.nn.Module):
+ """SourceModule for hn-nsf
+ SourceModule(sampling_rate, harmonic_num=0, sine_amp=0.1,
+ add_noise_std=0.003, voiced_threshod=0)
+ sampling_rate: sampling_rate in Hz
+ harmonic_num: number of harmonic above F0 (default: 0)
+ sine_amp: amplitude of sine source signal (default: 0.1)
+ add_noise_std: std of additive Gaussian noise (default: 0.003)
+ note that amplitude of noise in unvoiced is decided
+ by sine_amp
+ voiced_threshold: threhold to set U/V given F0 (default: 0)
+ Sine_source, noise_source = SourceModuleHnNSF(F0_sampled)
+ F0_sampled (batchsize, length, 1)
+ Sine_source (batchsize, length, 1)
+ noise_source (batchsize, length 1)
+ uv (batchsize, length, 1)
+ """
+
+ def __init__(
+ self,
+ sampling_rate,
+ harmonic_num=0,
+ sine_amp=0.1,
+ add_noise_std=0.003,
+ voiced_threshod=0,
+ is_half=True,
+ ):
+ super(SourceModuleHnNSF, self).__init__()
+
+ self.sine_amp = sine_amp
+ self.noise_std = add_noise_std
+ self.is_half = is_half
+ # to produce sine waveforms
+ self.l_sin_gen = SineGen(
+ sampling_rate, harmonic_num, sine_amp, add_noise_std, voiced_threshod
+ )
+
+ # to merge source harmonics into a single excitation
+ self.l_linear = torch.nn.Linear(harmonic_num + 1, 1)
+ self.l_tanh = torch.nn.Tanh()
+ # self.ddtype:int = -1
+
+ def forward(self, x: torch.Tensor, upp: int = 1):
+ # if self.ddtype ==-1:
+ # self.ddtype = self.l_linear.weight.dtype
+ sine_wavs, uv, _ = self.l_sin_gen(x, upp)
+ # print(x.dtype,sine_wavs.dtype,self.l_linear.weight.dtype)
+ # if self.is_half:
+ # sine_wavs = sine_wavs.half()
+ # sine_merge = self.l_tanh(self.l_linear(sine_wavs.to(x)))
+ # print(sine_wavs.dtype,self.ddtype)
+ # if sine_wavs.dtype != self.l_linear.weight.dtype:
+ sine_wavs = sine_wavs.to(dtype=self.l_linear.weight.dtype)
+ sine_merge = self.l_tanh(self.l_linear(sine_wavs))
+ return sine_merge, None, None # noise, uv
+
+
+class GeneratorNSF(torch.nn.Module):
+ def __init__(
+ self,
+ initial_channel,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ gin_channels,
+ sr,
+ is_half=False,
+ ):
+ super(GeneratorNSF, self).__init__()
+ self.num_kernels = len(resblock_kernel_sizes)
+ self.num_upsamples = len(upsample_rates)
+
+ self.f0_upsamp = torch.nn.Upsample(scale_factor=math.prod(upsample_rates))
+ self.m_source = SourceModuleHnNSF(
+ sampling_rate=sr, harmonic_num=0, is_half=is_half
+ )
+ self.noise_convs = nn.ModuleList()
+ self.conv_pre = Conv1d(
+ initial_channel, upsample_initial_channel, 7, 1, padding=3
+ )
+ resblock = modules.ResBlock1 if resblock == "1" else modules.ResBlock2
+
+ self.ups = nn.ModuleList()
+ for i, (u, k) in enumerate(zip(upsample_rates, upsample_kernel_sizes)):
+ c_cur = upsample_initial_channel // (2 ** (i + 1))
+ self.ups.append(
+ weight_norm(
+ ConvTranspose1d(
+ upsample_initial_channel // (2**i),
+ upsample_initial_channel // (2 ** (i + 1)),
+ k,
+ u,
+ padding=(k - u) // 2,
+ )
+ )
+ )
+ if i + 1 < len(upsample_rates):
+ stride_f0 = math.prod(upsample_rates[i + 1 :])
+ self.noise_convs.append(
+ Conv1d(
+ 1,
+ c_cur,
+ kernel_size=stride_f0 * 2,
+ stride=stride_f0,
+ padding=stride_f0 // 2,
+ )
+ )
+ else:
+ self.noise_convs.append(Conv1d(1, c_cur, kernel_size=1))
+
+ self.resblocks = nn.ModuleList()
+ for i in range(len(self.ups)):
+ ch = upsample_initial_channel // (2 ** (i + 1))
+ for j, (k, d) in enumerate(
+ zip(resblock_kernel_sizes, resblock_dilation_sizes)
+ ):
+ self.resblocks.append(resblock(ch, k, d))
+
+ self.conv_post = Conv1d(ch, 1, 7, 1, padding=3, bias=False)
+ self.ups.apply(init_weights)
+
+ if gin_channels != 0:
+ self.cond = nn.Conv1d(gin_channels, upsample_initial_channel, 1)
+
+ self.upp = math.prod(upsample_rates)
+
+ self.lrelu_slope = modules.LRELU_SLOPE
+
+ def forward(self, x, f0, g: Optional[torch.Tensor] = None):
+ har_source, noi_source, uv = self.m_source(f0, self.upp)
+ har_source = har_source.transpose(1, 2)
+ x = self.conv_pre(x)
+ if g is not None:
+ x = x + self.cond(g)
+ # torch.jit.script() does not support direct indexing of torch modules
+ # That's why I wrote this
+ for i, (ups, noise_convs) in enumerate(zip(self.ups, self.noise_convs)):
+ if i < self.num_upsamples:
+ x = F.leaky_relu(x, self.lrelu_slope)
+ x = ups(x)
+ x_source = noise_convs(har_source)
+ x = x + x_source
+ xs: Optional[torch.Tensor] = None
+ l = [i * self.num_kernels + j for j in range(self.num_kernels)]
+ for j, resblock in enumerate(self.resblocks):
+ if j in l:
+ if xs is None:
+ xs = resblock(x)
+ else:
+ xs += resblock(x)
+ # This assertion cannot be ignored! \
+ # If ignored, it will cause torch.jit.script() compilation errors
+ assert isinstance(xs, torch.Tensor)
+ x = xs / self.num_kernels
+ x = F.leaky_relu(x)
+ x = self.conv_post(x)
+ x = torch.tanh(x)
+ return x
+
+ def remove_weight_norm(self):
+ for l in self.ups:
+ remove_weight_norm(l)
+ for l in self.resblocks:
+ l.remove_weight_norm()
+
+ def __prepare_scriptable__(self):
+ for l in self.ups:
+ for hook in l._forward_pre_hooks.values():
+ # The hook we want to remove is an instance of WeightNorm class, so
+ # normally we would do `if isinstance(...)` but this class is not accessible
+ # because of shadowing, so we check the module name directly.
+ # https://github.com/pytorch/pytorch/blob/be0ca00c5ce260eb5bcec3237357f7a30cc08983/torch/nn/utils/__init__.py#L3
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(l)
+ for l in self.resblocks:
+ for hook in self.resblocks._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(l)
+ return self
+
+
+sr2sr = {
+ "32k": 32000,
+ "40k": 40000,
+ "48k": 48000,
+}
+
+
+class SynthesizerTrnMs256NSFsid(nn.Module):
+ def __init__(
+ self,
+ spec_channels,
+ segment_size,
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ p_dropout,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ spk_embed_dim,
+ gin_channels,
+ sr,
+ **kwargs
+ ):
+ super(SynthesizerTrnMs256NSFsid, self).__init__()
+ if isinstance(sr, str):
+ sr = sr2sr[sr]
+ self.spec_channels = spec_channels
+ self.inter_channels = inter_channels
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = float(p_dropout)
+ self.resblock = resblock
+ self.resblock_kernel_sizes = resblock_kernel_sizes
+ self.resblock_dilation_sizes = resblock_dilation_sizes
+ self.upsample_rates = upsample_rates
+ self.upsample_initial_channel = upsample_initial_channel
+ self.upsample_kernel_sizes = upsample_kernel_sizes
+ self.segment_size = segment_size
+ self.gin_channels = gin_channels
+ # self.hop_length = hop_length#
+ self.spk_embed_dim = spk_embed_dim
+ self.enc_p = TextEncoder256(
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ float(p_dropout),
+ )
+ self.dec = GeneratorNSF(
+ inter_channels,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ gin_channels=gin_channels,
+ sr=sr,
+ is_half=kwargs["is_half"],
+ )
+ self.enc_q = PosteriorEncoder(
+ spec_channels,
+ inter_channels,
+ hidden_channels,
+ 5,
+ 1,
+ 16,
+ gin_channels=gin_channels,
+ )
+ self.flow = ResidualCouplingBlock(
+ inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
+ )
+ self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
+
+ def remove_weight_norm(self):
+ self.dec.remove_weight_norm()
+ self.flow.remove_weight_norm()
+ self.enc_q.remove_weight_norm()
+
+ def __prepare_scriptable__(self):
+ for hook in self.dec._forward_pre_hooks.values():
+ # The hook we want to remove is an instance of WeightNorm class, so
+ # normally we would do `if isinstance(...)` but this class is not accessible
+ # because of shadowing, so we check the module name directly.
+ # https://github.com/pytorch/pytorch/blob/be0ca00c5ce260eb5bcec3237357f7a30cc08983/torch/nn/utils/__init__.py#L3
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.dec)
+ for hook in self.flow._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.flow)
+ if hasattr(self, "enc_q"):
+ for hook in self.enc_q._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.enc_q)
+ return self
+
+ @torch.jit.ignore
+ def forward(
+ self,
+ phone: torch.Tensor,
+ phone_lengths: torch.Tensor,
+ pitch: torch.Tensor,
+ pitchf: torch.Tensor,
+ y: torch.Tensor,
+ y_lengths: torch.Tensor,
+ ds: Optional[torch.Tensor] = None,
+ ): # 这里ds是id,[bs,1]
+ # print(1,pitch.shape)#[bs,t]
+ g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
+ m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
+ z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
+ z_p = self.flow(z, y_mask, g=g)
+ z_slice, ids_slice = commons.rand_slice_segments(
+ z, y_lengths, self.segment_size
+ )
+ # print(-1,pitchf.shape,ids_slice,self.segment_size,self.hop_length,self.segment_size//self.hop_length)
+ pitchf = commons.slice_segments2(pitchf, ids_slice, self.segment_size)
+ # print(-2,pitchf.shape,z_slice.shape)
+ o = self.dec(z_slice, pitchf, g=g)
+ return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
+
+ @torch.jit.export
+ def infer(
+ self,
+ phone: torch.Tensor,
+ phone_lengths: torch.Tensor,
+ pitch: torch.Tensor,
+ nsff0: torch.Tensor,
+ sid: torch.Tensor,
+ rate: Optional[torch.Tensor] = None,
+ ):
+ g = self.emb_g(sid).unsqueeze(-1)
+ m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
+ z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
+ if rate is not None:
+ assert isinstance(rate, torch.Tensor)
+ head = int(z_p.shape[2] * (1 - rate.item()))
+ z_p = z_p[:, :, head:]
+ x_mask = x_mask[:, :, head:]
+ nsff0 = nsff0[:, head:]
+ z = self.flow(z_p, x_mask, g=g, reverse=True)
+ o = self.dec(z * x_mask, nsff0, g=g)
+ return o, x_mask, (z, z_p, m_p, logs_p)
+
+
+class SynthesizerTrnMs768NSFsid(nn.Module):
+ def __init__(
+ self,
+ spec_channels,
+ segment_size,
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ p_dropout,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ spk_embed_dim,
+ gin_channels,
+ sr,
+ **kwargs
+ ):
+ super(SynthesizerTrnMs768NSFsid, self).__init__()
+ if isinstance(sr, str):
+ sr = sr
+ self.spec_channels = spec_channels
+ self.inter_channels = inter_channels
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = float(p_dropout)
+ self.resblock = resblock
+ self.resblock_kernel_sizes = resblock_kernel_sizes
+ self.resblock_dilation_sizes = resblock_dilation_sizes
+ self.upsample_rates = upsample_rates
+ self.upsample_initial_channel = upsample_initial_channel
+ self.upsample_kernel_sizes = upsample_kernel_sizes
+ self.segment_size = segment_size
+ self.gin_channels = gin_channels
+ # self.hop_length = hop_length#
+ self.spk_embed_dim = spk_embed_dim
+ self.enc_p = TextEncoder768(
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ float(p_dropout),
+ )
+ self.dec = GeneratorNSF(
+ inter_channels,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ gin_channels=gin_channels,
+ sr=sr,
+ is_half=kwargs["is_half"],
+ )
+ self.enc_q = PosteriorEncoder(
+ spec_channels,
+ inter_channels,
+ hidden_channels,
+ 5,
+ 1,
+ 16,
+ gin_channels=gin_channels,
+ )
+ self.flow = ResidualCouplingBlock(
+ inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
+ )
+ self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
+
+ def remove_weight_norm(self):
+ self.dec.remove_weight_norm()
+ self.flow.remove_weight_norm()
+ self.enc_q.remove_weight_norm()
+
+ def __prepare_scriptable__(self):
+ for hook in self.dec._forward_pre_hooks.values():
+ # The hook we want to remove is an instance of WeightNorm class, so
+ # normally we would do `if isinstance(...)` but this class is not accessible
+ # because of shadowing, so we check the module name directly.
+ # https://github.com/pytorch/pytorch/blob/be0ca00c5ce260eb5bcec3237357f7a30cc08983/torch/nn/utils/__init__.py#L3
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.dec)
+ for hook in self.flow._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.flow)
+ if hasattr(self, "enc_q"):
+ for hook in self.enc_q._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.enc_q)
+ return self
+
+ @torch.jit.ignore
+ def forward(
+ self, phone, phone_lengths, pitch, pitchf, y, y_lengths, ds
+ ): # 这里ds是id,[bs,1]
+ # print(1,pitch.shape)#[bs,t]
+ g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
+ m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
+ z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
+ z_p = self.flow(z, y_mask, g=g)
+ z_slice, ids_slice = commons.rand_slice_segments(
+ z, y_lengths, self.segment_size
+ )
+ # print(-1,pitchf.shape,ids_slice,self.segment_size,self.hop_length,self.segment_size//self.hop_length)
+ pitchf = commons.slice_segments2(pitchf, ids_slice, self.segment_size)
+ # print(-2,pitchf.shape,z_slice.shape)
+ o = self.dec(z_slice, pitchf, g=g)
+ return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
+
+ @torch.jit.export
+ def infer(
+ self,
+ phone: torch.Tensor,
+ phone_lengths: torch.Tensor,
+ pitch: torch.Tensor,
+ nsff0: torch.Tensor,
+ sid: torch.Tensor,
+ rate: Optional[torch.Tensor] = None,
+ ):
+ g = self.emb_g(sid).unsqueeze(-1)
+ m_p, logs_p, x_mask = self.enc_p(phone, pitch, phone_lengths)
+ z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
+ if rate is not None:
+ head = int(z_p.shape[2] * (1.0 - rate.item()))
+ z_p = z_p[:, :, head:]
+ x_mask = x_mask[:, :, head:]
+ nsff0 = nsff0[:, head:]
+ z = self.flow(z_p, x_mask, g=g, reverse=True)
+ o = self.dec(z * x_mask, nsff0, g=g)
+ return o, x_mask, (z, z_p, m_p, logs_p)
+
+
+class SynthesizerTrnMs256NSFsid_nono(nn.Module):
+ def __init__(
+ self,
+ spec_channels,
+ segment_size,
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ p_dropout,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ spk_embed_dim,
+ gin_channels,
+ sr=None,
+ **kwargs
+ ):
+ super(SynthesizerTrnMs256NSFsid_nono, self).__init__()
+ self.spec_channels = spec_channels
+ self.inter_channels = inter_channels
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = float(p_dropout)
+ self.resblock = resblock
+ self.resblock_kernel_sizes = resblock_kernel_sizes
+ self.resblock_dilation_sizes = resblock_dilation_sizes
+ self.upsample_rates = upsample_rates
+ self.upsample_initial_channel = upsample_initial_channel
+ self.upsample_kernel_sizes = upsample_kernel_sizes
+ self.segment_size = segment_size
+ self.gin_channels = gin_channels
+ # self.hop_length = hop_length#
+ self.spk_embed_dim = spk_embed_dim
+ self.enc_p = TextEncoder256(
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ float(p_dropout),
+ f0=False,
+ )
+ self.dec = Generator(
+ inter_channels,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ gin_channels=gin_channels,
+ )
+ self.enc_q = PosteriorEncoder(
+ spec_channels,
+ inter_channels,
+ hidden_channels,
+ 5,
+ 1,
+ 16,
+ gin_channels=gin_channels,
+ )
+ self.flow = ResidualCouplingBlock(
+ inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
+ )
+ self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
+
+ def remove_weight_norm(self):
+ self.dec.remove_weight_norm()
+ self.flow.remove_weight_norm()
+ self.enc_q.remove_weight_norm()
+
+ def __prepare_scriptable__(self):
+ for hook in self.dec._forward_pre_hooks.values():
+ # The hook we want to remove is an instance of WeightNorm class, so
+ # normally we would do `if isinstance(...)` but this class is not accessible
+ # because of shadowing, so we check the module name directly.
+ # https://github.com/pytorch/pytorch/blob/be0ca00c5ce260eb5bcec3237357f7a30cc08983/torch/nn/utils/__init__.py#L3
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.dec)
+ for hook in self.flow._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.flow)
+ if hasattr(self, "enc_q"):
+ for hook in self.enc_q._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.enc_q)
+ return self
+
+ @torch.jit.ignore
+ def forward(self, phone, phone_lengths, y, y_lengths, ds): # 这里ds是id,[bs,1]
+ g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
+ m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
+ z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
+ z_p = self.flow(z, y_mask, g=g)
+ z_slice, ids_slice = commons.rand_slice_segments(
+ z, y_lengths, self.segment_size
+ )
+ o = self.dec(z_slice, g=g)
+ return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
+
+ @torch.jit.export
+ def infer(
+ self,
+ phone: torch.Tensor,
+ phone_lengths: torch.Tensor,
+ sid: torch.Tensor,
+ rate: Optional[torch.Tensor] = None,
+ ):
+ g = self.emb_g(sid).unsqueeze(-1)
+ m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
+ z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
+ if rate is not None:
+ head = int(z_p.shape[2] * (1.0 - rate.item()))
+ z_p = z_p[:, :, head:]
+ x_mask = x_mask[:, :, head:]
+ z = self.flow(z_p, x_mask, g=g, reverse=True)
+ o = self.dec(z * x_mask, g=g)
+ return o, x_mask, (z, z_p, m_p, logs_p)
+
+
+class SynthesizerTrnMs768NSFsid_nono(nn.Module):
+ def __init__(
+ self,
+ spec_channels,
+ segment_size,
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ p_dropout,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ spk_embed_dim,
+ gin_channels,
+ sr=None,
+ **kwargs
+ ):
+ super(SynthesizerTrnMs768NSFsid_nono, self).__init__()
+ self.spec_channels = spec_channels
+ self.inter_channels = inter_channels
+ self.hidden_channels = hidden_channels
+ self.filter_channels = filter_channels
+ self.n_heads = n_heads
+ self.n_layers = n_layers
+ self.kernel_size = kernel_size
+ self.p_dropout = float(p_dropout)
+ self.resblock = resblock
+ self.resblock_kernel_sizes = resblock_kernel_sizes
+ self.resblock_dilation_sizes = resblock_dilation_sizes
+ self.upsample_rates = upsample_rates
+ self.upsample_initial_channel = upsample_initial_channel
+ self.upsample_kernel_sizes = upsample_kernel_sizes
+ self.segment_size = segment_size
+ self.gin_channels = gin_channels
+ # self.hop_length = hop_length#
+ self.spk_embed_dim = spk_embed_dim
+ self.enc_p = TextEncoder768(
+ inter_channels,
+ hidden_channels,
+ filter_channels,
+ n_heads,
+ n_layers,
+ kernel_size,
+ float(p_dropout),
+ f0=False,
+ )
+ self.dec = Generator(
+ inter_channels,
+ resblock,
+ resblock_kernel_sizes,
+ resblock_dilation_sizes,
+ upsample_rates,
+ upsample_initial_channel,
+ upsample_kernel_sizes,
+ gin_channels=gin_channels,
+ )
+ self.enc_q = PosteriorEncoder(
+ spec_channels,
+ inter_channels,
+ hidden_channels,
+ 5,
+ 1,
+ 16,
+ gin_channels=gin_channels,
+ )
+ self.flow = ResidualCouplingBlock(
+ inter_channels, hidden_channels, 5, 1, 3, gin_channels=gin_channels
+ )
+ self.emb_g = nn.Embedding(self.spk_embed_dim, gin_channels)
+
+ def remove_weight_norm(self):
+ self.dec.remove_weight_norm()
+ self.flow.remove_weight_norm()
+ self.enc_q.remove_weight_norm()
+
+ def __prepare_scriptable__(self):
+ for hook in self.dec._forward_pre_hooks.values():
+ # The hook we want to remove is an instance of WeightNorm class, so
+ # normally we would do `if isinstance(...)` but this class is not accessible
+ # because of shadowing, so we check the module name directly.
+ # https://github.com/pytorch/pytorch/blob/be0ca00c5ce260eb5bcec3237357f7a30cc08983/torch/nn/utils/__init__.py#L3
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.dec)
+ for hook in self.flow._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.flow)
+ if hasattr(self, "enc_q"):
+ for hook in self.enc_q._forward_pre_hooks.values():
+ if (
+ hook.__module__ == "torch.nn.utils.weight_norm"
+ and hook.__class__.__name__ == "WeightNorm"
+ ):
+ torch.nn.utils.remove_weight_norm(self.enc_q)
+ return self
+
+ @torch.jit.ignore
+ def forward(self, phone, phone_lengths, y, y_lengths, ds): # 这里ds是id,[bs,1]
+ g = self.emb_g(ds).unsqueeze(-1) # [b, 256, 1]##1是t,广播的
+ m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
+ z, m_q, logs_q, y_mask = self.enc_q(y, y_lengths, g=g)
+ z_p = self.flow(z, y_mask, g=g)
+ z_slice, ids_slice = commons.rand_slice_segments(
+ z, y_lengths, self.segment_size
+ )
+ o = self.dec(z_slice, g=g)
+ return o, ids_slice, x_mask, y_mask, (z, z_p, m_p, logs_p, m_q, logs_q)
+
+ @torch.jit.export
+ def infer(
+ self,
+ phone: torch.Tensor,
+ phone_lengths: torch.Tensor,
+ sid: torch.Tensor,
+ rate: Optional[torch.Tensor] = None,
+ ):
+ g = self.emb_g(sid).unsqueeze(-1)
+ m_p, logs_p, x_mask = self.enc_p(phone, None, phone_lengths)
+ z_p = (m_p + torch.exp(logs_p) * torch.randn_like(m_p) * 0.66666) * x_mask
+ if rate is not None:
+ head = int(z_p.shape[2] * (1.0 - rate.item()))
+ z_p = z_p[:, :, head:]
+ x_mask = x_mask[:, :, head:]
+ z = self.flow(z_p, x_mask, g=g, reverse=True)
+ o = self.dec(z * x_mask, g=g)
+ return o, x_mask, (z, z_p, m_p, logs_p)
+
+
+class MultiPeriodDiscriminator(torch.nn.Module):
+ def __init__(self, use_spectral_norm=False):
+ super(MultiPeriodDiscriminator, self).__init__()
+ periods = [2, 3, 5, 7, 11, 17]
+ # periods = [3, 5, 7, 11, 17, 23, 37]
+
+ discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
+ discs = discs + [
+ DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods
+ ]
+ self.discriminators = nn.ModuleList(discs)
+
+ def forward(self, y, y_hat):
+ y_d_rs = [] #
+ y_d_gs = []
+ fmap_rs = []
+ fmap_gs = []
+ for i, d in enumerate(self.discriminators):
+ y_d_r, fmap_r = d(y)
+ y_d_g, fmap_g = d(y_hat)
+ # for j in range(len(fmap_r)):
+ # print(i,j,y.shape,y_hat.shape,fmap_r[j].shape,fmap_g[j].shape)
+ y_d_rs.append(y_d_r)
+ y_d_gs.append(y_d_g)
+ fmap_rs.append(fmap_r)
+ fmap_gs.append(fmap_g)
+
+ return y_d_rs, y_d_gs, fmap_rs, fmap_gs
+
+
+class MultiPeriodDiscriminatorV2(torch.nn.Module):
+ def __init__(self, use_spectral_norm=False):
+ super(MultiPeriodDiscriminatorV2, self).__init__()
+ # periods = [2, 3, 5, 7, 11, 17]
+ periods = [2, 3, 5, 7, 11, 17, 23, 37]
+
+ discs = [DiscriminatorS(use_spectral_norm=use_spectral_norm)]
+ discs = discs + [
+ DiscriminatorP(i, use_spectral_norm=use_spectral_norm) for i in periods
+ ]
+ self.discriminators = nn.ModuleList(discs)
+
+ def forward(self, y, y_hat):
+ y_d_rs = [] #
+ y_d_gs = []
+ fmap_rs = []
+ fmap_gs = []
+ for i, d in enumerate(self.discriminators):
+ y_d_r, fmap_r = d(y)
+ y_d_g, fmap_g = d(y_hat)
+ # for j in range(len(fmap_r)):
+ # print(i,j,y.shape,y_hat.shape,fmap_r[j].shape,fmap_g[j].shape)
+ y_d_rs.append(y_d_r)
+ y_d_gs.append(y_d_g)
+ fmap_rs.append(fmap_r)
+ fmap_gs.append(fmap_g)
+
+ return y_d_rs, y_d_gs, fmap_rs, fmap_gs
+
+
+class DiscriminatorS(torch.nn.Module):
+ def __init__(self, use_spectral_norm=False):
+ super(DiscriminatorS, self).__init__()
+ norm_f = weight_norm if use_spectral_norm == False else spectral_norm
+ self.convs = nn.ModuleList(
+ [
+ norm_f(Conv1d(1, 16, 15, 1, padding=7)),
+ norm_f(Conv1d(16, 64, 41, 4, groups=4, padding=20)),
+ norm_f(Conv1d(64, 256, 41, 4, groups=16, padding=20)),
+ norm_f(Conv1d(256, 1024, 41, 4, groups=64, padding=20)),
+ norm_f(Conv1d(1024, 1024, 41, 4, groups=256, padding=20)),
+ norm_f(Conv1d(1024, 1024, 5, 1, padding=2)),
+ ]
+ )
+ self.conv_post = norm_f(Conv1d(1024, 1, 3, 1, padding=1))
+
+ def forward(self, x):
+ fmap = []
+
+ for l in self.convs:
+ x = l(x)
+ x = F.leaky_relu(x, modules.LRELU_SLOPE)
+ fmap.append(x)
+ x = self.conv_post(x)
+ fmap.append(x)
+ x = torch.flatten(x, 1, -1)
+
+ return x, fmap
+
+
+class DiscriminatorP(torch.nn.Module):
+ def __init__(self, period, kernel_size=5, stride=3, use_spectral_norm=False):
+ super(DiscriminatorP, self).__init__()
+ self.period = period
+ self.use_spectral_norm = use_spectral_norm
+ norm_f = weight_norm if use_spectral_norm == False else spectral_norm
+ self.convs = nn.ModuleList(
+ [
+ norm_f(
+ Conv2d(
+ 1,
+ 32,
+ (kernel_size, 1),
+ (stride, 1),
+ padding=(get_padding(kernel_size, 1), 0),
+ )
+ ),
+ norm_f(
+ Conv2d(
+ 32,
+ 128,
+ (kernel_size, 1),
+ (stride, 1),
+ padding=(get_padding(kernel_size, 1), 0),
+ )
+ ),
+ norm_f(
+ Conv2d(
+ 128,
+ 512,
+ (kernel_size, 1),
+ (stride, 1),
+ padding=(get_padding(kernel_size, 1), 0),
+ )
+ ),
+ norm_f(
+ Conv2d(
+ 512,
+ 1024,
+ (kernel_size, 1),
+ (stride, 1),
+ padding=(get_padding(kernel_size, 1), 0),
+ )
+ ),
+ norm_f(
+ Conv2d(
+ 1024,
+ 1024,
+ (kernel_size, 1),
+ 1,
+ padding=(get_padding(kernel_size, 1), 0),
+ )
+ ),
+ ]
+ )
+ self.conv_post = norm_f(Conv2d(1024, 1, (3, 1), 1, padding=(1, 0)))
+
+ def forward(self, x):
+ fmap = []
+
+ # 1d to 2d
+ b, c, t = x.shape
+ if t % self.period != 0: # pad first
+ n_pad = self.period - (t % self.period)
+ if has_xpu and x.dtype == torch.bfloat16:
+ x = F.pad(x.to(dtype=torch.float16), (0, n_pad), "reflect").to(
+ dtype=torch.bfloat16
+ )
+ else:
+ x = F.pad(x, (0, n_pad), "reflect")
+ t = t + n_pad
+ x = x.view(b, c, t // self.period, self.period)
+
+ for l in self.convs:
+ x = l(x)
+ x = F.leaky_relu(x, modules.LRELU_SLOPE)
+ fmap.append(x)
+ x = self.conv_post(x)
+ fmap.append(x)
+ x = torch.flatten(x, 1, -1)
+
+ return x, fmap
diff --git a/rvc/lib/infer_pack/modules.py b/rvc/lib/infer_pack/modules.py
new file mode 100644
index 0000000000000000000000000000000000000000..7c18733a9e4124821dc0b2f934f262e56098626a
--- /dev/null
+++ b/rvc/lib/infer_pack/modules.py
@@ -0,0 +1,521 @@
+import math
+import torch
+from torch import nn
+from torch.nn import functional as F
+
+from torch.nn import Conv1d
+from torch.nn.utils import remove_weight_norm
+from torch.nn.utils.parametrizations import weight_norm
+
+
+from . import commons
+from .commons import init_weights, get_padding
+from .transforms import piecewise_rational_quadratic_transform
+
+
+LRELU_SLOPE = 0.1
+
+
+class LayerNorm(nn.Module):
+ def __init__(self, channels, eps=1e-5):
+ super().__init__()
+ self.channels = channels
+ self.eps = eps
+
+ self.gamma = nn.Parameter(torch.ones(channels))
+ self.beta = nn.Parameter(torch.zeros(channels))
+
+ def forward(self, x):
+ x = x.transpose(1, -1)
+ x = F.layer_norm(x, (self.channels,), self.gamma, self.beta, self.eps)
+ return x.transpose(1, -1)
+
+
+class ConvReluNorm(nn.Module):
+ def __init__(
+ self,
+ in_channels,
+ hidden_channels,
+ out_channels,
+ kernel_size,
+ n_layers,
+ p_dropout,
+ ):
+ super().__init__()
+ self.in_channels = in_channels
+ self.hidden_channels = hidden_channels
+ self.out_channels = out_channels
+ self.kernel_size = kernel_size
+ self.n_layers = n_layers
+ self.p_dropout = p_dropout
+ assert n_layers > 1, "Number of layers should be larger than 0."
+
+ self.conv_layers = nn.ModuleList()
+ self.norm_layers = nn.ModuleList()
+ self.conv_layers.append(
+ nn.Conv1d(
+ in_channels, hidden_channels, kernel_size, padding=kernel_size // 2
+ )
+ )
+ self.norm_layers.append(LayerNorm(hidden_channels))
+ self.relu_drop = nn.Sequential(nn.ReLU(), nn.Dropout(p_dropout))
+ for _ in range(n_layers - 1):
+ self.conv_layers.append(
+ nn.Conv1d(
+ hidden_channels,
+ hidden_channels,
+ kernel_size,
+ padding=kernel_size // 2,
+ )
+ )
+ self.norm_layers.append(LayerNorm(hidden_channels))
+ self.proj = nn.Conv1d(hidden_channels, out_channels, 1)
+ self.proj.weight.data.zero_()
+ self.proj.bias.data.zero_()
+
+ def forward(self, x, x_mask):
+ x_org = x
+ for i in range(self.n_layers):
+ x = self.conv_layers[i](x * x_mask)
+ x = self.norm_layers[i](x)
+ x = self.relu_drop(x)
+ x = x_org + self.proj(x)
+ return x * x_mask
+
+
+class DDSConv(nn.Module):
+ def __init__(self, channels, kernel_size, n_layers, p_dropout=0.0):
+ super().__init__()
+ self.channels = channels
+ self.kernel_size = kernel_size
+ self.n_layers = n_layers
+ self.p_dropout = p_dropout
+
+ self.drop = nn.Dropout(p_dropout)
+ self.convs_sep = nn.ModuleList()
+ self.convs_1x1 = nn.ModuleList()
+ self.norms_1 = nn.ModuleList()
+ self.norms_2 = nn.ModuleList()
+ for i in range(n_layers):
+ dilation = kernel_size**i
+ padding = (kernel_size * dilation - dilation) // 2
+ self.convs_sep.append(
+ nn.Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ groups=channels,
+ dilation=dilation,
+ padding=padding,
+ )
+ )
+ self.convs_1x1.append(nn.Conv1d(channels, channels, 1))
+ self.norms_1.append(LayerNorm(channels))
+ self.norms_2.append(LayerNorm(channels))
+
+ def forward(self, x, x_mask, g=None):
+ if g is not None:
+ x = x + g
+ for i in range(self.n_layers):
+ y = self.convs_sep[i](x * x_mask)
+ y = self.norms_1[i](y)
+ y = F.gelu(y)
+ y = self.convs_1x1[i](y)
+ y = self.norms_2[i](y)
+ y = F.gelu(y)
+ y = self.drop(y)
+ x = x + y
+ return x * x_mask
+
+
+class WN(torch.nn.Module):
+ def __init__(
+ self,
+ hidden_channels,
+ kernel_size,
+ dilation_rate,
+ n_layers,
+ gin_channels=0,
+ p_dropout=0,
+ ):
+ super(WN, self).__init__()
+ assert kernel_size % 2 == 1
+ self.hidden_channels = hidden_channels
+ self.kernel_size = (kernel_size,)
+ self.dilation_rate = dilation_rate
+ self.n_layers = n_layers
+ self.gin_channels = gin_channels
+ self.p_dropout = p_dropout
+
+ self.in_layers = torch.nn.ModuleList()
+ self.res_skip_layers = torch.nn.ModuleList()
+ self.drop = nn.Dropout(p_dropout)
+
+ if gin_channels != 0:
+ cond_layer = torch.nn.Conv1d(
+ gin_channels, 2 * hidden_channels * n_layers, 1
+ )
+ self.cond_layer = torch.nn.utils.parametrizations.weight_norm(
+ cond_layer, name="weight"
+ )
+
+ for i in range(n_layers):
+ dilation = dilation_rate**i
+ padding = int((kernel_size * dilation - dilation) / 2)
+ in_layer = torch.nn.Conv1d(
+ hidden_channels,
+ 2 * hidden_channels,
+ kernel_size,
+ dilation=dilation,
+ padding=padding,
+ )
+ in_layer = torch.nn.utils.parametrizations.weight_norm(
+ in_layer, name="weight"
+ )
+ self.in_layers.append(in_layer)
+ if i < n_layers - 1:
+ res_skip_channels = 2 * hidden_channels
+ else:
+ res_skip_channels = hidden_channels
+
+ res_skip_layer = torch.nn.Conv1d(hidden_channels, res_skip_channels, 1)
+ res_skip_layer = torch.nn.utils.parametrizations.weight_norm(
+ res_skip_layer, name="weight"
+ )
+ self.res_skip_layers.append(res_skip_layer)
+
+ def forward(self, x, x_mask, g=None, **kwargs):
+ output = torch.zeros_like(x)
+ n_channels_tensor = torch.IntTensor([self.hidden_channels])
+
+ if g is not None:
+ g = self.cond_layer(g)
+
+ for i in range(self.n_layers):
+ x_in = self.in_layers[i](x)
+ if g is not None:
+ cond_offset = i * 2 * self.hidden_channels
+ g_l = g[:, cond_offset : cond_offset + 2 * self.hidden_channels, :]
+ else:
+ g_l = torch.zeros_like(x_in)
+
+ acts = commons.fused_add_tanh_sigmoid_multiply(x_in, g_l, n_channels_tensor)
+ acts = self.drop(acts)
+
+ res_skip_acts = self.res_skip_layers[i](acts)
+ if i < self.n_layers - 1:
+ res_acts = res_skip_acts[:, : self.hidden_channels, :]
+ x = (x + res_acts) * x_mask
+ output = output + res_skip_acts[:, self.hidden_channels :, :]
+ else:
+ output = output + res_skip_acts
+ return output * x_mask
+
+ def remove_weight_norm(self):
+ if self.gin_channels != 0:
+ torch.nn.utils.remove_weight_norm(self.cond_layer)
+ for l in self.in_layers:
+ torch.nn.utils.remove_weight_norm(l)
+ for l in self.res_skip_layers:
+ torch.nn.utils.remove_weight_norm(l)
+
+
+class ResBlock1(torch.nn.Module):
+ def __init__(self, channels, kernel_size=3, dilation=(1, 3, 5)):
+ super(ResBlock1, self).__init__()
+ self.convs1 = nn.ModuleList(
+ [
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=dilation[0],
+ padding=get_padding(kernel_size, dilation[0]),
+ )
+ ),
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=dilation[1],
+ padding=get_padding(kernel_size, dilation[1]),
+ )
+ ),
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=dilation[2],
+ padding=get_padding(kernel_size, dilation[2]),
+ )
+ ),
+ ]
+ )
+ self.convs1.apply(init_weights)
+
+ self.convs2 = nn.ModuleList(
+ [
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=1,
+ padding=get_padding(kernel_size, 1),
+ )
+ ),
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=1,
+ padding=get_padding(kernel_size, 1),
+ )
+ ),
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=1,
+ padding=get_padding(kernel_size, 1),
+ )
+ ),
+ ]
+ )
+ self.convs2.apply(init_weights)
+
+ def forward(self, x, x_mask=None):
+ for c1, c2 in zip(self.convs1, self.convs2):
+ xt = F.leaky_relu(x, LRELU_SLOPE)
+ if x_mask is not None:
+ xt = xt * x_mask
+ xt = c1(xt)
+ xt = F.leaky_relu(xt, LRELU_SLOPE)
+ if x_mask is not None:
+ xt = xt * x_mask
+ xt = c2(xt)
+ x = xt + x
+ if x_mask is not None:
+ x = x * x_mask
+ return x
+
+ def remove_weight_norm(self):
+ for l in self.convs1:
+ remove_weight_norm(l)
+ for l in self.convs2:
+ remove_weight_norm(l)
+
+
+class ResBlock2(torch.nn.Module):
+ def __init__(self, channels, kernel_size=3, dilation=(1, 3)):
+ super(ResBlock2, self).__init__()
+ self.convs = nn.ModuleList(
+ [
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=dilation[0],
+ padding=get_padding(kernel_size, dilation[0]),
+ )
+ ),
+ weight_norm(
+ Conv1d(
+ channels,
+ channels,
+ kernel_size,
+ 1,
+ dilation=dilation[1],
+ padding=get_padding(kernel_size, dilation[1]),
+ )
+ ),
+ ]
+ )
+ self.convs.apply(init_weights)
+
+ def forward(self, x, x_mask=None):
+ for c in self.convs:
+ xt = F.leaky_relu(x, LRELU_SLOPE)
+ if x_mask is not None:
+ xt = xt * x_mask
+ xt = c(xt)
+ x = xt + x
+ if x_mask is not None:
+ x = x * x_mask
+ return x
+
+ def remove_weight_norm(self):
+ for l in self.convs:
+ remove_weight_norm(l)
+
+
+class Log(nn.Module):
+ def forward(self, x, x_mask, reverse=False, **kwargs):
+ if not reverse:
+ y = torch.log(torch.clamp_min(x, 1e-5)) * x_mask
+ logdet = torch.sum(-y, [1, 2])
+ return y, logdet
+ else:
+ x = torch.exp(x) * x_mask
+ return x
+
+
+class Flip(nn.Module):
+ def forward(self, x, *args, reverse=False, **kwargs):
+ x = torch.flip(x, [1])
+ if not reverse:
+ logdet = torch.zeros(x.size(0)).to(dtype=x.dtype, device=x.device)
+ return x, logdet
+ else:
+ return x
+
+
+class ElementwiseAffine(nn.Module):
+ def __init__(self, channels):
+ super().__init__()
+ self.channels = channels
+ self.m = nn.Parameter(torch.zeros(channels, 1))
+ self.logs = nn.Parameter(torch.zeros(channels, 1))
+
+ def forward(self, x, x_mask, reverse=False, **kwargs):
+ if not reverse:
+ y = self.m + torch.exp(self.logs) * x
+ y = y * x_mask
+ logdet = torch.sum(self.logs * x_mask, [1, 2])
+ return y, logdet
+ else:
+ x = (x - self.m) * torch.exp(-self.logs) * x_mask
+ return x
+
+
+class ResidualCouplingLayer(nn.Module):
+ def __init__(
+ self,
+ channels,
+ hidden_channels,
+ kernel_size,
+ dilation_rate,
+ n_layers,
+ p_dropout=0,
+ gin_channels=0,
+ mean_only=False,
+ ):
+ assert channels % 2 == 0, "channels should be divisible by 2"
+ super().__init__()
+ self.channels = channels
+ self.hidden_channels = hidden_channels
+ self.kernel_size = kernel_size
+ self.dilation_rate = dilation_rate
+ self.n_layers = n_layers
+ self.half_channels = channels // 2
+ self.mean_only = mean_only
+
+ self.pre = nn.Conv1d(self.half_channels, hidden_channels, 1)
+ self.enc = WN(
+ hidden_channels,
+ kernel_size,
+ dilation_rate,
+ n_layers,
+ p_dropout=p_dropout,
+ gin_channels=gin_channels,
+ )
+ self.post = nn.Conv1d(hidden_channels, self.half_channels * (2 - mean_only), 1)
+ self.post.weight.data.zero_()
+ self.post.bias.data.zero_()
+
+ def forward(self, x, x_mask, g=None, reverse=False):
+ x0, x1 = torch.split(x, [self.half_channels] * 2, 1)
+ h = self.pre(x0) * x_mask
+ h = self.enc(h, x_mask, g=g)
+ stats = self.post(h) * x_mask
+ if not self.mean_only:
+ m, logs = torch.split(stats, [self.half_channels] * 2, 1)
+ else:
+ m = stats
+ logs = torch.zeros_like(m)
+
+ if not reverse:
+ x1 = m + x1 * torch.exp(logs) * x_mask
+ x = torch.cat([x0, x1], 1)
+ logdet = torch.sum(logs, [1, 2])
+ return x, logdet
+ else:
+ x1 = (x1 - m) * torch.exp(-logs) * x_mask
+ x = torch.cat([x0, x1], 1)
+ return x
+
+ def remove_weight_norm(self):
+ self.enc.remove_weight_norm()
+
+
+class ConvFlow(nn.Module):
+ def __init__(
+ self,
+ in_channels,
+ filter_channels,
+ kernel_size,
+ n_layers,
+ num_bins=10,
+ tail_bound=5.0,
+ ):
+ super().__init__()
+ self.in_channels = in_channels
+ self.filter_channels = filter_channels
+ self.kernel_size = kernel_size
+ self.n_layers = n_layers
+ self.num_bins = num_bins
+ self.tail_bound = tail_bound
+ self.half_channels = in_channels // 2
+
+ self.pre = nn.Conv1d(self.half_channels, filter_channels, 1)
+ self.convs = DDSConv(filter_channels, kernel_size, n_layers, p_dropout=0.0)
+ self.proj = nn.Conv1d(
+ filter_channels, self.half_channels * (num_bins * 3 - 1), 1
+ )
+ self.proj.weight.data.zero_()
+ self.proj.bias.data.zero_()
+
+ def forward(self, x, x_mask, g=None, reverse=False):
+ x0, x1 = torch.split(x, [self.half_channels] * 2, 1)
+ h = self.pre(x0)
+ h = self.convs(h, x_mask, g=g)
+ h = self.proj(h) * x_mask
+
+ b, c, t = x0.shape
+ h = h.reshape(b, c, -1, t).permute(0, 1, 3, 2)
+
+ unnormalized_widths = h[..., : self.num_bins] / math.sqrt(self.filter_channels)
+ unnormalized_heights = h[..., self.num_bins : 2 * self.num_bins] / math.sqrt(
+ self.filter_channels
+ )
+ unnormalized_derivatives = h[..., 2 * self.num_bins :]
+
+ x1, logabsdet = piecewise_rational_quadratic_transform(
+ x1,
+ unnormalized_widths,
+ unnormalized_heights,
+ unnormalized_derivatives,
+ inverse=reverse,
+ tails="linear",
+ tail_bound=self.tail_bound,
+ )
+
+ x = torch.cat([x0, x1], 1) * x_mask
+ logdet = torch.sum(logabsdet * x_mask, [1, 2])
+ if not reverse:
+ return x, logdet
+ else:
+ return x
diff --git a/rvc/lib/infer_pack/modules/F0Predictor/DioF0Predictor.py b/rvc/lib/infer_pack/modules/F0Predictor/DioF0Predictor.py
new file mode 100644
index 0000000000000000000000000000000000000000..6d241b4712b1f0c6e764a4150b425cb2a764d538
--- /dev/null
+++ b/rvc/lib/infer_pack/modules/F0Predictor/DioF0Predictor.py
@@ -0,0 +1,86 @@
+from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
+import pyworld
+import numpy as np
+
+
+class DioF0Predictor(F0Predictor):
+ def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
+ self.hop_length = hop_length
+ self.f0_min = f0_min
+ self.f0_max = f0_max
+ self.sampling_rate = sampling_rate
+
+ def interpolate_f0(self, f0):
+ data = np.reshape(f0, (f0.size, 1))
+
+ vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
+ vuv_vector[data > 0.0] = 1.0
+ vuv_vector[data <= 0.0] = 0.0
+
+ ip_data = data
+
+ frame_number = data.size
+ last_value = 0.0
+ for i in range(frame_number):
+ if data[i] <= 0.0:
+ j = i + 1
+ for j in range(i + 1, frame_number):
+ if data[j] > 0.0:
+ break
+ if j < frame_number - 1:
+ if last_value > 0.0:
+ step = (data[j] - data[i - 1]) / float(j - i)
+ for k in range(i, j):
+ ip_data[k] = data[i - 1] + step * (k - i + 1)
+ else:
+ for k in range(i, j):
+ ip_data[k] = data[j]
+ else:
+ for k in range(i, frame_number):
+ ip_data[k] = last_value
+ else:
+ ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
+ last_value = data[i]
+
+ return ip_data[:, 0], vuv_vector[:, 0]
+
+ def resize_f0(self, x, target_len):
+ source = np.array(x)
+ source[source < 0.001] = np.nan
+ target = np.interp(
+ np.arange(0, len(source) * target_len, len(source)) / target_len,
+ np.arange(0, len(source)),
+ source,
+ )
+ res = np.nan_to_num(target)
+ return res
+
+ def compute_f0(self, wav, p_len=None):
+ if p_len is None:
+ p_len = wav.shape[0] // self.hop_length
+ f0, t = pyworld.dio(
+ wav.astype(np.double),
+ fs=self.sampling_rate,
+ f0_floor=self.f0_min,
+ f0_ceil=self.f0_max,
+ frame_period=1000 * self.hop_length / self.sampling_rate,
+ )
+ f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
+ for index, pitch in enumerate(f0):
+ f0[index] = round(pitch, 1)
+ return self.interpolate_f0(self.resize_f0(f0, p_len))[0]
+
+ def compute_f0_uv(self, wav, p_len=None):
+ if p_len is None:
+ p_len = wav.shape[0] // self.hop_length
+ f0, t = pyworld.dio(
+ wav.astype(np.double),
+ fs=self.sampling_rate,
+ f0_floor=self.f0_min,
+ f0_ceil=self.f0_max,
+ frame_period=1000 * self.hop_length / self.sampling_rate,
+ )
+ f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
+ for index, pitch in enumerate(f0):
+ f0[index] = round(pitch, 1)
+ return self.interpolate_f0(self.resize_f0(f0, p_len))
diff --git a/rvc/lib/infer_pack/modules/F0Predictor/F0Predictor.py b/rvc/lib/infer_pack/modules/F0Predictor/F0Predictor.py
new file mode 100644
index 0000000000000000000000000000000000000000..384f43f8a15977edb66d5cf8b074a8109abf10a1
--- /dev/null
+++ b/rvc/lib/infer_pack/modules/F0Predictor/F0Predictor.py
@@ -0,0 +1,6 @@
+class F0Predictor(object):
+ def compute_f0(self, wav, p_len):
+ pass
+
+ def compute_f0_uv(self, wav, p_len):
+ pass
diff --git a/rvc/lib/infer_pack/modules/F0Predictor/HarvestF0Predictor.py b/rvc/lib/infer_pack/modules/F0Predictor/HarvestF0Predictor.py
new file mode 100644
index 0000000000000000000000000000000000000000..e533f284faa7320ddd5d29b4e3cfef952e00f6e8
--- /dev/null
+++ b/rvc/lib/infer_pack/modules/F0Predictor/HarvestF0Predictor.py
@@ -0,0 +1,82 @@
+from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
+import pyworld
+import numpy as np
+
+
+class HarvestF0Predictor(F0Predictor):
+ def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
+ self.hop_length = hop_length
+ self.f0_min = f0_min
+ self.f0_max = f0_max
+ self.sampling_rate = sampling_rate
+
+ def interpolate_f0(self, f0):
+ data = np.reshape(f0, (f0.size, 1))
+
+ vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
+ vuv_vector[data > 0.0] = 1.0
+ vuv_vector[data <= 0.0] = 0.0
+
+ ip_data = data
+
+ frame_number = data.size
+ last_value = 0.0
+ for i in range(frame_number):
+ if data[i] <= 0.0:
+ j = i + 1
+ for j in range(i + 1, frame_number):
+ if data[j] > 0.0:
+ break
+ if j < frame_number - 1:
+ if last_value > 0.0:
+ step = (data[j] - data[i - 1]) / float(j - i)
+ for k in range(i, j):
+ ip_data[k] = data[i - 1] + step * (k - i + 1)
+ else:
+ for k in range(i, j):
+ ip_data[k] = data[j]
+ else:
+ for k in range(i, frame_number):
+ ip_data[k] = last_value
+ else:
+ ip_data[i] = data[i]
+ last_value = data[i]
+
+ return ip_data[:, 0], vuv_vector[:, 0]
+
+ def resize_f0(self, x, target_len):
+ source = np.array(x)
+ source[source < 0.001] = np.nan
+ target = np.interp(
+ np.arange(0, len(source) * target_len, len(source)) / target_len,
+ np.arange(0, len(source)),
+ source,
+ )
+ res = np.nan_to_num(target)
+ return res
+
+ def compute_f0(self, wav, p_len=None):
+ if p_len is None:
+ p_len = wav.shape[0] // self.hop_length
+ f0, t = pyworld.harvest(
+ wav.astype(np.double),
+ fs=self.sampling_rate,
+ f0_ceil=self.f0_max,
+ f0_floor=self.f0_min,
+ frame_period=1000 * self.hop_length / self.sampling_rate,
+ )
+ f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.fs)
+ return self.interpolate_f0(self.resize_f0(f0, p_len))[0]
+
+ def compute_f0_uv(self, wav, p_len=None):
+ if p_len is None:
+ p_len = wav.shape[0] // self.hop_length
+ f0, t = pyworld.harvest(
+ wav.astype(np.double),
+ fs=self.sampling_rate,
+ f0_floor=self.f0_min,
+ f0_ceil=self.f0_max,
+ frame_period=1000 * self.hop_length / self.sampling_rate,
+ )
+ f0 = pyworld.stonemask(wav.astype(np.double), f0, t, self.sampling_rate)
+ return self.interpolate_f0(self.resize_f0(f0, p_len))
diff --git a/rvc/lib/infer_pack/modules/F0Predictor/PMF0Predictor.py b/rvc/lib/infer_pack/modules/F0Predictor/PMF0Predictor.py
new file mode 100644
index 0000000000000000000000000000000000000000..0fe1c744fafb0c55df5d81fad21ad83731cee5e8
--- /dev/null
+++ b/rvc/lib/infer_pack/modules/F0Predictor/PMF0Predictor.py
@@ -0,0 +1,93 @@
+from infer_pack.modules.F0Predictor.F0Predictor import F0Predictor
+import parselmouth
+import numpy as np
+
+
+class PMF0Predictor(F0Predictor):
+ def __init__(self, hop_length=512, f0_min=50, f0_max=1100, sampling_rate=44100):
+ self.hop_length = hop_length
+ self.f0_min = f0_min
+ self.f0_max = f0_max
+ self.sampling_rate = sampling_rate
+
+ def interpolate_f0(self, f0):
+ data = np.reshape(f0, (f0.size, 1))
+
+ vuv_vector = np.zeros((data.size, 1), dtype=np.float32)
+ vuv_vector[data > 0.0] = 1.0
+ vuv_vector[data <= 0.0] = 0.0
+
+ ip_data = data
+
+ frame_number = data.size
+ last_value = 0.0
+ for i in range(frame_number):
+ if data[i] <= 0.0:
+ j = i + 1
+ for j in range(i + 1, frame_number):
+ if data[j] > 0.0:
+ break
+ if j < frame_number - 1:
+ if last_value > 0.0:
+ step = (data[j] - data[i - 1]) / float(j - i)
+ for k in range(i, j):
+ ip_data[k] = data[i - 1] + step * (k - i + 1)
+ else:
+ for k in range(i, j):
+ ip_data[k] = data[j]
+ else:
+ for k in range(i, frame_number):
+ ip_data[k] = last_value
+ else:
+ ip_data[i] = data[i] # 这里可能存在一个没有必要的拷贝
+ last_value = data[i]
+
+ return ip_data[:, 0], vuv_vector[:, 0]
+
+ def compute_f0(self, wav, p_len=None):
+ x = wav
+ if p_len is None:
+ p_len = x.shape[0] // self.hop_length
+ else:
+ assert abs(p_len - x.shape[0] // self.hop_length) < 4, "pad length error"
+ time_step = self.hop_length / self.sampling_rate * 1000
+ f0 = (
+ parselmouth.Sound(x, self.sampling_rate)
+ .to_pitch_ac(
+ time_step=time_step / 1000,
+ voicing_threshold=0.6,
+ pitch_floor=self.f0_min,
+ pitch_ceiling=self.f0_max,
+ )
+ .selected_array["frequency"]
+ )
+
+ pad_size = (p_len - len(f0) + 1) // 2
+ if pad_size > 0 or p_len - len(f0) - pad_size > 0:
+ f0 = np.pad(f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant")
+ f0, uv = self.interpolate_f0(f0)
+ return f0
+
+ def compute_f0_uv(self, wav, p_len=None):
+ x = wav
+ if p_len is None:
+ p_len = x.shape[0] // self.hop_length
+ else:
+ assert abs(p_len - x.shape[0] // self.hop_length) < 4, "pad length error"
+ time_step = self.hop_length / self.sampling_rate * 1000
+ f0 = (
+ parselmouth.Sound(x, self.sampling_rate)
+ .to_pitch_ac(
+ time_step=time_step / 1000,
+ voicing_threshold=0.6,
+ pitch_floor=self.f0_min,
+ pitch_ceiling=self.f0_max,
+ )
+ .selected_array["frequency"]
+ )
+
+ pad_size = (p_len - len(f0) + 1) // 2
+ if pad_size > 0 or p_len - len(f0) - pad_size > 0:
+ f0 = np.pad(f0, [[pad_size, p_len - len(f0) - pad_size]], mode="constant")
+ f0, uv = self.interpolate_f0(f0)
+ return f0, uv
diff --git a/rvc/lib/infer_pack/modules/F0Predictor/__init__.py b/rvc/lib/infer_pack/modules/F0Predictor/__init__.py
new file mode 100644
index 0000000000000000000000000000000000000000..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
diff --git a/rvc/lib/infer_pack/transforms.py b/rvc/lib/infer_pack/transforms.py
new file mode 100644
index 0000000000000000000000000000000000000000..a11f799e023864ff7082c1f49c0cc18351a13b47
--- /dev/null
+++ b/rvc/lib/infer_pack/transforms.py
@@ -0,0 +1,209 @@
+import torch
+from torch.nn import functional as F
+
+import numpy as np
+
+
+DEFAULT_MIN_BIN_WIDTH = 1e-3
+DEFAULT_MIN_BIN_HEIGHT = 1e-3
+DEFAULT_MIN_DERIVATIVE = 1e-3
+
+
+def piecewise_rational_quadratic_transform(
+ inputs,
+ unnormalized_widths,
+ unnormalized_heights,
+ unnormalized_derivatives,
+ inverse=False,
+ tails=None,
+ tail_bound=1.0,
+ min_bin_width=DEFAULT_MIN_BIN_WIDTH,
+ min_bin_height=DEFAULT_MIN_BIN_HEIGHT,
+ min_derivative=DEFAULT_MIN_DERIVATIVE,
+):
+ if tails is None:
+ spline_fn = rational_quadratic_spline
+ spline_kwargs = {}
+ else:
+ spline_fn = unconstrained_rational_quadratic_spline
+ spline_kwargs = {"tails": tails, "tail_bound": tail_bound}
+
+ outputs, logabsdet = spline_fn(
+ inputs=inputs,
+ unnormalized_widths=unnormalized_widths,
+ unnormalized_heights=unnormalized_heights,
+ unnormalized_derivatives=unnormalized_derivatives,
+ inverse=inverse,
+ min_bin_width=min_bin_width,
+ min_bin_height=min_bin_height,
+ min_derivative=min_derivative,
+ **spline_kwargs
+ )
+ return outputs, logabsdet
+
+
+def searchsorted(bin_locations, inputs, eps=1e-6):
+ bin_locations[..., -1] += eps
+ return torch.sum(inputs[..., None] >= bin_locations, dim=-1) - 1
+
+
+def unconstrained_rational_quadratic_spline(
+ inputs,
+ unnormalized_widths,
+ unnormalized_heights,
+ unnormalized_derivatives,
+ inverse=False,
+ tails="linear",
+ tail_bound=1.0,
+ min_bin_width=DEFAULT_MIN_BIN_WIDTH,
+ min_bin_height=DEFAULT_MIN_BIN_HEIGHT,
+ min_derivative=DEFAULT_MIN_DERIVATIVE,
+):
+ inside_interval_mask = (inputs >= -tail_bound) & (inputs <= tail_bound)
+ outside_interval_mask = ~inside_interval_mask
+
+ outputs = torch.zeros_like(inputs)
+ logabsdet = torch.zeros_like(inputs)
+
+ if tails == "linear":
+ unnormalized_derivatives = F.pad(unnormalized_derivatives, pad=(1, 1))
+ constant = np.log(np.exp(1 - min_derivative) - 1)
+ unnormalized_derivatives[..., 0] = constant
+ unnormalized_derivatives[..., -1] = constant
+
+ outputs[outside_interval_mask] = inputs[outside_interval_mask]
+ logabsdet[outside_interval_mask] = 0
+ else:
+ raise RuntimeError("{} tails are not implemented.".format(tails))
+
+ (
+ outputs[inside_interval_mask],
+ logabsdet[inside_interval_mask],
+ ) = rational_quadratic_spline(
+ inputs=inputs[inside_interval_mask],
+ unnormalized_widths=unnormalized_widths[inside_interval_mask, :],
+ unnormalized_heights=unnormalized_heights[inside_interval_mask, :],
+ unnormalized_derivatives=unnormalized_derivatives[inside_interval_mask, :],
+ inverse=inverse,
+ left=-tail_bound,
+ right=tail_bound,
+ bottom=-tail_bound,
+ top=tail_bound,
+ min_bin_width=min_bin_width,
+ min_bin_height=min_bin_height,
+ min_derivative=min_derivative,
+ )
+
+ return outputs, logabsdet
+
+
+def rational_quadratic_spline(
+ inputs,
+ unnormalized_widths,
+ unnormalized_heights,
+ unnormalized_derivatives,
+ inverse=False,
+ left=0.0,
+ right=1.0,
+ bottom=0.0,
+ top=1.0,
+ min_bin_width=DEFAULT_MIN_BIN_WIDTH,
+ min_bin_height=DEFAULT_MIN_BIN_HEIGHT,
+ min_derivative=DEFAULT_MIN_DERIVATIVE,
+):
+ if torch.min(inputs) < left or torch.max(inputs) > right:
+ raise ValueError("Input to a transform is not within its domain")
+
+ num_bins = unnormalized_widths.shape[-1]
+
+ if min_bin_width * num_bins > 1.0:
+ raise ValueError("Minimal bin width too large for the number of bins")
+ if min_bin_height * num_bins > 1.0:
+ raise ValueError("Minimal bin height too large for the number of bins")
+
+ widths = F.softmax(unnormalized_widths, dim=-1)
+ widths = min_bin_width + (1 - min_bin_width * num_bins) * widths
+ cumwidths = torch.cumsum(widths, dim=-1)
+ cumwidths = F.pad(cumwidths, pad=(1, 0), mode="constant", value=0.0)
+ cumwidths = (right - left) * cumwidths + left
+ cumwidths[..., 0] = left
+ cumwidths[..., -1] = right
+ widths = cumwidths[..., 1:] - cumwidths[..., :-1]
+
+ derivatives = min_derivative + F.softplus(unnormalized_derivatives)
+
+ heights = F.softmax(unnormalized_heights, dim=-1)
+ heights = min_bin_height + (1 - min_bin_height * num_bins) * heights
+ cumheights = torch.cumsum(heights, dim=-1)
+ cumheights = F.pad(cumheights, pad=(1, 0), mode="constant", value=0.0)
+ cumheights = (top - bottom) * cumheights + bottom
+ cumheights[..., 0] = bottom
+ cumheights[..., -1] = top
+ heights = cumheights[..., 1:] - cumheights[..., :-1]
+
+ if inverse:
+ bin_idx = searchsorted(cumheights, inputs)[..., None]
+ else:
+ bin_idx = searchsorted(cumwidths, inputs)[..., None]
+
+ input_cumwidths = cumwidths.gather(-1, bin_idx)[..., 0]
+ input_bin_widths = widths.gather(-1, bin_idx)[..., 0]
+
+ input_cumheights = cumheights.gather(-1, bin_idx)[..., 0]
+ delta = heights / widths
+ input_delta = delta.gather(-1, bin_idx)[..., 0]
+
+ input_derivatives = derivatives.gather(-1, bin_idx)[..., 0]
+ input_derivatives_plus_one = derivatives[..., 1:].gather(-1, bin_idx)[..., 0]
+
+ input_heights = heights.gather(-1, bin_idx)[..., 0]
+
+ if inverse:
+ a = (inputs - input_cumheights) * (
+ input_derivatives + input_derivatives_plus_one - 2 * input_delta
+ ) + input_heights * (input_delta - input_derivatives)
+ b = input_heights * input_derivatives - (inputs - input_cumheights) * (
+ input_derivatives + input_derivatives_plus_one - 2 * input_delta
+ )
+ c = -input_delta * (inputs - input_cumheights)
+
+ discriminant = b.pow(2) - 4 * a * c
+ assert (discriminant >= 0).all()
+
+ root = (2 * c) / (-b - torch.sqrt(discriminant))
+ outputs = root * input_bin_widths + input_cumwidths
+
+ theta_one_minus_theta = root * (1 - root)
+ denominator = input_delta + (
+ (input_derivatives + input_derivatives_plus_one - 2 * input_delta)
+ * theta_one_minus_theta
+ )
+ derivative_numerator = input_delta.pow(2) * (
+ input_derivatives_plus_one * root.pow(2)
+ + 2 * input_delta * theta_one_minus_theta
+ + input_derivatives * (1 - root).pow(2)
+ )
+ logabsdet = torch.log(derivative_numerator) - 2 * torch.log(denominator)
+
+ return outputs, -logabsdet
+ else:
+ theta = (inputs - input_cumwidths) / input_bin_widths
+ theta_one_minus_theta = theta * (1 - theta)
+
+ numerator = input_heights * (
+ input_delta * theta.pow(2) + input_derivatives * theta_one_minus_theta
+ )
+ denominator = input_delta + (
+ (input_derivatives + input_derivatives_plus_one - 2 * input_delta)
+ * theta_one_minus_theta
+ )
+ outputs = input_cumheights + numerator / denominator
+
+ derivative_numerator = input_delta.pow(2) * (
+ input_derivatives_plus_one * theta.pow(2)
+ + 2 * input_delta * theta_one_minus_theta
+ + input_derivatives * (1 - theta).pow(2)
+ )
+ logabsdet = torch.log(derivative_numerator) - 2 * torch.log(denominator)
+
+ return outputs, logabsdet
diff --git a/rvc/lib/process/__pycache__/model_fusion.cpython-39.pyc b/rvc/lib/process/__pycache__/model_fusion.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..42f82683cd8b6bed93db11ae4bfa041bb169fa16
Binary files /dev/null and b/rvc/lib/process/__pycache__/model_fusion.cpython-39.pyc differ
diff --git a/rvc/lib/process/__pycache__/model_information.cpython-39.pyc b/rvc/lib/process/__pycache__/model_information.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..7577acc412f6bf1b9e48fc777fdb9c76d6df4860
Binary files /dev/null and b/rvc/lib/process/__pycache__/model_information.cpython-39.pyc differ
diff --git a/rvc/lib/process/model_fusion.py b/rvc/lib/process/model_fusion.py
new file mode 100644
index 0000000000000000000000000000000000000000..4cb3e0646a976f22f474d4ffec10c89db6a2130b
--- /dev/null
+++ b/rvc/lib/process/model_fusion.py
@@ -0,0 +1,33 @@
+import torch
+from collections import OrderedDict
+
+
+def extract(ckpt):
+ model = ckpt["model"]
+ opt = OrderedDict()
+ opt["weight"] = {key: value for key, value in model.items() if "enc_q" not in key}
+ return opt
+
+
+def model_fusion(model_name, pth_path_1, pth_path_2):
+ ckpt1 = torch.load(pth_path_1, map_location="cpu")
+ ckpt2 = torch.load(pth_path_2, map_location="cpu")
+ if "model" in ckpt1:
+ ckpt1 = extract(ckpt1)
+ else:
+ ckpt1 = ckpt1["weight"]
+ if "model" in ckpt2:
+ ckpt2 = extract(ckpt2)
+ else:
+ ckpt2 = ckpt2["weight"]
+ if sorted(ckpt1.keys()) != sorted(ckpt2.keys()):
+ return "Fail to merge the models. The model architectures are not the same."
+ opt = OrderedDict(
+ weight={
+ key: 1 * value.float() + (1 - 1) * ckpt2[key].float()
+ for key, value in ckpt1.items()
+ }
+ )
+ opt["info"] = f"Model fusion of {pth_path_1} and {pth_path_2}"
+ torch.save(opt, f"logs/{model_name}.pth")
+ print(f"Model fusion of {pth_path_1} and {pth_path_2} is done.")
diff --git a/rvc/lib/process/model_information.py b/rvc/lib/process/model_information.py
new file mode 100644
index 0000000000000000000000000000000000000000..25bc6704594f338df54c45164c68dd9a18a54f3d
--- /dev/null
+++ b/rvc/lib/process/model_information.py
@@ -0,0 +1,15 @@
+import torch
+
+def model_information(path):
+ model_data = torch.load(path, map_location="cpu")
+
+ print(f"Loaded model from {path}")
+
+ data = model_data
+
+ epochs = data.get("info", "None")
+ sr = data.get("sr", "None")
+ f0 = data.get("f0", "None")
+ version = data.get("version", "None")
+
+ return(f"Epochs: {epochs}\nSampling rate: {sr}\nPitch guidance: {f0}\nVersion: {version}")
\ No newline at end of file
diff --git a/rvc/lib/rmvpe.py b/rvc/lib/rmvpe.py
new file mode 100644
index 0000000000000000000000000000000000000000..2f50d085d9f5d848bcb6358392f6814ce9f0e1b9
--- /dev/null
+++ b/rvc/lib/rmvpe.py
@@ -0,0 +1,388 @@
+import torch.nn as nn
+import torch, numpy as np
+import torch.nn.functional as F
+from librosa.filters import mel
+
+
+class BiGRU(nn.Module):
+ def __init__(self, input_features, hidden_features, num_layers):
+ super(BiGRU, self).__init__()
+ self.gru = nn.GRU(
+ input_features,
+ hidden_features,
+ num_layers=num_layers,
+ batch_first=True,
+ bidirectional=True,
+ )
+
+ def forward(self, x):
+ return self.gru(x)[0]
+
+
+class ConvBlockRes(nn.Module):
+ def __init__(self, in_channels, out_channels, momentum=0.01):
+ super(ConvBlockRes, self).__init__()
+ self.conv = nn.Sequential(
+ nn.Conv2d(
+ in_channels=in_channels,
+ out_channels=out_channels,
+ kernel_size=(3, 3),
+ stride=(1, 1),
+ padding=(1, 1),
+ bias=False,
+ ),
+ nn.BatchNorm2d(out_channels, momentum=momentum),
+ nn.ReLU(),
+ nn.Conv2d(
+ in_channels=out_channels,
+ out_channels=out_channels,
+ kernel_size=(3, 3),
+ stride=(1, 1),
+ padding=(1, 1),
+ bias=False,
+ ),
+ nn.BatchNorm2d(out_channels, momentum=momentum),
+ nn.ReLU(),
+ )
+ if in_channels != out_channels:
+ self.shortcut = nn.Conv2d(in_channels, out_channels, (1, 1))
+ self.is_shortcut = True
+ else:
+ self.is_shortcut = False
+
+ def forward(self, x):
+ if self.is_shortcut:
+ return self.conv(x) + self.shortcut(x)
+ else:
+ return self.conv(x) + x
+
+
+class Encoder(nn.Module):
+ def __init__(
+ self,
+ in_channels,
+ in_size,
+ n_encoders,
+ kernel_size,
+ n_blocks,
+ out_channels=16,
+ momentum=0.01,
+ ):
+ super(Encoder, self).__init__()
+ self.n_encoders = n_encoders
+ self.bn = nn.BatchNorm2d(in_channels, momentum=momentum)
+ self.layers = nn.ModuleList()
+ self.latent_channels = []
+ for i in range(self.n_encoders):
+ self.layers.append(
+ ResEncoderBlock(
+ in_channels, out_channels, kernel_size, n_blocks, momentum=momentum
+ )
+ )
+ self.latent_channels.append([out_channels, in_size])
+ in_channels = out_channels
+ out_channels *= 2
+ in_size //= 2
+ self.out_size = in_size
+ self.out_channel = out_channels
+
+ def forward(self, x):
+ concat_tensors = []
+ x = self.bn(x)
+ for i in range(self.n_encoders):
+ _, x = self.layers[i](x)
+ concat_tensors.append(_)
+ return x, concat_tensors
+
+
+class ResEncoderBlock(nn.Module):
+ def __init__(
+ self, in_channels, out_channels, kernel_size, n_blocks=1, momentum=0.01
+ ):
+ super(ResEncoderBlock, self).__init__()
+ self.n_blocks = n_blocks
+ self.conv = nn.ModuleList()
+ self.conv.append(ConvBlockRes(in_channels, out_channels, momentum))
+ for i in range(n_blocks - 1):
+ self.conv.append(ConvBlockRes(out_channels, out_channels, momentum))
+ self.kernel_size = kernel_size
+ if self.kernel_size is not None:
+ self.pool = nn.AvgPool2d(kernel_size=kernel_size)
+
+ def forward(self, x):
+ for i in range(self.n_blocks):
+ x = self.conv[i](x)
+ if self.kernel_size is not None:
+ return x, self.pool(x)
+ else:
+ return x
+
+
+class Intermediate(nn.Module): #
+ def __init__(self, in_channels, out_channels, n_inters, n_blocks, momentum=0.01):
+ super(Intermediate, self).__init__()
+ self.n_inters = n_inters
+ self.layers = nn.ModuleList()
+ self.layers.append(
+ ResEncoderBlock(in_channels, out_channels, None, n_blocks, momentum)
+ )
+ for i in range(self.n_inters - 1):
+ self.layers.append(
+ ResEncoderBlock(out_channels, out_channels, None, n_blocks, momentum)
+ )
+
+ def forward(self, x):
+ for i in range(self.n_inters):
+ x = self.layers[i](x)
+ return x
+
+
+class ResDecoderBlock(nn.Module):
+ def __init__(self, in_channels, out_channels, stride, n_blocks=1, momentum=0.01):
+ super(ResDecoderBlock, self).__init__()
+ out_padding = (0, 1) if stride == (1, 2) else (1, 1)
+ self.n_blocks = n_blocks
+ self.conv1 = nn.Sequential(
+ nn.ConvTranspose2d(
+ in_channels=in_channels,
+ out_channels=out_channels,
+ kernel_size=(3, 3),
+ stride=stride,
+ padding=(1, 1),
+ output_padding=out_padding,
+ bias=False,
+ ),
+ nn.BatchNorm2d(out_channels, momentum=momentum),
+ nn.ReLU(),
+ )
+ self.conv2 = nn.ModuleList()
+ self.conv2.append(ConvBlockRes(out_channels * 2, out_channels, momentum))
+ for i in range(n_blocks - 1):
+ self.conv2.append(ConvBlockRes(out_channels, out_channels, momentum))
+
+ def forward(self, x, concat_tensor):
+ x = self.conv1(x)
+ x = torch.cat((x, concat_tensor), dim=1)
+ for i in range(self.n_blocks):
+ x = self.conv2[i](x)
+ return x
+
+
+class Decoder(nn.Module):
+ def __init__(self, in_channels, n_decoders, stride, n_blocks, momentum=0.01):
+ super(Decoder, self).__init__()
+ self.layers = nn.ModuleList()
+ self.n_decoders = n_decoders
+ for i in range(self.n_decoders):
+ out_channels = in_channels // 2
+ self.layers.append(
+ ResDecoderBlock(in_channels, out_channels, stride, n_blocks, momentum)
+ )
+ in_channels = out_channels
+
+ def forward(self, x, concat_tensors):
+ for i in range(self.n_decoders):
+ x = self.layers[i](x, concat_tensors[-1 - i])
+ return x
+
+
+class DeepUnet(nn.Module):
+ def __init__(
+ self,
+ kernel_size,
+ n_blocks,
+ en_de_layers=5,
+ inter_layers=4,
+ in_channels=1,
+ en_out_channels=16,
+ ):
+ super(DeepUnet, self).__init__()
+ self.encoder = Encoder(
+ in_channels, 128, en_de_layers, kernel_size, n_blocks, en_out_channels
+ )
+ self.intermediate = Intermediate(
+ self.encoder.out_channel // 2,
+ self.encoder.out_channel,
+ inter_layers,
+ n_blocks,
+ )
+ self.decoder = Decoder(
+ self.encoder.out_channel, en_de_layers, kernel_size, n_blocks
+ )
+
+ def forward(self, x):
+ x, concat_tensors = self.encoder(x)
+ x = self.intermediate(x)
+ x = self.decoder(x, concat_tensors)
+ return x
+
+
+class E2E(nn.Module):
+ def __init__(
+ self,
+ n_blocks,
+ n_gru,
+ kernel_size,
+ en_de_layers=5,
+ inter_layers=4,
+ in_channels=1,
+ en_out_channels=16,
+ ):
+ super(E2E, self).__init__()
+ self.unet = DeepUnet(
+ kernel_size,
+ n_blocks,
+ en_de_layers,
+ inter_layers,
+ in_channels,
+ en_out_channels,
+ )
+ self.cnn = nn.Conv2d(en_out_channels, 3, (3, 3), padding=(1, 1))
+ if n_gru:
+ self.fc = nn.Sequential(
+ BiGRU(3 * 128, 256, n_gru),
+ nn.Linear(512, 360),
+ nn.Dropout(0.25),
+ nn.Sigmoid(),
+ )
+
+ def forward(self, mel):
+ mel = mel.transpose(-1, -2).unsqueeze(1)
+ x = self.cnn(self.unet(mel)).transpose(1, 2).flatten(-2)
+ x = self.fc(x)
+ return x
+
+
+class MelSpectrogram(torch.nn.Module):
+ def __init__(
+ self,
+ is_half,
+ n_mel_channels,
+ sampling_rate,
+ win_length,
+ hop_length,
+ n_fft=None,
+ mel_fmin=0,
+ mel_fmax=None,
+ clamp=1e-5,
+ ):
+ super().__init__()
+ n_fft = win_length if n_fft is None else n_fft
+ self.hann_window = {}
+ mel_basis = mel(
+ sr=sampling_rate,
+ n_fft=n_fft,
+ n_mels=n_mel_channels,
+ fmin=mel_fmin,
+ fmax=mel_fmax,
+ htk=True,
+ )
+ mel_basis = torch.from_numpy(mel_basis).float()
+ self.register_buffer("mel_basis", mel_basis)
+ self.n_fft = win_length if n_fft is None else n_fft
+ self.hop_length = hop_length
+ self.win_length = win_length
+ self.sampling_rate = sampling_rate
+ self.n_mel_channels = n_mel_channels
+ self.clamp = clamp
+ self.is_half = is_half
+
+ def forward(self, audio, keyshift=0, speed=1, center=True):
+ factor = 2 ** (keyshift / 12)
+ n_fft_new = int(np.round(self.n_fft * factor))
+ win_length_new = int(np.round(self.win_length * factor))
+ hop_length_new = int(np.round(self.hop_length * speed))
+ keyshift_key = str(keyshift) + "_" + str(audio.device)
+ if keyshift_key not in self.hann_window:
+ self.hann_window[keyshift_key] = torch.hann_window(win_length_new).to(
+ audio.device
+ )
+ fft = torch.stft(
+ audio,
+ n_fft=n_fft_new,
+ hop_length=hop_length_new,
+ win_length=win_length_new,
+ window=self.hann_window[keyshift_key],
+ center=center,
+ return_complex=True,
+ )
+ magnitude = torch.sqrt(fft.real.pow(2) + fft.imag.pow(2))
+ if keyshift != 0:
+ size = self.n_fft // 2 + 1
+ resize = magnitude.size(1)
+ if resize < size:
+ magnitude = F.pad(magnitude, (0, 0, 0, size - resize))
+ magnitude = magnitude[:, :size, :] * self.win_length / win_length_new
+ mel_output = torch.matmul(self.mel_basis, magnitude)
+ if self.is_half == True:
+ mel_output = mel_output.half()
+ log_mel_spec = torch.log(torch.clamp(mel_output, min=self.clamp))
+ return log_mel_spec
+
+
+class RMVPE:
+ def __init__(self, model_path, is_half, device=None):
+ self.resample_kernel = {}
+ model = E2E(4, 1, (2, 2))
+ ckpt = torch.load(model_path, map_location="cpu")
+ model.load_state_dict(ckpt)
+ model.eval()
+ if is_half == True:
+ model = model.half()
+ self.model = model
+ self.resample_kernel = {}
+ self.is_half = is_half
+ if device is None:
+ device = "cuda" if torch.cuda.is_available() else "cpu"
+ self.device = device
+ self.mel_extractor = MelSpectrogram(
+ is_half, 128, 16000, 1024, 160, None, 30, 8000
+ ).to(device)
+ self.model = self.model.to(device)
+ cents_mapping = 20 * np.arange(360) + 1997.3794084376191
+ self.cents_mapping = np.pad(cents_mapping, (4, 4)) # 368
+
+ def mel2hidden(self, mel):
+ with torch.no_grad():
+ n_frames = mel.shape[-1]
+ mel = F.pad(
+ mel, (0, 32 * ((n_frames - 1) // 32 + 1) - n_frames), mode="reflect"
+ )
+ hidden = self.model(mel)
+ return hidden[:, :n_frames]
+
+ def decode(self, hidden, thred=0.03):
+ cents_pred = self.to_local_average_cents(hidden, thred=thred)
+ f0 = 10 * (2 ** (cents_pred / 1200))
+ f0[f0 == 10] = 0
+ return f0
+
+ def infer_from_audio(self, audio, thred=0.03):
+ audio = torch.from_numpy(audio).float().to(self.device).unsqueeze(0)
+ mel = self.mel_extractor(audio, center=True)
+ hidden = self.mel2hidden(mel)
+ hidden = hidden.squeeze(0).cpu().numpy()
+ if self.is_half == True:
+ hidden = hidden.astype("float32")
+ f0 = self.decode(hidden, thred=thred)
+ return f0
+
+ def to_local_average_cents(self, salience, thred=0.05):
+ center = np.argmax(salience, axis=1)
+ salience = np.pad(salience, ((0, 0), (4, 4)))
+ center += 4
+ todo_salience = []
+ todo_cents_mapping = []
+ starts = center - 4
+ ends = center + 5
+ for idx in range(salience.shape[0]):
+ todo_salience.append(salience[:, starts[idx] : ends[idx]][idx])
+ todo_cents_mapping.append(self.cents_mapping[starts[idx] : ends[idx]])
+ todo_salience = np.array(todo_salience)
+ todo_cents_mapping = np.array(todo_cents_mapping)
+ product_sum = np.sum(todo_salience * todo_cents_mapping, 1)
+ weight_sum = np.sum(todo_salience, 1)
+ devided = product_sum / weight_sum
+ maxx = np.max(salience, axis=1)
+ devided[maxx <= thred] = 0
+ return devided
diff --git a/rvc/lib/tools/__pycache__/pretrained_selector.cpython-39.pyc b/rvc/lib/tools/__pycache__/pretrained_selector.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..b1d9a4a7b59b696d1e7edd763b05a2029b21ff38
Binary files /dev/null and b/rvc/lib/tools/__pycache__/pretrained_selector.cpython-39.pyc differ
diff --git a/rvc/lib/tools/__pycache__/split_audio.cpython-39.pyc b/rvc/lib/tools/__pycache__/split_audio.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..fe1958da1a4ca0373b8ba84d51f34c8286d809d2
Binary files /dev/null and b/rvc/lib/tools/__pycache__/split_audio.cpython-39.pyc differ
diff --git a/rvc/lib/tools/__pycache__/validators.cpython-39.pyc b/rvc/lib/tools/__pycache__/validators.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..bf9c96891d392c980808e2eb0decd599c917d86e
Binary files /dev/null and b/rvc/lib/tools/__pycache__/validators.cpython-39.pyc differ
diff --git a/rvc/lib/tools/gdown.py b/rvc/lib/tools/gdown.py
new file mode 100644
index 0000000000000000000000000000000000000000..5f13a56ce49c30940d2827ae05f570b9f59f0d58
--- /dev/null
+++ b/rvc/lib/tools/gdown.py
@@ -0,0 +1,402 @@
+from __future__ import print_function
+
+import json
+import os
+import os.path as osp
+import re
+import warnings
+from six.moves import urllib_parse
+import shutil
+import sys
+import tempfile
+import textwrap
+import time
+
+import requests
+import six
+import tqdm
+
+def indent(text, prefix):
+ def prefixed_lines():
+ for line in text.splitlines(True):
+ yield (prefix + line if line.strip() else line)
+
+ return "".join(prefixed_lines())
+
+class FileURLRetrievalError(Exception):
+ pass
+
+
+class FolderContentsMaximumLimitError(Exception):
+ pass
+
+def parse_url(url, warning=True):
+ """Parse URLs especially for Google Drive links.
+
+ file_id: ID of file on Google Drive.
+ is_download_link: Flag if it is download link of Google Drive.
+ """
+ parsed = urllib_parse.urlparse(url)
+ query = urllib_parse.parse_qs(parsed.query)
+ is_gdrive = parsed.hostname in ["drive.google.com", "docs.google.com"]
+ is_download_link = parsed.path.endswith("/uc")
+
+ if not is_gdrive:
+ return is_gdrive, is_download_link
+
+ file_id = None
+ if "id" in query:
+ file_ids = query["id"]
+ if len(file_ids) == 1:
+ file_id = file_ids[0]
+ else:
+ patterns = [
+ r"^/file/d/(.*?)/(edit|view)$",
+ r"^/file/u/[0-9]+/d/(.*?)/(edit|view)$",
+ r"^/document/d/(.*?)/(edit|htmlview|view)$",
+ r"^/document/u/[0-9]+/d/(.*?)/(edit|htmlview|view)$",
+ r"^/presentation/d/(.*?)/(edit|htmlview|view)$",
+ r"^/presentation/u/[0-9]+/d/(.*?)/(edit|htmlview|view)$",
+ r"^/spreadsheets/d/(.*?)/(edit|htmlview|view)$",
+ r"^/spreadsheets/u/[0-9]+/d/(.*?)/(edit|htmlview|view)$",
+ ]
+ for pattern in patterns:
+ match = re.match(pattern, parsed.path)
+ if match:
+ file_id = match.groups()[0]
+ break
+
+ if warning and not is_download_link:
+ warnings.warn(
+ "You specified a Google Drive link that is not the correct link "
+ "to download a file. You might want to try `--fuzzy` option "
+ "or the following url: {url}".format(
+ url="https://drive.google.com/uc?id={}".format(file_id)
+ )
+ )
+
+ return file_id, is_download_link
+
+
+CHUNK_SIZE = 512 * 1024 # 512KB
+home = osp.expanduser("~")
+
+
+def get_url_from_gdrive_confirmation(contents):
+ url = ""
+ m = re.search(r'href="(\/uc\?export=download[^"]+)', contents)
+ if m:
+ url = "https://docs.google.com" + m.groups()[0]
+ url = url.replace("&", "&")
+ return url
+
+ m = re.search(r'href="/open\?id=([^"]+)"', contents)
+ if m:
+ url = m.groups()[0]
+ uuid = re.search(r'(.*)
', contents)
+ if m:
+ error = m.groups()[0]
+ raise FileURLRetrievalError(error)
+
+ raise FileURLRetrievalError(
+ "Cannot retrieve the public link of the file. "
+ "You may need to change the permission to "
+ "'Anyone with the link', or have had many accesses."
+ )
+def _get_session(proxy, use_cookies, return_cookies_file=False):
+ sess = requests.session()
+
+ sess.headers.update(
+ {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6)"}
+ )
+
+ if proxy is not None:
+ sess.proxies = {"http": proxy, "https": proxy}
+ print("Using proxy:", proxy, file=sys.stderr)
+
+ # Load cookies if exists
+ cookies_file = osp.join(home, ".cache/gdown/cookies.json")
+ if osp.exists(cookies_file) and use_cookies:
+ with open(cookies_file) as f:
+ cookies = json.load(f)
+ for k, v in cookies:
+ sess.cookies[k] = v
+
+ if return_cookies_file:
+ return sess, cookies_file
+ else:
+ return sess
+
+
+def download(
+ url=None,
+ output=None,
+ quiet=False,
+ proxy=None,
+ speed=None,
+ use_cookies=True,
+ verify=True,
+ id=None,
+ fuzzy=True,
+ resume=False,
+ format=None,
+):
+ """Download file from URL.
+
+ Parameters
+ ----------
+ url: str
+ URL. Google Drive URL is also supported.
+ output: str
+ Output filename. Default is basename of URL.
+ quiet: bool
+ Suppress terminal output. Default is False.
+ proxy: str
+ Proxy.
+ speed: float
+ Download byte size per second (e.g., 256KB/s = 256 * 1024).
+ use_cookies: bool
+ Flag to use cookies. Default is True.
+ verify: bool or string
+ Either a bool, in which case it controls whether the server's TLS
+ certificate is verified, or a string, in which case it must be a path
+ to a CA bundle to use. Default is True.
+ id: str
+ Google Drive's file ID.
+ fuzzy: bool
+ Fuzzy extraction of Google Drive's file Id. Default is False.
+ resume: bool
+ Resume the download from existing tmp file if possible.
+ Default is False.
+ format: str, optional
+ Format of Google Docs, Spreadsheets and Slides. Default is:
+ - Google Docs: 'docx'
+ - Google Spreadsheet: 'xlsx'
+ - Google Slides: 'pptx'
+
+ Returns
+ -------
+ output: str
+ Output filename.
+ """
+ if not (id is None) ^ (url is None):
+ raise ValueError("Either url or id has to be specified")
+ if id is not None:
+ url = "https://drive.google.com/uc?id={id}".format(id=id)
+
+ url_origin = url
+
+ sess, cookies_file = _get_session(
+ proxy=proxy, use_cookies=use_cookies, return_cookies_file=True
+ )
+
+ gdrive_file_id, is_gdrive_download_link = parse_url(url, warning=not fuzzy)
+
+ if fuzzy and gdrive_file_id:
+ # overwrite the url with fuzzy match of a file id
+ url = "https://drive.google.com/uc?id={id}".format(id=gdrive_file_id)
+ url_origin = url
+ is_gdrive_download_link = True
+
+
+
+ while True:
+ res = sess.get(url, stream=True, verify=verify)
+
+ if url == url_origin and res.status_code == 500:
+ # The file could be Google Docs or Spreadsheets.
+ url = "https://drive.google.com/open?id={id}".format(
+ id=gdrive_file_id
+ )
+ continue
+
+ if res.headers["Content-Type"].startswith("text/html"):
+ m = re.search("(.+)", res.text)
+ if m and m.groups()[0].endswith(" - Google Docs"):
+ url = (
+ "https://docs.google.com/document/d/{id}/export"
+ "?format={format}".format(
+ id=gdrive_file_id,
+ format="docx" if format is None else format,
+ )
+ )
+ continue
+ elif m and m.groups()[0].endswith(" - Google Sheets"):
+ url = (
+ "https://docs.google.com/spreadsheets/d/{id}/export"
+ "?format={format}".format(
+ id=gdrive_file_id,
+ format="xlsx" if format is None else format,
+ )
+ )
+ continue
+ elif m and m.groups()[0].endswith(" - Google Slides"):
+ url = (
+ "https://docs.google.com/presentation/d/{id}/export"
+ "?format={format}".format(
+ id=gdrive_file_id,
+ format="pptx" if format is None else format,
+ )
+ )
+ continue
+ elif (
+ "Content-Disposition" in res.headers
+ and res.headers["Content-Disposition"].endswith("pptx")
+ and format not in {None, "pptx"}
+ ):
+ url = (
+ "https://docs.google.com/presentation/d/{id}/export"
+ "?format={format}".format(
+ id=gdrive_file_id,
+ format="pptx" if format is None else format,
+ )
+ )
+ continue
+
+ if use_cookies:
+ if not osp.exists(osp.dirname(cookies_file)):
+ os.makedirs(osp.dirname(cookies_file))
+ # Save cookies
+ with open(cookies_file, "w") as f:
+ cookies = [
+ (k, v)
+ for k, v in sess.cookies.items()
+ if not k.startswith("download_warning_")
+ ]
+ json.dump(cookies, f, indent=2)
+
+ if "Content-Disposition" in res.headers:
+ # This is the file
+ break
+ if not (gdrive_file_id and is_gdrive_download_link):
+ break
+
+ # Need to redirect with confirmation
+ try:
+ url = get_url_from_gdrive_confirmation(res.text)
+ except FileURLRetrievalError as e:
+ message = (
+ "Failed to retrieve file url:\n\n{}\n\n"
+ "You may still be able to access the file from the browser:"
+ "\n\n\t{}\n\n"
+ "but Gdown can't. Please check connections and permissions."
+ ).format(
+ indent("\n".join(textwrap.wrap(str(e))), prefix="\t"),
+ url_origin,
+ )
+ raise FileURLRetrievalError(message)
+
+ if gdrive_file_id and is_gdrive_download_link:
+ content_disposition = six.moves.urllib_parse.unquote(
+ res.headers["Content-Disposition"]
+ )
+
+ m = re.search(r"filename\*=UTF-8''(.*)", content_disposition)
+ if not m:
+ m = re.search(r'filename=["\']?(.*?)["\']?$', content_disposition)
+ filename_from_url = m.groups()[0]
+ filename_from_url = filename_from_url.replace(osp.sep, "_")
+ else:
+ filename_from_url = osp.basename(url)
+
+ if output is None:
+ output = filename_from_url
+
+ output_is_path = isinstance(output, six.string_types)
+ if output_is_path and output.endswith(osp.sep):
+ if not osp.exists(output):
+ os.makedirs(output)
+ output = osp.join(output, filename_from_url)
+
+ if output_is_path:
+ existing_tmp_files = []
+ for file in os.listdir(osp.dirname(output) or "."):
+ if file.startswith(osp.basename(output)):
+ existing_tmp_files.append(osp.join(osp.dirname(output), file))
+ if resume and existing_tmp_files:
+ if len(existing_tmp_files) != 1:
+ print(
+ "There are multiple temporary files to resume:",
+ file=sys.stderr,
+ )
+ print("\n")
+ for file in existing_tmp_files:
+ print("\t", file, file=sys.stderr)
+ print("\n")
+ print(
+ "Please remove them except one to resume downloading.",
+ file=sys.stderr,
+ )
+ return
+ tmp_file = existing_tmp_files[0]
+ else:
+ resume = False
+ # mkstemp is preferred, but does not work on Windows
+ # https://github.com/wkentaro/gdown/issues/153
+ tmp_file = tempfile.mktemp(
+ suffix=tempfile.template,
+ prefix=osp.basename(output),
+ dir=osp.dirname(output),
+ )
+ f = open(tmp_file, "ab")
+ else:
+ tmp_file = None
+ f = output
+
+ if tmp_file is not None and f.tell() != 0:
+ headers = {"Range": "bytes={}-".format(f.tell())}
+ res = sess.get(url, headers=headers, stream=True, verify=verify)
+
+ if not quiet:
+ # print("Downloading...", file=sys.stderr)
+ if resume:
+ print("Resume:", tmp_file, file=sys.stderr)
+ # if url_origin != url:
+ # print("From (original):", url_origin, file=sys.stderr)
+ # print("From (redirected):", url, file=sys.stderr)
+ # else:
+ # print("From:", url, file=sys.stderr)
+ print(
+ "To:",
+ osp.abspath(output) if output_is_path else output,
+ file=sys.stderr,
+ )
+
+ try:
+ total = res.headers.get("Content-Length")
+ if total is not None:
+ total = int(total)
+ if not quiet:
+ pbar = tqdm.tqdm(total=total, unit="B", unit_scale=True)
+ t_start = time.time()
+ for chunk in res.iter_content(chunk_size=CHUNK_SIZE):
+ f.write(chunk)
+ if not quiet:
+ pbar.update(len(chunk))
+ if speed is not None:
+ elapsed_time_expected = 1.0 * pbar.n / speed
+ elapsed_time = time.time() - t_start
+ if elapsed_time < elapsed_time_expected:
+ time.sleep(elapsed_time_expected - elapsed_time)
+ if not quiet:
+ pbar.close()
+ if tmp_file:
+ f.close()
+ shutil.move(tmp_file, output)
+ finally:
+ sess.close()
+
+ return output
diff --git a/rvc/lib/tools/launch_tensorboard.py b/rvc/lib/tools/launch_tensorboard.py
new file mode 100644
index 0000000000000000000000000000000000000000..3c628d3895cbbbfdec024ec5ad493a711f55acd4
--- /dev/null
+++ b/rvc/lib/tools/launch_tensorboard.py
@@ -0,0 +1,15 @@
+import time
+from tensorboard import program
+
+log_path = "logs"
+
+if __name__ == "__main__":
+ tb = program.TensorBoard()
+ tb.configure(argv=[None, "--logdir", log_path])
+ url = tb.launch()
+ print(
+ f"Access the tensorboard using the following link:\n{url}?pinnedCards=%5B%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fg%2Ftotal%22%7D%2C%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fd%2Ftotal%22%7D%2C%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fg%2Fkl%22%7D%2C%7B%22plugin%22%3A%22scalars%22%2C%22tag%22%3A%22loss%2Fg%2Fmel%22%7D%5D"
+ )
+
+ while True:
+ time.sleep(600)
diff --git a/rvc/lib/tools/model_download.py b/rvc/lib/tools/model_download.py
new file mode 100644
index 0000000000000000000000000000000000000000..4356dcc904fa64ea8f8136e1724398bd88154bc0
--- /dev/null
+++ b/rvc/lib/tools/model_download.py
@@ -0,0 +1,225 @@
+import os
+import sys
+import wget
+import zipfile
+from bs4 import BeautifulSoup
+import requests
+from urllib.parse import unquote
+import re
+
+def find_folder_parent(search_dir, folder_name):
+ for dirpath, dirnames, _ in os.walk(search_dir):
+ if folder_name in dirnames:
+ return os.path.abspath(dirpath)
+ return None
+
+now_dir = os.getcwd()
+sys.path.append(now_dir)
+
+import rvc.lib.tools.gdown as gdown
+
+file_path = find_folder_parent(now_dir, "logs")
+
+zips_path = os.getcwd() + "/logs/zips"
+
+
+def search_pth_index(folder):
+ pth_paths = [
+ os.path.join(folder, file)
+ for file in os.listdir(folder)
+ if os.path.isfile(os.path.join(folder, file)) and file.endswith(".pth")
+ ]
+ index_paths = [
+ os.path.join(folder, file)
+ for file in os.listdir(folder)
+ if os.path.isfile(os.path.join(folder, file)) and file.endswith(".index")
+ ]
+
+ return pth_paths, index_paths
+
+
+def get_mediafire_download_link(url):
+ response = requests.get(url)
+ response.raise_for_status()
+ soup = BeautifulSoup(response.text, "html.parser")
+ download_button = soup.find(
+ "a", {"class": "input popsok", "aria-label": "Download file"}
+ )
+ if download_button:
+ download_link = download_button.get("href")
+ return download_link
+ else:
+ return None
+
+
+def download_from_url(url):
+ os.makedirs(zips_path, exist_ok=True)
+ if url != "":
+ if "drive.google.com" in url:
+ if "file/d/" in url:
+ file_id = url.split("file/d/")[1].split("/")[0]
+ elif "id=" in url:
+ file_id = url.split("id=")[1].split("&")[0]
+ else:
+ return None
+
+ if file_id:
+ os.chdir(zips_path)
+ try:
+ gdown.download(
+ f"https://drive.google.com/uc?id={file_id}",
+ quiet=False,
+ fuzzy=True,
+ )
+ except Exception as error:
+ error_message = str(error)
+ if (
+ "Too many users have viewed or downloaded this file recently"
+ in error_message
+ ):
+ os.chdir(now_dir)
+ return "too much use"
+ elif (
+ "Cannot retrieve the public link of the file." in error_message
+ ):
+ os.chdir(now_dir)
+ return "private link"
+ else:
+ print(error_message)
+ os.chdir(now_dir)
+ return None
+
+ elif "/blob/" in url or "/resolve/" in url:
+ os.chdir(zips_path)
+ if "/blob/" in url:
+ url = url.replace("/blob/", "/resolve/")
+
+ response = requests.get(url, stream=True)
+ if response.status_code == 200:
+ file_name = url.split("/")[-1]
+ file_name = unquote(file_name)
+
+ file_name = re.sub(r"[^a-zA-Z0-9_.-]", "_", file_name)
+
+ total_size_in_bytes = int(response.headers.get("content-length", 0))
+ block_size = 1024
+ progress_bar_length = 50
+ progress = 0
+
+ with open(os.path.join(zips_path, file_name), "wb") as file:
+ for data in response.iter_content(block_size):
+ file.write(data)
+ progress += len(data)
+ progress_percent = int((progress / total_size_in_bytes) * 100)
+ num_dots = int(
+ (progress / total_size_in_bytes) * progress_bar_length
+ )
+ progress_bar = (
+ "["
+ + "." * num_dots
+ + " " * (progress_bar_length - num_dots)
+ + "]"
+ )
+ print(
+ f"{progress_percent}% {progress_bar} {progress}/{total_size_in_bytes} ",
+ end="\r",
+ )
+ if progress_percent == 100:
+ print("\n")
+
+ else:
+ os.chdir(now_dir)
+ return None
+ elif "/tree/main" in url:
+ os.chdir(zips_path)
+ response = requests.get(url)
+ soup = BeautifulSoup(response.content, "html.parser")
+ temp_url = ""
+ for link in soup.find_all("a", href=True):
+ if link["href"].endswith(".zip"):
+ temp_url = link["href"]
+ break
+ if temp_url:
+ url = temp_url
+ url = url.replace("blob", "resolve")
+ if "huggingface.co" not in url:
+ url = "https://huggingface.co" + url
+
+ wget.download(url)
+ else:
+ os.chdir(now_dir)
+ return None
+ else:
+ try:
+ os.chdir(zips_path)
+ wget.download(url)
+ except Exception as error:
+ os.chdir(now_dir)
+ print(error)
+ return None
+
+ for currentPath, _, zipFiles in os.walk(zips_path):
+ for Files in zipFiles:
+ filePart = Files.split(".")
+ extensionFile = filePart[len(filePart) - 1]
+ filePart.pop()
+ nameFile = "_".join(filePart)
+ realPath = os.path.join(currentPath, Files)
+ os.rename(realPath, nameFile + "." + extensionFile)
+
+ os.chdir(now_dir)
+ return "downloaded"
+
+ os.chdir(now_dir)
+ return None
+
+
+def extract_and_show_progress(zipfile_path, unzips_path):
+ try:
+ with zipfile.ZipFile(zipfile_path, "r") as zip_ref:
+ for file_info in zip_ref.infolist():
+ zip_ref.extract(file_info, unzips_path)
+ os.remove(zipfile_path)
+ return True
+ except Exception as error:
+ print(error)
+ return False
+
+
+def unzip_file(zip_path, zip_file_name):
+ zip_file_path = os.path.join(zip_path, zip_file_name + ".zip")
+ extract_path = os.path.join(file_path, zip_file_name)
+ with zipfile.ZipFile(zip_file_path, "r") as zip_ref:
+ zip_ref.extractall(extract_path)
+ os.remove(zip_file_path)
+
+
+url = sys.argv[1]
+verify = download_from_url(url)
+
+if verify == "downloaded":
+ extract_folder_path = ""
+ for filename in os.listdir(zips_path):
+ if filename.endswith(".zip"):
+ zipfile_path = os.path.join(zips_path, filename)
+ print("Proceeding with the extraction...")
+
+ model_name = os.path.basename(zipfile_path)
+ extract_folder_path = os.path.join(
+ "logs",
+ os.path.normpath(str(model_name).replace(".zip", "")),
+ )
+
+ success = extract_and_show_progress(zipfile_path, extract_folder_path)
+ if success:
+ print(f"Model {model_name} downloaded!")
+ else:
+ print(f"Error downloading {model_name}")
+ sys.exit()
+ if extract_folder_path == "":
+ print("No zip founded...")
+ sys.exit()
+ result = search_pth_index(extract_folder_path)
+else:
+ message = "Error"
+ sys.exit()
diff --git a/rvc/lib/tools/prerequisites_download.py b/rvc/lib/tools/prerequisites_download.py
new file mode 100644
index 0000000000000000000000000000000000000000..7e46d24251bb0c38c4294f04f60af51fa5470cfb
--- /dev/null
+++ b/rvc/lib/tools/prerequisites_download.py
@@ -0,0 +1,84 @@
+import os
+import wget
+import sys
+
+url_base = "https://huggingface.co/lj1995/VoiceConversionWebUI/resolve/main"
+models_download = [
+ (
+ "pretrained/",
+ [
+ "D32k.pth",
+ "D40k.pth",
+ "D48k.pth",
+ "G32k.pth",
+ "G40k.pth",
+ "G48k.pth",
+ "f0D32k.pth",
+ "f0D40k.pth",
+ "f0D48k.pth",
+ "f0G32k.pth",
+ "f0G40k.pth",
+ "f0G48k.pth",
+ ],
+ ),
+ (
+ "pretrained_v2/",
+ [
+ "D32k.pth",
+ "D40k.pth",
+ "D48k.pth",
+ "G32k.pth",
+ "G40k.pth",
+ "G48k.pth",
+ "f0D32k.pth",
+ "f0D40k.pth",
+ "f0D48k.pth",
+ "f0G32k.pth",
+ "f0G40k.pth",
+ "f0G48k.pth",
+ ],
+ ),
+]
+
+models_file = [
+ "hubert_base.pt",
+ "rmvpe.pt",
+ # "rmvpe.onnx",
+]
+
+executables_file = [
+ "ffmpeg.exe",
+ "ffprobe.exe",
+]
+
+folder_mapping = {
+ "pretrained/": "rvc/pretraineds/pretrained_v1/",
+ "pretrained_v2/": "rvc/pretraineds/pretrained_v2/",
+}
+
+for file_name in models_file:
+ destination_path = os.path.join(file_name)
+ url = f"{url_base}/{file_name}"
+ if not os.path.exists(destination_path):
+ os.makedirs(os.path.dirname(destination_path) or ".", exist_ok=True)
+ print(f"\nDownloading {url} to {destination_path}...")
+ wget.download(url, out=destination_path)
+
+for file_name in executables_file:
+ if sys.platform == "win32":
+ destination_path = os.path.join(file_name)
+ url = f"{url_base}/{file_name}"
+ if not os.path.exists(destination_path):
+ os.makedirs(os.path.dirname(destination_path) or ".", exist_ok=True)
+ print(f"\nDownloading {url} to {destination_path}...")
+ wget.download(url, out=destination_path)
+
+for remote_folder, file_list in models_download:
+ local_folder = folder_mapping.get(remote_folder, "")
+ for file in file_list:
+ destination_path = os.path.join(local_folder, file)
+ url = f"{url_base}/{remote_folder}{file}"
+ if not os.path.exists(destination_path):
+ os.makedirs(os.path.dirname(destination_path) or ".", exist_ok=True)
+ print(f"\nDownloading {url} to {destination_path}...")
+ wget.download(url, out=destination_path)
\ No newline at end of file
diff --git a/rvc/lib/tools/pretrained_selector.py b/rvc/lib/tools/pretrained_selector.py
new file mode 100644
index 0000000000000000000000000000000000000000..59960dacf60a1958790f0159283a15682c3062ea
--- /dev/null
+++ b/rvc/lib/tools/pretrained_selector.py
@@ -0,0 +1,63 @@
+def pretrained_selector(pitch_guidance):
+ if pitch_guidance:
+ return {
+ "v1": {
+ "32000": (
+ "rvc/pretraineds/pretrained_v1/f0G32k.pth",
+ "rvc/pretraineds/pretrained_v1/f0D32k.pth",
+ ),
+ "40000": (
+ "rvc/pretraineds/pretrained_v1/f0G40k.pth",
+ "rvc/pretraineds/pretrained_v1/f0D40k.pth",
+ ),
+ "48000": (
+ "rvc/pretraineds/pretrained_v1/f0G48k.pth",
+ "rvc/pretraineds/pretrained_v1/f0D48k.pth",
+ ),
+ },
+ "v2": {
+ "32000": (
+ "rvc/pretraineds/pretrained_v2/f0G32k.pth",
+ "rvc/pretraineds/pretrained_v2/f0D32k.pth",
+ ),
+ "40000": (
+ "rvc/pretraineds/pretrained_v2/f0G40k.pth",
+ "rvc/pretraineds/pretrained_v2/f0D40k.pth",
+ ),
+ "48000": (
+ "rvc/pretraineds/pretrained_v2/f0G48k.pth",
+ "rvc/pretraineds/pretrained_v2/f0D48k.pth",
+ ),
+ },
+ }
+ else:
+ return {
+ "v1": {
+ "32000": (
+ "rvc/pretraineds/pretrained_v1/G32k.pth",
+ "rvc/pretraineds/pretrained_v1/D32k.pth",
+ ),
+ "40000": (
+ "rvc/pretraineds/pretrained_v1/G40k.pth",
+ "rvc/pretraineds/pretrained_v1/D40k.pth",
+ ),
+ "48000": (
+ "rvc/pretraineds/pretrained_v1/G48k.pth",
+ "rvc/pretraineds/pretrained_v1/D48k.pth",
+ ),
+ },
+ "v2": {
+ "32000": (
+ "rvc/pretraineds/pretrained_v2/G32k.pth",
+ "rvc/pretraineds/pretrained_v2/D32k.pth",
+ ),
+ "40000": (
+ "rvc/pretraineds/pretrained_v2/G40k.pth",
+ "rvc/pretraineds/pretrained_v2/D40k.pth",
+ ),
+ "48000": (
+ "rvc/pretraineds/pretrained_v2/G48k.pth",
+ "rvc/pretraineds/pretrained_v2/D48k.pth",
+ ),
+ },
+ }
\ No newline at end of file
diff --git a/rvc/lib/tools/split_audio.py b/rvc/lib/tools/split_audio.py
new file mode 100644
index 0000000000000000000000000000000000000000..004e7b7b376c00997e953dcc2663da4ab4a4bef3
--- /dev/null
+++ b/rvc/lib/tools/split_audio.py
@@ -0,0 +1,105 @@
+from pydub.silence import detect_nonsilent
+from pydub import AudioSegment
+import numpy as np
+import re
+import os
+
+from rvc.lib.utils import format_title
+
+
+def process_audio(file_path):
+ try:
+ # load audio file
+ song = AudioSegment.from_file(file_path)
+
+ # set silence threshold and duration
+ silence_thresh = -70 # dB
+ min_silence_len = 750 # ms, adjust as needed
+
+ # detect nonsilent parts
+ nonsilent_parts = detect_nonsilent(song, min_silence_len=min_silence_len, silence_thresh=silence_thresh)
+
+ # Create a new directory to store chunks
+ file_dir = os.path.dirname(file_path)
+ file_name = os.path.basename(file_path).split('.')[0]
+ file_name = format_title(file_name)
+ new_dir_path = os.path.join(file_dir, file_name)
+ os.makedirs(new_dir_path, exist_ok=True)
+
+ # Check if timestamps file exists, if so delete it
+ timestamps_file = os.path.join(file_dir, f"{file_name}_timestamps.txt")
+ if os.path.isfile(timestamps_file):
+ os.remove(timestamps_file)
+
+ # export chunks and save start times
+ segment_count = 0
+ for i, (start_i, end_i) in enumerate(nonsilent_parts):
+ chunk = song[start_i:end_i]
+ chunk_file_path = os.path.join(new_dir_path, f"chunk{i}.wav")
+ chunk.export(chunk_file_path, format="wav")
+
+ print(f"Segment {i} created!")
+ segment_count += 1
+
+ # write start times to file
+ with open(timestamps_file, "a", encoding="utf-8") as f:
+ f.write(f"{chunk_file_path} starts at {start_i} ms\n")
+
+ print(f"Total segments created: {segment_count}")
+ print(f"Split all chunks for {file_path} successfully!")
+
+ return "Finish", new_dir_path
+
+ except Exception as e:
+ print(f"An error occurred: {e}")
+ return "Error", None
+
+
+def merge_audio(timestamps_file):
+ try:
+ # Extract prefix from the timestamps filename
+ prefix = os.path.basename(timestamps_file).replace('_timestamps.txt', '')
+ timestamps_dir = os.path.dirname(timestamps_file)
+
+ # Open the timestamps file
+ with open(timestamps_file, "r", encoding="utf-8") as f:
+ lines = f.readlines()
+
+ # Initialize empty list to hold audio segments
+ audio_segments = []
+ last_end_time = 0
+
+ print(f"Processing file: {timestamps_file}")
+
+ for line in lines:
+ # Extract filename and start time from line
+ match = re.search(r"(chunk\d+.wav) starts at (\d+) ms", line)
+ if match:
+ filename, start_time = match.groups()
+ start_time = int(start_time)
+
+ # Construct the complete path to the chunk file
+ chunk_file = os.path.join(timestamps_dir, prefix, filename)
+
+ # Add silence from last_end_time to start_time
+ silence_duration = max(start_time - last_end_time, 0)
+ silence = AudioSegment.silent(duration=silence_duration)
+ audio_segments.append(silence)
+
+ # Load audio file and append to list
+ audio = AudioSegment.from_wav(chunk_file)
+ audio_segments.append(audio)
+
+ # Update last_end_time
+ last_end_time = start_time + len(audio)
+
+ print(f"Processed chunk: {chunk_file}")
+
+ # Concatenate all audio_segments and export
+ merged_audio = sum(audio_segments)
+ merged_audio_np = np.array(merged_audio.get_array_of_samples())
+ #print(f"Exported merged file: {merged_filename}\n")
+ return merged_audio.frame_rate, merged_audio_np
+
+ except Exception as e:
+ print(f"An error occurred: {e}")
\ No newline at end of file
diff --git a/rvc/lib/tools/tts.py b/rvc/lib/tools/tts.py
new file mode 100644
index 0000000000000000000000000000000000000000..917a2471302257caeb61a41d57c4f8246cc0f09e
--- /dev/null
+++ b/rvc/lib/tools/tts.py
@@ -0,0 +1,16 @@
+import sys
+import asyncio
+import edge_tts
+
+
+async def main():
+ text = sys.argv[1]
+ voice = sys.argv[2]
+ output_file = sys.argv[3]
+
+ await edge_tts.Communicate(text, voice).save(output_file)
+ print(f"TTS with {voice} completed. Output TTS file: '{output_file}'")
+
+
+if __name__ == "__main__":
+ asyncio.run(main())
diff --git a/rvc/lib/tools/tts_voices.json b/rvc/lib/tools/tts_voices.json
new file mode 100644
index 0000000000000000000000000000000000000000..ce6c03fff9d2bee7a4a5f6937ea80597af36356b
--- /dev/null
+++ b/rvc/lib/tools/tts_voices.json
@@ -0,0 +1,5462 @@
+[
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (af-ZA, AdriNeural)",
+ "ShortName": "af-ZA-AdriNeural",
+ "Gender": "Female",
+ "Locale": "af-ZA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Adri Online (Natural) - Afrikaans (South Africa)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (af-ZA, WillemNeural)",
+ "ShortName": "af-ZA-WillemNeural",
+ "Gender": "Male",
+ "Locale": "af-ZA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Willem Online (Natural) - Afrikaans (South Africa)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sq-AL, AnilaNeural)",
+ "ShortName": "sq-AL-AnilaNeural",
+ "Gender": "Female",
+ "Locale": "sq-AL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Anila Online (Natural) - Albanian (Albania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sq-AL, IlirNeural)",
+ "ShortName": "sq-AL-IlirNeural",
+ "Gender": "Male",
+ "Locale": "sq-AL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ilir Online (Natural) - Albanian (Albania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (am-ET, AmehaNeural)",
+ "ShortName": "am-ET-AmehaNeural",
+ "Gender": "Male",
+ "Locale": "am-ET",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ameha Online (Natural) - Amharic (Ethiopia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (am-ET, MekdesNeural)",
+ "ShortName": "am-ET-MekdesNeural",
+ "Gender": "Female",
+ "Locale": "am-ET",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Mekdes Online (Natural) - Amharic (Ethiopia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-DZ, AminaNeural)",
+ "ShortName": "ar-DZ-AminaNeural",
+ "Gender": "Female",
+ "Locale": "ar-DZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Amina Online (Natural) - Arabic (Algeria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-DZ, IsmaelNeural)",
+ "ShortName": "ar-DZ-IsmaelNeural",
+ "Gender": "Male",
+ "Locale": "ar-DZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ismael Online (Natural) - Arabic (Algeria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-BH, AliNeural)",
+ "ShortName": "ar-BH-AliNeural",
+ "Gender": "Male",
+ "Locale": "ar-BH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ali Online (Natural) - Arabic (Bahrain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-BH, LailaNeural)",
+ "ShortName": "ar-BH-LailaNeural",
+ "Gender": "Female",
+ "Locale": "ar-BH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Laila Online (Natural) - Arabic (Bahrain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-EG, SalmaNeural)",
+ "ShortName": "ar-EG-SalmaNeural",
+ "Gender": "Female",
+ "Locale": "ar-EG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Salma Online (Natural) - Arabic (Egypt)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-EG, ShakirNeural)",
+ "ShortName": "ar-EG-ShakirNeural",
+ "Gender": "Male",
+ "Locale": "ar-EG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Shakir Online (Natural) - Arabic (Egypt)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-IQ, BasselNeural)",
+ "ShortName": "ar-IQ-BasselNeural",
+ "Gender": "Male",
+ "Locale": "ar-IQ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Bassel Online (Natural) - Arabic (Iraq)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-IQ, RanaNeural)",
+ "ShortName": "ar-IQ-RanaNeural",
+ "Gender": "Female",
+ "Locale": "ar-IQ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Rana Online (Natural) - Arabic (Iraq)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-JO, SanaNeural)",
+ "ShortName": "ar-JO-SanaNeural",
+ "Gender": "Female",
+ "Locale": "ar-JO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sana Online (Natural) - Arabic (Jordan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-JO, TaimNeural)",
+ "ShortName": "ar-JO-TaimNeural",
+ "Gender": "Male",
+ "Locale": "ar-JO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Taim Online (Natural) - Arabic (Jordan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-KW, FahedNeural)",
+ "ShortName": "ar-KW-FahedNeural",
+ "Gender": "Male",
+ "Locale": "ar-KW",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Fahed Online (Natural) - Arabic (Kuwait)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-KW, NouraNeural)",
+ "ShortName": "ar-KW-NouraNeural",
+ "Gender": "Female",
+ "Locale": "ar-KW",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Noura Online (Natural) - Arabic (Kuwait)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-LB, LaylaNeural)",
+ "ShortName": "ar-LB-LaylaNeural",
+ "Gender": "Female",
+ "Locale": "ar-LB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Layla Online (Natural) - Arabic (Lebanon)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-LB, RamiNeural)",
+ "ShortName": "ar-LB-RamiNeural",
+ "Gender": "Male",
+ "Locale": "ar-LB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Rami Online (Natural) - Arabic (Lebanon)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-LY, ImanNeural)",
+ "ShortName": "ar-LY-ImanNeural",
+ "Gender": "Female",
+ "Locale": "ar-LY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Iman Online (Natural) - Arabic (Libya)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-LY, OmarNeural)",
+ "ShortName": "ar-LY-OmarNeural",
+ "Gender": "Male",
+ "Locale": "ar-LY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Omar Online (Natural) - Arabic (Libya)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-MA, JamalNeural)",
+ "ShortName": "ar-MA-JamalNeural",
+ "Gender": "Male",
+ "Locale": "ar-MA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jamal Online (Natural) - Arabic (Morocco)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-MA, MounaNeural)",
+ "ShortName": "ar-MA-MounaNeural",
+ "Gender": "Female",
+ "Locale": "ar-MA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Mouna Online (Natural) - Arabic (Morocco)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-OM, AbdullahNeural)",
+ "ShortName": "ar-OM-AbdullahNeural",
+ "Gender": "Male",
+ "Locale": "ar-OM",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Abdullah Online (Natural) - Arabic (Oman)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-OM, AyshaNeural)",
+ "ShortName": "ar-OM-AyshaNeural",
+ "Gender": "Female",
+ "Locale": "ar-OM",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Aysha Online (Natural) - Arabic (Oman)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-QA, AmalNeural)",
+ "ShortName": "ar-QA-AmalNeural",
+ "Gender": "Female",
+ "Locale": "ar-QA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Amal Online (Natural) - Arabic (Qatar)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-QA, MoazNeural)",
+ "ShortName": "ar-QA-MoazNeural",
+ "Gender": "Male",
+ "Locale": "ar-QA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Moaz Online (Natural) - Arabic (Qatar)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-SA, HamedNeural)",
+ "ShortName": "ar-SA-HamedNeural",
+ "Gender": "Male",
+ "Locale": "ar-SA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Hamed Online (Natural) - Arabic (Saudi Arabia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-SA, ZariyahNeural)",
+ "ShortName": "ar-SA-ZariyahNeural",
+ "Gender": "Female",
+ "Locale": "ar-SA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Zariyah Online (Natural) - Arabic (Saudi Arabia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-SY, AmanyNeural)",
+ "ShortName": "ar-SY-AmanyNeural",
+ "Gender": "Female",
+ "Locale": "ar-SY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Amany Online (Natural) - Arabic (Syria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-SY, LaithNeural)",
+ "ShortName": "ar-SY-LaithNeural",
+ "Gender": "Male",
+ "Locale": "ar-SY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Laith Online (Natural) - Arabic (Syria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-TN, HediNeural)",
+ "ShortName": "ar-TN-HediNeural",
+ "Gender": "Male",
+ "Locale": "ar-TN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Hedi Online (Natural) - Arabic (Tunisia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-TN, ReemNeural)",
+ "ShortName": "ar-TN-ReemNeural",
+ "Gender": "Female",
+ "Locale": "ar-TN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Reem Online (Natural) - Arabic (Tunisia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-AE, FatimaNeural)",
+ "ShortName": "ar-AE-FatimaNeural",
+ "Gender": "Female",
+ "Locale": "ar-AE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Fatima Online (Natural) - Arabic (United Arab Emirates)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-AE, HamdanNeural)",
+ "ShortName": "ar-AE-HamdanNeural",
+ "Gender": "Male",
+ "Locale": "ar-AE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Hamdan Online (Natural) - Arabic (United Arab Emirates)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-YE, MaryamNeural)",
+ "ShortName": "ar-YE-MaryamNeural",
+ "Gender": "Female",
+ "Locale": "ar-YE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Maryam Online (Natural) - Arabic (Yemen)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ar-YE, SalehNeural)",
+ "ShortName": "ar-YE-SalehNeural",
+ "Gender": "Male",
+ "Locale": "ar-YE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Saleh Online (Natural) - Arabic (Yemen)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (az-AZ, BabekNeural)",
+ "ShortName": "az-AZ-BabekNeural",
+ "Gender": "Male",
+ "Locale": "az-AZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Babek Online (Natural) - Azerbaijani (Azerbaijan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (az-AZ, BanuNeural)",
+ "ShortName": "az-AZ-BanuNeural",
+ "Gender": "Female",
+ "Locale": "az-AZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Banu Online (Natural) - Azerbaijani (Azerbaijan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bn-BD, NabanitaNeural)",
+ "ShortName": "bn-BD-NabanitaNeural",
+ "Gender": "Female",
+ "Locale": "bn-BD",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Nabanita Online (Natural) - Bangla (Bangladesh)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bn-BD, PradeepNeural)",
+ "ShortName": "bn-BD-PradeepNeural",
+ "Gender": "Male",
+ "Locale": "bn-BD",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Pradeep Online (Natural) - Bangla (Bangladesh)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bn-IN, BashkarNeural)",
+ "ShortName": "bn-IN-BashkarNeural",
+ "Gender": "Male",
+ "Locale": "bn-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Bashkar Online (Natural) - Bangla (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bn-IN, TanishaaNeural)",
+ "ShortName": "bn-IN-TanishaaNeural",
+ "Gender": "Female",
+ "Locale": "bn-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Tanishaa Online (Natural) - Bengali (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bs-BA, GoranNeural)",
+ "ShortName": "bs-BA-GoranNeural",
+ "Gender": "Male",
+ "Locale": "bs-BA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Goran Online (Natural) - Bosnian (Bosnia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bs-BA, VesnaNeural)",
+ "ShortName": "bs-BA-VesnaNeural",
+ "Gender": "Female",
+ "Locale": "bs-BA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Vesna Online (Natural) - Bosnian (Bosnia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bg-BG, BorislavNeural)",
+ "ShortName": "bg-BG-BorislavNeural",
+ "Gender": "Male",
+ "Locale": "bg-BG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Borislav Online (Natural) - Bulgarian (Bulgaria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (bg-BG, KalinaNeural)",
+ "ShortName": "bg-BG-KalinaNeural",
+ "Gender": "Female",
+ "Locale": "bg-BG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Kalina Online (Natural) - Bulgarian (Bulgaria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (my-MM, NilarNeural)",
+ "ShortName": "my-MM-NilarNeural",
+ "Gender": "Female",
+ "Locale": "my-MM",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Nilar Online (Natural) - Burmese (Myanmar)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (my-MM, ThihaNeural)",
+ "ShortName": "my-MM-ThihaNeural",
+ "Gender": "Male",
+ "Locale": "my-MM",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Thiha Online (Natural) - Burmese (Myanmar)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ca-ES, EnricNeural)",
+ "ShortName": "ca-ES-EnricNeural",
+ "Gender": "Male",
+ "Locale": "ca-ES",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Enric Online (Natural) - Catalan (Spain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ca-ES, JoanaNeural)",
+ "ShortName": "ca-ES-JoanaNeural",
+ "Gender": "Female",
+ "Locale": "ca-ES",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Joana Online (Natural) - Catalan (Spain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-HK, HiuGaaiNeural)",
+ "ShortName": "zh-HK-HiuGaaiNeural",
+ "Gender": "Female",
+ "Locale": "zh-HK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft HiuGaai Online (Natural) - Chinese (Cantonese Traditional)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-HK, HiuMaanNeural)",
+ "ShortName": "zh-HK-HiuMaanNeural",
+ "Gender": "Female",
+ "Locale": "zh-HK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft HiuMaan Online (Natural) - Chinese (Hong Kong)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-HK, WanLungNeural)",
+ "ShortName": "zh-HK-WanLungNeural",
+ "Gender": "Male",
+ "Locale": "zh-HK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft WanLung Online (Natural) - Chinese (Hong Kong)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN, XiaoxiaoNeural)",
+ "ShortName": "zh-CN-XiaoxiaoNeural",
+ "Gender": "Female",
+ "Locale": "zh-CN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Xiaoxiao Online (Natural) - Chinese (Mainland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Warm"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN, XiaoyiNeural)",
+ "ShortName": "zh-CN-XiaoyiNeural",
+ "Gender": "Female",
+ "Locale": "zh-CN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Xiaoyi Online (Natural) - Chinese (Mainland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Cartoon",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Lively"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN, YunjianNeural)",
+ "ShortName": "zh-CN-YunjianNeural",
+ "Gender": "Male",
+ "Locale": "zh-CN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yunjian Online (Natural) - Chinese (Mainland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Sports",
+ " Novel"
+ ],
+ "VoicePersonalities": [
+ "Passion"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN, YunxiNeural)",
+ "ShortName": "zh-CN-YunxiNeural",
+ "Gender": "Male",
+ "Locale": "zh-CN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yunxi Online (Natural) - Chinese (Mainland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Lively",
+ "Sunshine"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN, YunxiaNeural)",
+ "ShortName": "zh-CN-YunxiaNeural",
+ "Gender": "Male",
+ "Locale": "zh-CN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yunxia Online (Natural) - Chinese (Mainland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Cartoon",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Cute"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN, YunyangNeural)",
+ "ShortName": "zh-CN-YunyangNeural",
+ "Gender": "Male",
+ "Locale": "zh-CN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yunyang Online (Natural) - Chinese (Mainland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News"
+ ],
+ "VoicePersonalities": [
+ "Professional",
+ "Reliable"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN-liaoning, XiaobeiNeural)",
+ "ShortName": "zh-CN-liaoning-XiaobeiNeural",
+ "Gender": "Female",
+ "Locale": "zh-CN-liaoning",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Xiaobei Online (Natural) - Chinese (Northeastern Mandarin)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Dialect"
+ ],
+ "VoicePersonalities": [
+ "Humorous"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-TW, HsiaoChenNeural)",
+ "ShortName": "zh-TW-HsiaoChenNeural",
+ "Gender": "Female",
+ "Locale": "zh-TW",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft HsiaoChen Online (Natural) - Chinese (Taiwan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-TW, YunJheNeural)",
+ "ShortName": "zh-TW-YunJheNeural",
+ "Gender": "Male",
+ "Locale": "zh-TW",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft YunJhe Online (Natural) - Chinese (Taiwan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-TW, HsiaoYuNeural)",
+ "ShortName": "zh-TW-HsiaoYuNeural",
+ "Gender": "Female",
+ "Locale": "zh-TW",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft HsiaoYu Online (Natural) - Chinese (Taiwanese Mandarin)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zh-CN-shaanxi, XiaoniNeural)",
+ "ShortName": "zh-CN-shaanxi-XiaoniNeural",
+ "Gender": "Female",
+ "Locale": "zh-CN-shaanxi",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Xiaoni Online (Natural) - Chinese (Zhongyuan Mandarin Shaanxi)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Dialect"
+ ],
+ "VoicePersonalities": [
+ "Bright"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (hr-HR, GabrijelaNeural)",
+ "ShortName": "hr-HR-GabrijelaNeural",
+ "Gender": "Female",
+ "Locale": "hr-HR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gabrijela Online (Natural) - Croatian (Croatia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (hr-HR, SreckoNeural)",
+ "ShortName": "hr-HR-SreckoNeural",
+ "Gender": "Male",
+ "Locale": "hr-HR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Srecko Online (Natural) - Croatian (Croatia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (cs-CZ, AntoninNeural)",
+ "ShortName": "cs-CZ-AntoninNeural",
+ "Gender": "Male",
+ "Locale": "cs-CZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Antonin Online (Natural) - Czech (Czech)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (cs-CZ, VlastaNeural)",
+ "ShortName": "cs-CZ-VlastaNeural",
+ "Gender": "Female",
+ "Locale": "cs-CZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Vlasta Online (Natural) - Czech (Czech)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (da-DK, ChristelNeural)",
+ "ShortName": "da-DK-ChristelNeural",
+ "Gender": "Female",
+ "Locale": "da-DK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Christel Online (Natural) - Danish (Denmark)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (da-DK, JeppeNeural)",
+ "ShortName": "da-DK-JeppeNeural",
+ "Gender": "Male",
+ "Locale": "da-DK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jeppe Online (Natural) - Danish (Denmark)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (nl-BE, ArnaudNeural)",
+ "ShortName": "nl-BE-ArnaudNeural",
+ "Gender": "Male",
+ "Locale": "nl-BE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Arnaud Online (Natural) - Dutch (Belgium)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (nl-BE, DenaNeural)",
+ "ShortName": "nl-BE-DenaNeural",
+ "Gender": "Female",
+ "Locale": "nl-BE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Dena Online (Natural) - Dutch (Belgium)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (nl-NL, ColetteNeural)",
+ "ShortName": "nl-NL-ColetteNeural",
+ "Gender": "Female",
+ "Locale": "nl-NL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Colette Online (Natural) - Dutch (Netherlands)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (nl-NL, FennaNeural)",
+ "ShortName": "nl-NL-FennaNeural",
+ "Gender": "Female",
+ "Locale": "nl-NL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Fenna Online (Natural) - Dutch (Netherlands)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (nl-NL, MaartenNeural)",
+ "ShortName": "nl-NL-MaartenNeural",
+ "Gender": "Male",
+ "Locale": "nl-NL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Maarten Online (Natural) - Dutch (Netherlands)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-AU, NatashaNeural)",
+ "ShortName": "en-AU-NatashaNeural",
+ "Gender": "Female",
+ "Locale": "en-AU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Natasha Online (Natural) - English (Australia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-AU, WilliamNeural)",
+ "ShortName": "en-AU-WilliamNeural",
+ "Gender": "Male",
+ "Locale": "en-AU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft William Online (Natural) - English (Australia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-CA, ClaraNeural)",
+ "ShortName": "en-CA-ClaraNeural",
+ "Gender": "Female",
+ "Locale": "en-CA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Clara Online (Natural) - English (Canada)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-CA, LiamNeural)",
+ "ShortName": "en-CA-LiamNeural",
+ "Gender": "Male",
+ "Locale": "en-CA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Liam Online (Natural) - English (Canada)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-HK, SamNeural)",
+ "ShortName": "en-HK-SamNeural",
+ "Gender": "Male",
+ "Locale": "en-HK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sam Online (Natural) - English (Hongkong)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-HK, YanNeural)",
+ "ShortName": "en-HK-YanNeural",
+ "Gender": "Female",
+ "Locale": "en-HK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yan Online (Natural) - English (Hongkong)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-IN, NeerjaExpressiveNeural)",
+ "ShortName": "en-IN-NeerjaExpressiveNeural",
+ "Gender": "Female",
+ "Locale": "en-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Neerja Online (Natural) - English (India) (Preview)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-IN, NeerjaNeural)",
+ "ShortName": "en-IN-NeerjaNeural",
+ "Gender": "Female",
+ "Locale": "en-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Neerja Online (Natural) - English (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-IN, PrabhatNeural)",
+ "ShortName": "en-IN-PrabhatNeural",
+ "Gender": "Male",
+ "Locale": "en-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Prabhat Online (Natural) - English (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-IE, ConnorNeural)",
+ "ShortName": "en-IE-ConnorNeural",
+ "Gender": "Male",
+ "Locale": "en-IE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Connor Online (Natural) - English (Ireland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-IE, EmilyNeural)",
+ "ShortName": "en-IE-EmilyNeural",
+ "Gender": "Female",
+ "Locale": "en-IE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Emily Online (Natural) - English (Ireland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-KE, AsiliaNeural)",
+ "ShortName": "en-KE-AsiliaNeural",
+ "Gender": "Female",
+ "Locale": "en-KE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Asilia Online (Natural) - English (Kenya)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-KE, ChilembaNeural)",
+ "ShortName": "en-KE-ChilembaNeural",
+ "Gender": "Male",
+ "Locale": "en-KE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Chilemba Online (Natural) - English (Kenya)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-NZ, MitchellNeural)",
+ "ShortName": "en-NZ-MitchellNeural",
+ "Gender": "Male",
+ "Locale": "en-NZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Mitchell Online (Natural) - English (New Zealand)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-NZ, MollyNeural)",
+ "ShortName": "en-NZ-MollyNeural",
+ "Gender": "Female",
+ "Locale": "en-NZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Molly Online (Natural) - English (New Zealand)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-NG, AbeoNeural)",
+ "ShortName": "en-NG-AbeoNeural",
+ "Gender": "Male",
+ "Locale": "en-NG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Abeo Online (Natural) - English (Nigeria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-NG, EzinneNeural)",
+ "ShortName": "en-NG-EzinneNeural",
+ "Gender": "Female",
+ "Locale": "en-NG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ezinne Online (Natural) - English (Nigeria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-PH, JamesNeural)",
+ "ShortName": "en-PH-JamesNeural",
+ "Gender": "Male",
+ "Locale": "en-PH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft James Online (Natural) - English (Philippines)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-PH, RosaNeural)",
+ "ShortName": "en-PH-RosaNeural",
+ "Gender": "Female",
+ "Locale": "en-PH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Rosa Online (Natural) - English (Philippines)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-SG, LunaNeural)",
+ "ShortName": "en-SG-LunaNeural",
+ "Gender": "Female",
+ "Locale": "en-SG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Luna Online (Natural) - English (Singapore)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-SG, WayneNeural)",
+ "ShortName": "en-SG-WayneNeural",
+ "Gender": "Male",
+ "Locale": "en-SG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Wayne Online (Natural) - English (Singapore)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-ZA, LeahNeural)",
+ "ShortName": "en-ZA-LeahNeural",
+ "Gender": "Female",
+ "Locale": "en-ZA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Leah Online (Natural) - English (South Africa)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-ZA, LukeNeural)",
+ "ShortName": "en-ZA-LukeNeural",
+ "Gender": "Male",
+ "Locale": "en-ZA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Luke Online (Natural) - English (South Africa)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-TZ, ElimuNeural)",
+ "ShortName": "en-TZ-ElimuNeural",
+ "Gender": "Male",
+ "Locale": "en-TZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Elimu Online (Natural) - English (Tanzania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-TZ, ImaniNeural)",
+ "ShortName": "en-TZ-ImaniNeural",
+ "Gender": "Female",
+ "Locale": "en-TZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Imani Online (Natural) - English (Tanzania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-GB, LibbyNeural)",
+ "ShortName": "en-GB-LibbyNeural",
+ "Gender": "Female",
+ "Locale": "en-GB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Libby Online (Natural) - English (United Kingdom)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-GB, MaisieNeural)",
+ "ShortName": "en-GB-MaisieNeural",
+ "Gender": "Female",
+ "Locale": "en-GB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Maisie Online (Natural) - English (United Kingdom)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-GB, RyanNeural)",
+ "ShortName": "en-GB-RyanNeural",
+ "Gender": "Male",
+ "Locale": "en-GB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ryan Online (Natural) - English (United Kingdom)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-GB, SoniaNeural)",
+ "ShortName": "en-GB-SoniaNeural",
+ "Gender": "Female",
+ "Locale": "en-GB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sonia Online (Natural) - English (United Kingdom)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-GB, ThomasNeural)",
+ "ShortName": "en-GB-ThomasNeural",
+ "Gender": "Male",
+ "Locale": "en-GB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Thomas Online (Natural) - English (United Kingdom)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, AriaNeural)",
+ "ShortName": "en-US-AriaNeural",
+ "Gender": "Female",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Aria Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Positive",
+ "Confident"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, AnaNeural)",
+ "ShortName": "en-US-AnaNeural",
+ "Gender": "Female",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ana Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Cartoon",
+ "Conversation"
+ ],
+ "VoicePersonalities": [
+ "Cute"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, AndrewNeural)",
+ "ShortName": "en-US-AndrewNeural",
+ "Gender": "Male",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Andrew Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Conversation",
+ "Copilot"
+ ],
+ "VoicePersonalities": [
+ "Warm",
+ "Confident",
+ "Engaging"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, AvaNeural)",
+ "ShortName": "en-US-AvaNeural",
+ "Gender": "Female",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ava Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "Conversation",
+ "Copilot"
+ ],
+ "VoicePersonalities": [
+ "Pleasant",
+ "Genuine",
+ "Engaging"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, ChristopherNeural)",
+ "ShortName": "en-US-ChristopherNeural",
+ "Gender": "Male",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Christopher Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Reliable",
+ "Authority"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, EricNeural)",
+ "ShortName": "en-US-EricNeural",
+ "Gender": "Male",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Eric Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Rational"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, GuyNeural)",
+ "ShortName": "en-US-GuyNeural",
+ "Gender": "Male",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Guy Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Passion"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, JennyNeural)",
+ "ShortName": "en-US-JennyNeural",
+ "Gender": "Female",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jenny Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Considerate",
+ "Comfort"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, MichelleNeural)",
+ "ShortName": "en-US-MichelleNeural",
+ "Gender": "Female",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Michelle Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Pleasant"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, RogerNeural)",
+ "ShortName": "en-US-RogerNeural",
+ "Gender": "Male",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Roger Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Lively"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (en-US, SteffanNeural)",
+ "ShortName": "en-US-SteffanNeural",
+ "Gender": "Male",
+ "Locale": "en-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Steffan Online (Natural) - English (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "News",
+ "Novel"
+ ],
+ "VoicePersonalities": [
+ "Rational"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (et-EE, AnuNeural)",
+ "ShortName": "et-EE-AnuNeural",
+ "Gender": "Female",
+ "Locale": "et-EE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Anu Online (Natural) - Estonian (Estonia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (et-EE, KertNeural)",
+ "ShortName": "et-EE-KertNeural",
+ "Gender": "Male",
+ "Locale": "et-EE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Kert Online (Natural) - Estonian (Estonia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fil-PH, AngeloNeural)",
+ "ShortName": "fil-PH-AngeloNeural",
+ "Gender": "Male",
+ "Locale": "fil-PH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Angelo Online (Natural) - Filipino (Philippines)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fil-PH, BlessicaNeural)",
+ "ShortName": "fil-PH-BlessicaNeural",
+ "Gender": "Female",
+ "Locale": "fil-PH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Blessica Online (Natural) - Filipino (Philippines)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fi-FI, HarriNeural)",
+ "ShortName": "fi-FI-HarriNeural",
+ "Gender": "Male",
+ "Locale": "fi-FI",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Harri Online (Natural) - Finnish (Finland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fi-FI, NooraNeural)",
+ "ShortName": "fi-FI-NooraNeural",
+ "Gender": "Female",
+ "Locale": "fi-FI",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Noora Online (Natural) - Finnish (Finland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-BE, CharlineNeural)",
+ "ShortName": "fr-BE-CharlineNeural",
+ "Gender": "Female",
+ "Locale": "fr-BE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Charline Online (Natural) - French (Belgium)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-BE, GerardNeural)",
+ "ShortName": "fr-BE-GerardNeural",
+ "Gender": "Male",
+ "Locale": "fr-BE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gerard Online (Natural) - French (Belgium)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-CA, AntoineNeural)",
+ "ShortName": "fr-CA-AntoineNeural",
+ "Gender": "Male",
+ "Locale": "fr-CA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Antoine Online (Natural) - French (Canada)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-CA, JeanNeural)",
+ "ShortName": "fr-CA-JeanNeural",
+ "Gender": "Male",
+ "Locale": "fr-CA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jean Online (Natural) - French (Canada)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-CA, SylvieNeural)",
+ "ShortName": "fr-CA-SylvieNeural",
+ "Gender": "Female",
+ "Locale": "fr-CA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sylvie Online (Natural) - French (Canada)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-FR, DeniseNeural)",
+ "ShortName": "fr-FR-DeniseNeural",
+ "Gender": "Female",
+ "Locale": "fr-FR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Denise Online (Natural) - French (France)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-FR, EloiseNeural)",
+ "ShortName": "fr-FR-EloiseNeural",
+ "Gender": "Female",
+ "Locale": "fr-FR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Eloise Online (Natural) - French (France)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-FR, HenriNeural)",
+ "ShortName": "fr-FR-HenriNeural",
+ "Gender": "Male",
+ "Locale": "fr-FR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Henri Online (Natural) - French (France)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-CH, ArianeNeural)",
+ "ShortName": "fr-CH-ArianeNeural",
+ "Gender": "Female",
+ "Locale": "fr-CH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ariane Online (Natural) - French (Switzerland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fr-CH, FabriceNeural)",
+ "ShortName": "fr-CH-FabriceNeural",
+ "Gender": "Male",
+ "Locale": "fr-CH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Fabrice Online (Natural) - French (Switzerland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (gl-ES, RoiNeural)",
+ "ShortName": "gl-ES-RoiNeural",
+ "Gender": "Male",
+ "Locale": "gl-ES",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Roi Online (Natural) - Galician (Spain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (gl-ES, SabelaNeural)",
+ "ShortName": "gl-ES-SabelaNeural",
+ "Gender": "Female",
+ "Locale": "gl-ES",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sabela Online (Natural) - Galician (Spain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ka-GE, EkaNeural)",
+ "ShortName": "ka-GE-EkaNeural",
+ "Gender": "Female",
+ "Locale": "ka-GE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Eka Online (Natural) - Georgian (Georgia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ka-GE, GiorgiNeural)",
+ "ShortName": "ka-GE-GiorgiNeural",
+ "Gender": "Male",
+ "Locale": "ka-GE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Giorgi Online (Natural) - Georgian (Georgia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-AT, IngridNeural)",
+ "ShortName": "de-AT-IngridNeural",
+ "Gender": "Female",
+ "Locale": "de-AT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ingrid Online (Natural) - German (Austria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-AT, JonasNeural)",
+ "ShortName": "de-AT-JonasNeural",
+ "Gender": "Male",
+ "Locale": "de-AT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jonas Online (Natural) - German (Austria)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-DE, AmalaNeural)",
+ "ShortName": "de-DE-AmalaNeural",
+ "Gender": "Female",
+ "Locale": "de-DE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Amala Online (Natural) - German (Germany)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-DE, ConradNeural)",
+ "ShortName": "de-DE-ConradNeural",
+ "Gender": "Male",
+ "Locale": "de-DE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Conrad Online (Natural) - German (Germany)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-DE, KatjaNeural)",
+ "ShortName": "de-DE-KatjaNeural",
+ "Gender": "Female",
+ "Locale": "de-DE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Katja Online (Natural) - German (Germany)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-DE, KillianNeural)",
+ "ShortName": "de-DE-KillianNeural",
+ "Gender": "Male",
+ "Locale": "de-DE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Killian Online (Natural) - German (Germany)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-CH, JanNeural)",
+ "ShortName": "de-CH-JanNeural",
+ "Gender": "Male",
+ "Locale": "de-CH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jan Online (Natural) - German (Switzerland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (de-CH, LeniNeural)",
+ "ShortName": "de-CH-LeniNeural",
+ "Gender": "Female",
+ "Locale": "de-CH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Leni Online (Natural) - German (Switzerland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (el-GR, AthinaNeural)",
+ "ShortName": "el-GR-AthinaNeural",
+ "Gender": "Female",
+ "Locale": "el-GR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Athina Online (Natural) - Greek (Greece)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (el-GR, NestorasNeural)",
+ "ShortName": "el-GR-NestorasNeural",
+ "Gender": "Male",
+ "Locale": "el-GR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Nestoras Online (Natural) - Greek (Greece)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (gu-IN, DhwaniNeural)",
+ "ShortName": "gu-IN-DhwaniNeural",
+ "Gender": "Female",
+ "Locale": "gu-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Dhwani Online (Natural) - Gujarati (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (gu-IN, NiranjanNeural)",
+ "ShortName": "gu-IN-NiranjanNeural",
+ "Gender": "Male",
+ "Locale": "gu-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Niranjan Online (Natural) - Gujarati (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (he-IL, AvriNeural)",
+ "ShortName": "he-IL-AvriNeural",
+ "Gender": "Male",
+ "Locale": "he-IL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Avri Online (Natural) - Hebrew (Israel)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (he-IL, HilaNeural)",
+ "ShortName": "he-IL-HilaNeural",
+ "Gender": "Female",
+ "Locale": "he-IL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Hila Online (Natural) - Hebrew (Israel)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (hi-IN, MadhurNeural)",
+ "ShortName": "hi-IN-MadhurNeural",
+ "Gender": "Male",
+ "Locale": "hi-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Madhur Online (Natural) - Hindi (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (hi-IN, SwaraNeural)",
+ "ShortName": "hi-IN-SwaraNeural",
+ "Gender": "Female",
+ "Locale": "hi-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Swara Online (Natural) - Hindi (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (hu-HU, NoemiNeural)",
+ "ShortName": "hu-HU-NoemiNeural",
+ "Gender": "Female",
+ "Locale": "hu-HU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Noemi Online (Natural) - Hungarian (Hungary)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (hu-HU, TamasNeural)",
+ "ShortName": "hu-HU-TamasNeural",
+ "Gender": "Male",
+ "Locale": "hu-HU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Tamas Online (Natural) - Hungarian (Hungary)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (is-IS, GudrunNeural)",
+ "ShortName": "is-IS-GudrunNeural",
+ "Gender": "Female",
+ "Locale": "is-IS",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gudrun Online (Natural) - Icelandic (Iceland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (is-IS, GunnarNeural)",
+ "ShortName": "is-IS-GunnarNeural",
+ "Gender": "Male",
+ "Locale": "is-IS",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gunnar Online (Natural) - Icelandic (Iceland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (id-ID, ArdiNeural)",
+ "ShortName": "id-ID-ArdiNeural",
+ "Gender": "Male",
+ "Locale": "id-ID",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ardi Online (Natural) - Indonesian (Indonesia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (id-ID, GadisNeural)",
+ "ShortName": "id-ID-GadisNeural",
+ "Gender": "Female",
+ "Locale": "id-ID",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gadis Online (Natural) - Indonesian (Indonesia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ga-IE, ColmNeural)",
+ "ShortName": "ga-IE-ColmNeural",
+ "Gender": "Male",
+ "Locale": "ga-IE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Colm Online (Natural) - Irish (Ireland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ga-IE, OrlaNeural)",
+ "ShortName": "ga-IE-OrlaNeural",
+ "Gender": "Female",
+ "Locale": "ga-IE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Orla Online (Natural) - Irish (Ireland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (it-IT, DiegoNeural)",
+ "ShortName": "it-IT-DiegoNeural",
+ "Gender": "Male",
+ "Locale": "it-IT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Diego Online (Natural) - Italian (Italy)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (it-IT, ElsaNeural)",
+ "ShortName": "it-IT-ElsaNeural",
+ "Gender": "Female",
+ "Locale": "it-IT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Elsa Online (Natural) - Italian (Italy)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (it-IT, IsabellaNeural)",
+ "ShortName": "it-IT-IsabellaNeural",
+ "Gender": "Female",
+ "Locale": "it-IT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Isabella Online (Natural) - Italian (Italy)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ja-JP, KeitaNeural)",
+ "ShortName": "ja-JP-KeitaNeural",
+ "Gender": "Male",
+ "Locale": "ja-JP",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Keita Online (Natural) - Japanese (Japan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ja-JP, NanamiNeural)",
+ "ShortName": "ja-JP-NanamiNeural",
+ "Gender": "Female",
+ "Locale": "ja-JP",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Nanami Online (Natural) - Japanese (Japan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (jv-ID, DimasNeural)",
+ "ShortName": "jv-ID-DimasNeural",
+ "Gender": "Male",
+ "Locale": "jv-ID",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Dimas Online (Natural) - Javanese (Indonesia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (jv-ID, SitiNeural)",
+ "ShortName": "jv-ID-SitiNeural",
+ "Gender": "Female",
+ "Locale": "jv-ID",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Siti Online (Natural) - Javanese (Indonesia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (kn-IN, GaganNeural)",
+ "ShortName": "kn-IN-GaganNeural",
+ "Gender": "Male",
+ "Locale": "kn-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gagan Online (Natural) - Kannada (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (kn-IN, SapnaNeural)",
+ "ShortName": "kn-IN-SapnaNeural",
+ "Gender": "Female",
+ "Locale": "kn-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sapna Online (Natural) - Kannada (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (kk-KZ, AigulNeural)",
+ "ShortName": "kk-KZ-AigulNeural",
+ "Gender": "Female",
+ "Locale": "kk-KZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Aigul Online (Natural) - Kazakh (Kazakhstan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (kk-KZ, DauletNeural)",
+ "ShortName": "kk-KZ-DauletNeural",
+ "Gender": "Male",
+ "Locale": "kk-KZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Daulet Online (Natural) - Kazakh (Kazakhstan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (km-KH, PisethNeural)",
+ "ShortName": "km-KH-PisethNeural",
+ "Gender": "Male",
+ "Locale": "km-KH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Piseth Online (Natural) - Khmer (Cambodia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (km-KH, SreymomNeural)",
+ "ShortName": "km-KH-SreymomNeural",
+ "Gender": "Female",
+ "Locale": "km-KH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sreymom Online (Natural) - Khmer (Cambodia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ko-KR, InJoonNeural)",
+ "ShortName": "ko-KR-InJoonNeural",
+ "Gender": "Male",
+ "Locale": "ko-KR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft InJoon Online (Natural) - Korean (Korea)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ko-KR, SunHiNeural)",
+ "ShortName": "ko-KR-SunHiNeural",
+ "Gender": "Female",
+ "Locale": "ko-KR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft SunHi Online (Natural) - Korean (Korea)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (lo-LA, ChanthavongNeural)",
+ "ShortName": "lo-LA-ChanthavongNeural",
+ "Gender": "Male",
+ "Locale": "lo-LA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Chanthavong Online (Natural) - Lao (Laos)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (lo-LA, KeomanyNeural)",
+ "ShortName": "lo-LA-KeomanyNeural",
+ "Gender": "Female",
+ "Locale": "lo-LA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Keomany Online (Natural) - Lao (Laos)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (lv-LV, EveritaNeural)",
+ "ShortName": "lv-LV-EveritaNeural",
+ "Gender": "Female",
+ "Locale": "lv-LV",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Everita Online (Natural) - Latvian (Latvia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (lv-LV, NilsNeural)",
+ "ShortName": "lv-LV-NilsNeural",
+ "Gender": "Male",
+ "Locale": "lv-LV",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Nils Online (Natural) - Latvian (Latvia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (lt-LT, LeonasNeural)",
+ "ShortName": "lt-LT-LeonasNeural",
+ "Gender": "Male",
+ "Locale": "lt-LT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Leonas Online (Natural) - Lithuanian (Lithuania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (lt-LT, OnaNeural)",
+ "ShortName": "lt-LT-OnaNeural",
+ "Gender": "Female",
+ "Locale": "lt-LT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ona Online (Natural) - Lithuanian (Lithuania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mk-MK, AleksandarNeural)",
+ "ShortName": "mk-MK-AleksandarNeural",
+ "Gender": "Male",
+ "Locale": "mk-MK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Aleksandar Online (Natural) - Macedonian (Republic of North Macedonia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mk-MK, MarijaNeural)",
+ "ShortName": "mk-MK-MarijaNeural",
+ "Gender": "Female",
+ "Locale": "mk-MK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Marija Online (Natural) - Macedonian (Republic of North Macedonia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ms-MY, OsmanNeural)",
+ "ShortName": "ms-MY-OsmanNeural",
+ "Gender": "Male",
+ "Locale": "ms-MY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Osman Online (Natural) - Malay (Malaysia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ms-MY, YasminNeural)",
+ "ShortName": "ms-MY-YasminNeural",
+ "Gender": "Female",
+ "Locale": "ms-MY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yasmin Online (Natural) - Malay (Malaysia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ml-IN, MidhunNeural)",
+ "ShortName": "ml-IN-MidhunNeural",
+ "Gender": "Male",
+ "Locale": "ml-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Midhun Online (Natural) - Malayalam (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ml-IN, SobhanaNeural)",
+ "ShortName": "ml-IN-SobhanaNeural",
+ "Gender": "Female",
+ "Locale": "ml-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sobhana Online (Natural) - Malayalam (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mt-MT, GraceNeural)",
+ "ShortName": "mt-MT-GraceNeural",
+ "Gender": "Female",
+ "Locale": "mt-MT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Grace Online (Natural) - Maltese (Malta)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mt-MT, JosephNeural)",
+ "ShortName": "mt-MT-JosephNeural",
+ "Gender": "Male",
+ "Locale": "mt-MT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Joseph Online (Natural) - Maltese (Malta)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mr-IN, AarohiNeural)",
+ "ShortName": "mr-IN-AarohiNeural",
+ "Gender": "Female",
+ "Locale": "mr-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Aarohi Online (Natural) - Marathi (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mr-IN, ManoharNeural)",
+ "ShortName": "mr-IN-ManoharNeural",
+ "Gender": "Male",
+ "Locale": "mr-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Manohar Online (Natural) - Marathi (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mn-MN, BataaNeural)",
+ "ShortName": "mn-MN-BataaNeural",
+ "Gender": "Male",
+ "Locale": "mn-MN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Bataa Online (Natural) - Mongolian (Mongolia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (mn-MN, YesuiNeural)",
+ "ShortName": "mn-MN-YesuiNeural",
+ "Gender": "Female",
+ "Locale": "mn-MN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yesui Online (Natural) - Mongolian (Mongolia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ne-NP, HemkalaNeural)",
+ "ShortName": "ne-NP-HemkalaNeural",
+ "Gender": "Female",
+ "Locale": "ne-NP",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Hemkala Online (Natural) - Nepali (Nepal)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ne-NP, SagarNeural)",
+ "ShortName": "ne-NP-SagarNeural",
+ "Gender": "Male",
+ "Locale": "ne-NP",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sagar Online (Natural) - Nepali (Nepal)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (nb-NO, FinnNeural)",
+ "ShortName": "nb-NO-FinnNeural",
+ "Gender": "Male",
+ "Locale": "nb-NO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Finn Online (Natural) - Norwegian (Bokmål Norway)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (nb-NO, PernilleNeural)",
+ "ShortName": "nb-NO-PernilleNeural",
+ "Gender": "Female",
+ "Locale": "nb-NO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Pernille Online (Natural) - Norwegian (Bokmål, Norway)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ps-AF, GulNawazNeural)",
+ "ShortName": "ps-AF-GulNawazNeural",
+ "Gender": "Male",
+ "Locale": "ps-AF",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft GulNawaz Online (Natural) - Pashto (Afghanistan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ps-AF, LatifaNeural)",
+ "ShortName": "ps-AF-LatifaNeural",
+ "Gender": "Female",
+ "Locale": "ps-AF",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Latifa Online (Natural) - Pashto (Afghanistan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fa-IR, DilaraNeural)",
+ "ShortName": "fa-IR-DilaraNeural",
+ "Gender": "Female",
+ "Locale": "fa-IR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Dilara Online (Natural) - Persian (Iran)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (fa-IR, FaridNeural)",
+ "ShortName": "fa-IR-FaridNeural",
+ "Gender": "Male",
+ "Locale": "fa-IR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Farid Online (Natural) - Persian (Iran)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (pl-PL, MarekNeural)",
+ "ShortName": "pl-PL-MarekNeural",
+ "Gender": "Male",
+ "Locale": "pl-PL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Marek Online (Natural) - Polish (Poland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (pl-PL, ZofiaNeural)",
+ "ShortName": "pl-PL-ZofiaNeural",
+ "Gender": "Female",
+ "Locale": "pl-PL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Zofia Online (Natural) - Polish (Poland)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (pt-BR, AntonioNeural)",
+ "ShortName": "pt-BR-AntonioNeural",
+ "Gender": "Male",
+ "Locale": "pt-BR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Antonio Online (Natural) - Portuguese (Brazil)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (pt-BR, FranciscaNeural)",
+ "ShortName": "pt-BR-FranciscaNeural",
+ "Gender": "Female",
+ "Locale": "pt-BR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Francisca Online (Natural) - Portuguese (Brazil)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (pt-PT, DuarteNeural)",
+ "ShortName": "pt-PT-DuarteNeural",
+ "Gender": "Male",
+ "Locale": "pt-PT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Duarte Online (Natural) - Portuguese (Portugal)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (pt-PT, RaquelNeural)",
+ "ShortName": "pt-PT-RaquelNeural",
+ "Gender": "Female",
+ "Locale": "pt-PT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Raquel Online (Natural) - Portuguese (Portugal)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ro-RO, AlinaNeural)",
+ "ShortName": "ro-RO-AlinaNeural",
+ "Gender": "Female",
+ "Locale": "ro-RO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Alina Online (Natural) - Romanian (Romania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ro-RO, EmilNeural)",
+ "ShortName": "ro-RO-EmilNeural",
+ "Gender": "Male",
+ "Locale": "ro-RO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Emil Online (Natural) - Romanian (Romania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ru-RU, DmitryNeural)",
+ "ShortName": "ru-RU-DmitryNeural",
+ "Gender": "Male",
+ "Locale": "ru-RU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Dmitry Online (Natural) - Russian (Russia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ru-RU, SvetlanaNeural)",
+ "ShortName": "ru-RU-SvetlanaNeural",
+ "Gender": "Female",
+ "Locale": "ru-RU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Svetlana Online (Natural) - Russian (Russia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sr-RS, NicholasNeural)",
+ "ShortName": "sr-RS-NicholasNeural",
+ "Gender": "Male",
+ "Locale": "sr-RS",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Nicholas Online (Natural) - Serbian (Serbia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sr-RS, SophieNeural)",
+ "ShortName": "sr-RS-SophieNeural",
+ "Gender": "Female",
+ "Locale": "sr-RS",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sophie Online (Natural) - Serbian (Serbia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (si-LK, SameeraNeural)",
+ "ShortName": "si-LK-SameeraNeural",
+ "Gender": "Male",
+ "Locale": "si-LK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sameera Online (Natural) - Sinhala (Sri Lanka)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (si-LK, ThiliniNeural)",
+ "ShortName": "si-LK-ThiliniNeural",
+ "Gender": "Female",
+ "Locale": "si-LK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Thilini Online (Natural) - Sinhala (Sri Lanka)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sk-SK, LukasNeural)",
+ "ShortName": "sk-SK-LukasNeural",
+ "Gender": "Male",
+ "Locale": "sk-SK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Lukas Online (Natural) - Slovak (Slovakia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sk-SK, ViktoriaNeural)",
+ "ShortName": "sk-SK-ViktoriaNeural",
+ "Gender": "Female",
+ "Locale": "sk-SK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Viktoria Online (Natural) - Slovak (Slovakia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sl-SI, PetraNeural)",
+ "ShortName": "sl-SI-PetraNeural",
+ "Gender": "Female",
+ "Locale": "sl-SI",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Petra Online (Natural) - Slovenian (Slovenia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sl-SI, RokNeural)",
+ "ShortName": "sl-SI-RokNeural",
+ "Gender": "Male",
+ "Locale": "sl-SI",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Rok Online (Natural) - Slovenian (Slovenia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (so-SO, MuuseNeural)",
+ "ShortName": "so-SO-MuuseNeural",
+ "Gender": "Male",
+ "Locale": "so-SO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Muuse Online (Natural) - Somali (Somalia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (so-SO, UbaxNeural)",
+ "ShortName": "so-SO-UbaxNeural",
+ "Gender": "Female",
+ "Locale": "so-SO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ubax Online (Natural) - Somali (Somalia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-AR, ElenaNeural)",
+ "ShortName": "es-AR-ElenaNeural",
+ "Gender": "Female",
+ "Locale": "es-AR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Elena Online (Natural) - Spanish (Argentina)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-AR, TomasNeural)",
+ "ShortName": "es-AR-TomasNeural",
+ "Gender": "Male",
+ "Locale": "es-AR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Tomas Online (Natural) - Spanish (Argentina)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-BO, MarceloNeural)",
+ "ShortName": "es-BO-MarceloNeural",
+ "Gender": "Male",
+ "Locale": "es-BO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Marcelo Online (Natural) - Spanish (Bolivia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-BO, SofiaNeural)",
+ "ShortName": "es-BO-SofiaNeural",
+ "Gender": "Female",
+ "Locale": "es-BO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sofia Online (Natural) - Spanish (Bolivia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CL, CatalinaNeural)",
+ "ShortName": "es-CL-CatalinaNeural",
+ "Gender": "Female",
+ "Locale": "es-CL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Catalina Online (Natural) - Spanish (Chile)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CL, LorenzoNeural)",
+ "ShortName": "es-CL-LorenzoNeural",
+ "Gender": "Male",
+ "Locale": "es-CL",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Lorenzo Online (Natural) - Spanish (Chile)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CO, GonzaloNeural)",
+ "ShortName": "es-CO-GonzaloNeural",
+ "Gender": "Male",
+ "Locale": "es-CO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gonzalo Online (Natural) - Spanish (Colombia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CO, SalomeNeural)",
+ "ShortName": "es-CO-SalomeNeural",
+ "Gender": "Female",
+ "Locale": "es-CO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Salome Online (Natural) - Spanish (Colombia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CR, JuanNeural)",
+ "ShortName": "es-CR-JuanNeural",
+ "Gender": "Male",
+ "Locale": "es-CR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Juan Online (Natural) - Spanish (Costa Rica)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CR, MariaNeural)",
+ "ShortName": "es-CR-MariaNeural",
+ "Gender": "Female",
+ "Locale": "es-CR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Maria Online (Natural) - Spanish (Costa Rica)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CU, BelkysNeural)",
+ "ShortName": "es-CU-BelkysNeural",
+ "Gender": "Female",
+ "Locale": "es-CU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Belkys Online (Natural) - Spanish (Cuba)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-CU, ManuelNeural)",
+ "ShortName": "es-CU-ManuelNeural",
+ "Gender": "Male",
+ "Locale": "es-CU",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Manuel Online (Natural) - Spanish (Cuba)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-DO, EmilioNeural)",
+ "ShortName": "es-DO-EmilioNeural",
+ "Gender": "Male",
+ "Locale": "es-DO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Emilio Online (Natural) - Spanish (Dominican Republic)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-DO, RamonaNeural)",
+ "ShortName": "es-DO-RamonaNeural",
+ "Gender": "Female",
+ "Locale": "es-DO",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ramona Online (Natural) - Spanish (Dominican Republic)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-EC, AndreaNeural)",
+ "ShortName": "es-EC-AndreaNeural",
+ "Gender": "Female",
+ "Locale": "es-EC",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Andrea Online (Natural) - Spanish (Ecuador)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-EC, LuisNeural)",
+ "ShortName": "es-EC-LuisNeural",
+ "Gender": "Male",
+ "Locale": "es-EC",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Luis Online (Natural) - Spanish (Ecuador)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-SV, LorenaNeural)",
+ "ShortName": "es-SV-LorenaNeural",
+ "Gender": "Female",
+ "Locale": "es-SV",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Lorena Online (Natural) - Spanish (El Salvador)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-SV, RodrigoNeural)",
+ "ShortName": "es-SV-RodrigoNeural",
+ "Gender": "Male",
+ "Locale": "es-SV",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Rodrigo Online (Natural) - Spanish (El Salvador)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-GQ, JavierNeural)",
+ "ShortName": "es-GQ-JavierNeural",
+ "Gender": "Male",
+ "Locale": "es-GQ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Javier Online (Natural) - Spanish (Equatorial Guinea)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-GQ, TeresaNeural)",
+ "ShortName": "es-GQ-TeresaNeural",
+ "Gender": "Female",
+ "Locale": "es-GQ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Teresa Online (Natural) - Spanish (Equatorial Guinea)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-GT, AndresNeural)",
+ "ShortName": "es-GT-AndresNeural",
+ "Gender": "Male",
+ "Locale": "es-GT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Andres Online (Natural) - Spanish (Guatemala)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-GT, MartaNeural)",
+ "ShortName": "es-GT-MartaNeural",
+ "Gender": "Female",
+ "Locale": "es-GT",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Marta Online (Natural) - Spanish (Guatemala)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-HN, CarlosNeural)",
+ "ShortName": "es-HN-CarlosNeural",
+ "Gender": "Male",
+ "Locale": "es-HN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Carlos Online (Natural) - Spanish (Honduras)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-HN, KarlaNeural)",
+ "ShortName": "es-HN-KarlaNeural",
+ "Gender": "Female",
+ "Locale": "es-HN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Karla Online (Natural) - Spanish (Honduras)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-MX, DaliaNeural)",
+ "ShortName": "es-MX-DaliaNeural",
+ "Gender": "Female",
+ "Locale": "es-MX",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Dalia Online (Natural) - Spanish (Mexico)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-MX, JorgeNeural)",
+ "ShortName": "es-MX-JorgeNeural",
+ "Gender": "Male",
+ "Locale": "es-MX",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jorge Online (Natural) - Spanish (Mexico)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-NI, FedericoNeural)",
+ "ShortName": "es-NI-FedericoNeural",
+ "Gender": "Male",
+ "Locale": "es-NI",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Federico Online (Natural) - Spanish (Nicaragua)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-NI, YolandaNeural)",
+ "ShortName": "es-NI-YolandaNeural",
+ "Gender": "Female",
+ "Locale": "es-NI",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Yolanda Online (Natural) - Spanish (Nicaragua)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PA, MargaritaNeural)",
+ "ShortName": "es-PA-MargaritaNeural",
+ "Gender": "Female",
+ "Locale": "es-PA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Margarita Online (Natural) - Spanish (Panama)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PA, RobertoNeural)",
+ "ShortName": "es-PA-RobertoNeural",
+ "Gender": "Male",
+ "Locale": "es-PA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Roberto Online (Natural) - Spanish (Panama)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PY, MarioNeural)",
+ "ShortName": "es-PY-MarioNeural",
+ "Gender": "Male",
+ "Locale": "es-PY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Mario Online (Natural) - Spanish (Paraguay)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PY, TaniaNeural)",
+ "ShortName": "es-PY-TaniaNeural",
+ "Gender": "Female",
+ "Locale": "es-PY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Tania Online (Natural) - Spanish (Paraguay)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PE, AlexNeural)",
+ "ShortName": "es-PE-AlexNeural",
+ "Gender": "Male",
+ "Locale": "es-PE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Alex Online (Natural) - Spanish (Peru)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PE, CamilaNeural)",
+ "ShortName": "es-PE-CamilaNeural",
+ "Gender": "Female",
+ "Locale": "es-PE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Camila Online (Natural) - Spanish (Peru)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PR, KarinaNeural)",
+ "ShortName": "es-PR-KarinaNeural",
+ "Gender": "Female",
+ "Locale": "es-PR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Karina Online (Natural) - Spanish (Puerto Rico)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-PR, VictorNeural)",
+ "ShortName": "es-PR-VictorNeural",
+ "Gender": "Male",
+ "Locale": "es-PR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Victor Online (Natural) - Spanish (Puerto Rico)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-ES, AlvaroNeural)",
+ "ShortName": "es-ES-AlvaroNeural",
+ "Gender": "Male",
+ "Locale": "es-ES",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Alvaro Online (Natural) - Spanish (Spain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-ES, ElviraNeural)",
+ "ShortName": "es-ES-ElviraNeural",
+ "Gender": "Female",
+ "Locale": "es-ES",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Elvira Online (Natural) - Spanish (Spain)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-US, AlonsoNeural)",
+ "ShortName": "es-US-AlonsoNeural",
+ "Gender": "Male",
+ "Locale": "es-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Alonso Online (Natural) - Spanish (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-US, PalomaNeural)",
+ "ShortName": "es-US-PalomaNeural",
+ "Gender": "Female",
+ "Locale": "es-US",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Paloma Online (Natural) - Spanish (United States)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-UY, MateoNeural)",
+ "ShortName": "es-UY-MateoNeural",
+ "Gender": "Male",
+ "Locale": "es-UY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Mateo Online (Natural) - Spanish (Uruguay)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-UY, ValentinaNeural)",
+ "ShortName": "es-UY-ValentinaNeural",
+ "Gender": "Female",
+ "Locale": "es-UY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Valentina Online (Natural) - Spanish (Uruguay)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-VE, PaolaNeural)",
+ "ShortName": "es-VE-PaolaNeural",
+ "Gender": "Female",
+ "Locale": "es-VE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Paola Online (Natural) - Spanish (Venezuela)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (es-VE, SebastianNeural)",
+ "ShortName": "es-VE-SebastianNeural",
+ "Gender": "Male",
+ "Locale": "es-VE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sebastian Online (Natural) - Spanish (Venezuela)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (su-ID, JajangNeural)",
+ "ShortName": "su-ID-JajangNeural",
+ "Gender": "Male",
+ "Locale": "su-ID",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Jajang Online (Natural) - Sundanese (Indonesia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (su-ID, TutiNeural)",
+ "ShortName": "su-ID-TutiNeural",
+ "Gender": "Female",
+ "Locale": "su-ID",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Tuti Online (Natural) - Sundanese (Indonesia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sw-KE, RafikiNeural)",
+ "ShortName": "sw-KE-RafikiNeural",
+ "Gender": "Male",
+ "Locale": "sw-KE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Rafiki Online (Natural) - Swahili (Kenya)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sw-KE, ZuriNeural)",
+ "ShortName": "sw-KE-ZuriNeural",
+ "Gender": "Female",
+ "Locale": "sw-KE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Zuri Online (Natural) - Swahili (Kenya)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sw-TZ, DaudiNeural)",
+ "ShortName": "sw-TZ-DaudiNeural",
+ "Gender": "Male",
+ "Locale": "sw-TZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Daudi Online (Natural) - Swahili (Tanzania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sw-TZ, RehemaNeural)",
+ "ShortName": "sw-TZ-RehemaNeural",
+ "Gender": "Female",
+ "Locale": "sw-TZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Rehema Online (Natural) - Swahili (Tanzania)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sv-SE, MattiasNeural)",
+ "ShortName": "sv-SE-MattiasNeural",
+ "Gender": "Male",
+ "Locale": "sv-SE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Mattias Online (Natural) - Swedish (Sweden)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (sv-SE, SofieNeural)",
+ "ShortName": "sv-SE-SofieNeural",
+ "Gender": "Female",
+ "Locale": "sv-SE",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sofie Online (Natural) - Swedish (Sweden)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-IN, PallaviNeural)",
+ "ShortName": "ta-IN-PallaviNeural",
+ "Gender": "Female",
+ "Locale": "ta-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Pallavi Online (Natural) - Tamil (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-IN, ValluvarNeural)",
+ "ShortName": "ta-IN-ValluvarNeural",
+ "Gender": "Male",
+ "Locale": "ta-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Valluvar Online (Natural) - Tamil (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-MY, KaniNeural)",
+ "ShortName": "ta-MY-KaniNeural",
+ "Gender": "Female",
+ "Locale": "ta-MY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Kani Online (Natural) - Tamil (Malaysia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-MY, SuryaNeural)",
+ "ShortName": "ta-MY-SuryaNeural",
+ "Gender": "Male",
+ "Locale": "ta-MY",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Surya Online (Natural) - Tamil (Malaysia)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-SG, AnbuNeural)",
+ "ShortName": "ta-SG-AnbuNeural",
+ "Gender": "Male",
+ "Locale": "ta-SG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Anbu Online (Natural) - Tamil (Singapore)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-SG, VenbaNeural)",
+ "ShortName": "ta-SG-VenbaNeural",
+ "Gender": "Female",
+ "Locale": "ta-SG",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Venba Online (Natural) - Tamil (Singapore)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-LK, KumarNeural)",
+ "ShortName": "ta-LK-KumarNeural",
+ "Gender": "Male",
+ "Locale": "ta-LK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Kumar Online (Natural) - Tamil (Sri Lanka)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ta-LK, SaranyaNeural)",
+ "ShortName": "ta-LK-SaranyaNeural",
+ "Gender": "Female",
+ "Locale": "ta-LK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Saranya Online (Natural) - Tamil (Sri Lanka)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (te-IN, MohanNeural)",
+ "ShortName": "te-IN-MohanNeural",
+ "Gender": "Male",
+ "Locale": "te-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Mohan Online (Natural) - Telugu (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (te-IN, ShrutiNeural)",
+ "ShortName": "te-IN-ShrutiNeural",
+ "Gender": "Female",
+ "Locale": "te-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Shruti Online (Natural) - Telugu (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (th-TH, NiwatNeural)",
+ "ShortName": "th-TH-NiwatNeural",
+ "Gender": "Male",
+ "Locale": "th-TH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Niwat Online (Natural) - Thai (Thailand)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (th-TH, PremwadeeNeural)",
+ "ShortName": "th-TH-PremwadeeNeural",
+ "Gender": "Female",
+ "Locale": "th-TH",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Premwadee Online (Natural) - Thai (Thailand)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (tr-TR, AhmetNeural)",
+ "ShortName": "tr-TR-AhmetNeural",
+ "Gender": "Male",
+ "Locale": "tr-TR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ahmet Online (Natural) - Turkish (Turkey)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (tr-TR, EmelNeural)",
+ "ShortName": "tr-TR-EmelNeural",
+ "Gender": "Female",
+ "Locale": "tr-TR",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Emel Online (Natural) - Turkish (Turkey)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (uk-UA, OstapNeural)",
+ "ShortName": "uk-UA-OstapNeural",
+ "Gender": "Male",
+ "Locale": "uk-UA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Ostap Online (Natural) - Ukrainian (Ukraine)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (uk-UA, PolinaNeural)",
+ "ShortName": "uk-UA-PolinaNeural",
+ "Gender": "Female",
+ "Locale": "uk-UA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Polina Online (Natural) - Ukrainian (Ukraine)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ur-IN, GulNeural)",
+ "ShortName": "ur-IN-GulNeural",
+ "Gender": "Female",
+ "Locale": "ur-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Gul Online (Natural) - Urdu (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ur-IN, SalmanNeural)",
+ "ShortName": "ur-IN-SalmanNeural",
+ "Gender": "Male",
+ "Locale": "ur-IN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Salman Online (Natural) - Urdu (India)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ur-PK, AsadNeural)",
+ "ShortName": "ur-PK-AsadNeural",
+ "Gender": "Male",
+ "Locale": "ur-PK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Asad Online (Natural) - Urdu (Pakistan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (ur-PK, UzmaNeural)",
+ "ShortName": "ur-PK-UzmaNeural",
+ "Gender": "Female",
+ "Locale": "ur-PK",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Uzma Online (Natural) - Urdu (Pakistan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (uz-UZ, MadinaNeural)",
+ "ShortName": "uz-UZ-MadinaNeural",
+ "Gender": "Female",
+ "Locale": "uz-UZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Madina Online (Natural) - Uzbek (Uzbekistan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (uz-UZ, SardorNeural)",
+ "ShortName": "uz-UZ-SardorNeural",
+ "Gender": "Male",
+ "Locale": "uz-UZ",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Sardor Online (Natural) - Uzbek (Uzbekistan)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (vi-VN, HoaiMyNeural)",
+ "ShortName": "vi-VN-HoaiMyNeural",
+ "Gender": "Female",
+ "Locale": "vi-VN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft HoaiMy Online (Natural) - Vietnamese (Vietnam)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (vi-VN, NamMinhNeural)",
+ "ShortName": "vi-VN-NamMinhNeural",
+ "Gender": "Male",
+ "Locale": "vi-VN",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft NamMinh Online (Natural) - Vietnamese (Vietnam)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (cy-GB, AledNeural)",
+ "ShortName": "cy-GB-AledNeural",
+ "Gender": "Male",
+ "Locale": "cy-GB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Aled Online (Natural) - Welsh (United Kingdom)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (cy-GB, NiaNeural)",
+ "ShortName": "cy-GB-NiaNeural",
+ "Gender": "Female",
+ "Locale": "cy-GB",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Nia Online (Natural) - Welsh (United Kingdom)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zu-ZA, ThandoNeural)",
+ "ShortName": "zu-ZA-ThandoNeural",
+ "Gender": "Female",
+ "Locale": "zu-ZA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Thando Online (Natural) - Zulu (South Africa)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ },
+ {
+ "Name": "Microsoft Server Speech Text to Speech Voice (zu-ZA, ThembaNeural)",
+ "ShortName": "zu-ZA-ThembaNeural",
+ "Gender": "Male",
+ "Locale": "zu-ZA",
+ "SuggestedCodec": "audio-24khz-48kbitrate-mono-mp3",
+ "FriendlyName": "Microsoft Themba Online (Natural) - Zulu (South Africa)",
+ "Status": "GA",
+ "VoiceTag": {
+ "ContentCategories": [
+ "General"
+ ],
+ "VoicePersonalities": [
+ "Friendly",
+ "Positive"
+ ]
+ }
+ }
+]
\ No newline at end of file
diff --git a/rvc/lib/tools/validators.py b/rvc/lib/tools/validators.py
new file mode 100644
index 0000000000000000000000000000000000000000..9fb290bdfaa86c5bb210b9e969906447fb659d64
--- /dev/null
+++ b/rvc/lib/tools/validators.py
@@ -0,0 +1,67 @@
+import argparse
+import os
+import json
+
+
+def validate_sampling_rate(value):
+ valid_sampling = [
+ "32000",
+ "40000",
+ "48000",
+ ]
+ if value in valid_sampling:
+ return value
+ else:
+ raise argparse.ArgumentTypeError(
+ f"Invalid sampling_rate. Please choose from {valid_sampling} not {value}"
+ )
+
+
+def validate_f0up_key(value):
+ f0up_key = int(value)
+ if -24 <= f0up_key <= 24:
+ return f0up_key
+ else:
+ raise argparse.ArgumentTypeError(f"f0up_key must be in the range of -24 to +24")
+
+def validate_true_false(value):
+ valid_tf = [
+ "True",
+ "False",
+ ]
+ if value in valid_tf:
+ return value
+ else:
+ raise argparse.ArgumentTypeError(
+ f"Invalid true_false. Please choose from {valid_tf} not {value}"
+ )
+
+def validate_f0method(value):
+ valid_f0methods = [
+ "pm",
+ "dio",
+ "crepe",
+ "crepe-tiny",
+ "harvest",
+ "rmvpe",
+ ]
+ if value in valid_f0methods:
+ return value
+ else:
+ raise argparse.ArgumentTypeError(
+ f"Invalid f0method. Please choose from {valid_f0methods} not {value}"
+ )
+
+def validate_tts_voices(value):
+ json_path = os.path.join("rvc", "lib", "tools", "tts_voices.json")
+ with open(json_path, 'r') as file:
+ tts_voices_data = json.load(file)
+
+ # Extrae los valores de "ShortName" del JSON
+ short_names = [voice.get("ShortName", "") for voice in tts_voices_data]
+ if value in short_names:
+ return value
+ else:
+ raise argparse.ArgumentTypeError(
+ f"Invalid voice. Please choose from {short_names} not {value}"
+ )
\ No newline at end of file
diff --git a/rvc/lib/utils.py b/rvc/lib/utils.py
new file mode 100644
index 0000000000000000000000000000000000000000..b01b9561f25fd28c9d8ba751060c559d700feed3
--- /dev/null
+++ b/rvc/lib/utils.py
@@ -0,0 +1,26 @@
+import ffmpeg
+import numpy as np
+import re
+import unicodedata
+
+
+def load_audio(file, sampling_rate):
+ try:
+ file = file.strip(" ").strip('"').strip("\n").strip('"').strip(" ")
+ out, _ = (
+ ffmpeg.input(file, threads=0)
+ .output("-", format="f32le", acodec="pcm_f32le", ac=1, ar=sampling_rate)
+ .run(cmd=["ffmpeg", "-nostdin"], capture_stdout=True, capture_stderr=True)
+ )
+ except Exception as error:
+ raise RuntimeError(f"Failed to load audio: {error}")
+
+ return np.frombuffer(out, np.float32).flatten()
+
+
+def format_title(title):
+ formatted_title = unicodedata.normalize('NFKD', title).encode('ascii', 'ignore').decode('utf-8')
+ formatted_title = re.sub(r'[\u2500-\u257F]+', '', formatted_title)
+ formatted_title = re.sub(r'[^\w\s.-]', '', formatted_title)
+ formatted_title = re.sub(r'\s+', '_', formatted_title)
+ return formatted_title
\ No newline at end of file
diff --git a/rvc/pretraineds/pretrained/D32k.pth b/rvc/pretraineds/pretrained/D32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..346293c7023f67178a4c85da94cc3e85bdb320ef
--- /dev/null
+++ b/rvc/pretraineds/pretrained/D32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ab20645829460fdad0d3c44254f1ab53c32cae50c22a66c926ae5aa30abda6f
+size 109978943
diff --git a/rvc/pretraineds/pretrained/D40k.pth b/rvc/pretraineds/pretrained/D40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..11fd6ad63daeb5d786e78d843a6f0800c3d2394c
--- /dev/null
+++ b/rvc/pretraineds/pretrained/D40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:547f66dbbcd9023b9051ed244d12ab043ba8a4e854b154cc28761ac7c002909b
+size 109978943
diff --git a/rvc/pretraineds/pretrained/D48k.pth b/rvc/pretraineds/pretrained/D48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..48beafd328bedd8cf493bbf5f4a9d37d2260024a
--- /dev/null
+++ b/rvc/pretraineds/pretrained/D48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8cc013fa60ed9c3f902f5bd99f48c7e3b9352d763d4d3cd6bc241c37b0bfd9ad
+size 109978943
diff --git a/rvc/pretraineds/pretrained/G32k.pth b/rvc/pretraineds/pretrained/G32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..e64d79fd69b7287cdac27cd31dbdfd62c563e094
--- /dev/null
+++ b/rvc/pretraineds/pretrained/G32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:81817645cde7ed2e2d83f23ef883f33dda564924b497e84d792743912eca4c23
+size 72653893
diff --git a/rvc/pretraineds/pretrained/G40k.pth b/rvc/pretraineds/pretrained/G40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..16796af627338b8c55934df239be3b9d27f9f060
--- /dev/null
+++ b/rvc/pretraineds/pretrained/G40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e428573bda1124b0ae0ae843fd8dcded6027d3993444790b3e9b0100938b2113
+size 72763063
diff --git a/rvc/pretraineds/pretrained/G48k.pth b/rvc/pretraineds/pretrained/G48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..509a033306a137648a4f59e6016097b7bd318dd8
--- /dev/null
+++ b/rvc/pretraineds/pretrained/G48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3862a67ea6313e8ffefc05cee6bee656ef3e089442e9ecf4a6618d60721f3e95
+size 72850501
diff --git a/rvc/pretraineds/pretrained/f0D32k.pth b/rvc/pretraineds/pretrained/f0D32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..9f36ffb9c4afdf77440f4619688d985daa25b107
--- /dev/null
+++ b/rvc/pretraineds/pretrained/f0D32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:294db3087236e2c75260d6179056791c9231245daf5d0485545d9e54c4057c77
+size 109978943
diff --git a/rvc/pretraineds/pretrained/f0D40k.pth b/rvc/pretraineds/pretrained/f0D40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..da7dad91a825dac3a2ed0fb418c99be4a804811e
--- /dev/null
+++ b/rvc/pretraineds/pretrained/f0D40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7d4f5a441594b470d67579958b2fd4c6b992852ded28ff9e72eda67abcebe423
+size 109978943
diff --git a/rvc/pretraineds/pretrained/f0D48k.pth b/rvc/pretraineds/pretrained/f0D48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..789032e0a223731da818f55c6f65df22a354d6e3
--- /dev/null
+++ b/rvc/pretraineds/pretrained/f0D48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1b84c8bf347ad1e539c842e8f2a4c36ecd9e7fb23c16041189e4877e9b07925c
+size 109978943
diff --git a/rvc/pretraineds/pretrained/f0G32k.pth b/rvc/pretraineds/pretrained/f0G32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..b425a989fbdccb9821e512e9c0b4d84b80169769
--- /dev/null
+++ b/rvc/pretraineds/pretrained/f0G32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:285f524bf48bb692c76ad7bd0bc654c12bd9e5edeb784dddf7f61a789a608574
+size 72795627
diff --git a/rvc/pretraineds/pretrained/f0G40k.pth b/rvc/pretraineds/pretrained/f0G40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..a4207034410f808123cfef2ea4aeb2d412f15f72
--- /dev/null
+++ b/rvc/pretraineds/pretrained/f0G40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9115654aeef1995f7dd3c6fc4140bebbef0ca9760bed798105a2380a34299831
+size 72909665
diff --git a/rvc/pretraineds/pretrained/f0G48k.pth b/rvc/pretraineds/pretrained/f0G48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..8da740c01aeb6ec0054b221fa7da4242139b273b
--- /dev/null
+++ b/rvc/pretraineds/pretrained/f0G48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:78bc9cab27e34bcfc194f93029374d871d8b3e663ddedea32a9709e894cc8fe8
+size 73008619
diff --git a/rvc/pretraineds/pretrained_v1/D32k.pth b/rvc/pretraineds/pretrained_v1/D32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..346293c7023f67178a4c85da94cc3e85bdb320ef
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/D32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2ab20645829460fdad0d3c44254f1ab53c32cae50c22a66c926ae5aa30abda6f
+size 109978943
diff --git a/rvc/pretraineds/pretrained_v1/D40k.pth b/rvc/pretraineds/pretrained_v1/D40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..11fd6ad63daeb5d786e78d843a6f0800c3d2394c
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/D40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:547f66dbbcd9023b9051ed244d12ab043ba8a4e854b154cc28761ac7c002909b
+size 109978943
diff --git a/rvc/pretraineds/pretrained_v1/D48k.pth b/rvc/pretraineds/pretrained_v1/D48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..48beafd328bedd8cf493bbf5f4a9d37d2260024a
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/D48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:8cc013fa60ed9c3f902f5bd99f48c7e3b9352d763d4d3cd6bc241c37b0bfd9ad
+size 109978943
diff --git a/rvc/pretraineds/pretrained_v1/G32k.pth b/rvc/pretraineds/pretrained_v1/G32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..e64d79fd69b7287cdac27cd31dbdfd62c563e094
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/G32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:81817645cde7ed2e2d83f23ef883f33dda564924b497e84d792743912eca4c23
+size 72653893
diff --git a/rvc/pretraineds/pretrained_v1/G40k.pth b/rvc/pretraineds/pretrained_v1/G40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..16796af627338b8c55934df239be3b9d27f9f060
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/G40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:e428573bda1124b0ae0ae843fd8dcded6027d3993444790b3e9b0100938b2113
+size 72763063
diff --git a/rvc/pretraineds/pretrained_v1/G48k.pth b/rvc/pretraineds/pretrained_v1/G48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..509a033306a137648a4f59e6016097b7bd318dd8
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/G48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3862a67ea6313e8ffefc05cee6bee656ef3e089442e9ecf4a6618d60721f3e95
+size 72850501
diff --git a/rvc/pretraineds/pretrained_v1/f0D32k.pth b/rvc/pretraineds/pretrained_v1/f0D32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..9f36ffb9c4afdf77440f4619688d985daa25b107
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/f0D32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:294db3087236e2c75260d6179056791c9231245daf5d0485545d9e54c4057c77
+size 109978943
diff --git a/rvc/pretraineds/pretrained_v1/f0D40k.pth b/rvc/pretraineds/pretrained_v1/f0D40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..da7dad91a825dac3a2ed0fb418c99be4a804811e
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/f0D40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:7d4f5a441594b470d67579958b2fd4c6b992852ded28ff9e72eda67abcebe423
+size 109978943
diff --git a/rvc/pretraineds/pretrained_v1/f0D48k.pth b/rvc/pretraineds/pretrained_v1/f0D48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..789032e0a223731da818f55c6f65df22a354d6e3
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/f0D48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:1b84c8bf347ad1e539c842e8f2a4c36ecd9e7fb23c16041189e4877e9b07925c
+size 109978943
diff --git a/rvc/pretraineds/pretrained_v1/f0G32k.pth b/rvc/pretraineds/pretrained_v1/f0G32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..b425a989fbdccb9821e512e9c0b4d84b80169769
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/f0G32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:285f524bf48bb692c76ad7bd0bc654c12bd9e5edeb784dddf7f61a789a608574
+size 72795627
diff --git a/rvc/pretraineds/pretrained_v1/f0G40k.pth b/rvc/pretraineds/pretrained_v1/f0G40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..a4207034410f808123cfef2ea4aeb2d412f15f72
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/f0G40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:9115654aeef1995f7dd3c6fc4140bebbef0ca9760bed798105a2380a34299831
+size 72909665
diff --git a/rvc/pretraineds/pretrained_v1/f0G48k.pth b/rvc/pretraineds/pretrained_v1/f0G48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..8da740c01aeb6ec0054b221fa7da4242139b273b
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v1/f0G48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:78bc9cab27e34bcfc194f93029374d871d8b3e663ddedea32a9709e894cc8fe8
+size 73008619
diff --git a/rvc/pretraineds/pretrained_v2/D32k.pth b/rvc/pretraineds/pretrained_v2/D32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..b55340b0bc2875f148b245e781d534c5dd4f7894
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/D32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:d8043378cc6619083d385f5a045de09b83fb3bf8de45c433ca863b71723ac3ca
+size 142875703
diff --git a/rvc/pretraineds/pretrained_v2/D40k.pth b/rvc/pretraineds/pretrained_v2/D40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..6d13aea9208310573b59309a9c80310ef71c5547
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/D40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:471378e894e7191f89a94eda8288c5947b16bbe0b10c3f1f17efdb7a1d998242
+size 142875703
diff --git a/rvc/pretraineds/pretrained_v2/D48k.pth b/rvc/pretraineds/pretrained_v2/D48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..2f3b46950856921425d3dd2a0857ce14fc7dc622
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/D48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:db01094a93c09868a278e03dafe8bb781bfcc1a5ba8df168c948bf9168c84d82
+size 142875703
diff --git a/rvc/pretraineds/pretrained_v2/G32k.pth b/rvc/pretraineds/pretrained_v2/G32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..d34c78904a383344a31fa9814782e55d82d852ae
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/G32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:869b26a47f75168d6126f64ac39e6de5247017a8658cfd68aca600f7323efb9f
+size 73811639
diff --git a/rvc/pretraineds/pretrained_v2/G40k.pth b/rvc/pretraineds/pretrained_v2/G40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..ee39bf64a1fc1d0d8154e242a3b60ef3e2abf0ca
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/G40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:a3843da7fde33db1dab176146c70d6c2df06eafe9457f4e3aa10024e9c6a4b69
+size 72959671
diff --git a/rvc/pretraineds/pretrained_v2/G48k.pth b/rvc/pretraineds/pretrained_v2/G48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..71fb5f1037137dae5ae4a5786c452197f3eabab1
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/G48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2e2b1581a436d07a76b10b9d38765f64aa02836dc65c7dee1ce4140c11ea158b
+size 75318967
diff --git a/rvc/pretraineds/pretrained_v2/f0D32k.pth b/rvc/pretraineds/pretrained_v2/f0D32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..7449cc83c3f97fd87c62596f005d262120b64772
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/f0D32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:bd7134e7793674c85474d5145d2d982e3c5d8124fc7bb6c20f710ed65808fa8a
+size 142875703
diff --git a/rvc/pretraineds/pretrained_v2/f0D40k.pth b/rvc/pretraineds/pretrained_v2/f0D40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..68e29fb9debf8994f68cb4f31cc4d81d360fb73b
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/f0D40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:6b6ab091e70801b28e3f41f335f2fc5f3f35c75b39ae2628d419644ec2b0fa09
+size 142875703
diff --git a/rvc/pretraineds/pretrained_v2/f0D48k.pth b/rvc/pretraineds/pretrained_v2/f0D48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..a9f2b74cdccf9bfc2ebb0be8b481c76552a28661
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/f0D48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2269b73c7a4cf34da09aea99274dabf99b2ddb8a42cbfb065fb3c0aa9a2fc748
+size 142875703
diff --git a/rvc/pretraineds/pretrained_v2/f0G32k.pth b/rvc/pretraineds/pretrained_v2/f0G32k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..6bff869bb04fae663dddd1fbe5c04b497bfc4209
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/f0G32k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:2332611297b8d88c7436de8f17ef5f07a2119353e962cd93cda5806d59a1133d
+size 73950049
diff --git a/rvc/pretraineds/pretrained_v2/f0G40k.pth b/rvc/pretraineds/pretrained_v2/f0G40k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..3333a970abc908b4e8afd45c1cc2120ce1b4b0b4
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/f0G40k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:3b2c44035e782c4b14ddc0bede9e2f4a724d025cd073f736d4f43708453adfcb
+size 73106273
diff --git a/rvc/pretraineds/pretrained_v2/f0G48k.pth b/rvc/pretraineds/pretrained_v2/f0G48k.pth
new file mode 100644
index 0000000000000000000000000000000000000000..34d1ec0e2594379989cad7b72991152a9f97d99e
--- /dev/null
+++ b/rvc/pretraineds/pretrained_v2/f0G48k.pth
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:b5d51f589cc3632d4eae36a315b4179397695042edc01d15312e1bddc2b764a4
+size 75465569
diff --git a/rvc/train/__pycache__/data_utils.cpython-39.pyc b/rvc/train/__pycache__/data_utils.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..799d66ce214cdfdb60bee20cd500c03c118c630d
Binary files /dev/null and b/rvc/train/__pycache__/data_utils.cpython-39.pyc differ
diff --git a/rvc/train/__pycache__/losses.cpython-39.pyc b/rvc/train/__pycache__/losses.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..ab4e628be37c93f048d09d6be09ef8ee1343e293
Binary files /dev/null and b/rvc/train/__pycache__/losses.cpython-39.pyc differ
diff --git a/rvc/train/__pycache__/mel_processing.cpython-39.pyc b/rvc/train/__pycache__/mel_processing.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d9352c2dd13ade2f18a8d7b4f222707a8d742ecc
Binary files /dev/null and b/rvc/train/__pycache__/mel_processing.cpython-39.pyc differ
diff --git a/rvc/train/__pycache__/process_ckpt.cpython-39.pyc b/rvc/train/__pycache__/process_ckpt.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..52960d1967aec120b9b2e59ec639670b40558b49
Binary files /dev/null and b/rvc/train/__pycache__/process_ckpt.cpython-39.pyc differ
diff --git a/rvc/train/__pycache__/slicer.cpython-39.pyc b/rvc/train/__pycache__/slicer.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..9abed39a097214cd1d0623e839f32f3e31945a22
Binary files /dev/null and b/rvc/train/__pycache__/slicer.cpython-39.pyc differ
diff --git a/rvc/train/__pycache__/utils.cpython-39.pyc b/rvc/train/__pycache__/utils.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..d9357798fdc5d325c3cbddf95a4aeb3ae01f53cc
Binary files /dev/null and b/rvc/train/__pycache__/utils.cpython-39.pyc differ
diff --git a/rvc/train/extract/__pycache__/preparing_files.cpython-39.pyc b/rvc/train/extract/__pycache__/preparing_files.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..e2059a64dd91a302eab3bc752fea01c5a1349ed3
Binary files /dev/null and b/rvc/train/extract/__pycache__/preparing_files.cpython-39.pyc differ
diff --git a/rvc/train/process/__pycache__/extract_model.cpython-39.pyc b/rvc/train/process/__pycache__/extract_model.cpython-39.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..aaf2238b02ffa6a45214e09810a172f0437d364f
Binary files /dev/null and b/rvc/train/process/__pycache__/extract_model.cpython-39.pyc differ