/// <summary> /// H(s) = s / (s^2 + s/Q + 1) (constant skirt gain, peak gain = Q) /// </summary> public static BiQuadFilter BandPassFilterConstantSkirtGain(float sampleRate, float centreFrequency, float q) { double w0 = 2 * Math.PI * centreFrequency / sampleRate; double cosw0 = Math.Cos(w0); double sinw0 = Math.Sin(w0); double alpha = sinw0 / (2 * q); BiQuadFilter filter = new BiQuadFilter(); filter.b0 = sinw0 / 2; // = Q*alpha filter.b1 = 0; filter.b2 = -sinw0 / 2; // = -Q*alpha filter.a0 = 1 + alpha; filter.a1 = -2 * cosw0; filter.a2 = 1 - alpha; return filter; }
/// <summary> /// H(s) = (s^2 - s/Q + 1) / (s^2 + s/Q + 1) /// </summary> public static BiQuadFilter AllPassFilter(float sampleRate, float centreFrequency, float q) { double w0 = 2 * Math.PI * centreFrequency / sampleRate; double cosw0 = Math.Cos(w0); double sinw0 = Math.Sin(w0); double alpha = sinw0 / (2 * q); BiQuadFilter filter = new BiQuadFilter(); filter.b0 = 1 - alpha; filter.b1 = -2 * cosw0; filter.b2 = 1 + alpha; filter.a0 = 1 + alpha; filter.a1 = -2 * cosw0; filter.a2 = 1 - alpha; return filter; }
/// <summary> /// H(s) = s^2 / (s^2 + s/Q + 1) /// </summary> public static BiQuadFilter HighPassFilter(float sampleRate, float cutoffFrequency, float q) { double w0 = 2 * Math.PI * cutoffFrequency / sampleRate; double cosw0 = Math.Cos(w0); double alpha = Math.Sin(w0) / (2 * q); BiQuadFilter filter = new BiQuadFilter(); filter.b0 = (1 + Math.Cos(w0)) / 2; filter.b1 = -(1 + Math.Cos(w0)); filter.b2 = (1 + Math.Cos(w0)) / 2; filter.a0 = 1 + alpha; filter.a1 = -2 * Math.Cos(w0); filter.a2 = 1 - alpha; return filter; }
/// <summary> /// H(s) = (s^2 + s*(A/Q) + 1) / (s^2 + s/(A*Q) + 1) /// </summary> public static BiQuadFilter PeakingEQ(float sampleRate, float centreFrequency, float q, float dbGain) { double w0 = 2 * Math.PI * centreFrequency / sampleRate; double cosw0 = Math.Cos(w0); double sinw0 = Math.Sin(w0); double alpha = sinw0 / (2 * q); double A = Math.Pow(10, dbGain / 40); // TODO: should we square root this value? BiQuadFilter filter = new BiQuadFilter(); filter.b0 = 1 + alpha * A; filter.b1 = -2 * cosw0; filter.b2 = 1 - alpha * A; filter.a0 = 1 + alpha / A; filter.a1 = -2 * cosw0; filter.a2 = 1 - alpha / A; return filter; }
/// <summary> /// H(s) = A * (s^2 + (sqrt(A)/Q)*s + A)/(A*s^2 + (sqrt(A)/Q)*s + 1) /// </summary> /// <param name="sampleRate"></param> /// <param name="cutoffFrequency"></param> /// <param name="shelfSlope">a "shelf slope" parameter (for shelving EQ only). /// When S = 1, the shelf slope is as steep as it can be and remain monotonically /// increasing or decreasing gain with frequency. The shelf slope, in dB/octave, /// remains proportional to S for all other values for a fixed f0/Fs and dBgain.</param> /// <param name="dbGain">Gain in decibels</param> public static BiQuadFilter LowShelf(float sampleRate, float cutoffFrequency, float shelfSlope, float dbGain) { double w0 = 2 * Math.PI * cutoffFrequency / sampleRate; double cosw0 = Math.Cos(w0); double sinw0 = Math.Sin(w0); double A = Math.Pow(10, dbGain / 40); // TODO: should we square root this value? double alpha = sinw0 / 2 * Math.Sqrt((A + 1 / A) * (1 / shelfSlope - 1) + 2); double temp = 2 * Math.Sqrt(A) * alpha; BiQuadFilter filter = new BiQuadFilter(); filter.b0 = A * ((A + 1) - (A - 1) * cosw0 + temp); filter.b1 = 2 * A * ((A - 1) - (A + 1) * cosw0); filter.b2 = A * ((A + 1) - (A - 1) * cosw0 - temp); filter.a0 = (A + 1) + (A - 1) * cosw0 + temp; filter.a1 = -2 * ((A - 1) + (A + 1) * cosw0); filter.a2 = (A + 1) + (A - 1) * cosw0 - temp; return filter; }