Reputation: 3389
I'm trying to increase / decrease the frequency of a signal using fft and ifft. The first plot is 1hz and the second plot is 2hz which I'm trying to get by altering the fft and ifft values.
I can go between the frequency domain and time domain but how can I increase or decrease the frequency of the signal using fft / ifft?
Note: Yes I know I could change the frequency by changing the frequency value of the equation but I'm just using that as a test signal. The signals I will be using won't have equations they will be imported.
The plot with 2hz is what I'm trying to get by adjusting the fft and ifft values
Example code below:
clear all,clf
Fs = 100;% Sampling frequency
t=linspace(0,1,Fs);
%1a create signal
ya = .5*sin(2*pi*1*t);
%2a create frequency domain
ya_fft = fft(ya);
mag = abs(ya_fft);
phase = unwrap(angle(ya_fft));
ya_newifft=ifft(mag.*exp(i*phase));
%3a frequency back to time domain
ya_ifft=real(ifft(ya_fft));
%1b time domain plot
subplot(2,2,1),plot(t,ya)
title('1 Orginal Signal Time domain')
ylabel('amplitude')
xlabel('Seconds')
%2b frequency domain plot.
[xfreq,yamp]=rtplotfft(ya,Fs);
yamp2=(yamp(:,1)/max(abs(yamp(:,1)))*1); %keep at 1, amplitude levels adjustied in loop below
subplot(2,2,2),plot(xfreq,yamp)
title('2 Frequency domain')
xlabel('Frequency (Hz)')
ylabel('amplitude')
Ps: I'm using octave 3.8.1 which works with matlab
Upvotes: 0
Views: 3869
Reputation: 5821
I apologize that the following is a bit messy. I did everything manually because I'm not sure how else to do it.
First you need to know how MATLAB stores frequency domain data. Take the following example:
N = 100; % number of samples
Fs = 100; % sampling frequency
f = 5; % frequency of the signal
t = 0:1/N:1-1/N; % time goes from 0 to 1 second
y = cos(2*pi*f*t); % time signal
Y = fft(y); % frequency signal
figure(1); plot(y);
figure(2); plot(abs(Y));
Y(1)
is the constant offset (sometimes called the DC offset)Y(2:N/2 + 1)
is the set of positive frequenciesY(N/2 + 2:end)
is the set of negative frequencies... normally we would plot this left of the vertical axis.Note that because N=100
is even, there will be 50
positive frequency components and 49
negative frequency components. If N
is odd, then there will be an equal number of positive and negative frequencies.
If we want to increase the frequency, we need to do is:
To decrease the frequency we would just reverse the direction of the shifts.
In your case, what you need to do is...
clear all,clf
Fs = 100;% Sampling frequency
t=linspace(0,1,Fs);
%1a create signal
ya = .5*sin(2*pi*1*t);
%2a create frequency domain
ya_fft = fft(ya);
mag = abs(ya_fft);
phase = unwrap(angle(ya_fft));
ya_newifft=ifft(mag.*exp(i*phase));
% ----- changes start here ----- %
shift = 1; % shift amount
N = length(ya_fft); % number of points in the fft
mag1 = mag(2:N/2+1); % get positive freq. magnitude
phase1 = phase(2:N/2+1); % get positive freq. phases
mag2 = mag(N/2+2:end); % get negative freq. magnitude
phase2 = phase(N/2+2:end); % get negative freq. phases
% pad the positive frequency signals with 'shift' zeros on the left
% remove 'shift' components on the right
mag1s = [zeros(1,shift) , mag1(1:end-shift)];
phase1s = [zeros(1,shift) , phase1(1:end-shift)];
% pad the negative frequency signals with 'shift' zeros on the right
% remove 'shift' components on the left
mag2s = [mag2(shift+1:end), zeros(1,shift)];
phase2s = [phase2(shift+1:end), zeros(1,shift) ];
% recreate the frequency spectrum after the shift
% DC +ve freq. -ve freq.
magS = [mag(1) , mag1s , mag2s];
phaseS = [phase(1) , phase1s , phase2s];
x = magS.*cos(phaseS); % change from polar to rectangular
y = magS.*sin(phaseS);
ya_fft2 = x + i*y; % store signal as complex numbers
ya_ifft2 = real(ifft(ya_fft2)); % take inverse fft
plot(t,ya_ifft2); % time signal with increased frequency
And there you go:
Upvotes: 3