gpt4 book ai didi

java - 音频剪辑卡住

转载 作者:行者123 更新时间:2023-11-30 11:58:37 25 4
gpt4 key购买 nike

我看到 <a href="http://download.oracle.com/javase/6/docs/api/javax/sound/sampled/Clip.html" rel="noreferrer noopener nofollow">Clip</a> 有一些奇怪的行为Java 中的实例。

我正在学习的类(class)的目的是统计 Clip 的数量。包含相同声音样本的实例(由 <a href="http://download.oracle.com/javase/6/docs/api/java/net/URI.html" rel="noreferrer noopener nofollow">URI</a> 索引。)当应用程序请求播放剪辑并且已经有来自同一源的三个或更多剪辑正在播放时,将执行以下步骤:

  • <a href="http://download.oracle.com/javase/6/docs/api/javax/sound/sampled/FloatControl.Type.html#PAN" rel="noreferrer noopener nofollow">PAN</a> 的加权和对当前播放的剪辑进行排序和 <a href="http://download.oracle.com/javase/6/docs/api/javax/sound/sampled/DataLine.html#getFramePosition%28%29" rel="noreferrer noopener nofollow">framePosition</a> .
  • 选择具有最高值的剪辑作为要停止并重新开始的剪辑。
  • 重新启动剪辑(以下方法):

void restart(Clip clip, float gain, float pan) {
clip.stop();
clip.flush();
pan = Math.max(-1f, Math.min(pan, 1f));
((FloatControl) clip.getControl(FloatControl.Type.MASTER_GAIN))
.setValue(gain);
((FloatControl) clip.getControl(FloatControl.Type.PAN))
.setValue(pan);
clip.setFramePosition(0);
clip.start();
}

如果快速连续多次调用此方法(例如,在 1 毫秒内调用 20 次),则会出现奇怪的行为:

  • 剪辑播放
  • 剪辑触发 <a href="http://download.oracle.com/javase/6/docs/api/javax/sound/sampled/LineEvent.Type.html#START" rel="noreferrer noopener nofollow">START</a>表示已开始播放的事件
  • 剪辑从不触发 <a href="http://download.oracle.com/javase/6/docs/api/javax/sound/sampled/LineEvent.Type.html#STOP" rel="noreferrer noopener nofollow">STOP</a>事件。
  • 随后调用 stopstart没有效果(但不抛出异常。)
  • getFramePosition总是返回 0 ,即使可以听到剪辑(最后一次)。

知道是什么原因造成的吗?

我不认为这是线程问题(至少在我的代码中不是。)只有一个线程正在调用我类的公共(public)方法(而且它们都是 synchronized 无论如何)


可能与 this bug 有关.

最佳答案

DataLine.startDataLine.stop 的调用在 DataLine 的混音器上已经同步里面AbstractDataLine .

我强烈怀疑在调用堆栈的某个地方(implStart()/implStop() 下的任何 DataLine 化身,非常可能在 native nStart/nstop 中)至少进行了一次异步调用,从而导致您观察到的竞争条件。

如果不深入了解所调用的 native 实现,您就不可能使用 synchronized 或任何其他 Java 构造来解决此类问题。

一个可行的直接解决方法可能是关闭旧剪辑并打开一个新实例,而不是倒带旧剪辑。不是最优的,但在进行更深入的调查之前,它很可能会起到作用。

为了能够执行上述更深入的调查,必须知道您在哪个平台上,以及确认您的 Clip 的实际(实现)类名和Mixer 实例。

更新

同时,请使用内省(introspection)设置 com.sun.media.sound.Printer.trace = true(或在 CLASSPATH 中提供您自己的 com.sun.media.sound.Printer 实现>.)

本质上 DirectClip.open() spawns一个thread访问几个 volatile variables (特别感兴趣的是 doIO)以非线程安全的方式,这可能会导致主播放循环挂起。

您可以通过强制执行 thread dump 来确认(或证实)这一点(结合 Printer 跟踪)在明显挂起时,检查回放线程状态/堆栈跟踪(或使用调试器。)

如果 doIO 等访问结果不是是问题,那么继续挖掘 native 实现仍然是要做的事情;如果 doIO 等访问 does 再次成为问题,则没有简单的解决方法(您可以尝试使用内省(introspection)来获取 DirectClip.thread 并定期向它发出信号,以防它因 doIO 而停止——再次确认。)

关于java - 音频剪辑卡住,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3081808/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com