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,
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. 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. 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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With