Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Звук, графика и видео > Исправление зеркального эффекта у ДПФ


Автор: ivan219 11.11.2008, 20:06
Как избавится от зеркального эфекта в ДПФ smile 

Автор: Alexeis 11.11.2008, 21:07
  Какого еще зеркального эффекта? 

Автор: ivan219 11.11.2008, 23:01
Цитата(Alexeis @  11.11.2008,  21:07 Найти цитируемый пост)
  Какого еще зеркального эффекта? 

С верху как должно быть а снизу получается в итоге: 
user posted image
Применяемый мною код БПФ:
Код

unit fft;
interface
uses Math, Ap, Sysutils;

procedure FastFourierTransform(var a : TReal1DArray; nn : Integer;
 InverseFFT : Boolean);

implementation
uses Unit1;
(*************************************************************************
Быстрое преобразование Фурье

Алгоритм проводит быстрое преобразование Фурье комплексной
функции, заданной nn отсчетами на действительной оси.

В зависимости от переданных параметров, может выполняться
как прямое, так и обратное преобразование.

Входные параметры:
 nn - Число значений функции. Должно быть степенью
   двойки. Алгоритм не проверяет правильность
   переданного значения.
 a - array [0 .. 2*nn-1] of Real
   Значения функции. I-ому значению соответствуют
   элементы a[2*I]  (вещественная  часть)
   и a[2*I+1] (мнимая часть).
 InverseFFT
  - направление преобразования.
   True, если обратное, False, если прямое.
   
Выходные параметры:
 a - результат преобразования. Подробнее см.
   описание на сайте.
*************************************************************************)
procedure FastFourierTransform(var a : TReal1DArray; nn : Integer;
 InverseFFT : Boolean);
var
  Jj, n ,Mmax ,m , j, istep, i, isign: Integer;
  wtemp, wr, wpr, wpi, wi, theta, tempr, tempi: Extended;
begin
 if InverseFFT then isign := -1
 else isign := 1;

 n := 2 * nn;
 j := 1;
 I := 1;
 mmax := 2;
 
 while I <= n do   // Реверс
  begin
   if j > i then
    begin
     tempr := a[j - 1];
     tempi := a[j];
     a[j - 1] := a[i - 1];
     a[j] := a[i];
     a[i - 1] := tempr;
     a[i] := tempi;
    end;
   m := nn;
   while (m >= 2) and (j > m) do
    begin
     j := j - m;
     m := m div 2;
    end;
   j := j + m;
   I := I + 2;
  end;              // Реверс

 while n > mmax do   // FFT
  begin
   istep := 2 * mmax;                 // 4, 8, 16..2 * NN
   theta := 2 * Pi * isign  / mmax;   // Прямое 2 * Pi * (-1) / (2, 4, 8, 16..2 * NN) Обратное 2 * Pi * 1 / (2, 4, 8, 16..2 * NN)
   wpr := -2 * sqr(sin(0.5 * theta)); // Cos(X) - 1
   wpi := sin(theta);                 // Sin(X)
   wr := 1;
   wi := 0;
   M := 1;
   while M <= mmax do
    begin
     for Jj := 0 to (n - m) div istep do
      begin
       i := m + Jj * istep;
       j := i + mmax;
       tempr := wr * a[j - 1] - wi * a[j];
       tempi := wr * a[j] + wi * a[j - 1];
       a[j - 1] := a[i - 1] - tempr;
       a[j] := a[i] - tempi;
       a[i - 1] := a[i - 1] + tempr;
       a[i] := a[i] + tempi;
      end;
     wtemp := wr;
     wr := wr * wpr - wi * wpi + wr;
     wi := wi * wpr + wtemp * wpi + wi;
     M := M + 2;
    end;
   mmax := istep;
  end;                   //FFT

 if InverseFFT then      // Обратное FFT
  for I := 0 to N - 1 do
   a[I] := a[I] / nn; 
end;
end.

Автор: Alexeis 11.11.2008, 23:08
ivan219, нижняя картинка правильная. Так выглядит правильный модуль комплексного спектра. С ним не нужно бороться, он такой какой должен быть.

