Continue to Site

fft frequency shift

Status
Not open for further replies.

edmont

Newbie level 6
To determine the response of the fft to a sinusoidal of increasing
frequency yet same amplitude of 1.

I used a pure sine wave sin(2*pi*t*a) , where the multiplier 'a'
determines the period , and hence frequency of the wave.

Now examining the fft, the peak does indeed shift as expected,
the amplitude however doesn't quite behave as expected.
For a pure sine , in the analog world, the Fourier Transform doesn't
change amplitude with frequency .

The fft amplitude almost follows the equation 0.5-0.4*(w^1.8).

What is the actual relationship ?

To determine the response of the fft to a sinusoidal of increasing
frequency yet same amplitude of 1.

I used a pure sine wave sin(2*pi*t*a) , where the multiplier 'a'
determines the period , and hence frequency of the wave.

Now examining the fft, the peak does indeed shift as expected,
the amplitude however doesn't quite behave as expected.
For a pure sine , in the analog world, the Fourier Transform doesn't
change amplitude with frequency .

The fft amplitude almost follows the equation 0.5-0.4*(w^1.8).

What is the actual relationship ?
It is likely your fft size is the cause. You need avoid power smearing around bins by having exact cycles. Or apply window but is less accurate.

It is likely your fft size is the cause. You need avoid power smearing around bins by having exact cycles. Or apply window but is less accurate.
If I use a particular length fft, not necessarily radix 2, will this correct the situation ?

So that everyone comprehends what I did, here are some details:

• ω0 = 50
• f1(t,x) = sin(ω0*2*pi*t*x)
• N=1024 number of points
• x = 1 to 18 , step 1
• frequency range is then 0 to approximately 900 Hz
• abs(fft) values, red multiplier character .
• Curve fitting g1(x) = 0.5 - 0.42*(x/820)^1.8 , the blue line .

And, maybe, an image file; freq_shift.png

If there's a general formula to correct for this, without
adjusting the size of the fft all the time, then that is preferable
and likely useful.

Already I need to correct a few details and reload the graph with
the proper labels for the axes.

abs(a + i*b) = sqrt(a*a + b*b)

frequency range is 0 to approximately 400 Hz

Why not showing the Matlab code?

If I use a particular length fft, not necessarily radix 2, will this correct the situation ?

So that everyone comprehends what I did, here are some details:

ω0 = 50
f1(t,x) = sin(ω0*2*pi*t*x)
N=1024 number of points
x = 1 to 18 , step 1
frequency range is then 0 to approximately 900 Hz
abs(fft) values, red multiplier character .
Curve fitting g1(x) = 0.5 - 0.42*(x/820)^1.8 , the blue line .

And, maybe, an image file; freq_shift.png

If there's a general formula to correct for this, without
adjusting the size of the fft all the time, then that is preferable
and likely useful.
The easiest way is to use iFFT to generate the frequencies.
You decide which bins are populated, the rest of bins at zeros. Then apply iFFT. By this method you should get same amplitude provided the bin value is same. For example:
x = zeros(1,1024);
x(46) = 1;
y=real(ifft(x));

Why not showing the Matlab code?
I used maxima computer algebra system to examine this.
I have , and have used the Matlab clone, Octave, however
maxima is quite useful and nowadays has ffts available that

The easiest way is to use iFFT to generate the frequencies.
You decide which bins are populated, the rest of bins at zeros. Then apply iFFT. By this method you should get same amplitude provided the bin value is same. For example:
x = zeros(1,1024);
x(46) = 1;
y=real(ifft(x));
That's an interesting approach and one I haven't investigated.
From the ifft the time domain amplitudes should be amplitude adjusted.

That's an interesting approach and one I haven't investigated.
From the ifft the time domain amplitudes should be amplitude adjusted.
you can scale it at input to ifft. ifft scaling is arbitrary and may pass unity power.
so scale up (x) as you want output to be:

x = zeros(1,1024);
x(87) = 2^15;
y=real(ifft(x));

you can scale it at input to ifft. ifft scaling is arbitrary and may pass unity power.
so scale up (x) as you want output to be:

x = zeros(1,1024);
x(87) = 2^15;
y=real(ifft(x));
If I apply the fft to

sin(t*2*%pi*f)

where f, the frequency, is an integer, and n equals
the number of samples, then the peaks in the frequency
domain appear at f+1 and n+1-f and the absolute amplitude is
always 0.5.

If f isn't an integer, then the peaks are 'smeared out' and
the only way I presently know to correct the amplitude, is
by dividing by the curve that I previously fitted.

Perhaps you can illustrate more succintly how you apply
frequency binning.

Zero extension, in the time domain appears to overcome a lot of the problems relating to
the amplitude of the frequency shifted signal , at the expense of some extra lobes.

With this approach I just put values within the first quarter of the input array, the other three quarters remained
at zero, I then did an fft ; this was somewhat valid even for non integer frequency values.
I noted that the peak amplitudes were the same, irrespective of the frequency; a filter might reduce the
side lobes without changing the peak value.

Next consideration time domain amplitude modulation plus frequency modulation.

If I apply the fft to

sin(t*2*%pi*f)

where f, the frequency, is an integer, and n equals
the number of samples, then the peaks in the frequency
domain appear at f+1 and n+1-f and the absolute amplitude is
always 0.5.

If f isn't an integer, then the peaks are 'smeared out' and
the only way I presently know to correct the amplitude, is
by dividing by the curve that I previously fitted.

