This repository has been archived by the owner on Jan 5, 2024. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathtext.py
220 lines (205 loc) · 6.33 KB
/
text.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
import re
from typing import List
from espnet2.text.phoneme_tokenizer import pyopenjtalk_g2p_prosody
p2kata = {"cl": "ッ", "N": "ン", "_": "、", "#": " "}
kata2p = {v: k for k, v in p2kata.items()}
"""
頑張って作った、カタカナをトークンに分割するための辞書。
後でトークン・アルファベットをカタカナにするのにも使うので、2文字のもの・母音以外のものを先に書く。
"ヂ"は"ジ"、"ヅ"は"ズ"を使うので、載せない。
ヰ(ウィ)やヲ(発音上は「オ」らしい)等も同じく使わないので載せない。
"""
kata2tokens = {
# 置換のため、2文字のものを先に
"イェ": ["y", "e"],
"ウィ": ["w", "i"],
"ウェ": ["w", "e"],
"ウォ": ["w", "o"],
"ヴァ": ["v", "a"],
"ヴィ": ["v", "i"],
"ヴェ": ["v", "e"],
"ヴォ": ["v", "o"],
"キャ": ["ky", "a"],
"キュ": ["ky", "u"],
"キェ": ["ky", "e"],
"キョ": ["ky", "o"],
"ギャ": ["gy", "a"],
"ギュ": ["gy", "u"],
"ギェ": ["gy", "e"],
"ギョ": ["gy", "o"],
"シャ": ["sh", "a"],
"シュ": ["sh", "u"],
"シェ": ["sh", "e"],
"ショ": ["sh", "o"],
"ジャ": ["j", "a"],
"ジュ": ["j", "u"],
"ジェ": ["j", "e"],
"ジョ": ["j", "o"],
"スィ": ["s", "i"],
"チャ": ["ch", "a"],
"チュ": ["ch", "u"],
"チェ": ["ch", "e"],
"チョ": ["ch", "o"],
"ツァ": ["ts", "a"],
"ツィ": ["ts", "i"],
"ツェ": ["ts", "e"],
"ツォ": ["ts", "o"],
"ティ": ["t", "i"],
"トゥ": ["t", "u"],
"テャ": ["ty", "a"],
"テュ": ["ty", "u"],
"テョ": ["ty", "o"],
"ディ": ["d", "i"],
"ドゥ": ["d", "u"],
"デャ": ["dy", "a"],
"デュ": ["dy", "u"],
"デェ": ["dy", "e"],
"デョ": ["dy", "o"],
"ニャ": ["ny", "a"],
"ニュ": ["ny", "u"],
"ニェ": ["ny", "e"],
"ニョ": ["ny", "o"],
"ヒャ": ["hy", "a"],
"ヒュ": ["hy", "u"],
"ヒェ": ["hy", "e"],
"ヒョ": ["hy", "o"],
"ファ": ["f", "a"],
"フィ": ["f", "i"],
"フェ": ["f", "e"],
"フォ": ["f", "o"],
"ミャ": ["my", "a"],
"ミュ": ["my", "u"],
"ミェ": ["my", "e"],
"ミョ": ["my", "o"],
"リャ": ["ry", "a"],
"リュ": ["ry", "u"],
"リェ": ["ry", "e"],
"リョ": ["ry", "o"],
"ビャ": ["by", "a"],
"ビュ": ["by", "u"],
"ビェ": ["by", "e"],
"ビョ": ["by", "o"],
"ピャ": ["py", "a"],
"ピュ": ["py", "u"],
"ピェ": ["py", "e"],
"ピョ": ["py", "o"],
"ズィ": ["z", "i"],
"ヴ": ["v", "u"],
"ガ": ["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"],
"カ": ["k", "a"],
"キ": ["k", "i"],
"ク": ["k", "u"],
"ケ": ["k", "e"],
"コ": ["k", "o"],
"サ": ["s", "a"],
"シ": ["sh", "i"],
"ツ": ["ts", "u"], # "tsu"のほうを"su"より優先させなきゃいけない
"ス": ["s", "u"],
"セ": ["s", "e"],
"ソ": ["s", "o"],
"タ": ["t", "a"],
"チ": ["ch", "i"],
"テ": ["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"],
"ヤ": ["y", "a"],
"ユ": ["y", "u"],
"ヨ": ["y", "o"],
"ワ": ["w", "a"],
"ア": ["a"],
"イ": ["i"],
"ウ": ["u"],
"エ": ["e"],
"オ": ["o"],
"ン": ["N"],
}
kata2a = {k: "".join(v) for k, v in kata2tokens.items()}
# {"ア": " a", "キャ": " ky a", ...}
kata2a_with_spaces = {k: " " + " ".join(v) for k, v in kata2tokens.items()}
a2kata = {v: k for k, v in kata2a.items()}
def g2tokens(text: str) -> List[str]:
return pyopenjtalk_g2p_prosody(text)
def g2p(text: str) -> str:
"""
与えられた文字列を、カタカナとアクセント記号からなる文字列に変換。
記号の扱いは`p2kata`に準ずる:
- `cl`は「`ッ`」
- `N`は`ン`
- `_`は`、`
- `#`は` `(半角スペース)
"""
tokens = g2tokens(text)
# `tokens`の最初は'^'で始まり、通常文は'$'で終わり、疑問文は'?'で終わる
tokens = tokens[1:] # 最初の'^'を落とす
if tokens[-1] == "$":
tokens = tokens[:-1] # 疑問文でないとき'$'を落とす
tokens = [p2kata[token] if token in p2kata else token for token in tokens]
text = "".join(tokens)
for k, v in a2kata.items():
text = text.replace(k, v)
return text
def p2tokens(p: str) -> List[str]:
"""
カタカナと記号で表記された音素列を、VITSモデルの入力となるトークン列に変換する。
例:
コ[ンニチワ → [^, k, o, [, N, n, i, ch, i, w, a, $]
"""
p = p.replace(" ", " ") # 全角スペースを半角スペースに
p = p.replace("?", "?") # 全角疑問符を半角に
p = re.sub(r"\s{2,}", " ", p) # 連続するスペースを1つに
p = p.strip() # 先頭と末尾のスペースを削除
# 以下では、一度空白で区切られた"^ k o [ N n i ch i w a $"を作り、あとで分割。
if p[-1] != "?" and p[-1] != "$": # 疑問でない場合、最後に"$"がなければ付ける
p = p + "$"
for k, v in kata2p.items(): # 例外文字を先にトークンに置換
p = p.replace(k, v)
p = "^" + p # 先頭に"^"を付ける
for k, v in kata2a_with_spaces.items():
p = p.replace(k, v)
symbols = ["[", "]", "#", "_", "N", "cl", "?", "$"]
for sym in symbols:
p = p.replace(sym, " " + sym)
return p.split(" ")