周波数スペクトルをシフトするには?


7

-X MHzから+ X MHzの範囲のスペクトルがあるとします。ゼロ成分を中央(0 Hz)にシフトして、スペクトルの周波数誤差を修正する必要があります。

出力(周波数スペクトル)がFFTを介して計算される場合、私が知る限り、「回転因子」(または係数、複雑なデータの正弦波および余弦波の場合)を調整することによってスペクトルを移動できます。

サイズ1024 FFT(ビンインデックス0〜1023)の場合、ビン番号511に0 Hz成分が存在する必要があります。ただし、周波数誤差の可能性があるため、0 hz成分は実際にはビン510にある可能性があります。

私はこれについて多くの情報を見つけることができないようです。助けてくれてありがとう。

編集:質問の間違い。


2
0 Hzはビン0にありますか?FFTの中央は高周波です
エンドリス

1
これは、使用されるアルゴリズムに完全に依存します。ただし、それを考える簡単な方法は、波をプロットすることです:
wolfram

それがどのように機能するかは次のとおりです。最高周波数係数が使用される場所に応じて、最高周波数成分の位置になります。ただし、一部のアルゴリズムが出力を別の位置などに配置できる理由(最後にそれらを再配置する以外)については、ルールを説明できません。
user1166780 2012

Wolframアルファリンクはこれを持っているはずです:cos((2 * pi / 512)* x * 500)+ i * sin((2 * pi / 512)* x * 500)、それは機能しないようです。500を1に変更して、違いを確認します。0と0を入力すると、周波数はもちろん0になります。ただし、最後にそれらを再配置すると(データが-somethingから+ somethingの場合)、中央に0 Hzコンポーネントを配置できます。
user1166780 2012

回答:


8

例のように、必要な周波数シフトがビンの間隔の倍数である場合は、FFT出力を必要なビンの数だけ回転させるだけで、必要なシフトを簡単に実行できます。周波数オフセットがビンの間隔の整数倍ではない、より一般的なケースでは、FFTを実行する前に、信号に複素指数関数を乗算できます。

したがって、話している中心周波数成分が実際にはデータの周波数 Hz にあると判断し、データを Hzのレートでサンプリングした場合、対象の成分が次のようになるようにスペクトルをシフトします。 FFT出力の周波数がゼロの場合、次のようにします。foffsetfs

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

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

1
ありがとうございましたが、この情報はどこで見つけましたか?
user1166780 2012

よく気にしないでください、「複雑な指数乗算周波数シフト」または同様のものが私が探していたキーワードです。再度、感謝します。
user1166780 2012

1
これは、離散フーリエ変換の基本的な特性であり、FFTは単なる効率的な実装です。フーリエファミリの他の変換には、類似のプロパティがありますが、それぞれに微妙な違いがあります。
Jason R

よくわかりません。これを使用して、FFTを使用してリアルタイムドメイン信号を(循環)シフトします。整数サンプルシフトは正常に機能しますが、サンプルの半分だけシフトしようとすると、結果は虚数になり、元のようには見えません(元は偶数対称、結果は奇対称です)。奇数長さまたは偶数長さについても同じです。
内部石2013

@endolith:何をしようとしているのかわかりません。上記の答えは、周波数シフトを信号に簡単に適用するためのものです。分数遅延を適用しようとしていますか?
Jason R

-2

まあ、簡単な方法は、もしuがフーリエを使ってスペクトルを見つけ、uがどれだけシフトされたかによって周波数を知る必要がある場合、uは1つのことを実行できます。

1)そのスペクトルからインパルス応答を見つける

2)ノイズで畳み込みます

3)uが取得する信号を確認しますe4)前の信号と一致する場合は、確実に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を取る引数があるので、代わりにur独自の信号を使用できます。

私はこれをどれほどうまく説明できたかわかりませんが、これは私の場合にはうまくいきました。

乾杯!

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.