2016-07-26 1 views
1

AVFoundation을 사용하여 1-2 이외의 추가 오디오 하드웨어 출력에 액세스하려면 어떻게합니까? 나는 다양한 출력 장치를 통해 MP3 파일을 재생하는 맥 OS-X 응용 프로그램에 대한 신속한 코드를 쓰고 있어요 (USB 인터페이스, 단테, soundflower)는 다음과 같습니다AVFoundation 및 Swift를 사용하여 여러 오디오 하드웨어 출력/채널에 액세스

myPlayer = AVPlayer(URL: myFilePathURL) 
myPlayer.audioOutputDeviceUniqueID = myAudioOutputDevices[1].deviceUID() 
myPlayer.play() 

을하지만, 나는 방법을 잘 모르겠어요 오디오 파일을 단지 1-2 이외의 채널로 재생할 수 있습니다. 예를 들어 mp3를 출력 3-4로 재생하고 싶습니다.

AVPlayer를 통해이 작업을 수행 할 수 있습니까? 아니면 다른 곳을 봐야합니까? 아마도 믹서 노드와 함께 AVAudioEngine? AVAudioEngine 예제를 살펴 보았고 어느 곳에서나 참조 된 하드웨어 채널을 찾을 수 없었습니다. 어떤 도움을 주셔서 감사합니다!

+0

AVAudioEngine은 iOS 프레임 워크 일뿐입니다. iOS 및 OS-X 프레임 워크 용 Apple 설명서는 서로 얽혀 있습니다. 슬프게도 각 플랫폼별로 사용할 수있는 것에 대한 설명이 많지 않습니다. –

+0

mainMixerNode와 함께 AVAudioEngine 및 AVAudioPlayerNode를 사용하는 다른 경로를 찾으려고합니다. mainMixerNode를 기본값이 아닌 다른 하드웨어 채널에 할당 할 수 있는지 여부를 파악하지 못했습니다. 어쩌면 이것은 AVPlayer를 사용하는 것보다 나은 경로일까요? –

+0

[여기] (https://developer.apple.com/library/prerelease/content/technotes/tn2091/_index.html#//apple_ref/doc/uid/DTS10003118-CH1-CHANNELMAPPING)에 설명 된대로 채널 맵 작업을 시작했습니다. 아직 일하지 않고 있지만 곧 만만치 않다. –

답변

1

채널 맵 속성을 설정하는 2 개의 채널로 작업하는 신속한 버전이 있습니다. 완전한 멀티 채널 시스템으로 테스트하지는 않았지만 원칙은 동일해야합니다.

let engine = AVAudioEngine() 
let player = AVAudioPlayerNode() 

func testCode(){ 

    // get output hardware format 
    let output = engine.outputNode 
    let outputHWFormat = output.outputFormatForBus(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.attachNode(player) 


    //find the audiofile 
    guard let audioFileURL = NSBundle.mainBundle().URLForResource("tones", withExtension: "wav") else { 
     fatalError("audio file is not in bundle.") 
    } 


    var songFile:AVAudioFile? 
    do { 
     songFile = try AVAudioFile(forReading: audioFileURL) 
     print(songFile!.processingFormat) 

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

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



    let channelMap: [Int32] = [0, 1] //left out left, right out right 
    //let channelMap: [Int32] = [1, 0] //right out left, left out right 


    let propSize: UInt32 = UInt32(channelMap.count) * UInt32(sizeof(sint32)) 

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

    print(code) 


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

    player.scheduleFile(songFile!, atTime: nil) { 
     print("done") 
     self.player.play() 
    } 

    player.play() 



} 
+0

입력을 통해이를 수행하는 방법을 알고 있습니까? 8ch 인터페이스가 있지만 믹서 노드가 인터페이스의 특정 채널을 듣기를 원합니다. – JoeBayLD

+0

이 예제를 시도하고 왼쪽 및 오른쪽 채널의 파일을 여전히 재생 ... – tsugua

+0

입력면에서이 작업을 수행하지 않았습니다. 그러나 저는 출력측과 함께 16 개의 스테레오 출력 (하드웨어 또는 사운드 플라워/가상 단테)을 통해 피드를 보내고 있습니다. –

0

시간이 지남에 따라이 코드를 반복했지만 기본 개요가 작동합니다. 다음은 멀티 채널 설정에 오디오를 보내는 현재 설정 코드입니다. 나는 아래의 코드를 사용하여 16 개의 스테레오 인스턴스 스트림으로 단테 가상 사운드 카드를 사용하고 있습니다 :

func setupAudioPath(){ 
    //print("setupAudioPath") 

    // get output hardware format 
    let output = engine.outputNode 
    outputHWFormat = output.outputFormat(forBus: 0) 

    //print("outputHWFormat = \(outputHWFormat)") 
    //print("outputHWFormat.channelCount = \(outputHWFormat.channelCount)") 

    // connect mixer to output 
    mixer = engine.mainMixerNode 

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

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

    var channelMap: [sint32] = [] 
    //UInt32 numOfChannels = fileFormat.NumberChannels(); 
    let numOfChannels: UInt32 = UInt32(numberOfStreams) * UInt32(2); // Number of output device channels 
    let mapSize: UInt32 = numOfChannels * UInt32(MemoryLayout<sint32>.size); 
    for _ in 0...(numOfChannels-1) { 
     channelMap.append(-1) 
    } 
    //channelMap[desiredInputChannel] = deviceOutputChannel; 
    channelMap[leftChannel - 1] = 0; 
    channelMap[leftChannel]  = 1; 


    //print(channelMap) 
    //print("number of channels in my map: \(channelMap.count)") 

    let code: OSStatus = AudioUnitSetProperty((engine.outputNode.audioUnit)!, 
               kAudioOutputUnitProperty_ChannelMap, 
               kAudioUnitScope_Global, 
               1, 
               channelMap, 
               mapSize); 


    print("osstatus = \(code)") 
} 
관련 문제