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
firhilbfobject
copy()¶
Copy object including all internal objects and state
firhilbf = firhilbf_copy(firhilbf _q);
firhilbf _q:returns new
firhilbfobject
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