This commit is contained in:
rcell
2023-07-24 15:16:06 +08:00
parent 1fa3ce1d03
commit 9fd6e9a259
7 changed files with 348 additions and 50345 deletions

View File

@@ -13,7 +13,7 @@
"batch_size": 32, "batch_size": 32,
"fp16_run": true, "fp16_run": true,
"lr_decay": 0.999875, "lr_decay": 0.999875,
"segment_size": 8192, "segment_size": 16384,
"init_lr_ratio": 1, "init_lr_ratio": 1,
"warmup_epochs": 0, "warmup_epochs": 0,
"c_mel": 45, "c_mel": 45,
@@ -23,161 +23,194 @@
"training_files": "filelists/train.list", "training_files": "filelists/train.list",
"validation_files": "filelists/val.list", "validation_files": "filelists/val.list",
"max_wav_value": 32768.0, "max_wav_value": 32768.0,
"sampling_rate": 22050, "sampling_rate": 44100,
"filter_length": 1024, "filter_length": 2048,
"hop_length": 256, "hop_length": 512,
"win_length": 1024, "win_length": 2048,
"n_mel_channels": 80, "n_mel_channels": 128,
"mel_fmin": 0.0, "mel_fmin": 0.0,
"mel_fmax": null, "mel_fmax": null,
"add_blank": true, "add_blank": true,
"n_speakers": 300, "n_speakers": 300,
"cleaned_text": true, "cleaned_text": true,
"spk2id": { "spk2id": {
"SSB0080": 0, "": 0,
"SSB0012": 1, "": 1,
"SSB0038": 2, "派蒙": 2,
"SSB0382": 3, "纳西妲": 3,
"SSB0394": 4, "阿贝多": 4,
"SSB0395": 5, "温迪": 5,
"SSB0316": 6, "枫原万叶": 6,
"SSB0200": 7, "钟离": 7,
"SSB1408": 8, "荒泷一斗": 8,
"SSB1392": 9, "八重神子": 9,
"SSB0700": 10, "艾尔海森": 10,
"SSB1138": 11, "提纳里": 11,
"SSB1072": 12, "迪希雅": 12,
"SSB0751": 13, "卡维": 13,
"SSB0338": 14, "宵宫": 14,
"SSB0435": 15, "莱依拉": 15,
"SSB0913": 16, "赛诺": 16,
"SSB1806": 17, "诺艾尔": 17,
"SSB1878": 18, "托马": 18,
"SSB1385": 19, "凝光": 19,
"SSB0817": 20, "莫娜": 20,
"SSB0599": 21, "北斗": 21,
"SSB0887": 22, "神里绫华": 22,
"SSB0720": 23, "雷电将军": 23,
"SSB1091": 24, "芭芭拉": 24,
"SSB0786": 25, "鹿野院平藏": 25,
"SSB0737": 26, "五郎": 26,
"SSB0666": 27, "迪奥娜": 27,
"SSB0606": 28, "凯亚": 28,
"SSB0535": 29, "安柏": 29,
"SSB0112": 30, "班尼特": 30,
"SSB1161": 31, "": 31,
"SSB1448": 32, "柯莱": 32,
"SSB1684": 33, "夜兰": 33,
"SSB1699": 34, "妮露": 34,
"SSB1341": 35, "辛焱": 35,
"SSB0919": 36, "珐露珊": 36,
"SSB1056": 37, "": 37,
"SSB1115": 38, "香菱": 38,
"SSB1563": 39, "达达利亚": 39,
"SSB0482": 40, "砂糖": 40,
"SSB0502": 41, "早柚": 41,
"SSB0415": 42, "云堇": 42,
"SSB0145": 43, "刻晴": 43,
"0001_Angry": 44, "丽莎": 44,
"0001_Happy": 45, "迪卢克": 45,
"0001_Neutral": 46, "烟绯": 46,
"0001_Sad": 47, "重云": 47,
"0001_Surprise": 48, "珊瑚宫心海": 48,
"0002_Angry": 49, "胡桃": 49,
"0002_Happy": 50, "可莉": 50,
"0002_Neutral": 51, "流浪者": 51,
"0002_Sad": 52, "久岐忍": 52,
"0002_Surprise": 53, "神里绫人": 53,
"0003_Angry": 54, "甘雨": 54,
"0003_Happy": 55, "戴因斯雷布": 55,
"0003_Neutral": 56, "优菈": 56,
"0003_Sad": 57, "菲谢尔": 57,
"0003_Surprise": 58, "行秋": 58,
"0004_Angry": 59, "白术": 59,
"0004_Happy": 60, "九条裟罗": 60,
"0004_Neutral": 61, "雷泽": 61,
"0004_Sad": 62, "申鹤": 62,
"0004_Surprise": 63, "迪娜泽黛": 63,
"0005_Angry": 64, "凯瑟琳": 64,
"0005_Happy": 65, "多莉": 65,
"0005_Neutral": 66, "坎蒂丝": 66,
"0005_Sad": 67, "萍姥姥": 67,
"0005_Surprise": 68, "罗莎莉亚": 68,
"0006_Angry": 69, "留云借风真君": 69,
"0006_Happy": 70, "绮良良": 70,
"0006_Neutral": 71, "瑶瑶": 71,
"0006_Sad": 72, "七七": 72,
"0006_Surprise": 73, "奥兹": 73,
"0007_Angry": 74, "米卡": 74,
"0007_Happy": 75, "夏洛蒂": 75,
"0007_Neutral": 76, "埃洛伊": 76,
"0007_Sad": 77, "博士": 77,
"0007_Surprise": 78, "女士": 78,
"0008_Angry": 79, "大慈树王": 79,
"0008_Happy": 80, "三月七": 80,
"0008_Neutral": 81, "娜塔莎": 81,
"0008_Sad": 82, "希露瓦": 82,
"0008_Surprise": 83, "虎克": 83,
"0009_Angry": 84, "克拉拉": 84,
"0009_Happy": 85, "丹恒": 85,
"0009_Neutral": 86, "希儿": 86,
"0009_Sad": 87, "布洛妮娅": 87,
"0009_Surprise": 88, "瓦尔特": 88,
"0010_Angry": 89, "杰帕德": 89,
"0010_Happy": 90, "佩拉": 90,
"0010_Neutral": 91, "姬子": 91,
"0010_Sad": 92, "艾丝妲": 92,
"0010_Surprise": 93, "白露": 93,
"0011_Angry": 94, "": 94,
"0011_Happy": 95, "": 95,
"0011_Neutral": 96, "桑博": 96,
"0011_Sad": 97, "伦纳德": 97,
"0011_Surprise": 98, "停云": 98,
"0012_Angry": 99, "罗刹": 99,
"0012_Happy": 100, "卡芙卡": 100,
"0012_Neutral": 101, "彦卿": 101,
"0012_Sad": 102, "史瓦罗": 102,
"0012_Surprise": 103, "螺丝咕姆": 103,
"0013_Angry": 104, "阿兰": 104,
"0013_Happy": 105, "银狼": 105,
"0013_Neutral": 106, "素裳": 106,
"0013_Sad": 107, "丹枢": 107,
"0013_Surprise": 108, "黑塔": 108,
"0014_Angry": 109, "景元": 109,
"0014_Happy": 110, "帕姆": 110,
"0014_Neutral": 111, "可可利亚": 111,
"0014_Sad": 112, "半夏": 112,
"0014_Surprise": 113, "符玄": 113,
"0015_Angry": 114, "公输师傅": 114,
"0015_Happy": 115, "奥列格": 115,
"0015_Neutral": 116, "青雀": 116,
"0015_Sad": 117, "大毫": 117,
"0015_Surprise": 118, "青镞": 118,
"0016_Angry": 119, "费斯曼": 119,
"0016_Happy": 120, "绿芙蓉": 120,
"0016_Neutral": 121, "镜流": 121,
"0016_Sad": 122, "信使": 122,
"0016_Surprise": 123, "丽塔": 123,
"0017_Angry": 124, "失落迷迭": 124,
"0017_Happy": 125, "缭乱星棘": 125,
"0017_Neutral": 126, "伊甸": 126,
"0017_Sad": 127, "伏特加女孩": 127,
"0017_Surprise": 128, "狂热蓝调": 128,
"0018_Angry": 129, "莉莉娅": 129,
"0018_Happy": 130, "萝莎莉娅": 130,
"0018_Neutral": 131, "八重樱": 131,
"0018_Sad": 132, "八重霞": 132,
"0018_Surprise": 133, "卡莲": 133,
"0019_Angry": 134, "第六夜想曲": 134,
"0019_Happy": 135, "卡萝尔": 135,
"0019_Neutral": 136, "极地战刃": 136,
"0019_Sad": 137, "次生银翼": 137,
"0019_Surprise": 138, "理之律者": 138,
"0020_Angry": 139, "真理之律者": 139,
"0020_Happy": 140, "迷城骇兔": 140,
"0020_Neutral": 141, "魇夜星渊": 141,
"0020_Sad": 142, "黑希儿": 142,
"0020_Surprise": 143 "帕朵菲莉丝": 143,
"天元骑英": 144,
"幽兰黛尔": 145,
"德丽莎": 146,
"月下初拥": 147,
"朔夜观星": 148,
"暮光骑士": 149,
"明日香": 150,
"李素裳": 151,
"格蕾修": 152,
"梅比乌斯": 153,
"渡鸦": 154,
"人之律者": 155,
"爱莉希雅": 156,
"爱衣": 157,
"天穹游侠": 158,
"琪亚娜": 159,
"空之律者": 160,
"终焉之律者": 161,
"薪炎之律者": 162,
"云墨丹心": 163,
"符华": 164,
"识之律者": 165,
"维尔薇": 166,
"始源之律者": 167,
"芽衣": 168,
"雷之律者": 169,
"苏莎娜": 170,
"阿波尼亚": 171,
"陆景和": 172,
"莫弈": 173,
"夏彦": 174,
"左然": 175,
"标贝": 176
} }
}, },
"model": { "model": {
@@ -214,14 +247,14 @@
"upsample_rates": [ "upsample_rates": [
8, 8,
8, 8,
2, 4,
2 2
], ],
"upsample_initial_channel": 512, "upsample_initial_channel": 512,
"upsample_kernel_sizes": [ "upsample_kernel_sizes": [
16, 16,
16, 16,
4, 8,
4 4
], ],
"n_layers_q": 3, "n_layers_q": 3,

View File

@@ -5,26 +5,29 @@ import numpy as np
import torch import torch
import torch.utils.data import torch.utils.data
import commons import commons
from mel_processing import spectrogram_torch from mel_processing import spectrogram_torch
from utils import load_wav_to_torch, load_filepaths_and_text from utils import load_wav_to_torch, load_filepaths_and_text
from text import cleaned_text_to_sequence, get_bert from text import cleaned_text_to_sequence, get_bert
"""Multi speaker version""" """Multi speaker version"""
class TextAudioSpeakerLoader(torch.utils.data.Dataset): class TextAudioSpeakerLoader(torch.utils.data.Dataset):
""" """
1) loads audio, speaker_id, text pairs 1) loads audio, speaker_id, text pairs
2) normalizes text and converts them to sequences of integers 2) normalizes text and converts them to sequences of integers
3) computes spectrograms from audio files. 3) computes spectrograms from audio files.
""" """
def __init__(self, audiopaths_sid_text, hparams): def __init__(self, audiopaths_sid_text, hparams):
self.audiopaths_sid_text = load_filepaths_and_text(audiopaths_sid_text) self.audiopaths_sid_text = load_filepaths_and_text(audiopaths_sid_text)
self.max_wav_value = hparams.max_wav_value self.max_wav_value = hparams.max_wav_value
self.sampling_rate = hparams.sampling_rate self.sampling_rate = hparams.sampling_rate
self.filter_length = hparams.filter_length self.filter_length = hparams.filter_length
self.hop_length = hparams.hop_length self.hop_length = hparams.hop_length
self.win_length = hparams.win_length self.win_length = hparams.win_length
self.sampling_rate = hparams.sampling_rate self.sampling_rate = hparams.sampling_rate
self.spk_map = hparams.spk2id self.spk_map = hparams.spk2id
self.cleaned_text = getattr(hparams, "cleaned_text", False) self.cleaned_text = getattr(hparams, "cleaned_text", False)
@@ -49,12 +52,12 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
lengths = [] lengths = []
skipped = 0 skipped = 0
for _id, spk, language, text, phones, tone, word2ph in self.audiopaths_sid_text: for _id, spk, language, text, phones, tone, word2ph in self.audiopaths_sid_text:
audiopath = f'dataset/{spk}/{_id}.wav' audiopath = f'dataset/{spk}/{_id}.wav'
if self.min_text_len <= len(phones) and len(phones) <= self.max_text_len: if self.min_text_len <= len(phones) and len(phones) <= self.max_text_len:
phones = phones.split(" ") phones = phones.split(" ")
tone = [int(i) for i in tone.split(" ")] tone = [int(i) for i in tone.split(" ")]
word2ph = [int(i) for i in word2ph.split(" ")] word2ph = [int(i) for i in word2ph.split(" ")]
audiopaths_sid_text_new.append([audiopath, spk, language,text, phones, tone, word2ph]) audiopaths_sid_text_new.append([audiopath, spk, language, text, phones, tone, word2ph])
lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length)) lengths.append(os.path.getsize(audiopath) // (2 * self.hop_length))
else: else:
skipped += 1 skipped += 1
@@ -66,7 +69,7 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
# separate filename, speaker_id and text # separate filename, speaker_id and text
audiopath, sid, language, text, phones, tone, word2ph = audiopath_sid_text audiopath, sid, language, text, phones, tone, word2ph = audiopath_sid_text
bert, phones, tone, language = self.get_text(text, word2ph, phones, tone, language,audiopath) bert, phones, tone, language = self.get_text(text, word2ph, phones, tone, language, audiopath)
spec, wav = self.get_audio(audiopath) spec, wav = self.get_audio(audiopath)
sid = torch.LongTensor([int(self.spk_map[sid])]) sid = torch.LongTensor([int(self.spk_map[sid])])
@@ -80,17 +83,17 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
audio_norm = audio / self.max_wav_value audio_norm = audio / self.max_wav_value
audio_norm = audio_norm.unsqueeze(0) audio_norm = audio_norm.unsqueeze(0)
spec_filename = filename.replace(".wav", ".spec.pt") spec_filename = filename.replace(".wav", ".spec.pt")
if os.path.exists(spec_filename): try:
spec = torch.load(spec_filename) spec = torch.load(spec_filename)
else: except:
spec = spectrogram_torch(audio_norm, self.filter_length, spec = spectrogram_torch(audio_norm, self.filter_length,
self.sampling_rate, self.hop_length, self.win_length, self.sampling_rate, self.hop_length, self.win_length,
center=False) center=False)
spec = torch.squeeze(spec, 0) spec = torch.squeeze(spec, 0)
torch.save(spec, spec_filename) torch.save(spec, spec_filename)
return spec, audio_norm return spec, audio_norm
def get_text(self,text, word2ph,phone, tone, language_str, wav_path): def get_text(self, text, word2ph, phone, tone, language_str, wav_path):
# print(text, word2ph,phone, tone, language_str) # print(text, word2ph,phone, tone, language_str)
pold = phone pold = phone
w2pho = [i for i in word2ph] w2pho = [i for i in word2ph]
@@ -115,8 +118,12 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
assert bert.shape[-1] == len(phone) assert bert.shape[-1] == len(phone)
except: except:
bert = get_bert(text, word2ph, language_str) bert = get_bert(text, word2ph, language_str)
assert bert.shape[-1] == len(phone), (bert.shape, len(phone), sum(word2ph), p1, p2, t1, t2, pold, pold2,word2ph, text,w2pho) torch.save(bert, bert_path)
torch.save(bert, bert_path) print(bert.shape[-1], bert_path, text, pold)
assert bert.shape[-1] == len(phone)
assert bert.shape[-1] == len(phone), (
bert.shape, len(phone), sum(word2ph), p1, p2, t1, t2, pold, pold2, word2ph, text, w2pho)
phone = torch.LongTensor(phone) phone = torch.LongTensor(phone)
tone = torch.LongTensor(tone) tone = torch.LongTensor(tone)
language = torch.LongTensor(language) language = torch.LongTensor(language)
@@ -136,6 +143,7 @@ class TextAudioSpeakerLoader(torch.utils.data.Dataset):
class TextAudioSpeakerCollate(): class TextAudioSpeakerCollate():
""" Zero-pads model inputs and targets """ Zero-pads model inputs and targets
""" """
def __init__(self, return_ids=False): def __init__(self, return_ids=False):
self.return_ids = return_ids self.return_ids = return_ids
@@ -206,20 +214,21 @@ class DistributedBucketSampler(torch.utils.data.distributed.DistributedSampler):
Maintain similar input lengths in a batch. Maintain similar input lengths in a batch.
Length groups are specified by boundaries. Length groups are specified by boundaries.
Ex) boundaries = [b1, b2, b3] -> any batch is included either {x | b1 < length(x) <=b2} or {x | b2 < length(x) <= b3}. Ex) boundaries = [b1, b2, b3] -> any batch is included either {x | b1 < length(x) <=b2} or {x | b2 < length(x) <= b3}.
It removes samples which are not included in the boundaries. It removes samples which are not included in the boundaries.
Ex) boundaries = [b1, b2, b3] -> any x s.t. length(x) <= b1 or length(x) > b3 are discarded. Ex) boundaries = [b1, b2, b3] -> any x s.t. length(x) <= b1 or length(x) > b3 are discarded.
""" """
def __init__(self, dataset, batch_size, boundaries, num_replicas=None, rank=None, shuffle=True): def __init__(self, dataset, batch_size, boundaries, num_replicas=None, rank=None, shuffle=True):
super().__init__(dataset, num_replicas=num_replicas, rank=rank, shuffle=shuffle) super().__init__(dataset, num_replicas=num_replicas, rank=rank, shuffle=shuffle)
self.lengths = dataset.lengths self.lengths = dataset.lengths
self.batch_size = batch_size self.batch_size = batch_size
self.boundaries = boundaries self.boundaries = boundaries
self.buckets, self.num_samples_per_bucket = self._create_buckets() self.buckets, self.num_samples_per_bucket = self._create_buckets()
self.total_size = sum(self.num_samples_per_bucket) self.total_size = sum(self.num_samples_per_bucket)
self.num_samples = self.total_size // self.num_replicas self.num_samples = self.total_size // self.num_replicas
def _create_buckets(self): def _create_buckets(self):
buckets = [[] for _ in range(len(self.boundaries) - 1)] buckets = [[] for _ in range(len(self.boundaries) - 1)]
for i in range(len(self.lengths)): for i in range(len(self.lengths)):
@@ -227,12 +236,12 @@ class DistributedBucketSampler(torch.utils.data.distributed.DistributedSampler):
idx_bucket = self._bisect(length) idx_bucket = self._bisect(length)
if idx_bucket != -1: if idx_bucket != -1:
buckets[idx_bucket].append(i) buckets[idx_bucket].append(i)
for i in range(len(buckets) - 1, 0, -1): for i in range(len(buckets) - 1, 0, -1):
if len(buckets[i]) == 0: if len(buckets[i]) == 0:
buckets.pop(i) buckets.pop(i)
self.boundaries.pop(i+1) self.boundaries.pop(i + 1)
num_samples_per_bucket = [] num_samples_per_bucket = []
for i in range(len(buckets)): for i in range(len(buckets)):
len_bucket = len(buckets[i]) len_bucket = len(buckets[i])
@@ -240,61 +249,61 @@ class DistributedBucketSampler(torch.utils.data.distributed.DistributedSampler):
rem = (total_batch_size - (len_bucket % total_batch_size)) % total_batch_size rem = (total_batch_size - (len_bucket % total_batch_size)) % total_batch_size
num_samples_per_bucket.append(len_bucket + rem) num_samples_per_bucket.append(len_bucket + rem)
return buckets, num_samples_per_bucket return buckets, num_samples_per_bucket
def __iter__(self): def __iter__(self):
# deterministically shuffle based on epoch # deterministically shuffle based on epoch
g = torch.Generator() g = torch.Generator()
g.manual_seed(self.epoch) g.manual_seed(self.epoch)
indices = [] indices = []
if self.shuffle: if self.shuffle:
for bucket in self.buckets: for bucket in self.buckets:
indices.append(torch.randperm(len(bucket), generator=g).tolist()) indices.append(torch.randperm(len(bucket), generator=g).tolist())
else: else:
for bucket in self.buckets: for bucket in self.buckets:
indices.append(list(range(len(bucket)))) indices.append(list(range(len(bucket))))
batches = [] batches = []
for i in range(len(self.buckets)): for i in range(len(self.buckets)):
bucket = self.buckets[i] bucket = self.buckets[i]
len_bucket = len(bucket) len_bucket = len(bucket)
ids_bucket = indices[i] ids_bucket = indices[i]
num_samples_bucket = self.num_samples_per_bucket[i] num_samples_bucket = self.num_samples_per_bucket[i]
# add extra samples to make it evenly divisible # add extra samples to make it evenly divisible
rem = num_samples_bucket - len_bucket rem = num_samples_bucket - len_bucket
ids_bucket = ids_bucket + ids_bucket * (rem // len_bucket) + ids_bucket[:(rem % len_bucket)] ids_bucket = ids_bucket + ids_bucket * (rem // len_bucket) + ids_bucket[:(rem % len_bucket)]
# subsample # subsample
ids_bucket = ids_bucket[self.rank::self.num_replicas] ids_bucket = ids_bucket[self.rank::self.num_replicas]
# batching # batching
for j in range(len(ids_bucket) // self.batch_size): for j in range(len(ids_bucket) // self.batch_size):
batch = [bucket[idx] for idx in ids_bucket[j*self.batch_size:(j+1)*self.batch_size]] batch = [bucket[idx] for idx in ids_bucket[j * self.batch_size:(j + 1) * self.batch_size]]
batches.append(batch) batches.append(batch)
if self.shuffle: if self.shuffle:
batch_ids = torch.randperm(len(batches), generator=g).tolist() batch_ids = torch.randperm(len(batches), generator=g).tolist()
batches = [batches[i] for i in batch_ids] batches = [batches[i] for i in batch_ids]
self.batches = batches self.batches = batches
assert len(self.batches) * self.batch_size == self.num_samples assert len(self.batches) * self.batch_size == self.num_samples
return iter(self.batches) return iter(self.batches)
def _bisect(self, x, lo=0, hi=None): def _bisect(self, x, lo=0, hi=None):
if hi is None: if hi is None:
hi = len(self.boundaries) - 1 hi = len(self.boundaries) - 1
if hi > lo: if hi > lo:
mid = (hi + lo) // 2 mid = (hi + lo) // 2
if self.boundaries[mid] < x and x <= self.boundaries[mid+1]: if self.boundaries[mid] < x and x <= self.boundaries[mid + 1]:
return mid return mid
elif x <= self.boundaries[mid]: elif x <= self.boundaries[mid]:
return self._bisect(x, lo, mid) return self._bisect(x, lo, mid)
else: else:
return self._bisect(x, mid + 1, hi) return self._bisect(x, mid + 1, hi)
else: else:
return -1 return -1
def __len__(self): def __len__(self):
return self.num_samples // self.batch_size return self.num_samples // self.batch_size

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +0,0 @@
SSB00800286|SSB0080|ZH|合肥的-城镇-有什么.|_ h e f ei d e - ch eng zh en - y ou sh en m e . _|0 2 2 2 2 5 5 0 2 2 4 4 0 3 3 2 2 5 5 0 0|1 2 2 2 1 2 2 1 2 2 2 1 1
SSB00800245|SSB0080|ZH|跟-以前的-地方-差不多-一样.|_ g en - y i q ian d e - d i f ang - ch a b u d uo - y i y ang . _|0 1 1 0 3 3 2 2 5 5 0 4 4 5 5 0 4 4 5 5 1 1 0 2 2 4 4 0 0|1 2 1 2 2 2 1 2 2 1 2 2 2 1 2 2 1 1
SSB00120433|SSB0012|ZH|江华的-连续剧-有什么.|_ j iang h ua d e - l ian x v j v - y ou sh en m e . _|0 1 1 2 2 5 5 0 2 2 4 4 4 4 0 3 3 2 2 5 5 0 0|1 2 2 2 1 2 2 2 1 2 2 2 1 1
SSB00120132|SSB0012|ZH|还在你-老爸的-思达-柜台-干活吗.|_ h ai z ai n i - l ao b a d e - s i0 d a - g ui t ai - g an h uo m a . _|0 2 2 4 4 3 3 0 3 3 4 4 5 5 0 1 1 2 2 0 4 4 2 2 0 4 4 2 2 5 5 0 0|1 2 2 2 1 2 2 2 1 2 2 1 2 2 1 2 2 2 1 1
SSB00380151|SSB0038|ZH|给我-放首歌-谭咏麟的歌.|_ g ei w o - f ang sh ou g e - t an y ong l in d e g e . _|0 2 2 3 3 0 4 4 3 3 1 1 0 2 2 3 3 2 2 5 5 1 1 0 0|1 2 2 1 2 2 2 1 2 2 2 2 2 1 1
SSB00380331|SSB0038|ZH|推测-投放-时间为.十九日-下午-或-傍晚.|_ t ui c e - t ou f ang - sh ir j ian w ei . sh ir j iu r ir - x ia w u - h uo - b ang w an . _|0 1 1 4 4 0 2 2 4 4 0 2 2 1 1 4 4 0 2 2 3 3 4 4 0 4 4 3 3 0 4 4 0 4 4 3 3 0 0|1 2 2 1 2 2 1 2 2 2 1 2 2 2 1 2 2 1 2 1 2 2 1 1
SSB03820389|SSB0382|ZH|停车场.|_ t ing ch e ch ang . _|0 2 2 1 1 3 3 0 0|1 2 2 2 1 1
SSB03820048|SSB0382|ZH|宝华-图文.|_ b ao h ua - t u w en . _|0 3 3 2 2 0 2 2 2 2 0 0|1 2 2 1 2 2 1 1

View File

@@ -4,9 +4,9 @@ from random import shuffle
import tqdm import tqdm
from text.cleaner import clean_text from text.cleaner import clean_text
from collections import defaultdict from collections import defaultdict
stage = [1,2,3] stage = [2,3]
transcription_path = 'filelists/aishell.list' transcription_path = 'filelists/genshin.txt'
train_path = 'filelists/train.list' train_path = 'filelists/train.list'
val_path = 'filelists/val.list' val_path = 'filelists/val.list'
config_path = "configs/config.json" config_path = "configs/config.json"
@@ -16,11 +16,14 @@ max_val_total = 8
if 1 in stage: if 1 in stage:
with open( transcription_path+'.cleaned', 'w', encoding='utf-8') as f: with open( transcription_path+'.cleaned', 'w', encoding='utf-8') as f:
for line in tqdm.tqdm(open(transcription_path, encoding='utf-8').readlines()): for line in tqdm.tqdm(open(transcription_path, encoding='utf-8').readlines()):
utt, spk, language, text = line.strip().split('|') try:
norm_text, phones, tones, word2ph = clean_text(text, language) utt, spk, language, text = line.strip().split('|')
f.write('{}|{}|{}|{}|{}|{}|{}\n'.format(utt, spk, language, norm_text, ' '.join(phones), norm_text, phones, tones, word2ph = clean_text(text, language)
" ".join([str(i) for i in tones]), f.write('{}|{}|{}|{}|{}|{}|{}\n'.format(utt, spk, language, norm_text, ' '.join(phones),
" ".join([str(i) for i in word2ph]))) " ".join([str(i) for i in tones]),
" ".join([str(i) for i in word2ph])))
except:
print("err!", text)
if 2 in stage: if 2 in stage:
spk_utt_map = defaultdict(list) spk_utt_map = defaultdict(list)
@@ -34,29 +37,29 @@ if 2 in stage:
if spk not in spk_id_map.keys(): if spk not in spk_id_map.keys():
spk_id_map[spk] = current_sid spk_id_map[spk] = current_sid
current_sid += 1 current_sid += 1
#
train_list = [] # train_list = []
val_list = [] # val_list = []
#
for spk, utts in spk_utt_map.items(): # for spk, utts in spk_utt_map.items():
shuffle(utts) # shuffle(utts)
val_list+=utts[:val_per_spk] # val_list+=utts[:val_per_spk]
train_list+=utts[val_per_spk:] # train_list+=utts[val_per_spk:]
if len(val_list) > max_val_total: # if len(val_list) > max_val_total:
train_list+=val_list[max_val_total:] # train_list+=val_list[max_val_total:]
val_list = val_list[:max_val_total] # val_list = val_list[:max_val_total]
#
with open( train_path,"w", encoding='utf-8') as f: # with open( train_path,"w", encoding='utf-8') as f:
for line in train_list: # for line in train_list:
f.write(line) # f.write(line)
#
with open(val_path, "w", encoding='utf-8') as f: # with open(val_path, "w", encoding='utf-8') as f:
for line in val_list: # for line in val_list:
f.write(line) # f.write(line)
if 3 in stage: if 3 in stage:
assert 2 in stage assert 2 in stage
config = json.load(open(config_path)) config = json.load(open(config_path))
config["data"]['spk2id'] = spk_id_map config["data"]['spk2id'] = spk_id_map
with open(config_path, 'w', encoding='utf-8') as f: with open(config_path, 'w', encoding='utf-8') as f:
json.dump(config, f, indent=2) json.dump(config, f, indent=2, ensure_ascii=False)

View File

@@ -1,14 +1,57 @@
import torch
from torch.utils.data import DataLoader
import commons
import utils import utils
from data_utils import TextAudioSpeakerLoader from data_utils import TextAudioSpeakerLoader, TextAudioSpeakerCollate
from tqdm import tqdm from tqdm import tqdm
config_path = 'configs/fzh.json' from text import cleaned_text_to_sequence, get_bert
config_path = 'configs/config.json'
hps = utils.get_hparams_from_file(config_path) hps = utils.get_hparams_from_file(config_path)
train_dataset = TextAudioSpeakerLoader(hps.data.training_files, hps.data) train_dataset = TextAudioSpeakerLoader(hps.data.training_files, hps.data)
eval_dataset = TextAudioSpeakerLoader(hps.data.validation_files, hps.data) eval_dataset = TextAudioSpeakerLoader(hps.data.validation_files, hps.data)
for _ in tqdm(train_dataset): collate_fn = TextAudioSpeakerCollate()
train_loader = DataLoader(train_dataset, num_workers=12, shuffle=False,
batch_size=32, pin_memory=True,
drop_last=False, collate_fn=collate_fn)
eval_loader = DataLoader(eval_dataset, num_workers=12, shuffle=False,
batch_size=32, pin_memory=True,
drop_last=False, collate_fn=collate_fn)
for _ in tqdm(train_loader):
pass pass
for _ in tqdm(eval_dataset): for _ in tqdm(eval_loader):
pass pass
# for line in tqdm( open(hps.data.training_files).readlines()):
# _id, spk, language_str, text, phones, tone, word2ph = line.strip().split("|")
# phone = phones.split(" ")
# tone = [int(i) for i in tone.split(" ")]
# word2ph = [int(i) for i in word2ph.split(" ")]
# # print(text, word2ph,phone, tone, language_str)
# w2pho = [i for i in word2ph]
# word2ph = [i for i in word2ph]
# phone, tone, language = cleaned_text_to_sequence(phone, tone, language_str)
# pold2 = phone
# if hps.data.add_blank:
# phone = commons.intersperse(phone, 0)
# tone = commons.intersperse(tone, 0)
# language = commons.intersperse(language, 0)
# for i in range(len(word2ph)):
# word2ph[i] = word2ph[i] * 2
# word2ph[0] += 1
# wav_path = f'dataset/{spk}/{_id}.wav'
# bert_path = wav_path.replace(".wav", ".bert.pt")
# try:
# bert = torch.load(bert_path)
# assert bert.shape[-1] == len(phone)
# except:
# bert = get_bert(text, word2ph, language_str)
# assert bert.shape[-1] == len(phone)
# torch.save(bert, bert_path)

View File

@@ -72,7 +72,7 @@ def run(rank, n_gpus, hps):
rank=rank, rank=rank,
shuffle=True) shuffle=True)
collate_fn = TextAudioSpeakerCollate() collate_fn = TextAudioSpeakerCollate()
train_loader = DataLoader(train_dataset, num_workers=4, shuffle=False, pin_memory=True, train_loader = DataLoader(train_dataset, num_workers=20, shuffle=False, pin_memory=True,
collate_fn=collate_fn, batch_sampler=train_sampler, persistent_workers=True) collate_fn=collate_fn, batch_sampler=train_sampler, persistent_workers=True)
if rank == 0: if rank == 0:
eval_dataset = TextAudioSpeakerLoader(hps.data.validation_files, hps.data) eval_dataset = TextAudioSpeakerLoader(hps.data.validation_files, hps.data)
@@ -107,7 +107,7 @@ def run(rank, n_gpus, hps):
net_g = DDP(net_g, device_ids=[rank]) net_g = DDP(net_g, device_ids=[rank])
net_d = DDP(net_d, device_ids=[rank]) net_d = DDP(net_d, device_ids=[rank])
pretrain_dir = "logs/esd" pretrain_dir = None
if pretrain_dir is None: if pretrain_dir is None:
_, _, _, epoch_str = utils.load_checkpoint(utils.latest_checkpoint_path(hps.model_dir, "G_*.pth"), net_g, _, _, _, epoch_str = utils.load_checkpoint(utils.latest_checkpoint_path(hps.model_dir, "G_*.pth"), net_g,
optim_g, False) optim_g, False)
@@ -120,8 +120,6 @@ def run(rank, n_gpus, hps):
optim_g, True) optim_g, True)
_, _, _, epoch_str = utils.load_checkpoint(utils.latest_checkpoint_path(pretrain_dir, "D_*.pth"), net_d, _, _, _, epoch_str = utils.load_checkpoint(utils.latest_checkpoint_path(pretrain_dir, "D_*.pth"), net_d,
optim_d, True) optim_d, True)
epoch_str = 1
global_step = 0