2017-09-04 10 views
1

J'ai 15 fichiers WAV que j'ai besoin de lire en séquence sur des canaux individuels. Je commence à essayer d'obtenir deux fichiers fonctionnant avec une séparation stéréo gauche/droite.Lecture de plusieurs canaux WAV multiples AVAudioEngine

Je crée un moteur audio, une table de mixage et deux AVAudioPlayerNodes. Les fichiers audio sont mono et j'essaie d'obtenir le fichier de PlayerA pour sortir le canal gauche et le fichier de PlayerB pour sortir le bon canal. Ce que j'ai de la difficulté à comprendre, c'est comment fonctionne AudioUnitSetProperty. Il semble se rapporter à un seul fichier et semble être seulement en mesure d'en avoir un par audioUnit? Je me demande s'il y a un moyen que je peux associer un fichier avec un audioUnit? Je n'arrive pas à retourner l'objet audioUnit associé à chaque piste.

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) 

} 

Répondre

0

engine.connect (mélangeur, à: sortie, format: outputHWFormat)

Ce n'est pas nécessaire, le mélangeur sera connecté implicitement quand on y accède.

Comme pour le panoramique: AudioUnitSetProperty n'est pas non plus nécessaire. AVAudioPlayerNode est conforme à AVAudioMixing, donc puisqu'il ya un aval noeud mélangeur du lecteur, tout ce que vous avez à faire est la suivante:

playerA.pan = -1 
playerB.pan = 1 
+0

Merci pour la suggestion dave. J'avais regardé la fonction de panoramique, mais j'essaie en fin de compte de sortir 15 fichiers sur 15 canaux différents, donc le panoramique ne fonctionnera pas dans cette application. – tsugua