To check out this repository please hg clone the following URL, or open the URL using EasyMercurial or your preferred Mercurial client.
The primary repository for this project is hosted at https://github.com/sonic-visualiser/sv-dependency-builds .
This repository is a read-only copy which is updated automatically every hour.
root / src / portaudio_20161030_catalina_patch / qa / loopback / src / biquad_filter.c @ 162:d43aab368df9
History | View | Annotate | Download (3.34 KB)
| 1 |
#include <math.h> |
|---|---|
| 2 |
#include <string.h> |
| 3 |
|
| 4 |
#include "biquad_filter.h" |
| 5 |
|
| 6 |
/**
|
| 7 |
* Unit_BiquadFilter implements a second order IIR filter.
|
| 8 |
Here is the equation that we use for this filter:
|
| 9 |
y(n) = a0*x(n) + a1*x(n-1) + a2*x(n-2) - b1*y(n-1) - b2*y(n-2)
|
| 10 |
*
|
| 11 |
* @author (C) 2002 Phil Burk, SoftSynth.com, All Rights Reserved
|
| 12 |
*/
|
| 13 |
|
| 14 |
#define FILTER_PI (3.141592653589793238462643) |
| 15 |
/***********************************************************
|
| 16 |
** Calculate coefficients common to many parametric biquad filters.
|
| 17 |
*/
|
| 18 |
static void BiquadFilter_CalculateCommon( BiquadFilter *filter, double ratio, double Q ) |
| 19 |
{
|
| 20 |
double omega;
|
| 21 |
|
| 22 |
memset( filter, 0, sizeof(BiquadFilter) ); |
| 23 |
|
| 24 |
/* Don't let frequency get too close to Nyquist or filter will blow up. */
|
| 25 |
if( ratio >= 0.499 ) ratio = 0.499; |
| 26 |
omega = 2.0 * (double)FILTER_PI * ratio; |
| 27 |
|
| 28 |
filter->cos_omega = (double) cos( omega );
|
| 29 |
filter->sin_omega = (double) sin( omega );
|
| 30 |
filter->alpha = filter->sin_omega / (2.0 * Q); |
| 31 |
} |
| 32 |
|
| 33 |
/*********************************************************************************
|
| 34 |
** Calculate coefficients for Highpass filter.
|
| 35 |
*/
|
| 36 |
void BiquadFilter_SetupHighPass( BiquadFilter *filter, double ratio, double Q ) |
| 37 |
{
|
| 38 |
double scalar, opc;
|
| 39 |
|
| 40 |
if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO;
|
| 41 |
if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q;
|
| 42 |
|
| 43 |
BiquadFilter_CalculateCommon( filter, ratio, Q ); |
| 44 |
|
| 45 |
scalar = 1.0 / (1.0 + filter->alpha); |
| 46 |
opc = (1.0 + filter->cos_omega); |
| 47 |
|
| 48 |
filter->a0 = opc * 0.5 * scalar; |
| 49 |
filter->a1 = - opc * scalar; |
| 50 |
filter->a2 = filter->a0; |
| 51 |
filter->b1 = -2.0 * filter->cos_omega * scalar; |
| 52 |
filter->b2 = (1.0 - filter->alpha) * scalar; |
| 53 |
} |
| 54 |
|
| 55 |
|
| 56 |
/*********************************************************************************
|
| 57 |
** Calculate coefficients for Notch filter.
|
| 58 |
*/
|
| 59 |
void BiquadFilter_SetupNotch( BiquadFilter *filter, double ratio, double Q ) |
| 60 |
{
|
| 61 |
double scalar, opc;
|
| 62 |
|
| 63 |
if( ratio < BIQUAD_MIN_RATIO ) ratio = BIQUAD_MIN_RATIO;
|
| 64 |
if( Q < BIQUAD_MIN_Q ) Q = BIQUAD_MIN_Q;
|
| 65 |
|
| 66 |
BiquadFilter_CalculateCommon( filter, ratio, Q ); |
| 67 |
|
| 68 |
scalar = 1.0 / (1.0 + filter->alpha); |
| 69 |
opc = (1.0 + filter->cos_omega); |
| 70 |
|
| 71 |
filter->a0 = scalar; |
| 72 |
filter->a1 = -2.0 * filter->cos_omega * scalar; |
| 73 |
filter->a2 = filter->a0; |
| 74 |
filter->b1 = filter->a1; |
| 75 |
filter->b2 = (1.0 - filter->alpha) * scalar; |
| 76 |
} |
| 77 |
|
| 78 |
/*****************************************************************
|
| 79 |
** Perform core IIR filter calculation without permutation.
|
| 80 |
*/
|
| 81 |
void BiquadFilter_Filter( BiquadFilter *filter, float *inputs, float *outputs, int numSamples ) |
| 82 |
{
|
| 83 |
int i;
|
| 84 |
double xn, yn;
|
| 85 |
// Pull values from structure to speed up the calculation.
|
| 86 |
double a0 = filter->a0;
|
| 87 |
double a1 = filter->a1;
|
| 88 |
double a2 = filter->a2;
|
| 89 |
double b1 = filter->b1;
|
| 90 |
double b2 = filter->b2;
|
| 91 |
double xn1 = filter->xn1;
|
| 92 |
double xn2 = filter->xn2;
|
| 93 |
double yn1 = filter->yn1;
|
| 94 |
double yn2 = filter->yn2;
|
| 95 |
|
| 96 |
for( i=0; i<numSamples; i++) |
| 97 |
{
|
| 98 |
// Generate outputs by filtering inputs.
|
| 99 |
xn = inputs[i]; |
| 100 |
yn = (a0 * xn) + (a1 * xn1) + (a2 * xn2) - (b1 * yn1) - (b2 * yn2); |
| 101 |
outputs[i] = yn; |
| 102 |
|
| 103 |
// Delay input and output values.
|
| 104 |
xn2 = xn1; |
| 105 |
xn1 = xn; |
| 106 |
yn2 = yn1; |
| 107 |
yn1 = yn; |
| 108 |
|
| 109 |
if( (i & 7) == 0 ) |
| 110 |
{
|
| 111 |
// Apply a small bipolar impulse to filter to prevent arithmetic underflow.
|
| 112 |
// Underflows can cause the FPU to interrupt the CPU.
|
| 113 |
yn1 += (double) 1.0E-26; |
| 114 |
yn2 -= (double) 1.0E-26; |
| 115 |
} |
| 116 |
} |
| 117 |
|
| 118 |
filter->xn1 = xn1; |
| 119 |
filter->xn2 = xn2; |
| 120 |
filter->yn1 = yn1; |
| 121 |
filter->yn2 = yn2; |
| 122 |
} |