'z' as in 'Zorro': Frequency Masking FIR
An efficient way to implement FIR filters. Matlab / Octave example included.
Keywords: Frequency masking FIR filter implementation
An "upsampled" FIR filter uses multiple-sample delays between the taps, compared to the unity delays in a conventional FIR filter. The resulting frequency response has steeper edges, but contains periodic images along the frequency axis (Fig. 1).
Due to the latter, it is typically not too useful on its own.
Figure 1: Conventional and 'upsampled' FIR
The so-called "interpolated" FIR, or "IFIR"  adds a second stage to remove unwanted frequency response images. For an example, see  Fig. 6 and 7, also  Fig. 2.
As one period of the upsampled FIR defines the width of the passband, this idea won't work for wideband filters.
Frequency Masking FIR filter
The "frequency masking FIR filter"  circumvents said problem and can achieve a steep transition at the edge of a wide bandwidth.
A complementary filter is constructed from the upsampled filter by subtracting its output from a unity impulse response with the same group delay (conveniently derived from the same tapped delay line at no extra cost).
Where the upsampled filter has a passband, the complementary filter shows a stopband, and vice versa.
Either filter output is highly frequency selective relative to the other, but no information is lost as a whole.
Figure 2: Upsampled and complementary FIR
Next, independent FIR filters g1 and g2 are added to the outputs, and the results are summed (Figure 3). This is the basic topology of the "frequency-masking FIR filter":
Figure 3: Frequency Masking FIR filter
So far so good. Assuming that it worked (which seemed a bit dubious, at least to me), how on earth would I design such a thing?
A systematic approach that seems to be best suited for very long filters can be found in  and .
After studying it for an hour, I remembered the old chinese proverb: If fminunc() doesn't know the answer, you're asking the wrong questions.
Alright, I just made this up, but the "general purpose heavy-duty" solver does find a good answer after a minute-and-a-half (freeware OctaveForge; Matlab is about four times faster).
Note that this gives a least-squares solution, whereas the original design in  is minimax-constrained. If the latter is needed, use of IRLS techniques to adjust the weights should be straightforward.
Slowly ramping up the order of the norm in the objective function during iteration is another method that has been successfully used to "nudge" a LS-design slightly towards minimax with little effort.
The following plots are generated by the attached Matlab program. They show the frequency responses of individual stages (Fig. 4) and the input-output frequency response (Fig. 5).
It is interesting to note that the roles of the invividual stages in the least-squares-type solution only loosely resemble the "systematic" design approach in  and !
Figure 4: Frequency response (individual stages)
Figure 5: Frequency response (input-output): The complete wide-band filter
For comparison, the design script includes a conventional symmetric FIR filter as reference design.
It needs 401 non-zero taps, whereas the frequency masking FIR uses 45 + 33 + 41 = 119 taps.
Less than 1/3 of the computational load, not too bad, IMHO.
 reached a similar conclusion in section VII, giving 383 taps for a conventional FIR filter that meets the same specs. Note, "my" numbers show orders-of-magnitude only and aren't optimized carefully.
The design program can be downloaded here . It uses a generic solver with the difference between nominal and actual frequency response in the objective function.
From a practical perspective, the main difficulty is to juggle parameters and optimizer variables, making sure each coefficient ends up in the right slot of a filter's impulse response.
The oh_xyz "optimization helper" functions collect all optimization parameters from a struct into a single flat vector for the optimizer, and write the result back into the struct, which is then used to evaluate the frequency response.
Each filter's impulse response is constructed from a coefficient map as described in .
The purpose of all the "bureaucracy" is that changing the length ("delay") of each filter requires only a single modification to the code.
If one looks past all the (necessary) clutter, the program is maybe as straightforward as filter design ever gets:
- prepare the nominal frequency response and weights
- prepare the design frequency response
- prepare the objective function as weighted difference between above
- run the optimizer on the objective function
This article reviews the "frequency-masking FIR" concept from  and provides a "fire-and-forget" design program to explore the design space of filter sizes and oversampling factor.
The program can be downloaded here .
It was developed on OctaveForge, and works on Matlab too (with toolboxes).
Previous post by Markus Nentwig:
FIR sideways (interpolator polyphase decomposition)
Next post by Markus Nentwig: