diff --git a/src/espeak-ng.c b/src/espeak-ng.c index 812397fe..10b8a887 100644 --- a/src/espeak-ng.c +++ b/src/espeak-ng.c @@ -28,6 +28,7 @@ #include #include #include +#include #include #include @@ -113,6 +114,7 @@ static const char *help_text = "--voices=\n" "\t List the available voices for the specified language.\n" "\t If is omitted, then list all voices.\n" + "--load Load voice from a file in current directory by name.\n" "-h, --help Show this help.\n"; int samplerate; @@ -321,6 +323,7 @@ int main(int argc, char **argv) { "compile-mbrola", optional_argument, 0, 0x10e }, { "compile-intonations", no_argument, 0, 0x10f }, { "compile-phonemes", optional_argument, 0, 0x110 }, + { "load", no_argument, 0, 0x111 }, { 0, 0, 0, 0 } }; @@ -336,6 +339,7 @@ int main(int argc, char **argv) int value; int flag_stdin = 0; int flag_compile = 0; + int flag_load = 0; int filesize = 0; int synth_flags = espeakCHARS_AUTO | espeakPHONEMES | espeakENDPAUSE; @@ -349,7 +353,7 @@ int main(int argc, char **argv) int phoneme_options = 0; int option_linelength = 0; int option_waveout = 0; - + espeak_VOICE voice_select; char filename[200]; char voicename[40]; @@ -562,6 +566,9 @@ int main(int argc, char **argv) } return EXIT_SUCCESS; } + case 0x111: // --load + flag_load = 1; + break; default: exit(0); } @@ -605,7 +612,10 @@ int main(int argc, char **argv) if (voicename[0] == 0) strcpy(voicename, ESPEAKNG_DEFAULT_VOICE); - result = espeak_ng_SetVoiceByName(voicename); + if(flag_load) + result = espeak_ng_SetVoiceByFile(voicename); + else + result = espeak_ng_SetVoiceByName(voicename); if (result != ENS_OK) { memset(&voice_select, 0, sizeof(voice_select)); voice_select.languages = voicename; diff --git a/src/include/espeak-ng/espeak_ng.h b/src/include/espeak-ng/espeak_ng.h index 36d2682b..b9804fce 100644 --- a/src/include/espeak-ng/espeak_ng.h +++ b/src/include/espeak-ng/espeak_ng.h @@ -119,6 +119,9 @@ espeak_ng_SetPunctuationList(const wchar_t *punctlist); ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetVoiceByName(const char *name); +ESPEAK_NG_API espeak_ng_STATUS +espeak_ng_SetVoiceByFile(const char *filename); + ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetVoiceByProperties(espeak_VOICE *voice_selector); diff --git a/src/include/espeak-ng/speak_lib.h b/src/include/espeak-ng/speak_lib.h index 5cce6164..cc1e35e7 100644 --- a/src/include/espeak-ng/speak_lib.h +++ b/src/include/espeak-ng/speak_lib.h @@ -606,6 +606,19 @@ ESPEAK_API const espeak_VOICE **espeak_ListVoices(espeak_VOICE *voice_spec); are listed, and they are listed in preference order. */ +#ifdef __cplusplus +extern "C" +#endif +ESPEAK_API espeak_ERROR espeak_SetVoiceByFile(const char *filename); +/* Loads a voice given the file path. Language is not considered. + "filename" is a UTF8 string. + + Return: EE_OK: operation achieved + EE_BUFFER_FULL: the command can not be buffered; + you may try after a while to call the function again. + EE_INTERNAL_ERROR. +*/ + #ifdef __cplusplus extern "C" #endif diff --git a/src/libespeak-ng/espeak_api.c b/src/libespeak-ng/espeak_api.c index 0a5f6fd7..73d9417b 100644 --- a/src/libespeak-ng/espeak_api.c +++ b/src/libespeak-ng/espeak_api.c @@ -128,6 +128,11 @@ ESPEAK_API espeak_ERROR espeak_SetVoiceByName(const char *name) return status_to_espeak_error(espeak_ng_SetVoiceByName(name)); } +ESPEAK_API espeak_ERROR espeak_SetVoiceByFile(const char *filename) +{ + return status_to_espeak_error(espeak_ng_SetVoiceByFile(filename)); +} + ESPEAK_API espeak_ERROR espeak_SetVoiceByProperties(espeak_VOICE *voice_selector) { return status_to_espeak_error(espeak_ng_SetVoiceByProperties(voice_selector)); diff --git a/src/libespeak-ng/voices.c b/src/libespeak-ng/voices.c index 73a48fc4..3eca48f7 100644 --- a/src/libespeak-ng/voices.c +++ b/src/libespeak-ng/voices.c @@ -1466,6 +1466,45 @@ static void GetVoices(const char *path, int len_path_voices, int is_language_fil #pragma GCC visibility push(default) + +ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetVoiceByFile(const char *filename) +{ + espeak_VOICE *v; + int ix; + espeak_VOICE voice_selector; + char *variant_name; + static char buf[60]; + + strncpy0(buf, filename, 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 *)filename; // 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, 0x10) != NULL) { + if (variant_name[0] != 0) + LoadVoice(variant_name, 2); + + DoVoiceChange(voice); + voice_selector.languages = voice->language_name; + SetVoiceStack(&voice_selector, variant_name); + return ENS_OK; + } + + return ENS_VOICE_NOT_FOUND; +} + + ESPEAK_NG_API espeak_ng_STATUS espeak_ng_SetVoiceByName(const char *name) { espeak_VOICE *v;