我最近问了一个关于controlling the volume of a Java audio clip的问题,并建议我尝试JMF。由于我使用的是旧的JVM(1.4)并且只对播放WAV文件感兴趣,因此JMF是一个完美的解决方案,并且极大地简化了加载,播放和控制应用程序中音频剪辑量的代码。
但是我很难按需停止剪辑。它看起来像调用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秒长。
答案 0 :(得分: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() );
答案 1 :(得分:0)
我也遇到了短音频文件的问题。设置缓冲区没有帮助。我最后在大胆中为音频增加了沉默。
我讨厌JMF:)
编辑:嗯,当你有一个简短的音频文件时,JMF也会阻止GainControl.setLevel()调用。我想问题的根源是相同的,JMF只是阻止你的请求(设置音量,停止)直到短文件完成。