mirror of
https://github.com/linux-speakup/espeakup.git
synced 2026-08-09 09:19:09 +02:00
espeak: escape XML-special characters in single-character mode
When speakup echoes a single character, espeakup wraps it in SSML:
<say-as interpret-as="characters">%c</say-as>
If the character is one of XML's five special characters (< > & ' "),
the raw byte is injected straight into the markup, producing ill-formed
SSML. espeak-ng then misparses the <say-as> element, which surfaces as
a spurious high-pitched "ringing" whenever one of these characters is
spoken.
Escape each special character to its corresponding XML entity
(< > & ' ") so the markup stays well-formed.
Non-printable characters (< 0x20 or > 0x7e) are no longer wrapped in
SSML either; they fall through to the existing raw-synthesis fallback
so they cannot corrupt the surrounding element either.
The space and ordinary-printable-character paths are unchanged.
This commit is contained in:
parent
c3c7c6a007
commit
f266faaff7
1 changed files with 30 additions and 6 deletions
36
src/espeak.c
36
src/espeak.c
|
|
@ -302,15 +302,39 @@ static espeak_ERROR speak_text(struct synth_t *s)
|
|||
synth_mode |= espeakSSML;
|
||||
|
||||
if (espeakup_mode == ESPEAKUP_MODE_SPEAKUP && (s->len == 1)) {
|
||||
char *buf;
|
||||
char *buf = NULL;
|
||||
int n;
|
||||
if (s->buf[0] == ' ')
|
||||
unsigned char c = s->buf[0];
|
||||
if (c == ' ')
|
||||
n = asprintf(&buf,
|
||||
"<say-as interpret-as=\"tts:char\"> </say-as>");
|
||||
else
|
||||
n = asprintf(&buf,
|
||||
"<say-as interpret-as=\"characters\">%c</say-as>",
|
||||
s->buf[0]);
|
||||
else if (c < 0x20 || c > 0x7e) {
|
||||
/* Not a printable character; do not embed it in SSML, as
|
||||
* that would produce invalid markup. Fall through to the
|
||||
* raw-synthesis path below. */
|
||||
n = -1;
|
||||
} else {
|
||||
/* Escape characters that are special in XML/SSML so the
|
||||
* resulting markup stays well-formed; otherwise espeak-ng
|
||||
* misparses the <say-as> element, which is the source of
|
||||
* the spurious high-pitched "ringing" on these characters. */
|
||||
const char *entity = NULL;
|
||||
switch (c) {
|
||||
case '<': entity = "<"; break;
|
||||
case '>': entity = ">"; break;
|
||||
case '&': entity = "&"; break;
|
||||
case '\'': entity = "'"; break;
|
||||
case '"': entity = """; break;
|
||||
}
|
||||
if (entity)
|
||||
n = asprintf(&buf,
|
||||
"<say-as interpret-as=\"characters\">%s</say-as>",
|
||||
entity);
|
||||
else
|
||||
n = asprintf(&buf,
|
||||
"<say-as interpret-as=\"characters\">%c</say-as>",
|
||||
c);
|
||||
}
|
||||
if (n == -1) {
|
||||
/* D'oh. Not much to do on allocation failure.
|
||||
* Perhaps espeak will happen to say the character */
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue