1
$\begingroup$

I considered a time sequence of sine wave t = [0,0.707,1,0.707,0,-0.707,-1,-0.707]

I took spectrum = fft(t) and got the spectrum. I then gave spectrum_shifted = fftshift(spectrum) to the spectrum and obtained a zero frequency point at the center of the spectrum.

Now, I want to get back to the time domain and reach t, the original time sample sequence.

Which one do I do?

  1. ifft(ifftshift(spectrum_shifted)) ?
  2. ifftshift(ifft(spectrum_shifted)) ?

Which one gives me the proper t, I started with and why? I am not getting the reasoning behind this...

$\endgroup$
2
  • 1
    $\begingroup$ The same question has been asked and answered here. Bottom line, ifft(fft(t)) or ifft(ifftshift(fftshift(fft(t)))). You'll notice the redundancy in the second call... $\endgroup$
    – Jdip
    Dec 9, 2022 at 11:20
  • $\begingroup$ For details about re-ordering sequences, see this answer for Python, but valid also in your case. $\endgroup$
    – mins
    May 31, 2023 at 20:38

2 Answers 2

1
$\begingroup$

Matlab makes this needlessly complicated. fftshift(x) is exactly the same as circshift(x,floor(length(x)/2)). ifftshift() is the inverse operation, i.e. circshift(x,-floor(length(x)/2)).

It the FFT length is even, then both operations are identical.

Which one do I do?

Don't shift. Just do ifft(fft(t)). Shifting is mainly for cosmetic purposes and plotting. If you really need to shift for processing use ifft(ifftshift(fftshift(fft(t))))

$\endgroup$
1
  • 5
    $\begingroup$ There are good applications to using fftshift() in MATLAB. When you window a piece of data (say it's a segment of audio) with a decent window (Hann, Hamming, Kaiser), you want to precede fft() with fftshift(), so that the point at t=0 is in the middle of the window. This prevents alternating sign changes in adjacent bins of the DFT result. If MATLAB would agree to get their indexing act together and allow users to define the base index of any array (and make fft() take notice of that), then we would have no need for fftshift(). $\endgroup$ Dec 9, 2022 at 21:20
1
$\begingroup$

Here is a MATLAB script I use to test basic sound analysis functions of MATLAB including fftshift() in displaying the output of fft().

if ~exist('inputFile', 'var')
    inputFile = 'vibe.wav';
end

[inputBuffer, Fs] = audioread(inputFile);

fileSize = length(inputBuffer);

numSamples = 2.^(ceil(log2(fileSize))); % round up to nearest power of 2

x = zeros(numSamples, 1);                   % zero pad if necessary

x(1:fileSize) = inputBuffer(:,1);           % if multi-channel, use left channel only

clear inputBuffer;                          % free this memory
clear fileSize;

t = linspace(0, (numSamples-1)/Fs, numSamples)';
f = linspace(-Fs/2, Fs/2 - Fs/numSamples, numSamples)';

X = fft(x);

plot(t, x);
xlabel('time (seconds)');
ylabel('amplitude');
title(['time-domain plot of ' inputFile]);
sound(x, Fs);                                           % play the sound
pause;




% display both positive and negative frequency spectrum

plot(f, real(fftshift(X)));
xlabel('frequency (Hz)');
ylabel('real part');
title(['real part frequency-domain plot of ' inputFile]);
pause;

plot(f, imag(fftshift(X)));
xlabel('frequency (Hz)');
ylabel('imag part');
title(['imag part frequency-domain plot of ' inputFile]);
pause;

plot(f, abs(fftshift(X)));                              % linear amplitude by linear freq plot
xlabel('frequency (Hz)');
ylabel('amplitude');
title(['abs frequency-domain plot of ' inputFile]);
pause;

plot(f, 20*log10(abs(fftshift(X))+1.0e-10));            % dB by linear freq plot
xlabel('frequency (Hz)');
ylabel('amplitude (dB)');
title(['dB frequency-domain plot of ' inputFile]);
pause;





% display only positive frequency spectrum for log frequency scale

semilogx(f(numSamples/2+2:numSamples), 20*log10(abs(X(2:numSamples/2))));       % dB by log freq plot
xlabel('frequency (Hz), log scale');
ylabel('amplitude (dB)');
title(['dB vs. log freq, frequency-domain plot of ' inputFile]);
pause;

semilogx(f(numSamples/2+2:numSamples), (180/pi)*angle(X(2:numSamples/2)));      % phase by log freq plot
xlabel('frequency (Hz), log scale');
ylabel('phase (degrees)');
title(['phase vs. log freq, frequency-domain plot of ' inputFile]);
pause;

%
%   this is an alternate method of unwrapping phase
%
%   phase = cumsum([angle(X(1)); angle( X(2:numSamples/2) ./ X(1:numSamples/2-1) ) ]);  
%   semilogx(f(numSamples/2+2:numSamples), phase(2:numSamples/2));                  % unwrapped phase by log freq plot
%

semilogx(f(numSamples/2+2:numSamples), unwrap(angle(X(2:numSamples/2))));       % unwrapped phase by log freq plot
xlabel('frequency (Hz), log scale');
ylabel('unwrapped phase (radians)');
title(['unwrapped phase vs. log freq, frequency-domain plot of ' inputFile]);

If you were windowing segments of audio and passing them to the FFT, then you should use fftshift() on the input to the FFT to define the center of the windowed segment as the t=0 point.

[x_input, Fs] = audioread('vibe.wav');     % load time-domain input
N = 2*floor(length(x_input)/2);            % make sure N is even
x = x_input(1:N);

t = linspace(-N/2, N/2-1, N);              % values of time in units of samples
omega = linspace(-pi, pi*(1-2/N), N);      % values of (normalized) angular frequency

X = fftshift( fft( fftshift( x.*hamming(length(x)) ) ) );

[X_max k_max] = max( abs(X) );

figure(1);
plot(t, x, 'g');

figure(2);
plot(omega, abs(X), 'b');
hold on;
plot(omega(k_max), X_max, 'or');
hold off;
$\endgroup$
1
  • $\begingroup$ Interesting! Never thought of this. $\endgroup$
    – Jdip
    Dec 9, 2022 at 22:03

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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