реклама на сайте
подробности

 
 
> Окна БПФ
ViKo
сообщение Oct 2 2013, 12:55
Сообщение #1


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Хочу задать несколько разных оконных функций при вычислении БПФ в своем устройстве. И уже на треугольном озадачился. Возьмем для простоты БПФ по 8 точкам. Трегольное окно спадает от 1 в середине до 0 на краях. Какой отсчет будет умножен на 1 - 3-й, 4-й, оба, никакой? Ведь вершина треугольника попадает между отсчетами - слева 4 и справа 4. Понятно, что при 1024 точках это почти не важно, но все равно напрягает. Тот же вопрос распространяется и на все остальные окна.
Go to the top of the page
 
+Quote Post
2 страниц V   1 2 >  
Start new topic
Ответов (1 - 22)
ivan219
сообщение Oct 2 2013, 13:16
Сообщение #2


Местный
***

Группа: Участник
Сообщений: 350
Регистрация: 16-11-08
Пользователь №: 41 680



Я так думаю что вот так -> 0 1 2 3 4 3 2 1 или так -> 1 2 3 4 3 2 1 0 будет правильно.

Сообщение отредактировал ivan219 - Oct 2 2013, 13:17
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 2 2013, 13:53
Сообщение #3


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Вот здесь что-то пишут, но не могу понять, что. rolleyes.gif
http://en.wikipedia.org/wiki/Window_function
Симметричное окно мне нравится больше.
И на 0 крайнюю точку умножать... жалко.
Go to the top of the page
 
+Quote Post
SemperAnte
сообщение Oct 3 2013, 06:59
Сообщение #4


Частый гость
**

Группа: Свой
Сообщений: 89
Регистрация: 24-10-10
Из: Санкт-Петербург
Пользователь №: 60 386



На ноль умножать и не надо.

Для этих целей всегда пользуюсь Матлабом.
Например, для 8-точечного окна матлаб-функция triang(8) выдаёт следующие коэффициенты:
0.1250
0.3750
0.6250
0.8750
0.8750
0.6250
0.3750
0.1250.

Там же, в справке есть и формулы для всех окон. Для треугольного, кстати, они разные для чётного и нечётного количества точек.
Go to the top of the page
 
+Quote Post
V_G
сообщение Oct 3 2013, 07:19
Сообщение #5


Профессионал
*****

Группа: Свой
Сообщений: 1 818
Регистрация: 15-10-09
Из: Владивосток
Пользователь №: 52 955



2 ViKo:
Вам точно нужно именно БПФ? Дело в том, что БПФ становится "быстрым" в сравнении с классическим ДПФ при числе точек > 64.
Зачем вообще вычислять спектр (через ДПФ или БПФ) по 8 точкам?
А если точек много, то умножать на 0 по краям не жалко.
Go to the top of the page
 
+Quote Post
thermit
сообщение Oct 3 2013, 08:14
Сообщение #6


Знающий
****

Группа: Участник
Сообщений: 781
Регистрация: 3-08-09
Пользователь №: 51 730



Цитата
V_G:
Дело в том, что БПФ становится "быстрым" в сравнении с классическим ДПФ при числе точек > 64.


Это вы погорячились...
Даже для 4-х точек бпф быстрое в сравнении с явным дпф.
Вообще-то для любого числа точек >2 можно построить алгоритм, который будет быстрее явного дпф.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 3 2013, 09:12
Сообщение #7


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



