C# C语言中的低通和高通滤波器#

C# C语言中的低通和高通滤波器#,c#,signal-processing,matlab,C#,Signal Processing,Matlab,我需要用c#写的低通和高通滤波器。我有两个数组用于这个过滤过程。我想,如果我尝试将matlab Butterworth和Chebyshev算法转换为c#,这会更容易。但是我在互联网上找不到butter.m和Chebyshev算法的代码,我也不想把matlab和信号处理工具箱安装到我的计算机中。你能提供那个密码吗?谢谢 看看/ 它们都是开源的,因此如果您正在寻找的是“代码”,那么您就可以拥有它。我发现这个在线工具看起来很有前途: 您只需输入您的要求: 滤波器设计:巴特沃斯/贝塞尔/切比雪夫 滤波

我需要用c#写的低通和高通滤波器。我有两个数组用于这个过滤过程。我想,如果我尝试将matlab Butterworth和Chebyshev算法转换为c#,这会更容易。但是我在互联网上找不到butter.m和Chebyshev算法的代码,我也不想把matlab和信号处理工具箱安装到我的计算机中。你能提供那个密码吗?谢谢

看看/


它们都是开源的,因此如果您正在寻找的是“代码”,那么您就可以拥有它。

我发现这个在线工具看起来很有前途:

您只需输入您的要求:

  • 滤波器设计:巴特沃斯/贝塞尔/切比雪夫
  • 滤波器类型:低通/高通/带通/带阻
  • 过滤顺序
  • 转角频率
单击“提交”,它将计算以下信息:

  • 增益、极点、零
  • 递推关系
  • 实现递归关系的C代码
  • 幅值、相位、脉冲和阶跃响应图
您可以直接从递归关系在C#中实现过滤器


如果您只需要几个常量过滤器,那么就完成了。但是,如果您需要能够在运行时调整过滤器参数,则需要做更多的工作。幸运的是,教授提供了,并且应该可以转换为C。

您可以在另一个stackoverflow问题上查看Butterworth低通滤波器的源代码。 正如其他人指出的那样,EmguCV附带了大量高效编码的过滤器,并且可以开箱即用

我在我们的表面肌电分析仪软件中实现了上面的半代码过滤器,效果非常好

public class FilterButterworth
{
    /// <summary>
    /// rez amount, from sqrt(2) to ~ 0.1
    /// </summary>
    private readonly float resonance;

    private readonly float frequency;
    private readonly int sampleRate;
    private readonly PassType passType;

    private readonly float c, a1, a2, a3, b1, b2;

    /// <summary>
    /// Array of input values, latest are in front
    /// </summary>
    private float[] inputHistory = new float[2];

    /// <summary>
    /// Array of output values, latest are in front
    /// </summary>
    private float[] outputHistory = new float[3];

    public FilterButterworth(float frequency, int sampleRate, PassType passType, float resonance)
    {
        this.resonance = resonance;
        this.frequency = frequency;
        this.sampleRate = sampleRate;
        this.passType = passType;

        switch (passType)
        {
            case PassType.Lowpass:
                c = 1.0f / (float)Math.Tan(Math.PI * frequency / sampleRate);
                a1 = 1.0f / (1.0f + resonance * c + c * c);
                a2 = 2f * a1;
                a3 = a1;
                b1 = 2.0f * (1.0f - c * c) * a1;
                b2 = (1.0f - resonance * c + c * c) * a1;
                break;
            case PassType.Highpass:
                c = (float)Math.Tan(Math.PI * frequency / sampleRate);
                a1 = 1.0f / (1.0f + resonance * c + c * c);
                a2 = -2f * a1;
                a3 = a1;
                b1 = 2.0f * (c * c - 1.0f) * a1;
                b2 = (1.0f - resonance * c + c * c) * a1;
                break;
        }
    }

    public enum PassType
    {
        Highpass,
        Lowpass,
    }

    public void Update(float newInput)
    {
        float newOutput = a1 * newInput + a2 * this.inputHistory[0] + a3 * this.inputHistory[1] - b1 * this.outputHistory[0] - b2 * this.outputHistory[1];

        this.inputHistory[1] = this.inputHistory[0];
        this.inputHistory[0] = newInput;

        this.outputHistory[2] = this.outputHistory[1];
        this.outputHistory[1] = this.outputHistory[0];
        this.outputHistory[0] = newOutput;
    }

