重新启动 Clip 对象 - flush() 方法

Posted

技术标签:

【中文标题】重新启动 Clip 对象 - flush() 方法【英文标题】:Restarting a Clip object - flush() method 【发布时间】:2015-04-24 01:44:31 【问题描述】:

Javadoc for DataLine.flush() 状态

从行中清除排队的数据。刷新的数据被丢弃。在某些情况下,并非所有排队的数据都可以丢弃。例如,混音器可以从缓冲区中刷新特定输入行的数据,但仍然会播放输出缓冲区中已经存在的任何未播放数据(混合的结果)。如果您想在重新开始播放或捕获时跳过“陈旧”数据,您可以在暂停一行(正常情况)后调用此方法。 (刷新未停止的行是合法的,但在活动行上这样做可能会导致数据不连续,从而导致可察觉的点击。)

这到底是什么意思?

此外,对于重新启动 Clip 对象,该站点上的许多人建议使用此:

clip.stop();
clip.setFramePosition(0);
clip.start();

当使用上面的代码时,我注意到一个示例剪辑(如果重要的话,大约 15 秒长)不会从一开始就重新开始,并且它的“重新开始位置”不一致。但是,当我尝试

clip.stop();
clip.flush();
clip.setFramePosition(0);
clip.start();

剪辑完美运行,并在声音开始时重新开始。我的问题是,flush() 方法做了什么来解决我之前的问题?还有,我当初为什么会遇到这个问题?

【问题讨论】:

【参考方案1】:

Clip 这样的数据线有一个内部数据缓冲区,可能是byte[]。缓冲区通常会在播放位置之前以块的形式填充。

假设在某个时刻我们有:

            playback position
                   v
buffer:         [..|.....]
  file: [..........|.....................]

因此,如果我们停止该行,缓冲区中仍然有数据——位于播放位置之前的数据。

如果我们所做的只是设置播放位置,则数据仍然存在,并且会在我们下次启动时播放。刷新该行会丢弃此数据。

我们也可以致电drain 等待此数据播放完毕。

【讨论】:

@Kootling 你看我的回答了吗?这回答了你的问题了吗?你还有什么不明白的吗? 这将取决于实现。您可以通过getBufferSize 查找。 open 的一些重载也允许您指定它。我在源代码中四处寻找,似乎默认值(在com.sun.media.sound.AbstractDataLine 中找到)的大小为给定格式的 500 毫秒音频。

以上是关于重新启动 Clip 对象 - flush() 方法的主要内容,如果未能解决你的问题,请参考以下文章

从 Xcode 启动 App Clip 时未调用 SceneDelegate 的“继续”

关于hibernate的saveOrUpdate方法的一个问题

flush close

Java - 无缝更改循环剪辑的音量?

Tomcat关闭后,重新启动,session中保存的对象为什么还存在解决方法

apache是 否可以重新启动可靠地清除pagespeed缓存?