Filter improvement: LP and HP filters, added test function
The -3 dB level at cut-off frequency is now maintained for multiple iterations.
This commit is contained in:
@@ -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;
|
||||
|
@@ -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 */
|
||||
|
@@ -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++) {
|
||||
|
@@ -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;
|
||||
|
@@ -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]);
|
||||
|
Reference in New Issue
Block a user