此问题底部的代码段在我的台式机上运行良好,对clip.getFramePosition()
的调用花费了1ms或更短的时间。在运行Raspbian Stretch和JDK 8u191的Pi 3 Model B +上,调用同一函数大约需要900毫秒。这似乎太慢了。
我实际上是在尝试通过JLayer播放MP3文件,但WAV文件也会出现此问题,并且由于不需要外部依赖项,因此使用WAV文件更容易重现,
CPU和内存
运行代码时,top
报告的Pi的CPU和内存使用率永远不会超过10%。我还尝试将音频预加载到byte
数组中,然后播放而不是流。它具有相同的问题,因此这似乎不是磁盘I / O瓶颈。
阻止
在运行时,clip
对象是com.sun.media.sound.DirectAudioDevice.DirectDL
的实例,其getLongFramePosition()
方法具有一个同步块,该块调用了native
方法:
synchronized(this.lockNative) {
var1 = DirectAudioDevice.nGetBytePosition(this.id, this.isSournce, this.bytePosition);
}
因此,可能是某些原因阻止了我的通话。但是,我认为在播放Clip
的过程中查询它的进度是合理的。
那会是什么? 有人能阐明这种缓慢吗?我是在滥用API,还是仅仅是Raspbian的Java Audio实现的问题?
更新#1:Ubuntu MATE + Liberica
我尝试使用Liberica JRE 11在Ubuntu MATE上运行代码,但速度仍然很慢。
更新#2:外部声卡
我将外部USB声卡插入pi并通过它播放了音频。我没想到它可以解决问题,但没有。
更新#3:直接使用JLayer
通过JLayer AdvancedPlayer
类而不是通过Java Sound API播放MP3会更好。获取进度大约需要50毫秒,而不是900毫秒,但这仍然很慢。
更新#4:使用Pi 3模型B
我周围有一个Pi 3 Model B(不是B +)。运行最新的Raspbian时,它具有相同的问题。使用Raspbian Jessie(2016-03-18)时,速度稍快(〜700ms),但不多。
示例代码
import java.io.File;
import java.io.InputStream;
import java.util.Date;
import javax.sound.sampled.AudioFormat;
import javax.sound.sampled.AudioInputStream;
import javax.sound.sampled.AudioSystem;
import javax.sound.sampled.Clip;
public class Main {
public static void main(String[] args) throws Exception {
File file = new File("/home/pi/beat.wav");
AudioInputStream ais = AudioSystem.getAudioInputStream(file);
AudioFormat format = ais.getFormat();
Clip clip = AudioSystem.getClip();
clip.open(ais);
clip.start();
for (int i = 0; i < 100; i++) {
long start = new Date().getTime();
long pos = clip.getFramePosition();
long duration = new Date().getTime() - start;
System.out.println("Pos: " + pos + ", duration: " + duration);
Thread.sleep(10);
}
}
}