Changing the phase of a signal in frequency domain
Asked Answered
B

1

6

i want to change the phase of a signal in the frequency domain. so i generated a cosine test signal to verify the code:

ycheck = cos(2*pi*t);

when i want to shift the phase about pi/4 i perform a fft on the signal split it in magnitude and phase and substract pi/4 from it.

Ycheck = abs(Ycheck).*exp(1i*angle(Ycheck)-1i*pi/4); % -pi/4 shift

plotting the result it looks like only the amplitude of the signal was lowered, but no phase shift happened. i did a little research on the forum and found this post Change phase of a signal in frequency domain (MatLab). So i generated another testsignal using the following:

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

when i do the phase shift with this signal it gives the desired result. sadly i can not post pictures :(, so i try to describe (the code is attached, so you can execute it): only the ifft of the imaginery term is shifted correctly. the ifft of the standard cosine is only lowered in amplitude. i dont quite get, whats the problem here.

my question is, why does the phase shift work on signals expressed in an imaginary term and not on a regularly generated cosine? My plan is to apply this phase shift to real signals - can i apply the phase shift in frequency domain to eg music signals or is there another (maybe smarter) way?

My code is here:

clear all;
close all;
clc;

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

% plot test signals
figure
plot(t,y)
hold on
plot(t,ycheck,'r--')

% fft
Y = fft(y);
Ycheck = fft(ycheck);

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

%ifft
u = ifft(Y);
ucheck = ifft(Ycheck);

% plot
figure
plot(t,real(u),'k')
hold on
plot(t,real(y),'r')
hold on
plot(t,real(ucheck),'g')
hold on
plot(t,ycheck,'b--')
legend('ifft(exp(1i*2*pi*t)) %-pi/4shift','real(cos(2*pi*t))','ifft(cos(2*pi*t)) %-pi/4 shift','cos(2*pi*t)')
Brynhild answered 15/9, 2015 at 11:5 Comment(0)
A
9

Interesting question!

As you know, the cosine can be expressed as the sum of two imaginary exponentials:

 cos(x) = ( exp(1i*x) + exp(-1i*x) ) / 2;

Changing the phase of the cosine means adding a number, say phi, to the cosine argument x:

 cos(x+phi) = ( exp(1i*(x+phi)) + exp(-1i*(x+phi)) ) / 2;

that is,

 cos(x+phi) = ( exp(1i*x + 1i*phi) + exp(-1i*x - 1i*phi) ) / 2;

Thus, you need to add 1i*phi in one of the exponents and subtract 1i*phi in the other. In your case phi = -pi/4. However, your line

Ycheck = abs(Ycheck).*exp(1i*angle(Ycheck)-1i*pi/4); % -pi/4 shift

adds the same term to both exponentials (actually, to all frequency components). That is the problem.

In an ordinary Fourier transform, the first exponential corresponds to positive frequency in the transformed domain, and the second to negative frequency. But since you are doing a DFT (FFT), the negative frequencies get folded and appear in the upper part. So you need to add phi in the lower half of the DFT and subtract phi in the upper half.

Assuming that the number of points of the DFT is even, as in your example, you just need to replace the line indicated above by

phi = -pi//4; %/ desired phase shift
ind = 1:numel(Ycheck)/2; %// lower half
Ycheck(ind) = abs(Ycheck(ind)).*exp(1i*angle(Ycheck(ind))+1i*phi); %// add 1i*phi
ind = numel(Ycheck)/2+1:numel(Ycheck); %// upper half
Ycheck(ind) = abs(Ycheck(ind)).*exp(1i*angle(Ycheck(ind))-1i*phi); %// subtract 1i*phi
Alodie answered 15/9, 2015 at 11:26 Comment(2)
wow, thank you for the great answer, now i get it! i only thought of the formula describing the complex number as "absexp(iangle) totally forgetting about that elementary fact of the dft. and thanks for the fact you made me aware of the problem with an even number of points. so in case i need to zero pad. i wouldnt have thought about that aswell. :)Brynhild
@Brynhild Glad I could help :-)Alodie

© 2022 - 2024 — McMap. All rights reserved.