Finite Impulse Response Hilbert Transform (firhilb)
API Keywords: firhilb Hilbert transform real to complex complex to real
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 [fig-filter-firhilb]. 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[ref: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);
}
Listed below is the full interface to the firhilbf family of objects.
- firhilbf_create(m,As) creates a firhilbf object with a filter semi-length of \(m\) samples (equal to the delay) and a stop-band attenuation of \(A_s\) dB. The value of \(m\) must be at least 2. The internal filter has a length \(4m+1\) coefficients and is designed using the firdes_kaiser_window() method (see [ref:section-filter-firdes-window] on FIR filter design using windowing functions).
- firhilbf_destroy(q) destroys the Hilbert transform object, freeing all internally-allocated memory.
- firhilbf_print(q) prints the internal properties of the object to the standard output.
- firhilbf_clear(q) clears the internal transform buffers.
- firhilbf_r2c_execute(q,x,*y) executes the real-to-complex transform as a half-band filter, rejecting the negative frequency band. The input \(x\) is a real sample; the output \(y\) is complex.
- firhilbf_c2r_execute(q,x,*y) executes the complex-to-real conversion as \(y = \Re\{x\}\) .
- firhilbf_decim_execute(q,*x,*y) executes the transform as a decimator, converting a 2-sample input array \(\vec{x}\) of real values into a single complex output value\(y\) .
- firhilbf_interp_execute(q,x,*y) executes the transform as a decimator, converting a single complex input sample \(x\) into a two real-valued samples stored in the output array \(\vec{y}\) .
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 ([ref:section-filter-resamp2] ), FIR filter design ([ref:section-filter-firdes] ).