简体   繁体   English

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

[英]FreeTTS no audio linux ubuntu - no errors

I am running Ubuntu 10.10 using Java 6 and can not get FreeTTS to output any audio. 我使用Java 6运行Ubuntu 10.10并且无法获取FreeTTS来输出任何音频。 I have tried it now on 3 different computers and even asked a buddy of mine to try it on his Ubuntu PC and he had the same problem. 我现在已经在3台不同的计算机上试过它,甚至要求我的一个伙伴在他的Ubuntu PC上试用它并且他遇到了同样的问题。 There is absolutly no errors that are displayed, after getting the MBROLA i no longer even get the warning about No MBROLA voices detected. 绝对没有显示错误,在获得MBROLA后我甚至不再收到关于没有检测到MBROLA声音的警告。 blah blah blah.. 等等等等等等..

Using the same computer I ran a virtual box and started Windows XP, i was actually able to get audio when running the HelloWorld.jar and TTSHelloWorld.jar however the freetts.jar is still silent when I try to input my own text. 使用同一台计算机,我运行了一个虚拟盒并启动了Windows XP,我实际上能够在运行HelloWorld.jar和TTSHelloWorld.jar时获得音频,但是当我尝试输入自己的文本时,freetts.jar仍然是静默的。

Command I use. 我使用的命令。

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

When I hit enter it starts up and used to give me the missing MBROLA warning message but now it just sits there until i CTRL-C to stop it. 当我按下Enter键时,它启动并用来给我丢失的MBROLA警告信息,但现在它只是坐在那里直到我按CTRL-C来阻止它。

I dont understand what I am doing wrong and why nobody else is having this problem, when I expierence it on every computer, well it works somewhat on Windows. 我不明白我做错了什么以及为什么没有其他人遇到这个问题,当我在每台计算机上展示它时,它在Windows上有所作为。 Can anyone Help me? 谁能帮我?

Thanks, 谢谢,

John 约翰

I am a student who has been trying to make FreeTTS working on its Ubuntu for one week. 我是一名学生,他一直试图让FreeTTS在Ubuntu上工作一周。 And finally I found the answer here : thank you so much hakvroot ! 最后我在这里找到答案:非常感谢hakvroot!

Your answer was perfect but you did not put your implementation and this took me quite one hour to understand what was going on in the JavaStreamingAudioPlayer class. 你的答案是完美的,但你没有实现你的实现,这花了我一个小时的时间来理解JavaStreamingAudioPlayer类中发生了什么。 To help the other people like me who are not used in "diving" in a completely unknown Java code (I am still a student), I will put here my code and hope it will help other people :) . 为了帮助像我这样没有用于“潜水”的其他人在一个完全未知的Java代码(我仍然是学生),我会把我的代码放在这里,希望它能帮助其他人:)。

First, a more detailed explanation : around line 152, the JavaStreamingAudioPlayer opens a Line. 首先,更详细的解释:在第152行附近,JavaStreamingAudioPlayer打开一个Line。 However this operation can require some time so before using it, it wants to check it is opened. 但是,此操作可能需要一些时间,因此在使用之前,它需要检查它是否已打开。 In the current implementation, the solution used is to create a LineListener listening to this line and then to sleep (using the wait() method of the threads). 在当前实现中,使用的解决方案是创建一个LineListener,监听此行,然后进入休眠状态(使用线程的wait()方法)。

The LineListener will "wake up" the main Thread using a notifyAll() and will do this only when it receives a LineEvent of type "OPEN" which will guarantee that the line has been opened. LineListener将使用notifyAll()“唤醒”主线程,并且只有在收到类型为“OPEN”的LineEvent时才会这样做,这将保证线路已被打开。

However as explained by hakvroot here the problem is that the notification is never sent because of the specific behavior of the DataLine used by Ubuntu. 但是正如hakvroot在这里解释的那样,问题是由于Ubuntu使用的DataLine的特定行为,因此永远不会发送通知。

So I removed the synchronized, wait() and notifyAll() parts of the code but as hakvroot, then your JavaStreamingAudioPlayer might try to use your Line before it is opened : you need to wait for the confirmation with a new mechanism to stop the JavaStreamingAudioPlayer and to wake it up later, when the confirmation arrived. 所以我删除了代码的synchronized,wait()和notifyAll()部分,但是作为hakvroot,那么你的JavaStreamingAudioPlayer可能会在打开它之前尝试使用你的Line:你需要等待使用新机制的确认来停止JavaStreamingAudioPlayer当确认到达时,将其唤醒。

