|
|
|
|
|
|
|
|
|
|
|
|
|
|
static unsigned int my_unique_identifier = 0; |
|
|
static unsigned int my_unique_identifier = 0; |
|
|
static void *my_user_data = NULL; |
|
|
static void *my_user_data = NULL; |
|
|
static espeak_AUDIO_OUTPUT my_mode = AUDIO_OUTPUT_SYNCHRONOUS; |
|
|
|
|
|
static int synchronous_mode = 1; |
|
|
|
|
|
|
|
|
static espeak_ng_OUTPUT_MODE my_mode = ENOUTPUT_MODE_SYNCHRONOUS; |
|
|
static int out_samplerate = 0; |
|
|
static int out_samplerate = 0; |
|
|
static int voice_samplerate = 22050; |
|
|
static int voice_samplerate = 22050; |
|
|
static espeak_ERROR err = EE_OK; |
|
|
static espeak_ERROR err = EE_OK; |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (my_mode) |
|
|
switch (my_mode) |
|
|
{ |
|
|
{ |
|
|
case AUDIO_OUTPUT_PLAYBACK: |
|
|
|
|
|
|
|
|
case ENOUTPUT_MODE_SPEAK_AUDIO: |
|
|
{ |
|
|
{ |
|
|
int event_type = 0; |
|
|
int event_type = 0; |
|
|
if (event) |
|
|
if (event) |
|
|
|
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
break; |
|
|
break; |
|
|
case AUDIO_OUTPUT_RETRIEVAL: |
|
|
|
|
|
|
|
|
case 0: |
|
|
if (synth_callback) |
|
|
if (synth_callback) |
|
|
synth_callback(outbuf, length, event); |
|
|
synth_callback(outbuf, length, event); |
|
|
break; |
|
|
break; |
|
|
case AUDIO_OUTPUT_SYNCHRONOUS: |
|
|
|
|
|
case AUDIO_OUTPUT_SYNCH_PLAYBACK: |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return a_wave_can_be_played == 0; // 1 = stop synthesis, -1 = error |
|
|
return a_wave_can_be_played == 0; // 1 = stop synthesis, -1 = error |
|
|
|
|
|
|
|
|
event_list[1].unique_identifier = unique_identifier; |
|
|
event_list[1].unique_identifier = unique_identifier; |
|
|
event_list[1].user_data = user_data; |
|
|
event_list[1].user_data = user_data; |
|
|
|
|
|
|
|
|
if (my_mode == AUDIO_OUTPUT_PLAYBACK) { |
|
|
|
|
|
|
|
|
if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) { |
|
|
while (1) { |
|
|
while (1) { |
|
|
espeak_ERROR a_error = event_declare(event_list); |
|
|
espeak_ERROR a_error = event_declare(event_list); |
|
|
if (a_error != EE_BUFFER_FULL) |
|
|
if (a_error != EE_BUFFER_FULL) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#endif |
|
|
#endif |
|
|
|
|
|
|
|
|
static void select_output(espeak_AUDIO_OUTPUT output_type) |
|
|
|
|
|
|
|
|
static void select_output(espeak_ng_OUTPUT_MODE output_mode) |
|
|
{ |
|
|
{ |
|
|
my_mode = output_type; |
|
|
|
|
|
|
|
|
my_mode = output_mode; |
|
|
my_audio = NULL; |
|
|
my_audio = NULL; |
|
|
synchronous_mode = 1; |
|
|
|
|
|
option_waveout = 1; // inhibit portaudio callback from wavegen.cpp |
|
|
option_waveout = 1; // inhibit portaudio callback from wavegen.cpp |
|
|
out_samplerate = 0; |
|
|
out_samplerate = 0; |
|
|
|
|
|
|
|
|
switch (my_mode) |
|
|
|
|
|
{ |
|
|
|
|
|
case AUDIO_OUTPUT_PLAYBACK: |
|
|
|
|
|
case AUDIO_OUTPUT_RETRIEVAL: |
|
|
|
|
|
synchronous_mode = 0; |
|
|
|
|
|
break; |
|
|
|
|
|
case AUDIO_OUTPUT_SYNCHRONOUS: |
|
|
|
|
|
break; |
|
|
|
|
|
case AUDIO_OUTPUT_SYNCH_PLAYBACK: |
|
|
|
|
|
|
|
|
if (output_mode == ENOUTPUT_MODE_SYNCHRONOUS | ENOUTPUT_MODE_SPEAK_AUDIO) { |
|
|
option_waveout = 0; |
|
|
option_waveout = 0; |
|
|
WavegenInitSound(); |
|
|
WavegenInitSound(); |
|
|
break; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
count_samples = 0; |
|
|
count_samples = 0; |
|
|
|
|
|
|
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
if (my_mode == AUDIO_OUTPUT_PLAYBACK) |
|
|
|
|
|
|
|
|
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 |
|
|
#endif |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
SpeakNextClause(NULL, text, 0); |
|
|
SpeakNextClause(NULL, text, 0); |
|
|
|
|
|
|
|
|
if (my_mode == AUDIO_OUTPUT_SYNCH_PLAYBACK) { |
|
|
|
|
|
|
|
|
if (my_mode == (ENOUTPUT_MODE_SYNCHRONOUS | ENOUTPUT_MODE_SPEAK_AUDIO)) { |
|
|
for (;;) { |
|
|
for (;;) { |
|
|
#ifdef PLATFORM_WINDOWS |
|
|
#ifdef PLATFORM_WINDOWS |
|
|
Sleep(300); // 0.3s |
|
|
Sleep(300); // 0.3s |
|
|
|
|
|
|
|
|
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 == AUDIO_OUTPUT_PLAYBACK) { |
|
|
|
|
|
|
|
|
if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) { |
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
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) |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (SpeakNextClause(NULL, NULL, 1) == 0) { |
|
|
if (SpeakNextClause(NULL, NULL, 1) == 0) { |
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
if (my_mode == AUDIO_OUTPUT_PLAYBACK) { |
|
|
|
|
|
|
|
|
if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) { |
|
|
if (dispatch_audio(NULL, 0, NULL) < 0) // TBD: test case |
|
|
if (dispatch_audio(NULL, 0, NULL) < 0) // TBD: test case |
|
|
return err = EE_INTERNAL_ERROR; |
|
|
return err = EE_INTERNAL_ERROR; |
|
|
} else |
|
|
} else |
|
|
|
|
|
|
|
|
} else |
|
|
} else |
|
|
fprintf(stderr, "Wrong version of espeak-data (expected 0x%x) at %s\n", version_phdata, path_home); |
|
|
fprintf(stderr, "Wrong version of espeak-data (expected 0x%x) at %s\n", version_phdata, path_home); |
|
|
} |
|
|
} |
|
|
select_output(output_type); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
switch (output_type) |
|
|
|
|
|
{ |
|
|
|
|
|
case AUDIO_OUTPUT_PLAYBACK: |
|
|
|
|
|
select_output(ENOUTPUT_MODE_SPEAK_AUDIO); |
|
|
|
|
|
break; |
|
|
|
|
|
case AUDIO_OUTPUT_RETRIEVAL: |
|
|
|
|
|
select_output(0); |
|
|
|
|
|
break; |
|
|
|
|
|
case AUDIO_OUTPUT_SYNCHRONOUS: |
|
|
|
|
|
select_output(ENOUTPUT_MODE_SYNCHRONOUS); |
|
|
|
|
|
break; |
|
|
|
|
|
case AUDIO_OUTPUT_SYNCH_PLAYBACK: |
|
|
|
|
|
select_output(ENOUTPUT_MODE_SYNCHRONOUS | ENOUTPUT_MODE_SPEAK_AUDIO); |
|
|
|
|
|
break; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
if (f_logespeak) |
|
|
if (f_logespeak) |
|
|
fprintf(f_logespeak, "INIT mode %d options 0x%x\n", output_type, options); |
|
|
fprintf(f_logespeak, "INIT mode %d options 0x%x\n", output_type, options); |
|
|
|
|
|
|
|
|
unique_identifier = &temp_identifier; |
|
|
unique_identifier = &temp_identifier; |
|
|
*unique_identifier = 0; |
|
|
*unique_identifier = 0; |
|
|
|
|
|
|
|
|
if (synchronous_mode) |
|
|
|
|
|
|
|
|
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) |
|
|
return sync_espeak_Synth(0, text, size, position, position_type, end_position, flags, user_data); |
|
|
return sync_espeak_Synth(0, text, size, position, position_type, end_position, flags, user_data); |
|
|
|
|
|
|
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
|
|
|
|
|
|
unique_identifier = &temp_identifier; |
|
|
unique_identifier = &temp_identifier; |
|
|
*unique_identifier = 0; |
|
|
*unique_identifier = 0; |
|
|
|
|
|
|
|
|
if (synchronous_mode) |
|
|
|
|
|
|
|
|
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) |
|
|
return sync_espeak_Synth_Mark(0, text, size, index_mark, end_position, flags, user_data); |
|
|
return sync_espeak_Synth_Mark(0, text, size, index_mark, end_position, flags, user_data); |
|
|
|
|
|
|
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
espeak_ERROR a_error = EE_OK; |
|
|
espeak_ERROR a_error = EE_OK; |
|
|
|
|
|
|
|
|
if (synchronous_mode) { |
|
|
|
|
|
|
|
|
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) { |
|
|
sync_espeak_Key(key); |
|
|
sync_espeak_Key(key); |
|
|
return EE_OK; |
|
|
return EE_OK; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
espeak_ERROR a_error; |
|
|
espeak_ERROR a_error; |
|
|
|
|
|
|
|
|
if (synchronous_mode) { |
|
|
|
|
|
|
|
|
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) { |
|
|
sync_espeak_Char(character); |
|
|
sync_espeak_Char(character); |
|
|
return EE_OK; |
|
|
return EE_OK; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
espeak_ERROR a_error; |
|
|
espeak_ERROR a_error; |
|
|
|
|
|
|
|
|
if (synchronous_mode) { |
|
|
|
|
|
|
|
|
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) { |
|
|
SetParameter(parameter, value, relative); |
|
|
SetParameter(parameter, value, relative); |
|
|
return EE_OK; |
|
|
return EE_OK; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
espeak_ERROR a_error; |
|
|
espeak_ERROR a_error; |
|
|
|
|
|
|
|
|
if (synchronous_mode) { |
|
|
|
|
|
|
|
|
if (my_mode & ENOUTPUT_MODE_SYNCHRONOUS) { |
|
|
sync_espeak_SetPunctuationList(punctlist); |
|
|
sync_espeak_SetPunctuationList(punctlist); |
|
|
return EE_OK; |
|
|
return EE_OK; |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
fifo_stop(); |
|
|
fifo_stop(); |
|
|
event_clear_all(); |
|
|
event_clear_all(); |
|
|
|
|
|
|
|
|
if (my_mode == AUDIO_OUTPUT_PLAYBACK) |
|
|
|
|
|
|
|
|
if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) |
|
|
wave_close(my_audio); |
|
|
wave_close(my_audio); |
|
|
#endif |
|
|
#endif |
|
|
embedded_value[EMBED_T] = 0; // reset echo for pronunciation announcements |
|
|
embedded_value[EMBED_T] = 0; // reset echo for pronunciation announcements |
|
|
|
|
|
|
|
|
ESPEAK_API int espeak_IsPlaying(void) |
|
|
ESPEAK_API int espeak_IsPlaying(void) |
|
|
{ |
|
|
{ |
|
|
#ifdef USE_ASYNC |
|
|
#ifdef USE_ASYNC |
|
|
if ((my_mode == AUDIO_OUTPUT_PLAYBACK) && wave_is_busy(my_audio)) |
|
|
|
|
|
|
|
|
if ((my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) && wave_is_busy(my_audio)) |
|
|
return 1; |
|
|
return 1; |
|
|
|
|
|
|
|
|
return fifo_is_busy(); |
|
|
return fifo_is_busy(); |
|
|
|
|
|
|
|
|
fifo_terminate(); |
|
|
fifo_terminate(); |
|
|
event_terminate(); |
|
|
event_terminate(); |
|
|
|
|
|
|
|
|
if (my_mode == AUDIO_OUTPUT_PLAYBACK) { |
|
|
|
|
|
|
|
|
if (my_mode == ENOUTPUT_MODE_SPEAK_AUDIO) { |
|
|
wave_close(my_audio); |
|
|
wave_close(my_audio); |
|
|
wave_terminate(); |
|
|
wave_terminate(); |
|
|
out_samplerate = 0; |
|
|
out_samplerate = 0; |