БПФ быстрее ДПФ. 8 точек - это только для примера. Делаю на 1024 (в принципе, #define пределяет).

Цитата(SemperAnte @ Oct 3 2013, 09:59) *
Для этих целей всегда пользуюсь Матлабом.
Например, для 8-точечного окна матлаб-функция triang(8) выдаёт следующие коэффициенты:
...
Там же, в справке есть и формулы для всех окон. Для треугольного, кстати, они разные для чётного и нечётного количества точек.

Такие коэффициенты и выбрал, симметричные. Мне не нужно их в виде таблицы иметь. Пусть микроконтроллер сам вычисляет по формуле (уже вычисляет, но я еще не смотрел результаты).

Возникает вопрос, какой же коэффициент (как он там называется, ослабления?) получается при использовании окон.
upd. Ага, сложить все к-ты и поделить на размер БПФ. Так, похоже...
Go to the top of the page
 
+Quote Post
SemperAnte
сообщение Oct 3 2013, 11:32
Сообщение #8


Частый гость
**

Группа: Свой
Сообщений: 89
Регистрация: 24-10-10
Из: Санкт-Петербург
Пользователь №: 60 386



Вот готовая формула, которую использует Матлаб, для расчёта треугольного окна:

http://www.mathworks.com/help/signal/ref/t...ighlight=triang

Здесь можно найти формулы для других окон:

http://www.mathworks.com/help/signal/windows.html
Go to the top of the page
 
+Quote Post
Alex11
сообщение Oct 3 2013, 15:59
Сообщение #9


Гуру
******

Группа: Свой
Сообщений: 2 106
Регистрация: 23-10-04
Из: С-Петербург
Пользователь №: 965



По поводу коэффициента при использовании окна. там, поскольку энергия, как я помню, cумма квадратов коэффициентов окна должна быть равна 1, чтобы окно не влияло. Если не получится - напишите в личку, я в свое время это делал точно, посмотрю материалы старинные.
Go to the top of the page
 
+Quote Post
Ruslan1
сообщение Oct 3 2013, 19:57
Сообщение #10


Гуру
******

Группа: Свой
Сообщений: 2 360
Регистрация: 6-03-06
Из: Кишинев
Пользователь №: 15 025



Я вот такое использую. Коэффициент альфа и форму окна подбирал в матлабе во время анализа реальных данных, характерных для исследуемого сигнала. Думаю, принцип понятен.

%% windowing
alpha = 4.05
for i=1:FFT_N_SAMPLES
%Gaussian:
tmp_n = abs(i - (FFT_N_SAMPLES)/2);
tmp = alpha * tmp_n / (FFT_N_SAMPLES/2);
coeff = exp(-0.5 * tmp*tmp);
data_win(i) = data_in(i) * coeff;
end
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 4 2013, 11:59
Сообщение #11


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Сделал, что мог. Использую Matlab. Окна по умолчанию получаются симметричными, что мне нравится. Результат расчетов выводится в файл, который включу в проект. Только запятую лишнюю в конце каждого массива нужно удалить.
Код
FFT_N = 8;
WindHann = hann(FFT_N);
WindHamm = hamming(FFT_N);
WindBart = bartlett(FFT_N);

fid = fopen('FFT_Windows.h', 'w');

fprintf(fid, '/* Hann Window */\n');
fprintf(fid, 'static const float WindHann[] = {\n');
fprintf(fid, '  %E, %E, %E, %E,\n', WindHann);
fprintf(fid, '};\n\n');

fprintf(fid, '/* Hamming Window */\n');
fprintf(fid, 'static const float WindHamm[] = {\n');
fprintf(fid, '  %E, %E, %E, %E,\n', WindHamm);
fprintf(fid, '};\n\n');

fprintf(fid, '/* Bartlett Window */\n');
fprintf(fid, 'static const float WindBart[] = {\n');
fprintf(fid, '  %E, %E, %E, %E,\n', WindBart);
fprintf(fid, '};\n\n');

fclose(fid);
Go to the top of the page
 
+Quote Post
mdmitry
сообщение Oct 4 2013, 13:27
Сообщение #12


Начинающий профессионал
*****

Группа: Свой
Сообщений: 1 215
Регистрация: 25-10-06
Из: СПб
Пользователь №: 21 648



Можно отказаться от правильного использования MATLAB и сделать явный цикл по выводу каждого элемента массива или в строку нескольких элементов. И проверку на открытие файлов лучше делать.

Рабочий порезаный пример вывода:
CODE

clc
clear

DataLength = 64;

fdirstr = 'C:\\tmp\\';
filestr = 'data';
fileextstr = '.h';

datafname = strcat(fdirstr,filestr,fileextstr);
[fid1,message] = fopen(datafname,'w');
if fid1 == -1
errordlg(message,'FILE OPEN ERROR');
else
fprintf(fid1,'/***********************************************************/');
fprintf(fid1,'\n/* Date: %s*/',datestr(now,0));
fprintf(fid1,'\n/***********************************************************/\n');
str = strcat(filestr,'_H_');
fprintf(fid1,'\n#ifndef %s',upper(str));
fprintf(fid1,'\n#define %s\n',upper(str));

fprintf(fid1,'\nconst uint32_t data[%i] = \n\t{',DataLength);
for i=1:DataLength
% здесь вывод того, что требуется, для примера поэлементно.
fprintf(fid1,'\n\t\t0x%04X',i);
% немного сложнее будет с расчетом необходимых индексов и форматом при выводе нескольких элементов массива в одной строке
if i ~= DataLength
fprintf(fid1,',');
end
end
fprintf(fid1,'\n\t};\n\n');
fprintf(fid1,'#endif /* %s */\n',upper(str));
end

if fid1 ~= -1
status = fclose(fid1);
if status == -1
errstr = strcat('Can not close file: ',datafname);
errordlg(errstr,'FILE CLOSE ERROR');
end
end



--------------------
Наука изощряет ум; ученье вострит память. Козьма Прутков
Go to the top of the page
 
+Quote Post
AndrewN
сообщение Oct 6 2013, 07:26
Сообщение #13


Местный
***

Группа: Участник
Сообщений: 336
Регистрация: 7-03-07
Из: Петербург
Пользователь №: 25 961



QUOTE (ViKo @ Oct 2 2013, 15:55) *
Трегольное окно спадает от 1 в середине до 0 на краях. Какой отсчет будет умножен на 1 - 3-й, 4-й, оба, никакой? Ведь вершина треугольника попадает между отсчетами - слева 4 и справа 4. Понятно, что при 1024 точках это почти не важно, но все равно напрягает. Тот же вопрос распространяется и на все остальные окна.
Hi there :)

Это писофкейк! :) Симметричная функция, по определению, обладает свойством f(x) = f(-x), для сдвинутого на (N-1)/2 интервала и целых x это свойство симметрии станет просто f(k) = f(N-k-1). Отсюда, при N=8, следует что f(3) = f(4), а в случае нечётного N есть единственный индекс без пары, k = (N-1)/2.

Оконная функции вовсе не обязательно должна обнуляться на границе интервала; достаточно быть нормированной, что бы мощность сигнала не менялясь, т.е. SUM(k=0, N-1) w(k) = 1.

Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 6 2013, 08:01
Сообщение #14


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(AndrewN @ Oct 6 2013, 10:26) *
Оконная функции вовсе не обязательно должна обнуляться на границе интервала; достаточно быть нормированной, что бы мощность сигнала не менялясь, т.е. SUM(k=0, N-1) w(k) = 1.

Все оконные функции БПФ приближаются к 1 в середине диапазона, и к 0 на краях (чтобы ослабить разрывы). Почему сразу не нормируются, как вы предлагаете? - видимо, из-за того, что числа слишком малыми становятся. Сейчас, для плавающей запятой это уже не важно...
Go to the top of the page
 
+Quote Post
AndrewN
сообщение Oct 6 2013, 09:08
Сообщение #15


Местный
***

Группа: Участник
Сообщений: 336
Регистрация: 7-03-07
Из: Петербург
Пользователь №: 25 961



