在JMF中停止音频播放器的错误

问题描述 投票:2回答:2

我最近问了一个关于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秒长。

java audio jmf audio-player
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() );

0
投票

我也只是用短音频文件来解决这个问题。设置缓冲区没有帮助。我最后在大胆中为音频增加了沉默。

我讨厌JMF :)

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

© www.soinside.com 2019 - 2024. All rights reserved.