Java FreeTTS无音频linux ubuntu-无错误

Java FreeTTS无音频linux ubuntu-无错误,java,audio,text-to-speech,javasound,freetts,Java,Audio,Text To Speech,Javasound,Freetts,我使用Java6运行Ubuntu10.10,无法获得FreeTTS来输出任何音频。我已经在3台不同的电脑上试过了,甚至让我的一个朋友在他的Ubuntu电脑上试过,他也有同样的问题。绝对没有显示错误,在获得MBROLA后,我甚至不再收到关于未检测到MBROLA声音的警告。胡说八道 使用同一台计算机,我运行了一个虚拟盒子并启动了Windows XP,在运行HelloWorld.jar和TTSHelloWorld.jar时,我实际上能够获得音频,但是当我尝试输入自己的文本时,freetts.jar仍然

我使用Java6运行Ubuntu10.10,无法获得FreeTTS来输出任何音频。我已经在3台不同的电脑上试过了,甚至让我的一个朋友在他的Ubuntu电脑上试过,他也有同样的问题。绝对没有显示错误,在获得MBROLA后,我甚至不再收到关于未检测到MBROLA声音的警告。胡说八道

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

我使用的命令

java-jarlib/freetts.jar-text Hello

当我按enter键时,它会启动,并用来给我丢失的MBROLA警告消息,但现在它只是坐在那里,直到我按CTRL-C键停止它

我不明白我做错了什么,为什么没有其他人有这个问题,当我在每台电脑上都体验过它的时候,它在Windows上也能工作。有人能帮我吗

谢谢


约翰

我不确定你是否已经解决了这个问题,但我遇到了同样的问题(Ubuntu 10.10/JavaSE6)。在对FreeTTS源进行一些调查之后,我在com.sun.speech.FreeTTS.audio.JavaStreamingAudioPlayer中找到了一个死锁。当一行被打开并且该行的类型为org.classpath.icedtea.pulseaudio.pulseaudiosourcedaline(这可能是Ubuntu 10.10 w JavaSE6中的默认值)时,就会发生死锁。由于您总是希望打开一条线路来输出音频,所以这种死锁总是会发生

此死锁的原因在于,在JavaStreamingAudioLayer中,对Line进行了一个假设,即所有LineListener都将从调用Line.open()的同一线程收到类型为open的LineEvent的通知,或者在该行被打开(并且可以返回对Line.open()的调用)之后收到通知。PulseaudioSourceDaline的情况并非如此;它首先从PulseAudio事件线程调用所有LineListener,等待它们全部返回,然后从open调用返回。JavaStreamingAudioPlayer强制围绕Line.open()调用进行同步,并处理特定的LineListener,该LineListener的任务是查看该行是否实际打开,因此会发生死锁

我选择的解决这个问题的方法是实现一个没有这个问题的音频播放器。我基本上复制了JavaStreamingAudioPlayer,并修改了第196行和第646行的同步块(参考完整源代码:)

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

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

System.setProperty("com.sun.speech.freetts.voice.defaultAudioPlayer", "classpath.to.your.AudioPlayer");
在代码早期的某个地方


希望这一切都能对你起作用。

我猜Ubuntu 12.04/OpenJDK-6上也有同样的问题,执行过程被阻塞在Voice.allocate()中,没有错误,也没有响应。 我尝试使用Oracle/Sun JDK-6而不是OpenJDK,效果很好

附言:在Ubuntu上安装SunJDK并将其配置为默认配置的尼斯指南
我是一名学生,一周来一直试图让FreeTTS在Ubuntu上运行。最后我在这里找到了答案:非常感谢哈克夫鲁特

你的答案很完美,但是你没有把你的实现放在首位,我花了一个小时才理解JavaStreamingAudioPlayer类中发生了什么。为了帮助像我这样不习惯“潜入”完全未知的Java代码的人(我还是一名学生),我将把我的代码放在这里,希望它能帮助其他人:)

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

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

然而,正如hakvroot在这里解释的,问题是由于Ubuntu使用的数据线的特定行为,通知从未发送

因此,我删除了代码中的synchronized、wait()和notifyAll()部分,但作为hakvroot,您的JavaStreamingAudioPlayer可能会在打开之前尝试使用您的行:您需要使用新机制等待确认,以停止JavaStreamingAudioPlayer,并在确认到达后将其唤醒

因此,我使用了havkroot使用的信号量(有关此锁系统的解释,请参阅Javadoc),该信号量由1个堆栈启动:

  • 当该行打开时,它将获得一个堆栈(因此0保留)

  • 当它想要使用该行时,它会尝试获取另一行(因此停止)

  • 当侦听器获取我们要查找的事件时,它会释放信号量

  • 这将释放JavaStreamingAudioPlayer,使其可以进入下一部分

  • 不要忘了再次释放信号量,这样它就又有一个堆栈供下一行打开

这是我的代码:

申报
System.setProperty("com.sun.speech.freetts.voice.defaultAudioPlayer", "classpath.to.your.AudioPlayer");
private Semaphore hackSemaphore;
hackSemaphore = new Semaphore(1);
            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();
        }
    }