aboutsummaryrefslogtreecommitdiffstats
path: root/src/common
diff options
context:
space:
mode:
authorAndreas Eversberg <jolly@eversberg.eu>2017-01-15 11:08:42 +0100
committerAndreas Eversberg <jolly@eversberg.eu>2017-02-18 21:01:04 +0100
commitac0da3f76ee3f31599b0c572ed296b251e94378b (patch)
treea1e3bfe7bedd349db38c11487023a57e5da1dfe0 /src/common
parent799b96c801567c1cd0c6a1281511bca90eeac1db (diff)
Filter improvement: LP and HP filters, added test function
The -3 dB level at cut-off frequency is now maintained for multiple iterations.
Diffstat (limited to 'src/common')
-rw-r--r--src/common/filter.c37
-rw-r--r--src/common/filter.h12
-rw-r--r--src/common/samplerate.c8
-rw-r--r--src/common/samplerate.h4
-rw-r--r--src/common/sdr.c10
5 files changed, 45 insertions, 26 deletions
diff --git a/src/common/filter.c b/src/common/filter.c
index f568f1b..3aea327 100644
--- a/src/common/filter.c
+++ b/src/common/filter.c
@@ -26,14 +26,18 @@
#define PI M_PI
-//#define CASCADE
-
-void filter_lowpass_init(filter_lowpass_t *bq, double frequency, int samplerate)
+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));
- Q = sqrt(0.5); /* 0.7071... */
+ 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);
@@ -44,18 +48,31 @@ void filter_lowpass_init(filter_lowpass_t *bq, double frequency, int samplerate)
bq->b2 = (1 - K / Q + K * K) * norm;
}
-void filter_lowpass_process(filter_lowpass_t *bq, double *samples, int length, int iterations)
+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, double *samples, int length)
{
double a0, a1, a2, b1, b2;
double *z1, *z2;
double in, out;
+ int iterations = bq->iter;
int i, j;
- if (iterations > 10) {
- fprintf(stderr, "%s failed: too many iterations, please fix!\n", __func__);
- abort();
- }
-
/* get states */
a0 = bq->a0;
a1 = bq->a1;
diff --git a/src/common/filter.h b/src/common/filter.h
index 09a379b..42f051b 100644
--- a/src/common/filter.h
+++ b/src/common/filter.h
@@ -1,12 +1,14 @@
#ifndef _FILTER_H
#define _FILTER_H
-typedef struct filter_lowpass {
+typedef struct filter {
+ int iter;
double a0, a1, a2, b1, b2;
- double z1[10], z2[10];
-} filter_lowpass_t;
+ double z1[64], z2[64];
+} filter_t;
-void filter_lowpass_init(filter_lowpass_t *bq, double frequency, int samplerate);
-void filter_lowpass_process(filter_lowpass_t *bq, double *samples, int length, int iterations);
+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, double *samples, int length);
#endif /* _FILTER_H */
diff --git a/src/common/samplerate.c b/src/common/samplerate.c
index 8113055..f554cf0 100644
--- a/src/common/samplerate.c
+++ b/src/common/samplerate.c
@@ -37,8 +37,8 @@ int init_samplerate(samplerate_t *state, double samplerate)
memset(state, 0, sizeof(*state));
state->factor = samplerate / 8000.0;
- filter_lowpass_init(&state->up.lp, 4000.0, samplerate);
- filter_lowpass_init(&state->down.lp, 4000.0, samplerate);
+ filter_lowpass_init(&state->up.lp, 4000.0, samplerate, 1);
+ filter_lowpass_init(&state->down.lp, 4000.0, samplerate, 1);
return 0;
}
@@ -56,7 +56,7 @@ int samplerate_downsample(samplerate_t *state, int16_t *input, int input_num, in
spl[i] = *input++ / 32768.0;
/* filter down */
- filter_lowpass_process(&state->down.lp, spl, input_num, 1);
+ filter_process(&state->down.lp, spl, input_num);
/* resample filtered result */
in_index = state->down.in_index;
@@ -125,7 +125,7 @@ int samplerate_upsample(samplerate_t *state, int16_t *input, int input_num, int1
state->up.in_index = in_index;
/* filter up */
- filter_lowpass_process(&state->up.lp, spl, output_num, 1);
+ filter_process(&state->up.lp, spl, output_num);
/* convert double to samples */
for (i = 0; i < output_num; i++) {
diff --git a/src/common/samplerate.h b/src/common/samplerate.h
index 27955de..d8c9d41 100644
--- a/src/common/samplerate.h
+++ b/src/common/samplerate.h
@@ -3,11 +3,11 @@
typedef struct samplerate {
double factor;
struct {
- filter_lowpass_t lp;
+ filter_t lp;
double in_index;
} down;
struct {
- filter_lowpass_t lp;
+ filter_t lp;
double in_index;
} up;
} samplerate_t;
diff --git a/src/common/sdr.c b/src/common/sdr.c
index 2644968..db46906 100644
--- a/src/common/sdr.c
+++ b/src/common/sdr.c
@@ -39,7 +39,7 @@ typedef struct sdr_chan {
double rx_rot; /* rotation step per sample to shift rx frequency (used to shift) */
double rx_phase; /* current rotation phase (used to shift) */
double rx_last_phase; /* last phase of FM (used to demodulate) */
- filter_lowpass_t rx_lp[2]; /* filters received IQ signal */
+ filter_t rx_lp[2]; /* filters received IQ signal */
} sdr_chan_t;
typedef struct sdr {
@@ -123,8 +123,8 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
PDEBUG(DSDR, DEBUG_INFO, "Frequency #%d: TX = %.6f MHz, RX = %.6f MHz\n", c, tx_frequency[c] / 1e6, rx_frequency[c] / 1e6);
sdr->chan[c].tx_frequency = tx_frequency[c];
sdr->chan[c].rx_frequency = rx_frequency[c];
- filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth, samplerate);
- filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth, samplerate);
+ filter_lowpass_init(&sdr->chan[c].rx_lp[0], bandwidth, samplerate, 1);
+ filter_lowpass_init(&sdr->chan[c].rx_lp[1], bandwidth, samplerate, 1);
}
if (sdr->paging_channel) {
PDEBUG(DSDR, DEBUG_INFO, "Paging Frequency: TX = %.6f MHz\n", paging_frequency / 1e6);
@@ -378,8 +378,8 @@ int sdr_read(void *inst, int16_t **samples, int num, int channels)
Q[s] = i * sin(phase) + q * cos(phase);
}
sdr->chan[c].rx_phase = phase;
- filter_lowpass_process(&sdr->chan[c].rx_lp[0], I, count, 1);
- filter_lowpass_process(&sdr->chan[c].rx_lp[1], Q, count, 1);
+ filter_process(&sdr->chan[c].rx_lp[0], I, count);
+ filter_process(&sdr->chan[c].rx_lp[1], Q, count);
last_phase = sdr->chan[c].rx_last_phase;
for (s = 0; s < count; s++) {
phase = atan2(Q[s], I[s]);