我是一名学生,他一直试图让 FreeTTS 在其 Ubuntu 上运行一周。最后我在这里找到了答案:非常感谢 hakvroot!
你的答案很完美,但你没有把你的实现,这花了我整整一个小时来理解 JavaStreamingAudioPlayer 类中发生了什么。为了帮助像我这样没有在完全未知的Java代码中“潜水”的人(我还是个学生),我将把我的代码放在这里,希望它可以帮助其他人:)。
首先,更详细的解释:在第 152 行附近,JavaStreamingAudioPlayer 打开了一个 Line。但是此操作可能需要一些时间,因此在使用它之前,它要检查它是否已打开。在当前的实现中,使用的解决方案是创建一个 LineListener 侦听此行然后休眠(使用线程的 wait() 方法)。
LineListener 将使用 notifyAll() “唤醒”主线程,并且仅当它接收到类型为“OPEN”的 LineEvent 时才会这样做,这将保证线路已打开。
但是,正如 hakvroot 在这里所解释的,问题是由于 Ubuntu 使用的 DataLine 的特定行为,通知永远不会发送。
因此,我删除了代码的同步、wait() 和 notifyAll() 部分,但作为 hakvroot,您的 JavaStreamingAudioPlayer 可能会在打开之前尝试使用您的 Line:您需要等待使用新机制的确认以停止 JavaStreamingAudioPlayer并在确认到达时将其唤醒。
因此,我使用了 havkroot 使用的 Semaphore(有关此锁系统的解释,请参见 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();
}
}