7
$\begingroup$

Take the simple frequency-domain band-pass filtering operation below . . .

NFFT = 128;
x = randn(NFFT,1);
H = zeros(NFFT,1);
H(10:20) = 1;
y = ifft(H.*fft(x), 'symmetric');

This gives a real output because I'm using the conjugate symmetric flag to the ifft operation.

I want a function that returns the conjugate symmetric version of H, so I do not have to rely on the builtin symmetric option in Matlab's ifft. NFFT can be any positive integer. This could be called something like this . .

H(10:20) = 1;
H = MakeConjSym(H);
$\endgroup$
  • $\begingroup$ Question: Is it possible to generalize this to 3D? i.e. if X is 3- dimensional $\endgroup$ – Emmanuel Nov 30 '18 at 11:02
10
$\begingroup$

Conjugate symmetric means

$$f(-x) = f^{\ast}(x)$$

i.e. the sign of the imaginary part is opposite when $x<0$

The FFT of a real signal is conjugate symmetric. One half of the spectrum is the positive frequencies, and the other half is the negative. The negative coefficients are conjugate of the positive.

So if you do filtering, your envelope must do both the positive frequencies and their corresponding negative frequencies, so that the imaginary bits cancel out.

In your example, H does only one half. That is why the output has imaginary bits in it. What you want is

NFFT = 128;
x = randn(NFFT,1);
H = zeros(NFFT,1);
H(10:20) = 1;
H(end-20+2:end-10+2) = 1;    % Other half
y = ifft(H.*fft(x));
$\endgroup$
6
$\begingroup$

You just have to make sure that

$$H_k = H^*_{N-k},\quad k=1,2,\ldots N-1,\quad (N\ldots\text{FFT length})$$

and that $H_0$ is real-valued.

$\endgroup$
0
$\begingroup$

Using the other answers I have a written a MATLAB function to perform what you required:

function X = forceFFTSymmetry(X)
% forceFFTSymmetry  A function to force conjugate symmetry on an FFT such that when an
% IFFT is performed the result is a real signal.

% The function has been written to replace MATLAB's ifft(X,'symmetric'), as this function
% is not compatible with MATLAB Coder.

% Licensed under Creative Commons Zero (CC0) so use freely.

XStartFlipped = fliplr(X(2:floor(end/2)));
X(ceil(end/2)+2:end) = real(XStartFlipped) - sqrt(complex(-1))*imag(XStartFlipped);

% Or
% X(ceil(end/2)+2:end) = conj(XStartFlipped);

end

As noted in the code, MATLAB Coder does not support a symmetric IFFT so a dedicated, hardcoded function is required to do this if code-compilation is the objective. The provided code should support both even and odd length FFTs.

The formatting looks slightly better on the gist.

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.