Swift iOS,使用 AVAudioPlayer 从数组中顺序播放曲目,每个曲目之间有一些功能?

Swift iOS, Play tracks sequentially from array using AVAudioPlayer, with some function in between each track?

我有一组音频指令,我想随机化、播放(一次一个),并在每条指令之间做一些数据记录。

使用下面的代码,我有一个触发 beginTest() 的按钮按下,但指令轨道同时播放。它永远不会到达 startRecord()。

我试过将 startRecord() 放在 audioPlayerDidFinishPlaying 中;在这种情况下,它确实会到达第一首曲目的 startRecord(),但不会继续到调用 playScript() 的 beginTest() 内循环的下一次迭代。

func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool)
{
    self.player = nil
    print("finished playing this file")

}

func playScript(c: String)
{
    let path = Bundle.main.path(forResource: c, ofType:"m4a")!
    let url = URL(fileURLWithPath: path)

    do {
        self.player = try AVAudioPlayer(contentsOf: url)
        self.player?.delegate = self
        self.player?.play()
        print(c)
        print("playing script for " + c)
    } catch {
        print("couldn't load script")
    }
}

func beginTest()
{
    for c in conditions.shuffled()
    {
        playScript(c: c)
        
        if self.player == nil
        {
            startRecord()
            print("started data recording")
        }
    }
    
    exportData()
}

我猜 beginTest() 在 audioPlayerDidFinishPlaying 将播放器重置为 nil 之前一直沿着 for 循环移动,但我不知道如何停止它。

使用audioPlayerDidFinishPlaying(_:,successfully:)的方法是正确的。在您的代码中,当您调用 playScript(c:) 时,您将遍历 conditions 数组中的所有音频文件并在播放第一个音频时非常快速地调用 startRecord 方法。所有声音将被放入一个队列中并一个一个地播放。我不知道 startRecord 方法的内容,但我不认为应该这样调用它。

为了避免这些问题,您需要调用 playScript(c:) 然后等待方法 startRecord() 完成,然后再次调用 playScript(c:)。所以你可以尝试这样的事情:

import AVFoundation

class SomeClass: NSObject, AVAudioPlayerDelegate {
    
    var player: AVAudioPlayer?
    var conditions = [String]()
    var instructions: [() -> ()] = []
        
    func audioPlayerDidFinishPlaying(_ player: AVAudioPlayer, successfully flag: Bool) {
        print("finished playing \(player.url)")
        startRecord {
            playNextInstruction()
        }
    }

    func playScript(c: String)
    {
        let path = Bundle.main.path(forResource: c, ofType:"m4a")!
        let url = URL(fileURLWithPath: path)

        do {
            self.player = try AVAudioPlayer(contentsOf: url)
            self.player?.delegate = self
            self.player?.play()
            print(c)
            print("playing script for " + c)
        } catch {
            print("couldn't load script")
        }
    }

    func beginTest() {
        instructions = conditions.shuffled().map { [unowned self] condition in
            return {
                self.playScript(c: condition)
            }
        }
        playNextInstruction()
    }
    
    func playNextInstruction() {
        if instructions.count != 0 {
            instructions.remove(at: 0)()
        } else {
            exportData()
        }
    }
    
    func exportData() {
    
    }
    
    func startRecord(completion: (() -> ())) {
        
    }
        
}

如果它不起作用,那么我建议尝试在您的代码中的其他地方搜索问题。