Автор: ivan219 11.11.2008, 23:18
Цитата(Alexeis @  11.11.2008,  23:08 Найти цитируемый пост)
он такой какой должен быть

Да но он портит всю картину при выводе этого спектра на экран :(

Как тогда быть smile 

Автор: ivan219 12.11.2008, 03:43
Всё вопрос за ненадобностью снимается с повестки дня smile

Автор: Alexeis 12.11.2008, 10:28
Цитата(ivan219 @  11.11.2008,  22:18 Найти цитируемый пост)
Да но он портит всю картину при выводе этого спектра на экран :(

  Выводи его половину. Все так делают.

Автор: ivan219 12.11.2008, 14:23
Цитата(Alexeis @  12.11.2008,  10:28 Найти цитируемый пост)
 Выводи его половину. Все так делают.

Да но тогда мы теряем половину диапазона это для меня не приемлимо!!!

Автор: Alexeis 12.11.2008, 14:54
Цитата(ivan219 @  12.11.2008,  13:23 Найти цитируемый пост)
Да но тогда мы теряем половину диапазона это для меня не приемлимо!!!

  ivan219, учи мат часть. Для идентификации волны нужна частота дискретизации в 2 раза выше ее частоты. При частоте выборок 44100 можно определить амплитуду и фазу волн с частотой не превышающий 22050 (в уравнении 2 неизвестных, для решения нужно 2е точки). Если у тебя блок на 44100 выборки, то половина диапазона это 22050 комплексных спектра, максимально теоретически возможное количество. Как бы ты не выкручивался больше не получиться.

Автор: ivan219 12.11.2008, 15:54
Цитата(Alexeis @  12.11.2008,  14:54 Найти цитируемый пост)
учи мат часть

Вот это правильно!!!

Я совсем запутался и неправильно проводил эксперементы или я и сеёчас ошибаюсь smile 

Цитата(Alexeis @  12.11.2008,  14:54 Найти цитируемый пост)
Если у тебя блок на 44100 выборки, то половина диапазона это 22050

Это я в курсе.

Суть непонятного для меня вопроса вот в чём если уменя есть частота дискретизации 44100 то максимальная частота будет 22050 и если я зделаю БПФ с 1024 осчётами то пик этой частоты будет ровно посередине т.е. 511 да? 
Тоесть унас какбы получается диапазон частот от 0-22050 а после фурье мы получим 0-511 отсчётов этих частот т.е. 0 частота будет принадлежать 0 отсчёту а 22050 будет пренадлежать 511 отсчёту я прав???

Автор: Alexeis 12.11.2008, 16:06
Цитата(ivan219 @  12.11.2008,  14:54 Найти цитируемый пост)
Суть непонятного для меня вопроса вот в чём если уменя есть частота дискретизации 44100 то максимальная частота будет 22050 и если я зделаю БПФ с 1024 осчётами то пик этой частоты будет ровно посередине т.е. 511 да? 
Тоесть унас какбы получается диапазон частот от 0-22050 а после фурье мы получим 0-511 отсчётов этих частот т.е. 0 частота будет принадлежать 0 отсчёту а 22050 будет пренадлежать 511 отсчёту я прав??? 

  Почти так, единственное в чем я не уверен так это в 511 отсчете. Спектр не совсем симметричный. 0й частоты нет в зеркальном спектре справа, он есть только слева, вместо нулевого там 1й. короч нужно проверить руками smile . Сгенерить волну максимальной частоты и проверить будет ли она в спектре или там все таки 22049.

Автор: ivan219 12.11.2008, 16:47
Ну вот наконецто разобрался smile 

Я то думал что весь спектр от 0 до 22050 это от 0 до 1024 отсчёта.

Да и эксперементы проводил коряво тамже массив в 2 раза больше число отсчётов, а какие данные туда загонять нигде не нашол вот и решил что там должно быть чисто непрерывная синусоида т.е. 
Код

Ar[0] := Sin(1);
Ar[1] := Sin(2);
.
.
.

А на самом деле должно быть так:
Код

Ar[0] := Sin(1);
Ar[1] := Sin(1);
Ar[2] := Sin(2);
Ar[3] := Sin(2);
.
.
.

Тогда всё встаёт на свои места smile 

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)