From ca10048e5caa77d8ed4c4902336f8ef88738a5e0 Mon Sep 17 00:00:00 2001 From: Andreas Eversberg Date: Sat, 13 May 2017 16:04:00 +0200 Subject: Rename filter -> iir_filter (file name and instance name) This is useful when using fir_filter in the future. --- src/common/Makefile.am | 2 +- src/common/call.c | 2 +- src/common/emphasis.c | 6 +- src/common/emphasis.h | 2 +- src/common/filter.c | 99 --------------------------------- src/common/filter.h | 14 ----- src/common/fm_modulation.c | 10 ++-- src/common/fm_modulation.h | 2 +- src/common/iir_filter.c | 133 +++++++++++++++++++++++++++++++++++++++++++++ src/common/iir_filter.h | 16 ++++++ src/common/samplerate.c | 10 ++-- src/common/samplerate.h | 8 +-- src/common/sdr.c | 2 +- src/common/sender.c | 2 +- 14 files changed, 172 insertions(+), 136 deletions(-) delete mode 100644 src/common/filter.c delete mode 100644 src/common/filter.h create mode 100644 src/common/iir_filter.c create mode 100644 src/common/iir_filter.h (limited to 'src/common') diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 095665e..fa26d21 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -12,7 +12,7 @@ libcommon_a_SOURCES = \ ../common/goertzel.c \ ../common/jitter.c \ ../common/loss.c \ - ../common/filter.c \ + ../common/iir_filter.c \ ../common/dtmf.c \ ../common/samplerate.c \ ../common/call.c \ diff --git a/src/common/call.c b/src/common/call.c index ff6128e..4452c5e 100644 --- a/src/common/call.c +++ b/src/common/call.c @@ -497,7 +497,7 @@ int call_init(const char *station_id, const char *audiodev, int samplerate, int if (!audiodev[0]) return 0; - rc = init_samplerate(&call.srstate, 8000.0, (double)samplerate); + rc = init_samplerate(&call.srstate, 8000.0, (double)samplerate, 3300.0); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to init sample rate conversion!\n"); goto error; diff --git a/src/common/emphasis.c b/src/common/emphasis.c index 3fb6679..241deee 100644 --- a/src/common/emphasis.c +++ b/src/common/emphasis.c @@ -22,7 +22,7 @@ #include #include #include "sample.h" -#include "filter.h" +#include "iir_filter.h" #include "emphasis.h" #include "debug.h" @@ -66,7 +66,7 @@ int init_emphasis(emphasis_t *state, int samplerate, double cut_off) state->d.factor = factor; state->d.amp = 1.0; - filter_highpass_init(&state->d.hp, CUT_OFF_H, samplerate, 1); + iir_highpass_init(&state->d.hp, CUT_OFF_H, samplerate, 1); /* calibrate amplification to be neutral at 1000 Hz */ gen_sine(test_samples, sizeof(test_samples) / sizeof(test_samples[0]), samplerate, 1000.0); @@ -128,6 +128,6 @@ void de_emphasis(emphasis_t *state, sample_t *samples, int num) /* high pass filter to remove DC and low frequencies */ void dc_filter(emphasis_t *state, sample_t *samples, int num) { - filter_process(&state->d.hp, samples, num); + iir_process(&state->d.hp, samples, num); } diff --git a/src/common/emphasis.h b/src/common/emphasis.h index 283afb1..235e3ce 100644 --- a/src/common/emphasis.h +++ b/src/common/emphasis.h @@ -5,7 +5,7 @@ typedef struct emphasis { double amp; } p; struct { - filter_t hp; + iir_filter_t hp; double y_last; double factor; double amp; diff --git a/src/common/filter.c b/src/common/filter.c deleted file mode 100644 index 0a5c0dd..0000000 --- a/src/common/filter.c +++ /dev/null @@ -1,99 +0,0 @@ -/* cut-off filter (biquad) based on Nigel Redmon (www.earlevel.com) - * - * (C) 2016 by Andreas Eversberg - * All Rights Reserved - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see . - */ - -#include -#include -#include -#include -#include -#include "sample.h" -#include "filter.h" - -#define PI M_PI - -void filter_lowpass_init(filter_t *bq, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - if (iterations > 64) { - fprintf(stderr, "%s failed: too many iterations, please fix!\n", __func__); - abort(); - } - - memset(bq, 0, sizeof(*bq)); - bq->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - bq->a0 = K * K * norm; - bq->a1 = 2 * bq->a0; - bq->a2 = bq->a0; - bq->b1 = 2 * (K * K - 1) * norm; - bq->b2 = (1 - K / Q + K * K) * norm; -} - -void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int iterations) -{ - double Fc, Q, K, norm; - - memset(bq, 0, sizeof(*bq)); - bq->iter = iterations; - Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ - Fc = frequency / (double)samplerate; - K = tan(PI * Fc); - norm = 1 / (1 + K / Q + K * K); - bq->a0 = 1 * norm; - bq->a1 = -2 * bq->a0; - bq->a2 = bq->a0; - bq->b1 = 2 * (K * K - 1) * norm; - bq->b2 = (1 - K / Q + K * K) * norm; -} - -void filter_process(filter_t *bq, sample_t *samples, int length) -{ - double a0, a1, a2, b1, b2; - double *z1, *z2; - double in, out; - int iterations = bq->iter; - int i, j; - - /* get states */ - a0 = bq->a0; - a1 = bq->a1; - a2 = bq->a2; - b1 = bq->b1; - b2 = bq->b2; - - z1 = bq->z1; - z2 = bq->z2; - - /* process filter */ - for (i = 0; i < length; i++) { - in = *samples; - for (j = 0; j < iterations; j++) { - out = in * a0 + z1[j]; - z1[j] = in * a1 + z2[j] - b1 * out; - z2[j] = in * a2 - b2 * out; - in = out; - } - *samples++ = in; - } -} - diff --git a/src/common/filter.h b/src/common/filter.h deleted file mode 100644 index 9f33fe2..0000000 --- a/src/common/filter.h +++ /dev/null @@ -1,14 +0,0 @@ -#ifndef _FILTER_H -#define _FILTER_H - -typedef struct filter { - int iter; - double a0, a1, a2, b1, b2; - double z1[64], z2[64]; -} filter_t; - -void filter_lowpass_init(filter_t *bq, double frequency, int samplerate, int iterations); -void filter_highpass_init(filter_t *bq, double frequency, int samplerate, int iterations); -void filter_process(filter_t *bq, sample_t *samples, int length); - -#endif /* _FILTER_H */ diff --git a/src/common/fm_modulation.c b/src/common/fm_modulation.c index dca88b0..aaf7e2c 100644 --- a/src/common/fm_modulation.c +++ b/src/common/fm_modulation.c @@ -23,7 +23,7 @@ #include #include #include "sample.h" -#include "filter.h" +#include "iir_filter.h" #include "fm_modulation.h" //#define FAST_SINE @@ -110,8 +110,8 @@ void fm_demod_init(fm_demod_t *demod, double samplerate, double offset, double b #endif /* use fourth order (2 iter) filter, since it is as fast as second order (1 iter) filter */ - filter_lowpass_init(&demod->lp[0], bandwidth / 2.0, samplerate, 2); - filter_lowpass_init(&demod->lp[1], bandwidth / 2.0, samplerate, 2); + iir_lowpass_init(&demod->lp[0], bandwidth / 2.0, samplerate, 2); + iir_lowpass_init(&demod->lp[1], bandwidth / 2.0, samplerate, 2); #ifdef FAST_SINE int i; @@ -169,8 +169,8 @@ void fm_demodulate(fm_demod_t *demod, sample_t *samples, int num, float *buff) Q[s] = i * _sin + q * _cos; } demod->phase = phase; - filter_process(&demod->lp[0], I, num); - filter_process(&demod->lp[1], Q, num); + iir_process(&demod->lp[0], I, num); + iir_process(&demod->lp[1], Q, num); last_phase = demod->last_phase; for (s = 0; s < num; s++) { phase = atan2(Q[s], I[s]); diff --git a/src/common/fm_modulation.h b/src/common/fm_modulation.h index 194ae3f..2cd571a 100644 --- a/src/common/fm_modulation.h +++ b/src/common/fm_modulation.h @@ -15,7 +15,7 @@ typedef struct fm_demod { double phase; /* current rotation phase (used to shift) */ double rot; /* rotation step per sample to shift rx frequency (used to shift) */ double last_phase; /* last phase of FM (used to demodulate) */ - filter_t lp[2]; /* filters received IQ signal */ + iir_filter_t lp[2]; /* filters received IQ signal */ double *sin_tab; /* sine/cosine table rotation */ } fm_demod_t; diff --git a/src/common/iir_filter.c b/src/common/iir_filter.c new file mode 100644 index 0000000..d080728 --- /dev/null +++ b/src/common/iir_filter.c @@ -0,0 +1,133 @@ +/* cut-off filter (biquad) based on Nigel Redmon (www.earlevel.com) + * + * (C) 2016 by Andreas Eversberg + * All Rights Reserved + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include "sample.h" +#include "iir_filter.h" + +#define PI M_PI + +void iir_lowpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) +{ + double Fc, Q, K, norm; + + if (iterations > 64) { + fprintf(stderr, "%s failed: too many iterations, please fix!\n", __func__); + abort(); + } + + memset(filter, 0, sizeof(*filter)); + filter->iter = iterations; + Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ + Fc = frequency / (double)samplerate; + K = tan(PI * Fc); + norm = 1 / (1 + K / Q + K * K); + filter->a0 = K * K * norm; + filter->a1 = 2 * filter->a0; + filter->a2 = filter->a0; + filter->b1 = 2 * (K * K - 1) * norm; + filter->b2 = (1 - K / Q + K * K) * norm; +} + +void iir_highpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) +{ + double Fc, Q, K, norm; + + memset(filter, 0, sizeof(*filter)); + filter->iter = iterations; + Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ + Fc = frequency / (double)samplerate; + K = tan(PI * Fc); + norm = 1 / (1 + K / Q + K * K); + filter->a0 = 1 * norm; + filter->a1 = -2 * filter->a0; + filter->a2 = filter->a0; + filter->b1 = 2 * (K * K - 1) * norm; + filter->b2 = (1 - K / Q + K * K) * norm; +} + +void iir_bandpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) +{ + double Fc, Q, K, norm; + + memset(filter, 0, sizeof(*filter)); + filter->iter = iterations; + Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ + Fc = frequency / (double)samplerate; + K = tan(PI * Fc); + norm = 1 / (1 + K / Q + K * K); + filter->a0 = K / Q * norm; + filter->a1 = 0; + filter->a2 = -filter->a0; + filter->b1 = 2 * (K * K - 1) * norm; + filter->b2 = (1 - K / Q + K * K) * norm; +} + +void iir_notch_init(iir_filter_t *filter, double frequency, int samplerate, int iterations) +{ + double Fc, Q, K, norm; + + memset(filter, 0, sizeof(*filter)); + filter->iter = iterations; + Q = pow(sqrt(0.5), 1.0 / (double)iterations); /* 0.7071 @ 1 iteration */ + Fc = frequency / (double)samplerate; + K = tan(PI * Fc); + norm = 1 / (1 + K / Q + K * K); + filter->a0 = (1 + K * K) * norm; + filter->a1 = 2 * (K * K - 1) * norm; + filter->a2 = filter->a0; + filter->b1 = filter->a1; + filter->b2 = (1 - K / Q + K * K) * norm; +} + +void iir_process(iir_filter_t *filter, sample_t *samples, int length) +{ + double a0, a1, a2, b1, b2; + double *z1, *z2; + double in, out; + int iterations = filter->iter; + int i, j; + + /* get states */ + a0 = filter->a0; + a1 = filter->a1; + a2 = filter->a2; + b1 = filter->b1; + b2 = filter->b2; + + z1 = filter->z1; + z2 = filter->z2; + + /* process filter */ + for (i = 0; i < length; i++) { + in = *samples; + for (j = 0; j < iterations; j++) { + out = in * a0 + z1[j]; + z1[j] = in * a1 + z2[j] - b1 * out; + z2[j] = in * a2 - b2 * out; + in = out; + } + *samples++ = in; + } +} + diff --git a/src/common/iir_filter.h b/src/common/iir_filter.h new file mode 100644 index 0000000..9d237eb --- /dev/null +++ b/src/common/iir_filter.h @@ -0,0 +1,16 @@ +#ifndef _FILTER_H +#define _FILTER_H + +typedef struct iir_filter { + int iter; + double a0, a1, a2, b1, b2; + double z1[64], z2[64]; +} iir_filter_t; + +void iir_lowpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); +void iir_highpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); +void iir_bandpass_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); +void iir_notch_init(iir_filter_t *filter, double frequency, int samplerate, int iterations); +void iir_process(iir_filter_t *filter, sample_t *samples, int length); + +#endif /* _FILTER_H */ diff --git a/src/common/samplerate.c b/src/common/samplerate.c index 8187748..db6b278 100644 --- a/src/common/samplerate.c +++ b/src/common/samplerate.c @@ -25,7 +25,7 @@ #include "sample.h" #include "samplerate.h" -int init_samplerate(samplerate_t *state, double low_samplerate, double high_samplerate) +int init_samplerate(samplerate_t *state, double low_samplerate, double high_samplerate, double filter_cutoff) { memset(state, 0, sizeof(*state)); state->factor = high_samplerate / low_samplerate; @@ -34,8 +34,8 @@ int init_samplerate(samplerate_t *state, double low_samplerate, double high_samp abort(); } - filter_lowpass_init(&state->up.lp, 3300.0, high_samplerate, 2); - filter_lowpass_init(&state->down.lp, 3300.0, high_samplerate, 2); + iir_lowpass_init(&state->up.lp, filter_cutoff, high_samplerate, 2); + iir_lowpass_init(&state->down.lp, filter_cutoff, high_samplerate, 2); return 0; } @@ -49,7 +49,7 @@ int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num) sample_t last_sample; /* filter down */ - filter_process(&state->down.lp, samples, input_num); + iir_process(&state->down.lp, samples, input_num); /* get last sample for interpolation */ last_sample = state->down.last_sample; @@ -144,7 +144,7 @@ int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sam state->up.in_index = in_index; /* filter up */ - filter_process(&state->up.lp, samples, output_num); + iir_process(&state->up.lp, samples, output_num); if (input == output) { /* copy samples */ diff --git a/src/common/samplerate.h b/src/common/samplerate.h index 8c69741..4fbf680 100644 --- a/src/common/samplerate.h +++ b/src/common/samplerate.h @@ -1,19 +1,19 @@ -#include "filter.h" +#include "iir_filter.h" typedef struct samplerate { double factor; struct { - filter_t lp; + iir_filter_t lp; sample_t last_sample; double in_index; } down; struct { - filter_t lp; + iir_filter_t lp; sample_t last_sample; double in_index; } up; } samplerate_t; -int init_samplerate(samplerate_t *state, double low_samplerate, double high_samplerate); +int init_samplerate(samplerate_t *state, double low_samplerate, double high_samplerate, double filter_cutoff); int samplerate_downsample(samplerate_t *state, sample_t *samples, int input_num); int samplerate_upsample(samplerate_t *state, sample_t *input, int input_num, sample_t *output); diff --git a/src/common/sdr.c b/src/common/sdr.c index 4205c21..b654b4f 100644 --- a/src/common/sdr.c +++ b/src/common/sdr.c @@ -24,7 +24,7 @@ #include #include #include "sample.h" -#include "filter.h" +#include "iir_filter.h" #include "fm_modulation.h" #include "sender.h" #ifdef HAVE_UHD diff --git a/src/common/sender.c b/src/common/sender.c index da7822b..8137cef 100644 --- a/src/common/sender.c +++ b/src/common/sender.c @@ -114,7 +114,7 @@ int sender_create(sender_t *sender, int kanal, double sendefrequenz, double empf } } - rc = init_samplerate(&sender->srstate, 8000.0, (double)samplerate); + rc = init_samplerate(&sender->srstate, 8000.0, (double)samplerate, 3300.0); if (rc < 0) { PDEBUG(DSENDER, DEBUG_ERROR, "Failed to init sample rate conversion!\n"); goto error; -- cgit v1.2.3