Setting the sampling rate to AUHAL

I am using the Audio Unit Framework to develop a VOIP application on mac os x. In my program, I configured the AUHAL input and used the default stream format (44.1 kHz, 32 bit / channel) to capture the sound from the microphone. In this case, my program works fine.

Here is the code:

//The default setting in my program CheckError(AudioUnitGetProperty(m_audCapUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, //the value is 0 inputBus, //the value is 1 &m_audCapUnitOutputStreamFormat, &propertySize), "Couldn't get OutputSample ASBD from input unit") ; //the inOutputSampleRate is 44100.0 m_audCapUnitOutputStreamFormat.mSampleRate = inOutputSampleRate ; CheckError(AudioUnitSetProperty(m_audCapUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, inputBus, &m_audCapUnitOutputStreamFormat, propertySize), "Couldn't set OutputSample ASBD on input unit"); // 

Since I am developing a VOIP application, the default format (44.1 kHz, 32 bit / channel) is not suitable for my program, so I want to change the sampling frequency to 8 kHz. And I wrote this code to change the format in my program:

 //...... inOutputFormat.mSampleRate = 8000. ; inOutputFormat.mFormatID = kAudioFormatLinearPCM ; inOutputFormat.mChannelsPerFrame = 2 ; inOutputFormat.mBitsPerChannel = 16 ; inOutputFormat.mBytesPerFrame = 2 ; inOutputFormat.mBytesPerPacket = 2 ; inOutputFormat.mFramesPerPacket = 1 ; inOutputFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical ; inOutputFormat.mReserved = 0 ; CheckError(AudioUnitSetProperty(m_audCapUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, inputBus, &inOutputFormat, ui32PropSize), "Couldn't set AUHAL Unit Output Format") ; //....... 

In this case, the program runs fine until my program calls AudioUnitRender in the callback function; it cannot call AudioUnitRender with error code -10876 , which means kAudioUnitErr_NoConnection in the documentation. The error code puzzled me so much, so I searched for it, but I did not find any useful information. Can someone tell me what the error really means?

This is not the end, I changed the format using this code:

 //..... inOutputFormat.mSampleRate = 8000. ; inOutputFormat.mFormatID = kAudioFormatLinearPCM ; inOutputFormat.mChannelsPerFrame = 2 ; inOutputFormat.mBitsPerChannel = 32 ; inOutputFormat.mBytesPerFrame = 4 ; inOutputFormat.mBytesPerPacket = 4 ; inOutputFormat.mFramesPerPacket = 1 ; inOutputFormat.mFormatFlags = kAudioFormatFlagsAudioUnitCanonical ; inOutputFormat.mReserved = 0 ; CheckError(AudioUnitSetProperty(m_audCapUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, inputBus, &inOutputFormat, ui32PropSize), "Couldn't set AUHAL Unit Output Format") ; //........ 

In this case, the program failed to call AudioUnitRender again and returned another error code -10863(kAudioUnitErr_CannotDoInCurrentContext) . I googled it, but I found something useful . After reading the information there, I think the sampling rate or the format that I set to AUHAL may not be supported by the hardware.

So, I wrote code to check the available sampling rates on the default input device:

 //.......... UInt32 propertySize = sizeof(AudioDeviceID) ; Boolean isWritable = false ; CheckError(AudioDeviceGetPropertyInfo(inDeviceID, //the inDeviceID is the default input device 0, true, kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, &isWritable), "Get the Available Sample Rate Count Failed") ; m_valueCount = propertySize / sizeof(AudioValueRange) ; printf("Available %d Sample Rate\n",m_valueCount) ; CheckError(AudioDeviceGetProperty(inDeviceID, 0, false, kAudioDevicePropertyAvailableNominalSampleRates, &propertySize, m_valueTabe), "Get the Available Sample Rate Count Failed") ; for(UInt32 i = 0 ; i < m_valueCount ; ++i) { printf("Available Sample Rate value : %ld\n",(long)m_valueTabe[i].mMinimum) ; } //.............. 

And then I discovered that the available sampling rates are 8000, 16000, 32000, 44100, 48000, 88200 and 96000.

The 8000 sample rate is what I installed before, but I get an error code by calling AudioUnitRender , I just want to say why?

I had a lot of Google and also read a lot of documents, but I can’t get an answer, can someone solve this problem, what have I encountered?

In other words; How to change the sampling rate or format on the input AUHAL?

+4
source share
3 answers

Finally, I fixed this problem yesterday.

Here is my solution:

  • First, I use AudioDeviceGetProperty to get a list of available formats on my AudioDeviceGetProperty input device, after which I found that the list of available formats contains: 8khz, 16khz, 32khz, 44.1khz, 48khz, 88.2khz,96khz (I just list here sampling rate field, but there are other fields in the list).
  • And then I select one of the available formats obtained in the first step. Take my program as an example, I select the format (8khz,32bits/Channel) and use AudioDeviceSetProperty to set it to the device by default, but not to AUHAL, this is the key that my program works fine after setting the format to AUHAL (OutputScope, inputBus).
  • In the last step, I use AudioUnitSetProperty to set the format that I need, the program works fine.

With this problem and solution, I think if I want to set the format to the input AUHAL, the format must match or there may be a shift to the available format that the input device uses. Therefore, I need to first set the format on the input device and set the format to AUHAL for input only.

+4
source

In my experience, using settings other than 44.1 kHz and 16-bit sound leads to different kinds of strange errors. Some general suggestions that may lead you to the right path:

  • Try Novocaine ( https://github.com/alexbw/novocaine ). This really alleviates the pain of working with AudioUnits.
  • Try connecting your application with a frequency of 44.1 kHz, and then dump the sound yourself.
  • The set bitrate may not match the desired sample rate.
+1
source

Your answer was very helpful to me. However, the use of AudioDeviceGetProperty is depreciating. The following list may be useful for updating information. As an example, the sampling frequency is set to 32 kHz.

  // Get the available sample rates of the default input device. defaultDeviceProperty.mSelector = kAudioDevicePropertyAvailableNominalSampleRates; CheckError (AudioObjectGetPropertyDataSize(defaultDevice, &defaultDeviceProperty, 0, NULL, &propertySize), "Couldn't get sample rate count"); int m_valueCount = propertySize / sizeof(AudioValueRange) ; printf("Available %d Sample Rates\n",m_valueCount) ; AudioValueRange m_valueTabe[m_valueCount]; CheckError (AudioObjectGetPropertyData(defaultDevice, &defaultDeviceProperty, 0, NULL, &propertySize, m_valueTabe), "Couldn't get available sample rates"); for(UInt32 i = 0 ; i < m_valueCount ; ++i) { printf("Available Sample Rate value : %f\n", m_valueTabe[i].mMinimum) ; } // Set the sample rate to one of the available values. AudioValueRange inputSampleRate; inputSampleRate.mMinimum = 32000; inputSampleRate.mMaximum = 32000; defaultDeviceProperty.mSelector = kAudioDevicePropertyNominalSampleRate; CheckError (AudioObjectSetPropertyData(defaultDevice, &defaultDeviceProperty, 0, NULL, sizeof(inputSampleRate), &inputSampleRate), "Couldn't get available sample rates"); 
+1
source

Source: https://habr.com/ru/post/1495954/


All Articles