void Biquad::setHighShelfParams(double frequency, double dbGain) { // Clip frequencies to between 0 and 1, inclusive. frequency = std::max(0.0, std::min(frequency, 1.0)); double A = pow(10.0, dbGain / 40); if (frequency == 1) { // The z-transform is 1. setNormalizedCoefficients(1, 0, 0, 1, 0, 0); } else if (frequency > 0) { double w0 = piDouble * frequency; double S = 1; // filter slope (1 is max value) double alpha = 0.5 * sin(w0) * sqrt((A + 1 / A) * (1 / S - 1) + 2); double k = cos(w0); double k2 = 2 * sqrt(A) * alpha; double aPlusOne = A + 1; double aMinusOne = A - 1; double b0 = A * (aPlusOne + aMinusOne * k + k2); double b1 = -2 * A * (aMinusOne + aPlusOne * k); double b2 = A * (aPlusOne + aMinusOne * k - k2); double a0 = aPlusOne - aMinusOne * k + k2; double a1 = 2 * (aMinusOne - aPlusOne * k); double a2 = aPlusOne - aMinusOne * k - k2; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); } else { // When frequency = 0, the filter is just a gain, A^2. setNormalizedCoefficients(A * A, 0, 0, 1, 0, 0); } }
void Biquad::setNotchParams(double frequency, double Q) { // Clip frequencies to between 0 and 1, inclusive. frequency = std::max(0.0, std::min(frequency, 1.0)); // Don't let Q go negative, which causes an unstable filter. Q = std::max(0.0, Q); if (frequency > 0 && frequency < 1) { if (Q > 0) { double w0 = piDouble * frequency; double alpha = sin(w0) / (2 * Q); double k = cos(w0); double b0 = 1; double b1 = -2 * k; double b2 = 1; double a0 = 1 + alpha; double a1 = -2 * k; double a2 = 1 - alpha; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); } else { // When Q = 0, the above formulas have problems. If we look at // the z-transform, we can see that the limit as Q->0 is 0, so // set the filter that way. setNormalizedCoefficients(0, 0, 0, 1, 0, 0); } } else { // When frequency is 0 or 1, the z-transform is 1. setNormalizedCoefficients(1, 0, 0, 1, 0, 0); } }
void Biquad::setLowpassParams(double cutoff, double resonance) { // Limit cutoff to 0 to 1. cutoff = std::max(0.0, std::min(cutoff, 1.0)); if (cutoff == 1) { // When cutoff is 1, the z-transform is 1. setNormalizedCoefficients(1, 0, 0, 1, 0, 0); } else if (cutoff > 0) { // Compute biquad coefficients for lowpass filter resonance = std::max(0.0, resonance); // can't go negative double g = pow(10.0, 0.05 * resonance); double d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); double theta = piDouble * cutoff; double sn = 0.5 * d * sin(theta); double beta = 0.5 * (1 - sn) / (1 + sn); double gamma = (0.5 + beta) * cos(theta); double alpha = 0.25 * (0.5 + beta - gamma); double b0 = 2 * alpha; double b1 = 2 * 2 * alpha; double b2 = 2 * alpha; double a1 = 2 * -gamma; double a2 = 2 * beta; setNormalizedCoefficients(b0, b1, b2, 1, a1, a2); } else { // When cutoff is zero, nothing gets through the filter, so set // coefficients up correctly. setNormalizedCoefficients(0, 0, 0, 1, 0, 0); } }
void Biquad::setLowpassParams(double cutoff, double resonance) { // Limit cutoff to 0 to 1. cutoff = std::max(0.0, std::min(cutoff, 1.0)); if (cutoff == 1) { // When cutoff is 1, the z-transform is 1. setNormalizedCoefficients(1, 0, 0, 1, 0, 0); } else if (cutoff > 0) { // Compute biquad coefficients for lowpass filter resonance = std::max(0.0, resonance); // can't go negative double g = pow(10.0, -0.05 * resonance); double w0 = M_PI * cutoff; double cos_w0 = cos(w0); double alpha = 0.5 * sin(w0) * g; double b1 = 1.0 - cos_w0; double b0 = 0.5 * b1; double b2 = b0; double a0 = 1.0 + alpha; double a1 = -2.0 * cos_w0; double a2 = 1.0 - alpha; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); } else { // When cutoff is zero, nothing gets through the filter, so set // coefficients up correctly. setNormalizedCoefficients(0, 0, 0, 1, 0, 0); } }
void Biquad::setHighpassParams(double cutoff, double resonance) { // Limit cutoff to 0 to 1. cutoff = std::max(0.0, std::min(cutoff, 1.0)); if (cutoff == 1) { // The z-transform is 0. setNormalizedCoefficients(0, 0, 0, 1, 0, 0); } else if (cutoff > 0) { // Compute biquad coefficients for highpass filter resonance = std::max(0.0, resonance); // can't go negative double g = pow(10.0, -0.05 * resonance); double w0 = M_PI * cutoff; double cos_w0 = cos(w0); double alpha = 0.5 * sin(w0) * g; double b1 = -1.0 - cos_w0; double b0 = -0.5 * b1; double b2 = b0; double a0 = 1.0 + alpha; double a1 = -2.0 * cos_w0; double a2 = 1.0 - alpha; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); } else { // When cutoff is zero, we need to be careful because the above // gives a quadratic divided by the same quadratic, with poles // and zeros on the unit circle in the same place. When cutoff // is zero, the z-transform is 1. setNormalizedCoefficients(1, 0, 0, 1, 0, 0); } }
Biquad::Biquad() { // Initialize as pass-thru (straight-wire, no filter effect) setNormalizedCoefficients(1, 0, 0, 1, 0, 0); reset(); // clear filter memory }
void Biquad::setBandpassParams(double frequency, double Q) { // No negative frequencies allowed. frequency = std::max(0.0, frequency); // Don't let Q go negative, which causes an unstable filter. Q = std::max(0.0, Q); if (frequency > 0 && frequency < 1) { double w0 = piDouble * frequency; if (Q > 0) { double alpha = sin(w0) / (2 * Q); double k = cos(w0); double b0 = alpha; double b1 = 0; double b2 = -alpha; double a0 = 1 + alpha; double a1 = -2 * k; double a2 = 1 - alpha; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); } else { // When Q = 0, the above formulas have problems. If we look at // the z-transform, we can see that the limit as Q->0 is 1, so // set the filter that way. setNormalizedCoefficients(1, 0, 0, 1, 0, 0); } } else { // When the cutoff is zero, the z-transform approaches 0, if Q // > 0. When both Q and cutoff are zero, the z-transform is // pretty much undefined. What should we do in this case? // For now, just make the filter 0. When the cutoff is 1, the // z-transform also approaches 0. setNormalizedCoefficients(0, 0, 0, 1, 0, 0); } }
Biquad::Biquad() { #if OS(DARWIN) // Allocate two samples more for filter history m_inputBuffer.allocate(kBufferSize + 2); m_outputBuffer.allocate(kBufferSize + 2); #endif // Initialize as pass-thru (straight-wire, no filter effect) setNormalizedCoefficients(1, 0, 0, 1, 0, 0); reset(); // clear filter memory }
void Biquad::setZeroPolePairs(const Complex& zero, const Complex& pole) { double b0 = 1; double b1 = -2 * zero.real(); double zeroMag = abs(zero); double b2 = zeroMag * zeroMag; double a1 = -2 * pole.real(); double poleMag = abs(pole); double a2 = poleMag * poleMag; setNormalizedCoefficients(b0, b1, b2, 1, a1, a2); }
void Biquad::setHighpassParams(double cutoff, double resonance) { // Limit cutoff to 0 to 1. cutoff = std::max(0.0, std::min(cutoff, 1.0)); if (cutoff == 1) { // The z-transform is 0. setNormalizedCoefficients(0, 0, 0, 1, 0, 0); } else if (cutoff > 0) { // Compute biquad coefficients for highpass filter resonance = std::max(0.0, resonance); // can't go negative double g = pow(10.0, 0.05 * resonance); double d = sqrt((4 - sqrt(16 - 16 / (g * g))) / 2); double theta = piDouble * cutoff; double sn = 0.5 * d * sin(theta); double beta = 0.5 * (1 - sn) / (1 + sn); double gamma = (0.5 + beta) * cos(theta); double alpha = 0.25 * (0.5 + beta + gamma); double b0 = 2 * alpha; double b1 = 2 * -2 * alpha; double b2 = 2 * alpha; double a1 = 2 * -gamma; double a2 = 2 * beta; setNormalizedCoefficients(b0, b1, b2, 1, a1, a2); } else { // When cutoff is zero, we need to be careful because the above // gives a quadratic divided by the same quadratic, with poles // and zeros on the unit circle in the same place. When cutoff // is zero, the z-transform is 1. setNormalizedCoefficients(1, 0, 0, 1, 0, 0); } }
void Biquad::setBandpassParams(double frequency, double Q) { double w0 = piDouble * frequency; double alpha = sin(w0) / (2 * Q); double k = cos(w0); double b0 = alpha; double b1 = 0; double b2 = -alpha; double a0 = 1 + alpha; double a1 = -2 * k; double a2 = 1 - alpha; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); }
void Biquad::setPeakingParams(double frequency, double Q, double dbGain) { double w0 = piDouble * frequency; double alpha = sin(w0) / (2 * Q); double A = pow(10.0, dbGain / 40); double k = cos(w0); double b0 = 1 + alpha * A; double b1 = -2 * k; double b2 = 1 - alpha * A; double a0 = 1 + alpha / A; double a1 = -2 * k; double a2 = 1 - alpha / A; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); }
Biquad::Biquad() { #if OS(DARWIN) // Allocate two samples more for filter history m_inputBuffer.allocate(kBufferSize + 2); m_outputBuffer.allocate(kBufferSize + 2); #endif #if USE(WEBAUDIO_IPP) int bufferSize; ippsIIRGetStateSize64f_BiQuad_32f(1, &bufferSize); m_ippInternalBuffer = ippsMalloc_8u(bufferSize); #endif // USE(WEBAUDIO_IPP) // Initialize as pass-thru (straight-wire, no filter effect) setNormalizedCoefficients(1, 0, 0, 1, 0, 0); reset(); // clear filter memory }
void Biquad::setHighShelfParams(double frequency, double dbGain) { double w0 = piDouble * frequency; double A = pow(10.0, dbGain / 40); double S = 1; // filter slope (1 is max value) double alpha = 0.5 * sin(w0) * sqrt((A + 1 / A) * (1 / S - 1) + 2); double k = cos(w0); double k2 = 2 * sqrt(A) * alpha; double aPlusOne = A + 1; double aMinusOne = A - 1; double b0 = A * (aPlusOne + aMinusOne * k + k2); double b1 = -2 * A * (aMinusOne + aPlusOne * k); double b2 = A * (aPlusOne + aMinusOne * k - k2); double a0 = aPlusOne - aMinusOne * k + k2; double a1 = 2 * (aMinusOne - aPlusOne * k); double a2 = aPlusOne - aMinusOne * k - k2; setNormalizedCoefficients(b0, b1, b2, a0, a1, a2); }