Skip to content

Commit

Permalink
Merge branch 'master' into bind-dev
Browse files Browse the repository at this point in the history
  • Loading branch information
jgaeddert committed Mar 8, 2024
2 parents 7a7c643 + ff5b1b6 commit c59e176
Show file tree
Hide file tree
Showing 22 changed files with 759 additions and 321 deletions.
15 changes: 15 additions & 0 deletions autotest/autotest.c
Original file line number Diff line number Diff line change
Expand Up @@ -347,3 +347,18 @@ int liquid_autotest_validate_psd_firfilt_cccf(firfilt_cccf _q, unsigned int _nff
return liquid_autotest_validate_spectrum(psd,_nfft,_regions,num_regions,debug_filename);
}

// validate spectral content of an iir filter (real coefficients, input)
int liquid_autotest_validate_psd_iirfilt_rrrf(iirfilt_rrrf _q, unsigned int _nfft,
autotest_psd_s * _regions, unsigned int num_regions, const char * debug_filename)
{
float psd[_nfft];
unsigned int i;
for (i=0; i<_nfft; i++) {
float f = (float)(i)/(float)(_nfft) - 0.5f;
float complex H;
iirfilt_rrrf_freqresponse(_q, f, &H);
psd[i] = 20*log10f(cabsf(H));
}
return liquid_autotest_validate_spectrum(psd,_nfft,_regions,num_regions,debug_filename);
}

4 changes: 4 additions & 0 deletions autotest/autotest.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,5 +312,9 @@ int liquid_autotest_validate_psd_firfilt_crcf(firfilt_crcf _q, unsigned int _nff
int liquid_autotest_validate_psd_firfilt_cccf(firfilt_cccf _q, unsigned int _nfft,
autotest_psd_s * _regions, unsigned int num_regions, const char * debug_filename);

// validate spectral content of an iir filter (real coefficients, input)
int liquid_autotest_validate_psd_iirfilt_rrrf(iirfilt_rrrf _q, unsigned int _nfft,
autotest_psd_s * _regions, unsigned int num_regions, const char * debug_filename);

#endif // __LIQUID_AUTOTEST_H__

72 changes: 72 additions & 0 deletions examples/iirfilt_rrrf_integrator_example.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,72 @@
// This example demonstrates how to create an integrating recursive
// (infinite impulse response) filter.
#include <stdio.h>
#include <math.h>

#include "liquid.h"

#define OUTPUT_FILENAME "iirfilt_rrrf_integrator_example.m"

int main() {
// options
unsigned int num_samples = 1200; // number of samples

// allocate memory for data arrays
float buf_0[num_samples]; // filter input
float buf_1[num_samples]; // filter output

// generate input signal
unsigned int i;
for (i=0; i<num_samples; i++)
buf_0[i] = (i > 200 && i < 800 ? 1 : 0) + 0.1*randnf();

// design filter from prototype
iirfilt_rrrf q = iirfilt_rrrf_create_integrator();
iirfilt_rrrf_print(q);

// run filter
iirfilt_rrrf_execute_block(q, buf_0, num_samples, buf_1);

// destroy filter object
iirfilt_rrrf_destroy(q);

// plot results to output file
FILE * fid = fopen(OUTPUT_FILENAME,"w");
fprintf(fid,"%% %s : auto-generated file\n", OUTPUT_FILENAME);
fprintf(fid,"clear all;\n");
fprintf(fid,"close all;\n");
fprintf(fid,"\n");
fprintf(fid,"num_samples=%u;\n",num_samples);
fprintf(fid,"x=zeros(1,num_samples);\n");
fprintf(fid,"y=zeros(1,num_samples);\n");

// save input, output arrays
for (i=0; i<num_samples; i++) {
fprintf(fid,"x(%4u) = %12.4e;\n", i+1, buf_0[i]);
fprintf(fid,"y(%4u) = %12.4e;\n", i+1, buf_1[i]);
}

// plot output
fprintf(fid,"t=0:(num_samples-1);\n");
fprintf(fid,"figure;\n");
fprintf(fid,"subplot(2,1,1);\n");
fprintf(fid," plot(t,x,'-','Color',[0 0.2 0.5],'LineWidth',2);\n");
fprintf(fid," xlabel('time');\n");
fprintf(fid," ylabel('original input');\n");
fprintf(fid," axis([0 num_samples -1 2]);\n");
fprintf(fid," grid on;\n");
fprintf(fid,"subplot(2,1,2);\n");
fprintf(fid," plot(t,y,'-','Color',[0 0.5 0.2],'LineWidth',2);\n");
fprintf(fid," xlabel('time');\n");
fprintf(fid," ylabel('input with DC offset');\n");
fprintf(fid," axis([0 num_samples -3 650]);\n");
fprintf(fid," grid on;\n");

// close output file
fclose(fid);
printf("results written to '%s'\n", OUTPUT_FILENAME);

printf("done.\n");
return 0;
}

11 changes: 1 addition & 10 deletions examples/iirinterp_crcf_example.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
//
// iirinterp_crcf_example.c
//
// This example demonstrates the iirinterp object (IIR interpolator)
// interface.
//

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
Expand All @@ -23,7 +18,6 @@ void usage()
printf(" n : number of input samples, default: 64\n");
}


