To convert a linear-phase FIR low-pass filter into a high-pass filter with the same cut-off frequency, we can invert the sign of the low-pass filter's impulse response $h(n)$ and then add one to the center point: $\delta(n)-h(n)$, where the $\delta(n)$ is the unit impulse function.
I am trying to verify the result in the frequency domain. If the DFT of $h(n)$ is $H(f)$, then the DFT of $\delta(n)-h(n)$ is $1-H(f)$. However, in MATLAB it seems that I cannot generate the desired high-pass filter kernel by applying the ifft()
function to $1-H(f)$. The unit impulse function is added to the first point of the high-pass filter kernel instead of the center point. What is the reason for this and how can I correct my code?
MATLAB code to generate this figure:
%% Generate window-sinc filter coefficients
% CutOffFreq and TransBandWidth should be expressed as fractions of sampling rate between 0 and 0.5.
CutOffFreq = 0.1;
TransBandWidth = 0.01;
% Approxiately calculate the filter order (must be a even integer).
M = 4 / TransBandWidth;
M = round((M-2)/2)*2+2; % Round to the nearest even integer
% Generate the sinc function. Filter length = filter order + 1.
idx = 0:1:M;
Sinc = sin(2*pi*CutOffFreq*(idx-M/2)) ./ (idx-M/2);
Sinc(M/2+1) = 2 * pi * CutOffFreq; % Solve the divided by zero problem
% Generate the Blackman window.
BlackMan = 0.42 - 0.5*cos(2*pi*idx/M) + 0.08*cos(4*pi*idx/M);
% Generate the filter coefficients (the impulse response function).
b = Sinc .* BlackMan;
% Normalized the filter coefficients to have unity gain at DC.
b = b / sum(b);
%% Spectral inversion in the frequency domain
bfft = fft(b);
b1 = ifft(1-bfft);
figure('Color','w');
plot(b,'Color','b','LineWidth',1);
hold on;
plot(b1,'Color','m','LineWidth',1);
xlim([-1,length(b)+1]);
legend({'Low-pass filter kernel','Wrong high-pass kernel'});