Java 音频字节缓冲区需要不同的时间来填充

标签 java audio byte buffer bytebuffer

我正在打开一个目标数据线来接受给定格式的音频输入。 我启动并打开该行,并且有一个填充了字节的缓冲区。这会持续循环运行,直到外部参数发生更改。

现在,对于固定的采样率和缓冲区大小,我希望它总是需要相同的时间来填充,即如果我的缓冲区大小为 8 位流的 48000,并且我的采样率为 48kHz,我会预计我的缓冲区总是需要 1 秒才能填满。然而我发现这差异很大。

以下是我使用的代码:

 DataLine.Info info1 = new DataLine.Info(TargetDataLine.class, format1);

     try (TargetDataLine line = (TargetDataLine) m1.getLine(info1)) {
         line.open(format1);
            line.start();

            while (!pauseInput){
            long time1 = System.currentTimeMillis();


            int numBytesRead1 = line.read(buffer1, 0, buffer1.length);

            //chan1double = deinterleaveAudio(buffer1, chan1selectedchannel, chan1totalchannels);
            long time2 = System.currentTimeMillis();
            System.out.println(threadName + " Capture time = " + (time2-time1));
            }
         line.stop(); 

     }

注释行是我想在每次缓冲区满时运行的进程。我意识到我不能把它放在这里,因为它会中断流,所以我需要找到一种不同的方式来调用它,因此我已经注释掉了。

出于测试目的,我的缓冲区大小为 4096。我的音频格式是 48kHz 16 位,因此我预计我的字节缓冲区将在 42.6ms 内填充。 ((1/48000)* 2048)。 (这是乘以缓冲区大小的一半,因为每个样本都是两个字节)。然而,使用 currentTimeMillies 来测量每次通过时,它会返回 123 毫秒和 250 毫秒,并且这些时间之间会有所不同。

我是否遗漏了一些尚未完成的事情?

编辑:我已将代码复制到一个全新的应用程序中,该应用程序甚至没有 GUI 或附加的任何内容。纯粹是为了输出到控制台并查看发生了什么,确保没有后台线程干扰,并且肯定会发生同样的情况。 95% 的情况下,预计填充时间为 250 毫秒的缓冲区会在 255-259 毫秒内填充。然而,有时这会下降到 127 毫秒(这在物理上是不可能的,除非发生一些奇怪的缓冲区事情。这是 java 中某个地方的错误吗?

最佳答案

我认为以这种方式调整时间并不是一个好主意。它取决于很多因素,例如 bufferSize、混合器等。此外,您的应用程序与混合器共享线路的缓冲区。如果您有实时处理,请将数据存储在循环缓冲区中,其长度足以容纳您需要的数据量。在另一个线程中,从循环缓冲区读取所需数量的数据,并以恒定的时间间隔进行处理。因此,有时,您可能会在两个连续处理之间重叠或丢失一些字节,但您始终拥有预期的字节数。

当您打开该行时,您可以使用 open(format, bufferSize) 指定该行的缓冲区大小。或者您可以通过以下方式检查实际缓冲区大小 调用DataLine.getBufferSize() 。然后,您需要指定当您通过TargetDataLine.read()检索数据时提供的短缓冲区的大小。 。您的短缓冲区大小必须小于行缓冲区大小。我认为短缓冲区大小为行缓冲区大小的 1/4、1/8、1/16 左右。另一个想法是检查可用字节 DataLine.available()在调用 read() 之前。请注意,read() 是一个阻塞调用(但它不会阻塞行的缓冲区),即,它将被卡住,直到读取了请求的字节数。

对于应用程序和音频接口(interface)之间的低延迟直接通信,您可以考虑 ASIO .

关于Java 音频字节缓冲区需要不同的时间来填充,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49197635/

相关文章:

java - 在 JPA/Hibernate 中动态更改表名称

Java Webstart Jar 签名 : Can it be signed partially?

java - 音频漂移问题。以编程方式创建视频帧并与 java 中的 midi/音频同步

java - 设置字节中的特定位

java - 更方便的方法来找到 2+ 数字的最大值?

java - 无法运行 yui jar 文件 - 缺少变量名并且函数体后缺少 }

objective-c - Phonegap 同时录音和回放

c# - 按下按钮即可播放声音

c# - 在字节 [] 中查找 MBUS 电报

java - 大于 127 的字节值