如何移动频谱?

信息处理 fft 频率 频谱
2022-01-07 16:29:58

假设我们的频谱范围从 -X MHz 到 +X MHz。我需要通过将零分量移动到中间(0 Hz)来纠正频谱中的频率误差。

如果输出(频谱)是通过 FFT 计算的,据我所知,我可以通过调整“旋转因子”(或系数,用于复杂数据正弦波和余弦波)来移动频谱。

在大小为 1024 FFT 的情况下(bin 索引从 0 到 1023),0 Hz 分量应该存在于 bin 编号 511 中。但是,由于可能的频率误差,例如,0 Hz 分量实际上可能位于 bin 510 中。

我似乎找不到太多关于此的信息。任何帮助表示赞赏。

编辑:问题中的错误。

2个回答

如果您想要的频移是箱间距的倍数,如您的示例中所示,那么您只需将 FFT 输出旋转所需的箱数即可轻松实现所需的频移。在频率偏移不是 bin 间距的整数倍的更常见情况下,您可以在执行 FFT 之前将信号乘以复指数函数。

因此,如果您确定您所说的中心频率分量实际上位于数据中的频率 Hz速率采样,那么要移动频谱以使感兴趣的分量为在 FFT 输出中的零频率下,您将执行以下操作:foffsetfs

xshifted[n]=x[n]ej2πfoffsetnfs,  n=0,1,,N1

Yshifted[k]=FFT[xshifted[n]]

好吧,简单的方法是,如果您使用傅立叶找到光谱,并且您需要知道它的频率偏移了多少,您可以做一件事..

1) 从该频谱中找出脉冲响应

2)将其与噪声卷积

3)查看你获得的信号4)采取它的FFT只是为了确定,如果它与前一个匹配

4)并通过对不同部分进行平均来查看光谱......为此,我可以在mathematica软件中给出ua算法,即

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]
  ]

在这段代码中,我有一个参数来接受 pmsesignal ,所以你可以使用你自己的信号来代替它..

我不确定,我解释得有多好,但这对我来说是有效的..

干杯!