Perhaps you can illustrate more succintly how you apply
frequency binning.
Let us experiment with two frequencies y1,y2:
Code:
x = zeros(1,1024);
x(87) = 2^15;
y1=real(ifft(x));

x = zeros(1,1024);
x(118) = 2^15;
y2=real(ifft(x));

%Now check fft of y1 and y2
plot(abs(fft(y1)));hold
plot(abs(fft(y2)));

or check time domain of y1,y2

Let us experiment with two frequencies y1,y2:
x = zeros(1,1024);
x(87) = 2^15;
y1=real(ifft(x));

x = zeros(1,1024);
x(118) = 2^15;
y2=real(ifft(x));

%Now check fft of y1 and y2
plot(abs(fft(y1)));hold
plot(abs(fft(y2)));

or check time domain of y1,y2
That's a little unexpected, two peaks appear for abs(fft(y1)) and abs(fft(y2)).
Are these the correct sign and imaginary or not though ?

That's a little unexpected, two peaks appear for abs(fft(y1)) and abs(fft(y2)).
Are these the correct sign and imaginary or not though ?
I displayed two tones one y1, one y2 on same plot to show they are at same amplitude
Since they are real only they get mirrored mirrored

I displayed two tones one y1, one y2 on same plot to show they are at same amplitude
Since they are real only they get mirrored mirrored
I used two separate p
lots and noted that all peaks were the same amplitude.

What I'm attempting to do is combine frequency modulation and amplitude
modulation with a generalised signal like this:

A(x)*sin(2*pi*t*x)

then have that replicated, in some way , in the frequency domain.
Partial success , zero extension that I used likely convoluted the output
with a sinc function.

Anyway stepping back from that, lets see what else is possible with your
approach.

This is what I've done so far for simultaneous
amplitude and frequency modulation .
It involves the sum of frequency shifted sinusoids,
x dependent amplitude modulation and zero extension.

Perhaps your approach has a place within this
scheme.

Where the function, floor, is similar to getting
the integer .

Code:
n=4096
ω0=floor(n/20)

f2(t,x)=cos(x*%pi*0.1)*sin(ω0*2*%pi*t*x)

m=floor(ω0/10)

Sum f2(t,x) across a domain of x, [0,m*0.5] in this instance .
eq=sum(f2(t,0.5*x ),x,1,m)
let f1(t) = previous

define(f1(t),eq)

Taking the fft(f1(t)) then using the plot of abs() values
I obtained
The outline of the time domain cosine function is apparent in the frequency
domain, as for the sign , I haven't bothered seeing how that might be found.
There is a limitation upon the resolution and other methods, unknown to me
at this stage, are required.

This is what I've done so far for simultaneous
amplitude and frequency modulation .
It involves the sum of frequency shifted sinusoids,
x dependent amplitude modulation and zero extension.

Perhaps your approach has a place within this
scheme.

Where the function, floor, is similar to getting
the integer .

n=4096
ω0=floor(n/20)

f2(t,x)=cos(x*%pi*0.1)*sin(ω0*2*%pi*t*x)

m=floor(ω0/10)

Sum f2(t,x) across a domain of x, [0,m*0.5] in this instance .
eq=sum(f2(t,0.5*x ),x,1,m)
let f1(t) = previous

define(f1(t),eq)

Taking the fft(f1(t)) then using the plot of abs() values
I obtained
The outline of the time domain cosine function is apparent in the frequency
domain, as for the sign , I haven't bothered seeing how that might be found.
There is a limitation upon the resolution and other methods, unknown to me
at this stage, are required.
your (x) input? what does it look like? what is sampling rate?

The input signal 'x' has a lot of what appear initially to be repetitions.

The input signal 'x' has a lot of what appear initially to be repetitions.View attachment 181093

Given such changing input you better avoid idea of iFFT. Though you still can modulate amplitude onto iFFT bin and modulate frequency by selecting bin.
But there is no point as you can just modulate your way. The original issue was about fft leakage giving different amplitudes for different frequencies. You can view that as artefact of fft and ignore it.

As some of you maybe familiar with octave, or matlab, here is a
script that replicates what I've done so far with maxima cas .

This uses the Octave syntax, to convert to matlab equivalent, replace
endfor with end, endfunction with end, then most everything else
should be compatible.
[
# fft_1t2.m

# Simultaneous Frequency and amplitude modulation.

# ---------------------------------- variables ---------------------------

t=0;
a=0;

# --------------------------------------- functions -----------------------

function retval=f2(t,a,w0)
retval=cos(a*pi*2*0.05)*sin(w0*2*pi*t*a); # am and fm

#retval=sin(2*pi*t*a*w0); # frequency shift, modulatiom only
endfunction

function retval=f1(t,w0,p)
s=0;
for j=1
s=s + f2(t,j*0.5,w0);
endfor
retval=s;
endfunction

# ----------------------------------- main ----------------------------

w0=50;
t=1;
a=0.5;
#f2(t,a,w0)
#plot(f2(t,a,w0));

t = 0:0.001:1;
#plot(t, f2(t,a,w0),"-b;sin(t);");
#plot(t, f1(t,w0,40),"-b;sin(t);");
n=1024;
x=zeros(n,1);

m=floor(n/2);
for i=1:m
t=(i-1)/n;
x(i)=f1(t,w0,40);

endfor
#plot(x);
Fx=fftshift(fft(x));
plot(abs(Fx));
]
--- Updated ---

Disregard the enclosing [ and ] in previous, I was attempting to put the code in
a code block.

Replace the smiley with for j equals 1 colon p

Last edited:

Status
Not open for further replies.