diff --git a/TTS/tts/datasets/preprocess.py b/TTS/tts/datasets/preprocess.py index 271b1734..62cb9fef 100644 --- a/TTS/tts/datasets/preprocess.py +++ b/TTS/tts/datasets/preprocess.py @@ -434,7 +434,7 @@ def kokoro(root_path, meta_file): with open(txt_file, "r") as ttf: for line in ttf: cols = line.split("|") - wav_file = os.path.join(root_path, "wavs", cols[0] + '.wav') + wav_file = os.path.join(root_path, "wavs", cols[0] + ".wav") text = cols[2].replace(" ", "") items.append([text, wav_file, speaker_name]) return items diff --git a/TTS/tts/utils/text/japanese/phonemizer.py b/TTS/tts/utils/text/japanese/phonemizer.py index f09d5b05..a4629a30 100644 --- a/TTS/tts/utils/text/japanese/phonemizer.py +++ b/TTS/tts/utils/text/japanese/phonemizer.py @@ -2,324 +2,321 @@ # compatible with Julius https://github.com/julius-speech/segmentation-kit import re + import MeCab _CONVRULES = [ # Conversion of 2 letters - 'アァ/ a a', - 'イィ/ i i', - 'イェ/ i e', - 'イャ/ y a', - 'ウゥ/ u:', - 'エェ/ e e', - 'オォ/ o:', - 'カァ/ k a:', - 'キィ/ k i:', - 'クゥ/ k u:', - 'クャ/ ky a', - 'クュ/ ky u', - 'クョ/ ky o', - 'ケェ/ k e:', - 'コォ/ k o:', - 'ガァ/ g a:', - 'ギィ/ g i:', - 'グゥ/ g u:', - 'グャ/ gy a', - 'グュ/ gy u', - 'グョ/ gy o', - 'ゲェ/ g e:', - 'ゴォ/ g o:', - 'サァ/ s a:', - 'シィ/ sh i:', - 'スゥ/ s u:', - 'スャ/ sh a', - 'スュ/ sh u', - 'スョ/ sh o', - 'セェ/ s e:', - 'ソォ/ s o:', - 'ザァ/ z a:', - 'ジィ/ j i:', - 'ズゥ/ z u:', - 'ズャ/ zy a', - 'ズュ/ zy u', - 'ズョ/ zy o', - 'ゼェ/ z e:', - 'ゾォ/ z o:', - 'タァ/ t a:', - 'チィ/ ch i:', - 'ツァ/ ts a', - 'ツィ/ ts i', - 'ツゥ/ ts u:', - 'ツャ/ ch a', - 'ツュ/ ch u', - 'ツョ/ ch o', - 'ツェ/ ts e', - 'ツォ/ ts o', - 'テェ/ t e:', - 'トォ/ t o:', - 'ダァ/ d a:', - 'ヂィ/ j i:', - 'ヅゥ/ d u:', - 'ヅャ/ zy a', - 'ヅュ/ zy u', - 'ヅョ/ zy o', - 'デェ/ d e:', - 'ドォ/ d o:', - 'ナァ/ n a:', - 'ニィ/ n i:', - 'ヌゥ/ n u:', - 'ヌャ/ ny a', - 'ヌュ/ ny u', - 'ヌョ/ ny o', - 'ネェ/ n e:', - 'ノォ/ n o:', - 'ハァ/ h a:', - 'ヒィ/ h i:', - 'フゥ/ f u:', - 'フャ/ hy a', - 'フュ/ hy u', - 'フョ/ hy o', - 'ヘェ/ h e:', - 'ホォ/ h o:', - 'バァ/ b a:', - 'ビィ/ b i:', - 'ブゥ/ b u:', - 'フャ/ hy a', - 'ブュ/ by u', - 'フョ/ hy o', - 'ベェ/ b e:', - 'ボォ/ b o:', - 'パァ/ p a:', - 'ピィ/ p i:', - 'プゥ/ p u:', - 'プャ/ py a', - 'プュ/ py u', - 'プョ/ py o', - 'ペェ/ p e:', - 'ポォ/ p o:', - 'マァ/ m a:', - 'ミィ/ m i:', - 'ムゥ/ m u:', - 'ムャ/ my a', - 'ムュ/ my u', - 'ムョ/ my o', - 'メェ/ m e:', - 'モォ/ m o:', - 'ヤァ/ y a:', - 'ユゥ/ y u:', - 'ユャ/ y a:', - 'ユュ/ y u:', - 'ユョ/ y o:', - 'ヨォ/ y o:', - 'ラァ/ r a:', - 'リィ/ r i:', - 'ルゥ/ r u:', - 'ルャ/ ry a', - 'ルュ/ ry u', - 'ルョ/ ry o', - 'レェ/ r e:', - 'ロォ/ r o:', - 'ワァ/ w a:', - 'ヲォ/ o:', - 'ディ/ d i', - 'デェ/ d e:', - 'デャ/ dy a', - 'デュ/ dy u', - 'デョ/ dy o', - 'ティ/ t i', - 'テェ/ t e:', - 'テャ/ ty a', - 'テュ/ ty u', - 'テョ/ ty o', - 'スィ/ s i', - 'ズァ/ z u a', - 'ズィ/ z i', - 'ズゥ/ z u', - 'ズャ/ zy a', - 'ズュ/ zy u', - 'ズョ/ zy o', - 'ズェ/ z e', - 'ズォ/ z o', - 'キャ/ ky a', - 'キュ/ ky u', - 'キョ/ ky o', - 'シャ/ sh a', - 'シュ/ sh u', - 'シェ/ sh e', - 'ショ/ sh o', - 'チャ/ ch a', - 'チュ/ ch u', - 'チェ/ ch e', - 'チョ/ ch o', - 'トゥ/ t u', - 'トャ/ ty a', - 'トュ/ ty u', - 'トョ/ ty o', - 'ドァ/ d o a', - 'ドゥ/ d u', - 'ドャ/ dy a', - 'ドュ/ dy u', - 'ドョ/ dy o', - 'ドォ/ d o:', - 'ニャ/ ny a', - 'ニュ/ ny u', - 'ニョ/ ny o', - 'ヒャ/ hy a', - 'ヒュ/ hy u', - 'ヒョ/ hy o', - 'ミャ/ my a', - 'ミュ/ my u', - 'ミョ/ my o', - 'リャ/ ry a', - 'リュ/ ry u', - 'リョ/ ry o', - 'ギャ/ gy a', - 'ギュ/ gy u', - 'ギョ/ gy o', - 'ヂェ/ j e', - 'ヂャ/ j a', - 'ヂュ/ j u', - 'ヂョ/ j o', - 'ジェ/ j e', - 'ジャ/ j a', - 'ジュ/ j u', - 'ジョ/ j o', - 'ビャ/ by a', - 'ビュ/ by u', - 'ビョ/ by o', - 'ピャ/ py a', - 'ピュ/ py u', - 'ピョ/ py o', - 'ウァ/ u a', - 'ウィ/ w i', - 'ウェ/ w e', - 'ウォ/ w o', - 'ファ/ f a', - 'フィ/ f i', - 'フゥ/ f u', - 'フャ/ hy a', - 'フュ/ hy u', - 'フョ/ hy o', - 'フェ/ f e', - 'フォ/ f o', - 'ヴァ/ b a', - 'ヴィ/ b i', - 'ヴェ/ b e', - 'ヴォ/ b o', - 'ヴュ/ by u', - + "アァ/ a a", + "イィ/ i i", + "イェ/ i e", + "イャ/ y a", + "ウゥ/ u:", + "エェ/ e e", + "オォ/ o:", + "カァ/ k a:", + "キィ/ k i:", + "クゥ/ k u:", + "クャ/ ky a", + "クュ/ ky u", + "クョ/ ky o", + "ケェ/ k e:", + "コォ/ k o:", + "ガァ/ g a:", + "ギィ/ g i:", + "グゥ/ g u:", + "グャ/ gy a", + "グュ/ gy u", + "グョ/ gy o", + "ゲェ/ g e:", + "ゴォ/ g o:", + "サァ/ s a:", + "シィ/ sh i:", + "スゥ/ s u:", + "スャ/ sh a", + "スュ/ sh u", + "スョ/ sh o", + "セェ/ s e:", + "ソォ/ s o:", + "ザァ/ z a:", + "ジィ/ j i:", + "ズゥ/ z u:", + "ズャ/ zy a", + "ズュ/ zy u", + "ズョ/ zy o", + "ゼェ/ z e:", + "ゾォ/ z o:", + "タァ/ t a:", + "チィ/ ch i:", + "ツァ/ ts a", + "ツィ/ ts i", + "ツゥ/ ts u:", + "ツャ/ ch a", + "ツュ/ ch u", + "ツョ/ ch o", + "ツェ/ ts e", + "ツォ/ ts o", + "テェ/ t e:", + "トォ/ t o:", + "ダァ/ d a:", + "ヂィ/ j i:", + "ヅゥ/ d u:", + "ヅャ/ zy a", + "ヅュ/ zy u", + "ヅョ/ zy o", + "デェ/ d e:", + "ドォ/ d o:", + "ナァ/ n a:", + "ニィ/ n i:", + "ヌゥ/ n u:", + "ヌャ/ ny a", + "ヌュ/ ny u", + "ヌョ/ ny o", + "ネェ/ n e:", + "ノォ/ n o:", + "ハァ/ h a:", + "ヒィ/ h i:", + "フゥ/ f u:", + "フャ/ hy a", + "フュ/ hy u", + "フョ/ hy o", + "ヘェ/ h e:", + "ホォ/ h o:", + "バァ/ b a:", + "ビィ/ b i:", + "ブゥ/ b u:", + "フャ/ hy a", + "ブュ/ by u", + "フョ/ hy o", + "ベェ/ b e:", + "ボォ/ b o:", + "パァ/ p a:", + "ピィ/ p i:", + "プゥ/ p u:", + "プャ/ py a", + "プュ/ py u", + "プョ/ py o", + "ペェ/ p e:", + "ポォ/ p o:", + "マァ/ m a:", + "ミィ/ m i:", + "ムゥ/ m u:", + "ムャ/ my a", + "ムュ/ my u", + "ムョ/ my o", + "メェ/ m e:", + "モォ/ m o:", + "ヤァ/ y a:", + "ユゥ/ y u:", + "ユャ/ y a:", + "ユュ/ y u:", + "ユョ/ y o:", + "ヨォ/ y o:", + "ラァ/ r a:", + "リィ/ r i:", + "ルゥ/ r u:", + "ルャ/ ry a", + "ルュ/ ry u", + "ルョ/ ry o", + "レェ/ r e:", + "ロォ/ r o:", + "ワァ/ w a:", + "ヲォ/ o:", + "ディ/ d i", + "デェ/ d e:", + "デャ/ dy a", + "デュ/ dy u", + "デョ/ dy o", + "ティ/ t i", + "テェ/ t e:", + "テャ/ ty a", + "テュ/ ty u", + "テョ/ ty o", + "スィ/ s i", + "ズァ/ z u a", + "ズィ/ z i", + "ズゥ/ z u", + "ズャ/ zy a", + "ズュ/ zy u", + "ズョ/ zy o", + "ズェ/ z e", + "ズォ/ z o", + "キャ/ ky a", + "キュ/ ky u", + "キョ/ ky o", + "シャ/ sh a", + "シュ/ sh u", + "シェ/ sh e", + "ショ/ sh o", + "チャ/ ch a", + "チュ/ ch u", + "チェ/ ch e", + "チョ/ ch o", + "トゥ/ t u", + "トャ/ ty a", + "トュ/ ty u", + "トョ/ ty o", + "ドァ/ d o a", + "ドゥ/ d u", + "ドャ/ dy a", + "ドュ/ dy u", + "ドョ/ dy o", + "ドォ/ d o:", + "ニャ/ ny a", + "ニュ/ ny u", + "ニョ/ ny o", + "ヒャ/ hy a", + "ヒュ/ hy u", + "ヒョ/ hy o", + "ミャ/ my a", + "ミュ/ my u", + "ミョ/ my o", + "リャ/ ry a", + "リュ/ ry u", + "リョ/ ry o", + "ギャ/ gy a", + "ギュ/ gy u", + "ギョ/ gy o", + "ヂェ/ j e", + "ヂャ/ j a", + "ヂュ/ j u", + "ヂョ/ j o", + "ジェ/ j e", + "ジャ/ j a", + "ジュ/ j u", + "ジョ/ j o", + "ビャ/ by a", + "ビュ/ by u", + "ビョ/ by o", + "ピャ/ py a", + "ピュ/ py u", + "ピョ/ py o", + "ウァ/ u a", + "ウィ/ w i", + "ウェ/ w e", + "ウォ/ w o", + "ファ/ f a", + "フィ/ f i", + "フゥ/ f u", + "フャ/ hy a", + "フュ/ hy u", + "フョ/ hy o", + "フェ/ f e", + "フォ/ f o", + "ヴァ/ b a", + "ヴィ/ b i", + "ヴェ/ b e", + "ヴォ/ b o", + "ヴュ/ by u", # Conversion of 1 letter - 'ア/ a', - 'イ/ i', - 'ウ/ u', - 'エ/ e', - 'オ/ o', - 'カ/ k a', - 'キ/ k i', - 'ク/ k u', - 'ケ/ k e', - 'コ/ k o', - 'サ/ s a', - 'シ/ sh i', - 'ス/ s u', - 'セ/ s e', - 'ソ/ s o', - 'タ/ t a', - 'チ/ ch i', - 'ツ/ ts u', - 'テ/ t e', - 'ト/ t o', - 'ナ/ n a', - 'ニ/ n i', - 'ヌ/ n u', - 'ネ/ n e', - 'ノ/ n o', - 'ハ/ h a', - 'ヒ/ h i', - 'フ/ f u', - 'ヘ/ h e', - 'ホ/ h o', - 'マ/ m a', - 'ミ/ m i', - 'ム/ m u', - 'メ/ m e', - 'モ/ m o', - 'ラ/ r a', - 'リ/ r i', - 'ル/ r u', - 'レ/ r e', - 'ロ/ r o', - 'ガ/ g a', - 'ギ/ g i', - 'グ/ g u', - 'ゲ/ g e', - 'ゴ/ g o', - 'ザ/ z a', - 'ジ/ j i', - 'ズ/ z u', - 'ゼ/ z e', - 'ゾ/ z o', - 'ダ/ d a', - 'ヂ/ j i', - 'ヅ/ z u', - 'デ/ d e', - 'ド/ d o', - 'バ/ b a', - 'ビ/ b i', - 'ブ/ b u', - 'ベ/ b e', - 'ボ/ b o', - 'パ/ p a', - 'ピ/ p i', - 'プ/ p u', - 'ペ/ p e', - 'ポ/ p o', - 'ヤ/ y a', - 'ユ/ y u', - 'ヨ/ y o', - 'ワ/ w a', - 'ヰ/ i', - 'ヱ/ e', - 'ヲ/ o', - 'ン/ N', - 'ッ/ q', - 'ヴ/ b u', - 'ー/:', - + "ア/ a", + "イ/ i", + "ウ/ u", + "エ/ e", + "オ/ o", + "カ/ k a", + "キ/ k i", + "ク/ k u", + "ケ/ k e", + "コ/ k o", + "サ/ s a", + "シ/ sh i", + "ス/ s u", + "セ/ s e", + "ソ/ s o", + "タ/ t a", + "チ/ ch i", + "ツ/ ts u", + "テ/ t e", + "ト/ t o", + "ナ/ n a", + "ニ/ n i", + "ヌ/ n u", + "ネ/ n e", + "ノ/ n o", + "ハ/ h a", + "ヒ/ h i", + "フ/ f u", + "ヘ/ h e", + "ホ/ h o", + "マ/ m a", + "ミ/ m i", + "ム/ m u", + "メ/ m e", + "モ/ m o", + "ラ/ r a", + "リ/ r i", + "ル/ r u", + "レ/ r e", + "ロ/ r o", + "ガ/ g a", + "ギ/ g i", + "グ/ g u", + "ゲ/ g e", + "ゴ/ g o", + "ザ/ z a", + "ジ/ j i", + "ズ/ z u", + "ゼ/ z e", + "ゾ/ z o", + "ダ/ d a", + "ヂ/ j i", + "ヅ/ z u", + "デ/ d e", + "ド/ d o", + "バ/ b a", + "ビ/ b i", + "ブ/ b u", + "ベ/ b e", + "ボ/ b o", + "パ/ p a", + "ピ/ p i", + "プ/ p u", + "ペ/ p e", + "ポ/ p o", + "ヤ/ y a", + "ユ/ y u", + "ヨ/ y o", + "ワ/ w a", + "ヰ/ i", + "ヱ/ e", + "ヲ/ o", + "ン/ N", + "ッ/ q", + "ヴ/ b u", + "ー/:", # Try converting broken text - 'ァ/ a', - 'ィ/ i', - 'ゥ/ u', - 'ェ/ e', - 'ォ/ o', - 'ヮ/ w a', - 'ォ/ o', - + "ァ/ a", + "ィ/ i", + "ゥ/ u", + "ェ/ e", + "ォ/ o", + "ヮ/ w a", + "ォ/ o", # Symbols - '、/ ,', - '。/ .', - '!/ !', - '?/ ?', - '・/ ,' + "、/ ,", + "。/ .", + "!/ !", + "?/ ?", + "・/ ,", ] -_COLON_RX = re.compile(':+') -_REJECT_RX = re.compile('[^ a-zA-Z:,.?]') +_COLON_RX = re.compile(":+") +_REJECT_RX = re.compile("[^ a-zA-Z:,.?]") + def _makerulemap(): - l = [tuple(x.split('/')) for x in _CONVRULES] - return tuple( - {k: v for k, v in l if len(k) == i} - for i in (1, 2) - ) + l = [tuple(x.split("/")) for x in _CONVRULES] + return tuple({k: v for k, v in l if len(k) == i} for i in (1, 2)) + _RULEMAP1, _RULEMAP2 = _makerulemap() + def kata2phoneme(text: str) -> str: - """Convert katakana text to phonemes. - """ + """Convert katakana text to phonemes.""" text = text.strip() - res = '' + res = "" while text: if len(text) >= 2: x = _RULEMAP2.get(text[:2]) @@ -332,30 +329,34 @@ def kata2phoneme(text: str) -> str: text = text[1:] res += x continue - res += ' ' + text[0] + res += " " + text[0] text = text[1:] - res = _COLON_RX.sub(':', res) + res = _COLON_RX.sub(":", res) return res[1:] -_KATAKANA = ''.join(chr(ch) for ch in range(ord('ァ'), ord('ン') + 1)) -_HIRAGANA = ''.join(chr(ch) for ch in range(ord('ぁ'), ord('ん') + 1)) + +_KATAKANA = "".join(chr(ch) for ch in range(ord("ァ"), ord("ン") + 1)) +_HIRAGANA = "".join(chr(ch) for ch in range(ord("ぁ"), ord("ん") + 1)) _HIRA2KATATRANS = str.maketrans(_HIRAGANA, _KATAKANA) + def hira2kata(text: str) -> str: text = text.translate(_HIRA2KATATRANS) - return text.replace('う゛', 'ヴ') + return text.replace("う゛", "ヴ") -_SYMBOL_TOKENS = set(list('・、。?!')) -_NO_YOMI_TOKENS = set(list('「」『』―()[][] …')) + +_SYMBOL_TOKENS = set(list("・、。?!")) +_NO_YOMI_TOKENS = set(list("「」『』―()[][] …")) _TAGGER = MeCab.Tagger() + def text2kata(text: str) -> str: parsed = _TAGGER.parse(text) res = [] - for line in parsed.split('\n'): - if line == 'EOS': + for line in parsed.split("\n"): + if line == "EOS": break - parts = line.split('\t') + parts = line.split("\t") word, yomi = parts[0], parts[1] if yomi: @@ -363,17 +364,17 @@ def text2kata(text: str) -> str: else: if word in _SYMBOL_TOKENS: res.append(word) - elif word in ('っ', 'ッ'): - res.append('ッ') + elif word in ("っ", "ッ"): + res.append("ッ") elif word in _NO_YOMI_TOKENS: pass else: res.append(word) - return hira2kata(''.join(res)) + return hira2kata("".join(res)) + def japanese_text_to_phonemes(text: str) -> str: - """Convert Japanese text to phonemes. - """ + """Convert Japanese text to phonemes.""" res = text2kata(text) res = kata2phoneme(res) - return res.replace(' ', '') + return res.replace(" ", "") diff --git a/tests/text_tests/test_japanese_phonemizer.py b/tests/text_tests/test_japanese_phonemizer.py index 437042f0..b3b1ece3 100644 --- a/tests/text_tests/test_japanese_phonemizer.py +++ b/tests/text_tests/test_japanese_phonemizer.py @@ -1,7 +1,8 @@ import unittest + from TTS.tts.utils.text.japanese.phonemizer import japanese_text_to_phonemes -_TEST_CASES = ''' +_TEST_CASES = """ どちらに行きますか?/dochiraniikimasuka? 今日は温泉に、行きます。/kyo:waoNseNni,ikimasu. 「A」から「Z」までです。/AkaraZmadedesu. @@ -9,14 +10,15 @@ _TEST_CASES = ''' クジラは哺乳類です。/kujirawahonyu:ruidesu. ヴィディオを見ます。/bidioomimasu. ky o: w a o N s e N n i , i k i m a s u ./kyo:waoNseNni,ikimasu. -''' +""" + class TestText(unittest.TestCase): - def test_japanese_text_to_phonemes(self): - for line in _TEST_CASES.strip().split('\n'): - text, phone = line.split('/') + for line in _TEST_CASES.strip().split("\n"): + text, phone = line.split("/") self.assertEqual(japanese_text_to_phonemes(text), phone) -if __name__ == '__main__': + +if __name__ == "__main__": unittest.main()