Chapter 17Custom Filters |
307 |
break the signal into a large number of segments, take the DFT of each segment, convert into polar form, and then average the magnitudes together. In the simplest case, the unknown frequency response is taken as the average spectrum of the old recording, divided by the average spectrum of the modern recording. (The method used by Stockham et al. is based on a more sophisticated technique called homomorphic processing, providing a better estimate of the characteristics of the recording system).
Optimal Filters
Figure 17-7a illustrates a common filtering problem: trying to extract a waveform (in this example, an exponential pulse) buried in random noise. As shown in (b), this problem is no easier in the frequency domain. The signal has a spectrum composed mainly of low frequency components. In comparison, the spectrum of the noise is white (the same amplitude at all frequencies). Since the spectra of the signal and noise overlap, it is not clear how the two can best be separated. In fact, the real question is how to define what "best" means. We will look at three filters, each of which is "best" (optimal) in a different way. Figure 17-8 shows the filter kernel and frequency response for each of these filters. Figure 17-9 shows the result of using these filters on the example waveform of Fig. 17-7a.
The moving average filter is the topic of Chapter 15. As you recall, each output point produced by the moving average filter is the average of a certain number of points from the input signal. This makes the filter kernel a rectangular pulse with an amplitude equal to the reciprocal of the number of points in the average. The moving average filter is optimal in the sense that it provides the fastest step response for a given noise reduction.
The matched filter was previously discussed in Chapter 7. As shown in Fig. 17-8a, the filter kernel of the matched filter is the same as the target signal
1.5
a.Signal + noise (time domain)
1.0










