int main(int argc, char*argv[]) {
// options
unsigned int k = 4; // interpolation factor
Expand Down Expand Up @@ -75,10 +69,7 @@ int main(int argc, char*argv[]) {
// destroy interpolator object
iirinterp_crcf_destroy(q);


//
// export output file
//
FILE * fid = fopen(OUTPUT_FILENAME,"w");
fprintf(fid,"%% %s: auto-generated file\n\n", OUTPUT_FILENAME);
fprintf(fid,"clear all;\n");
Expand All @@ -93,7 +84,7 @@ int main(int argc, char*argv[]) {
fprintf(fid,"x(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(x[i]), cimagf(x[i]));

for (i=0; i<k*num_samples; i++)
fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, k*crealf(y[i]), k*cimagf(y[i]));
fprintf(fid,"y(%4u) = %12.4e + j*%12.4e;\n", i+1, crealf(y[i]), cimagf(y[i]));

fprintf(fid,"\n\n");
fprintf(fid,"tx = [0:( num_samples-1)];\n");
Expand Down
84 changes: 41 additions & 43 deletions examples/rresamp_crcf_example.c
Original file line number Diff line number Diff line change
@@ -1,10 +1,5 @@
//
// rresamp_crcf_example.c
//
// Demonstration of rresamp object whereby an input signal
// is resampled at a rational rate Q/P.
//

// is resampled at a rational rate P/Q = interp/decim.
#include <stdio.h>
#include <stdlib.h>
#include <complex.h>
Expand All @@ -19,62 +14,65 @@
void usage()
{
printf("Usage: %s [OPTION]\n", __FILE__);
printf("Resample a signal at a rate P/Q\n");
printf("Resample a signal at a rate interp/decim\n");
printf(" -h : print help\n");
printf(" -P <decim> : decimation (output) rate, default: 3\n");
printf(" -Q <interp> : interpolation (input) rate, default: 5\n");
printf(" -P <interp> : interpolation rate, default: 5\n");
printf(" -Q <decim> : decimation rate, default: 3\n");
printf(" -m <len> : filter semi-length (delay), default: 12\n");
printf(" -w <bandwidth>: filter bandwidth, default: 0.5f\n");
printf(" -w <bandwidth>: filter bandwidth, default: -1\n");
printf(" -s <atten> : filter stop-band attenuation [dB], default: 60\n");
}

int main(int argc, char*argv[])
{
// options
unsigned int P = 3; // output rate (interpolation factor)
unsigned int Q = 5; // input rate (decimation factor)
unsigned int m = 12; // resampling filter semi-length (filter delay)
float bw = 0.5f; // resampling filter bandwidth
float As = 60.0f; // resampling filter stop-band attenuation [dB]
unsigned int interp = 3; // output rate (interpolation factor)
unsigned int decim = 5; // input rate (decimation factor)
unsigned int m = 20; // resampling filter semi-length (filter delay)
float bw = -1.0f; // resampling filter bandwidth
float As = 60.0f; // resampling filter stop-band attenuation [dB]

int dopt;
while ((dopt = getopt(argc,argv,"hP:Q:m:s:w:")) != EOF) {
switch (dopt) {
case 'h': usage(); return 0;
case 'P': P = atoi(optarg); break;
case 'Q': Q = atoi(optarg); break;
case 'm': m = atoi(optarg); break;
case 'w': bw = atof(optarg); break;
case 's': As = atof(optarg); break;
case 'h': usage(); return 0;
case 'P': interp = atoi(optarg); break;
case 'Q': decim = atoi(optarg); break;
case 'm': m = atoi(optarg); break;
case 'w': bw = atof(optarg); break;
case 's': As = atof(optarg); break;
default:
exit(1);
}
}

// validate input
if (P == 0 || P > 1000) {
fprintf(stderr,"error: %s, input rate P must be in [1,1000]\n", argv[0]);
if (interp == 0 || interp > 1000) {
fprintf(stderr,"error: %s, interpolation rate must be in [1,1000]\n", argv[0]);
exit(1);
} else if (Q == 0 || Q > 1000) {
fprintf(stderr,"error: %s, output rate Q must be in [1,1000]\n", argv[0]);
} else if (decim == 0 || decim > 1000) {
fprintf(stderr,"error: %s, decimation rate must be in [1,1000]\n", argv[0]);
exit(1);
}

// create resampler object
rresamp_crcf q = rresamp_crcf_create_kaiser(P,Q,m,bw,As);
rresamp_crcf q = rresamp_crcf_create_kaiser(interp,decim,m,bw,As);
if (q == NULL) return -1;
rresamp_crcf_print(q);
float rate = rresamp_crcf_get_rate(q);

// number of sample blocks (limit by large interp/decim rates)
unsigned int n = 120e3 / (P > Q ? P : Q);
unsigned int n = 120e3 / (interp > decim ? interp : decim);

// input/output buffers
float complex buf_x[Q]; // input
float complex buf_y[P]; // output
float complex buf_x[decim ]; // input
float complex buf_y[interp]; // output

// create signal generator (wide-band noise)
// create signal generator (wide-band noise and tone)
float noise_bw = 0.7f * (rate > 1.0 ? 1.0 : rate);
msourcecf gen = msourcecf_create_default();
msourcecf_add_noise(gen, 0.0f, 0.7f * (rate > 1.0 ? 1.0 : rate), 0);
msourcecf_add_noise(gen, 0.0f, noise_bw, 0);
msourcecf_add_tone (gen, rate > 1.0 ? 0.4 : noise_bw, 0.00f, 20);

// create spectral periodogram objects
unsigned int nfft = 2400;
Expand All @@ -84,15 +82,15 @@ int main(int argc, char*argv[])
// generate input signal (filtered noise)
unsigned int i;
for (i=0; i<n; i++) {
// write Q input samples to buffer
msourcecf_write_samples(gen, buf_x, Q);
// write decim input samples to buffer
msourcecf_write_samples(gen, buf_x, decim);

// run resampler and write P output samples
// run resampler and write interp output samples
rresamp_crcf_execute(q, buf_x, buf_y);

// write input and output to respective spectral periodogram estimate
spgramcf_write(px, buf_x, Q);
spgramcf_write(py, buf_y, P);
spgramcf_write(px, buf_x, decim);
spgramcf_write(py, buf_y, interp);
}
printf("num samples out : %llu\n", spgramcf_get_num_samples_total(py));
printf("num samples in : %llu\n", spgramcf_get_num_samples_total(px));
Expand All @@ -111,12 +109,12 @@ int main(int argc, char*argv[])
fprintf(fid,"%% %s: auto-generated file\n",OUTPUT_FILENAME);
fprintf(fid,"clear all;\n");
fprintf(fid,"close all;\n");
fprintf(fid,"P = %u;\n", P);
fprintf(fid,"Q = %u;\n", Q);
fprintf(fid,"r = P/Q;\n");
fprintf(fid,"nfft = %u;\n", nfft);
fprintf(fid,"X = zeros(1,nfft);\n");
fprintf(fid,"Y = zeros(1,nfft);\n");
fprintf(fid,"interp = %u;\n", interp);
fprintf(fid,"decim = %u;\n", decim);
fprintf(fid,"r = interp/decim;\n");
fprintf(fid,"nfft = %u;\n", nfft);
fprintf(fid,"X = zeros(1,nfft);\n");
fprintf(fid,"Y = zeros(1,nfft);\n");
for (i=0; i<nfft; i++) {
fprintf(fid,"X(%3u) = %12.4e;\n", i+1, X[i]);
fprintf(fid,"Y(%3u) = %12.4e;\n", i+1, Y[i]);
Expand All @@ -128,7 +126,7 @@ int main(int argc, char*argv[])
fprintf(fid,"figure('Color','white','position',[500 500 800 600]);\n");
fprintf(fid,"plot(fx,X,'-','LineWidth',2,'Color',[0.5 0.5 0.5],'MarkerSize',1,...\n");
fprintf(fid," fy,Y,'-','LineWidth',2,'Color',[0.5 0 0], 'MarkerSize',1);\n");
fprintf(fid,"legend('original','resampled','location','northeast');");
fprintf(fid,"legend('original','resampled','location','northwest');");
fprintf(fid,"xlabel('Normalized Frequency [f/F_s]');\n");
fprintf(fid,"ylabel('Power Spectral Density [dB]');\n");
fprintf(fid,"fmin = min(fx( 1),fy( 1));\n");
Expand Down
25 changes: 23 additions & 2 deletions include/liquid.h
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright (c) 2007 - 2023 Joseph Gaeddert
* Copyright (c) 2007 - 2024 Joseph Gaeddert
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
Expand Down Expand Up @@ -3437,6 +3437,16 @@ int IIRFILT(_print)(IIRFILT() _q); \
/* Reset iirfilt object internals */ \
int IIRFILT(_reset)(IIRFILT() _q); \
\
/* Set output scaling for filter */ \
/* _q : filter object */ \
/* _scale : scaling factor to apply to each output sample */ \
int IIRFILT(_set_scale)(IIRFILT() _q, TC _scale); \
\
/* Get output scaling for filter */ \
/* _q : filter object */ \
/* _scale : scaling factor applied to each output sample */ \
int IIRFILT(_get_scale)(IIRFILT() _q, TC * _scale); \
\
/* Compute filter output given a single input sample */ \
/* _q : iirfilt object */ \
/* _x : input sample */ \
Expand Down Expand Up @@ -4367,7 +4377,9 @@ RRESAMP() RRESAMP(_create)(unsigned int _interp, \
/* the resampler is configured as an interpolator a value of */ \
/* 0.5 (critically filtered) or less is recommended. */ \
/* When the resampler is configured as a decimator, the */ \
/* critical sampling rate is 0.5*_interp/_decim, */ \
/* critical bandwidth is 0.5*_interp/_decim. */ \
/* When _bw < 0, the object will use the appropriate */ \
/* critical bandwidth (interpolation or decimation), */ \
/* 0 < _bw <= 0.5 */ \
/* _as : filter stop-band attenuation [dB], 0 < _as */ \
RRESAMP() RRESAMP(_create_kaiser)(unsigned int _interp, \
Expand All @@ -4381,6 +4393,11 @@ RRESAMP() RRESAMP(_create_kaiser)(unsigned int _interp, \
/* Note that because the filter coefficients are computed internally */ \
/* here, the greatest common divisor (gcd) from _interp and _decim is */ \
/* internally removed to improve speed. */ \
/* _type : filter type (e.g. LIQUID_FIRFILT_RCOS) */ \
/* _interp : interpolation factor, _interp > 0 */ \
/* _decim : decimation factor, _decim > 0 */ \
/* _m : filter semi-length (delay), 0 < _m */ \
/* _beta : excess bandwidth factor, 0 <= _beta <= 1 */ \
RRESAMP() RRESAMP(_create_prototype)(int _type, \
unsigned int _interp, \
unsigned int _decim, \
Expand Down Expand Up @@ -4945,6 +4962,10 @@ int SYMSYNC(_lock)(SYMSYNC() _q); \
/* Unlock the symbol synchronizer's loop control */ \
int SYMSYNC(_unlock)(SYMSYNC() _q); \
\
/* Check the lock state of the symbol synchronizer's loop control, */ \
/* returning 1 if the object is locked, 0 if unlocked. */ \
int SYMSYNC(_is_locked)(SYMSYNC() _q); \
\
/* Set synchronizer output rate (samples/symbol) */ \
/* _q : synchronizer object */ \
/* _k_out : output samples/symbol, _k_out > 0 */ \
Expand Down
3 changes: 2 additions & 1 deletion makefile.in
Original file line number Diff line number Diff line change
Expand Up @@ -524,8 +524,8 @@ filter_autotests := \
src/filter/tests/iirdecim_autotest.c \
src/filter/tests/iirdes_autotest.c \
src/filter/tests/iirdes_support_autotest.c \
src/filter/tests/iirfilt_autotest.c \
src/filter/tests/iirfilt_xxxf_autotest.c \
src/filter/tests/iirfilt_copy_autotest.c \
src/filter/tests/iirfiltsos_autotest.c \
src/filter/tests/iirhilb_autotest.c \
src/filter/tests/iirinterp_autotest.c \
Expand Down Expand Up @@ -1701,6 +1701,7 @@ example_programs := \
examples/iirfilt_cccf_example \
examples/iirfilt_crcf_example \
examples/iirfilt_crcf_dcblocker_example \
examples/iirfilt_rrrf_integrator_example \
examples/iirhilb_example \
examples/iirhilb_filter_example \
examples/iirinterp_crcf_example \
Expand Down
Loading

0 comments on commit c59e176

Please sign in to comment.