Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 计算分贝_C#_Audio_Audio Recording - Fatal编程技术网

C# 计算分贝

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,

我正在使用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));
双峰=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-