Java 声音 API:尝试进行实时麦克风输入监控很慢
Java Sound API: Attempt to Do Live Microphone Input Monitoring is Slow
我认为 Java 声音 API 存在性能(延迟)问题。
音频监视器
下面的代码确实对我有用。它正确地打开麦克风,并通过我的扬声器实时输出音频输入(即监听)。但我担心的是播放的速度......从我对着麦克风说话到通过扬声器播放,它落后了半秒。
如何提高性能?如何降低延迟?
private void initForLiveMonitor() {
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
try {
//Speaker
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open();
//Microphone
info = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open();
Thread monitorThread = new Thread() {
@Override
public void run() {
targetLine.start();
sourceLine.start();
byte[] data = new byte[targetLine.getBufferSize() / 5];
int readBytes;
while (true) {
readBytes = targetLine.read(data, 0, data.length);
sourceLine.write(data, 0, readBytes);
}
}
};
System.out.println( "Start LIVE Monitor for 15 seconds" );
monitorThread.start();
Thread.sleep(15000);
targetLine.stop();
targetLine.close();
System.out.println( "End LIVE Monitor" );
}
catch(LineUnavailableException lue) { lue.printStackTrace(); }
catch(InterruptedException ie) { ie.printStackTrace(); }
}
补充说明
- 使用此代码,播放流畅(无爆音或抖动),仅延迟半秒。
- 我也知道我的电脑和 USB Audio 接口可以通过电脑进行实时监听,因为当我用 Logic Pro X 做并排比较时,延迟很小--我觉得完全没有延迟。
- 我尝试 smaller/larger byte[] 大小并没有解决这个问题。
我的结论是,这是我遇到的 Java 代码问题。提前致谢。
涉及的缓冲区不止一个!
当您打开 SourceDataLine 和 TargetDataLine 时,我建议您使用指定缓冲区大小的表单。但我不知道推荐什么尺寸。我还没有玩过这个足以知道安全管道麦克风输入的最佳尺寸是多少——我的经验更多的是实时合成。
无论如何,这样如何:定义 data[] 的长度并在您的行打开方法中使用相同的长度。尝试 1024 之类的数字或倍数(同时确保字节数可以除以每帧字节数,根据您使用的格式,每帧字节数看起来是 4)。
int bufferLen = 1024 * 4; // experiment with buffer size here
byte[] data = new byte[bufferLen];
sourceLine.open(bufferLen);
targetLine.open(bufferLen);
此外,也许 运行() 中的代码最好放在其他地方,以免在管道开始之前添加到所需的处理中。数组 data[] 和 int readBytes 可以是实例变量并准备好滚动而不是在 运行() 中使用,可能会增加延迟。
无论如何,这些都是我会尝试的。
我认为 Java 声音 API 存在性能(延迟)问题。
音频监视器
下面的代码确实对我有用。它正确地打开麦克风,并通过我的扬声器实时输出音频输入(即监听)。但我担心的是播放的速度......从我对着麦克风说话到通过扬声器播放,它落后了半秒。
如何提高性能?如何降低延迟?
private void initForLiveMonitor() {
AudioFormat format = new AudioFormat(AudioFormat.Encoding.PCM_SIGNED, 44100, 16, 2, 4, 44100, false);
try {
//Speaker
DataLine.Info info = new DataLine.Info(SourceDataLine.class, format);
SourceDataLine sourceLine = (SourceDataLine) AudioSystem.getLine(info);
sourceLine.open();
//Microphone
info = new DataLine.Info(TargetDataLine.class, format);
TargetDataLine targetLine = (TargetDataLine) AudioSystem.getLine(info);
targetLine.open();
Thread monitorThread = new Thread() {
@Override
public void run() {
targetLine.start();
sourceLine.start();
byte[] data = new byte[targetLine.getBufferSize() / 5];
int readBytes;
while (true) {
readBytes = targetLine.read(data, 0, data.length);
sourceLine.write(data, 0, readBytes);
}
}
};
System.out.println( "Start LIVE Monitor for 15 seconds" );
monitorThread.start();
Thread.sleep(15000);
targetLine.stop();
targetLine.close();
System.out.println( "End LIVE Monitor" );
}
catch(LineUnavailableException lue) { lue.printStackTrace(); }
catch(InterruptedException ie) { ie.printStackTrace(); }
}
补充说明
- 使用此代码,播放流畅(无爆音或抖动),仅延迟半秒。
- 我也知道我的电脑和 USB Audio 接口可以通过电脑进行实时监听,因为当我用 Logic Pro X 做并排比较时,延迟很小--我觉得完全没有延迟。
- 我尝试 smaller/larger byte[] 大小并没有解决这个问题。
我的结论是,这是我遇到的 Java 代码问题。提前致谢。
涉及的缓冲区不止一个!
当您打开 SourceDataLine 和 TargetDataLine 时,我建议您使用指定缓冲区大小的表单。但我不知道推荐什么尺寸。我还没有玩过这个足以知道安全管道麦克风输入的最佳尺寸是多少——我的经验更多的是实时合成。
无论如何,这样如何:定义 data[] 的长度并在您的行打开方法中使用相同的长度。尝试 1024 之类的数字或倍数(同时确保字节数可以除以每帧字节数,根据您使用的格式,每帧字节数看起来是 4)。
int bufferLen = 1024 * 4; // experiment with buffer size here
byte[] data = new byte[bufferLen];
sourceLine.open(bufferLen);
targetLine.open(bufferLen);
此外,也许 运行() 中的代码最好放在其他地方,以免在管道开始之前添加到所需的处理中。数组 data[] 和 int readBytes 可以是实例变量并准备好滚动而不是在 运行() 中使用,可能会增加延迟。
无论如何,这些都是我会尝试的。