Приветствую Вас Гость!
Четверг, 28.03.2024, 13:04
Главная | Регистрация | Вход | RSS

Advert

Категории раздела

Наш опрос

Оцените мой сайт
Всего ответов: 32

Статистика


Онлайн всего: 1
Гостей: 1
Пользователей: 0

Реклама

Вход на сайт

Меню сайта

Поиск

Друзья сайта

DSA.Statistics

Каталог статей

Главная » Статьи » Цифровая обработка сигналов

Быстрое преобразование Фурье – простой пример на Delphi

В данной статье рассмотрим, как использовать Быстрое преобразование Фурье (БПФ) в своей программе.

Модули с функциями, которые реализуют БПФ, доступны в каталоге файлов.

Для начала работы создадим пустой проект (приложение W32) и добавим в секции “uses” модули “fftbase” и  fftfilterconst” (прописав предварительно путь к ним в меню tools->Environment Options->Library…).

Разместим на форме кнопку (для выполнения генерации тестовых данных и их отображения), и два элемента TPaintBox – PaintBoxSgnl (для отображения тестового сигнала во временной области) и PaintBoxFFT (для отображения результата БПФ).

Общие принципы работы разрабатываемого тестового приложения:

1.     Сгенерируем тестовый сигнал (синус).

2.     Заполним полученными значениями буфер (размером 128 значений).

3.     Выполним отображение сигнала в элементе PaintBoxSgnl.

4.     Выполним преобразование тестового сигнала (БПФ).

5.     Выполним отображение результата БПФ в элементе PaintBoxFFT.

Для начала работы объявим несколько переменных:

 

Глобальные:

 

fDataBuf: array [0..127] of SmallInt; //Буфер для хранения тестового сигнала

 

Сгенерируем тестовый сигнал (синус) и отобразим результаты на экране (по событию – нажатие на кнопку):

 

for i:=0 to 128-1 do //генерация тестового сигнала

  begin

   fDataBuf[i] := 10000*sin(2*Pi*2000*i/180);

  end;

DrawSgnl();

MakeFFT();

DrawFFT();

 

Для отображения тестового сигнала во временной области:

 

procedure DrawSgnl(); //Тестовый сигнал - временное представление

 

Текст процедуры:

 

procedure TForm1.DrawSgnl;

var

 i, tmpX, tmpY: integer;

begin

 PaintBoxSgnl.Canvas.MoveTo(0, PaintBoxSgnl.Height div 2);

 for i:=0 to 128-1 do

  begin

   tmpX := Round(i*PaintBoxSgnl.Width/128);

   tmpY := PaintBoxSgnl.Height div 2 - Round(fDataBuf[i]*PaintBoxSgnl.Height/2/32767);

   PaintBoxSgnl.Canvas.LineTo(tmpX, tmpY);

  end;

end;

 

Непосредственно БПФ и отображение результата:

 

procedure MakeFFT();  //БПФ

 

Текст процедуры:

 

procedure TForm1.MakeFFT;

var

 fftb: TFFTBase; //класс, который реализует БПФ

 fFFTComplBuf: ^TComplexArray;  //Буфер для хранения комплексных величин

 i: integer;

begin

 GetMem(fFFTComplBuf, 128*SizeOf(TComplex)); //Выделение памяти под массив

 for i:=0 to 128-1 do //Заполняем данными массив

  begin

   fFFTComplBuf[i].Re := fDataBuf[i];

   fFFTComplBuf[i].Im := 0;

  end;

 fftb:=TFFTBase.Create(nil);

 //

 //FFT - выполнение БПФ

 //Параметры:

 //указатель на массив данных (с комплексными числами)

 //N - количество данных (размерность массива)

 //2^X=N (степень числа два)

 //False – прямое преобразование; True – обратное

 //Тип окна:

 // 0-прямоугольное

 // 1-треугольное

 // 2-Хэминга

 // 3-Ханна

 // 4-Блэкмана

 //

fftb.FFT(Pointer(fFFTComplBuf), 128, 7, False, 0);

 for i:=0 to 128-1 do //Переносим результат БПФ в исходный массив

  begin

   //заполняем массив выходными значениями (предварительно масштабируем их)

   fDataBuf[i] := Round(fFFTComplBuf[i].Re / 500);

  end;

 fftb.Free;

 FreeMem(fFFTComplBuf, 128*SizeOf(TComplex)); //Освобождение памяти выделенной под массив

end;

 

Отображение результата БПФ:

 

procedure DrawFFT(); //Отображение результата БПФ

 

Текст процедуры:

 

procedure TForm1.DrawFFT;

var

 i, tmpX, tmpY: integer;

begin

 PaintBoxSgnl.Canvas.MoveTo(0, PaintBoxFFT.Height);

 for i:=0 to 128-1 do

  begin

   tmpX := Round(i*PaintBoxFFT.Width/128);

   tmpY := PaintBoxFFT.Height - Round(fDataBuf[i]);

   PaintBoxFFT.Canvas.LineTo(tmpX, tmpY);

  end;

end;

 

Вот собственно и все…

Не так уж и сложно.

 

И еще несколько замечаний:

Результат применения различных типов окон при БПФ можно посмотреть, подставив в последний параметр функции FFT значения от 0 до 4 (см. комментарии).

Результат работы БПФ все-таки комплексный, поэтому в результат вычисляется (в самом модуле) следующим образом:

