Rya*_*ook 23 c# audio audio-recording
我正在使用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));
Run Code Online (Sandbox Code Playgroud)
如果我将分贝值输出到屏幕,我可以看到值越高越大,因为我说话更柔和.然而,当我绝对安静时,它总是在-40左右徘徊......我认为它会是-90.我必须在上面的块中计算错误?从我在某些网站上看到的内容-40相当于"软谈话"...然而,它完全是安静的.
此外,如果我将麦克风静音,它会直接转到-90.
我做错了吗?
Han*_*Han 32
测量声音信号的电平时,应根据RMS值计算dB.在您的样本中,您正在查看绝对峰值水平.即使所有其他样本都精确为0,单个(峰值)样本值也会确定您的dB值.
试试这个:
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);
Run Code Online (Sandbox Code Playgroud)
对于"瞬时"dB水平,您通常会在20-50 ms的段内计算RMS.请注意,计算的dB值是相对于满量程的.对于声音,dB值应与20 uPa相关,您需要校准信号以找到从数字值到压力值的正确转换.
我很欣赏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;
}
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
17968 次 |
最近记录: |