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になります。
私はそれを間違っていますか?
音声信号のレベルを測定するときは、RMS値からdBを計算する必要があります。サンプルでは、絶対ピークレベルを確認しています。単一の(ピーク)サンプル値によってdBが決まります。他のすべてのサンプルが正確に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);
「瞬間的な」dBレベルの場合、通常は20〜50ミリ秒のセグメントでRMSを計算します。計算されたdB値はフルスケールを基準にしていることに注意してください。サウンドの場合、dB値は次のようになります。 20 uPaに関連しており、デジタル値から圧力値への適切な変換を見つけるために信号を校正する必要があります。
ハンの投稿に感謝し、彼の例を使用して、複数のチャネルを使用して、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;
}
}
ヤンはデシベルが相対的なスケールであることを意味すると思います。実際の音圧レベルまたはSPLを測定しようとしている場合は、校正する必要があります。測定しているのはdBFSです(フルスケールのデシベルだと思います)。システムが表すことができる最大の信号(「フルスケール」信号、またはこれらの16ビットサンプルの場合は32768)よりも信号が何デシベル静かであるかを測定しています。そのため、すべての値が負になります。