title: Low latency input/output AudioQueue
body: <p>I have two iOS AudioQueues - one input that feeds samples directly to one output. Unfortunately, there is an echo effect that is quite noticeable :(</p>
  
  <p>Is it possible to do low latency audio using AudioQueues or do I really need to use AudioUnits? (I have tried the Novocaine framework that uses AudioUnits and here the latency is much smaller. I've also noticed this framework seems to use less CPU resources. Unfortunately, I was unable to use this framework in my Swift project without major changes to it.)</p>
  
  <p>Here are some extracts of my code, which is mainly done in Swift, except those callbacks which needs to be implemented in C.</p>
  
  <pre><code>private let audioStreamBasicDescription = AudioStreamBasicDescription(
      mSampleRate: 16000,
      mFormatID: AudioFormatID(kAudioFormatLinearPCM),
      mFormatFlags: AudioFormatFlags(kAudioFormatFlagsNativeFloatPacked),
      mBytesPerPacket: 4,
      mFramesPerPacket: 1,
      mBytesPerFrame: 4,
      mChannelsPerFrame: 1,
      mBitsPerChannel: 32,
      mReserved: 0)
  
  private let numberOfBuffers = 80
  private let bufferSize: UInt32 = 256
  
  private var active = false
  
  private var inputQueue: AudioQueueRef = nil
  private var outputQueue: AudioQueueRef = nil
  
  private var inputBuffers = [AudioQueueBufferRef]()
  private var outputBuffers = [AudioQueueBufferRef]()
  private var headOfFreeOutputBuffers: AudioQueueBufferRef = nil
  
  // callbacks implemented in Swift
  private func audioQueueInputCallback(inputBuffer: AudioQueueBufferRef) {
      if active {
          if headOfFreeOutputBuffers != nil {
              let outputBuffer = headOfFreeOutputBuffers
              headOfFreeOutputBuffers = AudioQueueBufferRef(outputBuffer.memory.mUserData)
              outputBuffer.memory.mAudioDataByteSize = inputBuffer.memory.mAudioDataByteSize
              memcpy(outputBuffer.memory.mAudioData, inputBuffer.memory.mAudioData, Int(inputBuffer.memory.mAudioDataByteSize))
              assert(AudioQueueEnqueueBuffer(outputQueue, outputBuffer, 0, nil) == 0)
          } else {
              println(__FUNCTION__ + ": out-of-output-buffers!")
          }
  
          assert(AudioQueueEnqueueBuffer(inputQueue, inputBuffer, 0, nil) == 0)
      }
  }
  
  private func audioQueueOutputCallback(outputBuffer: AudioQueueBufferRef) {
      if active {
          outputBuffer.memory.mUserData = UnsafeMutablePointer&lt;Void&gt;(headOfFreeOutputBuffers)
          headOfFreeOutputBuffers = outputBuffer
      }
  }
  
  func start() {
      var error: NSError?
      audioSession.setCategory(AVAudioSessionCategoryPlayAndRecord, withOptions: .allZeros, error: &amp;error)
      dumpError(error, functionName: "AVAudioSessionCategoryPlayAndRecord")
      audioSession.setPreferredSampleRate(16000, error: &amp;error)
      dumpError(error, functionName: "setPreferredSampleRate")
      audioSession.setPreferredIOBufferDuration(0.005, error: &amp;error)
      dumpError(error, functionName: "setPreferredIOBufferDuration")
  
      audioSession.setActive(true, error: &amp;error)
      dumpError(error, functionName: "setActive(true)")
  
      assert(active == false)
      active = true
  
      // cannot provide callbacks to AudioQueueNewInput/AudioQueueNewOutput from Swift and so need to interface C functions
      assert(MyAudioQueueConfigureInputQueueAndCallback(audioStreamBasicDescription, &amp;inputQueue, audioQueueInputCallback) == 0)
      assert(MyAudioQueueConfigureOutputQueueAndCallback(audioStreamBasicDescription, &amp;outputQueue, audioQueueOutputCallback) == 0)
  
      for (var i = 0; i &lt; numberOfBuffers; i++) {
          var audioQueueBufferRef: AudioQueueBufferRef = nil
          assert(AudioQueueAllocateBuffer(inputQueue, bufferSize, &amp;audioQueueBufferRef) == 0)
          assert(AudioQueueEnqueueBuffer(inputQueue, audioQueueBufferRef, 0, nil) == 0)
          inputBuffers.append(audioQueueBufferRef)
  
          assert(AudioQueueAllocateBuffer(outputQueue, bufferSize, &amp;audioQueueBufferRef) == 0)
          outputBuffers.append(audioQueueBufferRef)
  
          audioQueueBufferRef.memory.mUserData = UnsafeMutablePointer&lt;Void&gt;(headOfFreeOutputBuffers)
          headOfFreeOutputBuffers = audioQueueBufferRef
      }
  
      assert(AudioQueueStart(inputQueue, nil) == 0)
      assert(AudioQueueStart(outputQueue, nil) == 0)
  }
  </code></pre>
  
  <p>And then my C-code to set up the callbacks back to Swift:</p>
  
  <pre><code>static void MyAudioQueueAudioInputCallback(void * inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer, const AudioTimeStamp * inStartTime,
                                     UInt32 inNumberPacketDescriptions, const AudioStreamPacketDescription * inPacketDescs) {
      void(^block)(AudioQueueBufferRef) = (__bridge void(^)(AudioQueueBufferRef))inUserData;
      block(inBuffer);
  }
  
  static void MyAudioQueueAudioOutputCallback(void *inUserData, AudioQueueRef inAQ, AudioQueueBufferRef inBuffer) {
      void(^block)(AudioQueueBufferRef) = (__bridge void(^)(AudioQueueBufferRef))inUserData;
      block(inBuffer);
  }
  
  OSStatus MyAudioQueueConfigureInputQueueAndCallback(AudioStreamBasicDescription inFormat, AudioQueueRef *inAQ, void(^callback)(AudioQueueBufferRef)) {
      return AudioQueueNewInput(&amp;inFormat, MyAudioQueueAudioInputCallback, (__bridge_retained void *)([callback copy]), nil, nil, 0, inAQ);
  }
  
  OSStatus MyAudioQueueConfigureOutputQueueAndCallback(AudioStreamBasicDescription inFormat, AudioQueueRef *inAQ, void(^callback)(AudioQueueBufferRef)) {
      return AudioQueueNewOutput(&amp;inFormat, MyAudioQueueAudioOutputCallback, (__bridge_retained void *)([callback copy]), nil, nil, 0, inAQ);
  }
  </code></pre>