【问题标题】:Java Seamless Audio Transition/LoopJava 无缝音频转换/循环
【发布时间】:2019-06-20 22:00:40
【问题描述】:

如何确保两段音频之间的无缝过渡?

在 JavaFX 应用程序中,我使用 javafx.scene.media.MediaPlayer 播放一段介绍片段,该片段由主/循环片段进行。媒体播放得很好,但问题是过渡和循环。

这是我目前正在做的事情:

private static void foo(final Media intro, final Media loop) {
        final MediaPlayer introPlayer = new MediaPlayer(intro);
        introPlayer.play();

        final MediaPlayer loopPlayer = new MediaPlayer(loop);
        loopPlayer.pause(); //  An attempt to load the media so it will be ready to be played.

        introPlayer.setOnEndOfMedia(loopPlayer::play());

        loopPlayer.setOnEndOfMedia(() -> loopPlayer.seek(Duration.ZERO));
        //loopPlayer.setCycleCount(Integer.MAX_VALUE); // Similar to the above line, but there is still a delay between loops.
    }

MediaPlayer::pause 确实有一些帮助,但是在介绍媒体结束和循环媒体开始之间有一个非常明显的延迟。此外,在循环媒体结束和重复之间还有另一个明显的延迟。

我还尝试使用javafx.scene.media.AudioClip,因为据说它的开销比javafx.scene.media.MediaPlayer 少。我编写了自己的监听器来告知曲目何时结束(并在之后立即开始循环播放),但我仍然看到了类似的延迟。

我找到了一些类似的帖子,但没有提供解决问题的方法:

JavaFX MediaPlayer playing background music loop with small intro music

这个肯定是相关的(巧合的是,它几乎是 那篇文章的周年纪念日),但我已经在使用 .wav 格式 媒体文件,但仍然会遇到延迟。

JavaFX AudioClip.play()

这与我尝试使用 Audioclip 的方法类似,但我使用了 计划的执行者何时重播音频。 (我还在的地方 遇到延迟)。

最后,我已经在 Audacity 中测试了我的音频,它们可以无缝地转换和循环播放。

对于这些类型的问题有哪些推荐的解决方案?

编辑:

  1. 在代码块中添加了附录,提及 MediaPlayer::setCycleCount(Integer)

【问题讨论】:

    标签: java audio javafx java-8 audio-player


    【解决方案1】:

    AudioClip Javadocs 声明 AudioClip 表示可以以最小延迟播放并立即可用的音频片段。但是,它也指出

    不过,媒体对象更适合长时间播放的声音。这主要是因为 AudioClip 将整个声音的原始、未压缩的音频数据存储在内存中,这对于长音频剪辑来说可能非常大。 MediaPlayer 将仅在内存中预滚动足够的解压缩音频数据以在短时间内播放,因此对于长剪辑而言内存效率要高得多,尤其是在压缩时。

    根据循环媒体的长度,AudioClip 可能更适合您。您可以使用AudioClip.setCycleCount(AudioClip.INDEFINITE) 来永久循环播放音频,而不是需要ScheduledExecutorService

    使用此信息,我相信您最好的选择是使用MediaPlayer 进行介绍,然后使用MediaPlayer#setOnEndOfMedia 调用循环AudioClip;可能在介绍和循环过渡之间有一个小的延迟,但在那之后是无缝的。

    【讨论】:

    • 尝试结合这两种工具是一个有趣的想法,但我仍然遇到过渡和循环延迟。
    • 它也可能与您的代码无关,可能取决于其他因素?
    【解决方案2】:

    我知道你发帖已经有一段时间了。你找到答案了吗?我想知道你是否在玩introPlayer 之前加载了loopPlayer,如果这会有所帮助。

    如果 MediaPlayer 的“监听器”有点迟钝,也许切换到使用 Java 的 SourceDataLine 和用于触发循环提示的 LineListener 会更无缝地工作? (我会使用Clip 进行循环播放。)

    最后一个建议,我有一个音频库AudioCue 可以解决这个问题。该库包含一个AudioCueListener,它可以在提示结束时触发一个事件(例如开始另一个AudioCue 播放)。但是库的限制要求您将音乐保存在内存中,并且源文件是 .wav 的。

    【讨论】:

    • 不幸的是,我没有。我正在尝试使用音频可视化器。我改用 Unity 是因为它对音频播放器和视觉效果的支持比自制的 Java 应用程序更好。
    猜你喜欢
    • 2018-04-06
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 2012-12-06
    • 2014-01-12
    • 2015-05-03
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多