How can I specify the format of AVAudioEngine Mic-Input? How can I specify the format of AVAudioEngine Mic-Input? ios ios

How can I specify the format of AVAudioEngine Mic-Input?


You cannot change audio format directly on input nor output nodes. In the case of the microphone, the format will always be 44KHz, 1 channel, 32bits. To do so, you need to insert a mixer in between. Then when you connect inputNode > changeformatMixer > mainEngineMixer, you can specify the details of the format you want.

Something like:

var inputNode = audioEngine.inputNodevar downMixer = AVAudioMixerNode()//I think you the engine's I/O nodes are already attached to itself by default, so we attach only the downMixer here:audioEngine.attachNode(downMixer)//You can tap the downMixer to intercept the audio and do something with it:downMixer.installTapOnBus(0, bufferSize: 2048, format: downMixer.outputFormatForBus(0), block:  //originally 1024            { (buffer: AVAudioPCMBuffer!, time: AVAudioTime!) -> Void in                print(NSString(string: "downMixer Tap"))                do{                    print("Downmixer Tap Format: "+self.downMixer.outputFormatForBus(0).description)//buffer.audioBufferList.debugDescription)        })//let's get the input audio format right as it islet format = inputNode.inputFormatForBus(0)//I initialize a 16KHz format I need:let format16KHzMono = AVAudioFormat.init(commonFormat: AVAudioCommonFormat.PCMFormatInt16, sampleRate: 11050.0, channels: 1, interleaved: true)//connect the nodes inside the engine://INPUT NODE --format-> downMixer --16Kformat--> mainMixer//as you can see I m downsampling the default 44khz we get in the input to the 16Khz I want audioEngine.connect(inputNode, to: downMixer, format: format)//use default input formataudioEngine.connect(downMixer, to: audioEngine.outputNode, format: format16KHzMono)//use new audio format//run the engineaudioEngine.prepare()try! audioEngine.start()

I would recommend using an open framework such as EZAudio, instead, though.


The only thing I found that worked to change the sampling rate was

AVAudioSettings.sharedInstance().setPreferredSampleRate(...)

You can tap off engine.inputNode and use the input node's output format:

engine.inputNode.installTap(onBus: 0, bufferSize: 2048,                            format: engine.inputNode.outputFormat(forBus: 0))

Unfortunately, there is no guarantee that you will get the sample rate that you want, although it seems like 8000, 12000, 16000, 22050, 44100 all worked.

The following did NOT work:

  1. Setting the my custom format in a tap off engine.inputNode. (Exception)
  2. Adding a mixer with my custom format and tapping that. (Exception)
  3. Adding a mixer, connecting it with the inputNode's format, connecting the mixer to the main mixer with my custom format, then removing the input of the outputNode so as not to send the audio to the speaker and get instant feedback. (Worked, but got all zeros)
  4. Not using my custom format at all in the AVAudioEngine, and using AVAudioConverter to convert from the hardware rate in my tap. (Length of the buffer was not set, no way to tell if results were correct)

This was with iOS 12.3.1.


In order to change the sample rate of input node, you have to first connect the input node to a mixer node, and specify a new format in the parameter.

let input = avAudioEngine.inputNodelet mainMixer = avAudioEngine.mainMixerNodelet newAudioFormat = AVAudioFormat(commonFormat: .pcmFormatFloat32, sampleRate: 44100, channels: 1, interleaved: true)avAudioEngine.connect(input, to: mainMixer, format: newAudioFormat)

Now you can call installTap function on input node with the newAudioFormat.

One more thing I'd like to point out is, since the new launch of iPhone12, the default sample rate of input node has been no longer 44100 anymore. It has been upgraded to 48000.