So I used the Semaphore which havkroot used (see Javadoc for explanations on this lock system) initiated with 1 stack : 所以我使用了havkroot使用的Semaphore(参见Javadoc对这个锁系统的解释)以1个堆栈启动:

  • when the line is opened it acquires one stack (so 0 remains) 当线被打开时,它获得一个堆栈(因此0保持不变)

  • when it wants to use the line it tries to acquire another (so it is stopped) 当它想要使用它试图获取另一条线时(所以它被停止)

  • when the listener gets the event we are looking for, it releases the semaphore 当监听器获取我们正在寻找的事件时,它会释放信号量

  • this frees the JavaStreamingAudioPlayer who can go for the next part 这将释放出可以用于下一部分的JavaStreamingAudioPlayer

  • do not forget to release again the semaphore so it has again 1 stack for the next line to open 不要忘记再次释放信号量,这样它又有1个堆栈,可以打开下一行

And here is my code : 这是我的代码:

Declare a Semaphore variable : 声明一个Semaphore变量:

private Semaphore hackSemaphore;

Initiate it in the constructor : 在构造函数中启动它:

hackSemaphore = new Semaphore(1);

Then the first part to replace (see hakvroot to see where to put it) : 然后第一部分要更换(参见hakvroot看看它放在哪里):

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

            line.open(format, AUDIO_BUFFER_SIZE);
            hackSemaphore.acquire(); 
            hackSemaphore.acquire(); 
            opened = true;
            hackSemaphore.release();

And the second part : 第二部分:

    public void update(LineEvent event) {
        if (event.getType().equals(LineEvent.Type.OPEN)) {
            hackSemaphore.release();
        }
    }

I'm not sure whether you already managed to solve this one, but I ran into the same problem (Ubuntu 10.10 / JavaSE6). 我不确定你是否已经设法解决了这个问题,但我遇到了同样的问题(Ubuntu 10.10 / JavaSE6)。 After some investigation of the FreeTTS source I found the culprit, a deadlock, in com.sun.speech.freetts.audio.JavaStreamingAudioPlayer. 在对FreeTTS源进行一些调查之后,我在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). 当Line打开并且Line的类型为org.classpath.icedtea.pulseaudio.PulseAudioSourceDataLine时(这可能是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). 造成这种死锁的原因在于,在JavaStreamingAudioPlayer中有一个关于Line的假设,即所有LineListener都会被调用一个类型为Line的LineEvent,它与调用Line.open()的线程相同,或者在Line之后已打开(并且可以返回对Line.open()的调用)。 This is not the case for the PulseAudioSourceDataLine; 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. 它首先从PulseAudio事件Thread调用所有LineListener,等待所有LineListeners返回,然后从open调用返回。 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. 随着JavaStreamingAudioPlayer强制同步Line.open()的调用和特定LineListener的处理,该任务是查看Line是否实际打开,发生死锁。

The workaround I chose for solving this problem is to implement an AudioPlayer which doesn't has this problem. 我选择解决此问题的解决方法是实现没有此问题的AudioPlayer。 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 ). 我基本上复制了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: ...

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. 我删除了两个同步块,而不是确保两个部分相互排除,我使用信号量来表示Line实际上是打开的。 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. 当然,这并不是必需的,因为PulseAudioSourceDataLine已经保证在返回时打开,但是当在另一个平台上测试相同的代码时,它更有可能发挥得很好。 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 ;). 如果您要这样做,您可能正在考虑更大的JavaStreamingAudioPlayer重写;)。

Finally, after you have created your new AudioPlayer you'll have to instruct FreeTTS to use your implementation rather than the default JavaStreamingAudioPlayer. 最后,在创建新的AudioPlayer之后,您必须指示FreeTTS使用您的实现而不是默认的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. 希望这一切都适合你。

I guess had the same issue on Ubuntu 12.04/OpenJDK-6, the execution get stuck in Voice.allocate() with no errors and no response. 我想在Ubuntu 12.04 / OpenJDK-6上遇到了同样的问题,执行卡在Voice.allocate()中没有错误且没有响应。 I tried using the Oracle/Sun JDK-6 instead of OpenJDK, and it worked fine. 我尝试使用Oracle / Sun JDK-6而不是OpenJDK,它运行良好。

PS Nice guide to install SunJDK on Ubuntu and configuring as default http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/ PS很好的指南,可以在Ubuntu上安装SunJDK并配置为默认值http://www.devsniper.com/ubuntu-12-04-install-sun-jdk-6-7/

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM