FreeTTS没有音频linux ubuntu - 没有错误

Joh*_*ohn 9 java audio text-to-speech javasound freetts

我使用Java 6运行Ubuntu 10.10并且无法获取FreeTTS来输出任何音频.我现在已经在3台不同的计算机上试过它,甚至要求我的一个伙伴在他的Ubuntu PC上试用它并且他遇到了同样的问题.绝对没有显示错误,在获得MBROLA后我甚至不再收到关于没有检测到MBROLA声音的警告.等等等等等等..

使用同一台计算机,我运行了一个虚拟盒并启动了Windows XP,我实际上能够在运行HelloWorld.jar和TTSHelloWorld.jar时获得音频,但是当我尝试输入自己的文本时,freetts.jar仍然是静默的.

我使用的命令.

java -jar lib/freetts.jar -text你好

当我按下Enter键时,它启动并用来给我丢失的MBROLA警告信息,但现在它只是坐在那里直到我按CTRL-C来阻止它.

我不明白我做错了什么以及为什么没有其他人遇到这个问题,当我在每台计算机上展示它时,它在Windows上有所作为.谁能帮我?

谢谢,

约翰

小智 10

我不确定你是否已经设法解决了这个问题,但我遇到了同样的问题(Ubuntu 10.10/JavaSE6).在对FreeTTS源进行一些调查之后,我在com.sun.speech.freetts.audio.JavaStreamingAudioPlayer中找到了罪魁祸首,一个死锁.当Line打开并且Line的类型为org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine时(这可能是Ubuntu 10.10 w JavaSE6中的默认值),会发生此死锁.由于您总是希望打开一行来获取音频,因此将始终发生此死锁.

造成这种死锁的原因在于,在JavaStreamingAudioPlayer中有一个关于Line的假设,即所有LineListener都将被调用一个类型为Line的LineEvent,它与调用Line.open()的线程相同,或者在Line之后已打开(并且可以返回对Line.open()的调用).PulseAudioSourceDataLine不是这种情况; 它首先从PulseAudio事件Thread调用所有LineListener,等待所有LineListeners返回,然后从open调用返回.随着JavaStreamingAudioPlayer强制同步Line.open()的调用和特定LineListener的处理,该任务是查看Line是否实际打开,发生死锁.

我选择解决此问题的解决方法是实现没有此问题的AudioPlayer.我基本上复制了JavaStreamingAudioPlayer并修改了第196行和第646行的同步块(完整的参考资料来源: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: ...
Run Code Online (Sandbox Code Playgroud)

我删除了两个同步块,而不是确保两个部分相互排除,我使用信号量来表示Line实际上是打开的.当然,这并不是必需的,因为PulseAudioSourceDataLine已经保证在返回时打开,但是当在另一个平台上测试相同的代码时,它更有可能发挥得很好.我没有深入研究代码,足以说明当你多个线程同时打开/关闭/打开线路时会发生什么.如果您要这样做,您可能正在考虑更大的JavaStreamingAudioPlayer重写;).

最后,在创建新的AudioPlayer之后,您必须指示FreeTTS使用您的实现而不是默认的JavaStreamingAudioPlayer.这可以通过使用来完成

System.setProperty("com.sun.speech.freetts.voice.defaultAudioPlayer", "classpath.to.your.AudioPlayer");
Run Code Online (Sandbox Code Playgroud)

在代码的早期某处.

希望这一切都适合你.


Saa*_*raz 10

我是一名学生,他一直试图让FreeTTS在Ubuntu上工作一周.最后我在这里找到答案:非常感谢hakvroot!

你的答案是完美的,但你没有把你的实现,这花了我一个小时来了解JavaStreamingAudioPlayer类中发生了什么.为了帮助像我这样没有用于"潜水"的其他人在一个完全未知的Java代码(我仍然是学生),我会把我的代码放在这里,希望它能帮助其他人:).

首先,更详细的解释:在第152行附近,JavaStreamingAudioPlayer打开一个Line.但是,此操作可能需要一些时间,因此在使用之前,它需要检查它是否已打开.在当前实现中,使用的解决方案是创建一个LineListener,监听此行,然后进入休眠状态(使用线程的wait()方法).

LineListener将使用notifyAll()"唤醒"主线程,并且只有在收到类型为"OPEN"的LineEvent时才会这样做,这将保证线路已被打开.

但是正如hakvroot在这里解释的那样,问题是由于Ubuntu使用的DataLine的特定行为,因此永远不会发送通知.

所以我删除了代码的synchronized,wait()和notifyAll()部分但是作为hakvroot,那么你的JavaStreamingAudioPlayer可能会在它打开之前尝试使用你的Line:你需要等待使用新机制的确认来停止JavaStreamingAudioPlayer当确认到达时,将其唤醒.

所以我使用了havkroot使用的Semaphore(参见Javadoc对这个锁系统的解释)以1个堆栈启动:

  • 当线被打开时,它获得一个堆栈(因此0保持不变)

  • 当它想要使用它试图获取另一条线时(所以它被停止)

  • 当监听器获取我们正在寻找的事件时,它会释放信号量

  • 这将释放出可以用于下一部分的JavaStreamingAudioPlayer

  • 不要忘记再次释放信号量,这样它又有1个堆栈,可以打开下一行

这是我的代码:

声明一个Semaphore变量:

private Semaphore hackSemaphore;
Run Code Online (Sandbox Code Playgroud)

在构造函数中启动它:

hackSemaphore = new Semaphore(1);
Run Code Online (Sandbox Code Playgroud)

然后第一部分要更换(参见hakvroot看看它放在哪里):

            line = (SourceDataLine) AudioSystem.getLine(info);
            line.addLineListener(new JavaStreamLineListener());

            line.open(format, AUDIO_BUFFER_SIZE);
            hackSemaphore.acquire(); 
            hackSemaphore.acquire(); 
            opened = true;
            hackSemaphore.release();
Run Code Online (Sandbox Code Playgroud)

第二部分:

    public void update(LineEvent event) {
        if (event.getType().equals(LineEvent.Type.OPEN)) {
            hackSemaphore.release();
        }
    }
Run Code Online (Sandbox Code Playgroud)

  • 非常感谢你这么明确的解释.我把你的修复程序放到我的FreeTTS副本中.您可以在这里查看/使用补丁:https://github.com/timabell/FreeTTS/commit/254086f22f0f53d6456a494826e72b7abab4d8bf - 学生现在是老师:-)我已经测试了helloworld jar文件,并且不再使用此补丁和freeTTS挂在openJdk下. (2认同)
  • @Tim好工作.我已经向Ubuntu报告了这个错误[这里](https://bugs.launchpad.net/ubuntu/+source/freetts/+bug/1191512).请投票. (2认同)