AuAudioUnit.inputHandler callback in Swift 2 does not conform to AuInputHandler definition?

Using Swift 2 with XCode 7.2 on a Mac running OS X 10.11.2; Working with AUAudioUnit callbacks to process real time microphone input.


Have successfully configured HAL Output device to use default input and set the inputHandler to a callback block defined to be compliant with the AUInputHandler definition. The following code fragment works (provides live data with 512 sample frames in real-time):


let renderBlock = audioUnit.renderBlock

let inputBuffer = AVAudioPCMBuffer(...


audioUnit.inputHandler = {

(actionFlags, timestamp, inputBusNumber, frameCount) -> Void in

renderBlock(actionFlags, timestamp, AUAudioFrameCount(frameCount), Int(inputBusNumber), inputBuffer.mutableAudioBufferList, nil)

}


My question involves fields: inputBusNumber, frameCount, which are reversed compared to the spec.


These two are passed in to the callback block in in the order given above and not as specified in the definition:


(UnsafeMutablePointer<AudioUnitRenderActionFlags>, UnsafePointer<AudioTimeStamp>, AUAudioFrameCount, Int) -> Void


In my original code, I used the fields in the specified order:


audioUnit.inputHandler = {

(actionFlags, timestamp, frameCount, inputBusNumber) -> Void in

renderBlock(actionFlags, timestamp, frameCount, inputBusNumber, inputBuffer.mutableAudioBufferList, nil)

}


And the code blew up. When I printed out the values for these fields as passed-in, the frameCount was getting set to 1, and the inputBusNumber was set to 512. Once I swapped the order, my code magically came to life.


Has anybody else seen this or have I missed something fundamental?


Thanks,


Bill

Accepted Reply

FYI - This is indeed a bug where the frame count and bus number arguments are swapped causing this headache - we will be fixing this in a future update.


Thank you for filing the report!

Replies

I dunno, looking at the actual header files, it seems consistent in putting the frame count before the bus number, when both are present in an argument list.


What is your code at the point where you say there are 512 samples in the frame? Perhaps you have two parameters interchanged at that point?

The original code was:


audioUnit.inputHandler = {

(actionFlags, timestamp, frameCount, inputBusNumber) -> Void in

print("Input handler called")

print("actionFlags: \(actionFlags)")

print("timestamp: \(timestamp)")

print("frameCount: \(frameCount)")

print("inputBusNumber: \(inputBusNumber)")


The output looks like:

Input handler called

actionFlags: 0x00007000003a5c54

timestamp: 0x0000000105d010a0

frameCount: 1

inputBusNumber: 512


Now the standard convention for input bus is numbering on an I/O AU is 1, and the AUAudioUnit.maximumFramesToRender parameter gives 512...

Looking at the Core Audio structures, the new object-based wrappers seem to reverse the order of these two fields compared to the C version:


extern ComponentResult AudioUnitRender (

AudioUnit ci,

AudioUnitRenderActionFlags *ioActionFlags,

const AudioTimeStamp *inTimeStamp,

UInt32 inOutputBusNumber,

UInt32 inNumberFrames,

AudioBufferList *ioData

);


I filed a bug report.

FYI - This is indeed a bug where the frame count and bus number arguments are swapped causing this headache - we will be fixing this in a future update.


Thank you for filing the report!

I have implemented with version 3

AUAudioUnit
but now i am facing noise on speaker side for my voip app. The codes are below:-


auAudioUnit?.outputProvider = { ( // AURenderPullInputBlock?

actionFlags,

timestamp,

frameCount,

inputBusNumber,

inputDataList ) -> AUAudioUnitStatus in

if let block = self.renderBlock {

// print("Action Flag: \(actionFlags) and timeStamp: \(timestamp) and inputBusNumber: \(inputBusNumber) and dataListBuffersCount:\(inputDataList[0].mBuffers)")

if let dataReceived = self.getInputDataForConsumption() {

let mutabledata = NSMutableData(data: dataReceived)

var bufferListSpeaker = AudioBufferList(

mNumberBuffers: 1,

mBuffers: AudioBuffer(

mNumberChannels: 1,

mDataByteSize: 0,

mData: nil))


let err : OSStatus = block(actionFlags,

timestamp,

frameCount,

1,

&bufferListSpeaker,

.none)

if err == noErr {

print("Output Provider before Buffer size \(inputDataList[0].mBuffers.mDataByteSize) and at Index 1 \(inputDataList[1].mBuffers.mDataByteSize)")

bufferListSpeaker.mBuffers.mDataByteSize = UInt32(mutabledata.length)

bufferListSpeaker.mBuffers.mData = mutabledata.mutableBytes

inputDataList[0] = bufferListSpeaker

#if DEBUG

print("Output Provider mDataByteSize: \(inputDataList[0].mBuffers.mDataByteSize) and data Size: \(mutabledata.length) output FrameCount: \(frameCount)")

#endif

return err

} else {

#if DEBUG

print("Output Provider \(err)")

#endif

return err

}

}

}

return 0

}