在 Raspberry Pi 上获取声音片段位置非常慢

问题描述 投票:0回答:1

我在 Raspberry Pi 3B(64 位操作系统)上运行 Java 21。在正在运行的音频剪辑上调用

javax.sound.sampled.Clip#getFramePosition()
每次调用最多需要 3 秒,而在我的 PC 上则需要不到 1 毫秒。

这些年来我又回到了这个问题,尝试:

    不同的 JDK(8、17、21)
  • 不同的树莓派
  • 不同的 Pi 操作系统(32 和 64 位)
  • 不同的音频格式(我的实际用例使用 MP3 文件,但 WAV 可以实现更简单的再现情况)
  • 外接声卡
  • 在单独的线程上运行循环
但我从未能够从这次通话中获得合理的表现。在代码运行时使用

top

 进行监控显示,
java
 进程消耗的 CPU 或 RAM 从未超过 2% 或 5%。

我考虑过的解决方案:

    我错过了一些明显的东西吗?
  • 可以更改音频配置(或音频驱动程序)吗?
  • 还有其他方法获取剪辑的进度吗?我认为
  • SourceDataLine
     不太适合我的用例。
  • 我可以在某处提出错误报告吗? (不确定这属于谁的管辖范围:JDK、Pi 团队或其他人)。
  • 如何找出性能瓶颈在哪里?
这是一个可重现的示例(需要工作目录中的外部

test.wav

 文件):

import java.io.ByteArrayInputStream; import java.io.File; import java.io.InputStream; import java.nio.file.Files; 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 { byte[] fileBytes = Files.readAllBytes(new File("./test.wav").toPath()); InputStream bais = new ByteArrayInputStream(fileBytes); AudioInputStream ais = AudioSystem.getAudioInputStream(bais); 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); } } }
这是一些示例输出:

Pos: 0, duration: 0 Pos: 32778, duration: 645 Pos: 164690, duration: 2980 Pos: 262573, duration: 2207 Pos: 426196, duration: 3698 Pos: 458820, duration: 728 Pos: 524493, duration: 1479 Pos: 557127, duration: 729 Pos: 590678, duration: 749 Pos: 656352, duration: 1478 Pos: 721684, duration: 1469 Pos: 754290, duration: 728 Pos: 786924, duration: 729 Pos: 813348, duration: 588
    
java audio raspberry-pi javasound
1个回答
0
投票
一些想法。首先,我很好奇

AudioCue-maven 如何在 Raspberry PI 上工作。它的运行方式类似于 Clip

,但基于 
SourceDataLine
,并且可能具有适合您的用例的每个方面的最佳方面。

另一个想法,使用

SourceDataLine

,您可以在帧流逝时对其进行计数。 
音频教程中的“读取音频文件”部分中有一个代码示例,其中保存了正在读取的帧数。通过一些修改,您可以使该变量可以被其他线程读取,例如,将其指定为 volatile

当您

open

Clip
时尝试不同的缓冲区设置可能会有所帮助。我也很好奇您是否有笔记本电脑输出的数据示例,以与您显示的 Raspberry 输出进行对比。

© www.soinside.com 2019 - 2024. All rights reserved.