Skip to main content

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.


Comments

  1. 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.

    ReplyDelete
  2. Interesting question. I am not aware of any such filter... you can set an input callback on the remote IO unit and get a stream of floats.

    I haven't seen any documentation that this float stream is in some way already processed.

    I have written a pitch detector which successfully picks up notes at the low end of my singing range (~80Hz)

    Maybe post code -- what are you doing inside this callback?

    ReplyDelete
  3. Can I recommend you re-ask this question, with an appropriate title ( Maybe something like ' how to prevent iPhone from filtering low frequencies ( < 150Hz ) ' ) and containing all of the necessary information, also stick in that picture, that is an important part of the question. it's very easy to embed a picture.

    you haven't even stated what it is you are trying to accomplish.

    It looks like you're new to the site, and it looks like a very interesting question.

    But you are not being at all clear.

    Firstly, this is an issue with record or playback or both?

    Now, what exactly are you doing in your experiment? Western scientific method... lay it out.

    You are generating static in your remoteIO render callback? No, it sounds like you are using passthrough, you say you are putting white noise into the iPhone. how are you setting up your audio unit?

    so the white noise goes into the iPhone, straight out, and... now what does that graph represent? FFT / Spectral analysis of the output of the iPhone? how are you doing that? You're feeding this into some OSX graphing software that can take input from the line in?

    also, you could do with narrowing it down. If you are indeed passing sound right through the device, you have no idea where the filtering is occurring. for all you know there could be filtering occurring in the device that generates the white noise, as well as the device that graphs the iPhone output.

    how about generating your white noise from inside the remote I/O render callback?

    and then generating it externally and analysing the data that arrives from within this callback -- you could perform an FFT.

    anyway, for input wouldn't you do better to feed in sine waves of different frequencies?

    ReplyDelete

Post a Comment

Popular posts from this blog

[韓日関係] 首相含む大幅な内閣改造の可能性…早ければ来月10日ごろ=韓国

div not scrolling properly with slimScroll plugin

I am using the slimScroll plugin for jQuery by Piotr Rochala Which is a great plugin for nice scrollbars on most browsers but I am stuck because I am using it for a chat box and whenever the user appends new text to the boxit does scroll using the .scrollTop() method however the plugin's scrollbar doesnt scroll with it and when the user wants to look though the chat history it will start scrolling from near the top. I have made a quick demo of my situation http://jsfiddle.net/DY9CT/2/ Does anyone know how to solve this problem?

Why does this javascript based printing cause Safari to refresh the page?

The page I am working on has a javascript function executed to print parts of the page. For some reason, printing in Safari, causes the window to somehow update. I say somehow, because it does not really refresh as in reload the page, but rather it starts the "rendering" of the page from start, i.e. scroll to top, flash animations start from 0, and so forth. The effect is reproduced by this fiddle: http://jsfiddle.net/fYmnB/ Clicking the print button and finishing or cancelling a print in Safari causes the screen to "go white" for a sec, which in my real website manifests itself as something "like" a reload. While running print button with, let's say, Firefox, just opens and closes the print dialogue without affecting the fiddle page in any way. Is there something with my way of calling the browsers print method that causes this, or how can it be explained - and preferably, avoided? P.S.: On my real site the same occurs with Chrome. In the ex