Change phase of a signal in frequency domain (MatLab)

北城以北 提交于 2019-12-22 01:10:14

问题


I posted this question on dsp.stackexchange, and was informed that it was more relevant for stackoverflow as it is primarily a programming question:

I am attempting to write a code which allows me to change the phase of a signal in the frequency domain. However, my output isn't exactly correct, so something must be wrong. For a simple example assume that we have the function y = sin(2*pi*t) and want to implement a phase shift of -pi/2. My code looks as follows:

clear all
close all

N = 64; %number of samples
fs = 10; %sampling frequency
ts = 1/fs; %sample interval
tmax = (N-1)*ts;
t = 0:ts:tmax;
y = sin(2*pi*t);

figure
plot(t,y)

% We do the FT
f = -fs/2:fs/(N-1):fs/2;
Y = fftshift(fft(y));

% Magnitude spectrum
figure
plot(f,abs(Y));

phase = angle(Y);

% Phase spectrum
figure
plot(f,phase)

Y = ifftshift(Y)

% Attempt at phase shift
Y = Y.*exp(-i*2*pi*f*pi/2);

% Inverse FT
u = ifft(Y);

figure
plot(t,real(u))

All plots look OK except for the final plot which looks as follows:

This looks almost correct but not quite. If anyone can give me some pointers as to how my code can be corrected in order to fix this, I would greatly appreciate it! I have a feeling my mistake has something to do with the line Y = Y.*exp(-i*2*pi*f*pi/2);, but I'm not sure how to fix it.


回答1:


I can't really get into the Fourier analysis details (because I do not really know them), but I can offer a working solution with some hints:

First of all, You should express Your wave in imaginary terms, i.e.:

y = exp(1i*2*pi*t);

And what's even more crucial, You have to truly shift only the phase, without messing with the whole spectrum:

% Attempt at phase shift
Y = abs(Y).*exp(1i*angle(Y)-1i*pi/4); % -pi/4 shift

You should note that the shift isn't related to frequency anymore, which I guess makes sense. Finally You can plot the results:

figure
plot(t,real(u),'k')
hold on
plot(t,real(y),'r')

real(y) is actually a cosine function, and You started with sine, but hopefully You get the idea. For pi/4 shift i got something like this (started with red, finished with black):




回答2:


You made 3 major mistakes in your code design.

  1. The input vector of a FFT is interpreted as a period of a signal with is repeated infinitely. This means your input vector should contain an integer number of complete periods of your sine signal. You have an input vector of 64 samples and a sample rate of 10. This results in 6.4 periods of your sine wave, which leads to leakage. If you inspect the frequency spectrum after performing the FFT, you will see, that there are not two clean frequency lines, but a lot of frequency components around two places.
  2. After correcting your input vector, there should be only two single frequencies with values which are not close to zeros. 62 frequency components will consist of numerical noise very close to zero. Calculating the phase of these values results in garbage data.
  3. A phase shift of pi/2 in time domain is equivalent by a shift in time domain by N/4 if N is the number of input samples.

I modified your code. You will find it below. With the variable M you can change the number of periods of a sine wave in your input vector. In the example I have set M=3.

clear all;
close all;

T = 1;  %length of sampling sequence in s
N = 64; %number of samples
M = 3; % number of periods per sequence
ts = T/N; %sample interval
fs = 1/ts %sampling frequency
tmax = (N-1)*ts;
t = 0:ts:tmax;
y = sin(2*pi*M*t);

fig01 = figure;
plot(t,y);
grid on;

%% We do the FT
Y = fft(y);

%% We create a frequency vector in natural order
% -fs/2, ..., 0, ... +fs/2
f =fftshift(( 0:(fs-1)) - fs/2);

%% Show Magnitude spectrum
% There shold be only two lines at -M and +M
figure;
plot(f,abs(Y),'o');
grid on;

%% Attempt at phase shift
% y/t) -> Y(w)
% y(t-t0) -> Y(w) * exp(-i*w*t0)
% Phase shift of pi/2 in frequncy domain is equavalent to as time shift
% of T/4 in time domain

Y = Y.*exp(-i*2*pi*f*T/4);

% Inverse FT
u = ifft(Y);

figure
hold on;
plot(t,real(u),'b-');
plot(t,real(y),'r-');
hold off;
grid;

Input signal with three periods of a sine signal

Spectrum of input signal. Frequency lines at -3 and +3

Input signal (blue) and phase shifted signal (red)



来源:https://stackoverflow.com/questions/25963607/change-phase-of-a-signal-in-frequency-domain-matlab

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!