2

我有 15 个 WAV 文件,需要在各个频道上按顺序播放。我开始尝试让两个文件使用左/右立体声分离。

我正在创建一个音频引擎、一个混音器和两个 AVAudioPlayerNode。音频文件是单声道的,我试图让 PlayerA 的文件从左声道输出,而从 PlayerB 的文件从右声道输出。我无法理解的是 AudioUnitSetProperty 的工作原理。它似乎只与一个文件有关,而且每个音频单元似乎只能有一个?我想知道是否有一种方法可以将文件与 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)  

}  
4

1 回答 1

0

engine.connect(混合器,到:输出,格式:outputHWFormat)

这不是必需的,混音器在访问时将被隐式连接。

至于平移: AudioUnitSetProperty 也不是必需的。AVAudioPlayerNode 符合AVAudioMixing,因此由于播放器下游有一个混音器节点,您所要做的就是:

playerA.pan = -1
playerB.pan = 1
于 2017-09-05T23:31:52.570 回答