我使用Java 6运行Ubuntu10.10,无法让FreeTTS输出任何音频。我现在已经在3台不同的电脑上试过了,甚至让我的一个朋友在他的Ubuntu上试用,他也遇到了同样的问题。绝对没有显示错误,在获得MBROLA之后,我甚至不再收到关于没有检测到MBROLA声音的警告。诸如此类..。
使用同一台计算机,我运行了一个虚拟盒并启动了Windows,在运行HelloWorld.jar和TTSHelloWorld.jar时,我实际上能够获得音频,但是当我尝试输入自己的文本时,freetts.jar仍然保持沉默。
我用的命令。
java -jar lib/freetts.jar -text Hello
当我点击enter时,它会启动,并给我丢失的MBROLA警告信息,但现在它就一直在那里,直到我CTRL来阻止它。
我不明白我做错了什么,为什么没有其他人有这个问题,当我在每台电脑上解释它时,它在Windows上有点工作。有谁可以帮我?
谢谢,
约翰
发布于 2011-06-07 09:43:41
我不确定您是否已经解决了这个问题,但是我遇到了同样的问题(Ubuntu10.10/ JavaSE6)。在对com.sun.speech.freetts.audio.JavaStreamingAudioPlayer.中的FreeTTS源代码进行了一些调查之后,我发现了一个死锁的罪魁祸首。这个死锁发生在打开一条线并且该行是org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine类型(这很可能是Ubuntu10.10w JavaSE6中的默认值)时发生的。因为您总是希望打开一条线路来获取音频,所以这种死锁总是会发生的。
造成这种死锁的原因在于,在JavaStreamingAudioPlayer中有一个关于Line的假设,即所有LineListeners都会被通知一个与调用Line.open()相同的线程类型打开的LineEvent,或者在打开了Line.open()之后(对Line.open()的调用可以返回)。PulseAudioSourceDataLine的情况并非如此;它首先从PulseAudio事件线程调用所有LineListeners,然后等待它们全部返回,然后从打开的调用返回。通过JavaStreamingAudioPlayer强制Line.open()调用周围的同步,以及处理特定的LineListener (该任务是查看Lineís是否真的打开),就会发生死锁。
为了解决这个问题,我选择的解决方法是实现一个没有这个问题的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: ...我删除了两个同步块,而不是确保两个部分相互排除,而是使用一个信号量来表示实际上该行是打开的。当然,这并不是必要的,因为PulseAudioSourceDataLine已经保证在返回时打开,但是当在另一个平台上测试相同的代码时,它更有可能发挥良好的作用。我没有深入研究代码,不足以说明当您同时通过多个线程打开/关闭/打开行时会发生什么。如果要这样做,您可能会看到对JavaStreamingAudioPlayer的更大的重写;)。
最后,在创建了新的AudioPlayer之后,您必须指示FreeTTS使用您的实现,而不是默认的JavaStreamingAudioPlayer。这可以通过使用
System.setProperty("com.sun.speech.freetts.voice.defaultAudioPlayer", "classpath.to.your.AudioPlayer");在你代码的早期位置。
希望这一切都对你有用。
发布于 2012-07-17 01:17:02
我是一个学生,他一直试图让FreeTTS在其Ubuntu上工作一周。最后我在这里找到了答案:谢谢你!
您的回答是完美的,但是您没有将您的实现放在这里,这花了我一个小时的时间来理解JavaStreamingAudioPlayer类中发生了什么。为了帮助那些没有在一个完全未知的Java代码中使用“潜水”(我还是学生)的人,我会把我的代码放在这里,希望它能帮助其他人:)。
首先,一个更详细的解释:在第152号线周围,JavaStreamingAudioPlayer打开一条线。但是,这个操作可能需要一些时间,所以在使用它之前,它希望检查它是否打开。在当前的实现中,使用的解决方案是创建一个侦听这一行的LineListener,然后休眠(使用线程的wait()方法)。
LineListener将使用notifyAll()“唤醒”主线程,并且只有当它接收到类型为"OPEN“的LineEvent时才会这样做,这将保证行已经打开。
但是,正如hakvroot在这里解释的那样,问题是,由于Ubuntu使用的DataLine的特定行为,从未发送通知。
因此,我删除了代码的同步、等待()和notifyAll()部分,但作为hakvroot,您的JavaStreamingAudioPlayer可能在打开它之前尝试使用它:您需要等待使用新机制的确认,以停止JavaStreamingAudioPlayer,并在确认到达后唤醒它。
因此,我使用了havkroot使用的信号量(关于这个锁系统的解释,请参阅Javadoc ),它由一个堆栈启动:
H 210F 211。这是我的密码:
声明一个信号量变量:
private Semaphore hackSemaphore;在构造函数中启动它:
hackSemaphore = new Semaphore(1);然后是要替换的第一部分(参见hakvroot以查看将其放在何处):
line = (SourceDataLine) AudioSystem.getLine(info);
line.addLineListener(new JavaStreamLineListener());
line.open(format, AUDIO_BUFFER_SIZE);
hackSemaphore.acquire();
hackSemaphore.acquire();
opened = true;
hackSemaphore.release();第二部分:
public void update(LineEvent event) {
if (event.getType().equals(LineEvent.Type.OPEN)) {
hackSemaphore.release();
}
}发布于 2012-07-03 16:45:39
我想Ubuntu12.04/OpenJDK-6也有同样的问题,执行会卡在Voice.allocate()中,没有错误,也没有响应。我尝试使用Oracle/SunJDK-6而不是OpenJDK,它运行得很好。
在Ubuntu上安装SunJDK并将其配置为默认http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/的很好的指南
https://stackoverflow.com/questions/5501394
复制相似问题