代码之家  ›  专栏  ›  技术社区  ›  finnw

音频剪辑卡住

  •  2
  • finnw  · 技术社区  · 14 年前

    我看到一些奇怪的行为 Clip Java中的实例。

    我正在学习的这门课的目的是数一数 Clip 包含相同声音样本的实例(按索引 URI .)当应用程序请求播放剪辑,并且已经播放了来自同一源的三个或更多剪辑时,将执行以下步骤:

    • 按加权和对当前播放的剪辑进行排序 PAN framePosition .
    • 选择值最高的剪辑作为要停止和重新启动的剪辑。
    • 重新启动剪辑(以下方法):

    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次),则会出现奇怪的行为:

    • 剪辑剧
    • 剪辑将激发 START 表示已开始播放的事件
    • 剪辑从不触发 STOP 事件。
    • 后续呼叫 stop start 没有效果(但不要抛出异常。)
    • getFramePosition 总是回报 0 ,即使可以听到剪辑(最后一次)。

    知道是什么引起的吗?

    我不认为这是线程问题(至少在我的代码中没有),只有一个线程在调用我的类的公共方法(它们都是 synchronized 不管怎样)


    可能与 this bug .

    1 回复  |  直到 13 年前
        1
  •  1
  •   vladr    14 年前

    呼唤 DataLine.start DataLine.stop 已同步 DataLine 里面的搅拌器 AbstractDataLine .

    我强烈怀疑有人在下面 implStart() / implStop() 无论什么 数据链 你的化身,很可能是在本地 nStart / nstop ) 至少进行了一个异步调用 从而导致你观察到的种族状况。

    你不可能用 synchronized 或者任何其他Java构造,而不需要更深入地了解被调用的本机实现。

    可行的即时解决方案 关闭旧剪辑并打开新实例,而不是重绕旧剪辑。不是最理想的,但在更深入的调查之前它很可能会成功。

    为了能够进行上述更深入的调查,我们必须知道您所处的平台,以及您的实际(实现)类名的确认。 Clip Mixer 实例。

    更新

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

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

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

    如果 多伊奥 等。访问结果 要成为问题,那么继续挖掘本机实现仍然是需要做的事情;如果 多伊奥 访问等 结果是问题再次出现,没有简单的解决方法(你可以试着用内省来抓住 DirectClip.thread 并定期发出信号,以防因 多伊奥 --再次确认。)