Hello,
I have a couple of questions that are loosely related to the nature of the our app. We are developing an iPhone app that perform musical analysis on recorded audio from the iPhone. Our app implementation make use of the Audio Queue service to receive raw audio buffers from the audio queue callback.
In the first version of our app we had the problem of too much clipping on the recording which degrade the accuracy of our analysis. We also suspected that the noise canceling algorithm in iPhone 5 produce distorted sound, which is not much noticeable by human ear but distorted enough to affect our sensitive algorithm.
I found that the solution to our problem is to set the audio session mode to kAudioSessionMode_Measurement. This session mode is supposed to give maximum freedom for us to control the microphone input, which include turning off the automatic gain control and probably noise canceling as well.
Q1. How to adjust input gain level? The solution worked very well for us in the beginning, however after some further code changes I messed up somewhere and ended up being unable to change the input gain even after setting the audio session mode to measurement. Unfortunately I didn't commit immediately when it worked so I lost the original code that worked. I was pretty sure that my first attempt of changing the input gain worked, as I printed the value before and after setting to the console. The value of kAudioSessionProperty_InputGainAvailable I got back is now false, and I don't know how to make it available on iOS again.
Q2. Strange recording glitch in iPhone 5 Other than that, I notice that setting the session to measurement mode introduce a strange waveform glitch in the beginning of all recordings on iPhone 5. It is very hard to explain the waveform I get, so I have attached two recordings so that you can see it visually
This recording is made in an almost quite environment, and you can see the weird spike in the beginning of the recording.
This recording is made with constant background noise, and you can see that the actual sound wave is offset from the strange curve and gradually increase to its original volume.
This waveform only happens on iPhone 5 devices that we tested, and there is no problem at all for iPhone 4S and older generations. I have tried various settings and the glitch is still unavoidable as long as I set the audio session mode to kAudioSessionMode_Measurement. I also find similar glitch in one of our iPhone 5 devices, in which the glitch happens even if I try to set just the input gain level without changing the session mode.
I am not sure if this is a hardware-related bug in iPhone 5, or if it is fixable software glitch in the future version of iOS. Currently I found a strange workaround to the problem: If a sound playback is made first, the recording that is immediately followed by the playback will not contain the glitch. The glitch will come back in the second recording, so I have to perform a playback every time before doing recording to fix the glitch.
I tried two of my existing playback solution: one that use output audio queue and one that use MusicPlayer and MusicSequence. None of the playback code have any audio session manipulation, and an operation as simple as AudioQueueStart can make the glitch disappear "magically".
I have attached at the end of this mail a snippet of the refactored audio session configuration code I have written. I'd appreciate if anyone can tell me what went wrong in my code.
Q3. Is there any way to disable just the built-in noise canceling feature?
Q4. Can I record from all three microphones of iPhone 5 in separate channels?
Thank you.
Best Regards,
Soares Chen
Code snippet for my audio session configuration:
***** #include <AudioToolbox/AudioSession.h>
const Float32 kCustomGain = 0;
static void SetAudioInputGain(Float32 newGain) { printf("Attempt to set input gain to %f.\n", newGain); OSStatus res = noErr; Float32 currentGain = 0; UInt32 gainSize = sizeof(currentGain); AudioSessionGetProperty(kAudioSessionProperty_InputGainScalar, &gainSize, ¤tGain); printf("Current microphone gain is %f.\n", currentGain); res = AudioSessionSetProperty(kAudioSessionProperty_InputGainScalar, gainSize, &newGain); if(res != noErr) printf("Failed to set input gain.\n"); AudioSessionGetProperty(kAudioSessionProperty_InputGainScalar, &gainSize, ¤tGain); printf("New microphone gain is %f.\n", currentGain); }
static void ConfigureAudioSession() { AudioSessionInitialize(NULL, NULL, NULL, NULL); OSStatus res = noErr; printf("Setting audio session category to record mode.\n"); UInt32 sessionCategory = kAudioSessionCategory_RecordAudio; res = AudioSessionSetProperty (kAudioSessionProperty_AudioCategory, sizeof(sessionCategory), &sessionCategory); if(res != noErr) printf("Failed to set audio session category.\n"); printf("Setting audio session mode to measurement mode.\n"); UInt32 sessionMode = kAudioSessionMode_Measurement; res = AudioSessionSetProperty(kAudioSessionProperty_Mode, sizeof(sessionMode), &sessionMode); if(res != noErr) printf("Failed to set audio session mode.\n"); UInt32 inputGainAvailable = 0; UInt32 inputGainAvailableSize = sizeof(inputGainAvailable); res = AudioSessionGetProperty(kAudioSessionProperty_InputGainAvailable, &inputGainAvailableSize, &inputGainAvailable); if(res != noErr) printf("Failed to get input gain availability.\n"); if(!inputGainAvailable) printf("Input gain is not available.\n"); SetAudioInputGain(kCustomGain); printf("Activating audio session.\n"); res = AudioSessionSetActive(true); if(res != noErr) printf("Failed to activate audio session.\n"); } *****
Running ConfigureAudioSession() on my iPad for example would print the following to the console:
Setting audio session category to record mode. Setting audio session mode to measurement mode. Input gain is not available. Attempt to set input gain to 0.000000. Current microphone gain is 0.500000. New microphone gain is 0.500000. Activating audio session. |