espeak_ERROR SetVoiceByName(const char *name) {//========================================= espeak_VOICE *v; int ix; espeak_VOICE voice_selector; char *variant_name; static char buf[60]; strncpy0(buf,name,sizeof(buf)); variant_name = ExtractVoiceVariantName(buf, 0, 1); for(ix=0; ; ix++) { // convert voice name to lower case (ascii) if((buf[ix] = tolower(buf[ix])) == 0) break; } memset(&voice_selector,0,sizeof(voice_selector)); voice_selector.name = (char *)name; // include variant name in voice stack ?? // first check for a voice with this filename // This may avoid the need to call espeak_ListVoices(). if(LoadVoice(buf,1) != NULL) { if(variant_name[0] != 0) { LoadVoice(variant_name,2); } DoVoiceChange(voice); voice_selector.languages = voice->language_name; SetVoiceStack(&voice_selector, variant_name); return(EE_OK); } if(n_voices_list == 0) espeak_ListVoices(NULL); // create the voices list if((v = SelectVoiceByName(voices_list,buf)) != NULL) { if(LoadVoice(v->identifier,0) != NULL) { if(variant_name[0] != 0) { LoadVoice(variant_name,2); } DoVoiceChange(voice); voice_selector.languages = voice->language_name; SetVoiceStack(&voice_selector, variant_name); return(EE_OK); } } return(EE_INTERNAL_ERROR); // voice name not found } // end of SetVoiceByName
voice_t *LoadVoiceVariant(const char *vname, int variant_num) { // Load a voice file. // Also apply a voice variant if specified by "variant", or by "+number" or "+name" in the "vname" voice_t *v; char *variant_name; char buf[60]; strncpy0(buf, vname, sizeof(buf)); variant_name = ExtractVoiceVariantName(buf, variant_num, 1); if ((v = LoadVoice(buf, 0)) == NULL) return NULL; if (variant_name[0] != 0) v = LoadVoice(variant_name, 2); return v; }
char const *SelectVoice(espeak_VOICE *voice_select, int *found) {//============================================================ // Returns a path within espeak-voices, with a possible +variant suffix // variant is an output-only parameter int nv; // number of candidates int ix, ix2; int j; int n_variants; int variant_number; int gender; int skip; int aged=1; char *variant_name; const char *p, *p_start; espeak_VOICE *vp = NULL; espeak_VOICE *vp2; espeak_VOICE voice_select2; espeak_VOICE *voices[N_VOICES_LIST]; // list of candidates espeak_VOICE *voices2[N_VOICES_LIST+N_VOICE_VARIANTS]; static espeak_VOICE voice_variants[N_VOICE_VARIANTS]; static char voice_id[50]; *found = 1; memcpy(&voice_select2,voice_select,sizeof(voice_select2)); if(n_voices_list == 0) espeak_ListVoices(NULL); // create the voices list if((voice_select2.languages == NULL) || (voice_select2.languages[0] == 0)) { // no language is specified. Get language from the named voice static char buf[60]; if(voice_select2.name == NULL) { if((voice_select2.name = voice_select2.identifier) == NULL) voice_select2.name = "default"; } strncpy0(buf,voice_select2.name,sizeof(buf)); variant_name = ExtractVoiceVariantName(buf,0,0); vp = SelectVoiceByName(voices_list,buf); if(vp != NULL) { voice_select2.languages = &(vp->languages[1]); if((voice_select2.gender==0) && (voice_select2.age==0) && (voice_select2.variant==0)) { if(variant_name[0] != 0) { sprintf(voice_id,"%s+%s", vp->identifier, variant_name); return(voice_id); } return(vp->identifier); } } } // select and sort voices for the required language nv = SetVoiceScores(&voice_select2,voices,0); if(nv == 0) { // no matching voice, choose the default *found = 0; if((voices[0] = SelectVoiceByName(voices_list,"default")) != NULL) nv = 1; } gender = 0; if((voice_select2.gender == 2) || ((voice_select2.age > 0) && (voice_select2.age < 13))) gender = 2; else if(voice_select2.gender == 1) gender = 1; #define AGE_OLD 60 if(voice_select2.age < AGE_OLD) aged = 0; p = p_start = variant_lists[gender]; if(aged == 0) p++; // the first voice in the variants list is older // add variants for the top voices n_variants = 0; for(ix=0, ix2=0; ix<nv; ix++) { vp = voices[ix]; // is the main voice the required gender? skip=0; if((gender != 0) && (vp->gender != gender)) { skip=1; } if((ix2==0) && aged && (vp->age < AGE_OLD)) { skip=1; } if(skip==0) { voices2[ix2++] = vp; } for(j=0; (j < vp->xx1) && (n_variants < N_VOICE_VARIANTS);) { if((variant_number = *p) == 0) { p = p_start; continue; } vp2 = &voice_variants[n_variants++]; // allocate space for voice variant memcpy(vp2,vp,sizeof(espeak_VOICE)); // copy from the original voice vp2->variant = variant_number; voices2[ix2++] = vp2; p++; j++; } } // add any more variants to the end of the list while((vp != NULL) && ((variant_number = *p++) != 0) && (n_variants < N_VOICE_VARIANTS)) { vp2 = &voice_variants[n_variants++]; // allocate space for voice variant memcpy(vp2,vp,sizeof(espeak_VOICE)); // copy from the original voice vp2->variant = variant_number; voices2[ix2++] = vp2; } // index the sorted list by the required variant number if(ix2 == 0) return(NULL); vp = voices2[voice_select2.variant % ix2]; if(vp->variant != 0) { variant_name = ExtractVoiceVariantName(NULL, vp->variant, 0); sprintf(voice_id,"%s+%s", vp->identifier, variant_name); return(voice_id); } return(vp->identifier); } // end of SelectVoice