如何在Java游戏中播放声音?

发布于 2024-08-21 09:01:49 字数 531 浏览 2 评论 0原文

我使用以下代码成功在 Java (1.5) 小程序游戏中播放声音:(

// get an available clip to play it
Clip clip = null;
for (Clip clipTemp : players) {
    if (!clipTemp.isOpen()) {
    clip = clipTemp;
        break;
    }
}
if (clip == null) {
    // no available player found, don't play
    return;
}

clip.open(audioFormat, audioByteData, 0, audioByteData.length);

clip.start();

播放器是我在开始时打开的剪辑列表,目的是减少延迟,当停止事件发生时,线路侦听器会关闭线路已检索。)

我面临的问题是播放声音时间歇性延迟最多 1 秒。这可真够可怜的。

有什么办法可以改善这一点吗? SourceDataLines 值得考虑吗?

I'm successfully playing sounds in a Java (1.5) applet game using the following code:

// get an available clip to play it
Clip clip = null;
for (Clip clipTemp : players) {
    if (!clipTemp.isOpen()) {
    clip = clipTemp;
        break;
    }
}
if (clip == null) {
    // no available player found, don't play
    return;
}

clip.open(audioFormat, audioByteData, 0, audioByteData.length);

clip.start();

(Players are a list of clips that I open at the start with the aim to reduce latency, a line listener closes the line when the stop event is retrieved.)

The problem I'm facing is intermittent delays of upto 1 second when playing a sound. This is pretty poor.

Is there any way to improve this? Are SourceDataLines worth considering?

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

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

发布评论

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

评论(2

油饼 2024-08-28 09:01:49

只要您想播放剪辑,Java Applet 就会对您的剪辑进行流式传输,这就是为什么您会遇到延迟,因为声音文件尚未加载到内存中。

我已经有一段时间没有进行 Java 小程序编程了,但我确实记得我曾经预加载所有剪辑,然后后续的播放调用不会重新打开文件。

这是我的一个旧项目中的一些代码

Clip shoot;

private loadShootWav()
{
    AudioInputStream sample;
    sample = AudioSystem.getAudioInputStream(this.getClass().getResource("shoot.wav"));
    shoot = AudioSystem.getClip();
    shoot.open(sample);
}

public void playShootSFX()
{
    shoot.stop();
    shoot.setFramePosition(0);
    shoot.start(); 
}

The Java Applet is streaming your clip whenever you want to play it, which is why you are getting a delay as the sound file hasn't been loaded into memory yet.

It's been awhile since I have done Java applet programming, but I do remember that I used to pre-load all my clips and then subsequent calls to play would not re-open the files.

Here is some code from one of my old projects

Clip shoot;

private loadShootWav()
{
    AudioInputStream sample;
    sample = AudioSystem.getAudioInputStream(this.getClass().getResource("shoot.wav"));
    shoot = AudioSystem.getClip();
    shoot.open(sample);
}

public void playShootSFX()
{
    shoot.stop();
    shoot.setFramePosition(0);
    shoot.start(); 
}
霓裳挽歌倾城醉 2024-08-28 09:01:49

如果我正确地阅读了您的代码,您将找到一个未打开的剪辑并在播放之前将其打开。采取打开的剪辑并重新启动它们会更快。您可能必须先停止并重置它们的位置,如 playShootSFX() 示例中的 JSmyth 所示。

我从 SourceDataLines 得到了很好的回应。好处是它们比未打开的剪辑启动得更快,因为它们立即启动,而不是等到声音的所有数据都加载到 RAM 中(每次“打开”剪辑时都会发生这种情况)。

但是,是的,如果您有很多经常播放的小声音,那么剪辑池就是您的最佳选择。如果您希望它们重叠,或者始终播放完整,那么您需要多个副本。如果不是,则停止,重置为 0,然后重新启动。但不要继续重新开放!如果您这样做,不妨使用 SourceDataLine。

If I am reading your code correctly, you are finding an unopened clip and opening it before playing it. It would be quicker to take opened clips and restart them. You might have to stop and reset their positions first, as shown by JSmyth in playShootSFX() example.

I am getting pretty good response with SourceDataLines. The nice thing is that they start quicker than an unopened Clip, since they start right away instead of waiting until ALL the data for the sound is loaded into RAM (which occurs each time you "open" a Clip).

But, yes, if you have a lot of little sounds that are played frequently, a clip pool is the way to go. If you want them to overlap, or always play to completion, then you need multiple copies. If not, then stop, reset to 0 and restart. But don't keep reopening! If you are doing that, you might as well use a SourceDataLine.

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