mirror of
https://github.com/rhasspy/espeak-ng.git
synced 2026-10-31 05:35:35 +00:00
move GetVoiceFromStack()
This commit is contained in:
@@ -550,82 +550,6 @@ static int AnnouncePunctuation(Translator *tr, int c1, int *c2_ptr, char *output
|
||||
return short_pause;
|
||||
}
|
||||
|
||||
const char *VoiceFromStack()
|
||||
{
|
||||
// Use the voice properties from the SSML stack to choose a voice, and switch
|
||||
// to that voice if it's not the current voice
|
||||
|
||||
int ix;
|
||||
const char *p;
|
||||
SSML_STACK *sp;
|
||||
const char *v_id;
|
||||
int voice_name_specified;
|
||||
int voice_found;
|
||||
espeak_VOICE voice_select;
|
||||
static char voice_name[40];
|
||||
char language[40];
|
||||
char buf[80];
|
||||
|
||||
strcpy(voice_name, ssml_stack[0].voice_name);
|
||||
strcpy(language, ssml_stack[0].language);
|
||||
voice_select.age = ssml_stack[0].voice_age;
|
||||
voice_select.gender = ssml_stack[0].voice_gender;
|
||||
voice_select.variant = ssml_stack[0].voice_variant_number;
|
||||
voice_select.identifier = NULL;
|
||||
|
||||
for (ix = 0; ix < n_ssml_stack; ix++) {
|
||||
sp = &ssml_stack[ix];
|
||||
voice_name_specified = 0;
|
||||
|
||||
if ((sp->voice_name[0] != 0) && (SelectVoiceByName(NULL, sp->voice_name) != NULL)) {
|
||||
voice_name_specified = 1;
|
||||
strcpy(voice_name, sp->voice_name);
|
||||
language[0] = 0;
|
||||
voice_select.gender = ENGENDER_UNKNOWN;
|
||||
voice_select.age = 0;
|
||||
voice_select.variant = 0;
|
||||
}
|
||||
if (sp->language[0] != 0) {
|
||||
strcpy(language, sp->language);
|
||||
|
||||
// is this language provided by the base voice?
|
||||
p = base_voice.languages;
|
||||
while (*p++ != 0) {
|
||||
if (strcmp(p, language) == 0) {
|
||||
// yes, change the language to the main language of the base voice
|
||||
strcpy(language, &base_voice.languages[1]);
|
||||
break;
|
||||
}
|
||||
p += (strlen(p) + 1);
|
||||
}
|
||||
|
||||
if (voice_name_specified == 0)
|
||||
voice_name[0] = 0; // forget a previous voice name if a language is specified
|
||||
}
|
||||
if (sp->voice_gender != ENGENDER_UNKNOWN)
|
||||
voice_select.gender = sp->voice_gender;
|
||||
|
||||
if (sp->voice_age != 0)
|
||||
voice_select.age = sp->voice_age;
|
||||
if (sp->voice_variant_number != 0)
|
||||
voice_select.variant = sp->voice_variant_number;
|
||||
}
|
||||
|
||||
voice_select.name = voice_name;
|
||||
voice_select.languages = language;
|
||||
v_id = SelectVoice(&voice_select, &voice_found);
|
||||
if (v_id == NULL)
|
||||
return "default";
|
||||
|
||||
if ((strchr(v_id, '+') == NULL) && ((voice_select.gender == ENGENDER_UNKNOWN) || (voice_select.gender == base_voice.gender)) && (base_voice_variant_name[0] != 0)) {
|
||||
// a voice variant has not been selected, use the original voice variant
|
||||
sprintf(buf, "%s+%s", v_id, base_voice_variant_name);
|
||||
strncpy0(voice_name, buf, sizeof(voice_name));
|
||||
return voice_name;
|
||||
}
|
||||
return v_id;
|
||||
}
|
||||
|
||||
static void ProcessParamStack(char *outbuf, int *outix)
|
||||
{
|
||||
// Set the speech parameters from the parameter stack
|
||||
@@ -1210,57 +1134,57 @@ static int ProcessSsmlTag(wchar_t *xml_buf, char *outbuf, int *outix, int n_outb
|
||||
if ((index = AddNameData(buf, 0)) >= 0)
|
||||
xmlbase = &namedata[index];
|
||||
}
|
||||
if (GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id) == 0)
|
||||
if (GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name) == 0)
|
||||
return 0; // no voice change
|
||||
return CLAUSE_VOICE;
|
||||
case SSML_VOICE:
|
||||
if (GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id) == 0)
|
||||
if (GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name) == 0)
|
||||
return 0; // no voice change
|
||||
return CLAUSE_VOICE;
|
||||
case SSML_SPEAK + SSML_CLOSE:
|
||||
// unwind stack until the previous <voice> or <speak> tag
|
||||
while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_SPEAK))
|
||||
n_ssml_stack--;
|
||||
return CLAUSE_PERIOD + GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
return CLAUSE_PERIOD + GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
case SSML_VOICE + SSML_CLOSE:
|
||||
// unwind stack until the previous <voice> or <speak> tag
|
||||
while ((n_ssml_stack > 1) && (ssml_stack[n_ssml_stack-1].tag_type != SSML_VOICE))
|
||||
n_ssml_stack--;
|
||||
|
||||
terminator = 0; // ?? Sentence intonation, but no pause ??
|
||||
return terminator + GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
return terminator + GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
case HTML_BREAK:
|
||||
case HTML_BREAK + SSML_CLOSE:
|
||||
return CLAUSE_COLON;
|
||||
case SSML_SENTENCE:
|
||||
if (ssml_sp->tag_type == SSML_SENTENCE) {
|
||||
// new sentence implies end-of-sentence
|
||||
voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
}
|
||||
voice_change_flag |= GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
voice_change_flag |= GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
return CLAUSE_PARAGRAPH + voice_change_flag;
|
||||
case SSML_PARAGRAPH:
|
||||
if (ssml_sp->tag_type == SSML_SENTENCE) {
|
||||
// new paragraph implies end-of-sentence or end-of-paragraph
|
||||
voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
voice_change_flag = GetVoiceAttributes(px, SSML_SENTENCE+SSML_CLOSE, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
}
|
||||
if (ssml_sp->tag_type == SSML_PARAGRAPH) {
|
||||
// new paragraph implies end-of-sentence or end-of-paragraph
|
||||
voice_change_flag |= GetVoiceAttributes(px, SSML_PARAGRAPH+SSML_CLOSE, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
voice_change_flag |= GetVoiceAttributes(px, SSML_PARAGRAPH+SSML_CLOSE, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
}
|
||||
voice_change_flag |= GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
voice_change_flag |= GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
return CLAUSE_PARAGRAPH + voice_change_flag;
|
||||
case SSML_SENTENCE + SSML_CLOSE:
|
||||
if (ssml_sp->tag_type == SSML_SENTENCE) {
|
||||
// end of a sentence which specified a language
|
||||
voice_change_flag = GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id);
|
||||
voice_change_flag = GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name);
|
||||
}
|
||||
return CLAUSE_PERIOD + voice_change_flag;
|
||||
case SSML_PARAGRAPH + SSML_CLOSE:
|
||||
if ((ssml_sp->tag_type == SSML_SENTENCE) || (ssml_sp->tag_type == SSML_PARAGRAPH)) {
|
||||
// End of a paragraph which specified a language.
|
||||
// (End-of-paragraph also implies end-of-sentence)
|
||||
return GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, ¤t_voice_id) + CLAUSE_PARAGRAPH;
|
||||
return GetVoiceAttributes(px, tag_type, ssml_sp, ssml_stack, n_ssml_stack, current_voice_id, &base_voice, base_voice_variant_name) + CLAUSE_PARAGRAPH;
|
||||
}
|
||||
return CLAUSE_PARAGRAPH;
|
||||
}
|
||||
|
||||
+79
-2
@@ -158,7 +158,7 @@ int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out)
|
||||
return sign; // -1, 0, or 1
|
||||
}
|
||||
|
||||
int GetVoiceAttributes(wchar_t *pw, int tag_type, SSML_STACK *ssml_sp, SSML_STACK *ssml_stack, int n_ssml_stack, char current_voice_id[])
|
||||
int GetVoiceAttributes(wchar_t *pw, int tag_type, SSML_STACK *ssml_sp, SSML_STACK *ssml_stack, int n_ssml_stack, char current_voice_id[40], espeak_VOICE *base_voice, char base_voice_variant_name[40])
|
||||
{
|
||||
// Determines whether voice attribute are specified in this tag, and if so, whether this means
|
||||
// a voice change.
|
||||
@@ -217,7 +217,7 @@ int GetVoiceAttributes(wchar_t *pw, int tag_type, SSML_STACK *ssml_sp, SSML_STAC
|
||||
ssml_sp->tag_type = tag_type;
|
||||
}
|
||||
|
||||
new_voice_id = VoiceFromStack();
|
||||
new_voice_id = VoiceFromStack(ssml_stack, n_ssml_stack, base_voice, base_voice_variant_name);
|
||||
if (strcmp(new_voice_id, current_voice_id) != 0) {
|
||||
// add an embedded command to change the voice
|
||||
strcpy(current_voice_id, new_voice_id);
|
||||
@@ -226,3 +226,80 @@ int GetVoiceAttributes(wchar_t *pw, int tag_type, SSML_STACK *ssml_sp, SSML_STAC
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
const char *VoiceFromStack(SSML_STACK *ssml_stack, int n_ssml_stack, espeak_VOICE *base_voice, char base_voice_variant_name[40])
|
||||
{
|
||||
// Use the voice properties from the SSML stack to choose a voice, and switch
|
||||
// to that voice if it's not the current voice
|
||||
|
||||
int ix;
|
||||
const char *p;
|
||||
SSML_STACK *sp;
|
||||
const char *v_id;
|
||||
int voice_name_specified;
|
||||
int voice_found;
|
||||
espeak_VOICE voice_select;
|
||||
static char voice_name[40];
|
||||
char language[40];
|
||||
char buf[80];
|
||||
|
||||
strcpy(voice_name, ssml_stack[0].voice_name);
|
||||
strcpy(language, ssml_stack[0].language);
|
||||
voice_select.age = ssml_stack[0].voice_age;
|
||||
voice_select.gender = ssml_stack[0].voice_gender;
|
||||
voice_select.variant = ssml_stack[0].voice_variant_number;
|
||||
voice_select.identifier = NULL;
|
||||
|
||||
for (ix = 0; ix < n_ssml_stack; ix++) {
|
||||
sp = &ssml_stack[ix];
|
||||
voice_name_specified = 0;
|
||||
|
||||
if ((sp->voice_name[0] != 0) && (SelectVoiceByName(NULL, sp->voice_name) != NULL)) {
|
||||
voice_name_specified = 1;
|
||||
strcpy(voice_name, sp->voice_name);
|
||||
language[0] = 0;
|
||||
voice_select.gender = ENGENDER_UNKNOWN;
|
||||
voice_select.age = 0;
|
||||
voice_select.variant = 0;
|
||||
}
|
||||
if (sp->language[0] != 0) {
|
||||
strcpy(language, sp->language);
|
||||
|
||||
// is this language provided by the base voice?
|
||||
p = base_voice->languages;
|
||||
while (*p++ != 0) {
|
||||
if (strcmp(p, language) == 0) {
|
||||
// yes, change the language to the main language of the base voice
|
||||
strcpy(language, &base_voice->languages[1]);
|
||||
break;
|
||||
}
|
||||
p += (strlen(p) + 1);
|
||||
}
|
||||
|
||||
if (voice_name_specified == 0)
|
||||
voice_name[0] = 0; // forget a previous voice name if a language is specified
|
||||
}
|
||||
if (sp->voice_gender != ENGENDER_UNKNOWN)
|
||||
voice_select.gender = sp->voice_gender;
|
||||
|
||||
if (sp->voice_age != 0)
|
||||
voice_select.age = sp->voice_age;
|
||||
if (sp->voice_variant_number != 0)
|
||||
voice_select.variant = sp->voice_variant_number;
|
||||
}
|
||||
|
||||
voice_select.name = voice_name;
|
||||
voice_select.languages = language;
|
||||
v_id = SelectVoice(&voice_select, &voice_found);
|
||||
if (v_id == NULL)
|
||||
return "default";
|
||||
|
||||
if ((strchr(v_id, '+') == NULL) && ((voice_select.gender == ENGENDER_UNKNOWN) || (voice_select.gender == base_voice->gender)) && (base_voice_variant_name[0] != 0)) {
|
||||
// a voice variant has not been selected, use the original voice variant
|
||||
sprintf(buf, "%s+%s", v_id, base_voice_variant_name);
|
||||
strncpy0(voice_name, buf, sizeof(voice_name));
|
||||
return voice_name;
|
||||
}
|
||||
return v_id;
|
||||
}
|
||||
|
||||
|
||||
@@ -73,5 +73,5 @@ int attrlookup(const wchar_t *string1, const MNEM_TAB *mtab);
|
||||
int attrnumber(const wchar_t *pw, int default_value, int type);
|
||||
int attr_prosody_value(int param_type, const wchar_t *pw, int *value_out);
|
||||
int attrcopy_utf8(char *buf, const wchar_t *pw, int len);
|
||||
int GetVoiceAttributes(wchar_t *pw, int tag_type, SSML_STACK *ssml_sp, SSML_STACK *ssml_stack, int n_ssml_stack, char current_voice_id[]);
|
||||
|
||||
int GetVoiceAttributes(wchar_t *pw, int tag_type, SSML_STACK *ssml_sp, SSML_STACK *ssml_stack, int n_ssml_stack, char current_voice_id[40], espeak_VOICE *base_voice, char base_voice_variant_name[40]);
|
||||
const char *VoiceFromStack(SSML_STACK *ssml_stack, int n_ssml_stack, espeak_VOICE *base_voice, char base_voice_variant_name[40]);
|
||||
|
||||
Reference in New Issue
Block a user