Mar 20, 2017

Audio chirp processing problems on OS X

In a previous blog post, I explored directly processing the sound samples from the built-in mic on OS X using the CoreAudio framework.  In that post, I briefly mentioned about the non-ideal response seen on my MacBook Pro.  For convenience, here is the raw sample.
This is supposed to be a flat chirp going from 50 Hz to 22 kHz (except for a short ramp up and down windowing at the beginning and the end).  Since the MacBook Pro's mic is RIGHT under the speaker, I expected some distortion, but this seemed too much.  So I tried turning off the "voice processing" units in the HW.

    if (true) { // Is the voice filter on?  Try to turn it off
        AudioComponentDescription desc;
        desc.componentType = kAudioUnitType_Output;
        desc.componentSubType = kAudioUnitSubType_VoiceProcessingIO;
        desc.componentManufacturer = kAudioUnitManufacturer_Apple;
        desc.componentFlags = 0;
        desc.componentFlagsMask = 0;
        AudioComponent comp = AudioComponentFindNext(NULL, &desc);
        
        AudioUnit vpioUnit;
        AudioComponentInstanceNew(comp, &vpioUnit);
        CheckError(AudioUnitSetProperty(vpioUnit, kAUVoiceIOProperty_BypassVoiceProcessing
                             , kAudioUnitScope_Global, 1, &enableFlag, sizeof(enableFlag))
                   , "BypassVoiceProcessing failed");
        CheckError(AudioUnitSetProperty(vpioUnit, kAUVoiceIOProperty_VoiceProcessingEnableAGC
                             , kAudioUnitScope_Global, 1, &disableFlag, sizeof(disableFlag))
                   , "VoiceProcessingEnableAGC");
        //Deprecated a long time ago
        //AudioUnitSetProperty(vpioUnit, kAUVoiceIOProperty_DuckNonVoiceAudio
        //                     , kAudioUnitScope_Global, 1, &disableFlag, sizeof(disableFlag));

    }

The result is even stranger:
I then tried different combinations of the above 2 options, and even got an address sanitizer inside AudioUnitSetProperty when I tried to enable kAUVoiceIOProperty_VoiceProcessingEnableAGC.

Running the simple LFM (linear frequency modulated) matched filter on a non-ideal received signal is problematic.  The non-constant group delay is the biggest problem.  This can be visualized in 2 different ways: the first is to simply get the best cross-correlation I can, and shift the received signal by this many sample delay, as shown in the zoomed in view below:
This "best effort" fit clearly is not well aligned--even when I reduced the bandwidth from 20 kHz down to 8 kHz, to avoid the low and high frequencies (where the distortion seems the greatest).  Another way to visualize is to segment the filter (I have been using 1024 taps) into smaller chunks and calculate the best cross correlation.  If the MacBook mic (and the iPod speaker) were distortion-free, the group delay should be constant, which means that the maximum correlation index should increase linearly (because group delay is the derivative of the phase lag).  But as you can see below, this is not the case.


Apple audio HW is supposed to be high quality, but I guess the built-in speaker/mic are far more limited...