0

我正在使用 a向 aAudioInputStream提供字节来SourceDataLine播放 PCM 文件。我想让用户能够移动滑块以跳转到文件中的某个点。

我遇到的问题:

  • markSupported()返回false我的AudioInputStream. 所以我不能使用我最初的方法来打电话reset()skip()我已经认为这有点难看......)
  • 我真的不想拆掉InputStream 并创建一个新的,只是为了跳到我当前标记之前的位置。
  • SourceLineData.getLongFramePosition()似乎不是很可靠......我知道它有一个缓冲区,但即使考虑到byte缓冲区中的 s ,我也不明白这种行为

我考虑过使用 aMemory-Mapped File将字节馈送到行中,这样我就可以跳到任何我想要的地方,但是如果我不需要的话,我不想增加函数的复杂性。有没有我想念的好方法?也有人可以解释getLongFramePosition()实际返回的帧号是什么意思吗?是通过扬声器的帧数(似乎不是)?

4

2 回答 2

1

BigClip 对您有用吗?

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

有了这个小程序,你可以加载一个 wav——我已经加载了超过 5 分钟的 wav,它运行良好,但音频数据确实占用了大量的 RAM。

加载 WAV 后,您可以将鼠标移动到任意点并通过按住鼠标并拖动来播放。显然,这并不是你想要做的,因为你想从一个点回放,而不用担心拖动或拖动速度。但是我为使数据处于可播放状态所采取的方法仍然适用于您。

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

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

如果您没有可用的 AudioInputStream,有办法获得...但它更复杂,涉及 ByteArrayOutput 和 Input Stream 对象。应该没必要去吧。(我使用它们来读取上述 Applet 中的客户端数据。)

至于您关于当前 Frame 位置的问题,关键问题是 JVM 以块的形式处理音频数据,并且它往往会在突发事件之前运行。我很长一段时间都在努力解决这个问题,然后想出了这个: http ://www.java-gaming.org/index.php/topic,24605.0.html

于 2011-08-23T03:10:36.847 回答
1

我能想出的最干净的方法是使用 a根据用户移动滑块FileChannel以这种方式读取字节SourceDataLine我可以确定文件中的字节位置(确保调整或舍入它以与框架对齐) 然后在 中设置该位置,FileChannel然后继续播放。当发生这种情况以阻止播放剩余字节时,我刷新了线路。

于 2011-09-15T18:18:05.530 回答