| @@ -86,15 +86,18 @@ void WVoiceChanged(voice_t *wvoice) | |||
| voice_samplerate = wvoice->samplerate; | |||
| } | |||
| #ifdef USE_ASYNC | |||
| static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) | |||
| { | |||
| int a_wave_can_be_played = fifo_is_command_enabled(); | |||
| int a_wave_can_be_played = 1; | |||
| #ifdef USE_ASYNC | |||
| if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) | |||
| a_wave_can_be_played = fifo_is_command_enabled(); | |||
| #endif | |||
| switch (my_mode) | |||
| { | |||
| case ENOUTPUT_MODE_SPEAK_AUDIO: | |||
| case ENOUTPUT_MODE_SPEAK_AUDIO | ENOUTPUT_MODE_SYNCHRONOUS: | |||
| { | |||
| int event_type = 0; | |||
| if (event) | |||
| @@ -115,8 +118,12 @@ static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) | |||
| err = ENS_AUDIO_ERROR; | |||
| return -1; | |||
| } | |||
| wave_set_callback_is_output_enabled(fifo_is_command_enabled); | |||
| event_init(); | |||
| #ifdef USE_ASYNC | |||
| if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) { | |||
| wave_set_callback_is_output_enabled(fifo_is_command_enabled); | |||
| event_init(); | |||
| } | |||
| #endif | |||
| } | |||
| } | |||
| @@ -124,6 +131,7 @@ static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) | |||
| wave_write(my_audio, (char *)outbuf, 2*length); | |||
| } | |||
| #ifdef USE_ASYNC | |||
| while (event && a_wave_can_be_played) { | |||
| // TBD: some event are filtered here but some insight might be given | |||
| // TBD: in synthesise.cpp for avoiding to create WORDs with size=0. | |||
| @@ -132,12 +140,16 @@ static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) | |||
| // TBD: the last one has its size=0. | |||
| if ((event->type == espeakEVENT_WORD) && (event->length == 0)) | |||
| break; | |||
| err = event_declare(event); | |||
| if (err != ENS_EVENT_BUFFER_FULL) | |||
| if ((my_mode & ENOUTPUT_MODE_SYNCHRONOUS) == 0) { | |||
| err = event_declare(event); | |||
| if (err != ENS_EVENT_BUFFER_FULL) | |||
| break; | |||
| usleep(10000); | |||
| a_wave_can_be_played = fifo_is_command_enabled(); | |||
| } else | |||
| break; | |||
| usleep(10000); | |||
| a_wave_can_be_played = fifo_is_command_enabled(); | |||
| } | |||
| #endif | |||
| } | |||
| break; | |||
| case 0: | |||
| @@ -175,6 +187,8 @@ static int create_events(short *outbuf, int length, espeak_EVENT *event_list, ui | |||
| return finished; | |||
| } | |||
| #ifdef USE_ASYNC | |||
| int sync_espeak_terminated_msg(uint32_t unique_identifier, void *user_data) | |||
| { | |||
| int finished = 0; | |||
| @@ -212,15 +226,6 @@ ESPEAK_NG_API espeak_ng_STATUS espeak_ng_InitializeOutput(espeak_ng_OUTPUT_MODE | |||
| option_waveout = 1; // inhibit portaudio callback from wavegen.cpp | |||
| out_samplerate = 0; | |||
| #ifdef USE_ASYNC | |||
| if (output_mode == (ENOUTPUT_MODE_SYNCHRONOUS | ENOUTPUT_MODE_SPEAK_AUDIO)) { | |||
| #else | |||
| if ((output_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | |||
| #endif | |||
| option_waveout = 0; | |||
| WavegenInitSound(); | |||
| } | |||
| // buflength is in mS, allocate 2 bytes per sample | |||
| if ((buffer_length == 0) || (output_mode & ENOUTPUT_MODE_SPEAK_AUDIO)) | |||
| buffer_length = 200; | |||
| @@ -362,9 +367,7 @@ static espeak_ng_STATUS Synthesize(unsigned int unique_identifier, const void *t | |||
| int length; | |||
| int finished = 0; | |||
| int count_buffers = 0; | |||
| #ifdef USE_ASYNC | |||
| uint32_t a_write_pos = 0; | |||
| #endif | |||
| if ((outbuf == NULL) || (event_list == NULL)) | |||
| return ENS_NOT_INITIALIZED; | |||
| @@ -376,49 +379,14 @@ static espeak_ng_STATUS Synthesize(unsigned int unique_identifier, const void *t | |||
| count_samples = 0; | |||
| #ifdef USE_ASYNC | |||
| if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) | |||
| a_write_pos = wave_get_write_position(my_audio); | |||
| #endif | |||
| if (translator == NULL) | |||
| espeak_SetVoiceByName("default"); | |||
| SpeakNextClause(NULL, text, 0); | |||
| #ifdef USE_ASYNC | |||
| if (my_mode == (ENOUTPUT_MODE_SYNCHRONOUS | ENOUTPUT_MODE_SPEAK_AUDIO)) { | |||
| #else | |||
| if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | |||
| #endif | |||
| bool continue_speaking = true; | |||
| while (continue_speaking) { | |||
| #ifdef PLATFORM_WINDOWS | |||
| Sleep(300); // 0.3s | |||
| #else | |||
| #ifdef USE_NANOSLEEP | |||
| struct timespec period; | |||
| struct timespec remaining; | |||
| period.tv_sec = 0; | |||
| period.tv_nsec = 300000000; // 0.3 sec | |||
| nanosleep(&period, &remaining); | |||
| #else | |||
| sleep(1); | |||
| #endif | |||
| #endif | |||
| do { | |||
| if (WcmdqUsed() > 0) | |||
| WavegenOpenSound(); | |||
| if (Generate(phoneme_list, &n_phoneme_list, 1) == 0) { | |||
| if (SpeakNextClause(NULL, NULL, 1) == 0) | |||
| continue_speaking = WavegenCloseSound() == 0; | |||
| } | |||
| } while (skipping_text); | |||
| } | |||
| return ENS_OK; | |||
| } | |||
| for (;;) { | |||
| out_ptr = outbuf; | |||
| out_end = &outbuf[outbuf_size]; | |||
| @@ -432,12 +400,10 @@ static espeak_ng_STATUS Synthesize(unsigned int unique_identifier, const void *t | |||
| event_list[event_list_ix].user_data = my_user_data; | |||
| count_buffers++; | |||
| if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) { | |||
| #ifdef USE_ASYNC | |||
| if ((my_mode & ENOUTPUT_MODE_SPEAK_AUDIO) == ENOUTPUT_MODE_SPEAK_AUDIO) { | |||
| finished = create_events((short *)outbuf, length, event_list, a_write_pos); | |||
| if (finished < 0) | |||
| return ENS_AUDIO_ERROR; | |||
| #endif | |||
| } else if (synth_callback) | |||
| finished = synth_callback((short *)outbuf, length, event_list); | |||
| if (finished) { | |||