Рассчитать децибелы
Я записываю микрофонный вход с помощью библиотеки XNA (я не думаю, что это действительно технология, но это никогда не повредит). Каждый раз, когда я получаю образец, я бы хотел рассчитать децибелы. Я сделал много поисков в Интернете и не нашел убедительного примера...
Вот моя попытка вычисления децибел из образца:
double peak = 0;
for (var i = 0; i < _buffer.Length; i = i + 2)
{
var sample = BitConverter.ToInt16(_buffer, i);
if (sample > peak)
peak = sample;
else if (sample < -peak)
peak = -sample;
}
var decibel = (20 * Math.Log10(peak/32768));
Если я вывешу значение децибела на экран, я вижу, что значения становятся выше, когда я становлюсь все громче и ниже, когда говорю более мягко. Тем не менее, он всегда колеблется около -40, когда я абсолютно спокоен... Я бы предположил, что это будет -90. У меня должно быть неправильное вычисление в блоке выше? из того, что я читал на некоторых сайтах -40, эквивалентно "мягкому разговору"... однако, он абсолютно тихий.
Кроме того, если я отключу микрофон, он будет равен -90.
Я делаю это неправильно?
Ответы
Ответ 1
При измерении уровня звукового сигнала вы должны рассчитать дБ от значения RMS. В вашем примере вы смотрите на абсолютный пиковый уровень. Единственное (пиковое) значение выборки определяет ваше значение дБ, даже если все остальные образцы равны 0.
попробуйте следующее:
double sum = 0;
for (var i = 0; i < _buffer.length; i = i + 2)
{
double sample = BitConverter.ToInt16(_buffer, i) / 32768.0;
sum += (sample * sample);
}
double rms = Math.Sqrt(sum / (_buffer.length / 2));
var decibel = 20 * Math.Log10(rms);
Для "мгновенных" дБ уровней вы обычно вычисляете RMS в сегменте 20-50 мс.
Обратите внимание, что рассчитанное значение дБ относится к полномасштабному. Для звука значение дБ должно быть связано с 20 мкПа, и вам нужно будет откалибровать сигнал, чтобы найти правильное преобразование из цифровых значений в значения давления.
Ответ 2
Я ценю пост Han и написал процедуру, которая может вычислять децибелы в 8 и 16-битных аудиоформатах, используя несколько каналов, используя его пример.
public double MeasureDecibels(byte[] samples, int length, int bitsPerSample,
int numChannels, params int[] channelsToMeasure)
{
if (samples == null || length == 0 || samples.Length == 0)
{
throw new ArgumentException("Missing samples to measure.");
}
//check bits are 8 or 16.
if (bitsPerSample != 8 && bitsPerSample != 16)
{
throw new ArgumentException("Only 8 and 16 bit samples allowed.");
}
//check channels are valid
if (channelsToMeasure == null || channelsToMeasure.Length == 0)
{
throw new ArgumentException("Must have target channels.");
}
//check each channel is in proper range.
foreach (int channel in channelsToMeasure)
{
if (channel < 0 || channel >= numChannels)
{
throw new ArgumentException("Invalid channel requested.");
}
}
//ensure we have only full blocks. A half a block isn't considered valid.
int sampleSizeInBytes = bitsPerSample / 8;
int blockSizeInBytes = sampleSizeInBytes * numChannels;
if (length % blockSizeInBytes != 0)
{
throw new ArgumentException("Non-integral number of bytes passed for given audio format.");
}
double sum = 0;
for (var i = 0; i < length; i = i + blockSizeInBytes)
{
double sumOfChannels = 0;
for (int j = 0; j < channelsToMeasure.Length; j++)
{
int channelOffset = channelsToMeasure[j] * sampleSizeInBytes;
int channelIndex = i + channelOffset;
if (bitsPerSample == 8)
{
sumOfChannels = (127 - samples[channelIndex]) / byte.MaxValue;
}
else
{
double sampleValue = BitConverter.ToInt16(samples, channelIndex);
sumOfChannels += (sampleValue / short.MaxValue);
}
}
double averageOfChannels = sumOfChannels / channelsToMeasure.Length;
sum += (averageOfChannels * averageOfChannels);
}
int numberSamples = length / blockSizeInBytes;
double rootMeanSquared = Math.Sqrt(sum / numberSamples);
if (rootMeanSquared == 0)
{
return 0;
}
else
{
double logvalue = Math.Log10(rootMeanSquared);
double decibel = 20 * logvalue;
return decibel;
}
}
Ответ 3
Я думаю, что Янн означает, что децибелы являются относительной шкалой. Если вы пытаетесь измерить фактический уровень звукового давления или SPL, вам нужно будет откалибровать. Я думаю, что вы измеряете dBFS (децибелы полномасштабные). Вы измеряете, сколько децибел тише сигнала, чем самый громкий сигнал, который система может представлять ( "полномасштабный" сигнал, или 32768 для этих 16-битных выборок). Вот почему все значения отрицательные.