static int SynthCallback(short *wav, int numsamples, espeak_EVENT *events) {//======================================================================== char fname[210]; if(quiet) return(0); // -q quiet mode if(wav == NULL) { CloseWavFile(); return(0); } while(events->type != 0) { if(events->type == espeakEVENT_SAMPLERATE) { samplerate = events->id.number; samples_split = samples_split_seconds * samplerate; } else if(events->type == espeakEVENT_SENTENCE) { // start a new WAV file when the limit is reached, at this sentence boundary if((samples_split > 0) && (samples_total > samples_split)) { CloseWavFile(); samples_total = 0; wavefile_count++; } } events++; } if(f_wavfile == NULL) { if(samples_split > 0) { sprintf(fname,"%s_%.2d%s",wavefile,wavefile_count+1,filetype); if(OpenWavFile(fname, samplerate) != 0) return(1); } else { if(OpenWavFile(wavefile, samplerate) != 0) return(1); } } if(numsamples > 0) { samples_total += numsamples; fwrite(wav,numsamples*2,1,f_wavfile); } 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); }