0

我正在用 Java 制作一个 DAW,实际上它比这更基本,我以我曾经拥有的一台旧的 Tascam 4-Track 录音机为模型。我试图在录制时监控音频,同时尽可能减少两者之间的延迟(延迟)。如果我在同一个线程中写入音频字节,我正在读取它们会有大量的延迟(如果你想查看我拥有的代码,我会发布它,但它似乎无关紧要,因为我认为它需要重写) . 我一直在考虑做的是使用生产者、消费者线程和队列来存储它们之间的字节块。所以我的生产者线程会从TargetDataLine并将它们存储在队列中,可能使用返回读取的字节数的方法,以便我可以在我的 while 循环中检查 EOF。并创建一个并发线程,该线程获取存储在队列中的字节块(当它们是要写入的字节时)并将它们写入SourceDataLine. 我的想法是同时运行的两个线程将能够几乎在读取字节的同时写入字节,或者至少比我现在的更好,但我想知道其他人是如何解决这个问题的。

此外,如果队列中没有字节,我还需要确保我的消费者线程等待,并在添加字节以再次开始写入字节时收到通知,如果有人会发布一个同步两个线程的正确方法的示例,我会欣赏它。我知道它们必须在同步代码块中,我应该使用多个锁吗?我不是要一个特定于音频的示例,只是一个将某些内容添加到集合然后将其删除的一般示例,感谢您提供任何帮助。谢谢。

4

1 回答 1

1

在“经典”java 中,您可以(并且可能应该)为生产者-消费者实现使用单个锁对象。就像是

public final static Object LOCK = new Object();

然后在您的 producer() 方法中,您将拥有如下代码:

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。您可以只定义一个“全局”静态队列,然后分别为您的 producer() 和 consume() 实现使用 offer() 和 take()。

但是,如果您真的关心延迟,我会加倍努力并使用专门为低延迟线程间通信编写的库。这种库的一个很好的例子是破坏器,它声称比 ArrayBlockingQueue 有更好的延迟。

于 2013-04-11T05:24:04.760 回答