static int spk_construct(volatile SpeechSynthesizer *spk, char **parameters) { char *data_path, *voicename, *punctlist; int result; spk->setVolume = spk_setVolume; spk->setRate = spk_setRate; spk->setPitch = spk_setPitch; spk->setPunctuation = spk_setPunctuation; spk->drain = spk_drain; logMessage(LOG_INFO, "eSpeak-NG version %s", espeak_Info(NULL)); data_path = parameters[PARM_PATH]; if (data_path && !*data_path) data_path = NULL; result = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK, 0, data_path, 0); if (result < 0) { logMessage(LOG_ERR, "eSpeak-NG: initialization failed"); return 0; } voicename = parameters[PARM_VOICE]; if(!voicename || !*voicename) voicename = "en"; result = espeak_SetVoiceByName(voicename); if (result != EE_OK) { espeak_VOICE voice_select; memset(&voice_select, 0, sizeof(voice_select)); voice_select.languages = voicename; result = espeak_SetVoiceByProperties(&voice_select); } if (result != EE_OK) { logMessage(LOG_ERR, "eSpeak-NG: unable to load voice '%s'", voicename); return 0; } punctlist = parameters[PARM_PUNCTLIST]; if (punctlist && *punctlist) { wchar_t w_punctlist[strlen(punctlist) + 1]; int i = 0; while ((w_punctlist[i] = punctlist[i]) != 0) i++; espeak_SetPunctuationList(w_punctlist); } if (parameters[PARM_MAXRATE]) { int val = atoi(parameters[PARM_MAXRATE]); if (val > espeakRATE_MINIMUM) maxrate = val; } espeak_SetSynthCallback(SynthCallback); return 1; }
static TEspeakSuccess espeak_set_punctuation_list_from_utf8(const gchar *punct) { TEspeakSuccess result = ERROR; wchar_t *wc_punct = (wchar_t *) g_convert(punct, -1, "wchar_t", "utf-8", NULL, NULL, NULL); if (wc_punct != NULL) { espeak_ERROR ret = espeak_SetPunctuationList(wc_punct); if (ret == EE_OK) result = OK; g_free(wc_punct); } return result; }
int main(int argc, char **argv) { static struct option long_options[] = { { "help", no_argument, 0, 'h' }, { "stdin", no_argument, 0, 0x100 }, { "compile-debug", optional_argument, 0, 0x101 }, { "compile", optional_argument, 0, 0x102 }, { "punct", optional_argument, 0, 0x103 }, { "voices", optional_argument, 0, 0x104 }, { "stdout", no_argument, 0, 0x105 }, { "split", optional_argument, 0, 0x106 }, { "path", required_argument, 0, 0x107 }, { "phonout", required_argument, 0, 0x108 }, { "pho", no_argument, 0, 0x109 }, { "ipa", optional_argument, 0, 0x10a }, { "version", no_argument, 0, 0x10b }, { "sep", optional_argument, 0, 0x10c }, { "tie", optional_argument, 0, 0x10d }, { "compile-mbrola", optional_argument, 0, 0x10e }, { "compile-intonations", no_argument, 0, 0x10f }, { "compile-phonemes", optional_argument, 0, 0x110 }, { 0, 0, 0, 0 } }; FILE *f_text = NULL; char *p_text = NULL; FILE *f_phonemes_out = stdout; char *data_path = NULL; // use default path for espeak-ng-data int option_index = 0; int c; int ix; char *optarg2; int value; int flag_stdin = 0; int flag_compile = 0; int filesize = 0; int synth_flags = espeakCHARS_AUTO | espeakPHONEMES | espeakENDPAUSE; int volume = -1; int speed = -1; int pitch = -1; int wordgap = -1; int option_capitals = -1; int option_punctuation = -1; int phonemes_separator = 0; int phoneme_options = 0; int option_linelength = 0; int option_waveout = 0; espeak_VOICE voice_select; char filename[200]; char voicename[40]; char devicename[200]; #define N_PUNCTLIST 100 wchar_t option_punctlist[N_PUNCTLIST]; voicename[0] = 0; wavefile[0] = 0; filename[0] = 0; devicename[0] = 0; option_punctlist[0] = 0; while (true) { c = getopt_long(argc, argv, "a:b:d:f:g:hk:l:mp:qs:v:w:xXz", long_options, &option_index); // Detect the end of the options. if (c == -1) break; optarg2 = optarg; switch (c) { case 'b': // input character encoding, 8bit, 16bit, UTF8 if ((sscanf(optarg2, "%d", &value) == 1) && (value <= 4)) synth_flags |= value; else synth_flags |= espeakCHARS_8BIT; break; case 'd': strncpy0(devicename, optarg2, sizeof(devicename)); break; case 'h': printf("\n"); PrintVersion(); printf("%s", help_text); return 0; case 'k': option_capitals = atoi(optarg2); break; case 'x': phoneme_options |= espeakPHONEMES_SHOW; break; case 'X': phoneme_options |= espeakPHONEMES_TRACE; break; case 'm': synth_flags |= espeakSSML; break; case 'p': pitch = atoi(optarg2); break; case 'q': quiet = true; break; case 'f': strncpy0(filename, optarg2, sizeof(filename)); break; case 'l': option_linelength = atoi(optarg2); break; case 'a': volume = atoi(optarg2); break; case 's': speed = atoi(optarg2); break; case 'g': wordgap = atoi(optarg2); break; case 'v': strncpy0(voicename, optarg2, sizeof(voicename)); break; case 'w': option_waveout = 1; strncpy0(wavefile, optarg2, sizeof(filename)); break; case 'z': // remove pause from the end of a sentence synth_flags &= ~espeakENDPAUSE; break; case 0x100: // --stdin flag_stdin = 1; break; case 0x105: // --stdout option_waveout = 1; strcpy(wavefile, "stdout"); break; case 0x101: // --compile-debug case 0x102: // --compile if (optarg2 != NULL && *optarg2) { strncpy0(voicename, optarg2, sizeof(voicename)); flag_compile = c; quiet = true; break; } else { fprintf(stderr, "Voice name to '%s' not specified.\n", c == 0x101 ? "--compile-debug" : "--compile"); exit(EXIT_FAILURE); } case 0x103: // --punct option_punctuation = 1; if (optarg2 != NULL) { ix = 0; while ((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg2[ix]) != 0)) ix++; option_punctlist[N_PUNCTLIST-1] = 0; option_punctuation = 2; } break; case 0x104: // --voices espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS, 0, data_path, 0); DisplayVoices(stdout, optarg2); exit(0); case 0x106: // -- split if (optarg2 == NULL) samples_split_seconds = 30 * 60; // default 30 minutes else samples_split_seconds = atoi(optarg2) * 60; break; case 0x107: // --path data_path = optarg2; break; case 0x108: // --phonout if ((f_phonemes_out = fopen(optarg2, "w")) == NULL) fprintf(stderr, "Can't write to: %s\n", optarg2); break; case 0x109: // --pho phoneme_options |= espeakPHONEMES_MBROLA; break; case 0x10a: // --ipa phoneme_options |= espeakPHONEMES_IPA; if (optarg2 != NULL) { // deprecated and obsolete switch (atoi(optarg2)) { case 1: phonemes_separator = '_'; break; case 2: phonemes_separator = 0x0361; phoneme_options |= espeakPHONEMES_TIE; break; case 3: phonemes_separator = 0x200d; // ZWJ phoneme_options |= espeakPHONEMES_TIE; break; } } break; case 0x10b: // --version PrintVersion(); exit(0); case 0x10c: // --sep phoneme_options |= espeakPHONEMES_SHOW; if (optarg2 == 0) phonemes_separator = ' '; else utf8_in(&phonemes_separator, optarg2); if (phonemes_separator == 'z') phonemes_separator = 0x200c; // ZWNJ break; case 0x10d: // --tie phoneme_options |= (espeakPHONEMES_SHOW | espeakPHONEMES_TIE); if (optarg2 == 0) phonemes_separator = 0x0361; // default: combining-double-inverted-breve else utf8_in(&phonemes_separator, optarg2); if (phonemes_separator == 'z') phonemes_separator = 0x200d; // ZWJ break; case 0x10e: // --compile-mbrola { espeak_ng_InitializePath(data_path); espeak_ng_ERROR_CONTEXT context = NULL; espeak_ng_STATUS result = espeak_ng_CompileMbrolaVoice(optarg2, stdout, &context); if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, context); espeak_ng_ClearErrorContext(&context); return EXIT_FAILURE; } return EXIT_SUCCESS; } case 0x10f: // --compile-intonations { espeak_ng_InitializePath(data_path); espeak_ng_ERROR_CONTEXT context = NULL; espeak_ng_STATUS result = espeak_ng_CompileIntonation(stdout, &context); if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, context); espeak_ng_ClearErrorContext(&context); return EXIT_FAILURE; } return EXIT_SUCCESS; } case 0x110: // --compile-phonemes { espeak_ng_InitializePath(data_path); espeak_ng_ERROR_CONTEXT context = NULL; espeak_ng_STATUS result; if (optarg2) { result = espeak_ng_CompilePhonemeDataPath(22050, optarg2, NULL, stdout, &context); } else { result = espeak_ng_CompilePhonemeData(22050, stdout, &context); } if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, context); espeak_ng_ClearErrorContext(&context); return EXIT_FAILURE; } return EXIT_SUCCESS; } default: exit(0); } } espeak_ng_InitializePath(data_path); espeak_ng_ERROR_CONTEXT context = NULL; espeak_ng_STATUS result = espeak_ng_Initialize(&context); if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, context); espeak_ng_ClearErrorContext(&context); exit(1); } if (option_waveout || quiet) { // writing to a file (or no output), we can use synchronous mode result = espeak_ng_InitializeOutput(ENOUTPUT_MODE_SYNCHRONOUS, 0, devicename[0] ? devicename : NULL); samplerate = espeak_ng_GetSampleRate(); samples_split = samplerate * samples_split_seconds; espeak_SetSynthCallback(SynthCallback); if (samples_split) { char *extn; extn = strrchr(wavefile, '.'); if ((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) { strcpy(filetype, extn); *extn = 0; } } } else { // play the sound output result = espeak_ng_InitializeOutput(PLAYBACK_MODE, 0, devicename[0] ? devicename : NULL); samplerate = espeak_ng_GetSampleRate(); } if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, NULL); exit(EXIT_FAILURE); } if (voicename[0] == 0) strcpy(voicename, ESPEAKNG_DEFAULT_VOICE); result = espeak_ng_SetVoiceByName(voicename); if (result != ENS_OK) { memset(&voice_select, 0, sizeof(voice_select)); voice_select.languages = voicename; result = espeak_ng_SetVoiceByProperties(&voice_select); if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, NULL); exit(EXIT_FAILURE); } } if (flag_compile) { // This must be done after the voice is set espeak_ng_ERROR_CONTEXT context = NULL; espeak_ng_STATUS result = espeak_ng_CompileDictionary("", NULL, stderr, flag_compile & 0x1, &context); if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, context); espeak_ng_ClearErrorContext(&context); return EXIT_FAILURE; } return EXIT_SUCCESS; } // set any non-default values of parameters. This must be done after espeak_Initialize() if (speed > 0) espeak_SetParameter(espeakRATE, speed, 0); if (volume >= 0) espeak_SetParameter(espeakVOLUME, volume, 0); if (pitch >= 0) espeak_SetParameter(espeakPITCH, pitch, 0); if (option_capitals >= 0) espeak_SetParameter(espeakCAPITALS, option_capitals, 0); if (option_punctuation >= 0) espeak_SetParameter(espeakPUNCTUATION, option_punctuation, 0); if (wordgap >= 0) espeak_SetParameter(espeakWORDGAP, wordgap, 0); if (option_linelength > 0) espeak_SetParameter(espeakLINELENGTH, option_linelength, 0); if (option_punctuation == 2) espeak_SetPunctuationList(option_punctlist); espeak_SetPhonemeTrace(phoneme_options | (phonemes_separator << 8), f_phonemes_out); if (filename[0] == 0) { if ((optind < argc) && (flag_stdin == 0)) { // there's a non-option parameter, and no -f or --stdin // use it as text p_text = argv[optind]; } else { f_text = stdin; if (flag_stdin == 0) flag_stdin = 2; } } else { struct stat st; if (stat(filename, &st) != 0) { fprintf(stderr, "Failed to stat() file '%s'\n", filename); exit(EXIT_FAILURE); } filesize = GetFileLength(filename); f_text = fopen(filename, "r"); if (f_text == NULL) { fprintf(stderr, "Failed to read file '%s'\n", filename); exit(EXIT_FAILURE); } if (S_ISFIFO(st.st_mode)) { flag_stdin = 2; } } if (p_text != NULL) { int size; size = strlen(p_text); espeak_Synth(p_text, size+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); } else if (flag_stdin) { size_t max = 1000; if ((p_text = (char *)malloc(max)) == NULL) { espeak_ng_PrintStatusCodeMessage(ENOMEM, stderr, NULL); exit(EXIT_FAILURE); } if (flag_stdin == 2) { // line by line input on stdin or from FIFO while (fgets(p_text, max, f_text) != NULL) { p_text[max-1] = 0; espeak_Synth(p_text, max, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); // Allow subprocesses to use the audio data through pipes. fflush(stdout); } if (f_text != stdin) { fclose(f_text); } } else { // bulk input on stdin ix = 0; while (true) { if ((c = fgetc(stdin)) == EOF) break; p_text[ix++] = (char)c; if (ix >= (max-1)) { char *new_text = NULL; if (max <= SIZE_MAX - 1000) { max += 1000; new_text = (char *)realloc(p_text, max); } if (new_text == NULL) { free(p_text); espeak_ng_PrintStatusCodeMessage(ENOMEM, stderr, NULL); exit(EXIT_FAILURE); } p_text = new_text; } } if (ix > 0) { p_text[ix-1] = 0; espeak_Synth(p_text, ix+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); } } free(p_text); } else if (f_text != NULL) { if ((p_text = (char *)malloc(filesize+1)) == NULL) { espeak_ng_PrintStatusCodeMessage(ENOMEM, stderr, NULL); exit(EXIT_FAILURE); } fread(p_text, 1, filesize, f_text); p_text[filesize] = 0; espeak_Synth(p_text, filesize+1, 0, POS_CHARACTER, 0, synth_flags, NULL, NULL); fclose(f_text); free(p_text); } result = espeak_ng_Synchronize(); if (result != ENS_OK) { espeak_ng_PrintStatusCodeMessage(result, stderr, NULL); exit(EXIT_FAILURE); } if (f_phonemes_out != stdout) fclose(f_phonemes_out); CloseWavFile(); espeak_ng_Terminate(); return 0; }
int main (int argc, char **argv) //============================== { static struct option long_options[] = { /* These options set a flag. */ // {"verbose", no_argument, &verbose_flag, 1}, // {"brief", no_argument, &verbose_flag, 0}, /* These options don't set a flag. We distinguish them by their indices. */ {"help", no_argument, 0, 'h'}, {"stdin", no_argument, 0, 0x100}, {"compile-debug", optional_argument, 0, 0x101}, {"compile", optional_argument, 0, 0x102}, {"punct", optional_argument, 0, 0x103}, {"voices", optional_argument, 0, 0x104}, {"stdout", no_argument, 0, 0x105}, {"split", optional_argument, 0, 0x106}, {0, 0, 0, 0} }; static const char* err_load = "Failed to read "; FILE *f_text=NULL; char *p_text=NULL; int option_index = 0; int c; int ix; int flag_stdin = 0; int flag_compile = 0; int filesize = 0; int synth_flags = espeakCHARS_AUTO | espeakPHONEMES | espeakENDPAUSE; int volume = -1; int speed = -1; int pitch = -1; int wordgap = -1; int option_capitals = -1; int option_punctuation = -1; int option_phonemes = -1; int option_linelength = 0; int option_waveout = 0; char filename[120]; char voicename[40]; char voice_mbrola[20]; char dictname[40]; #define N_PUNCTLIST 100 wchar_t option_punctlist[N_PUNCTLIST]; voicename[0] = 0; voice_mbrola[0] = 0; dictname[0] = 0; wavefile[0] = 0; filename[0] = 0; option_punctlist[0] = 0; while(true) { c = getopt_long (argc, argv, "a:bf:g:hk:l:mp:qs:v:w:xXz", long_options, &option_index); /* Detect the end of the options. */ if (c == -1) break; switch (c) { case 'b': synth_flags |= espeakCHARS_8BIT; break; case 'h': printf("\n"); printf("eSpeak text-to-speech: %s\n%s",espeak_Info(NULL),help_text); exit(0); break; case 'k': option_capitals = atoi(optarg); break; case 'x': option_phonemes = 1; break; case 'X': option_phonemes = 2; break; case 'm': synth_flags |= espeakSSML; break; case 'p': pitch = atoi(optarg); break; case 'q': quiet = 1; break; case 'f': strncpy0(filename,optarg,sizeof(filename)); break; case 'l': option_linelength = atoi(optarg); break; case 'a': volume = atoi(optarg); break; case 's': speed = atoi(optarg); break; case 'g': wordgap = atoi(optarg); break; case 'v': strncpy0(voicename,optarg,sizeof(voicename)); break; case 'w': option_waveout = 1; strncpy0(wavefile,optarg,sizeof(filename)); break; case 'z': // remove pause from the end of a sentence synth_flags &= ~espeakENDPAUSE; break; case 0x100: // --stdin flag_stdin = 1; break; case 0x105: // --stdout option_waveout = 1; strcpy(wavefile,"stdout"); break; case 0x101: // --compile-debug case 0x102: // --compile strncpy0(voicename,optarg,sizeof(voicename)); flag_compile = c; quiet = 1; break; case 0x103: // --punct option_punctuation = 1; if(optarg != NULL) { ix = 0; while((ix < N_PUNCTLIST) && ((option_punctlist[ix] = optarg[ix]) != 0)) ix++; option_punctlist[N_PUNCTLIST-1] = 0; option_punctuation = 2; } break; case 0x104: // --voices espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,NULL,0); DisplayVoices(stdout,optarg); exit(0); case 0x106: // -- split if(optarg == NULL) samples_split = 30; // default 30 minutes else samples_split = atoi(optarg); break; default: exit(0); } } if(option_waveout || quiet) { // writing to a file (or no output), we can use synchronous mode samplerate = espeak_Initialize(AUDIO_OUTPUT_SYNCHRONOUS,0,NULL,0); samples_split = (samplerate * samples_split) * 60; espeak_SetSynthCallback(SynthCallback); if(samples_split) { char *extn; extn = strrchr(wavefile,'.'); if((extn != NULL) && ((wavefile + strlen(wavefile) - extn) <= 4)) { strcpy(filetype,extn); *extn = 0; } } else if(option_waveout) { if(OpenWavFile(wavefile,samplerate) != 0) exit(4); } } else { // play the sound output samplerate = espeak_Initialize(AUDIO_OUTPUT_PLAYBACK,0,NULL,0); } if(voicename[0] == 0) strcpy(voicename,"default"); if(espeak_SetVoiceByName(voicename) != EE_OK) { fprintf(stderr,"%svoice '%s'\n",err_load,voicename); exit(2); } if(flag_compile) { // This must be done after the voice is set espeak_CompileDictionary("", stderr, flag_compile & 0x1); exit(0); } // set any non-default values of parameters. This must be done after espeak_Initialize() if(speed > 0) espeak_SetParameter(espeakRATE,speed,0); if(volume >= 0) espeak_SetParameter(espeakVOLUME,volume,0); if(pitch >= 0) espeak_SetParameter(espeakPITCH,pitch,0); if(option_capitals >= 0) espeak_SetParameter(espeakCAPITALS,option_capitals,0); if(option_punctuation >= 0) espeak_SetParameter(espeakPUNCTUATION,option_punctuation,0); if(wordgap >= 0) espeak_SetParameter(espeakWORDGAP,wordgap,0); if(option_linelength > 0) espeak_SetParameter(espeakLINELENGTH,option_linelength,0); if(option_punctuation == 2) espeak_SetPunctuationList(option_punctlist); if(option_phonemes >= 0) espeak_SetPhonemeTrace(option_phonemes,stderr); if(filename[0]==0) { if((optind < argc) && (flag_stdin == 0)) { // there's a non-option parameter, and no -f or --stdin // use it as text p_text = argv[optind]; } else { f_text = stdin; if(flag_stdin == 0) { flag_stdin = 2; } } } else { filesize = GetFileLength(filename); f_text = fopen(filename,"r"); } if((f_text == NULL) && (p_text == NULL)) { fprintf(stderr,"%sfile '%s'\n",err_load,filename); exit(1); } if(p_text != NULL) { int size; size = strlen(p_text); espeak_Synth(p_text,size+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); } else if(flag_stdin) { int max = 1000; p_text = (char *)malloc(max); if(flag_stdin == 2) { // line by line input on stdin while(fgets(p_text,max,stdin) != NULL) { p_text[max-1] = 0; espeak_Synth(p_text,max,0,POS_CHARACTER,0,synth_flags,NULL,NULL); } } else { // bulk input on stdin ix = 0; while(!feof(stdin)) { p_text[ix++] = fgetc(stdin); if(ix >= (max-1)) { max += 1000; p_text = (char *)realloc(p_text,max); } } if(ix > 0) { p_text[ix-1] = 0; espeak_Synth(p_text,ix+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); } } } else if(f_text != NULL) { if((p_text = (char *)malloc(filesize+1)) == NULL) { fprintf(stderr,"Failed to allocate memory %d bytes",filesize); exit(3); } fread(p_text,1,filesize,f_text); p_text[filesize]=0; espeak_Synth(p_text,filesize+1,0,POS_CHARACTER,0,synth_flags,NULL,NULL); fclose(f_text); } espeak_Synchronize(); return(0); }