QUOTE (ViKo @ Oct 6 2013, 12:01) *
Все оконные функции БПФ приближаются к 1 в середине диапазона, и к 0 на краях (чтобы ослабить разрывы). Почему сразу не нормируются, как вы предлагаете? - видимо, из-за того, что числа слишком малыми становятся. Сейчас, для плавающей запятой это уже не важно...
К нулю по краям - для ослабления боковых лепестков, задавить sinc() от прямоугольного окна.

Формула нормировки - я её в математическом смысле имел, а так, при работе с фиксированной точкой, конечно, имеет смысл сохранять как можно больше битиков в промежуточных числах, а нормировать и округлять в самом конце. Консенсус. sm.gif
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 15 2013, 21:02
Сообщение #16


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Окна имеют коэффициент ослабления, показывающий, во сколько раз при БПФ будет отличаться постоянная составляющая, по сравнению с прямоугольным окном. Но при этом значения всех остальных спектральных составляющих тоже изменяются. Как можно верить этим окнам? И, вообще, ДПФ?
Я, правда, экспериментировал с 16-точечным БПФ. Подал точно рассчитанный по формуле сигнал, с частотами, точно укладывающимися в размер БПФ. Поэтому прямоугольное окно дает мне точные амплитуды спектральных составляющих. Остальные же окна выдают амплитуды, отличающиеся в несколько раз от поданных.
Может, при размере БПФ 1024 такого явления не будет? Сомневаюсь.
Go to the top of the page
 
+Quote Post
petrov
сообщение Oct 16 2013, 09:18
Сообщение #17


Гуру
******

Группа: Свой
Сообщений: 2 220
Регистрация: 21-10-04
Из: Balakhna
Пользователь №: 937



Цитата(ViKo @ Oct 16 2013, 01:02) *
Окна имеют коэффициент ослабления, показывающий, во сколько раз при БПФ будет отличаться постоянная составляющая, по сравнению с прямоугольным окном. Но при этом значения всех остальных спектральных составляющих тоже изменяются. Как можно верить этим окнам? И, вообще, ДПФ?
Я, правда, экспериментировал с 16-точечным БПФ. Подал точно рассчитанный по формуле сигнал, с частотами, точно укладывающимися в размер БПФ. Поэтому прямоугольное окно дает мне точные амплитуды спектральных составляющих. Остальные же окна выдают амплитуды, отличающиеся в несколько раз от поданных.
Может, при размере БПФ 1024 такого явления не будет? Сомневаюсь.


FFT c окнами это всего лишь банк фильтров на картинке по ссылке
https://ccrma.stanford.edu/~jos/sasp/Downsa...ilter_Bank.html
Окно - ИХ КИХ ФНЧ. Хотите точно амплитуду синуса мерить, используйте фильтры с плоскими вершинами АЧХ перекрывающимися, так называемые flat top window, в общем обсуждалось уже на форуме.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 16 2013, 11:30
Сообщение #18


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(petrov @ Oct 16 2013, 12:18) *
Хотите точно амплитуду синуса мерить, используйте фильтры с плоскими вершинами АЧХ перекрывающимися, так называемые flat top window, в общем обсуждалось уже на форуме.

У меня есть окно FlatTop. Для 16-точечного БПФ тоже сильно врет.
Go to the top of the page
 
+Quote Post
petrov
сообщение Oct 16 2013, 11:45
Сообщение #19


Гуру
******

Группа: Свой
Сообщений: 2 220
Регистрация: 21-10-04
Из: Balakhna
Пользователь №: 937



Цитата(ViKo @ Oct 16 2013, 15:30) *
У меня есть окно FlatTop. Для 16-точечного БПФ тоже сильно врет.


Ну так всё в ваших руках, в один фильтр попадает несколько гармоник, имеем соответствующий результат, амплитудой отдельной гармоники это не является.
Go to the top of the page
 
+Quote Post
Alex11
сообщение Oct 17 2013, 15:33
Сообщение #20


Гуру
******

Группа: Свой
Сообщений: 2 106
Регистрация: 23-10-04
Из: С-Петербург
Пользователь №: 965



