首页 > 解决方案 > 如果轨道不是从头开始的,如何使用循环(缓冲类型 = .always 在 AKPlayer 中)

问题描述

我运行了几个具有不同文件和相同长度的AKPlayer——第一个从头开始,其他的从按钮开始,相对于第一个的时间。文件是无缝的,值得缓冲 type = .always,loop = true。如果AKPlayer 没有从头开始,那么只有从该曲目开始播放到结束的那部分曲目,并且当循环发生时,starts StartTime 不是零值。循环播放时,必须从头开始播放所有曲目。使用 AKWaveTable,一切正常,但播放器中没有平移和音高设置。

这是一个示例代码。在原版中,我使用了一系列播放器,并在循环中将所有文件上传到我的播放器。我正在做类似鼓机的事情 - 正在播放几个音频文件,我可以根据播放器首次启动的时间并行打开/关闭其他文件。每个文件的持续时间相同。当我在 AKWaveTable 中执行相同操作时,一切正常,但将来它不适合我。在此示例中,我首先运行 playPlayer1 方法,然后运行 ​​playPlayer2。当 Player1 从头开始​​循环时,Player2 从上一个 currentTime 开始循环(例如从文件中间开始),并且它的长度永远相等(endTime - currentTime)

 var player1: AKPlayer!
    var player2: AKPlayer!
    var playersMixer: AKMixer!

    init() {
        do {
            let file1 = try AKAudioFile(readFileName: "Audio/file1.m4a")
            let file2 = try AKAudioFile(readFileName: "Audio/file2.m4a")

            player1.load(audioFile: file1)
            player2.load(audioFile: file2)
        } catch {
            print(error.localizedDescription)
        }

        player1.buffering = .always
        player1.isLooping = true
        player2.buffering = .always
        player2.isLooping = true

        playersMixer = AKMixer (player1,player2)
        AudioKit.output = playersMixer
        do {
           try AudioKit.start()
        } catch {
            print(error.localizedDescription)
        }
    }
    func playPlayer1() {
        player1.play()
    }
    func playPlayer2() {
        player2.play(from: currentTime)
    }
    var currentTime: Double {
        get {
            if player1.isPlaying {
                return player1.currentTime
            }
            return 0
        }
    }

标签: swiftaudiokit

解决方案


我认为这是 AudioKit 中缺少的功能或错误。同时,当前版本确实使用了startTimefor 循环点,正如我们在源代码中看到的那样(https://github.com/AudioKit/AudioKit/blob/master/AudioKit/Common/Nodes/Playback/Players/Player/AKPlayer .swift )

同时,我找到了一个解决方案,希望它对其他读者有用:

                    player.isLooping = false
                    player.buffering = .dynamic
                    player.completionHandler = {
                        player.isLooping = true
                        player.buffering = .always
                        player.play(from: 0, to: player.duration)
                    }
                    player.play(from: masterPlayer.currentTime)

我正在做的是创建一个玩家并设置.isLooping错误.buffering并调用.play将其作为一次性或单发游戏运行!在.completionHandler完成时调用回调,我在其中设置.isLooping.buffering积极。最后,使用属性和from调用.play设置所需的循环点。指的是一个单独的,用作获取当前播放位置的参考,我知道这很容易理解,但只是为了避免假设。fromtoselfmasterPlayerplayer

编辑:

在进行投掷测试后,我发现了一个我之前报告并删除的问题(是否支持同步循环,其持续时间为倍数的 AKPlayers?)并且不得不重新打开,所以希望我能得到答案并帮助理解它是否是应该工作与否。

也被迫playerdetach创建了一个新的:

                        player.completionHandler = {
                            player.detach()
                            let player = self.createPlayer(audioFile: audioFile)
                            self.connectPlayerToMixer(player)
                            player.isLooping = true
                            player.buffering = .always
                            player.startTime = 0
                            player.endTime = audioFile.duration
                            player.play(at: AVAudioTime.now())
                        }

我现在已经测试过了AKWaveTable,希望我做对了,但是在录制是预览录制大小的两倍之后它也失败了,例如:

  • 循环 1 > 1 2 3 4
  • 循环 2 > 1 2 3 4
  • 循环 3 > 1 2 3 4 5 6 7 8
  • 循环 4 > 1 2 3 4
  • Loop5 > 5 6 7 8(记录为 1 2 3 4 5 6 7 8,但播放为 5 6 7 8)

我将不得不返回并测试原件AKNodeRecorder以查看行为是否相似,但目前我将尝试使用AKWaveTable.

    • 经过一段时间的测试 * *

这是描述上述问题的录音:

https://drive.google.com/open?id=1zxIJgFFvTwGsve11RFpc-_Z94gEEzql7

在研究了一段时间后,我发现了所有的研究似乎是一个解决方案。通过转移使用的程序!与其将播放器设置为沿当前时间开始,不如将其安排为从开始时间开始。这是因为开始时间是用于循环开始和端点的!要了解更多信息,请点击我之前发布的另一篇 StackOverflow 帖子的链接(此处提供了解决方案(对于持续时间为倍数的 AKPlayers 是否支持同步循环?),谢谢!


推荐阅读