increase / decrease the frequency of a signal using fft and ifft in matlab / octave
Asked Answered
E

1

0

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.

Plot 1hz

The plot with 2hz is what I'm trying to get by adjusting the fft and ifft values

Plot 2hz which I trying to get by adjusting the fft and ifft

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

Elin answered 30/12, 2014 at 20:24 Comment(3)
Are you aware that horizontal shifts in the frequency domain correspond to frequency changes in the time domain? For example, slidding the FFT of a function +50Hz will increase that function's frequency by 50Hz.Livia
@Livia - I was about to mention that. +1 for your comment. Rick T - Why don't you simply translate all of your frequency components over by a positive amount?Aaronaaronic
@Livia I tried altering the frequency domain line ya_fft = fft(ya); by adding 1 and a 2. I also tried altering the phase in the line phase = unwrap(angle(ya_fft)); and that doesn't create the second plot am I missing something in your comment?Elin
L
3

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 frequencies
  • Y(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:

  • take the fourier transform
  • leave the DC offset unchanged
  • shift the positive part of the spectrum to the right
  • shift the negative part of the spectrum to the left

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:

enter image description here

Livia answered 31/12, 2014 at 18:10 Comment(1)
Doh. I also forgot to mention about leaving the DC component alone. Nice answer!Aaronaaronic

© 2022 - 2024 — McMap. All rights reserved.