FreeTTS no audio linux ubuntu - no errors

后端 未结 3 1420
情话喂你
情话喂你 2020-12-31 14:25

I am running Ubuntu 10.10 using Java 6 and can not get FreeTTS to output any audio. I have tried it now on 3 different computers and even asked a buddy of mine to try it on

3条回答
  •  借酒劲吻你
    2020-12-31 15:03

    I'm not sure whether you already managed to solve this one, but I ran into the same problem (Ubuntu 10.10 / JavaSE6). After some investigation of the FreeTTS source I found the culprit, a deadlock, in com.sun.speech.freetts.audio.JavaStreamingAudioPlayer. This deadlock occurs when a Line is opened and the Line is of the type org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine (which is likely to be the default in Ubuntu 10.10 w JavaSE6). Since you'd always want to open a Line to get audio out, this deadlock will always occur.

    The cause of this deadlock lies in the fact that in the JavaStreamingAudioPlayer an assumption is made about Line, namely that all LineListeners will be notified of a LineEvent of type open from the same Thread as Line.open() was called, or after the Line has been opened (and the call to Line.open() can return). This is not the case for the PulseAudioSourceDataLine; it first calls all LineListeners from the PulseAudio event Thread, waits for all of them to return and then returns from the open call. With the JavaStreamingAudioPlayer forcing synchronization around the call of Line.open() and the handling of a specific LineListener which task is to see whether the Line ís actually open, the deadlock occurs.

    The workaround I chose for solving this problem is to implement an AudioPlayer which doesn't has this problem. I basically copied JavaStreamingAudioPlayer and altered the synchronization blocks on line 196 and line 646 ( full source for reference : http://www.javadocexamples.com/java_source/com/sun/speech/freetts/audio/JavaStreamingAudioPlayer.java.html ).

    ___: // This is the actual JavaStreamAudioPlayer source, not the fix
    195: ...
    196:     synchronized (openLock) {
    197:         line.open(format, AUDIO_BUFFER_SIZE); // Blocks due to line 646
    198:         try {
    199:             openLock.wait();
    200:         } catch (InterruptedException ie) {
    201:             ie.printStackTrace();
    202:     }
    203: ...
    
    643: ...
    644: public void update(LineEvent event) {
    645:     if (event.getType().equals(LineEvent.Type.OPEN)) {
    646:         synchronized (openLock) { // Blocks due to line 196
    647:             openLock.notifyAll();
    648:         }
    649:     }
    650: }
    651: ...
    

    I removed both synchronization blocks and instead of ensuring both parts are mutually excluded I used a Semaphore to signal that the Line is in fact open. Of course this is not really a necessity since the PulseAudioSourceDataLine already guarantees being opened upon returning, but it is more likely to play nice when testing the same code on another platform. I didn't dive into the code long enough to say what is going to happen when you open/close/open the line by multiple Threads at the same time. If you're going to do this you are probably looking at a larger rewrite of the JavaStreamingAudioPlayer ;).

    Finally, after you have created your new AudioPlayer you'll have to instruct FreeTTS to use your implementation rather than the default JavaStreamingAudioPlayer. This can be done by using

    System.setProperty("com.sun.speech.freetts.voice.defaultAudioPlayer", "classpath.to.your.AudioPlayer");
    

    somewhere early in your code.

    Hopefully this all works for you.

提交回复
热议问题