用ExoPlayer击败相交的淡入淡出

Mar*_*ski 5 android exoplayer

我想使用ExoPlayer实现节拍匹配Crossfade功能。基本上,我对它应该如何工作有一个概念,但是我发现很难使其适应ExoPlayer。

首先,请允许我写出我想如何执行此操作,以便您了解情况。如您所知,Beat Matching Crossfade让我们从一首歌曲无缝切换到另一首歌曲。另外,它在淡入淡出期间将第二首歌曲的速度调整为第一首歌曲的速度。

所以我的计划如下:1.加载歌曲A和B,以便它们都开始缓冲。2.歌曲A和B的解码样本存储在缓冲区BF1和BF2中。3.会有一个称为MUX的类,它是一个主缓冲区,同时包含歌曲缓冲区BF1和BF2。MUX向播放器提供音频样本。提供给播放器的样本是BF1样本,或者是存在淡入淡出的BF1和BF2的混合样本。4.当缓冲区达到淡入淡出点时,会将样本发送到Analyzer类,以便它可以分析两个缓冲区中的样本并修改它们以进行淡入淡出。分析器将修改后的样本发送到MUX,MUX会更新其主缓冲区。淡入淡出完成后,请从播放列表加载下一首歌曲。

我的主要问题是如何混合两首歌曲,以便实现MUX之类的类。到目前为止,我所知道的是我可以在MediaCodecRender.processOutputBuffer()方法中访问解码的样本,因此从那时起,我可以创建BF1和BF2缓冲区。

还有一个想法是创建两个ExoPlayer实例,然后在播放第一首歌曲时分析第二首歌曲,并修改其样本以进行进一步淡入淡出,但我认为可能很难同步两个播放器,因此拍子会匹配。

在此先感谢您的帮助!

Mar*_*ski 0

回答@David 关于交叉淡入淡出实现的问题,它看起来或多或少像这样。当您想要开始交叉淡入淡出时,您必须监听活动播放器的播放并调用此方法。它采用 RxJava,但可以轻松迁移到 Couroutines Flow。

    fun crossfadeObservable(
        fadeOutPlayer: Player?,
        fadeInPlayer: Player,
        crossfadeDurationMs: Long,
        crossfadeScheduler: Scheduler,
        uiScheduler: Scheduler
): Observable<Unit> {
    val fadeInMaxGain = fadeInPlayer.audioTrack?.volume ?: 1f
    val fadeOutMaxGain = fadeOutPlayer?.audioTrack?.volume ?: 1f

    fadeOutPlayer?.enableAudioFocus(false)
    fadeInPlayer.enableAudioFocus(true)
    fadeInPlayer.playerVolume = 0f
    fadeInPlayer.play()
    fadeOutPlayer?.playerVolume = fadeOutMaxGain
    fadeOutPlayer?.play()

    val iterations: Float = crossfadeDurationMs / CROSSFADE_STEP_MS.toFloat()

    return Observable.interval(CROSSFADE_STEP_MS, TimeUnit.MILLISECONDS, crossfadeScheduler)
            .take(iterations.toInt())
            .map { iteration -> (iteration + 1) / iterations }
            .filter { percentOfCrossfade -> percentOfCrossfade <= 1f }
            .observeOn(uiScheduler)
            .map { percentOfCrossfade ->
                fadeInPlayer.playerVolume = percentOfCrossfade.coerceIn(0f, fadeInMaxGain)
                fadeOutPlayer?.playerVolume = (fadeOutMaxGain - percentOfCrossfade).coerceIn(0f, fadeOutMaxGain)
            }
            .last()
            .doOnTerminate { fadeOutPlayer?.pause() }
            .doOnUnsubscribe { fadeOutPlayer?.pause() }
}
Run Code Online (Sandbox Code Playgroud)

常量值 CROSSFADE_STEP_MS = 100L