java - 使用 Java Sound API 跳转到音频文件中的位置

标签 java memory-mapped-files audio javasound

我正在使用AudioInputStream将字节馈送到 SourceDataLine播放 PCM 文件。我想让用户能够移动 slider 以跳转到文件中的某个点。

我遇到的问题:

  • markSupported()在我的 AudioInputStream 上返回 false 。所以我 无法使用我最初的方法来调用 reset() 然后调用 skip() (其中 我已经觉得有点丑了......)
  • 我真的不想为了跳转到当前标记之前的位置而拆除 InputStream 并创建一个新的。
  • SourceLineData.getLongFramePosition()似乎不是很可靠...我知道它有一个缓冲区,但即使考虑到缓冲区中剩余的字节,我也不理解其行为

我考虑过使用 Memory-Mapped File将字节输入到行中,这样我就可以跳转到任何我想要的地方,但如果不需要的话,我不想增加函数的复杂性。有没有一个好的方法可以做到我所缺少的?任何人都可以解释 getLongFramePosition() 返回的帧号是什么实际上意味着什么?是通过扬声器的帧数(似乎不是)?

最佳答案

BigClip 对您有用吗?

如果没有,这里有一个可行的方法。警告,这有点令人费解。 http://hexara.com/VSL/VSL2.htm

使用此 Applet,您可以加载 wav - 我加载的 wav 时间超过 5 分钟,效果很好,但音频数据确实占用了大量 RAM。

加载 WAV 后,您可以将鼠标移动到任意点并通过按住鼠标并拖动来播放。显然,这不完全是您想要做的,因为您想从一个点开始播放,而不用担心拖动或拖动速度。但我为获取可播放状态的数据而采取的路径应该仍然适合您。

如果您有可用的 AudioInputStream 和 AudioFileFormat,则可以设置一个内部数组并将数据直接读入其中。音频文件格式为您提供编码和帧长度,您可以使用它们来计算数组维度。

然后,创建一个 TargetDataLine,从您创建的数组中获取音频数据。 TDL 必须有一个变量来标记下一次读取的开始位置。您可以使用 JSlider 更改该变量的内容以指向您想要的任何框架。

如果您没有可用的 AudioInputStream,可以通过多种方法获得...但它更复杂,涉及 ByteArrayOutput 和 Input Stream 对象。可能没有必要去那里。 (我用它们来读取上面Applet中的客户端数据。)

至于您关于当前帧位置的问题,关键问题是 JVM 以 block 的形式处理音频数据,并且它往往会领先于突发的音频数据。我为这个问题苦苦思索了很久,最后想到了这个: http://www.java-gaming.org/index.php/topic,24605.0.html

关于java - 使用 Java Sound API 跳转到音频文件中的位置,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7113688/

相关文章:

java - ThreadLocal 与新局部变量相比的真正优势

c# - 使用 MemoryMappedFile 读取文件字节

c++ - 关于大文件文本编辑器中的内存映射文件和用法

c - Darwin 真的没有mremap吗?

python - 解释 WAV 数据

android - 带有音频的图像幻灯片

android - 适用于 Android 的低级音频 API

java - 给定一个堆栈,其中包含多个类的对象,如何管理弹出的对象?

java - 从没有 storepass 的 Java Key Store 导出没有 keypass 的私钥

java - 使 Action 监听器(数组)更改值