2017-11-24 26 views
0

신속한 동시 녹음 및 재생을 시도합니다. 왼쪽 채널과 오른쪽 채널에서 각각 연주해야합니다. AudioUnit을 사용하여 하나의 채널에서 녹음 및 재생에 성공했습니다. 하지만 두 개의 버퍼를 사용하여 두 개의 채널을 제어하려고하면 두 개의 채널 모두 음소거됩니다. 여기에 내가 포맷 설정 방법은 다음과 같습니다 여기 AudioUnit - Swift에서 왼쪽 채널 및 오른쪽 채널 출력 제어

private let outputCallback:AURenderCallback = { 
    (inRefCon, 
    ioActionFlags, 
    inTimeStamp, 
    inBusNumber, 
    inNumberFrames, 
    ioData) -> OSStatus in 
    let audioRAP:AudioUnitSample = Unmanaged<AudioUnitSample>.fromOpaque(inRefCon).takeUnretainedValue() 
    if ioData == nil{ 
     return noErr 
    } 
    ioData!.pointee.mNumberBuffers = 2 
    var bufferCount = ioData!.pointee.mNumberBuffers 

     var tempBuffer = audioRAP.audioBuffers[0] 

     var monoSamples = [Float]() 
     let ptr1 = tempBuffer.0.mData?.assumingMemoryBound(to: Float.self) 
     monoSamples.removeAll() 
     monoSamples.append(contentsOf: UnsafeBufferPointer(start: ptr1, count: Int(inNumberFrames))) 

     let abl = UnsafeMutableAudioBufferListPointer(ioData) 
     let bufferLeft = abl![0] 
     let bufferRight = abl![1] 
     let pointerLeft: UnsafeMutableBufferPointer<Float32> = UnsafeMutableBufferPointer(bufferLeft) 
     let pointerRight: UnsafeMutableBufferPointer<Float32> = UnsafeMutableBufferPointer(bufferRight) 

     for frame in 0..<inNumberFrames { 
      let pointerIndex = pointerLeft.startIndex.advanced(by: Int(frame)) 
      pointerLeft[pointerIndex] = monoSamples[Int(frame)] 
     } 
     for frame in 0..<inNumberFrames { 
      let pointerIndex = pointerRight.startIndex.advanced(by: Int(frame)) 
      pointerRight[pointerIndex] = monoSamples[Int(frame)] 
     } 

     tempBuffer.0.mData?.deallocate(bytes:tempBuffer.1, alignedTo: MemoryLayout<Int8>.alignment) 
     audioRAP.audioBuffers.removeFirst() 
    return noErr 
} 

는 오디오 버퍼에 대한 선언이다 : 여기

var audioFormat = AudioStreamBasicDescription() 
    audioFormat.mSampleRate = Double(sampleRate) 
    audioFormat.mFormatID = kAudioFormatLinearPCM 
    audioFormat.mFormatFlags = kLinearPCMFormatFlagIsSignedInteger | kLinearPCMFormatFlagIsPacked 
    audioFormat.mChannelsPerFrame = 2 
    audioFormat.mFramesPerPacket = 1 
    audioFormat.mBitsPerChannel = 32 
    audioFormat.mBytesPerPacket = 8 
    audioFormat.mReserved = 0 

을 그리고 나의 출력 콜백 내 입력 콜백 여기

private let inputCallback: AURenderCallback = {(
    inRefCon, 
    ioActionFlags, 
    inTimeStamp, 
    inBusNumber, 
    inNumberFrames, 
    ioData) -> OSStatus in 
    let audioRAP:AudioUnitSample = Unmanaged<AudioUnitSample>.fromOpaque(inRefCon).takeUnretainedValue() 
    var status = noErr; 
    var buf = UnsafeMutableRawPointer.allocate(bytes: Int(inNumberFrames * 4), 
               alignedTo: MemoryLayout<Int8>.alignment) 
    let bindptr = buf.bindMemory(to: Float.self, 
           capacity: Int(inNumberFrames * 4)) 
    bindptr.initialize(to: 0) 
    var buffer: AudioBuffer = AudioBuffer(mNumberChannels: 2, 
          mDataByteSize: inNumberFrames * 4, 
          mData: buf) 

    memset(buffer.mData, 0, Int(buffer.mDataByteSize)) 
    var bufferList: AudioBufferList = AudioBufferList(mNumberBuffers: 1, 
            mBuffers: buffer)(Int(bufferList.mBuffers.mDataByteSize))") 

    status = AudioUnitRender(audioRAP.newAudioUnit!, 
          ioActionFlags, 
          inTimeStamp, 
          inBusNumber, 
          inNumberFrames, 
          &bufferList) 
    audioRAP.audioBuffers.append((bufferList.mBuffers,Int(inNumberFrames * 4))) 

    return status 
} 

입니다

private var audioBuffers = [(AudioBuffer, Int)]() 

출력 또는 입력 부분에 뭔가가 있습니까? 어떤 도움이라도 정말 감사 할 것입니다!

+0

Core Audio (비디오 사용 가능)의 새로운 기능에 대한 2017 WWDC 세션에서 Apple 엔지니어는 오디오 컨텍스트에서 Swift 또는 Objective C 코드를 사용하지 않을 것을 권장했습니다. 스트레이트 C 코드 (또는 메모리 관리가없는 스트레이트 C 코드로 변환 될 수있는 스위프트 코드)는 오디오 유닛 콜백 내에서 정상입니다. – hotpaw2

+0

그래, 코어 오디오가 신속하게 잘 번역되지 않는 것 같습니다. 그러나 나는 아직도 어떤 이유로 그것을하기 위해 어떤 방법을 찾을 필요가있다. –

답변

0

첫 번째 큰 문제는 코드가 오디오 콜백 내에서 메모리 할당을 수행하고 있다는 것입니다. Apple 문서에서는 메모리 관리, 동기화 또는 객체 메시징조차도 오디오 컨텍스트 내에서 수행되지 않아야한다고 명시 적으로 말합니다. 오디오 콜백 내부에서 사전 할당 된 버퍼간에 오디오 샘플의 데이터 복사본 만 저장하는 것이 좋습니다. 다른 모든 것들 (특히 버퍼 생성과 할당 해제)은 오디오 콜백 외부에서 수행되어야합니다.

+0

답변 해 주셔서 감사합니다. 그렇습니다. 오디오 콜백 내에서 메모리를 관리하면 안됩니다. 내가 뭘 하려는지 InputCallback AudioUnitRender preform 후 것입니다. 내가 bufferList에서 데이터를 얻을 수 있습니다. outputcallback에서 ioData로 다시 보내면 스피커에서 소리가 들립니다. 난 ioData 왼쪽 채널과 오른쪽 채널을 제어 할 수있는 두 개의 버퍼가 있어야합니다 같아요. 그래서 ioData를 변경합니다! pointee.mNumberBuffers = 2, 그리고 두 번째 버퍼가 할당되지 않습니다. (메모리를 관리하는 그런 식으로) 나는 ioData가 두 개의 버퍼에 의해 왼쪽 채널과 오른쪽 채널에 데이터를 설정하지 않는다고 생각합니다. –

+0

왼쪽 채널이나 오른쪽 채널을 음소거하는 방법을 아직도 모릅니다. 어떤 힌트? @ hotpaw2 –