    public float Value
    {
        get { return this.outputHistory[0]; }
    }
}
公共类过滤器巴特沃斯
{
/// 
///rez量,从sqrt(2)到~0.1
/// 
私有只读浮动共振;
私有只读浮动频率;
私有只读int采样器;
私有只读PassType PassType;
专用只读浮点c、a1、a2、a3、b1、b2;
/// 
///输入值数组,最新值在前面
/// 
private float[]inputhhistory=新float[2];
/// 
///输出值数组,最新值在前面
/// 
私有浮点[]outputhhistory=新浮点[3];
公共滤波器巴特沃斯(浮动频率、整数采样率、通型通型、浮动共振)
{
这个共振=共振;
这个频率=频率;
this.sampleRate=sampleRate;
this.passType=passType;
交换机(passType)
{
case PassType.低通:
c=1.0f/(浮点数)数学Tan(数学π*频率/采样器);
a1=1.0f/(1.0f+共振*c+c*c);
a2=2f*a1;
a3=a1;
b1=2.0f*(1.0f-c*c)*a1;
b2=(1.0f-共振*c+c*c)*a1;
打破
case PassType.高通:
c=(浮点数)Math.Tan(Math.PI*频率/采样器);
a1=1.0f/(1.0f+共振*c+c*c);
a2=-2f*a1;
a3=a1;
b1=2.0f*(c*c-1.0f)*a1;
b2=(1.0f-共振*c+c*c)*a1;
打破
}
}
公共枚举密码类型
{
高通公司,
低通,
}
公共void更新(float newInput)
{
float newOutput=a1*newInput+a2*this.inpurthistory[0]+a3*this.inpurthistory[1]-b1*this.outpurthistory[0]-b2*this.outpurthistory[1];
this.inpusthistory[1]=this.inpusthistory[0];
this.inputHistory[0]=newInput;
this.outputhhistory[2]=this.outputhhistory[1];
this.outputhhistory[1]=this.outputhhistory[0];
this.outputhHistory[0]=新输出;
}
公众浮动价值
{
获取{返回此.outputhHistory[0];}
}
}

请注意,此过滤器是为音频DSP目的创建的。要创建干净的输出,您需要将共振设置为
sqrt(2)

以下是一些使用NMath的fft的a和滤波器的c#代码示例。

这里有一个,它有许多模式,HP LP BP peak,等等,这是一个双四阶,可能是2极的静态滤波器,它是一种特殊的滤波器,具有某种数字结果:

