How do I freqency shift a signal by a fractional amount using IFFT and FFT?
Show older comments
Let me preface this with: I am an extreme novice when it comes to FFTs.
I have a signal vector x of length 1200. To shift the frequency of the signal I am doing the following:
y=IFFT(x);
SHIFT=1;
t=[1:1200]*2*pi/1200;
for j=1:1200
mult(j)=exp(-i*SHIFT*t(j));
z=mult.*y;
end
w=real(fft(z));
When SHIFT is an integer I get what I am looking for in w, which is the signal x shifted by the value of SHIFT. However, when SHIFT is fractional the vector w looks like some combination between a shifted x and its derivative.
My question is: what do I do to shift x by a fractional amount using FFTs and IFFTs?
Thanks,
Victoria
Answers (2)
Matt J
on 11 Jun 2013
You would do something like this
N=length(y);
mult = exp(-1i*2*pi/N*(0:N-1)*SHIFT);
w=ifft((fft(y).*mult ),'symmetric')
5 Comments
This is equivalent to shifting a sinc-interpolated version of y. Unless you really can't live with linear interpolation, though, directly shifting/resampling in the original domain, without FFTs is going to be more efficient. Compare:
SHIFT=0.3;
y=rand(1,1e7);
N=length(y);
ax=(0:N-1);
tic
mult = exp(-1i*2*pi/N*(0:N-1)*SHIFT);
w=ifft((fft(y).*mult ),'symmetric');
toc;
%Elapsed time is 1.242511 seconds.
tic;
w= interp1(y,ax+SHIFT,'linear');
toc
%Elapsed time is 0.512226 seconds.
F=griddedInterpolant(y,'linear');
tic
w=F(ax+SHIFT);
toc
%Elapsed time is 0.312686 seconds.
Matt J
on 12 Jun 2013
Victoria commented:
Thanks. That did the trick.
Matt J
on 12 Jun 2013
You're welcome. If this resolves your question, the normal thing for you to do now would be to Accept-click my Answer.
rashi
on 3 Aug 2020
but the output for w,w1 and w2 are different, will those be not same?
Matt J
on 3 Aug 2020
No, the first version does not use linear interpolation and so will be different from the others.
Duncan Carlsmith
on 21 Jun 2025
1 vote
analytic_segment = hilbert(segment); % Complex analytic signal
shifted_segment = real(analytic_segment .* exp(1j*2*pi*f_shift*t));
2 Comments
Paul
on 22 Jun 2025
Hi Duncan,
Can you illustrate this approach with a concrete example?
Duncan Carlsmith
on 22 Jun 2025
Moved: Matt J
on 23 Jun 2025
%% Frequency-Shift Demo with Synthetic Audio
% This script creates a 1-s synthetic audio signal consisting of four
% sinusoids (1, 2, 3, 4 kHz) of decreasing amplitude plus Gaussian noise,
% shifts it up by 500 Hz, and compares the spectra and waveforms.
% -------------------------------------------------------------------------
% Parameters
% -------------------------------------------------------------------------
fs = 44100; % Sampling rate (Hz)
duration = 1.0; % Signal length (s)
f_shift = 500; % Desired frequency up-shift (Hz)
% -------------------------------------------------------------------------
% Construct synthetic signal (column vector)
% -------------------------------------------------------------------------
t = (0:1/fs:duration-1/fs).'; % Time axis
amp = [1.0 0.8 0.6 0.4]; % Amplitudes
freqs = [1000 2000 3000 4000]; % Frequencies (Hz)
segment = zeros(size(t));
for k = 1:numel(freqs)
segment = segment + amp(k)*sin(2*pi*freqs(k)*t);
end
segment = segment + 0.2*randn(size(t)); % Additive white Gaussian noise
% -------------------------------------------------------------------------
% Play original audio
% -------------------------------------------------------------------------
soundsc(segment,fs);
pause(2); % Brief pause
% -------------------------------------------------------------------------
% Frequency-shift via analytic signal
% -------------------------------------------------------------------------
analytic_segment = hilbert(segment); % Analytic (complex) signal
shifted_segment = real(analytic_segment ...
.* exp(1j*2*pi*f_shift*t));
% -------------------------------------------------------------------------
% Play shifted audio
% -------------------------------------------------------------------------
soundsc(shifted_segment,fs);
pause(2);
% -------------------------------------------------------------------------
% Power spectra (overlaid)
% -------------------------------------------------------------------------
% 1 Hz frequency resolution for clear peak separation
[P_orig,F] = pspectrum(segment, fs,'FrequencyResolution',3);
[P_shift,~] = pspectrum(shifted_segment,fs,'FrequencyResolution',3);
figure;
plot(F,10*log10(P_orig),'b','LineWidth',1.2,'DisplayName','Original');
hold on;
plot(F,10*log10(P_shift),'r','LineWidth',1.2,'DisplayName','Shifted');
xlim([0 6000]);
xlabel('Frequency (Hz)');
ylabel('Power/Frequency (dB/Hz)');
title('Power Spectrum: Original vs. Frequency-Shifted');
legend('Location','best');
grid on;
ylim([-60,0])
% -------------------------------------------------------------------------
% Time-domain waveforms (overlaid)
% -------------------------------------------------------------------------
figure;
plot(t,segment, 'b','DisplayName','Original'); hold on;
plot(t,shifted_segment,'r','DisplayName','Shifted');
xlabel('Time (s)');
ylabel('Amplitude');
title('Waveforms: Original vs. Frequency-Shifted');
legend('Location','best');
grid on;
% Uncomment the next line to zoom into the first 10 ms:
xlim([0 0.01]);
Categories
Find more on Vibration Analysis in Help Center and File Exchange
Community Treasure Hunt
Find the treasures in MATLAB Central and discover how the community can help you!
Start Hunting!