FIR Digital Filter Design
Hilbert Transform Design Example
Comparison to Optimal Chebyshev FIR FilterSearch Spectral Audio Signal Processing
Would you like to be notified by email when Julius Orion Smith III publishes a new entry into his blog?
Now we compare the window-method design using the Kaiser window to the optimal equiripple FIR filter design given by the Remez multiple exchange algorithm.
It turns out that the Remez algorithm has convergence problems for filters larger than a few hundred taps. Therefore, we have chosen a desired filter length that is small enough so that it will work. However, keep in mind that for very large filter orders, the Remez method is not really an option. However, there are more recently developed methods for optimal Chebyshev FIR filter design, using ``convex optimization'' techniques, which continue to work at very high orders [201].
The following command in Matlab will attempt to design the filter directly:
hri = remez(M-1, [f1,f2]/fn, [1,1], [1], 'Hilbert');Instead, however, we will use a more robust method [211] which uses the Remez exchange algorithm to design a lowpass filter, and then modulates that up by fs/4 to turn it into the single-sideband filter we need here:
if (doremez)
disp('Designing optimal Chebyshev equiripple FIR lowpass');
tic;
hrm = remez(M-1, [0,(f2-fs/4)/fn,0.5,1], [1,1,0,0], [1,10]);
dt = toc;
disp(sprintf('Remez design time = %0.2f minutes',dt/60));
Remez design time = 2.83 minutes % (33MHz '040 NeXT Turbo)
end;
% Modulate it up to become a single-sideband filter:
hr = hrm .* j .^ [0:M-1];
The weighting [1,P] in the call to remez above says
``make the passband ripple Next, we convert the linear-phase result to zero-phase form and zero-pad:
hrzp = [hr((M+1)/2:M), zeros(1,N-M), hr(1:(M-1)/2)]; Hr = fft(hrzp); % Freq. response of optimal SSB filter Hrp = [Hr(N/2+2:N), Hr(1:N/2+1)]; % Plot (-) freqs on the left plot(f,20*log10(abs(Hrp))); grid; % Don't normalize (see below) s = sprintf(['Length %d Optimal Chebyshev FIR',... ' Single-Sideband-Filter Freq. Response'],M); title(s); xlabel('Normalized Frequency (cycles/sample)'); ylabel('Gain (dB)') if saveplots, saveplot('OptimalHilbertFR.eps'); end; if dopause, disp('Pausing... RETURN to continue'); pause; end;
![]() |
We did not normalize the peak amplitude response to 0 dB because the Remez filter ripples about 1 in the passband. The resulting amplitude response is shown in Fig.B.18. Next, we zoom in on the low-frequency transition region (result in Fig.B.19). By symmetry the high-frequency transition region is identical (but flipped):
kshow = 2*k1; krange = kzero-kshow : kzero+kshow;
frange = (krange - kzero)/N; plot(frange,20*log10(Hrp(krange)));
grid; hold on;
plot((k1-1)/N,1,'+'); hold off;
s = sprintf(...
'Low-Frequency Transition Band, f1/fs=%f (marked by "+")',f1/fs);
title(s); xlabel('Normalized Frequency (cycles/sample)');
ylabel('Gain (dB)')
if saveplot, saveplot('OptimalHilbertZoomedFR.eps'); end;
if dopause, disp 'Pausing... RETURN to continue'; pause; end;
Now let's zoom in on the passband ripple (result in Fig.B.20):
kmid = kzero + (N/4); % bin index near middle of passband
kshow = N/16;
krange = kmid-kshow : kmid+kshow;
frange = (krange - kzero)/N;
plot(frange,20*log10(abs(Hrp(krange)))); grid;
s = sprintf('Passband Ripple');
title(s);
xlabel('Normalized Frequency (cycles/sample)');
ylabel('Gain (dB)')
if saveplots, saveplot('OptimalHilbertZoomedPB.eps'); end;
if dopause, disp 'Pausing... RETURN to continue'; pause; end;
% Zoom in on trailing FIR coefficients
% (looking for "ears" in IR):
plot(hrm(1:50)); grid;
s = sprintf('First 50 impulse-response coefficients');
title(s); xlabel('Index'); ylabel('Amplitude')
if saveplots, saveplot('OptimalHilbertZoomedIR.eps'); end;
if dopause, disp 'Pausing... RETURN to continue'; pause; end;
