Наши проекты:
Журнал · Discuz!ML · Wiki · DRKB · Помощь проекту |
||
ПРАВИЛА | FAQ | Помощь | Поиск | Участники | Календарь | Избранное | RSS |
[3.236.86.184] |
|
Страницы: (3) [1] 2 3 все ( Перейти к последнему сообщению ) |
Сообщ.
#1
,
|
|
|
У меня возникла следующая трабла:
Решил поработать со звуком, но когда юзаю БПФ, то спектр у меня получается симетричный . Не могу понять с чем это связано. Что я делаю не так? unit Unit1; interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, ExtCtrls, ComCtrls, MMSystem, TeeProcs, TeEngine, Chart, Series, ap, fft; const freq=44100; BufSize=2048; Xgraph=512; Ygraph=100; type TData16 = array [0..BufSize-1] of smallint; PData16 = ^TData16; TPointArr = array [0..BufSize-1] of TPoint; PPointArr = ^TPointArr; TForm1 = class(TForm) Button1: TButton; Button2: TButton; PaintBox1: TPaintBox; Chart1: TChart; Chart2: TChart; Series2: TBarSeries; procedure Button1Click(Sender: TObject); procedure Button2Click(Sender: TObject); procedure FormDestroy(Sender: TObject); procedure FormCreate(Sender: TObject); private { Private declarations } public procedure OnWaveIn(var Msg: TMessage); message MM_WIM_DATA; end; var Form1: TForm1; series1, series2 : tlineSeries; coef: array of integer; a,b: TReal1DArray; implementation {$R *.DFM} var WaveIn: hWaveIn; hBuf: THandle; BufHead: TWaveHdr; p: PPointArr; stop: boolean = false; comp:complex; function modul(const comp:complex):double; begin result:=sqrt(sqr(comp.x)+sqr(comp.y)); end; procedure TForm1.Button1Click(Sender: TObject); var header: TWaveFormatEx; BufLen: word; buf: pointer; begin with header do begin wFormatTag := WAVE_FORMAT_PCM; nChannels := 2; { количество каналов } nSamplesPerSec := freq; { частота } wBitsPerSample := 16; { 8 / 16 бит } nBlockAlign := nChannels * (wBitsPerSample div 8); nAvgBytesPerSec := nSamplesPerSec * nBlockAlign; cbSize := 0; end; WaveInOpen(Addr(WaveIn), WAVE_MAPPER, addr(header), Form1.Handle, 0, CALLBACK_WINDOW); BufLen := header.nBlockAlign * BufSize; hBuf := GlobalAlloc(GMEM_MOVEABLE and GMEM_SHARE, BufLen); Buf := GlobalLock(hBuf); with BufHead do begin lpData := Buf; dwBufferLength := BufLen; dwFlags := WHDR_BEGINLOOP; end; WaveInPrepareHeader(WaveIn, Addr(BufHead), sizeof(BufHead)); WaveInAddBuffer(WaveIn, addr(BufHead), sizeof(BufHead)); GetMem(p, BufSize * sizeof(TPoint)); stop := true; WaveInStart(WaveIn); end; procedure TForm1.Button2Click(Sender: TObject); begin if stop = false then Exit; stop := false; while not stop do Application.ProcessMessages; stop := false; WaveInReset(WaveIn); WaveInUnPrepareHeader(WaveIn, addr(BufHead), sizeof(BufHead)); WaveInClose(WaveIn); GlobalUnlock(hBuf); GlobalFree(hBuf); FreeMem(p, BufSize * sizeof(TPoint)); end; procedure TForm1.OnWaveIn; var i,j: integer; data16: PData16; XScale, YScale: single; begin XScale := Xgraph / BufSize; data16 := PData16(PWaveHdr(Msg.lParam)^.lpData); YScale := Ygraph / (1 shl 16); series1.Clear; for i := 0 to BufSize-1 do begin p^[i] := Point(round(i * XScale), round(Ygraph / 2 - data16^[i] * YScale)); series1.AddXY(round(i * XScale), round(Ygraph / 2 - data16^[i] * YScale)); a[2*i]:=round(Ygraph / 2 - data16^[i] * YScale); a[2*i+1]:=0; end; FastFourierTransform(a, BufSize, false); series2.clear; for j :=1 to BufSize-1 do begin // comp.X:= a[2*j]; // comp.Y:=a[2*j+1]; b[j]:=sqrt(a[2*j]*a[2*j]+a[2*j+1]*a[2*j+1]); series2.AddXY(coef[j],b[j]); end; with PaintBox1.Canvas do begin Brush.Color := clWhite; FillRect(ClipRect); Polyline(Slice(p^, BufSize)); end; if stop then WaveInAddBuffer(WaveIn, PWaveHdr(Msg.lParam), SizeOf(TWaveHdr)) else stop := true; end; procedure TForm1.FormDestroy(Sender: TObject); begin Button2.Click; Finalize(a); Finalize(b); Finalize(coef); end; procedure TForm1.FormCreate(Sender: TObject); var i: integer; XScale: single; begin series1 := tlineSeries.Create(nil); series1.ParentChart := Chart1; series1.Clear; setlength(a,2*BufSize); setlength(b,BufSize); setlength(coef,BufSize); XScale := Xgraph / BufSize; for I := 0 to BufSize-1 do coef[i]:=round(i * XScale); Button1.Caption := 'Start'; Button2.Caption := 'Stop'; end; end. Добавлено Сигнал беру с микрофона! |
Сообщ.
#2
,
|
|
|
Вот екзешник:
Прикреплённый файлProject1.rar (307.54 Кбайт, скачиваний: 477) |
Сообщ.
#3
,
|
|
|
Вообще-то так и должно быть.
|
Сообщ.
#4
,
|
|
|
Цитата andriano @ Вообще-то так и должно быть. Тада у меня вопрос. Неужто БПФ возвращает спектр в таком виде: 5г, 10г, 15г, ... 10кг, 15кг, 15кг, 10кг, ...15г, 10г, 5г??? (числа проставил условно) З.Ы. Изначально у меня все выходило норм(в моем понимании нормально), но потом я начал экспериментировать с размером буфера, количеством каналов, частотой... и стало так как есть сейчас. Вернуть как было у меня не получается |
Сообщ.
#5
,
|
|
|
Цитата Тада у меня вопрос. Неужто БПФ возвращает спектр в таком виде: 5г, 10г, 15г, ... 10кг, 15кг, 15кг, 10кг, ...15г, 10г, 5г??? (числа проставил условно) Такое у него, у БПФ, свойство. |
Сообщ.
#6
,
|
|
|
Комплексный БПФ он и есть симметричный. Отруби ненужную часть арифметически и получишь то что нужно. И еще, чей то на спектре нулевая частота разлезлась по краям спектра (т.е. симметрия наоборот, собственно математически они так и выглядят), но думаю и это организовать можно, перенеся выборку N/2...2*N-1 после БПФ в начало графика, а 0...N/2-1 за ней.
|
Сообщ.
#7
,
|
|
|
Цитата ХЭМ @ Комплексный БПФ он и есть симметричный. Отруби ненужную часть арифметически и получишь то что нужно. И еще, чей то на спектре нулевая частота разлезлась по краям спектра (т.е. симметрия наоборот, собственно математически они так и выглядят), но думаю и это организовать можно, перенеся выборку N/2...2*N-1 после БПФ в начало графика, а 0...N/2-1 за ней. Как я понял то выборка 0..N/2 - это и есть мой искомый спектр. Я просто игнорирую вторую часть масива который вернул FFT. З.Ы. Если все верно, то что нам даст если мы перенесем выборку N/2...2*N-1 после БПФ в начало графика, а 0...N/2-1 будет за ней? |
Сообщ.
#8
,
|
|
|
BFenix
Мы получим частоты в виде -N/2-1,...,-3,-2,-1,0,1,2,3,..., N/2-1 Отрицательная чатота тоже чатсота. Если взять цекличискую частоту то знак просто определяет направленияе вращения по частовой стрелки или против. Просто если переставить то так лучши смотриться. 0 Начало отсчета находиться по середине. Аналогично если перед прообразованием домножить на (-1)^i i- номер отсчета, то получим аналогичную перестановку. Свойства дублирования чатот можно использовать для двух вещей. Первое это убрать мнимые части внутрь массива, сэкономить место. И тем самым еще и ускорить. Тогда имея массив отсчетов их действительные части мы можем сразу получить упаковонное представление преобразования в этом же массиве. В виде Re0, Re(N/2-), Re1,Im1, Re2,Im2 Подробнее читай про реальное преобразование фурье. На этом сайте в алгоритмах. Или же загнать сразу два сигнала в один массив и использовать одино преобразования для двух сигналов. |
Сообщ.
#9
,
|
|
|
BFenix,
точнее: -15000,-14995,-14990,...-10б-5,0,5,10,15,...14990,14995,15000, т.к. ширины всех полос одинаковы. И желательно не отбрасывать "лшние" отсчеты, а посчитать модуль. |
Сообщ.
#10
,
|
|
|
Цитата andriano @ BFenix, точнее: -15000,-14995,-14990,...-10б-5,0,5,10,15,...14990,14995,15000, т.к. ширины всех полос одинаковы. И желательно не отбрасывать "лшние" отсчеты, а посчитать модуль. У меня задача состоит вот в чем: мне надо слушать работу преса(большой прес который давит ДСП). Прес не правильно настроен и потому останавливается с ударом. Я должен услышать этот удар и сказать, что удар точно был(возможно сравнение с предыдущими ударами по силе). Как я понимаю, то мне надо смотреть спектр и фиксировать всплески. После первого цикла я зафиксирую частоту на которой всплеск при ударе и дальше буду смотреть только некий диапазон спектра. Сигнал буду брать не с микрофона, а с пьезоэлемента. З.Ы. Подскажите моя задумка правильная или я чтото упустил? |
Сообщ.
#11
,
|
|
|
Цитата Мы получим частоты в виде -N/2-1,...,-3,-2,-1,0,1,2,3,..., N/2-1 Получается всего N-1 значений вместо N. Вроде частоты после БПФ(комплексного)получаются в виде: 0,1,2,3,...N/2-1, -N/2,-N/2-1,...-3,-2,-1. Или я совсем неправ? -Added Цитата BFenix @ Цитата andriano @ BFenix, точнее: -15000,-14995,-14990,...-10б-5,0,5,10,15,...14990,14995,15000, т.к. ширины всех полос одинаковы. И желательно не отбрасывать "лшние" отсчеты, а посчитать модуль. У меня задача состоит вот в чем: мне надо слушать работу преса(большой прес который давит ДСП). Прес не правильно настроен и потому останавливается с ударом. Я должен услышать этот удар и сказать, что удар точно был(возможно сравнение с предыдущими ударами по силе). Как я понимаю, то мне надо смотреть спектр и фиксировать всплески. После первого цикла я зафиксирую частоту на которой всплеск при ударе и дальше буду смотреть только некий диапазон спектра. Сигнал буду брать не с микрофона, а с пьезоэлемента. З.Ы. Подскажите моя задумка правильная или я чтото упустил? Имхо, конечно. Насчёт пьезо. Для него схему придётся собирать. И калибровать как-то нужно. А крепить как.... Может, поискать готовый датчик? И вот ещё, может быть эта страничка будет вам интересна. |
Сообщ.
#12
,
|
|
|
Цитата Prince @ Цитата Вроде частоты после БПФ(комплексного)получаются в виде: 0,1,2,3,...N/2-1, -N/2,-N/2-1,...-3,-2,-1. Или я совсем неправ? Именно так частоты и идут. Сенк статья оч полезная. -Added Цитата Prince @ Имхо, конечно. Насчёт пьезо. Для него схему придётся собирать. И калибровать как-то нужно. А крепить как.... Может, поискать готовый датчик? Ну прикрепить - это не большая трабла, особо заморачиваться с калибровкой не нужно(мне точные численые значения не нужны, мне нужно видеть сам факт - будет всплеск или нет). |
Сообщ.
#13
,
|
|
|
Prince
Ты 0 забыл посчитать. И читай внимательнее это уже после перестановки. Хотя это моя вина, в том что не уточнил что это ответ на вопрос о перестановки. BFenix Цитата BFenix @ Подскажите моя задумка правильная или я чтото упустил? Нужен вибро датчик. Теории для БПФ есть, найти легко. А вот для вайвлетов надо искать и не факт что есть в данной облости. Но помойму удары лучши какраз на вайвлетах изучать. Почему? Интуция. |
Сообщ.
#14
,
|
|
|
Цитата Ты 0 забыл посчитать. Ну давай вместе посчитаем(для твоего варианта):-N/2-1,...,-3,-2,-1,0,1,2,3,..., N/2-1. Есть две последовательности: -1...-N/2-1 и 1...N/2-1 , которые дают нам N-2 элементов. И плюс ещё 0. Итого: N-1 элементов. Цитата с калибровкой не нужно(мне точные численые значения не нужны, мне нужно видеть сам факт - будет всплеск или нет). Схему-то всё равно придётся клепать для пьезодатчика. Не к микрофонному же усилителю звуковушки его подключать. |
Сообщ.
#15
,
|
|
|
Цитата Prince @ Схему-то всё равно придётся клепать для пьезодатчика. Не к микрофонному же усилителю звуковушки его подключать. а почему не к микрофонному? Мона канеша на сом порт подцепить, но не факт, что это будет лучше. |