Я создаю приложение iOS с помощью EZAudio. Он делегирует обратно буфер float**
, который содержит значения float, указывающие обнаруженный том. Этот делегат вызывается постоянно, и он работает с другим потоком.
То, что я пытаюсь сделать, это взять значение float из EZAudio и преобразовать его в децибелы.
EZAudioDelegate
Здесь мой упрощенный делегат EZAudio для получения данных микрофона:
- (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);
});
}
Проблема
Проблема заключается в том, что после внедрения решений из приведенных ниже ссылок я не понимаю, как это работает. Если бы кто-то мог объяснить, как он преобразует громкость в децибелы, я был бы очень благодарен
Код
Решение использует следующие методы из Accelerate Framework для преобразования тома в децибелы:
Ниже приведен метод getDecibelsFromVolume
, который вызывается из делегата EZAudio. Он передается 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], 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;
}