Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing Buffer Size #84

Closed
LukasJoswiak opened this issue Aug 25, 2014 · 7 comments
Closed

Changing Buffer Size #84

LukasJoswiak opened this issue Aug 25, 2014 · 7 comments

Comments

@LukasJoswiak
Copy link

I have been searching for a way to change the buffer size to increase the number of data points received per second.

This issue (#50) is similar to what I am trying to do, but there does not appear to be an answer. How do I decrease the buffer size?

Thanks!

@syedhali
Copy link
Owner

For only the microphone component? If it's purely for a graphical display then you can adjust the rollingHistoryLength on the audio plot.

[self.audioPlot setRollingHistoryLength:128]

For the microphone it will default to the buffer size specified by the AVAudioSession, so before instantiating the microphone you could try adjusting the preferred IO buffer duration like:

NSError* err;
[[AVAudioSession sharedInstance] setPreferredIOBufferDuration:(DURATION IN SECONDS) error:&err];

Reference:
https://developer.apple.com/library/ios/documentation/avfoundation/reference/AVAudioSession_ClassReference/Reference/Reference.html#//apple_ref/occ/instm/AVAudioSession/setPreferredIOBufferDuration:error:

@LukasJoswiak
Copy link
Author

Yes, this is for the microphone. When the microphone is on, in the microphone:hasAudioReceived:withBufferSize:withNumberOfChannels: method, I am calling createFFTwithBufferSize:WithAudioData: and updateFFTWithBufferSize:withAudioData:, taken from the FFT example project. In updateFFTWithBufferSize:withAudioData:, I am storing the max frequency each loop in an array, which eventually gets turned into a graph.

Setting the preferred IO buffer duration does not change bufferSize in updateFFTWithBufferSize:withAudioData: and does not effect the number of data points being received. What I want to do is increase the number of data points by calling updateFFTWithBufferSize:withAudioData: more often, which I believe can be achieved by decreasing the buffer size.

@JeanRintoul
Copy link

Now I can run it with any window size to get better resolution.

-(void)microphone:(EZMicrophone *)microphone

hasAudioReceived:(float **)buffer

withBufferSize:(UInt32)bufferSize

withNumberOfChannels:(UInt32)numberOfChannels {

// Getting audio data as an array of float buffer arrays. What does that mean? Because the audio is coming in as a stereo signal the data is split into a left and right channel. So buffer[0] corresponds to the float* data for the left channel while buffer[1] corresponds to the float* data for the right channel.



// See the Thread Safety warning above, but in a nutshell these callbacks happen on a separate audio thread. We wrap any UI updating in a GCD block on the main thread to avoid blocking that audio flow.

dispatch_async(dispatch_get_main_queue(),^{

    // All the audio plot needs is the buffer data (float*) and the size. Internally the audio plot will handle all the drawing related code, history management, and freeing its own resources. Hence, one badass line of code gets you a pretty plot :)



    [self.audioPlot updateBuffer:buffer[0] withBufferSize:bufferSize];



    // Decibel Calculation.

    float one       = 1.0;

    float meanVal   = 0.0;

    float tiny      = 0.1;

    vDSP_vsq(buffer[0], 1, buffer[0], 1, bufferSize);

    vDSP_meanv(buffer[0], 1, &meanVal, bufferSize);

    vDSP_vdbcon(&meanVal, 1, &one, &meanVal, 1, 1, 0);

    // Exponential moving average to dB level to only get continous sounds.

    float currentdb = 1.0 - (fabs(meanVal)/100);

    if (lastdbValue == INFINITY || lastdbValue == -INFINITY || isnan(lastdbValue)) {

        lastdbValue = 0.0;

    }

    dbValue =   ((1.0 - tiny)*lastdbValue) + tiny*currentdb;

    lastdbValue = dbValue;

    // NSLog(@"dbval:  %f",dbValue);

    //

    // Setup the FFT if it's not already setup

    int samplestoCopy = fmin(bufferSize, FFTLEN - _fftBufIndex);

    for ( size_t i = 0; i < samplestoCopy; i++ ) {

        _fftBuf[_fftBufIndex+i] = buffer[0][i];

    }

    _fftBufIndex        += samplestoCopy;

   _samplesRemaining    -= samplestoCopy;

    if (_fftBufIndex == FFTLEN) {

        if( !_isFFTSetup ){

            [self createFFTWithBufferSize:FFTLEN withAudioData:_fftBuf];

            _isFFTSetup = YES;

        }

        [self updateFFTWithBufferSize:FFTLEN withAudioData:_fftBuf];

        _fftBufIndex        = 0.0f;

        _samplesRemaining   = FFTLEN;

    }



});

}

@LukasJoswiak
Copy link
Author

Jean, would you mind posting the Xcode project, so I can get a feel for how it works? If not, what are FFTLEN and fftBufIndex initialized as?

@JeanRintoul
Copy link

const UInt32 FFTLEN = 4410;
int _fftBufIndex = 0;
You may want to change FFTLEN to whatever you want, based on what resolution you want... This gave 5Hz bins.

@jamrader
Copy link

jamrader commented Jul 9, 2015

JeanRintoul or LikasJoswiak, did either of you manage to get a FFTViewController that could measure the Hz of a sound through the microphone with greater accuracy than that which is provided for with a buffer size of 512? I'm trying to manage increasing its accuracy (most likely by increasing buffer size) but am coming up short.

@syedhali
Copy link
Owner

As of 1.1.0 you can just use the EZAudioFFTRolling to get an FFT with a larger window. Please check out the answer for #185 for a code example of how to store more than 512 audio samples using an EZPlotHistoryInfo structure.

Also, the EZAudioFFTExample has been updated to be a high resolution pitch detector using a 4096 length FFT.
FFTExample

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants