maket style japanese PR

This commit is contained in:
Eren Gölge 2021-06-02 11:42:38 +02:00
parent 0c14278c30
commit 49c5e5d820
3 changed files with 328 additions and 325 deletions

View File

@ -434,7 +434,7 @@ def kokoro(root_path, meta_file):
with open(txt_file, "r") as ttf: with open(txt_file, "r") as ttf:
for line in ttf: for line in ttf:
cols = line.split("|") 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(" ", "") text = cols[2].replace(" ", "")
items.append([text, wav_file, speaker_name]) items.append([text, wav_file, speaker_name])
return items return items

View File

@ -2,324 +2,321 @@
# compatible with Julius https://github.com/julius-speech/segmentation-kit # compatible with Julius https://github.com/julius-speech/segmentation-kit
import re import re
import MeCab import MeCab
_CONVRULES = [ _CONVRULES = [
# Conversion of 2 letters # Conversion of 2 letters
'アァ/ a a', "アァ/ a a",
'イィ/ i i', "イィ/ i i",
'イェ/ i e', "イェ/ i e",
'イャ/ y a', "イャ/ y a",
'ウゥ/ u:', "ウゥ/ u:",
'エェ/ e e', "エェ/ e e",
'オォ/ o:', "オォ/ o:",
'カァ/ k a:', "カァ/ k a:",
'キィ/ k i:', "キィ/ k i:",
'クゥ/ k u:', "クゥ/ k u:",
'クャ/ ky a', "クャ/ ky a",
'クュ/ ky u', "クュ/ ky u",
'クョ/ ky o', "クョ/ ky o",
'ケェ/ k e:', "ケェ/ k e:",
'コォ/ k o:', "コォ/ k o:",
'ガァ/ g a:', "ガァ/ g a:",
'ギィ/ g i:', "ギィ/ g i:",
'グゥ/ g u:', "グゥ/ g u:",
'グャ/ gy a', "グャ/ gy a",
'グュ/ gy u', "グュ/ gy u",
'グョ/ gy o', "グョ/ gy o",
'ゲェ/ g e:', "ゲェ/ g e:",
'ゴォ/ g o:', "ゴォ/ g o:",
'サァ/ s a:', "サァ/ s a:",
'シィ/ sh i:', "シィ/ sh i:",
'スゥ/ s u:', "スゥ/ s u:",
'スャ/ sh a', "スャ/ sh a",
'スュ/ sh u', "スュ/ sh u",
'スョ/ sh o', "スョ/ sh o",
'セェ/ s e:', "セェ/ s e:",
'ソォ/ s o:', "ソォ/ s o:",
'ザァ/ z a:', "ザァ/ z a:",
'ジィ/ j i:', "ジィ/ j i:",
'ズゥ/ z u:', "ズゥ/ z u:",
'ズャ/ zy a', "ズャ/ zy a",
'ズュ/ zy u', "ズュ/ zy u",
'ズョ/ zy o', "ズョ/ zy o",
'ゼェ/ z e:', "ゼェ/ z e:",
'ゾォ/ z o:', "ゾォ/ z o:",
'タァ/ t a:', "タァ/ t a:",
'チィ/ ch i:', "チィ/ ch i:",
'ツァ/ ts a', "ツァ/ ts a",
'ツィ/ ts i', "ツィ/ ts i",
'ツゥ/ ts u:', "ツゥ/ ts u:",
'ツャ/ ch a', "ツャ/ ch a",
'ツュ/ ch u', "ツュ/ ch u",
'ツョ/ ch o', "ツョ/ ch o",
'ツェ/ ts e', "ツェ/ ts e",
'ツォ/ ts o', "ツォ/ ts o",
'テェ/ t e:', "テェ/ t e:",
'トォ/ t o:', "トォ/ t o:",
'ダァ/ d a:', "ダァ/ d a:",
'ヂィ/ j i:', "ヂィ/ j i:",
'ヅゥ/ d u:', "ヅゥ/ d u:",
'ヅャ/ zy a', "ヅャ/ zy a",
'ヅュ/ zy u', "ヅュ/ zy u",
'ヅョ/ zy o', "ヅョ/ zy o",
'デェ/ d e:', "デェ/ d e:",
'ドォ/ d o:', "ドォ/ d o:",
'ナァ/ n a:', "ナァ/ n a:",
'ニィ/ n i:', "ニィ/ n i:",
'ヌゥ/ n u:', "ヌゥ/ n u:",
'ヌャ/ ny a', "ヌャ/ ny a",
'ヌュ/ ny u', "ヌュ/ ny u",
'ヌョ/ ny o', "ヌョ/ ny o",
'ネェ/ n e:', "ネェ/ n e:",
'ノォ/ n o:', "ノォ/ n o:",
'ハァ/ h a:', "ハァ/ h a:",
'ヒィ/ h i:', "ヒィ/ h i:",
'フゥ/ f u:', "フゥ/ f u:",
'フャ/ hy a', "フャ/ hy a",
'フュ/ hy u', "フュ/ hy u",
'フョ/ hy o', "フョ/ hy o",
'ヘェ/ h e:', "ヘェ/ h e:",
'ホォ/ h o:', "ホォ/ h o:",
'バァ/ b a:', "バァ/ b a:",
'ビィ/ b i:', "ビィ/ b i:",
'ブゥ/ b u:', "ブゥ/ b u:",
'フャ/ hy a', "フャ/ hy a",
'ブュ/ by u', "ブュ/ by u",
'フョ/ hy o', "フョ/ hy o",
'ベェ/ b e:', "ベェ/ b e:",
'ボォ/ b o:', "ボォ/ b o:",
'パァ/ p a:', "パァ/ p a:",
'ピィ/ p i:', "ピィ/ p i:",
'プゥ/ p u:', "プゥ/ p u:",
'プャ/ py a', "プャ/ py a",
'プュ/ py u', "プュ/ py u",
'プョ/ py o', "プョ/ py o",
'ペェ/ p e:', "ペェ/ p e:",
'ポォ/ p o:', "ポォ/ p o:",
'マァ/ m a:', "マァ/ m a:",
'ミィ/ m i:', "ミィ/ m i:",
'ムゥ/ m u:', "ムゥ/ m u:",
'ムャ/ my a', "ムャ/ my a",
'ムュ/ my u', "ムュ/ my u",
'ムョ/ my o', "ムョ/ my o",
'メェ/ m e:', "メェ/ m e:",
'モォ/ m o:', "モォ/ m o:",
'ヤァ/ y a:', "ヤァ/ y a:",
'ユゥ/ y u:', "ユゥ/ y u:",
'ユャ/ y a:', "ユャ/ y a:",
'ユュ/ y u:', "ユュ/ y u:",
'ユョ/ y o:', "ユョ/ y o:",
'ヨォ/ y o:', "ヨォ/ y o:",
'ラァ/ r a:', "ラァ/ r a:",
'リィ/ r i:', "リィ/ r i:",
'ルゥ/ r u:', "ルゥ/ r u:",
'ルャ/ ry a', "ルャ/ ry a",
'ルュ/ ry u', "ルュ/ ry u",
'ルョ/ ry o', "ルョ/ ry o",
'レェ/ r e:', "レェ/ r e:",
'ロォ/ r o:', "ロォ/ r o:",
'ワァ/ w a:', "ワァ/ w a:",
'ヲォ/ o:', "ヲォ/ o:",
'ディ/ d i', "ディ/ d i",
'デェ/ d e:', "デェ/ d e:",
'デャ/ dy a', "デャ/ dy a",
'デュ/ dy u', "デュ/ dy u",
'デョ/ dy o', "デョ/ dy o",
'ティ/ t i', "ティ/ t i",
'テェ/ t e:', "テェ/ t e:",
'テャ/ ty a', "テャ/ ty a",
'テュ/ ty u', "テュ/ ty u",
'テョ/ ty o', "テョ/ ty o",
'スィ/ s i', "スィ/ s i",
'ズァ/ z u a', "ズァ/ z u a",
'ズィ/ z i', "ズィ/ z i",
'ズゥ/ z u', "ズゥ/ z u",
'ズャ/ zy a', "ズャ/ zy a",
'ズュ/ zy u', "ズュ/ zy u",
'ズョ/ zy o', "ズョ/ zy o",
'ズェ/ z e', "ズェ/ z e",
'ズォ/ z o', "ズォ/ z o",
'キャ/ ky a', "キャ/ ky a",
'キュ/ ky u', "キュ/ ky u",
'キョ/ ky o', "キョ/ ky o",
'シャ/ sh a', "シャ/ sh a",
'シュ/ sh u', "シュ/ sh u",
'シェ/ sh e', "シェ/ sh e",
'ショ/ sh o', "ショ/ sh o",
'チャ/ ch a', "チャ/ ch a",
'チュ/ ch u', "チュ/ ch u",
'チェ/ ch e', "チェ/ ch e",
'チョ/ ch o', "チョ/ ch o",
'トゥ/ t u', "トゥ/ t u",
'トャ/ ty a', "トャ/ ty a",
'トュ/ ty u', "トュ/ ty u",
'トョ/ ty o', "トョ/ ty o",
'ドァ/ d o a', "ドァ/ d o a",
'ドゥ/ d u', "ドゥ/ d u",
'ドャ/ dy a', "ドャ/ dy a",
'ドュ/ dy u', "ドュ/ dy u",
'ドョ/ dy o', "ドョ/ dy o",
'ドォ/ d o:', "ドォ/ d o:",
'ニャ/ ny a', "ニャ/ ny a",
'ニュ/ ny u', "ニュ/ ny u",
'ニョ/ ny o', "ニョ/ ny o",
'ヒャ/ hy a', "ヒャ/ hy a",
'ヒュ/ hy u', "ヒュ/ hy u",
'ヒョ/ hy o', "ヒョ/ hy o",
'ミャ/ my a', "ミャ/ my a",
'ミュ/ my u', "ミュ/ my u",
'ミョ/ my o', "ミョ/ my o",
'リャ/ ry a', "リャ/ ry a",
'リュ/ ry u', "リュ/ ry u",
'リョ/ ry o', "リョ/ ry o",
'ギャ/ gy a', "ギャ/ gy a",
'ギュ/ gy u', "ギュ/ gy u",
'ギョ/ gy o', "ギョ/ gy o",
'ヂェ/ j e', "ヂェ/ j e",
'ヂャ/ j a', "ヂャ/ j a",
'ヂュ/ j u', "ヂュ/ j u",
'ヂョ/ j o', "ヂョ/ j o",
'ジェ/ j e', "ジェ/ j e",
'ジャ/ j a', "ジャ/ j a",
'ジュ/ j u', "ジュ/ j u",
'ジョ/ j o', "ジョ/ j o",
'ビャ/ by a', "ビャ/ by a",
'ビュ/ by u', "ビュ/ by u",
'ビョ/ by o', "ビョ/ by o",
'ピャ/ py a', "ピャ/ py a",
'ピュ/ py u', "ピュ/ py u",
'ピョ/ py o', "ピョ/ py o",
'ウァ/ u a', "ウァ/ u a",
'ウィ/ w i', "ウィ/ w i",
'ウェ/ w e', "ウェ/ w e",
'ウォ/ w o', "ウォ/ w o",
'ファ/ f a', "ファ/ f a",
'フィ/ f i', "フィ/ f i",
'フゥ/ f u', "フゥ/ f u",
'フャ/ hy a', "フャ/ hy a",
'フュ/ hy u', "フュ/ hy u",
'フョ/ hy o', "フョ/ hy o",
'フェ/ f e', "フェ/ f e",
'フォ/ f o', "フォ/ f o",
'ヴァ/ b a', "ヴァ/ b a",
'ヴィ/ b i', "ヴィ/ b i",
'ヴェ/ b e', "ヴェ/ b e",
'ヴォ/ b o', "ヴォ/ b o",
'ヴュ/ by u', "ヴュ/ by u",
# Conversion of 1 letter # Conversion of 1 letter
'ア/ a', "ア/ a",
'イ/ i', "イ/ i",
'ウ/ u', "ウ/ u",
'エ/ e', "エ/ e",
'オ/ o', "オ/ o",
'カ/ k a', "カ/ k a",
'キ/ k i', "キ/ k i",
'ク/ k u', "ク/ k u",
'ケ/ k e', "ケ/ k e",
'コ/ k o', "コ/ k o",
'サ/ s a', "サ/ s a",
'シ/ sh i', "シ/ sh i",
'ス/ s u', "ス/ s u",
'セ/ s e', "セ/ s e",
'ソ/ s o', "ソ/ s o",
'タ/ t a', "タ/ t a",
'チ/ ch i', "チ/ ch i",
'ツ/ ts u', "ツ/ ts u",
'テ/ t e', "テ/ t e",
'ト/ t o', "ト/ t o",
'ナ/ n a', "ナ/ n a",
'ニ/ n i', "ニ/ n i",
'ヌ/ n u', "ヌ/ n u",
'ネ/ n e', "ネ/ n e",
'/ n o', "/ n o",
'ハ/ h a', "ハ/ h a",
'ヒ/ h i', "ヒ/ h i",
'フ/ f u', "フ/ f u",
'ヘ/ h e', "ヘ/ h e",
'ホ/ h o', "ホ/ h o",
'マ/ m a', "マ/ m a",
'ミ/ m i', "ミ/ m i",
'ム/ m u', "ム/ m u",
'メ/ m e', "メ/ m e",
'モ/ m o', "モ/ m o",
'ラ/ r a', "ラ/ r a",
'リ/ r i', "リ/ r i",
'ル/ r u', "ル/ r u",
'レ/ r e', "レ/ r e",
'ロ/ r o', "ロ/ r o",
'ガ/ g a', "ガ/ g a",
'ギ/ g i', "ギ/ g i",
'グ/ g u', "グ/ g u",
'ゲ/ g e', "ゲ/ g e",
'ゴ/ g o', "ゴ/ g o",
'ザ/ z a', "ザ/ z a",
'ジ/ j i', "ジ/ j i",
'ズ/ z u', "ズ/ z u",
'ゼ/ z e', "ゼ/ z e",
'ゾ/ z o', "ゾ/ z o",
'ダ/ d a', "ダ/ d a",
'ヂ/ j i', "ヂ/ j i",
'ヅ/ z u', "ヅ/ z u",
'デ/ d e', "デ/ d e",
'ド/ d o', "ド/ d o",
'バ/ b a', "バ/ b a",
'ビ/ b i', "ビ/ b i",
'ブ/ b u', "ブ/ b u",
'ベ/ b e', "ベ/ b e",
'ボ/ b o', "ボ/ b o",
'パ/ p a', "パ/ p a",
'ピ/ p i', "ピ/ p i",
'プ/ p u', "プ/ p u",
'ペ/ p e', "ペ/ p e",
'ポ/ p o', "ポ/ p o",
'ヤ/ y a', "ヤ/ y a",
'ユ/ y u', "ユ/ y u",
'ヨ/ y o', "ヨ/ y o",
'ワ/ w a', "ワ/ w a",
'ヰ/ i', "ヰ/ i",
'ヱ/ e', "ヱ/ e",
'ヲ/ o', "ヲ/ o",
'ン/ N', "ン/ N",
'ッ/ q', "ッ/ q",
'ヴ/ b u', "ヴ/ b u",
'ー/:', "ー/:",
# Try converting broken text # Try converting broken text
'ァ/ a', "ァ/ a",
'ィ/ i', "ィ/ i",
'ゥ/ u', "ゥ/ u",
'ェ/ e', "ェ/ e",
'ォ/ o', "ォ/ o",
'ヮ/ w a', "ヮ/ w a",
'ォ/ o', "ォ/ o",
# Symbols # Symbols
'、/ ,', "、/ ,",
'。/ .', "。/ .",
'/ !', "/ !",
'/ ?', "/ ?",
'・/ ,' "・/ ,",
] ]
_COLON_RX = re.compile(':+') _COLON_RX = re.compile(":+")
_REJECT_RX = re.compile('[^ a-zA-Z:,.?]') _REJECT_RX = re.compile("[^ a-zA-Z:,.?]")
def _makerulemap(): def _makerulemap():
l = [tuple(x.split('/')) for x in _CONVRULES] l = [tuple(x.split("/")) for x in _CONVRULES]
return tuple( return tuple({k: v for k, v in l if len(k) == i} for i in (1, 2))
{k: v for k, v in l if len(k) == i}
for i in (1, 2)
)
_RULEMAP1, _RULEMAP2 = _makerulemap() _RULEMAP1, _RULEMAP2 = _makerulemap()
def kata2phoneme(text: str) -> str: def kata2phoneme(text: str) -> str:
"""Convert katakana text to phonemes. """Convert katakana text to phonemes."""
"""
text = text.strip() text = text.strip()
res = '' res = ""
while text: while text:
if len(text) >= 2: if len(text) >= 2:
x = _RULEMAP2.get(text[:2]) x = _RULEMAP2.get(text[:2])
@ -332,30 +329,34 @@ def kata2phoneme(text: str) -> str:
text = text[1:] text = text[1:]
res += x res += x
continue continue
res += ' ' + text[0] res += " " + text[0]
text = text[1:] text = text[1:]
res = _COLON_RX.sub(':', res) res = _COLON_RX.sub(":", res)
return res[1:] 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) _HIRA2KATATRANS = str.maketrans(_HIRAGANA, _KATAKANA)
def hira2kata(text: str) -> str: def hira2kata(text: str) -> str:
text = text.translate(_HIRA2KATATRANS) 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() _TAGGER = MeCab.Tagger()
def text2kata(text: str) -> str: def text2kata(text: str) -> str:
parsed = _TAGGER.parse(text) parsed = _TAGGER.parse(text)
res = [] res = []
for line in parsed.split('\n'): for line in parsed.split("\n"):
if line == 'EOS': if line == "EOS":
break break
parts = line.split('\t') parts = line.split("\t")
word, yomi = parts[0], parts[1] word, yomi = parts[0], parts[1]
if yomi: if yomi:
@ -363,17 +364,17 @@ def text2kata(text: str) -> str:
else: else:
if word in _SYMBOL_TOKENS: if word in _SYMBOL_TOKENS:
res.append(word) res.append(word)
elif word in ('', ''): elif word in ("", ""):
res.append('') res.append("")
elif word in _NO_YOMI_TOKENS: elif word in _NO_YOMI_TOKENS:
pass pass
else: else:
res.append(word) res.append(word)
return hira2kata(''.join(res)) return hira2kata("".join(res))
def japanese_text_to_phonemes(text: str) -> str: def japanese_text_to_phonemes(text: str) -> str:
"""Convert Japanese text to phonemes. """Convert Japanese text to phonemes."""
"""
res = text2kata(text) res = text2kata(text)
res = kata2phoneme(res) res = kata2phoneme(res)
return res.replace(' ', '') return res.replace(" ", "")

