This logic was implemented to limit the number of audio events sent to a device, but the logic is not too relevant in practice (these calls return 0 most of the time), and the logic is broken (e.g. when calling Synthesize with a very long block of text).master
| @@ -266,44 +266,6 @@ static int sleep_until_timeout_or_stop_request(uint32_t time_in_ms) | |||
| return a_stop_is_required; | |||
| } | |||
| // Asked for the time interval required for reaching the sample. | |||
| // If the stream is opened but the audio samples are not played, | |||
| // a timeout is started. | |||
| static int get_remaining_time(uint32_t sample, uint32_t *time_in_ms, int *stop_is_required) | |||
| { | |||
| int err = 0; | |||
| *stop_is_required = 0; | |||
| int i = 0; | |||
| for (i = 0; i < MAX_ACTIVITY_CHECK && (*stop_is_required == 0); i++) { | |||
| err = wave_get_remaining_time(sample, time_in_ms); | |||
| if (err || // if err, stream not available: quit | |||
| wave_is_busy(NULL) || // if wave is busy, time_in_ms is known: quit | |||
| (*time_in_ms == 0)) { // if wave is not busy but remaining time == 0, event is reached: quit | |||
| break; | |||
| } | |||
| // stream opened but not active | |||
| // | |||
| // Several possible states: | |||
| // * the stream is opened but not yet started: | |||
| // | |||
| // wait for the start of stream | |||
| // | |||
| // * some samples have already been played, | |||
| // ** the end of stream is reached | |||
| // ** or there is an underrun | |||
| // | |||
| // wait for the close of stream | |||
| *stop_is_required = sleep_until_timeout_or_stop_request(ACTIVITY_TIMEOUT); | |||
| } | |||
| return err; | |||
| } | |||
| static void *polling_thread(void *p) | |||
| { | |||
| (void)p; // unused | |||
| @@ -338,41 +300,26 @@ static void *polling_thread(void *p) | |||
| espeak_EVENT *event = (espeak_EVENT *)(head->data); | |||
| assert(event); | |||
| uint32_t time_in_ms = 0; | |||
| int err = get_remaining_time((uint32_t)event->sample, | |||
| &time_in_ms, | |||
| &a_stop_is_required); | |||
| if (a_stop_is_required > 0) | |||
| break; | |||
| else if (err != 0) { | |||
| // No available time: the event is deleted. | |||
| a_status = pthread_mutex_lock(&my_mutex); | |||
| event_delete((espeak_EVENT *)pop()); | |||
| a_status = pthread_mutex_unlock(&my_mutex); | |||
| } else if (time_in_ms == 0) { // the event is already reached. | |||
| if (my_callback) { | |||
| event_notify(event); | |||
| // the user_data (and the type) are cleaned to be sure | |||
| // that MSG_TERMINATED is called twice (at delete time too). | |||
| event->type = espeakEVENT_LIST_TERMINATED; | |||
| event->user_data = NULL; | |||
| } | |||
| a_status = pthread_mutex_lock(&my_mutex); | |||
| event_delete((espeak_EVENT *)pop()); | |||
| a_status = pthread_mutex_unlock(&my_mutex); | |||
| if (my_callback) { | |||
| event_notify(event); | |||
| // the user_data (and the type) are cleaned to be sure | |||
| // that MSG_TERMINATED is called twice (at delete time too). | |||
| event->type = espeakEVENT_LIST_TERMINATED; | |||
| event->user_data = NULL; | |||
| } | |||
| a_status = pthread_mutex_lock(&my_mutex); | |||
| event_delete((espeak_EVENT *)pop()); | |||
| a_status = pthread_mutex_unlock(&my_mutex); | |||
| a_stop_is_required = 0; | |||
| a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); | |||
| if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
| ; | |||
| } else | |||
| a_stop_is_required = 0; | |||
| a_status = sem_getvalue(&my_sem_stop_is_required, &a_stop_is_required); | |||
| if ((a_status == 0) && (a_stop_is_required > 0)) { | |||
| while (0 == sem_trywait(&my_sem_stop_is_required)) | |||
| ; | |||
| } else | |||
| a_stop_is_required = 0; | |||
| } else // The event will be notified soon: sleep until timeout or stop request | |||
| a_stop_is_required = sleep_until_timeout_or_stop_request(time_in_ms); | |||
| } | |||
| a_status = pthread_mutex_lock(&my_mutex); | |||
| @@ -66,7 +66,6 @@ uint32_t wave_port_get_write_position(void *theHandler); | |||
| void wave_port_flush(void *theHandler); | |||
| void wave_port_set_callback_is_output_enabled(t_wave_callback *cb); | |||
| void *wave_port_test_get_write_buffer(); | |||
| int wave_port_get_remaining_time(uint32_t sample, uint32_t *time); | |||
| // wave_pulse.cpp | |||
| int is_pulse_running(); | |||
| @@ -79,7 +78,6 @@ uint32_t wave_pulse_get_write_position(void *theHandler); | |||
| void wave_pulse_flush(void *theHandler); | |||
| void wave_pulse_set_callback_is_output_enabled(t_wave_callback *cb); | |||
| void *wave_pulse_test_get_write_buffer(); | |||
| int wave_pulse_get_remaining_time(uint32_t sample, uint32_t *time); | |||
| // wrappers | |||
| void *wave_open(int srate, const char *device) | |||
| @@ -147,14 +145,6 @@ void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
| wave_port_set_callback_is_output_enabled(cb); | |||
| } | |||
| int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| { | |||
| if (pulse_running) | |||
| return wave_pulse_get_remaining_time(sample, time); | |||
| else | |||
| return wave_port_get_remaining_time(sample, time); | |||
| } | |||
| // rename functions to be wrapped | |||
| #define wave_open wave_port_open | |||
| #define wave_write wave_port_write | |||
| @@ -164,7 +154,6 @@ int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| #define wave_get_write_position wave_port_get_write_position | |||
| #define wave_flush wave_port_flush | |||
| #define wave_set_callback_is_output_enabled wave_port_set_callback_is_output_enabled | |||
| #define wave_get_remaining_time wave_port_get_remaining_time | |||
| #endif | |||
| @@ -768,25 +757,6 @@ uint32_t wave_get_write_position(void *theHandler) | |||
| return myWritePosition; | |||
| } | |||
| int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| { | |||
| double a_time = 0; | |||
| if (!time || !pa_stream) | |||
| return -1; | |||
| if (sample > myReadPosition) { | |||
| // TBD: take in account time suplied by portaudio V18 API | |||
| a_time = sample - myReadPosition; | |||
| a_time = 0.5 + (a_time * 1000.0) / wave_samplerate; | |||
| } else | |||
| a_time = 0; | |||
| *time = (uint32_t)a_time; | |||
| return 0; | |||
| } | |||
| #else | |||
| void *wave_open(int srate, const char *device) | |||
| @@ -840,13 +810,4 @@ void wave_set_callback_is_output_enabled(t_wave_callback *cb) | |||
| (void)cb; // unused | |||
| } | |||
| int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| { | |||
| (void)sample; // unused | |||
| if (!time) return -1; | |||
| *time = (uint32_t)0; | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -35,14 +35,6 @@ extern int wave_is_busy(void *theHandler); | |||
| extern void wave_terminate(); | |||
| extern uint32_t wave_get_write_position(void *theHandler); | |||
| // Supply the remaining time in ms before the sample is played | |||
| // (or 0 if the event has been already played). | |||
| // sample: sample identifier | |||
| // time: supplied value in ms | |||
| // | |||
| // return 0 if ok or -1 otherwise (stream not opened). | |||
| extern int wave_get_remaining_time(uint32_t sample, uint32_t *time); | |||
| // set the callback which informs if the output is still enabled. | |||
| // Helpful if a new sample is waiting for free space whereas sound must be stopped. | |||
| typedef int (t_wave_callback)(void); | |||
| @@ -73,7 +73,6 @@ static t_wave_callback *my_callback_is_output_enabled = NULL; | |||
| #define wave_get_write_position wave_pulse_get_write_position | |||
| #define wave_flush wave_pulse_flush | |||
| #define wave_set_callback_is_output_enabled wave_pulse_set_callback_is_output_enabled | |||
| #define wave_get_remaining_time wave_pulse_get_remaining_time | |||
| // check whether we can connect to PulseAudio | |||
| #include <pulse/simple.h> | |||
| @@ -619,26 +618,4 @@ uint32_t wave_get_write_position(void *theHandler) | |||
| return a_timing_info.write_index; | |||
| } | |||
| int wave_get_remaining_time(uint32_t sample, uint32_t *time) | |||
| { | |||
| double a_time = 0; | |||
| if (!time || !stream) | |||
| return -1; | |||
| pa_timing_info a_timing_info = {0}; | |||
| pulse_playing(&a_timing_info); | |||
| if (sample > a_timing_info.read_index) { | |||
| // TBD: take in account time suplied by portaudio V18 API | |||
| a_time = sample - a_timing_info.read_index; | |||
| a_time = 0.5 + (a_time * 1000.0) / wave_samplerate; | |||
| } else | |||
| a_time = 0; | |||
| *time = (uint32_t)a_time; | |||
| return 0; | |||
| } | |||
| #endif | |||
| @@ -62,6 +62,8 @@ static uint32_t last_play_position = 0; | |||
| static uint32_t wave_samplerate; | |||
| static int wave_get_remaining_time(uint32_t sample, uint32_t *time); | |||
| // wave_open | |||
| // | |||
| // DESCRIPTION: | |||