Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent iPhone 3GS from filtering low frequencies ( < 150Hz )

I'm developing a bass guitar pitch detection app on iphone 3GS. I found I can't get sound data lower than 150Hz with RemoteIO. However bass guitar may generate tones lower than 50hz. According to the report "iPhone 4 Headset Input Frequency Response", http://blog.faberacoustical.com/2010/iphone/iphone-4-audio-and-frequency-response-limitations/ There is a sharp drop-off below 150 Hz.

Here shows how I setup the AudioUnit.

// set audio unit
{
    // create AudioUnit
    {
        AudioComponentDescription desc;
        desc.componentType = kAudioUnitType_Output;
        desc.componentSubType = kAudioUnitSubType_RemoteIO;
        desc.componentManufacturer = kAudioUnitManufacturer_Apple;
        desc.componentFlags = 0;
        desc.componentFlagsMask = 0;

        AudioComponent comp = AudioComponentFindNext(NULL, &desc);
        OSAssert(AudioComponentInstanceNew(comp, &m_AudioUnit));
    }

    //enable input on the remote I/O unit (output is default enabled, but input is not)
    {
        UInt32 one = 1;
        OSAssert(AudioUnitSetProperty(m_AudioUnit, kAudioOutputUnitProperty_EnableIO,
                                      kAudioUnitScope_Input, 1, &one, sizeof(one)));
    }

    //set render callback function
    {
        AURenderCallbackStruct callbackInfo;
        callbackInfo.inputProc=staticPerformThru;
        callbackInfo.inputProcRefCon=this;

        OSAssert(AudioUnitSetProperty(m_AudioUnit,
                                      kAudioUnitProperty_SetRenderCallback,
                                      kAudioUnitScope_Input, 
                                      0, &callbackInfo, sizeof(callbackInfo)));

    }

    //set in/output format
    {
        CAStreamBasicDescription outFormat;
        outFormat.SetAUCanonical(channels, false);
        outFormat.mSampleRate = sampleRate;
        OSAssert(AudioUnitSetProperty(m_AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Input, 0, &outFormat, sizeof(outFormat)));
        OSAssert(AudioUnitSetProperty(m_AudioUnit, kAudioUnitProperty_StreamFormat, kAudioUnitScope_Output, 1, &outFormat, sizeof(outFormat)));
    }

    //Initialize remote I/O unit
    OSStatus r=AudioUnitInitialize(m_AudioUnit);
    OSAssert(r);
}
//start audio output
OSAssert(AudioOutputUnitStart(m_AudioUnit));

This is the callback function.

OSStatus AudioThruWorker::staticPerformThru(
                                           void                     *inRefCon, 
                                           AudioUnitRenderActionFlags   *ioActionFlags, 
                                           const AudioTimeStamp         *inTimeStamp, 
                                           UInt32                       inBusNumber, 
                                           UInt32                       inNumberFrames, 
                                           AudioBufferList          *ioData)
{

    AudioUnitRender(((AudioThruWorker*)inRefCon)->m_AudioUnit, ioActionFlags, inTimeStamp, 1, inNumberFrames, ioData);

    //Detect pitch here...

    return 0;
}

To identify the root cause,

  1. I modified my callback function to just bypass input data to output.
  2. Use Mac to generate white noise
  3. Use iRig to redirect the signal from Mac's headset to iPhone3Gs which is running my program.
  4. Use iRig to redirect output of iPhone back to Mac.
  5. Record data on Mac. enter image description here The output data spectrum shows in below figure. enter image description here

You can see the sharp drop at 150Hz.

To identify whether the problem is at input side or output side, I changed the callback function to ignore input data and output a white noise. Here is the result. enter image description here Very clear that there is NO drop at 150 Hz. Therefore the problem should at the input side.

I thought this is a hardware limitation. HOWEVER I tried the app "Amplitube" on the same device, turn off all effects ,input white noise and analyze output. It has NO drop at 150Hz. Here is the result.Amplitube frequency response on iPhone 3gs This means the drop-off problem is NOT a hardware limitation. There must be some way software can do to avoid the problem.

Does anyone know the secret?

Thanks.

like image 704
Albert Avatar asked Jul 19 '11 09:07

Albert


People also ask

What type of filter do we use to remove low frequencies?

A low-pass filter is a filter that passes signals with a frequency lower than a selected cutoff frequency and attenuates signals with frequencies higher than the cutoff frequency.


1 Answers

Well, it is a phone, a device optimized for speech supposedly. And devices optimized for speech usually have some sort of LF cut filter to avoid rumble and distortion.

This filter is probably on the input side of the phone, that is why you can generate and output a wider range of frequencies, it is probably a hardware/discrete element filter, since those are simple to create using only a few components and will work in real time without any strain on processing.

I don't think it makes sense to cut lows in software, I know I wouldn't do it, well, for a DAW application you can do it, but for a device optimized to filter lows...

Considered the fact amplitube devs might have been aware of this issue and added extra low boost to try and make it up for the hardware limitation?

On the other hand, it may very well be possible to chose different "signal paths" according to usage scenario, maybe there is some os handle apps can touch and say "hey, I am not voice, don't cut my lows" - if so, this feature should be somewhere in the api description.

like image 195
dtech Avatar answered Oct 05 '22 07:10

dtech