View File

@ -1,7 +1,8 @@
import unittest import unittest
from TTS.tts.utils.text.japanese.phonemizer import japanese_text_to_phonemes from TTS.tts.utils.text.japanese.phonemizer import japanese_text_to_phonemes
_TEST_CASES = ''' _TEST_CASES = """
どちらに行きますか/dochiraniikimasuka? どちらに行きますか/dochiraniikimasuka?
今日は温泉に行きます/kyo:waoNseNni,ikimasu. 今日は温泉に行きます/kyo:waoNseNni,ikimasu.
AからZまでです/AkaraZmadedesu. AからZまでです/AkaraZmadedesu.
@ -9,14 +10,15 @@ _TEST_CASES = '''
クジラは哺乳類です/kujirawahonyu:ruidesu. クジラは哺乳類です/kujirawahonyu:ruidesu.
ヴィディオを見ます/bidioomimasu. ヴィディオを見ます/bidioomimasu.
ky o: w a o N s e N n i , i k i m a s u ./kyo:waoNseNni,ikimasu. 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): class TestText(unittest.TestCase):
def test_japanese_text_to_phonemes(self): def test_japanese_text_to_phonemes(self):
for line in _TEST_CASES.strip().split('\n'): for line in _TEST_CASES.strip().split("\n"):
text, phone = line.split('/') text, phone = line.split("/")
self.assertEqual(japanese_text_to_phonemes(text), phone) self.assertEqual(japanese_text_to_phonemes(text), phone)
if __name__ == '__main__':
if __name__ == "__main__":
unittest.main() unittest.main()