/*
*这些实现基于http://www.earlevel.com/main/2011/01/02/biquad-formulas/
*/
使用制度;
名称空间CSCore.DSP
{
/// 
///表示双四元过滤器。
/// 
公共抽象类双四元组
{
/// 
///a0值。
/// 
保护双A0;
/// 
///a1值。
/// 
保护双A1;
/// 
///a2值。
/// 
保护双A2;
/// 
///b1值。
/// 
保护双B1;
/// 
///b2值。
/// 
保护双B2;
/// 
///q值。
/// 
私人双q ;;
/// 
///增益值以dB为单位。
/// 
私人双倍收入b;
/// 
///z1值。
/// 
双保护Z1;
/// 
///z2值。
/// 
双保护Z2;
专用双频;
/// 
///获取或设置频率。
/// 
///值;采样器必须大于2*频率。
公共双频
{
获取{return\u frequency;}
设置
{
if(采样器<值*2)
{
抛出新ArgumentOutOfRangeException(“值”),必须
    /*
     * These implementations are based on http://www.earlevel.com/main/2011/01/02/biquad-formulas/
     */

    using System;

    namespace CSCore.DSP
    {
        /// <summary>
        /// Represents a biquad-filter.
        /// </summary>
        public abstract class BiQuad
        {
            /// <summary>
            /// The a0 value.
            /// </summary>
            protected double A0;
            /// <summary>
            /// The a1 value.
            /// </summary>
            protected double A1;
            /// <summary>
            /// The a2 value.
            /// </summary>
            protected double A2;
            /// <summary>
            /// The b1 value.
            /// </summary>
            protected double B1;
            /// <summary>
            /// The b2 value.
            /// </summary>
            protected double B2;
            /// <summary>
            /// The q value.
            /// </summary>
            private double _q;
            /// <summary>
            /// The gain value in dB.
            /// </summary>
            private double _gainDB;
            /// <summary>
            /// The z1 value.
            /// </summary>
            protected double Z1;
            /// <summary>
            /// The z2 value.
            /// </summary>
            protected double Z2;

            private double _frequency;

            /// <summary>
            /// Gets or sets the frequency.
            /// </summary>
            /// <exception cref="System.ArgumentOutOfRangeException">value;The samplerate has to be bigger than 2 * frequency.</exception>
            public double Frequency
            {
                get { return _frequency; }
                set
                {
                    if (SampleRate < value * 2)
                    {
                        throw new ArgumentOutOfRangeException("value", "The samplerate has to be bigger than 2 * frequency.");
                    }
                    _frequency = value;
                    CalculateBiQuadCoefficients();
                }
            }

            /// <summary>
            /// Gets the sample rate.
            /// </summary>
            public int SampleRate { get; private set; }

            /// <summary>
            /// The q value.
            /// </summary>
            public double Q
            {
                get { return _q; }
                set
                {
                    if (value <= 0)
                    {
                        throw new ArgumentOutOfRangeException("value");
                    }
                    _q = value;
                    CalculateBiQuadCoefficients();
                }
            }

            /// <summary>
            /// Gets or sets the gain value in dB.
            /// </summary>
            public double GainDB
            {
                get { return _gainDB; }
                set
                {
                    _gainDB = value;
                    CalculateBiQuadCoefficients();
                }
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="BiQuad"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The frequency.</param>
            /// <exception cref="System.ArgumentOutOfRangeException">
            /// sampleRate
            /// or
            /// frequency
            /// or
            /// q
            /// </exception>
            protected BiQuad(int sampleRate, double frequency)
                : this(sampleRate, frequency, 1.0 / Math.Sqrt(2))
            {
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="BiQuad"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The frequency.</param>
            /// <param name="q">The q.</param>
            /// <exception cref="System.ArgumentOutOfRangeException">
            /// sampleRate
            /// or
            /// frequency
            /// or
            /// q
            /// </exception>
            protected BiQuad(int sampleRate, double frequency, double q)
            {
                if (sampleRate <= 0)
                    throw new ArgumentOutOfRangeException("sampleRate");
                if (frequency <= 0)
                    throw new ArgumentOutOfRangeException("frequency");
                if (q <= 0)
                    throw new ArgumentOutOfRangeException("q");
                SampleRate = sampleRate;
                Frequency = frequency;
                Q = q;
                GainDB = 6;
            }

            /// <summary>
            /// Processes a single <paramref name="input"/> sample and returns the result.
            /// </summary>
            /// <param name="input">The input sample to process.</param>
            /// <returns>The result of the processed <paramref name="input"/> sample.</returns>
            public float Process(float input)
            {
                double o = input * A0 + Z1;
                Z1 = input * A1 + Z2 - B1 * o;
                Z2 = input * A2 - B2 * o;
                return (float)o;
            }

            /// <summary>
            /// Processes multiple <paramref name="input"/> samples.
            /// </summary>
            /// <param name="input">The input samples to process.</param>
            /// <remarks>The result of the calculation gets stored within the <paramref name="input"/> array.</remarks>
            public void Process(float[] input)
            {
                for (int i = 0; i < input.Length; i++)
                {
                    input[i] = Process(input[i]);
                }
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected abstract void CalculateBiQuadCoefficients();
        }

        /// <summary>
        /// Used to apply a lowpass-filter to a signal.
        /// </summary>
        public class LowpassFilter : BiQuad
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="LowpassFilter"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The filter's corner frequency.</param>
            public LowpassFilter(int sampleRate, double frequency)
                : base(sampleRate, frequency)
            {
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected override void CalculateBiQuadCoefficients()
            {
                double k = Math.Tan(Math.PI * Frequency / SampleRate);
                var norm = 1 / (1 + k / Q + k * k);
                A0 = k * k * norm;
                A1 = 2 * A0;
                A2 = A0;
                B1 = 2 * (k * k - 1) * norm;
                B2 = (1 - k / Q + k * k) * norm;
            }
        }

        /// <summary>
        /// Used to apply a highpass-filter to a signal.
        /// </summary>
        public class HighpassFilter : BiQuad
        {
            private int p1;
            private double p2;

            /// <summary>
            /// Initializes a new instance of the <see cref="HighpassFilter"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The filter's corner frequency.</param>
            public HighpassFilter(int sampleRate, double frequency) 
                : base(sampleRate, frequency)
            {
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected override void CalculateBiQuadCoefficients()
            {
                double k = Math.Tan(Math.PI * Frequency / SampleRate);
                var norm = 1 / (1 + k / Q + k * k);
                A0 = 1 * norm;
                A1 = -2 * A0;
                A2 = A0;
                B1 = 2 * (k * k - 1) * norm;
                B2 = (1 - k / Q + k * k) * norm;
            }
        }

        /// <summary>
        /// Used to apply a bandpass-filter to a signal.
        /// </summary>
        public class BandpassFilter : BiQuad
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="BandpassFilter"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The filter's corner frequency.</param>
            public BandpassFilter(int sampleRate, double frequency) 
                : base(sampleRate, frequency)
            {
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected override void CalculateBiQuadCoefficients()
            {
                double k = Math.Tan(Math.PI * Frequency / SampleRate);
                double norm = 1 / (1 + k / Q + k * k);
                A0 = k / Q * norm;
                A1 = 0;
                A2 = -A0;
                B1 = 2 * (k * k - 1) * norm;
                B2 = (1 - k / Q + k * k) * norm;
            }
        }

        /// <summary>
        /// Used to apply a notch-filter to a signal.
        /// </summary>
        public class NotchFilter : BiQuad
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="NotchFilter"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The filter's corner frequency.</param>
            public NotchFilter(int sampleRate, double frequency) 
                : base(sampleRate, frequency)
            {
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected override void CalculateBiQuadCoefficients()
            {
                double k = Math.Tan(Math.PI * Frequency / SampleRate);
                double norm = 1 / (1 + k / Q + k * k);
                A0 = (1 + k * k) * norm;
                A1 = 2 * (k * k - 1) * norm;
                A2 = A0;
                B1 = A1;
                B2 = (1 - k / Q + k * k) * norm;
            }
        }

        /// <summary>
        /// Used to apply a lowshelf-filter to a signal.
        /// </summary>
        public class LowShelfFilter : BiQuad
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="LowShelfFilter"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The filter's corner frequency.</param>
            /// <param name="gainDB">Gain value in dB.</param>
            public LowShelfFilter(int sampleRate, double frequency, double gainDB) 
                : base(sampleRate, frequency)
            {
                GainDB = gainDB;
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected override void CalculateBiQuadCoefficients()
            {
                const double sqrt2 = 1.4142135623730951;
                double k = Math.Tan(Math.PI * Frequency / SampleRate);
                double v = Math.Pow(10, Math.Abs(GainDB) / 20.0);
                double norm;
                if (GainDB >= 0)
                {    // boost
                    norm = 1 / (1 + sqrt2 * k + k * k);
                    A0 = (1 + Math.Sqrt(2 * v) * k + v * k * k) * norm;
                    A1 = 2 * (v * k * k - 1) * norm;
                    A2 = (1 - Math.Sqrt(2 * v) * k + v * k * k) * norm;
                    B1 = 2 * (k * k - 1) * norm;
                    B2 = (1 - sqrt2 * k + k * k) * norm;
                }
                else
                {    // cut
                    norm = 1 / (1 + Math.Sqrt(2 * v) * k + v * k * k);
                    A0 = (1 + sqrt2 * k + k * k) * norm;
                    A1 = 2 * (k * k - 1) * norm;
                    A2 = (1 - sqrt2 * k + k * k) * norm;
                    B1 = 2 * (v * k * k - 1) * norm;
                    B2 = (1 - Math.Sqrt(2 * v) * k + v * k * k) * norm;
                }
            }
        }

        /// <summary>
        /// Used to apply a highshelf-filter to a signal.
        /// </summary>
        public class HighShelfFilter : BiQuad
        {
            /// <summary>
            /// Initializes a new instance of the <see cref="HighShelfFilter"/> class.
            /// </summary>
            /// <param name="sampleRate">The sample rate.</param>
            /// <param name="frequency">The filter's corner frequency.</param>
            /// <param name="gainDB">Gain value in dB.</param>
            public HighShelfFilter(int sampleRate, double frequency, double gainDB)
                : base(sampleRate, frequency)
            {
                GainDB = gainDB;
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected override void CalculateBiQuadCoefficients()
            {
                const double sqrt2 = 1.4142135623730951;
                double k = Math.Tan(Math.PI * Frequency / SampleRate);
                double v = Math.Pow(10, Math.Abs(GainDB) / 20.0);
                double norm;
                if (GainDB >= 0)
                {    // boost
                    norm = 1 / (1 + sqrt2 * k + k * k);
                    A0 = (v + Math.Sqrt(2 * v) * k + k * k) * norm;
                    A1 = 2 * (k * k - v) * norm;
                    A2 = (v - Math.Sqrt(2 * v) * k + k * k) * norm;
                    B1 = 2 * (k * k - 1) * norm;
                    B2 = (1 - sqrt2 * k + k * k) * norm;
                }
                else
                {    // cut
                    norm = 1 / (v + Math.Sqrt(2 * v) * k + k * k);
                    A0 = (1 + sqrt2 * k + k * k) * norm;
                    A1 = 2 * (k * k - 1) * norm;
                    A2 = (1 - sqrt2 * k + k * k) * norm;
                    B1 = 2 * (k * k - v) * norm;
                    B2 = (v - Math.Sqrt(2 * v) * k + k * k) * norm;
                }
            }
        }

        /// <summary>
        /// Used to apply an peak-filter to a signal.
        /// </summary>
        public class PeakFilter : BiQuad
        {
            /// <summary>
            /// Gets or sets the bandwidth.
            /// </summary>
            public double BandWidth
            {
                get { return Q; }
                set
                {
                    if (value <= 0)
                        throw new ArgumentOutOfRangeException("value");
                    Q = value;
                }
            }

            /// <summary>
            /// Initializes a new instance of the <see cref="PeakFilter"/> class.
            /// </summary>
            /// <param name="sampleRate">The sampleRate of the audio data to process.</param>
            /// <param name="frequency">The center frequency to adjust.</param>
            /// <param name="bandWidth">The bandWidth.</param>
            /// <param name="peakGainDB">The gain value in dB.</param>
            public PeakFilter(int sampleRate, double frequency, double bandWidth, double peakGainDB)
                : base(sampleRate, frequency, bandWidth)
            {
                GainDB = peakGainDB;
            }

            /// <summary>
            /// Calculates all coefficients.
            /// </summary>
            protected override void CalculateBiQuadCoefficients()
            {
                double norm;
                double v = Math.Pow(10, Math.Abs(GainDB) / 20.0);
                double k = Math.Tan(Math.PI * Frequency / SampleRate);
                double q = Q;

                if (GainDB >= 0) //boost
                {
                    norm = 1 / (1 + 1 / q * k + k * k);
                    A0 = (1 + v / q * k + k * k) * norm;
                    A1 = 2 * (k * k - 1) * norm;
                    A2 = (1 - v / q * k + k * k) * norm;
                    B1 = A1;
                    B2 = (1 - 1 / q * k + k * k) * norm;
                }
                else //cut
                {
                    norm = 1 / (1 + v / q * k + k * k);
                    A0 = (1 + 1 / q * k + k * k) * norm;
                    A1 = 2 * (k * k - 1) * norm;
                    A2 = (1 - 1 / q * k + k * k) * norm;
                    B1 = A1;
                    B2 = (1 - v / q * k + k * k) * norm;
                }
            }
        }
    }