2

我最近问了一个关于控制 Java 音频剪辑音量的问题,有人建议我尝试 JMF。由于我使用的是旧的 JVM (1.4) 并且只对播放 WAV 文件感兴趣,因此 JMF 是一个完美的解决方案,并且大大简化了在我的应用程序中加载、播放和控制音频剪辑音量的代码。

但我无法按需停止剪辑。它看起来像 call 一样简单player.stop(),但stop()似乎在玩家完成游戏之前一直阻塞。这是一个简单的代码示例:

Player p = Manager.createRealizedPlayer( f.toURI().toURL() );

p.start();
System.out.println( "Player playing" );

Thread.sleep( 1000 );
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );

p.stop();
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );

这会产生如下输出:

Player playing
 Clip is at time: 0.8591836730000001
 Clip is at time: 3.227619047

我预计第二次阅读的时间与第一次相同或仅稍晚于第一次。(或者可能已经重置为 0 或其他东西。)我也尝试过p.setStopTime( p.getMediaTime() ). 这会按时停止剪辑,但会在停止之前播放片刻的失真,这是不可取的。

谷歌搜索让我觉得其他人没有这个问题,而且很难找到选择。这可能是一个缓冲问题还是我错过了其他东西?非常感谢您提供的任何见解。


详细信息:我正在使用(并且无法更改)JVM 1.4.2 和 JMF 2.1.1。我所有的 WAV 文件只有 1-10 秒长。

4

2 回答 2

2

事实上,这是一个缓冲问题。我花了一段时间才找到这个,因为当我尝试使用以下代码片段显示可用控件时,没有列出 BufferControls:

Player p = ...
Control cs[] = p.getControls();
for ( int j = 0; j < cs.length; j++ )
  System.out.println( "  Found control: " + cs[j].getClass().getCanonicalName() );

最终,我只是盲目地尝试使用此代码段获取 BufferControl 并且它起作用了:

BufferControl bc = (BufferControl) p.getControl( "javax.media.control.BufferControl" );

经过更多的探索和摆弄,结果发现默认的缓冲区长度是 2 秒。将缓冲区长度减少到 1 秒使我能够正确停止 2.5 秒或更长的 WAV 文件。将它进一步减少到 0.5 秒最终给了我最初在所有输入文件上寻求的行为。

在不查看 JMF 源的情况下,我假设我只是遇到了一个问题,即音频正在以 2 秒的块读取和播放(2 秒是缓冲区的长度。)并且这些块必须完成播放- 无论出于何种原因 - 在他们被阻止之前。将它减少到 0.5 秒可能实际上并不能解决问题(如果声音在被告知停止后继续播放),但它至少会将问题减少到不明显的程度。此外,我所有的 WAV 文件都很小而且是本地文件,所以播放中的延迟或跳过应该不是问题。

最后,这里是原始问题的代码片段的修订版,它产生了所需的行为:

Player p = Manager.createRealizedPlayer( f.toURI().toURL() );

BufferControl bc = (BufferControl) p.getControl( "javax.media.control.BufferControl" );
if ( bc != null )
  bc.setBufferLength( 500 ); // buffer length specified in milliseconds

p.start();
System.out.println( "Player playing" );

Thread.sleep( 1000 );
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );

p.stop();
System.out.println( " Clip is at time: " + p.getMediaTime().getSeconds() );
于 2009-11-11T17:25:15.427 回答
0

我也只有短音频文件有这个问题。设置缓冲区没有帮助。我最终大胆地为音频添加了静音。

我讨厌 JMF :)

编辑:好吧,当您有一个简短的音频文件时,JMF 也会阻止 GainControl.setLevel() 调用。我想问题的根源是相同的,JMF 只是阻止您的请求(设置音量,停止),直到短文件完成。

于 2011-04-27T04:17:55.797 回答