5 Replies
      Latest reply on Oct 21, 2019 4:31 AM by manishlnmcbm
      woneill Level 1 Level 1 (0 points)

        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

        • Re: AuAudioUnit.inputHandler callback in Swift 2 does not conform to AuInputHandler definition?
          QuinceyMorris Level 8 Level 8 (6,050 points)

          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?

            • Re: AuAudioUnit.inputHandler callback in Swift 2 does not conform to AuInputHandler definition?
              woneill Level 1 Level 1 (0 points)

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

                • Re: AuAudioUnit.inputHandler callback in Swift 2 does not conform to AuInputHandler definition?
                  woneill Level 1 Level 1 (0 points)

                  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.

                    • Re: AuAudioUnit.inputHandler callback in Swift 2 does not conform to AuInputHandler definition?
                      theanalogkid Apple Staff Apple Staff (610 points)

                      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!

                        • Re: AuAudioUnit.inputHandler callback in Swift 2 does not conform to AuInputHandler definition?
                          manishlnmcbm Level 1 Level 1 (0 points)

                          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

                                      }