java - Raspberry Pi 上的 Java Audio Clip#getFramePosition() 非常慢
问题描述
这个问题底部的代码片段在我的台式电脑上运行良好,调用时间为 1clip.getFramePosition()
毫秒或更短。在我运行 Raspbian Stretch 和 JDK 8u191 的 Pi 3 Model B+ 上,调用相同的函数大约需要 900 毫秒。这似乎太慢了。
我实际上是在尝试通过 JLayer 播放 MP3 文件,但是 WAV 文件也会出现问题,并且使用 WAV 文件更容易重现,因为不需要外部依赖项,
CPU 和内存
运行代码时,Pi 报告的 CPU 和内存使用率top
从不超过 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 音频实现的问题?
更新#1:Ubuntu MATE + Liberica
我尝试使用 Liberica JRE 11 针对 Ubuntu MATE 运行代码,但仍然出现缓慢。
更新#2:外置声卡
我将外部 USB 声卡插入我的 pi 并通过它播放音频。我没想到它会解决这个问题,它没有。
更新#3:直接使用 JLayer
通过 JLayerAdvancedPlayer
类而不是通过 Java Sound API 播放 MP3 会好一些。获得进度大约需要 50 毫秒而不是 900 毫秒,但这仍然非常缓慢。
更新 #4:使用 Pi 3 Model B
我有一个 Pi 3 Model B(不是 B+)。运行最新的 Raspbian 时也有同样的问题。使用 Raspbian Jessie (2016-03-18) 会更快一些(约 700 毫秒),但并不多。
示例代码
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);
}
}
}
解决方案
推荐阅读
- java - 如何在 Java 8 中进行并行调用
- python - 仅当组中的最新记录不同时才插入表中
- python - 如何计算数据框中与一列不同的行数?
- python - Cholesky 分解浮点数错误
- android-studio - 驻留在外部 jar 中的 Kotlin @Serializable 上的注释处理
- python - 给定一个小写字符串's',返回字符串中仅出现一次的第一个字符的索引
- python-3.x - 深度学习中大数据框的 MemoryError
- opengl - OpenGL glScissors 坐标系中心
- asynchronous - 强制同步循环http请求
- c++ - dllexport 类模板实例(专业化),减少仅头文件模板库的编译时间