| voice_samplerate = wvoice->samplerate; | voice_samplerate = wvoice->samplerate; | ||||
| } | } | ||||
| #ifdef USE_ASYNC | |||||
| static int dispatch_audio(short *outbuf, int length, espeak_EVENT *event) | 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) | switch (my_mode) | ||||
| { | { | ||||
| case ENOUTPUT_MODE_SPEAK_AUDIO: | case ENOUTPUT_MODE_SPEAK_AUDIO: | ||||
| case ENOUTPUT_MODE_SPEAK_AUDIO | ENOUTPUT_MODE_SYNCHRONOUS: | |||||
| { | { | ||||
| int event_type = 0; | int event_type = 0; | ||||
| if (event) | if (event) | ||||
| err = ENS_AUDIO_ERROR; | err = ENS_AUDIO_ERROR; | ||||
| return -1; | 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 | |||||
| } | } | ||||
| } | } | ||||
| wave_write(my_audio, (char *)outbuf, 2*length); | wave_write(my_audio, (char *)outbuf, 2*length); | ||||
| } | } | ||||
| #ifdef USE_ASYNC | |||||
| while (event && a_wave_can_be_played) { | while (event && a_wave_can_be_played) { | ||||
| // TBD: some event are filtered here but some insight might be given | // TBD: some event are filtered here but some insight might be given | ||||
| // TBD: in synthesise.cpp for avoiding to create WORDs with size=0. | // TBD: in synthesise.cpp for avoiding to create WORDs with size=0. | ||||
| // TBD: the last one has its size=0. | // TBD: the last one has its size=0. | ||||
| if ((event->type == espeakEVENT_WORD) && (event->length == 0)) | if ((event->type == espeakEVENT_WORD) && (event->length == 0)) | ||||
| break; | 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; | break; | ||||
| usleep(10000); | |||||
| a_wave_can_be_played = fifo_is_command_enabled(); | |||||
| } | } | ||||
| #endif | |||||
| } | } | ||||
| break; | break; | ||||
| case 0: | case 0: | ||||
| return finished; | return finished; | ||||
| } | } | ||||
| #ifdef USE_ASYNC | |||||
| int sync_espeak_terminated_msg(uint32_t unique_identifier, void *user_data) | int sync_espeak_terminated_msg(uint32_t unique_identifier, void *user_data) | ||||
| { | { | ||||
| int finished = 0; | int finished = 0; | ||||
| option_waveout = 1; // inhibit portaudio callback from wavegen.cpp | option_waveout = 1; // inhibit portaudio callback from wavegen.cpp | ||||
| out_samplerate = 0; | 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 | // buflength is in mS, allocate 2 bytes per sample | ||||
| if ((buffer_length == 0) || (output_mode & ENOUTPUT_MODE_SPEAK_AUDIO)) | if ((buffer_length == 0) || (output_mode & ENOUTPUT_MODE_SPEAK_AUDIO)) | ||||
| buffer_length = 200; | buffer_length = 200; | ||||
| int length; | int length; | ||||
| int finished = 0; | int finished = 0; | ||||
| int count_buffers = 0; | int count_buffers = 0; | ||||
| #ifdef USE_ASYNC | |||||
| uint32_t a_write_pos = 0; | uint32_t a_write_pos = 0; | ||||
| #endif | |||||
| if ((outbuf == NULL) || (event_list == NULL)) | if ((outbuf == NULL) || (event_list == NULL)) | ||||
| return ENS_NOT_INITIALIZED; | return ENS_NOT_INITIALIZED; | ||||
| count_samples = 0; | count_samples = 0; | ||||
| #ifdef USE_ASYNC | |||||
| if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) | if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) | ||||
| a_write_pos = wave_get_write_position(my_audio); | a_write_pos = wave_get_write_position(my_audio); | ||||
| #endif | |||||
| if (translator == NULL) | if (translator == NULL) | ||||
| espeak_SetVoiceByName("default"); | espeak_SetVoiceByName("default"); | ||||
| SpeakNextClause(NULL, text, 0); | 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 (;;) { | for (;;) { | ||||
| out_ptr = outbuf; | out_ptr = outbuf; | ||||
| out_end = &outbuf[outbuf_size]; | out_end = &outbuf[outbuf_size]; | ||||
| event_list[event_list_ix].user_data = my_user_data; | event_list[event_list_ix].user_data = my_user_data; | ||||
| count_buffers++; | 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); | finished = create_events((short *)outbuf, length, event_list, a_write_pos); | ||||
| if (finished < 0) | if (finished < 0) | ||||
| return ENS_AUDIO_ERROR; | return ENS_AUDIO_ERROR; | ||||
| #endif | |||||
| } else if (synth_callback) | } else if (synth_callback) | ||||
| finished = synth_callback((short *)outbuf, length, event_list); | finished = synth_callback((short *)outbuf, length, event_list); | ||||
| if (finished) { | if (finished) { |