diff --git a/src/espeak.c b/src/espeak.c index 60cc996..c9ac908 100644 --- a/src/espeak.c +++ b/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, " "); - else - n = asprintf(&buf, - "%c", - 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 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, + "%s", + entity); + else + n = asprintf(&buf, + "%c", + c); + } if (n == -1) { /* D'oh. Not much to do on allocation failure. * Perhaps espeak will happen to say the character */