Чтобы получать правильный ответ с окнами, нужно брать корень из суммы квадратов некоторой части отсчетов около рассчитываемой гармоники. Если хвосты от гармоник перекрываются, то точный расчет невозможен. Сколько брать отсчетов - зависит от формы окна и требуемой точности.
Go to the top of the page
 
+Quote Post
Tiro
сообщение Oct 17 2013, 21:59
Сообщение #21


Знающий
****

Группа: Свой
Сообщений: 781
Регистрация: 3-10-04
Из: Санкт-Петербург
Пользователь №: 768



Маленькое примечание. Есть некоторые методические тонкости, которые почему-то все забывают.

1) ПФ от сигнала конечной длительности вычисляется в предположении, что это и был период образа сигнала. Это не так, это первое. Склейте хотя бы имеющуюся выборку с собой и увидите, от чего берете ПФ.

2) Наложение окна во временной области приводит к свертке ПФ сигнала и окна в спектральной. Но это не означает, что мы просто отфильтровали целиком все ПФ сигнала при помощи некоего фильтра. ПФ это расчет по каждой частотной компоненте и именно каждая компонента фильтруется оконной функцией, вычисленной для данной компоненты. Иначе окна не улучшали бы ПФ в полосе сигнала.

Типа резюме: способы с наложением окон хороши, но только для выборок статистически определенных сигналов. На детерминированных сигналах они тоже работают, но совсем иначе.
Go to the top of the page
 
+Quote Post
ViKo
сообщение Oct 18 2013, 10:43
Сообщение #22


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Я именно на целом количестве периодов и экспериментировал (вместо нулей подставлял числа - амплитуды). Окна для того и нужны, чтобы уменьшить последствия непериодичности.
Код
void Sig_load(void) {
  volatile float *pSig = Sig;
  for (uint32_t i = 0; i < FFT_N; i++) {
    *pSig++ = 1
            + 0 * sin(1 * i * 2 * PI / FFT_N)
            + 0 * sin(2 * i * 2 * PI / FFT_N + 3 * PI / 4)
            + 0 * sin(4 * i * 2 * PI / FFT_N);
  }
}
Go to the top of the page
 
+Quote Post
ViKo
сообщение Jan 22 2014, 09:58
Сообщение #23


Универсальный солдатик
******

Группа: Модераторы
Сообщений: 8 634
Регистрация: 1-11-05
Из: Минск
Пользователь №: 10 362



Цитата(ViKo @ Oct 4 2013, 14:59) *
Сделал, что мог. Использую Matlab. Окна по умолчанию получаются симметричными, что мне нравится. Результат расчетов выводится в файл, который включу в проект. Только запятую лишнюю в конце каждого массива нужно удалить.
Код
FFT_N = 8;
...
fid = fopen('FFT_Windows.h', 'w');

fprintf(fid, '/* Hann Window */\n');
fprintf(fid, 'static const float WindHann[] = {\n');
fprintf(fid, '  %E, %E, %E, %E,\n', WindHann);
fprintf(fid, '};\n\n');
...
fprintf(fid, '};\n\n');
fclose(fid);

Поможите, люди добрые, убрать запятую в конце массива в текстовом файле, созданном этим скриптом! В языке C она лишняя.
Если сложно, то не надо. rolleyes.gif Руками удалю. Но, может, есть элегантный способ?

Сам придумал.
Код
fseek(fid, -2, 0);
fprintf(fid, '\n};\n');
Go to the top of the page
 
+Quote Post

2 страниц V   1 2 >
Reply to this topicStart new topic
1 чел. читают эту тему (гостей: 1, скрытых пользователей: 0)
Пользователей: 0

 


RSS Текстовая версия Сейчас: 23rd July 2025 - 13:54
Рейтинг@Mail.ru


Страница сгенерированна за 0.01586 секунд с 7
ELECTRONIX ©2004-2016