単一周波数の位相を計算するアルゴリズムはありますか?


17

関数と参照正弦波がある場合、を計算するための高速アルゴリズムは何でしょうか?ω X φf(t)=Asin(ωt+ϕ)sin(ωx)ϕ

Goertzelアルゴリズムを見ていましたが、フェーズを処理していないようです。

回答:


5

特定の周波数でDFTを使用します。次に、実数/画像部分から振幅と位相を計算します。これにより、サンプリング時間の開始を基準とした位相が得られます。

「通常の」FFT(またはN個のすべての高調波に対して計算されたDFT)では、通常、f = k *(sample_rate)/ Nで周波数を計算します。ここで、kは整数です。(特に教会のWholly Integerのメンバーにとっては)見苦しいように見えるかもしれませんが、実際には、単一のDFTを行うときにkの非整数値を使用できます。

たとえば、27 Hzの正弦波のN = 256ポイントを生成(または取得)したとします。(たとえば、sample_rate = 200)。256ポイントFFT(またはNポイントDFT)の「通常の」周波数は、f = k *(sample_rate)/ N = k *(200)/ 256に対応します。ここで、kは整数です。ただし、34.56の非整数「k」は、上記のパラメーターを使用して、27 Hzの周波数に対応します。これは、対象の周波数(27 Hz)を正確に中心とするDFTの「ビン」を作成するようなものです。一部のC ++コード(DevC ++コンパイラ)は次のようになります。

#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
using namespace std;

// arguments in main needed for Dev-C++ I/O
int main (int nNumberofArgs, char* pszArgs[ ] ) {
const long N = 256 ;
double sample_rate = 200., amp, phase, t, C, S, twopi = 6.2831853071795865; 
double  r[N] = {0.}, i[N] = {0.}, R = 0., I = 0. ;
long n ;

// k need not be integer
double k = 34.56;

// generate real points
for (n = 0; n < N; n++) {
    t =  n/sample_rate;
    r[n] = 10.*cos(twopi*27.*t - twopi/4.);
}  // end for

// compute one DFT
for (n = 0; n < N; n++) {
    C = cos(twopi*n*k/N); S = sin(twopi*n*k/N);
    R = R + r[n]*C + i[n]*S;
    I = I + i[n]*C - r[n]*S;
} // end for

cout<<"\n\ndft results for N = " << N << "\n";
cout<<"\nindex k     real          imaginary       amplitude         phase\n";

amp = 2*sqrt( (R/N)*(R/N) + (I/N)*(I/N) ) ;
phase = atan2( I, R ) ;
// printed R and I are scaled
printf("%4.2f\t%11.8f\t%11.8f\t%11.8f\t%11.8f\n",k,R/N,I/N,amp,phase);

cout << "\n\n";
system ("PAUSE");
return 0;
} // end main

//**** end program

(追記:上記がStackoverflowにうまく変換されることを願っています–一部はラップアラウンドするかもしれません)

上記の結果は、生成された実際のポイントに示されているように-twopi / 4の位相になります(およびアンプは、pos / neg周波数を反映するために2倍になります)。

注意点–コサインを使用してテスト波形を生成し、結果を解釈します–注意する必要があります–位相は、サンプリングを開始したとき(つまり、r [0]を収集したとき)に参照されます。 )、コサインが正しい解釈です)。

上記のコードはエレガントでも効率的でもありません(例:sin / cos値にルックアップテーブルを使用するなど)。

より大きなNを使用すると、結果はより正確になります。サンプルレートと上記のNは互いに倍数ではないため、少し誤差があります。

もちろん、サンプルレート、N、またはfを変更する場合は、コードとkの値を変更する必要があります。DFTビンは、連続周波数ライン上のどこにでもプランクできます。目的の周波数に対応するkの値を使用していることを確認してください。


このアプローチは、Nを調整してkを全体に近づけることによって改善できます。このアルゴリズムの精度を損なう別の回答を投稿しました。
mojuba

10

問題は(非線形)最小二乗問題として定式化できます。

F(ϕ)=12i=1n[Asin(ωi+ϕ)fi(ω)]2

ここで、に対して最小限にする目的関数ですφF(ϕ)ϕ

導関数は非常に単純です:

F(ϕ)=i=1nAcos(ωi+ϕ)[Asin(ωi+ϕ)fi(ω)]

F(ϕ)

明らかに、上記の目的関数は周期性のために複数の最小値を持っているため、他の最小値を区別するためにペナルティ項を追加できます(たとえば、モデル方程式にを追加します)。しかし、最適化は最も近い最小値に収束するだけで、減算した結果を更新できます。 2 πのK K Nϕ22πk,kN


周期性のためにペナルティを課す必要はないと思いますか?あなたはちょうどそれが収束する位相空間でどのような極小取るとmodulu行うことができますなし、?2π
Spacey

@Mohammadはい。ただし、一部の最適化手法では、同じ値に収束する複数の開始点を使用したり、2次式で近似できる単一のグローバルミニマイザーで凸関数を想定したりすることがあります。他の利点は、すべての開始点で同じ結果になるということです。ϕ0
Libor 2012

面白い。この関連する質問にも答えてみませんか?:-)
Spacey

@Mohammad OK、私はそこに少し貢献した:)
Libor

関数fi(w)はどこに行きますか?fi(w)は定数ではないため、非定数の導関数を取得すると、どのようにゼロになりますか?
SamFisher83 2012

5

