获取音频队列缓冲区

时间:2017-05-17 00:18:10

标签: ios swift avfoundation core-audio audiotoolbox

我试图在Swift中创建一个连续的FIFO录音机。我试图创建audioQueueCallback时遇到并发出问题。

来自文档AudioTimeStamp有这个init方法:

AudioTimeStamp(mSampleTime: Float64, mHostTime: UInt64, mRateScalar: Float64, mWordClockTime: UInt64, mSMPTETime: SMPTETime, mFlags: AudioTimeStampFlags, mReserved: UInt32)

我不知道如何使用它。

在我看来,设备应该有一个可靠的内部时钟才能管理audioQueues,但我还没有能够找到它的任何文档。

这是我创建BufferQueue的尝试:

ypealias WYNDRInputQueueCallback = ((Data) -> Void)

class WYNDRInputQueue {

  class WYNDRInputQueueUserData {
    let callback: WYNDRInputQueueCallback
    let bufferStub: NSData

    init(callback: @escaping WYNDRInputQueueCallback, bufferStub: NSData){
      self.callback = callback
      self.bufferStub = bufferStub
    }
  }


  private var audioQueueRef: AudioQueueRef?
  private let userData: WYNDRInputQueueUserData



  public init(asbd: inout AudioStreamBasicDescription, callback: @escaping WYNDRInputQueueCallback, buffersCount: UInt32 = 3, bufferSize: UInt32 = 9600) throws {

    self.userData = WYNDRInputQueueUserData(callback: callback, bufferStub: NSMutableData(length: Int(bufferSize))!)

    let userDataUnsafe = UnsafeMutableRawPointer(Unmanaged.passRetained(self.userData).toOpaque())

    let input = AudioQueueNewInput(&asbd,
                                   audioQueueInputCallback,
                                   userDataUnsafe,
                                   .none,
                                   .none,
                                   0,
                                   &audioQueueRef)

    if input != noErr {
      throw InputQueueError.genericError(input)
    }

    assert(audioQueueRef != nil )

    for _ in 0..<buffersCount {
      var bufferRef: AudioQueueBufferRef?

      let bufferInput = AudioQueueAllocateBuffer(audioQueueRef!, bufferSize, &bufferRef)

      if bufferInput != noErr {
        throw InputQueueError.genericError(bufferInput)
      }

      assert(bufferRef != nil)

我在这里使用audioTimeStamp:

      audioQueueInputCallback(userDataUnsafe, audioQueueRef!, bufferRef!, <#T##UnsafePointer<AudioTimeStamp>#>, 0, nil)
    }
  }

  private let audioQueueInputCallback: AudioQueueInputCallback = { (inUserData, inAQ, inBuffer, inStartTime, inNumberPacketDescriptions, inPacketDescs) in

    let userData = Unmanaged<WYNDRInputQueueUserData>.fromOpaque(inUserData!).takeUnretainedValue()

    let dataSize = Int(inBuffer.pointee.mAudioDataByteSize)

    let inputData = Data(bytes: inBuffer.pointee.mAudioData, count: dataSize)

    userData.callback(inputData)

    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nil)
  }

非常感谢任何建议!

1 个答案:

答案 0 :(得分:1)

我不确定时间戳将如何使用或者谁将使用它,但如果有疑问,为什么不使用您记录的样本数作为时间戳?

var timestamp = AudioTimeStamp()

timestamp.mSampleTime = numberOfSamplesRecorded
timestamp.mFlags = .sampleHostTimeValid