I'm building an iOS app using EZAudio. It's delegate returns back a float**
buffer, which contains float values indicating the volume detected. This delegate is called constantly and it's work is done a different thread.
What I am trying to do is to take the float value from EZAudio and convert it into decibels.
EZAudioDelegate
Here's my simplified EZAudio Delegate for getting Microphone Data:
- (void)microphone:(EZMicrophone *)microphone hasAudioReceived:(float **)buffer withBufferSize:(UInt32)bufferSize withNumberOfChannels:(UInt32)numberOfChannels {
/*
* Returns a float array called buffer that contains the stereo signal data
* buffer[0] is the left audio channel
* buffer[1] is the right audio channel
*/
// Using a separate audio thread to not block the main UI thread
dispatch_async(dispatch_get_main_queue(), ^{
float decibels = [self getDecibelsFromVolume:buffer withBufferSize:bufferSize];
NSLog(@"Decibels: %f", decibels);
});
}
The Problem
The problem is that after implementing solutions from the links below, I do not understand how it works. If someone could explain how it converts volume to decibels I would be very grateful
The Code
The solution uses the following methods from the Accelerate Framework to convert the volume into decibels:
Below is the method getDecibelsFromVolume
that is called from the EZAudio Delegate. It is passed the float** buffer
and bufferSize
from the delegate.
- (float)getDecibelsFromVolume:(float**)buffer withBufferSize:(UInt32)bufferSize {
// Decibel Calculation.
float one = 1.0;
float meanVal = 0.0;
float tiny = 0.1;
float lastdbValue = 0.0;
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;
}
float dbValue = ((1.0 - tiny) * lastdbValue) + tiny * currentdb;
lastdbValue = dbValue;
return dbValue;
}