с алгоритмом Герцеля,
взял тут: http://www.dsplib.ru/content/goertzel/goertzel.html
Код
int main(){
// исходные данные
int N = 8; //точек ДПФ
int k = 1; //номер спектрального отсчта
//исходный сигнал
double s[8] = {3, 2, 1, -1, 1, -2, -3, -2};
//массив промежуточных результатов
double v[8] = {0, 0, 0, 0, 0, 0, 0, 0};
//параметр альфа
double a = 2*cos(2*M_PI*k/N);
//поворотный к-т W_N^-k
double wr = cos(2*M_PI*k/N); //реальная часть
double wi = sin(2*M_PI*k/N); //мнимая часть
//учет v[-1] = v[-2] = 0
v[0] = s[0];
v[1] = s[1]+a*v[0];
// итерационный расчет массива v согласно (14)
for(int i = 2; i < N; i++)
v[i] = s[i] + a*v[i-1] - v[i-2];
//реальная и мнимая части спектрального отсчета S(1) согласно (13)
double SR = v[N-1]*wr-v[N-2];
double SI = v[N-1]*wi;
//печать результата
printf("S(%d) = %.4f%+.4fj\n",k,SR,SI);
system("Pause");
return 0;
}
// исходные данные
int N = 8; //точек ДПФ
int k = 1; //номер спектрального отсчта
//исходный сигнал
double s[8] = {3, 2, 1, -1, 1, -2, -3, -2};
//массив промежуточных результатов
double v[8] = {0, 0, 0, 0, 0, 0, 0, 0};
//параметр альфа
double a = 2*cos(2*M_PI*k/N);
//поворотный к-т W_N^-k
double wr = cos(2*M_PI*k/N); //реальная часть
double wi = sin(2*M_PI*k/N); //мнимая часть
//учет v[-1] = v[-2] = 0
v[0] = s[0];
v[1] = s[1]+a*v[0];
// итерационный расчет массива v согласно (14)
for(int i = 2; i < N; i++)
v[i] = s[i] + a*v[i-1] - v[i-2];
//реальная и мнимая части спектрального отсчета S(1) согласно (13)
double SR = v[N-1]*wr-v[N-2];
double SI = v[N-1]*wi;
//печать результата
printf("S(%d) = %.4f%+.4fj\n",k,SR,SI);
system("Pause");
return 0;
}
и алгоритмом FFT для одной частоты
взял тут: http://forum.sources.ru/index.php?showtopi...showall&hl=
Код
function FT(w:Real; N:Integer; a:PReal):Complex;Overload;
var i:Integer;
begin
Result.Re:=0;
Result.Im:=0;
for i:=0 to N-1 do
begin
Result.Re:=Result.Re+A[i]*Cos(-2*Pi*i*w/N);
Result.Im:=Result.Im+A[i]*Sin(-2*Pi*i*w/N);
end;
Result.Re:=Result.Re/N;
Result.Im:=Result.Im/N;
end;
var i:Integer;
begin
Result.Re:=0;
Result.Im:=0;
for i:=0 to N-1 do
begin
Result.Re:=Result.Re+A[i]*Cos(-2*Pi*i*w/N);
Result.Im:=Result.Im+A[i]*Sin(-2*Pi*i*w/N);
end;
Result.Re:=Result.Re/N;
Result.Im:=Result.Im/N;
end;
По второй ссылке взял и перевод частей сигнала в реальную амплитуду и фазу.
Код
Faza:=arctan2(С.Im,С.Re); // Фаза
Amp:=hypot(C.Re, C.Im); // Амплитуда.
Amp:=hypot(C.Re, C.Im); // Амплитуда.
Взял 256 отсчетов синусоидального сигнала.
Фазы сошлись - не знаю на сколько реально :-)
Амплитуда после расчета по FFT га 15..20% ниже RMS напряжения который показывает осциллограф.
То есть амплитуда для этого метода корректна.
А по методу Герцеля получается число в ~500 раз больше.
Я читал, что алгоритм Герцеля работает неустойчиво при большой длине выборок. Может в этом вопрос?