espeak-ng
espeak-ng copied to clipboard
Add stress marks to phoneme events
I've added stress marks to phoneme events.
The implications of this are large for using eSpeak-ng
as a phonemizer. It means that it's now possible to get accurate mappings between the phonemized word and the original word (up till now it was pretty much impossible). This is huge for many applications that use it as a side-tool.
I have tested this for several weeks now, with many languages, and it seems to work correctly and produce results that should be identical to calling espeak_TextToPhonemes
when the phonemes are in IPA mode (I haven't tested Kirshenbaum phoneme names though, but they should work as well - it's just that I'm using it via Emscripten and the IPA output flag is "burned" into the code).
This is the main method I've added to output the phoneme names with stress marks:
char *WritePhMnemonicWithStress(char *phon_out, PHONEME_TAB *ph, PHONEME_LIST *plist, int use_ipa, int *flags) {
if (plist->synthflags & SFLAG_SYLLABLE) {
unsigned char stress = plist->stresslevel;
if (stress > 1) {
int c = 0;
if (stress > STRESS_IS_PRIORITY) {
stress = STRESS_IS_PRIORITY;
}
if (use_ipa) {
c = 0x2cc; // ipa, secondary stress
if (stress > STRESS_IS_SECONDARY) {
c = 0x02c8; // ipa, primary stress
}
} else {
const char stress_chars[] = "==,,''";
c = stress_chars[stress];
}
if (c != 0) {
phon_out += utf8_out(c, phon_out);
}
}
}
return WritePhMnemonic(phon_out, ph, plist, use_ipa, flags);
}
(The local constant const char stress_chars[] = "==,,''";
is somewhat of a "hack". This should be a global constant, but I didn't want to modify other methods to use this)
That method is based, almost exactly, on a code fragment I found in GetTranslatedPhonemeString
:
if (plist->synthflags & SFLAG_SYLLABLE) {
if ((stress = plist->stresslevel) > 1) {
c = 0;
if (stress > STRESS_IS_PRIORITY) stress = STRESS_IS_PRIORITY;
if (use_ipa) {
c = 0x2cc; // ipa, secondary stress
if (stress > STRESS_IS_SECONDARY)
c = 0x02c8; // ipa, primary stress
} else
c = stress_chars[stress];
if (c != 0)
buf += utf8_out(c, buf);
}
}
However, the way it's done now - it's a minor breaking change.
I guess it would be better to enable this feature via a flag, but I don't have sufficient knowledge of the codebase to implement something like that.
I'll give this code to you people to decide how and if you want to integrate it.
I have more code to contribute: For example: I've enhanced the Emscripten port to support events (and phoneme events in particular), and I've tested it extensively for more than 6 months now.