signal
0.5 |
|
|
|
|
|
|
|
|
|
|
noise |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-0.5 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0 |
100 |
200 |
300 |
400 |
500 |
Sample number
|
15 |
|
|
|
|
|
|
|
b. Signal + noise (frequency spectrum) |
|
Amplitude |
10 |
|
|
|
|
|
|
signal |
|
|
|
|
|
|
|
|
|
|
|
5 |
|
|
|
noise |
|
|
0 |
|
|
|
|
|
|
0 |
0.1 |
0.2 |
0.3 |
0.4 |
0.5 |
|
|
|
Frequency |
|
|
FIGURE 17-7
Example of optimal filtering. In (a), an exponential pulse buried in random noise. The frequency spectra of the pulse and noise are shown in (b). Since the signal and noise overlap in both the time and frequency domains, the best way to separate them isn't obvious.
308 |
The Scientist and Engineer's Guide to Digital Signal Processing |
0.25 |
|
1.5 |
|
a. Filter kernel |
|
|
b. Frequency response |
0.20 |
Wiener |
|
|
moving average |
|
1.0 |
moving average |
matched |
Amplitude |
|
0.10 |
|
0.15 |
|
|
|
|
|
|
Wiener |
|
|
0.5 |
matched |
0.05 |
|
|
|
0.00 |
|
|
|
|
|
0.0 |
|
|
|
|
|
0 |
10 |
20 |
30 |
40 |
50 |
0 |
0.1 |
0.2 |
0.3 |
0.4 |
0.5 |
FIGURE 17-8
Example of optimal filters. In (a), three filter kernels are shown, each of which is optimal in some sense. The corresponding frequency responses are shown in (b). The moving average filter is designed to have a rectangular pulse for a filter kernel. In comparison, the filter kernel of the matched filter looks like the signal being detected. The Wiener filter is designed in the frequency domain, based on the relative amounts of signal and noise present at each frequency.
being detected, except it has been flipped left-for-right. The idea behind the matched filter is correlation, and this flip is required to perform correlation using convolution. The amplitude of each point in the output signal is a measure of how well the filter kernel matches the corresponding section of the input signal. Recall that the output of a matched filter does not necessarily look like the signal being detected. This doesn't really matter; if a matched filter is used, the shape of the target signal must already be known. The matched filter is optimal in the sense that the top of the peak is farther above the noise than can be achieved with any other linear filter (see Fig. 17-9b).
The Wiener filter (named after the optimal estimation theory of Norbert Wiener) separates signals based on their frequency spectra. As shown in Fig. 17-7b, at some frequencies there is mostly signal, while at others there is mostly noise. It seems logical that the "mostly signal" frequencies should be passed through the filter, while the "mostly noise" frequencies should be blocked. The Wiener filter takes this idea a step further; the gain of the filter at each frequency is determined by the relative amount of signal and noise at that frequency:
EQUATION 17-1
The Wiener filter. The frequency response, represented by H [ f ] , is determined by the frequency spectra of the noise, N [ f ] , and the signal, S [ f ] . Only the magnitudes are important; all of the phases are zero.
S [ f ]2
H [ f ] '
S [ f ]2% N [ f ]2
This relation is used to convert the spectra in Fig. 17-7b into the Wiener filter's frequency response in Fig. 17-8b. The Wiener filter is optimal in the sense that it maximizes the ratio of the signal power to the noise power
Chapter 17Custom Filters |
309 |
|
1.5 |
|
|
|
|
|
|
|
a. Moving average filter |
|
|
Amplitude |
1.0 |
|
|
|
|
|
0.5 |
|
|
|
|
|
|
|
|
|
|
|
|
0.0 |
|
|
|
|
|
|
-0.5 |
|
|
|
|
|
|
0 |
100 |
200 |
300 |
400 |
500 |
Sample number
FIGURE 17-9
Example of using three optimal filters. These signals result from filtering the waveform in Fig. 17-7 with the filters in Fig. 17-8. Each of these three filters is optimal in some sense. In (a), the moving average filter results in the sharpest edge response for a given level of random noise reduction. In (b), the matched filter produces a peak that is farther above the residue noise than provided by any other filter. In (c), the Wiener filter optimizes the signal-to-noise ratio.
|
1.5 |
|
|
|
|
|
|
|
b. Matched filter |
|
|
|
|
1.0 |
|
|
|
|
|
Amplitude |
0.5 |
|
|
|
|
|
|
|
|
|
|
|
|
0.0 |
|
|
|
|
|
|
-0.5 |
|
|
|
|
|
|
0 |
100 |
200 |
300 |
400 |
500 |
Sample number
|
1.5 |
|
|
|
|
|
|
|
c. Wiener filter |
|
|
|
Amplitude |
1.0 |
|
|
|
|
|
0.5 |
|
|
|
|
|
|
|
|
|
|
|
|
0.0 |
|
|
|
|
|
|
-0.5 |
|
|
|
|
|
|
0 |
100 |
200 |
300 |
400 |
500 |
Sample number
(over the length of the signal, not at each individual point). An appropriate filter kernel is designed from the Wiener frequency response using the custom method.
While the ideas behind these optimal filters are mathematically elegant, they often fail in practicality. This isn't to say they should never be used. The point is, don't hear the word "optimal" and stop thinking. Let's look at several reasons why you might not want to use them.
First, the difference between the signals in Fig. 17-9 is very unimpressive. In fact, if you weren't told what parameters were being optimized, you probably couldn't tell by looking at the signals. This is usually the case for problems involving overlapping frequency spectra. The small amount of extra performance obtained from an optimal filter may not be worth the the increased program complexity, the extra design effort, or the longer execution time.
Second: The Wiener and matched filters are completely determined by the characteristics of the problem. Other filters, such as the windowed-sinc and moving average, can be tailored to your liking. Optimal filter advocates would claim that this diddling can only reduce the effectiveness of the filter. This is
310 |
The Scientist and Engineer's Guide to Digital Signal Processing |
very arguable. Remember, each of these filters is optimal in one specific way (i.e., "in some sense"). This is seldom sufficient to claim that the entire problem has been optimized, especially if the resulting signals are interpreted by a human observer. For instance, a biomedical engineer might use a Wiener filter to maximize the signal-to-noise ratio in an electro-cardiogram. However, it is not obvious that this also optimizes a physician's ability to detect irregular heart activity by looking at the signal.
Third: The Wiener and matched filter must be carried out by convolution, making them extremely slow to execute. Even with the speed improvements discussed in the next chapter (FFT convolution), the computation time can be excessively long. In comparison, recursive filters (such as the moving average or others presented in Chapter 19) are much faster, and may provide an acceptable level of performance.
CHAPTER
FFT Convolution
18
This chapter presents two important DSP techniques, the overlap-add method, and FFT convolution. The overlap-add method is used to break long signals into smaller segments for easier processing. FFT convolution uses the overlap-add method together with the Fast Fourier Transform, allowing signals to be convolved by multiplying their frequency spectra. For filter kernels longer than about 64 points, FFT convolution is faster than standard convolution, while producing exactly the same result.
The Overlap-Add Method
There are many DSP applications where a long signal must be filtered in segments. For instance, high fidelity digital audio requires a data rate of about 5 Mbytes/min, while digital video requires about 500 Mbytes/min. With data rates this high, it is common for computers to have insufficient memory to simultaneously hold the entire signal to be processed. There are also systems that process segment-by-segment because they operate in real time. For example, telephone signals cannot be delayed by more than a few hundred milliseconds, limiting the amount of data that are available for processing at any one instant. In still other applications, the processing may require that the signal be segmented. An example is FFT convolution, the main topic of this chapter.
The overlap-add method is based on the fundamental technique in DSP: (1) decompose the signal into simple components, (2) process each of the components in some useful way, and (3) recombine the processed components into the final signal. Figure 18-1 shows an example of how this is done for the overlap-add method. Figure (a) is the signal to be filtered, while (b) shows the filter kernel to be used, a windowed-sinc low-pass filter. Jumping to the bottom of the figure, (i) shows the filtered signal, a smoothed version of (a). The key to this method is how the lengths of these signals are affected by the convolution. When an N sample signal is convolved with an M sample
312 |
The Scientist and Engineer's Guide to Digital Signal Processing |
filter kernel, the output signal is N% M& 1 samples long. For instance, the input signal, (a), is 300 samples (running from 0 to 299), the filter kernel, (b), is 101 samples (running from 0 to 100), and the output signal, (i), is 400 samples (running from 0 to 399).
In other words, when an N sample signal is filtered, it will be expanded by M& 1 points to the right. (This is assuming that the filter kernel runs from index 0 to M. If negative indexes are used in the filter kernel, the expansion will also be to the left). In (a), zeros have been added to the signal between sample 300 and 399 to illustrate where this expansion will occur. Don't be confused by the small values at the ends of the output signal, (i). This is simply a result of the windowed-sinc filter kernel having small values near its ends. All 400 samples in (i) are nonzero, even though some of them are too small to be seen in the graph.
Figures (c), (d) and (e) show the decomposition used in the overlap-add method. The signal is broken into segments, with each segment having 100 samples from the original signal. In addition, 100 zeros are added to the right of each segment. In the next step, each segment is individually filtered by convolving it with the filter kernel. This produces the output segments shown in (f), (g), and (h). Since each input segment is 100 samples long, and the filter kernel is 101 samples long, each output segment will be 200 samples long. The important point to understand is that the 100 zeros were added to each input segment to allow for the expansion during the convolution.
Notice that the expansion results in the output segments overlapping each other. These overlapping output segments are added to give the output signal, (i). For instance, samples 200 to 299 in (i) are found by adding the corresponding samples in (g) and (h). The overlap-add method produces exactly the same output signal as direct convolution. The disadvantage is a much greater program complexity to keep track of the overlapping samples.
FFT Convolution
FFT convolution uses the principle that multiplication in the frequency domain corresponds to convolution in the time domain. The input signal is transformed into the frequency domain using the DFT, multiplied by the frequency response of the filter, and then transformed back into the time domain using the Inverse DFT. This basic technique was known since the days of Fourier; however, no one really cared. This is because the time required to calculate the DFT was longer than the time to directly calculate the convolution. This changed in 1965 with the development of the Fast Fourier Transform (FFT). By using the FFT algorithm to calculate the DFT, convolution via the frequency domain can be faster than directly convolving the time domain signals. The final result is the same; only the number of calculations has been changed by a more efficient algorithm. For this reason, FFT convolution is also called high-speed convolution.
314 |
The Scientist and Engineer's Guide to Digital Signal Processing |
FFT convolution uses the overlap-add method shown in Fig. 18-1; only the way that the input segments are converted into the output segments is changed. Figure 18-2 shows an example of how an input segment is converted into an output segment by FFT convolution. To start, the frequency response of the filter is found by taking the DFT of the filter kernel, using the FFT. For instance, (a) shows an example filter kernel, a windowed-sinc band-pass filter. The FFT converts this into the real and imaginary parts of the frequency response, shown in (b) & (c). These frequency domain signals may not look like a band-pass filter because they are in rectangular form. Remember, polar form is usually best for humans to understand the frequency domain, while rectangular form is normally best for mathematical calculations. These real and imaginary parts are stored in the computer for use when each segment is being calculated.
Figure (d) shows the input segment to being processed. The FFT is used to find its frequency spectrum, shown in (e) & (f). The frequency spectrum of the output segment, (h) & (i) is then found by multiplying the filter's frequency response, (b) & (c), by the spectrum of the input segment, (e) & (f). Since these spectra consist of real and imaginary parts, they are multiplied according to Eq. 9-1 in Chapter 9. The Inverse FFT is then used to find the output segment, (g), from its frequency spectrum, (h) & (i). It is important to recognize that this output segment is exactly the same as would be obtained by the direct convolution of the input segment, (d), and the filter kernel, (a).
The FFTs must be long enough that circular convolution does not take place (also described in Chapter 9). This means that the FFT should be the same length as the output segment, (g). For instance, in the example of Fig. 18-2, the filter kernel contains 129 points and each segment contains 128 points, making output segment 256 points long. This calls for 256 point FFTs to be used. This means that the filter kernel, (a), must be padded with 127 zeros to bring it to a total length of 256 points. Likewise, each of the input segments, (d), must be padded with 128 zeros. As another example, imagine you need to convolve a very long signal with a filter kernel having 600 samples. One alternative would be to use segments of 425 points, and 1024 point FFTs. Another alternative would be to use segments of 1449 points, and 2048 point FFTs.
Table 18-1 shows an example program to carry out FFT convolution. This program filters a 10 million point signal by convolving it with a 400 point filter kernel. This is done by breaking the input signal into 16000 segments, with each segment having 625 points. When each of these segments is convolved with the filter kernel, an output segment of 625 % 400 & 1 ' 1024 points is produced. Thus, 1024 point FFTs are used. After defining and initializing all the arrays (lines 130 to 230), the first step is to calculate and store the frequency response of the filter (lines 250 to 310). Line 260 calls a mythical subroutine that loads the filter kernel into XX[0] through XX[399], and sets XX[400] through XX[1023] to a value of zero. The subroutine in line 270 is the FFT, transforming the 1024 samples held in XX[ ] into the 513 samples held in REX[ ] & IMX[ ], the real and
|
Chapter 18FFT Convolution |
315 |
Time Domain |
Frequency Domain |
|
|
0.3 |
|
|
|
|
|
2.0 |
|
|
|
|
2.0 |
|
|
|
0.2 |
a. Filter kernel |
|
|
|
|
|
b. Real |
|
|
|
c. Imaginary |
|
|
|
|
|
|
|
1.0 |
|
|
|
|
1.0 |
|
|
Amplitude |
|
|
|
|
|
Amplitude |
|
|
|
Amplitude |
|
|
0.1 |
|
|
|
FFT |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0.0 |
|
|
|
|
0.0 |
|
|
|
0.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-0.1 |
|
signal in 0 to 128 |
|
|
-1.0 |
|
|
|
|
-1.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zeros in 129 to 255 |
|
|
|
|
|
|
|
|
|
|
|
-0.2 |
|
|
|
|
|
-2.0 |
|
|
|
|
-2.0 |
|
|
|
0 |
64 |
128 |
192 |
2565 |
|
|
0 |
64 |
128 |
|
0 |
64 |
128 |
|
|
Sample number |
|
|
|
|
|
Frequency |
|
|
|
Frequency |
|
|
6.0 |
|
|
|
|
|
100 |
|
|
|
|
100 |
|
|
|
4.0 |
d. Input segment |
|
|
|
|
|
e. Real |
|
|
|
f. Imaginary |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
50 |
|
|
|
|
50 |
|
|
Amplitude |
2.0 |
|
|
|
FFT |
Amplitude |
|
|
|
|
Amplitude |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0.0 |
|
|
|
|
|
0 |
|
|
|
|
0 |
|
|
|
-2.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-50 |
|
|
|
|
-50 |
|
|
-4.0 |
|
|
|
|
|
signal in 0 to 127 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
zeros in 128 to 255 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-6.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
-100 |
|
|
|
|
|
|
-100 |
|
|
|
|
|
|
0 |
64 |
128 |
192 |
2565 |
0 |
64 |
128 |
0 |
64 |
128 |
|
|
|
|
|
Sample number |
|
|
|
|
|
|
|
Frequency |
|
|
|
|
Frequency |
|
|
|
6.0 |
|
|
|
|
|
|
100 |
|
|
|
|
100 |
|
|
|
4.0 |
g. |
Output segment |
|
|
|
|
|
h. Real |
|
|
|
i. Imaginary |
|
|
|
|
|
|
|
|
|
50 |
|
|
|
|
50 |
|
|
Amplitude |
2.0 |
|
|
|
|
IFFT |
Amplitude |
|
|
|
|
Amplitude |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
0.0 |
|
|
|
|
|
|
0 |
|
|
|
|
0 |
|
|
|
-2.0 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
-50 |
|
|
|
|
-50 |
|
|
|
-4.0 |
|
|
signal in 0 to 255 |
|
|
|
|
|
|
|
|
|
|
|
-6.0 |
|
|
|
|
|
|
-100 |
|
|
|
|
-100 |
|
|
|
0 |
|
64 |
128 |
192 |
2565 |
|
|
0 |
64 |
128 |
|
0 |
64 |
128 |
|
|
|
Sample number |
|
|
|
|
|
Frequency |
|
|
|
Frequency |
|
FIGURE 18-2
FFT convolution. The filter kernel, (a), and the signal segment, (d), are converted into their respective spectra,
(b) & (c) and (e) & (f), via the FFT. These spectra are multiplied, resulting in the spectrum of the output segment, (h) & (i). The Inverse FFT then finds the output segment, (g).
imaginary parts of the frequency response. These values are transferred into the arrays REFR[ ] & IMFR[ ] (for: REal and IMaginary Frequency Response), to be used later in the program.
316 |
The Scientist and Engineer's Guide to Digital Signal Processing |
The FOR-NEXT loop between lines 340 and 580 controls how the 16000 segments are processed. In line 360, a subroutine loads the next segment to be processed into XX[0] through XX[624], and sets XX[625] through XX[1023] to a value of zero. In line 370, the FFT subroutine is used to find this segment's frequency spectrum, with the real part being placed in the 513 points of REX[ ], and the imaginary part being placed in the 513 points of IMX[ ]. Lines 390 to 430 show the multiplication of the segment's frequency spectrum, held in REX[ ] & IMX[ ], by the filter's frequency response, held in REFR[ ] and IMFR[ ]. The result of the multiplication is stored in REX[ ] & IMX[ ], overwriting the data previously there. Since this is now the frequency spectrum of the output segment, the IFFT can be used to find the output segment. This is done by the mythical IFFT subroutine in line 450, which transforms the 513 points held in REX[ ] & IMX[ ] into the 1024 points held in XX[ ], the output segment.
Lines 470 to 550 handle the overlapping of the segments. Each output segment is divided into two sections. The first 625 points (0 to 624) need to be combined with the overlap from the previous output segment, and then written to the output signal. The last 399 points (625 to 1023) need to be saved so that they can overlap with the next output segment.
To understand this, look back at Fig 18-1. Samples 100 to 199 in (g) need to be combined with the overlap from the previous output segment, (f), and can then be moved to the output signal (i). In comparison, samples 200 to 299 in
(g) need to be saved so that they can be combined with the next output segment, (h).
Now back to the program. The array OLAP[ ] is used to hold the 399 samples that overlap from one segment to the next. In lines 470 to 490 the 399 values in this array (from the previous output segment) are added to the output segment currently being worked on, held in XX[ ]. The mythical subroutine in line 550 then outputs the 625 samples in XX[0] to XX[624] to the file holding the output signal. The 399 samples of the current output segment that need to be held over to the next output segment are then stored in OLAP[ ] in lines 510 to 530.
After all 0 to 15999 segments have been processed, the array, OLAP[ ], will contain the 399 samples from segment 15999 that should overlap segment 16000. Since segment 16000 doesn't exist (or can be viewed as containing all zeros), the 399 samples are written to the output signal in line 600. This makes the length of the output signal 16000 × 625 % 399 ' 10,000,399 points. This matches the length of input signal, plus the length of the filter kernel, minus 1.
Speed Improvements
When is FFT convolution faster than standard convolution? The answer depends on the length of the filter kernel, as shown in Fig. 18-3. The time