Russian narration for the Enshrouded notes: mod 0.4.0, installer, generation pipeline
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
"""RUAccent stresses for the text of the voice.
|
||||
|
||||
plus_marks(): '+' before the stressed vowel, carried onto the ORIGINAL text word by word. RUAccent is
|
||||
fed lowercase (it is worse on Title-case) and drops spaces before "(", so a char-by-char walk drifts and
|
||||
garbles the tail ("в годод", "))"); here only the n-th Cyrillic word of its output gives its '+' (and ё)
|
||||
to the n-th word of the source, punctuation and spacing stay the source's. If the word counts differ,
|
||||
the text is accented clause by clause.
|
||||
acute_marks(): '+' before a vowel -> the vowel followed by U+0301, the input of the ru-stress model.
|
||||
"""
|
||||
import re
|
||||
|
||||
VOWELS = "аеёиоуыэюяАЕЁИОУЫЭЮЯ"
|
||||
W = re.compile(r"[А-Яа-яЁё]+(?:-[А-Яа-яЁё]+)*")
|
||||
WP = re.compile(r"[А-Яа-яЁё+]+(?:-[А-Яа-яЁё+]+)*")
|
||||
_acc = None
|
||||
|
||||
|
||||
def accentizer():
|
||||
global _acc
|
||||
if _acc is None:
|
||||
from ruaccent import RUAccent
|
||||
_acc = RUAccent()
|
||||
_acc.load(omograph_model_size="turbo3.1", use_dictionary=True, tiny_mode=False)
|
||||
return _acc
|
||||
|
||||
|
||||
def _transfer(orig, acc):
|
||||
out, i = [], 0
|
||||
for ch in acc:
|
||||
if ch == "+":
|
||||
out.append("+"); continue
|
||||
o = orig[i]
|
||||
out.append(("Ё" if o == "Е" else "ё") if ch.lower() == "ё" and o in "еЕ" else o)
|
||||
i += 1
|
||||
return "".join(out)
|
||||
|
||||
|
||||
def _plus(text):
|
||||
acc = accentizer().process_all(text.lower())
|
||||
src, dst = list(W.finditer(text)), WP.findall(acc)
|
||||
if len(src) != len(dst) or any(len(a.group(0)) != len(b.replace("+", "")) for a, b in zip(src, dst)):
|
||||
return None
|
||||
out, last = [], 0
|
||||
for a, b in zip(src, dst):
|
||||
out += [text[last:a.start()], _transfer(a.group(0), b)]
|
||||
last = a.end()
|
||||
return "".join(out) + text[last:]
|
||||
|
||||
|
||||
def plus_marks(text: str) -> str:
|
||||
r = _plus(text)
|
||||
if r is not None:
|
||||
return r
|
||||
parts = re.split(r"([,.;:!?()«»…]+\s*)", text)
|
||||
return "".join(p if i % 2 or not p.strip() else (_plus(p) or p) for i, p in enumerate(parts))
|
||||
|
||||
|
||||
def acute_marks(plus_text: str) -> str:
|
||||
return re.sub(r"\+([" + VOWELS + "])", lambda m: m.group(1) + "́", plus_text).replace("+", "")
|
||||
Reference in New Issue
Block a user