from 1D Fourier shift by Tim
Shift 1D signals using the Fourier shift theorem.

FourierShift(x, delta, zero_pad)
function y = FourierShift(x, delta, zero_pad)
%
% y = FourierShift(x, delta, zero_pad)
%
% Shifts x by delta cyclically. Uses the fourier shift theorem.
%
% zero_pad is optional. If set to 'pad' then zeros will be added making the
% shift non-cyclic. The default is not to.
%
% Real inputs should give real outputs.
%
% By Tim Hutt, 24/03/2009
% Small fix thanks to Brian Krause, 11/02/2010

% Force the input to be a column vector.
x = x(:);

% The length of the vector.
N = length(x);

% The range to return. This will be different if we are zero padding.
R = 1:N;

% See if they want to add zeros to make the shift non-cyclic. Actually it
% is still cyclic but instead of seeing the back of the signal shifted in
% at the front, they see the zeros we added.
if nargin > 2 && strcmp(zero_pad, 'pad')
    % Clamp to avoid cycling. Note that there may still be some ringing at
    % the sides. Should probably use more conservative zero padding.
    delta = min(max(delta, -N), N);
    
    % New zero padded signal.
    x = [zeros(ceil(N/2), 1); x; zeros(ceil(N/2), 1)];
    
    % We want to return a different range.
    R = R + ceil(N/2);
    
    % And the length has changed.
    N = length(x);
end

% FFT of our possibly padded input signal.
X = fft(x);

% The mathsy bit. The floors take care of odd-length signals.
W = exp(-1i * 2 * pi * delta * [0:floor(N/2)-1 floor(-N/2):-1]' / N); 
if mod(N, 2) == 0
	% Force conjugate symmetry. Otherwise this frequency component has no
	% corresponding negative frequency to cancel out its imaginary part.
	W(N/2+1) = real(W(N/2+1));
end 
Y = X .* W;

% Invert the FFT.
y = ifft(Y);

% There should be no imaginary component (for real input
% signals) but due to numerical effects some remnants remain.
if isreal(x)
    y = real(y);
end

% Extract the relevant range in case we used zero padding.
y = y(R);

Contact us at files@mathworks.com