V=SQRT(Re^2+Im^2)

Если количество данных меньше, чем размер буфера – остаток следует заполнить нулями.

Для вычисления БПФ некоторого набора данных данные последовательно записываются в буфер (буфер построенный по принципу FIFO), после каждого добавления нового значения вычисляется БПФ и отображается результат, после чего значения в буфере сдвигаются на одну позицию. И так пока данные не закончатся J.

 

Полный текст программы доступен в файловом хранилище (FFT_simple.rar).

Категория: Цифровая обработка сигналов | Добавил: Dsa (19.07.2007) | Автор: R.Sem E W
Просмотров: 14847 | Комментарии: 20 | Рейтинг: 4.0/7
Всего комментариев: 20
19 sasha  
0
простите за неграмотность, но программа не компилируется, так как не может распознать модули fftbase и второй, как правильно это устранить?

20 smbcommunity  
0
в путях к библиотекам необходимые файлы прописаны?

17 Виктор П.  
0
Доброго времени суток.

Вы не сравнивали Вашу реализацию алгоритма БПФ с другими по быстродействию? Конкретно, меня интересует, за какое время Ваша реализация выполнит двумерное прямое+обратное фурье матрицы размером 1024х1024. Программист из меня никакой, всякие ухищрения типа распараллеливания потоков данных мне недоступны, но надо фильтровать изображения хотя бы с частотой 25кадров/сек

Виктор П.

18 smbcommunity  
0
Задача по быстродействию не интересовала - но преобразование, по скорости работы, устраивало ...

14 Александр  
0
Спасибо за хорошую статью! Модули работают хорошо, но с небольшой ошибочкой. Сравнил результаты с маткадом, причем смотрел не амплитудный спектр,а отдельно действительные и мнимые составляющие.Численно вроде всё совпадает,но есть различие в знаке мнимой составляющей. В коде самого модуля есть процедура TFFTBase.InitSinCosTbl,в которой идет присвоение fSinTbl[i] := (-1)*Sin(PI/i), наверное ошибка здесь, по крайней мере, убрав множитель (-1) у меня результат совпал с маткадом. Также в модуле есть две процедуры FFT и simpleFFT,которые собственно и вычисляют бпф. Чем они отличаются? На мой взгляд только тем,что в конце FFT в действительную часть закидывается амплитудный спектр,а simpleFFT выдаёт просто действительную и мнимую составляющие. Так зачем было растягивать это на две процедуры? Можно ж было,наверное, и в одной всё сделать. Но это не притензии,а скорее интерес - почему так,а не по-другому. К тому же,я могу ошибаться,если так,то объясните в чем я не прав.
А в целом,благодарю,что выложили, модули пригодились!

15 Dsa  
0
спасибо за отзыв, реализовывал по книжным алгоритмам - использовал для построения сонограммы - поэтому -1 в формуле роли не играет smile но при случае перепроверю...

11 Андрей  
1
Спасибо большое, самая толковая статья во всем рунете. Благодаря ней я разобрался со всеми другими вариациями ФФТ.
p.s. Если бы еще было описано как правильно вывести сетку с конкретными значениями осей, то статье цены не было бы. Автор, сможешь?

12 Dsa  
0
По оси (Х) - конктерніе значения частоты зависят от частоты дискретизации сигнала и окна БПФ - wink простая пропорция, а по (У) - амплитуда (мощность на частоте), если проще сказать.

13 glTrinix  
0
А можно, пожалуйста, конкретнее про пропорцию - что к чему и во сколько раз. Всмысле во сколько раз?

По поводу амплитуды: у меня синус с аплитудой в 5В, однако БПФ дает величину в 80В, что в 16 раз больше.

Спасибо большое за оперативность.


16 Dsa  
0
в любом случае можно дополнительно нормализовать... вопросом таким не задавался - меня интересовало соотношение частот также модуль был исп для создания эквалайзера

9 LIN  
0
А вы не подскажите где можно хорошую теорию прочитать,почему получается 2пика?
и почему при расстяжении синуса у нас расстояние между 2-мя пиками уменьшается?

10 Dsa  
0
Преобразование Фурье - по шкале х - частота, а по у - мощность. В результате работы программы берем только половину массива значений (вторую). Чем больше частота - тем пик удаляется в лево во второй половине и вправо в первой половине (результат условно поделите на две ровные части...)
http://ru.wikipedia.org/wiki/Быстрое_преобразование_Фурье

6 чирл  
0
Почитай как надо бороться с зеркальным ефектом

8 Dsa  
0
Что Вы имели ввиду?

5 Блонди  
0
а можно по конкретнее про модули fftbase и fftfilterconst и как их правильнее прописать....

7 Dsa  
0
В настройках IDE - там где прописываются пути к библиотекам

3 Hammer  
0
Еще бы кто объяснил на пальцах БПФ... А то я только непрерывное проходил...

4 Dsa  
0
была одна книжка интересная - там на пальцах все было объяснено... нет жаль под рукой. поищите в интернете...

1 Hammer  
0
А почему 2 пика получается?

2 Dsa  
0
Их действительно два, читайте Теорию преобразования Фурье - такое оно есть... состоит из двух симетричных частей.

Добавлять комментарии могут только зарегистрированные пользователи.
[ Регистрация | Вход ]
puEnt1