2

I would need to set the AudioQueueBufferRef's mAudioData. I tried with copyMemory:

inBuffer.pointee.copyMemory(from: lastItemOfArray, byteCount: byteCount) // byteCount is 512

but it doesnt't work.

The AudioQueueNewOutput() queue is properly setted up to Int16 pcm format

Here is my code:

   class CustomObject {
       var pcmInt16DataArray = [UnsafeMutableRawPointer]() // this contains pcmInt16 data
   }
        
   let callback: AudioQueueOutputCallback = { (
       inUserData: UnsafeMutableRawPointer?,
       inAQ: AudioQueueRef,
       inBuffer: AudioQueueBufferRef) in
    
       guard let aqp: CustomObject = inUserData?.bindMemory(to: CustomObject.self, capacity: 1).pointee else { return }
       var numBytes: UInt32 = inBuffer.pointee.mAudioDataBytesCapacity
        
    
       /// Set inBuffer.pointee.mAudioData to pcmInt16DataArray.popLast()
       /// How can I set the mAudioData here??
    
       inBuffer.pointee.mAudioDataByteSize = numBytes
       AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nil)
    }

From apple doc: https://developer.apple.com/documentation/audiotoolbox/audioqueuebuffer?language=objc

mAudioData:

The audio data owned the audio queue buffer. The buffer address cannot be changed.

So I guess the solution would be to set a new value to the same address Anybody who knows how to do it?

UPDATE:

The incoming audio format is "pcm" signal (Little Endian) sampled at 48kHz. Here are my settings:

var dataFormat = AudioStreamBasicDescription()
dataFormat.mSampleRate = 48000;
dataFormat.mFormatID = kAudioFormatLinearPCM
dataFormat.mFormatFlags = kAudioFormatFlagIsSignedInteger | kAudioFormatFlagIsNonInterleaved;
dataFormat.mChannelsPerFrame = 1
dataFormat.mFramesPerPacket = 1
dataFormat.mBitsPerChannel = 16
dataFormat.mBytesPerFrame = 2
dataFormat.mBytesPerPacket = 2

And I am collecting the incoming data to

var pcmData = [UnsafeMutableRawPointer]()
Community
  • 1
  • 1
szuniverse
  • 1,076
  • 4
  • 17
  • 32

1 Answers1

3

You're close!

Try this:

inBuffer.pointee.mAudioData.copyMemory(from: lastItemOfArray, byteCount: Int(numBytes))

or this:

memcpy(inBuffer.pointee.mAudioData, lastItemOfArray, Int(numBytes))

Audio Queue Services was tough enough to work with when it was pure C. Now that we have to do so much bridging to get the API to work with Swift, it's a real pain. If you have the option, try out AVAudioEngine.


A few other things to check:

Make sure your AudioQueue has the same format that you've defined in your AudioStreamBasicDescription.

var queue: AudioQueueRef?

// assumes userData has already been initialized and configured
AudioQueueNewOutput(&dataFormat, callBack, &userData, nil, nil, 0, &queue)

Confirm you have allocated and primed the queue's buffers.

let numBuffers = 3

// using forced optionals here for brevity
for _ in 0..<numBuffers {
    var buffer: AudioQueueBufferRef?
    if AudioQueueAllocateBuffer(queue!, userData.bufferByteSize, &buffer) == noErr {
        userData.mBuffers.append(buffer!)
        callBack(inUserData: &userData, inAQ: queue!, inBuffer: buffer!)
    }
}

Consider making your callback a function.

func callBack(inUserData: UnsafeMutableRawPointer?, inAQ: AudioQueueRef, inBuffer: AudioQueueBufferRef) {

    let numBytes: UInt32 = inBuffer.pointee.mAudioDataBytesCapacity       
    memcpy(inBuffer.pointee.mAudioData, pcmData, Int(numBytes))
    inBuffer.pointee.mAudioDataByteSize = numBytes

    AudioQueueEnqueueBuffer(inAQ, inBuffer, 0, nil)

 }

Also, see if you can get some basic PCM data to play through your audio queue before attempting to bring in the server side data.

var pcmData: [Int16] = []
for i in 0..<frameCount {
    let element = Int16.random(in: Int16.min...Int16.max) // noise
    pcmData.append(Int16(element))

}
lentil
  • 664
  • 5
  • 5
  • thanks lentil, now it seems I have other issues... So I got from the server `int16_t* pcm` data, but what should I do with this, how should I pass it to the mAudioData ? – szuniverse Mar 09 '20 at 09:12
  • You should be able to pass it like this: memcpy(inBuffer.pointee.mAudioData, pcmData, Int(numBytes)) – lentil Mar 09 '20 at 14:24