2011-11-10 205 views
17

我需要用c#編寫的低通和高通濾波器。我有這個過濾器過程的雙數組。我想如果我嘗試將matlab Butterworth和Chebyshev算法轉換爲c#,它會更容易。但是我無法在互聯網上找到butter.m和Chebyshev算法的代碼,我也不想將matlab和信號處理工具箱設置到我的電腦中。你能提供那些代碼嗎?謝謝..C中的低通和高通濾波器#

回答

1

看一看OpenCV/EmguCV

他們都是開源的,所以你可以有「代碼」,如果這是你在找什麼。

+0

感謝您的建議。這些網站非常有用。但是我找不到低通和高通濾波器 – user741319

+1

沒有這個名字。所有的邊緣搜索算法都是高通的,所有的高斯均值和中值濾波器都是低通的。 – Aliostad

10

我發現這個在線工具,看起來很有希望:Interactive Digital Filter Design: Butterworth/Bessel/Chebyshev Filters

你只需輸入你的需求:

  • 濾波器設計:北海/貝塞爾/切比雪夫
  • 濾波器類型:低通/高通/帶通/ Bandstop
  • 濾波器次序
  • 角頻率/頻率

點擊提交,並計算了以下信息:

  • 收益,極點,零點
  • 遞推關係
  • C代碼實現的遞推關係的幅度,相位,衝動
  • 情節和一步響應

您可以直接從循環關係實現C#中的過濾器。

如果您只需要幾個常量過濾器,就完成了。但是,如果您需要能夠在運行時調整過濾器參數,則需要做更多。幸運的是,教授提供了the source code for his tool,應該可以轉換爲C#。

2

您可以在另一個stackoverflow問題上看看Butterworth低通濾波器here的源代碼。 正如其他人指出EmguCV自帶了很多過濾器效率和avalaible編碼開箱

12

http://www.musicdsp.org/archive.php?classid=3#38

我實現了過濾器semicode以上如下我們的sEMG分析儀軟件,它的效果很好。

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]; } 
    } 
} 
-1

這裏有一個它有很多模式,HP LP BP峯值等等,它是一個BiQuad或許是這種類型的2極靜態濾波器,它是一個特定的濾波器並且具有某種數字結果: https://github.com/filoe/cscore/blob/master/CSCore/DSP/BiQuad.cs

/* 
    * 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; 
       } 
      } 
     } 
    }