2017-11-24 14 views
0

私はすぐに録音して再生しようとしています。私はそれぞれ左チャンネルと右チャンネルで演奏する必要があります。 AudioUnitを使用して1つのチャンネルで録音して再生できます。しかし、2つのバッファを使って2つのチャンネルを制御しようとすると、両方ともミュート状態になります。ここで私は書式を設定方法は次のとおりです。AudioUnit - スウィフトの左チャンネルと右チャンネルの出力を制御します

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 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 
} 

はaudiobufferの宣言です:

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

出力や入力部分に何かがありますか?どんな助けでも本当にありがとう!

+0

Core Audio(ビデオが利用可能)の新機能に関する2017 WWDCセッションでは、アップルのエンジニアが、音声コンテキストでSwiftまたはObjective Cコードを使用しないことを推奨しました。ストレートCコード(またはメモリ管理のないストレートCコードに変換する可能性のあるスウィフトコード)は、Audio Unitコールバック内では問題ありません。 – hotpaw2

+0

ええ、Core Audioはすぐにすばやく翻訳されないようです。しかし、何らかの理由でそれを行うにはまだ何らかの方法を見つける必要があります。 –

答えて

0

最初の大きな問題は、コードが オーディオコールバック内でメモリ割り当てを行っていることです。 Appleのドキュメンテーションでは、メモリの管理、同期化、またはオブジェクトメッセージングは​​、オーディオコンテキストの中で行われることはないと明示的に述べています。オーディオコールバックの内部では、オーディオサンプルのデータコピーをあらかじめ割り当てられたバッファとの間でのみ行うことができます。他のすべて(特に、バッファの作成と割り当て解除)は、オーディオコールバックの外で行う必要があります。

+0

お返事ありがとうございます。はい、あなたは正しいです。私は、オーディオコールバック内のメモリを管理すべきではありません。私がやろうとしているのは、inputCallbackでAudioUnitRenderをプリフォームした後です。私はbufferListからデータを取得できます。私がoutputcallbackでioDataに送り返すと、スピーカーからの音が聞こえます。私は、ioDataは左チャンネルと右チャンネルを制御できる2つのバッファを持つべきだと思います。だから私はioData!.pointee.mNumberBuffers = 2を変更し、2番目のバッファが割り振りではないことを発見しました。(そのようにしてメモリを管理しようとしています)ioDataは2つのバッファによって左チャンネルと右チャンネルにデータを設定しません。 –

+0

私はまだ左チャンネルまたは右チャンネルをミュートする方法を知らないのですか?何かヒント? @ hotpaw2 –

関連する問題