C#仿matlab函数进行语音降噪(有bug)

一.介绍
前段时间接到一个项目:侦听调频广播,实现频谱、瀑布图显示,话音播放、存储及语音时域图绘制。其中,话音播放时感觉其噪声很大,必须对其降噪。在C#网上搜索了很多关于C#降噪的,没搜到。利用MATLAB编写降噪函数,并生成dll,但是发现调用Matlab的dll挺耗时的,所以不采用这种方式。于是我仿MATLAB降噪的函数,写出了C#版降噪函数。播放的话音明显实现了,但是其中有一个bug,就是降噪后会有哒哒哒的声音,找了好久没找到原因。如果能找出bug的兄弟,望告知一下。
二.代码
1.低通滤波函数

// 说明:MATLAB转C#函数
private double[,] Lowpass_T(Int16[] Indata, int Len)
{
    //定义滤波结果的数组,为二位数组,Len行,1列
    double[,] Filterdata = new double[Len, 1];
    int LowpassLen = 67;
    //滤波器系数
    double[] LowpassBuf_1 = new double[] {
  -0.0002297245116924, -0.001272528501084, -0.003334224714919, -0.006360776347928,
  - 0.009289045067669, -0.01048313976472, -0.008492643648294, -0.003258372951239,
   0.003268094048695, 0.007734987474474, 0.007277665725254, 0.001653277578148,
  - 0.005926998028789, -0.01029359540466, -0.007644782129877, 0.001353382650881,
    0.01111257398261, 0.01429420479649, 0.007026067120628, -0.007359476125338,
   - 0.01926144120085, -0.01876047817833, -0.003187318370228, 0.01905162190054,
    0.03211612756329, 0.02284966783339, -0.008518122931876, -0.04454921689637,
   - 0.05771153561822, -0.02573624712695, 0.05336790092737, 0.1561693966912,
     0.2429077783893, 0.2767802107121, 0.2429077783893, 0.1561693966912,
    0.05336790092737, -0.02573624712695, -0.05771153561822, -0.04454921689637,
  - 0.008518122931876, 0.02284966783339, 0.03211612756329, 0.01905162190054,
  - 0.003187318370228, -0.01876047817833, -0.01926144120085, -0.007359476125338,
   0.007026067120628, 0.01429420479649, 0.01111257398261, 0.001353382650881,
  - 0.007644782129877, -0.01029359540466, -0.005926998028789, 0.001653277578148,
   0.007277665725254, 0.007734987474474, 0.003268094048695, -0.003258372951239,
  - 0.008492643648294, -0.01048313976472, -0.009289045067669, -0.006360776347928,
  - 0.003334224714919, -0.001272528501084, -0.0002297245116924
    };
    //将滤波系数LowpassBuf_1转化为二位数组
    double[,] LowpassBuf = new double[LowpassBuf_1.Length, 1];
    for (int i = 0; i < LowpassBuf_1.Length; i++)
    {
        LowpassBuf[i, 0] = LowpassBuf_1[i];
    }
    //创建缓存变量
    Int16[] m_pData = new Int16[Len];

    //计算滤波
    for (int k = 0; k < Len; k++)
    {
        for (int i = LowpassLen - 1; i > 0; i--)
        {
            m_pData[i] = m_pData[i - 1];
        }

        m_pData[0] = Indata[k];
        double Temp = 0;
        for (int i = 0; i < LowpassLen; i++)
        {
            Temp = Temp + LowpassBuf[i, 0] * m_pData[i] * 2;
        }
        //保存为Len行1列的数组
        Filterdata[k, 0] = Temp;
    }
    return Filterdata;
}

2.降噪函数

 // 说明:MATLAB转C#函数
    private double[] NoiseReduction_T(Int16[] Indata, int Len, int Thre)
    {
        // 定义返回数组,和输入数据长度等长
        double[] Outdata = new double[Len];
            // 滤波器
            double[,] Filterdata = Lowpass_T(Indata, Len);

            // 设置窗口长度
            int Win = 256;
            for (int i = 0; i < Len / Win; i++)
            {
                //将数据按Win长度分段处理
                double[] Windata = new double[Win];
                for (int m = 0; m < Win; m++)
                {
                    Windata[m] = Filterdata[i * Win + m, 0];
                }
                int sum = 0;

                //判断每个Win长度数据中小于阈值Thre的数据个数
                for (int j = 0; j < Win; j++)
                {
                    if (Windata[j] < Thre)
                    {
                        sum = sum + 1;
                    }
                }
                // 如果大于250个 则认定为噪声 并对这段Win长度数据归零 如果不是噪声 往后延续15段保证声音连续
                if (sum > 250)
                {
                    for (int m = 0; m < Win; m++)
                    {
                        Filterdata[i * Win + m, 0] = 0;
                    }
                }
                else
                {
                    i = i + 15;
                }
            }

            for (int i = 0; i < Len; i++)
            {
                Outdata[i] = Filterdata[i, 0];
            }
            return Outdata;
        }

3.降噪处理函数

// 自定义函数:降噪处理
    public byte[] DeNoise(byte[] sData, int nLen, int Fs, int Thre)
    {
        // 长度:8192
        byte[] result = new byte[nLen];

        // 长度:4096
        Int16[] buffer_s = new Int16[nLen / 2];
        for (int i = 0; i < buffer_s.Length; i++)
        {
            // 两个字节转为short(低位在前,高位在后)
            buffer_s[i] = BitConverter.ToInt16(new byte[] {sData[2 * i], sData[2 * i + 1] }, 0);
        }

        // 降噪处理:输入(长度:4096)
        Int16[] array_In = buffer_s;

        // 降噪处理:输出(长度:4096)
        double[] array_Out = NoiseReduction_T(array_In, buffer_s.Length, Thre);

        // 取出最后一个值(即索引为4096的值)
        for (int i = 0; i < array_Out.Length - 1; i++)
        {
            sbyte[] tmp = TypeCast(array_Out[i]);
            result[i * 2] = (byte)tmp[0];           // 低位在前
            result[i * 2 + 1] = (byte)tmp[1];       // 高位在后
        }

        return result;
    }

4.调用降噪处理函数

        //降噪
        byte[] bytesDst = bytesSrc;                                
        bytesDst = m_NoiseReduct.DeNoise(bytesSrc, bytesSrc.Length, 31500, m_nThresholdDeNoise);
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

muyiliu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值