如果轨道不是从头开始的,那么如何使用循环(在AKPlayer中使用缓冲类型= .always)

时间:2019-09-03 03:54:17

标签: swift audiokit

我运行了几个具有不同文件和相同长度的AKPlayer-第一个从头开始,其他的从按钮开始(相对于第一个时间)。文件是无缝的,值得缓冲类型= .always,循环= true。如果AKPlayer并非从头开始,则仅从轨道开始播放到结束的那部分轨道,并且当发生循环时,开始时间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
        }
    }

1 个答案:

答案 0 :(得分:0)

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

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

                    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。最后,使用.play中的属性fromto调用self设置所需的循环点。 masterPlayer指的是单独的player,用作获取当前比赛位置的参考,我知道这很容易理解,但只是为了避免假设。

编辑:

经过掷球测试后,我发现一个问题,我之前已经报告并删除了该问题(Is synchronised looping supported for AKPlayers that are multiples in their duration?),因此不得不重新打开它,因此希望我能得到一个答案,并将帮助您了解该问题是否应该起作用

还强迫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
  • 循环5> 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帖子的链接(此处显示解决方案(Is synchronised looping supported for AKPlayers that are multiples in their duration?),谢谢!