Finite Impulse Response (FIR) Design using Windowed `sinc` ========================================================== The ideal low-pass filter has a rectangular response in the frequency domain and an infinite :math:`\sin(t)/t` response in the time domain. Because all time-dependent filters must be causal, this type of filter is unrealizable; furthermore, truncating its response results in poor pass-band ripple stop-band rejection. An improvement over truncation is offered by use of a band-limiting window. Operation ~~~~~~~~~ Let the finite impulse response of a filter be defined as .. math:: :label: eqn-filter-firdes-windowed_sinc h(n) = h_i(n) w(n) where :math:`w(n)` is a time-limited symmetric window and :math:`h_i(n)` is the impulse response of the ideal filter with a cutoff frequency :math:`\omega_c`, viz. .. math:: :label: eqn-filter-firdes-sinc h_i(n) = \frac{\omega_c}{\pi} \left( \frac{\sin\omega_c n}{\omega_c n} \right), \,\,\,\, \forall n A number of possible windows could be used; the Kaiser window is particularly common due to its systematic ability to trade transition bandwidth for stop-band rejection. The Kaiser window is defined as .. math:: :label: eqn-filter-firdes-kaiser_window w(n) = \frac{ I_0\left[\pi\alpha\sqrt{1-\left(\frac{n}{N/2}\right)^2}\right] }{ I_0\left(\pi\alpha\right) } \,\,\,\, -N/2 \leq n \leq N/2, \,\, \alpha \geq 0 where :math:`I_\nu(z)` is the modified Bessel function of the first kind of order :math:`\nu` and :math:`\alpha` is a shape parameter controlling the window decay. :math:`I_\nu(z)` can be expanded as .. math:: :label: eqn-filter-firdes-besseli_infinite_sum I_\nu(z) = \left( \frac{z}{2} \right)^\nu \sum_{k=0}^{\infty}{ \frac{ \left(\frac{1}{4}z^2\right)^k }{ k!\Gamma(k+\nu+1) } } The sum in [eqn-filter-firdes-besseli_infinite_sum] converges quickly due to the denominator increasing rapidly, (and in particular for :math:`\nu=0` the denominator reduces to :math:`(k!)^2`) and thus only a few terms are necessary for sufficient approximation. The sum [eqn-filter-firdes-besseli_infinite_sum] converges quickly due to the denominator increasing rapidly, thus only a few terms are necessary for sufficient approximation. For more approximations to :math:`I_0(z)` and :math:`I_\nu(z)`, see [section-math] in the math module. Kaiser gives an approximation for the value of :math:`\alpha` to give a particular sidelobe level for the window as {cite:Vaidyanathan:1993((3.2.7))} .. math:: :label: eq-kaiser_alpha \alpha = \begin{cases} 0.1102 (A_s - 8.7) & A_s \gt 50 \\ 0.5842 (A_s - 21)^{0.4} & 21 \lt A_s \le 50 \\ 0 & \text{else} \end{cases} where :math:`A_s \gt 0` is the stop-band attenuation in decibels. This approximation is provided in liquid by the `kaiser_beta_As()` method, and the length of the filter can be approximated with `estimate_req_filter_len()` (see [section-filter-misc] for more detail on these methods). .. qplot:: series firdes/window_sinc.c :kwargs: { "figsize":[12,12], "format": { "xlabel" : "Time [samples]", "ylabel" : "Signal" }, "plots": [ {"series":["t","sinc",{"color":"#aaa","label":"sinc"}]}, {"series":["t","w",{"color":"#004080","label":"Kaiser window"}]}, {"series":["t","h",{"color":"#008040","label":"composite"}]} ] } :width: 75% :name: fig-firdes-window-sinc :caption: Windowed ``sinc`` filter design Interface ~~~~~~~~~ The entire design process is provided in liquid with the :api:`firdes_kaiser_window()` method which can be invoked as follows: .. code-block:: c int liquid_firdes_kaiser(unsigned int _n, float _fc, float _as, float _mu, float *_h); where :c:`_n` is the length of the filter (number of samples), :c:`_fc` is the normalized cutoff frequency (:math:`0 \leq f_c \leq 0.5`), :c:`_As` is the stop-band attenuation in dB (:math:`A_s \gt 0`), :c:`_mu` is the fractional sample offset (:math:`-0.5 \leq \mu \leq 0.5`), and :c:`*_h` is the :math:`n`-sample output coefficient array. Example ~~~~~~~ Listed below is an example of the `firdes_kaiser_window` interface. .. literalinclude:: liquid_firdes_kaiser.c :language: c .. qplot:: window firdes/liquid_firdes_kaiser.c :width: 80% :kwargs: {"figsize":[12,12], "layout":"columns", "onesided":false, "ylim":[-90,10]} :name: fig-firdes-kaiser :caption: Example of :api:`liquid_firdes_kaiser` An example of a low-pass filter design using the Kaiser window can be found in [fig-filter-firdes_kaiser].