C# 计算分贝
我正在使用XNA库录制麦克风输入(我不认为这是特定于技术的,但它不会带来任何伤害)。每次我得到一个样本,我想计算分贝。我在互联网上做了很多搜索,但没有找到一个可靠的例子 以下是我从样本中计算分贝的尝试:C# 计算分贝,c#,audio,audio-recording,C#,Audio,Audio Recording,我正在使用XNA库录制麦克风输入(我不认为这是特定于技术的,但它不会带来任何伤害)。每次我得到一个样本,我想计算分贝。我在互联网上做了很多搜索,但没有找到一个可靠的例子 以下是我从样本中计算分贝的尝试: double peak = 0; for (var i = 0; i < _buffer.Length; i = i + 2) { var sample = BitConverter.ToInt16(_buffer,
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));
双峰=0;
对于(变量i=0;i<\u buffer.Length;i=i+2)
{
var sample=BitConverter.ToInt16(_buffer,i);
如果(样本>峰值)
峰值=样品;
否则如果(样本<-峰值)
峰值=-样本;
}
var分贝=(20*Math.Log10(峰值/32768));
如果我将分贝值输出到屏幕上,我可以看到随着声音的增大,分贝值会越来越高,而随着说话声音的减弱,分贝值会越来越低。然而,当我绝对安静的时候,它总是在-40左右徘徊……我想它应该是-90。我必须有一个错误的计算在上面块??从我在一些网站上读到的内容来看,40相当于“软对话”…然而,它完全是安静的
此外,如果我将麦克风静音,它会直接转到-90
我做错了吗?我认为Yann的意思是分贝是一个相对尺度。如果您试图测量实际声压级或SPL,则需要进行校准。你们测量的是dBFS(我想是满刻度分贝)。您正在测量信号比系统所能代表的最大可能信号(满标度信号,或这些16位采样的32768)低多少分贝。这就是为什么所有的值都是负值。当测量声音信号的电平时,您应该根据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);
double sum=0;
对于(变量i=0;i<\u buffer.length;i=i+2)
{
双采样=位转换器.ToInt16(_缓冲区,i)/32768.0;
总和+=(样本*样本);
}
double rms=Math.Sqrt(sum/(_buffer.length/2));
var分贝=20*数学对数10(rms);
对于“瞬时”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;
}
}
public-double-MeasureDecibels(字节[]样本,int-length,int-bitsPerSample,
int numChannels,参数int[]channelsToMeasure)
{
if(samples==null | | length==0 | | samples.length==0)
{
抛出新的ArgumentException(“缺少要测量的样本”);
}
//校验位为8或16。
if(bitsPerSample!=8&&bitsPerSample!=16)
{
抛出新的ArgumentException(“仅允许8位和16位样本”);
}
//检查通道是否有效
if(channelsToMeasure==null | | channelsToMeasure.Length==0)
{
抛出新ArgumentException(“必须有目标通道”);
}
//检查每个通道是否在正确的范围内。
foreach(channelsToMeasure中的int通道)
{
如果(通道<0 | |通道>=numChannels)
{
抛出新ArgumentException(“请求的通道无效”);
}
}
//确保只有完整的块。半个块无效。
int sampleSizeInBytes=bitsPerSample/8;
int blockSizeInBytes=采样SizeInBytes*numChannel;
if(长度%blockSizeInBytes!=0)
{
抛出新ArgumentException(“为给定音频格式传递的非整数字节数”);
}
双和=0;
对于(变量i=0;i
可能有背景噪音?对找到此页面的研究人员有用:float rms2db(float value){返回10*log10(value);}而校准意味着每个客户端必须找到它们的零…因为每个设备和环境都不同?例如,我的,似乎是-40,而一切都是无声的…我会校准到零吗?通常你会使用麦克风校准器。校准器提供的信号具有非常精确的已知水平,例如98 dB。然后测量/记录该信号,并导出比例因子(与每个采样值相乘),以便计算的分贝值为98 dB。校准器的98 dB与20uPa相关,因此实际rms压力水平为20*10E-