Goertzelアルゴリズムには、いくつかの異なる公式があります。多くの場合、可能な出力として2つの状態変数(直交または近似)または複素状態変数を提供するものを使用して、中央などのGoertzelウィンドウ内のある点を参照して位相を計算または推定できます。通常、単一のスカラー出力のみを提供するものはできません。

また、Goertzelウィンドウが時間軸との関係でどこにあるかを知る必要があります。

信号がGoertzelウィンドウで正確に整数周期的でない場合、ウィンドウの中央の基準点の周りの位相推定は、位相を最初または最後に参照するよりも正確になる可能性があります。

信号の周波数がわかっている場合、完全なFFTはやりすぎです。さらに、GoertzelはFFT長で周期的でない周波数に調整できますが、FFTは非周期的なウィンドウ周波数に対して追加の補間またはゼロパディングを必要とします。

複雑なGoertzelは、コサインとサインの基底ベクトルまたはFFT回転因子に再帰を使用するDFTの1ビンに相当します。


ωkkk=0

いいえ、wkを追加すると、ウィンドウの最後と非整数の周期的開口正弦波の開始時とでは、フェーズが異なるためです。ただし、1ビンDFTは、同じポイントで単一の円位相を計算します。したがって、3つの値はすべて異なります。しかし、中心位相は、f0が何であっても、常に奇数/偶数関数の比率に関連しています。
hotpaw2

試してみましたが、うまくいきません。
Olli Niemitalo

コサイン(k = 0でのゼロの位相)を使用し、周波数を少し微調整します(小さな無理数により、ただしk = 0での位相は変更しません)。DFTはフェーズが変更されたことを報告します!k = N / 2を正確に中心とするコサインで同じことを試してください。どのdfでもk = N / 2で変化なし。罪やどんなミックスでも同じです。位相基準点を中心にすると、f0の変化に伴う測定位相の変化が少なくなります。例えば、周波数誤差は、位相測定誤差の増加には寄与しません。
hotpaw2

1
はい、正弦波とゲルツェルフィルターの周波数が異なる場合は、ウィンドウの中央で位相推定誤差が小さくなるのは理にかなっています。その場合、ウィンドウの端での位相推定値は、ウィンドウの中心と端の間の距離と、正弦波とゲルツェルのフィルター周波数の差の積である定数によってバイアスされます。このバイアスを差し引くと、中心の推定と同じサイズの誤差が生じますが、正弦波の周波数を知る必要があります。
Olli Niemitalo

4

信号にノイズがなければ、両方でゼロクロッシングを識別し、周波数と相対位相を決定できます。


3

ϕ

f(t)ωω

そう:

  • 「速い」とはどういう意味ですか?
  • 見積もりはどのくらい正確ですか?
  • ϕ
  • 各信号のノイズレベルはどのくらいですか?

f(t)=Asin(ωt+ϕ)f(t)=Asin(ωx+ϕ)


2

開始点:
1)信号と基準正弦波を乗算します:
F(t)
T=π/ω
I(ϕ)=0TF(t)dt =0.5Acos(ϕ)T
ϕ
cos(ϕ)=I(t)/(0.5AT)



ϕ0..(2π)

離散信号の場合は、積分を合計に変更し、T!を慎重に選択します。


1

あなたはこれを(派手な表記で)することもできます:

np.arctan( (signal*cos).sum() / (signal*sin).sum() ))

ここで、signalは位相シフトされた信号で、cosとsinは参照信号です。2つの積を加算することにより、特定の時間の積分の近似を生成します。


0

これは、フラクショナルビンインデックスで単一周波数DFTを使用するという@Kevin McGeeの提案を改善したものです。ケビンのアルゴリズムは素晴らしい結果を生み出しません:ハーフビンとホールビンは非常に正確ですが、全体と半分に近く、それもかなり良いですが、それ以外の場合、エラーは5%以内になる可能性があり、ほとんどのタスクで許容できない可能性があります。

NkN

以下のコードはSwiftにありますが、直感的に明確でなければなりません。

let f = 27.0 // frequency of the sinusoid we are going to generate
let S = 200.0 // sampling rate
let Nmax = 512 // max DFT window length
let twopi = 2 * Double.pi

// First, calculate k for Nmax, and then round it
var k = round(f * Double(Nmax) / S)

// The magic part: recalculate N to make k as close to whole as possible
// We also need to recalculate k once again due to rounding of N. This is important.
let N = Int(k * S / f)
k = f * Double(N) / S

// Generate the sinusoid
var r: [Double] = []
for i in 0..<N {
    let t = Double(i) / S
    r.append(sin(twopi * f * t))
}

// Compute single-frequency DFT
var R = 0.0, I = 0.0
let twopikn = twopi * k / Double(N)
for i in 0..<N {
    let x = Double(i) * twopikn
    R += r[i] * cos(x)
    I += r[i] * sin(x)
}
R /= Double(N)
I /= Double(N)

let amp = 2 * sqrt(R * R + I * I)
let phase = atan2(I, R) / twopi

print(String(format: "k = %.2f    R = %.8f    I = %.8f    A = %.8f    φ/2π = %.8f", k, R, I, amp, phase))

FFTは単にDFTを効率的に計算する方法です。最近のライブラリーでは、2つの制限の力はもはやありません。1つまたは2つのビン値のみが必要な場合は、以前と同じように直接計算することをお勧めします。単一の純粋なトーン(実数または複素数)の場合、周波数、位相、および振幅を正確に計算するには、2つのビン値のみが必要です。dsprelated.com/showarticle/1284.phpを参照してください。数学はかなり洗練されていますが、派生が説明されている記事へのリンクがあります。線形代数は、真の理解のための前提条件です。
Cedron Dawg
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.