无法使用麦克风 c# naudio 捕捉 15k 的音调

Posted

技术标签:

【中文标题】无法使用麦克风 c# naudio 捕捉 15k 的音调【英文标题】:can't catch a tone frequency of 15k with microphone c# naudio 【发布时间】:2015-06-01 08:16:22 【问题描述】:

我用 NAudio 将一些声音录制到浮点数组中,在获得录制的音频后,我想将其从浮点数组转换回 wav 以检查它。

我写了一个方法,但我不确定,因为:我尝试录制 5 秒的 15Khz 音调,并通过 fft 检查频谱以确保捕获 15k。 这些是我的步骤:

    我首先用 matlab 生成这个音调,然后用 Audacity 记录它是正确的音调。 Audacity 显示了一个很好的频谱,峰值在 15k 和 -30db。

    我尝试使用 Naudio 录制音调,然后将其从录制的浮点数组转换回 wav 以在 Audacity 中检查它。不幸的是,它只显示高达 12k 的噪音,仅此而已(-80db at 12k)。

这是有数据时的常规录音转换:

void myWaveIn_DataAvailable(object sender, WaveInEventArgs e)
    
        myMemoryStream.Write(e.Buffer, 0, e.BytesRecorded);//this is for playing the myMemoryStream
        for (int index = 0; index < e.BytesRecorded; index += 2)//Here I convert in a loop the stream into floating number samples
        

            short sample = (short)((e.Buffer[index + 1] << 8) |
                                    e.Buffer[index + 0]);
            samples32.Add(sample / 32768f);//IEEE 32 floating number 
        
    

这是我的转换代码:

void floatBackToStream(float[] myfloatArray)
    
        short[] myShort = new short [myfloatArray.Length];
        myMemoryStream2 = new MemoryStream();
        for (int i = 0; i < myfloatArray.Length; i++)
        
            myShort[i] = (short)(myfloatArray[i] * 32768f);
            myMemoryStream2.WriteByte((byte)(myShort[i] & 255));
            myMemoryStream2.WriteByte((byte)(myShort[i] >> 8));
        

        myMemoryStream2.Position = 0;
        myRaw2 = new RawSourceWaveStream(myMemoryStream2, new WaveFormat(44100,1));
        WaveFileWriter.CreateWaveFile("C:/Users/alon/Desktop/myRecordings/myCalibration.wav", myRaw2);

    

【问题讨论】:

听起来好像在某处有一个低通滤波器...您使用的采样率是多少?您可以使用标准录音软件来录制您的音调吗? 44.1Khz。未应用数字滤波器。我必须用 NAudio 类录制。 你是如何设置你的WaveInEvent的?默认情况下,它使用 8kHz 采样率。 myWaveIn.WaveFormat = new WaveFormat(44100, 1); 在调试时,您希望首先隔离出现故障的系统。我建议您更换其中一个系统,看看问题是否在于您使用 NAudio 的方式。 【参考方案1】:

好的,所以:我创建了一个带通滤波器,峰值为 15 kHz。峰值为 +80dB,因为您说您在 12 kHz 处有 -80dB。如果我们想让滤波器正常工作,它需要是一个高阶传递函数。所以方程可能会变得很长,但它只是乘法和加法,因此 CPU 不会花费很长时间来执行。我假设您的采样率为 44,1 kHz。方程如下:

y[k]=a7*u[k-1]+a6*u[k-2]+a5*u[k-3]+a4*u[k-4]+a3*u[k-5]+a2*u[k-6]+a1*u[k-7]+a0*u[k-8] -b7*y[k-1]-b6*y[k-2]-b5*y[k-3]-b4*y[k-4]-b3*y[k-5]-b2*y[k-6]-b1*y[k-7]-b0*y[k-8];

其中u 是测量信号,y 是包含 15 kHz 频率的新矢量。现在有两种估计系数的方法:

    脉冲 [rad/s] = 2*pi * 频率 [Hz]

这是正确的物理方程。系数:

a7=207.5; 
a6=-578.1;
a5=546.6;
a4=-149.8;
a3=-49.39;
a2=22.21;
a1=1.349;
a0=0.006915;
b7=-0.945;
b6=0.3907;
b5=-0.09229;
b4=0.01363;
b3=-0.001288;
b2=0.00007605;
b1=-2.567*10^(-6);
b0=3.79*10^(-8);
    第二种方法是假设脉冲以 [Hz] 为单位。不要怪我,甚至一些 IDE 程序都遵循这种不恰当的做法。

对于这种情况,我们有以下系数:

a7=3.301;
a6=8.643;
a5=-51.47;
a4=59.35;
a3=-5.498;
a2=-23.56;
a1=8.625;
a0=0.6114;
b7=-5.693;
b6=14.18;
b5=-20.19;
b4=17.96;
b3=-10.22;
b2=3.638;
b1=-0.7397;
b0=0.0658;

只需尝试这两种方法,看看你会得到什么。确保使用足够精度的数据类型,以确保我们不会乘以 0。

【讨论】:

你好 Rafal,你用 matlab 提取系数了吗?如何计算其他频率的系数? 好吧,要设计过滤器,您必须对波特图有很好的了解。假设您要截断 10 kHz 以上的频率。这是脉冲 2*pi*10000 rad/s。接下来计算时间常数 T = 1/pulse。简单滤波就是一阶动力学系统,其传递函数为 G = k / (1+sT),其中 k 为增益,应为 1。 所以你在 Matlab 中使用命令 tf(..) 创建了这个传递函数。接下来,您必须使用 c2d(...) 将连续函数更改为离散函数。传递函数等于 Y/U,所以你得到一个方程 Y x function_denominator = U x function_nominator。离散函数中的算子为“z”,乘以z表示提前一个样本,例如Y*(2 + 5z) = 2y[k] + 5y[k+1]。将方程更改为 y[k+1] = f(y[k], y[k-1], ..., u[k], u[k-1], ...) 的形式。然后你就可以用任何编程语言实现等式了。

以上是关于无法使用麦克风 c# naudio 捕捉 15k 的音调的主要内容,如果未能解决你的问题,请参考以下文章

[C#] 使用 NAudio 实现音频可视化

[C#] NAudio 各种常见使用方式 播放 录制 转码 音频可视化

Naudio BadDeviceId 在 C# 中调用 waveInOpen 错误

C# 发送 NAudio WaveOut 到 Bing 语音识别平台

我将如何使用 NAudio 压缩来自麦克风的传入 PCM 数据?

C# 中的麦克风到扬声器音频流