在 JMF 中停止音频播放器时出现错误

发布于 2024-08-10 19:40:28 字数 1056 浏览 10 评论 0原文

我最近问了一个关于控制 Java 音频剪辑的音量的问题,有人建议我尝试 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 秒长。

I recently asked a question about controlling the volume of a Java audio clip and it was suggested that I try JMF. As I'm using an old JVM (1.4) and only interested in playing WAV files, JMF was a perfect solution and has greatly simplified the code to load, play, and control the volume of audio clips in my application.

But I'm having trouble stopping the clips on demand. It would seem as simple as calling player.stop(), but stop() seems to block until the player has finished playing. Here is a simple code example:

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() );

This produces output like:

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

Where I would have expected the second time to read equal to or only briefly later than the first. (Or perhaps to have been reset to 0 or something.) I have also tried p.setStopTime( p.getMediaTime() ). This stops the clip on time, but plays a split second of distortion before stopping, which is undesirable.

Googling around makes me think that others aren't having this issue, and it's been kind of hard to find options. Could this be a buffering issue or am I missing something else? Any insight you can provide is greatly appreciated.


Details: I am using (and cannot change) JVM 1.4.2 with JMF 2.1.1. All of my WAV files are only 1-10 seconds long.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

触ぅ动初心 2024-08-17 19:40:28

这确实是一个缓冲问题。我花了一段时间才找到这个,因为当我尝试使用以下代码片段显示可用的控件时,没有列出 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() );

And indeed it was a buffering issue. It took me a while to find this because when I attempted to display the available Controls with the following code snippet, there were no BufferControls listed:

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

Eventually I just made a blind stab at getting a BufferControl with this snippet and it worked:

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

After probing and fiddling around some more it turned out that the default buffer length was 2 seconds. Reducing the buffer length to 1 second allowed me to correctly stop WAV files which were 2.5 seconds long or longer. Further reducing it to .5 seconds ended up giving me the behavior I was originally seeking on all of my input files.

Without looking at the JMF source, I'm assuming that I was just running into an issue where the audio was being read and played in 2 second chunks (2 sec being the length of the buffer.) and that those chunks had to finish playing -- for whatever reason -- before they could be stopped. Reducing it to .5 seconds might not actually be fixing the problem (if the sounds keep playing after they're told to stop) but it will at least reduce the issue to the point of not being noticeable. Furthermore, all of my WAV files are small and local, so latency or skips in playback shouldn't be a problem.

In the end, here is the revision of the code snippet from the original question that results the desired behavior:

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() );
别念他 2024-08-17 19:40:28

我也仅在使用短音频文件时遇到此问题。设置缓冲区没有帮助。我最终大胆地给音频添加了静音。

我讨厌 JMF :)

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

I was having this problem with short audio files only, too. Setting the buffer didn't help. I ended up adding silence to the audio in audacity.

I hate JMF :)

Edit: Well, JMF also blocks GainControl.setLevel() calls when you have a short audio file. I guess the root of the issue is the same, JMF just blocks your request (set volume, stop) till the short file is complete.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文