2011-03-31 65 views
9

我使用Java 6运行Ubuntu 10.10,无法获得FreeTTS输出任何音频。我现在已经在3台不同的电脑上试过了,甚至还要求我的一个好友在他的Ubuntu PC上试用它,他也遇到了同样的问题。在获得MBROLA后,我绝对不会再收到有关未检测到MBROLA声音的警告,因此绝对不会显示任何错误。等等。FreeTTS没有音频Linux的Ubuntu的 - 没有错误

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

我使用的命令。

Java的罐子的lib/freetts.jar -text你好

当我击进入它启动,并经常给我失踪MBROLA警告消息,但现在它只是坐在那里,直到我CTRL- C来阻止它。

我不明白我在做什么错,为什么没有人有这个问题,当我在每台计算机上展示它时,它在Windows上的工作方式都有所不同。谁能帮我?

感谢,

约翰

+0

我你也可以在这里看到:https://bugs.launchpad.net/communication/+bug/920734 – 2013-01-08 22:34:16

回答

10

我不知道您是否已经成功地解决了这一个,但我遇到了同样的问题(Ubuntu的10.10/JavaSE6)。在对FreeTTS源码进行了一些调查后,我在com.sun.speech.freetts.audio.JavaStreamingAudioPlayer中发现了一个死锁的罪魁祸首。当打开Line并且Line的类型为org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine(这可能是Ubuntu 10.10和JavaSE6中的默认值)时,会发生此死锁。既然你总是想打开一条线来获取音频,这个死锁总是会发生。

这个死锁的原因在于,在JavaStreamingAudioPlayer中对Line进行了一个假设,即所有的LineListeners都会被调用Line.open()时从同一个Thread中得到一个类型为LineEvent的通知,或Line已打开后(以及对Line.open()的调用可返回)。 PulseAudioSourceDataLine不是这种情况;它首先调用PulseAudio事件Thread中的所有LineListeners,等待它们全部返回,然后从打开的调用中返回。使用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: ... 

我除去两个同步块和代替确保两个部分相互排除我使用的信号量的信号,该线实际上是开放的。当然,这并不是必须的,因为PulseAudioSourceDataLine已经保证在返回时打开,但当在另一个平台上测试相同的代码时,它更可能发挥出色。我没有深入研究代码,只是说当你同时打开/关闭/打开多个线程时会发生什么。如果你打算这样做,你可能会考虑对JavaStreamingAudioPlayer进行更大的重写;)。

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

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

在代码的早期某处。

希望这一切都适合你。

+0

当我看到这些答案时,我只想死。上帝啊,这到底是为什么?为什么我没有这种聪明的头脑?谢谢你的真棒:-) – Nabin 2015-10-18 15:53:22

1

我猜在Ubuntu 12.04/OpenJDK-6上有同样的问题,执行卡在Voice.allocate()中,没有错误,也没有响应。 我尝试使用Oracle/Sun JDK-6而不是OpenJDK,并且它工作正常。

P.S.在Ubuntu上安装SunJDK和配置为默认的好的指南 http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/

10

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

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

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

LineListener会使用notifyAll()“唤醒”主线程,并且只有当它收到一个类型为“OPEN”的LineEvent时才会这样做,这将保证该线已被打开。

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

因此,我删除了代码的同步wait()和notifyAll()部分,但作为hakvroot,那么JavaStreamingAudioPlayer可能会在打开它之前尝试使用您的Line:您需要等待带有新机制的确认停止JavaStreamingAudioPlayer并在稍后确认到达时将其唤醒。

因此,我使用的信号量,其havkroot使用(参见的Javadoc此锁定系统上的解释)被1个栈启动:

  • 当线被打开它获得一个叠层(所以0遗体)

  • 当它要利用它试图收购另一行(因此被停止)

  • 当听者得到我们正在寻找的事件,它释放的信号

  • 这释放了JavaStreamingAudioPlayer谁可以去下一部分

  • 不要忘记再次释放信号量,因此再次有1堆下一行开

这里是我的代码:

声明一个信号变量:

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(); 
     } 
    } 
+2

非常感谢你这么明确的解释。我已将您的修补程序转入我的FreeTTS副本。你可以在这里看到/使用补丁:https://github.com/timabell/FreeTTS/commit/254086f22f0f53d6456a494826e72b7abab4d8bf - 学生现在是老师:-)我已经测试了helloworld jar文件,并且使用这个补丁和freeTTS不再挂在openJdk下。 – 2013-01-09 01:36:05

+2

@Tim很好的工作。我已经向Ubuntu报告了这个bug [这里](https://bugs.launchpad.net/ubuntu/+source/freetts/+bug/1191512)。请投下您的投票。 – HRJ 2013-06-16 12:50:02

+0

完成! (如果我理解启动板,有时我不相信)。谢谢@HRJ – 2013-06-17 22:18:43