我正在用Java制作DAW,实际上它比它更基础,我用我曾经拥有的旧的Tascam 4轨录音机模拟它。我正在尝试在录制时监听音频,尽可能减少两者之间的延迟(延迟)。如果我在相同的线程中写入音频字节,我正在阅读它们有大量的延迟(如果你想看到我有的代码,我会发布它,但它似乎无关紧要,因为我认为它需要重写) 。我一直在考虑做的是使用生产者,消费者线程和队列来存储两者之间的字节块。所以我的生产者线程会从TargetDataLine
读取字节并将它们存储在一个队列中,可能使用一个返回读取的字节数的方法,这样我就可以检查我的while循环中的EOF。并创建一个并发线程,该线程获取存储在队列中的字节块(当它们是要写入的字节时)并将它们写入SourceDataLine
。我的想法是两个同时运行的线程几乎可以在读取它们的同时写入字节,或者至少比我现在的要好,但我想知道其他人是如何解决这个问题的。
此外,如果队列中没有字节,我需要确保我的消费者线程等待,并且当添加字节以再次开始写入字节时通知我,如果有人会发布一个正确的方法来同步两个字节的示例线程我会很感激。我知道他们必须在同步代码块中,我应该使用多个锁吗?我不是要求一个特定于音频的示例,只是一个将一些内容添加到集合然后将其删除的一般示例,任何帮助都表示赞赏。感谢。
答案 0 :(得分:1)
在“经典”java中你可以(并且probbaly应该)使用单个锁对象进行生产者 - 消费者实现。
之类的东西public final static Object LOCK = new Object();
然后在你的produce()方法中你会得到这样的代码:
synchronized(LOCK) {
//place stuff in queue
LOCK.notifyAll(); //wake up any sleepers
}
并且在您的consume()方法中,您将拥有另一方:
synchronized(LOCK) {
if (anything in queue) {
return something
}
//queue is empty - wait
while (nothing in queue) { //while bit is important - we might wakeup for no reason or someone else might grab everything leaving us with nothing
try {
Lock.wait();
} catch (InterruptedException ex) {
//99% of java code ignores these spurious wakeups, and they also hardly ever really happen
}
}
}
但这是老派。更现代的java版本有一个整齐地包装所有这个低级伏都教的类。例如ArrayBlockingQueue。你可以只定义一个“全局”静态队列,然后分别对你的produce()和consume()实现使用offer()和take()。
但如果你真的关心延迟,我会更加努力,并使用一个完全用于低延迟线程间通信的库。这个库的一个很好的例子是the disruptor,它声称延迟比ArrayBlockingQueue好得多。