Finite Impulse Response Hilbert Transform (firhilb
)¶
The firhilbf
object in liquid implements a finite impulse
response Hilbert transform which
converts between real and complex time series.
The interpolator takes a complex time series and produces real-valued
samples at twice the sample rate.
The decimator reverses the process by halving the sample rate of a
real-valued time series to a complex-valued one.
Typical trade-offs between filter length, side-lobe suppression, and
transition bandwidth apply.
The firhilbf
object uses a half-band filter to implement the
transform as efficiently as possible.
While any filter length can be accepted, the firhilbf
object
internally forces the length to be of the form \(n=4m+1\)
to reduce the computational load.
A half-band filter of this length has \(2m\) zeros and \(2m+1\) non-zero
coefficients.
Of these non-zero coefficients, the center is exactly \(1\) while the other \(2m\)
are even symmetric, and therefore only \(m\) computations are needed.

Figure 3 firhilbf
(Hilbert transform) decimator demonstration.
The small signal at \(f=0.13\) is due to aliasing as a result of
imperfect image rejection.¶
A graphical example of the Hilbert decimator can be seen in
[fig-filter-firhilb]
where a real-valued input sinusoid is converted into a complex sinusoid
with half the number of samples.
An example code listing is given below.
Although firhilbf
is a placeholder for both
decimation (real to complex) and
interpolation (complex to real),
separate objects should be used for each task.
#include <liquid/liquid.h>
int main() {
unsigned int m=5; // filter semi-length
float slsl=60.0f; // filter sidelobe suppression level
// create Hilbert transform objects
firhilbf q0 = firhilbf_create(m,slsl);
firhilbf q1 = firhilbf_create(m,slsl);
float complex x; // interpolator input
float y[2]; // interpolator output
float complex z; // decimator output
// ...
// execute transforms
firhilbf_interp_execute(q0, x, y); // interpolator
firhilbf_decim_execute(q1, y, &z); // decimator
// clean up allocated memory
firhilbf_destroy(q0);
firhilbf_destroy(q1);
}
For more detailed examples on Hilbert transforms in liquid, refer to the files examples/firhilb_decim_example.c and examples/firhilb_interp_example.c located within the main liquid project directory. _See also:_ resamp2 ([section-filter-resamp2]), FIR filter design ([section-filter-firdes]).
Interface¶
Listed below is the full interface to the firhilb
family of
objects.
create()
¶
Create a firhilb object with a particular filter semi-length and desired stop-band attenuation. Internally the object designs a half-band filter based on applying a Kaiser-Bessel window to a sinc function to guarantee zeros at all off-center odd indexed samples.
firhilbf = firhilbf_create(unsigned int _m, float _as);
unsigned int _m
: filter semi-length, delay is ( 2 m + 1 )float _as
: filter stop-band attenuationreturns new
firhilbf
object
copy()
¶
Copy object including all internal objects and state
firhilbf = firhilbf_copy(firhilbf _q);
firhilbf _q
:returns new
firhilbf
object
destroy()
¶
Destroy finite impulse response Hilbert transform, freeing all internally-allocted memory and objects.
int = firhilbf_destroy(firhilbf _q);
firhilbf _q
:returns standard error code
print()
¶
Print firhilb object internals to stdout
int = firhilbf_print(firhilbf _q);
firhilbf _q
:returns standard error code
reset()
¶
Reset firhilb object internal state
int = firhilbf_reset(firhilbf _q);
firhilbf _q
:returns standard error code
r2c_execute()
¶
Execute Hilbert transform (real to complex)
int = firhilbf_r2c_execute(firhilbf _q, float _x, float complex * _y);
firhilbf _q
: Hilbert transform objectfloat _x
: real-valued input samplefloat complex * _y
: complex-valued output samplereturns standard error code
c2r_execute()
¶
Execute Hilbert transform (complex to real)
int = firhilbf_c2r_execute(firhilbf _q, float complex _x, float * _y0, float * _y1);
firhilbf _q
: Hilbert transform objectfloat complex _x
: complex-valued input samplefloat * _y0
: real-valued output sample, lower side-band retainedfloat * _y1
: real-valued output sample, upper side-band retainedreturns standard error code
decim_execute()
¶
Execute Hilbert transform decimator (real to complex)
int = firhilbf_decim_execute(firhilbf _q, float * _x, float complex * _y);
firhilbf _q
: Hilbert transform objectfloat * _x
: real-valued input arrayfloat complex * _y
: complex-valued output samplereturns standard error code
decim_execute_block()
¶
Execute Hilbert transform decimator (real to complex) on a block of samples
int = firhilbf_decim_execute_block(firhilbf _q, float * _x, unsigned int _n, float complex * _y);
firhilbf _q
: Hilbert transform objectfloat * _x
: real-valued input arrayunsigned int _n
: number of output samplesfloat complex * _y
: complex-valued output arrayreturns standard error code
interp_execute()
¶
Execute Hilbert transform interpolator (real to complex)
int = firhilbf_interp_execute(firhilbf _q, float complex _x, float * _y);
firhilbf _q
: Hilbert transform objectfloat complex _x
: complex-valued input samplefloat * _y
: real-valued output arrayreturns standard error code
interp_execute_block()
¶
Execute Hilbert transform interpolator (complex to real) on a block of samples
int = firhilbf_interp_execute_block(firhilbf _q, float complex * _x, unsigned int _n, float * _y);
firhilbf _q
: Hilbert transform objectfloat complex * _x
: complex-valued input arrayunsigned int _n
: number of input samplesfloat * _y
: real-valued output arrayreturns standard error code