fighter-programmer/voicegen
0
1import os2import sys3import re4from pypinyin import lazy_pinyin, BOPOMOFO5import jieba6import cn2an7import logging8 9logging.getLogger('jieba').setLevel(logging.WARNING)10jieba.initialize()11 12 13# List of (Latin alphabet, bopomofo) pairs:14_latin_to_bopomofo = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [15 ('a', 'ㄟˉ'),16 ('b', 'ㄅㄧˋ'),17 ('c', 'ㄙㄧˉ'),18 ('d', 'ㄉㄧˋ'),19 ('e', 'ㄧˋ'),20 ('f', 'ㄝˊㄈㄨˋ'),21 ('g', 'ㄐㄧˋ'),22 ('h', 'ㄝˇㄑㄩˋ'),23 ('i', 'ㄞˋ'),24 ('j', 'ㄐㄟˋ'),25 ('k', 'ㄎㄟˋ'),26 ('l', 'ㄝˊㄛˋ'),27 ('m', 'ㄝˊㄇㄨˋ'),28 ('n', 'ㄣˉ'),29 ('o', 'ㄡˉ'),30 ('p', 'ㄆㄧˉ'),31 ('q', 'ㄎㄧㄡˉ'),32 ('r', 'ㄚˋ'),33 ('s', 'ㄝˊㄙˋ'),34 ('t', 'ㄊㄧˋ'),35 ('u', 'ㄧㄡˉ'),36 ('v', 'ㄨㄧˉ'),37 ('w', 'ㄉㄚˋㄅㄨˋㄌㄧㄡˋ'),38 ('x', 'ㄝˉㄎㄨˋㄙˋ'),39 ('y', 'ㄨㄞˋ'),40 ('z', 'ㄗㄟˋ')41]]42 43# List of (bopomofo, romaji) pairs:44_bopomofo_to_romaji = [(re.compile('%s' % x[0]), x[1]) for x in [45 ('ㄅㄛ', 'p⁼wo'),46 ('ㄆㄛ', 'pʰwo'),47 ('ㄇㄛ', 'mwo'),48 ('ㄈㄛ', 'fwo'),49 ('ㄅ', 'p⁼'),50 ('ㄆ', 'pʰ'),51 ('ㄇ', 'm'),52 ('ㄈ', 'f'),53 ('ㄉ', 't⁼'),54 ('ㄊ', 'tʰ'),55 ('ㄋ', 'n'),56 ('ㄌ', 'l'),57 ('ㄍ', 'k⁼'),58 ('ㄎ', 'kʰ'),59 ('ㄏ', 'h'),60 ('ㄐ', 'ʧ⁼'),61 ('ㄑ', 'ʧʰ'),62 ('ㄒ', 'ʃ'),63 ('ㄓ', 'ʦ`⁼'),64 ('ㄔ', 'ʦ`ʰ'),65 ('ㄕ', 's`'),66 ('ㄖ', 'ɹ`'),67 ('ㄗ', 'ʦ⁼'),68 ('ㄘ', 'ʦʰ'),69 ('ㄙ', 's'),70 ('ㄚ', 'a'),71 ('ㄛ', 'o'),72 ('ㄜ', 'ə'),73 ('ㄝ', 'e'),74 ('ㄞ', 'ai'),75 ('ㄟ', 'ei'),76 ('ㄠ', 'au'),77 ('ㄡ', 'ou'),78 ('ㄧㄢ', 'yeNN'),79 ('ㄢ', 'aNN'),80 ('ㄧㄣ', 'iNN'),81 ('ㄣ', 'əNN'),82 ('ㄤ', 'aNg'),83 ('ㄧㄥ', 'iNg'),84 ('ㄨㄥ', 'uNg'),85 ('ㄩㄥ', 'yuNg'),86 ('ㄥ', 'əNg'),87 ('ㄦ', 'əɻ'),88 ('ㄧ', 'i'),89 ('ㄨ', 'u'),90 ('ㄩ', 'ɥ'),91 ('ˉ', '→'),92 ('ˊ', '↑'),93 ('ˇ', '↓↑'),94 ('ˋ', '↓'),95 ('˙', ''),96 (',', ','),97 ('。', '.'),98 ('!', '!'),99 ('?', '?'),100 ('—', '-')101]]102 103# List of (romaji, ipa) pairs:104_romaji_to_ipa = [(re.compile('%s' % x[0], re.IGNORECASE), x[1]) for x in [105 ('ʃy', 'ʃ'),106 ('ʧʰy', 'ʧʰ'),107 ('ʧ⁼y', 'ʧ⁼'),108 ('NN', 'n'),109 ('Ng', 'ŋ'),110 ('y', 'j'),111 ('h', 'x')112]]113 114# List of (bopomofo, ipa) pairs:115_bopomofo_to_ipa = [(re.compile('%s' % x[0]), x[1]) for x in [116 ('ㄅㄛ', 'p⁼wo'),117 ('ㄆㄛ', 'pʰwo'),118 ('ㄇㄛ', 'mwo'),119 ('ㄈㄛ', 'fwo'),120 ('ㄅ', 'p⁼'),121 ('ㄆ', 'pʰ'),122 ('ㄇ', 'm'),123 ('ㄈ', 'f'),124 ('ㄉ', 't⁼'),125 ('ㄊ', 'tʰ'),126 ('ㄋ', 'n'),127 ('ㄌ', 'l'),128 ('ㄍ', 'k⁼'),129 ('ㄎ', 'kʰ'),130 ('ㄏ', 'x'),131 ('ㄐ', 'tʃ⁼'),132 ('ㄑ', 'tʃʰ'),133 ('ㄒ', 'ʃ'),134 ('ㄓ', 'ts`⁼'),135 ('ㄔ', 'ts`ʰ'),136 ('ㄕ', 's`'),137 ('ㄖ', 'ɹ`'),138 ('ㄗ', 'ts⁼'),139 ('ㄘ', 'tsʰ'),140 ('ㄙ', 's'),141 ('ㄚ', 'a'),142 ('ㄛ', 'o'),143 ('ㄜ', 'ə'),144 ('ㄝ', 'ɛ'),145 ('ㄞ', 'aɪ'),146 ('ㄟ', 'eɪ'),147 ('ㄠ', 'ɑʊ'),148 ('ㄡ', 'oʊ'),149 ('ㄧㄢ', 'jɛn'),150 ('ㄩㄢ', 'ɥæn'),151 ('ㄢ', 'an'),152 ('ㄧㄣ', 'in'),153 ('ㄩㄣ', 'ɥn'),154 ('ㄣ', 'ən'),155 ('ㄤ', 'ɑŋ'),156 ('ㄧㄥ', 'iŋ'),157 ('ㄨㄥ', 'ʊŋ'),158 ('ㄩㄥ', 'jʊŋ'),159 ('ㄥ', 'əŋ'),160 ('ㄦ', 'əɻ'),161 ('ㄧ', 'i'),162 ('ㄨ', 'u'),163 ('ㄩ', 'ɥ'),164 ('ˉ', '→'),165 ('ˊ', '↑'),166 ('ˇ', '↓↑'),167 ('ˋ', '↓'),168 ('˙', ''),169 (',', ','),170 ('。', '.'),171 ('!', '!'),172 ('?', '?'),173 ('—', '-')174]]175 176# List of (bopomofo, ipa2) pairs:177_bopomofo_to_ipa2 = [(re.compile('%s' % x[0]), x[1]) for x in [178 ('ㄅㄛ', 'pwo'),179 ('ㄆㄛ', 'pʰwo'),180 ('ㄇㄛ', 'mwo'),181 ('ㄈㄛ', 'fwo'),182 ('ㄅ', 'p'),183 ('ㄆ', 'pʰ'),184 ('ㄇ', 'm'),185 ('ㄈ', 'f'),186 ('ㄉ', 't'),187 ('ㄊ', 'tʰ'),188 ('ㄋ', 'n'),189 ('ㄌ', 'l'),190 ('ㄍ', 'k'),191 ('ㄎ', 'kʰ'),192 ('ㄏ', 'h'),193 ('ㄐ', 'tɕ'),194 ('ㄑ', 'tɕʰ'),195 ('ㄒ', 'ɕ'),196 ('ㄓ', 'tʂ'),197 ('ㄔ', 'tʂʰ'),198 ('ㄕ', 'ʂ'),199 ('ㄖ', 'ɻ'),200 ('ㄗ', 'ts'),201 ('ㄘ', 'tsʰ'),202 ('ㄙ', 's'),203 ('ㄚ', 'a'),204 ('ㄛ', 'o'),205 ('ㄜ', 'ɤ'),206 ('ㄝ', 'ɛ'),207 ('ㄞ', 'aɪ'),208 ('ㄟ', 'eɪ'),209 ('ㄠ', 'ɑʊ'),210 ('ㄡ', 'oʊ'),211 ('ㄧㄢ', 'jɛn'),212 ('ㄩㄢ', 'yæn'),213 ('ㄢ', 'an'),214 ('ㄧㄣ', 'in'),215 ('ㄩㄣ', 'yn'),216 ('ㄣ', 'ən'),217 ('ㄤ', 'ɑŋ'),218 ('ㄧㄥ', 'iŋ'),219 ('ㄨㄥ', 'ʊŋ'),220 ('ㄩㄥ', 'jʊŋ'),221 ('ㄥ', 'ɤŋ'),222 ('ㄦ', 'əɻ'),223 ('ㄧ', 'i'),224 ('ㄨ', 'u'),225 ('ㄩ', 'y'),226 ('ˉ', '˥'),227 ('ˊ', '˧˥'),228 ('ˇ', '˨˩˦'),229 ('ˋ', '˥˩'),230 ('˙', ''),231 (',', ','),232 ('。', '.'),233 ('!', '!'),234 ('?', '?'),235 ('—', '-')236]]237 238 239def number_to_chinese(text):240 numbers = re.findall(r'\d+(?:\.?\d+)?', text)241 for number in numbers:242 text = text.replace(number, cn2an.an2cn(number), 1)243 return text244 245 246def chinese_to_bopomofo(text):247 text = text.replace('、', ',').replace(';', ',').replace(':', ',')248 words = jieba.lcut(text, cut_all=False)249 text = ''250 for word in words:251 bopomofos = lazy_pinyin(word, BOPOMOFO)252 if not re.search('[\u4e00-\u9fff]', word):253 text += word254 continue255 for i in range(len(bopomofos)):256 bopomofos[i] = re.sub(r'([\u3105-\u3129])$', r'\1ˉ', bopomofos[i])257 if text != '':258 text += ' '259 text += ''.join(bopomofos)260 return text261 262 263def latin_to_bopomofo(text):264 for regex, replacement in _latin_to_bopomofo:265 text = re.sub(regex, replacement, text)266 return text267 268 269def bopomofo_to_romaji(text):270 for regex, replacement in _bopomofo_to_romaji:271 text = re.sub(regex, replacement, text)272 return text273 274 275def bopomofo_to_ipa(text):276 for regex, replacement in _bopomofo_to_ipa:277 text = re.sub(regex, replacement, text)278 return text279 280 281def bopomofo_to_ipa2(text):282 for regex, replacement in _bopomofo_to_ipa2:283 text = re.sub(regex, replacement, text)284 return text285 286 287def chinese_to_romaji(text):288 text = number_to_chinese(text)289 text = chinese_to_bopomofo(text)290 text = latin_to_bopomofo(text)291 text = bopomofo_to_romaji(text)292 text = re.sub('i([aoe])', r'y\1', text)293 text = re.sub('u([aoəe])', r'w\1', text)294 text = re.sub('([ʦsɹ]`[⁼ʰ]?)([→↓↑ ]+|$)',295 r'\1ɹ`\2', text).replace('ɻ', 'ɹ`')296 text = re.sub('([ʦs][⁼ʰ]?)([→↓↑ ]+|$)', r'\1ɹ\2', text)297 return text298 299 300def chinese_to_lazy_ipa(text):301 text = chinese_to_romaji(text)302 for regex, replacement in _romaji_to_ipa:303 text = re.sub(regex, replacement, text)304 return text305 306 307def chinese_to_ipa(text):308 text = number_to_chinese(text)309 text = chinese_to_bopomofo(text)310 text = latin_to_bopomofo(text)311 text = bopomofo_to_ipa(text)312 text = re.sub('i([aoe])', r'j\1', text)313 text = re.sub('u([aoəe])', r'w\1', text)314 text = re.sub('([sɹ]`[⁼ʰ]?)([→↓↑ ]+|$)',315 r'\1ɹ`\2', text).replace('ɻ', 'ɹ`')316 text = re.sub('([s][⁼ʰ]?)([→↓↑ ]+|$)', r'\1ɹ\2', text)317 return text318 319 320def chinese_to_ipa2(text):321 text = number_to_chinese(text)322 text = chinese_to_bopomofo(text)323 text = latin_to_bopomofo(text)324 text = bopomofo_to_ipa2(text)325 text = re.sub(r'i([aoe])', r'j\1', text)326 text = re.sub(r'u([aoəe])', r'w\1', text)327 text = re.sub(r'([ʂɹ]ʰ?)([˩˨˧˦˥ ]+|$)', r'\1ʅ\2', text)328 text = re.sub(r'(sʰ?)([˩˨˧˦˥ ]+|$)', r'\1ɿ\2', text)329 return text