9
$\begingroup$

Lets say we have a spectrum ranging from -X MHz to +X MHz. I would need to correct the frequency error in the spectrum by shifting the zero component to the middle (0 Hz).

If the output (the frequency spectrum) is calculated via FFT, as far as I know I can move the spectrum by adjusting the 'twiddle factors' (or coefficients, for complex data sine and cosine waves).

In the case of a size 1024 FFT (bin indexes from 0 to 1023), 0 Hz component should exist in bin number 511. However, due to possible frequency error the 0 hz component may actually be in bin 510 for example.

I cannot seem to find much information on this. Any help appreciated.

EDIT: Mistake in the question.

$\endgroup$
4
  • 2
    $\begingroup$ 0 Hz is in bin 0, no? The middle of the FFT is the high frequencies $\endgroup$
    – endolith
    Apr 10, 2012 at 13:49
  • 1
    $\begingroup$ This would depend entirely on the algorithm used. However, a simple way to think of it is to just plot the waves: wolfram alpha $\endgroup$ Apr 11, 2012 at 6:42
  • $\begingroup$ How I think it works is that: Depending on where the highest frequency coefficient is used, would be the position of the highest frequency component. However I cannot explain the rules as to why some algorithms can have their outputs in different positions etc (other than re-arranging them in the end). $\endgroup$ Apr 11, 2012 at 6:49
  • $\begingroup$ Wolfram alpha link should have this: cos((2*pi / 512) * x * 500) + i*sin((2*pi / 512) * x * 500), does not seem to work tho. Change 500 to 1 and see the difference. If you input 0 and 0, the frequency is ofcourse 0. But if we re-arrange them in the end (incase our data is from -something to +something) we can have our 0 Hz component in the middle. $\endgroup$ Apr 11, 2012 at 6:59

2 Answers 2

9
$\begingroup$

If the frequency shift that you want is a multiple of the bin spacing, as in your example, then you can easily effect the shift that you want by just rotating the FFT outputs by the number of bins that you need. In the more common case that the frequency offset is not an integer multiple of the bin spacing, then you can multiply the signal by a complex exponential function before doing the FFT.

So, if you determine that the center frequency component that you speak of is actually located at frequency $f_{offset}$ Hz in your data, and the data is sampled at rate $f_s$ Hz, then to shift the spectrum such that the component of interest is at zero frequency in the FFT output, you would do:

$$ x_{\text{shifted}}[n] = x[n] e^{-\frac{j 2 \pi f_{\text{offset}} n}{f_s}}, \ \ n = 0, 1, \ldots , N-1 $$

$$ Y_{\text{shifted}}[k] = FFT\left[x_{\text{shifted}}[n]\right] $$

$\endgroup$
7
  • 1
    $\begingroup$ Thanks for this, but where did you find this information? $\endgroup$ Apr 11, 2012 at 6:49
  • $\begingroup$ Well nevermind, 'complex exponential multiplication frequency shift' or similar is the keyword I was looking for. Thanks again. $\endgroup$ Apr 11, 2012 at 8:33
  • 1
    $\begingroup$ This is a basic property of the discrete Fourier transform, of which the FFT is just an efficient implementation. The other transforms in the Fourier family have analogous properties of their own, but there are subtle differences in each. $\endgroup$
    – Jason R
    Apr 11, 2012 at 12:46
  • $\begingroup$ I'm confused. I'm trying to use this to (circular) shift a real time-domain signal using FFT. Integer sample shifts work fine, but when I try to shift by half a sample, the result becomes imaginary and looks nothing like the original (original is even-symmetric, result is odd-symmetric). Same for odd- or even-lengths. $\endgroup$
    – endolith
    Aug 8, 2013 at 21:08
  • $\begingroup$ @endolith: I'm not sure what you're trying to do there. The answer I gave above was for easily applying a frequency shift to a signal. Are you trying to apply a fractional delay? $\endgroup$
    – Jason R
    Aug 9, 2013 at 1:03
-3
$\begingroup$

well, the simple way is , if u have used the fourier to find the spectra , and u need to know its frequency by how much is it shifted, u can do one thing ..

1) find out the impulse response from that spectra

2) convolve it with a noise

3) see the signal that u obtaine4) take its FFT just to be sure , if it matches with the previous one

4)and see the spectra by averaging in to differnt parts... for this i can give u a algorithm in mathematica software, which is

reflect[a_] := Module[{n = Length[a]},
  RotateRight[a, Floor[n/2]]
  ]

freqAxis[len_] := Module[{},
   If[OddQ[len],
    Range[1, len] - (Ceiling[len/2.]),
    Range[1, len] - (1 + Ceiling[len/2.])
    ]
   ];

colors = {Black, Red, Blue, Brown , ColorData["Legacy", "DarkGreen"], 
   ColorData["Legacy", "Goldenrod"], ColorData["Legacy", "DeepPink"], 
   Cyan, Orange, Purple, ColorData["Legacy", "DeepSkyBlue"], Magenta};

specPlot[pieces_, pieceLen_, color_] := 
 Module[{data, spec, fAxis, pos},
  fAxis = freqAxis[pieceLen];
  data = Partition[Take[mysignal, pieces*pieceLen], pieceLen];
  spec = Total[Abs[Fourier[data]]^2]/pieces;
  spec = reflect[spec];
  Print["valley=", Nearest[spec, 1.0][[1]], " atPos=", 
   pos = Position[spec, Nearest[spec, 1.0][[1]]][[1, 1]], " atFpos=", 
   Position[fAxis, 0][[1, 1]], " atF=", fAxis[[pos]], " firstMax=", 
   Max[Take[spec, Round[pieceLen/2]]], " atF=", 
   fAxis[[Position[spec, Max[Take[spec, Round[pieceLen/2]]]][[1, 
     1]]]], " lastMax=", Max[Take[spec, -Round[pieceLen/2]]], " atF=",
    fAxis[[Position[spec, Max[Take[spec, -Round[pieceLen/2]]]][[1, 
     1]]]]];
  ListLinePlot[Transpose[{fAxis, spec}], PlotStyle -> colors[[color]],
    PlotLabel -> "N = " <> ToString[pieces], PlotRange -> All]
  ]

in this code , i have a argument to take pmsesignal , so u can use ur own signal instead of it..

i am not sure, how well i explained this, but this had worked in my case..

Cheers!

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.