What I am trying to do is to take the float value from EZAudio and convert it into decibels.
EZAudioDelegate
这是我的简化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 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
> How to convert audio input to DB? #85
> How to change the buffer size to increase FFT window? #50
> Changing Buffer Size #84
代码
该解决方案使用Accelerate Framework中的以下方法将卷转换为分贝:
> vDSP_vsq
> vDSP_meanv
> vDSP_vdbcon
以下是EZAudio Delegate所调用的getDecibelsFromVolume方法.它从委托中传递了float ** buffer和bufferSize.
- (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],bufferSize);
vDSP_meanv(buffer[0],&meanVal,bufferSize);
vDSP_vdbcon(&meanVal,&one,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;
}
解决方法
首先,计算一个数据块的RMS和
double sumSquared = 0;
for (int i = 0 ; i < numSamples ; i++)
{
sumSquared += samples[i]*samples[i];
}
double rms = sumSquared/numSamples;
有关RMS的更多信息
接下来将RMS值转换为dB
double dBvalue = 20*log10(rms);
这与示例代码有关
vDSP_vsq(buffer[0],bufferSize);
该行循环遍历缓冲区,并计算缓冲区中所有元素的平方.如果缓冲区在调用之前包含值[1,2,3,4],则在调用后将包含值[1,4,9,16]
vDSP_meanv(buffer[0],对缓冲区中的值进行求和,然后返回总和除以元素数.所以对于输入缓冲区[1,16]计算总和30,除以4并返回结果7.5.vDSP_vdbcon(&meanVal,0);该行将meanVal转换为分贝.在这里调用矢量化函数真的没有意义,因为它只能在单个元素上运行.然而,它正在做的是将参数插入到以下公式中:
meanVal = n*log10(meanVal/one)其中n为10或20,具体取决于最后一个参数.在这种情况下,它是10. 10用于功率测量,20是用于振幅.我认为20对你来说会更有意义.
最后一点代码看起来正在做一些简单的平滑的结果,使仪表有点小的弹性.