Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 使用多个播放器播放多个音频文件_Swift_Audiokit - Fatal编程技术网

Swift 使用多个播放器播放多个音频文件

Swift 使用多个播放器播放多个音频文件,swift,audiokit,Swift,Audiokit,我正在尝试使用AudioKit的AKPlayer同步播放4个mp3文件,非常成功。不过,作为我Swift研究的一部分,我想使用数组(或我还没有学会的东西)简化我的代码,因为我觉得我的代码中有多余的东西,只需复制四次播放器代码。下面是我编写的代码: let file1 = try? AKAudioFile(readFileName: "mixing_1_vocal.mp3") let file2 = try? AKAudioFile(readFileName: "mixing_2_

我正在尝试使用AudioKit的AKPlayer同步播放4个mp3文件,非常成功。不过,作为我Swift研究的一部分,我想使用数组(或我还没有学会的东西)简化我的代码,因为我觉得我的代码中有多余的东西,只需复制四次播放器代码。下面是我编写的代码:

    let file1 = try? AKAudioFile(readFileName: "mixing_1_vocal.mp3")
    let file2 = try? AKAudioFile(readFileName: "mixing_2_drums.mp3")
    let file3 = try? AKAudioFile(readFileName: "mixing_3_synth.mp3")
    let file4 = try? AKAudioFile(readFileName: "mixing_4_bass.mp3")


    let player1 = AKPlayer(audioFile: file1!)
    let player2 = AKPlayer(audioFile: file2!)
    let player3 = AKPlayer(audioFile: file3!)
    let player4 = AKPlayer(audioFile: file4!)
    let startTime = AVAudioTime.now() + 0.25

    let mixer = AKMixer()
    player1 >>> mixer
    player2 >>> mixer
    player3 >>> mixer
    player4 >>> mixer

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

    AudioKit.output = mixer

    try? AudioKit.start()
    player1.start(at: startTime)
    player2.start(at: startTime)
    player3.start(at: startTime)
    player4.start(at: startTime)

就是这样!有四种不同的音轨(单独的乐器),它们应该同时演奏,无限循环。如果有人能帮我改进代码,那将非常有帮助。是否有更好的方法来执行相同的工作?

这是一个非常开放的问题,但这里有一个iOS的ViewController示例

class ViewController: UIViewController {

    let mixer = AKMixer()
    let players: [AKPlayer] = {
        do {
            let filenames = ["mixing_1_vocal.mp3",
                             "mixing_2_drums.mp3",
                             "mixing_3_synth.mp3",
                             "mixing_4_bass.mp3"]

            return try filenames.map { AKPlayer(audioFile: try AKAudioFile(readFileName: $0)) }
        } catch {
            fatalError()
        }
    }()


    override func viewDidLoad() {
        super.viewDidLoad()

        makeConnections()
        startAudioEngine()
        preparePlayers()
        startPlayers()
    }

    func makeConnections() {
        players.forEach { $0 >>> mixer }
        AudioKit.output = mixer
    }

    func startAudioEngine() {
        do {
            try AudioKit.start()
        } catch {
            print(error)
            fatalError()
        }
    }

    func preparePlayers() {
        players.forEach { player in
            player.isLooping = true
            player.buffering = .always
            player.prepare()
        }
    }

    func startPlayers() {
        let startTime = AVAudioTime.now() + 0.25
        players.forEach { $0.start(at: startTime) }
    }

}
要点:

使用
do{try expression}catch{error}
,而不是
try?表达式
。虽然忽略一个错误很方便,但它会很快地把你咬死

而且,map对于使用阵列非常重要。请注意,文件名数组是如何转换为播放器数组的。相关的速记参数名称:
players.forEach{player.play()}
players.forEach{$0.play()}
相同。同样相关的是,map重新抛出,所以您可以在map的闭包内部进行尝试

使用闭包来封装。players变量是使用立即计算的闭包定义的。另一种方法是必须在init上创建此数组,然后在以后填充它

最后,尽可能将逻辑分离为函数。它使您的代码更可读,更易于维护