Воспроизведение нескольких WAV из нескольких каналов AVAudioEngine

У меня есть 15 WAV-файлов, которые мне нужно воспроизводить последовательно по отдельным каналам. Я начинаю пытаться заставить два файла работать с левым / правым стереоразделением.

Я создаю аудио движок, микшер и два узла AVAudioPlayerNode. Аудиофайлы монофонические, и я пытаюсь получить файл от PlayerA для выхода из левого канала и файл от PlayerB для выхода из правого канала. Что мне трудно понять, так это то, как работает AudioUnitSetProperty. Кажется, он относится только к одному файлу и может иметь только один на audioUnit? Мне интересно, есть ли способ связать файл с audioUnit? Я не могу вернуть объект audioUnit, связанный с каждой дорожкой.

func testCode(){  

    // get output hardware format  
    let output = engine.outputNode  
    let outputHWFormat = output.outputFormat(forBus: 0)  
    // connect mixer to output  
    let mixer = engine.mainMixerNode  
    engine.connect(mixer, to: output, format: outputHWFormat)  


    //then work on the player end by first attaching the player to the engine  
    engine.attach(playerA)  
    engine.attach(playerB)  


    //find the audiofile  
    guard let audioFileURLA = Bundle.main.url(forResource: "test", withExtension: "wav") else {  
        fatalError("audio file is not in bundle.")  
    }  

    guard let audioFileURLB = Bundle.main.url(forResource: "test2", withExtension: "wav") else {  
        fatalError("audio file is not in bundle.")  
    }  

    var songFileA:AVAudioFile?  
    do {  
        songFileA = try AVAudioFile(forReading: audioFileURLA)  
        print(songFileA!.processingFormat)  

        // connect player to mixer  
        engine.connect(playerA, to: mixer, format: songFileA!.processingFormat)  

    } catch {  
        fatalError("canot create AVAudioFile \(error)")  
    }  


    let channelMap: [Int32] = [0, -1] //play channel in left  


    let propSize: UInt32 = UInt32(channelMap.count) * UInt32(MemoryLayout<sint32>.size)  

    print(propSize)  

    let code: OSStatus = AudioUnitSetProperty((engine.inputNode?.audioUnit)!,  
                                              kAudioOutputUnitProperty_ChannelMap,  
                                              kAudioUnitScope_Global,  
                                              1,  
                                              channelMap,  
                                              propSize);  
    print(code)  


    let channelMapB: [Int32] = [-1, 0] //play channel in left  

    var songFileB:AVAudioFile?  
    do {  
        songFileB = try AVAudioFile(forReading: audioFileURLB)  
        print(songFileB!.processingFormat)  

        // connect player to mixer  
        engine.connect(playerB, to: mixer, format: songFileB!.processingFormat)  

    } catch {  
        fatalError("canot create AVAudioFile \(error)")  
    }  

    let codeB: OSStatus = AudioUnitSetProperty((engine.inputNode?.audioUnit)!,  
                                              kAudioOutputUnitProperty_ChannelMap,  
                                              kAudioUnitScope_Global,  
                                              1,  
                                              channelMapB,  
                                              propSize);  

    print(codeB)  


    do {  
        try engine.start()  
    } catch {  
        fatalError("Could not start engine. error: \(error).")  
    }  

    playerA.scheduleFile(songFileA!, at: nil) {  
        print("done")  
        self.playerA.play()  
    }  
    playerB.scheduleFile(songFileA!, at: nil) {  
        print("done")  
        self.playerB.play()  
    }  

    playerA.play()  
    playerB.play()  

    print(playerA.isPlaying)  

}  

1 ответ

engine.connect(mixer, to: output, format: outputHWFormat)

Это не обязательно, микшер будет неявно подключен при доступе.

Что касается панорамирования: AudioUnitSetProperty также не является необходимым. AVAudioPlayerNode соответствует AVAudioMixing, поэтому, поскольку ниже по потоку от проигрывателя находится узел микшера, все, что вам нужно сделать, это:

playerA.pan = -1
playerB.pan = 1
Другие вопросы по тегам