GNOME Bugzilla – Bug 535493
eSpeak driver 'say' method can block
Last modified: 2008-07-08 19:13:44 UTC
Test case: 1) run gnome-speech's test-speech application 2) Choose the eSpeak server/driver 3) Select 'm' for gender 4) Select 'all' to display all voices The test-speech application quickly lists about 27 voices and then pauses for each one thereafter. What should happen is that the test-speech should quickly list all the voices without pause. The immediate problem seems to be in the gnome-speech driver for eSpeak. In particular, espeaksynthesisdriver.c:espeak_synthesis_driver_say has a while(1) loop in it that looks like the following (the printf lines and the else clause were added by me for debugging): while(1) { a_error = espeak_Synth((char *) text, strlen((char*)text)+1, 0, POS_CHARACTER, 0, espeakCHARS_UTF8, &unique_identifier, user_data); if (a_error != EE_BUFFER_FULL) { printf("OK\n"); break; } else { printf("BUFFER FULL!!!!\n"); } usleep(20000); }; The effect of this loop is that it causes the 'say' command to block until the eSpeak buffer frees enough to let the espeak_Synth command work. Instead, the 'say' command should never block and should be asynchronous. There are a couple of approaches we could take here: 1) modify gnome-speech to queue things up rather than doing a while/sleep loop in 'say' or 2) increase eSpeak's buffer size to lower the likelihood of the buffer getting full. Modifying the gnome-speech driver for eSpeak might be the best option from a technical standpoint, but it might be complex to implement. The DECtalk synthesis driver, however, seems to do this by processing synthesis operations in a gidle handler. It could possibly be used as a model. Modifying eSpeak itself would be rather simple (bump eSpeak's fifo.cpp:MAX_NODE_COUNTER value up), but would really just be a bandaid.
I tried changing the value of MAX_NODE_COUNTER from 200 to 2000 in espeak's fifo.cpp file with no luck. It looks like changing gnome-speech will probably be the only solution. I'm currently looking at gnome-speech code in an attempt to make the suggested fix. (In reply to comment #0) > Test case: > > 1) run gnome-speech's test-speech application > 2) Choose the eSpeak server/driver > 3) Select 'm' for gender > 4) Select 'all' to display all voices > > The test-speech application quickly lists about 27 voices and then pauses for > each one thereafter. What should happen is that the test-speech should quickly > list all the voices without pause. > > The immediate problem seems to be in the gnome-speech driver for eSpeak. In > particular, espeaksynthesisdriver.c:espeak_synthesis_driver_say has a while(1) > loop in it that looks like the following (the printf lines and the else clause > were added by me for debugging): > > while(1) > { > a_error = espeak_Synth((char *) text, strlen((char*)text)+1, > 0, POS_CHARACTER, 0, espeakCHARS_UTF8, > &unique_identifier, user_data); > if (a_error != EE_BUFFER_FULL) > { > printf("OK\n"); > break; > } > else { > printf("BUFFER FULL!!!!\n"); > } > usleep(20000); > }; > > The effect of this loop is that it causes the 'say' command to block until the > eSpeak buffer frees enough to let the espeak_Synth command work. Instead, the > 'say' command should never block and should be asynchronous. > > There are a couple of approaches we could take here: 1) modify gnome-speech to > queue things up rather than doing a while/sleep loop in 'say' or 2) increase > eSpeak's buffer size to lower the likelihood of the buffer getting full. > > Modifying the gnome-speech driver for eSpeak might be the best option from a > technical standpoint, but it might be complex to implement. The DECtalk > synthesis driver, however, seems to do this by processing synthesis operations > in a gidle handler. It could possibly be used as a model. > > Modifying eSpeak itself would be rather simple (bump eSpeak's > fifo.cpp:MAX_NODE_COUNTER value up), but would really just be a bandaid. >
(In reply to comment #1) > I'm currently looking at gnome-speech code in an attempt to make the suggested > fix. Thanks Kenny! Please let me know how work progresses here. This is something I'd like to see fixed for GNOME 2.22.3 if it can be done. :-)
Created attachment 112573 [details] [review] Patch to use a speech queue for espeak-synthesis-driver Here's a patch that enqueues calls to say and handles them on the gidle thread. Seems to work OK for me and I'm not seeing the blocked calls any longer. Kenny can you give this a shot?
Committed for 0.4.20.