Форум: "Media";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];
Внизполучить спектр звука с микрофона Найти похожие ветки
← →
antonn © (2006-05-19 09:45) [0]вобщем сабж. Нужно в массив (0..511 of double) поместить пропорционально значение уровня громкости определенной частоты (40..18К). Типа графического эквалайзера плееров, только колонок будет больше.
есть ли у кого примерчик рабочий? Перерыл кучу примеров "по FFT" - какие то не компилятся, какие то не пойму, как привязать. Что то типа компонентов MMTools - там эквалайзеры есть, ловят "общий" звук. Мне только массив нужно забацать.
← →
antonn © (2006-05-19 09:45) [1]да, забыл, нужно без "иногородних" компонент и библиотек
← →
Jeer © (2006-05-19 10:05) [2]А ведь придется учится, если хочешь.
Возьми алгоритм попроще - алг. Герцеля.
Пусть не быстро, но проще.
← →
tsa (2006-05-19 10:30) [3]http://oldsite.vislab.usyd.edu.au/CP3/Four3/node19.html
Используются мнимые числа,
входные данные(количество их это степени двойки, т.к. FFT):
первое число, ноль, второе число, ноль... последнее число, ноль :)
ноль это мнимая часть - если на входе реальные данные, например из звуковой платы
PROCEDURE four1(VAR data: gldarray; nn,isign: integer);
isign =1 прямое, -1 обратное FFT
выходные данные так же мнимые числа,
для темы ветки -
использовать первую половину
re1, im1, re2, im2, ... re(n/2+1),im(n/2+1)
искомая "громкость" = (re^2+im^2)^(1/2) - модуль этого числа мнимого.
← →
tsa (2006-05-19 12:28) [4]Пример:
После uses добавить -
TYPE
gldarray = ARRAY OF extended; //extended круче :)
Процедуру скопировать в код, "sngl", который не понимает компилятор просто удалить.
Ввести -
procedure TForm1.Button1Click(Sender: TObject);
var dat:gldarray;
i:integer;
e:array[0..257-1] of double; //тут "громкости" будут
begin
setlength(dat,512*2+1); //функция four1 хочет array[1.., нулевой элемент не задействован
for i:=1 to 512 do begin
dat[i*2-1]:=sin((2*pi/44100)*100*i); //тон 1000 гц при частоте дискретизации 44100 в сек
dat[i*2]:=0; //данные реальны, мнимая часть=0
end;
four1(dat,512,1);
for i:=1 to 512*2 do dat[i]:=1/512*dat[i]; //нужно, если потребуется обратное преобразование, что бы совпало с исходным
//информативна лишь первая половина FFT т.к. данные у нас реальные
for i:=1 to 512 div 2+1 do
e[i-1]:=sqrt(sqr(dat[i*2-1])+sqr(dat[i*2]));
end;
← →
antonn © (2006-05-19 14:14) [5]tsa (19.05.06 12:28) [4]
спасибо. еще пробывал какой то функцией Hartley(), эффект почти тот же.
вроде сделал, но все равно криво смотрится, басы завернуты кверху слишком, придется коэфициенты вводить...
кстати, при паузе в плеере, и полной тишине все уровни резво подпрыгивают и радостно колбасятся:) буду думать, как их убивать...
получилась, пока, такая фиговина:
http://an-files.narod.ru/_image/freq_mon.GIF (55kb)
при появлении высоких частот, все покрывается "шумом"...
← →
tsa (2006-05-19 14:25) [6]
> [5] antonn © (19.05.06 14:14)
>басы завернуты кверху слишком
0-й член FFT - e[0] из примера это "DC-OFFSET" -
постоянный ток в канале, можно отбросить.
А коэффициенты тоже хочу знать -
как я понял коэффициент это отношение площади "горба" синусоиды (интеграл sin 0..pi) к площади прямоугольника куда этот горб вписан (0..pi*1)
В общем случае не могу решить - для sin любой частоты и нулевой фазы
← →
Jeer © (2006-05-19 14:28) [7]Для снижения явления Гиббса входные данные надо обработать одной из оконных функций: Хениннг, Ханн, Гаусс, Папулис, Ланцош и тп
← →
MBo © (2006-05-19 14:34) [8]>басы завернуты кверху слишком
Не уверен, что понял, к чему это относится, однако если к мощности спектра, то шкалу по частоте логарифмическую используй, т.е. скажем, при выделении частотных полос делать их не равной ширины, а с одинаковым отношением верхней и нижней границы, например:
31.. 63 63..125 125..250 250.. 500 и т.д.
← →
antonn © (2006-05-19 14:50) [9]ну да, логарифмическую шкалу нужно заюзать (или к ней привести)...
из примеров к bass.dll:type
TFFTData = array [0..512] of Single;
TBandOut = array[0..25-1] of word;
procedure TBASSPlayer.TimerFFTTimer(Sender: TObject);
const
// Classify FFTData[x] by the number of required bands for spectrum visualization.
// FreqCoef defines the last index number of FFTData[x] for each band.
FreqCoef : array[0..NumFFTBands - 1] of word =
( 1, 2, 3, 6, // narrow interval for low freq. range
12, 18, 24, 30, 36, // normal interval for middle freq. range
42, 48, 54, 60, 66,
72, 78, 84, 90, 96,
102, 108,
120, 132, 156, 180 ); // wide interval for high freq. range
// If the sampling rate is (standard) 44100Hz then the frequency of FFTData[x]
// is 44100 / 512 * x, so the representative(or maximum) frequency of each
// band is as followings
// BandOut[0] : 86.1Hz BandOut[1] : 172.3Hz BandOut[2] : 344.5Hz
// BandOut[3] : 516.8Hz BandOut[4] : 1033.6Hz BandOut[5] : 1550.4Hz
// . . . (516.8Hz interval upto BandOut[20]) . . BandOut[20] : 9302.2Hz
// BandOut[21] : 10336Hz BandOut[22] : 11370Hz BandOut[23] : 13437Hz
// BandOut[24] : 15503Hz . . very high frequency range is excluded
Boost = 0.15; // Factor to intensify high frequency bands
Scale = 80; // Factor to calibrate the output range of BandOut[x]
// ( approximately from 0 to 24 ).
var
FFTData : TFFTData;
NewBandOut : TBandOut;
StartIndex : integer;
i, k : integer;
tmpIntensity : double;
begin
//тут нужно FFTData заполнить, удалил его.
//Тут было заполнением самим Бассом...
for i := 0 to (NumFFTBands - 1) do
begin
if i = 0 then
StartIndex := 1
else
StartIndex := FreqCoef[i-1] + 1;
tmpIntensity := 0;
for k := StartIndex to FreqCoef[i] do
if FFTData[k] > tmpIntensity then
tmpIntensity := FFTData[k];
NewBandOut[i] := round(tmpIntensity * (1 + i * Boost) * Scale);
if NewBandOut[i] > BandOut[i] then
BandOut[i] := NewBandOut[i]
else
if BandOut[i] >= 2 then
dec(BandOut[i], 2)
else
BandOut[i] := 0;
if NewBandOut[i] > BandOut[i] then
BandOut[i] := NewBandOut[i];
end;
end;
тут из массива 25 столбиков нарезает (для цивильного графического эквалайзера), BandOut - "выводной" и публично описаный (или две "н"?).
множитель подправить(Scale), и прямоугольнички более равномерно подпрыгивают:)
правда я смухлевал, не с самого начала использовал данные, а то по краям разность не на порядки - больше. Короче из центра вырезал, мне большая точность не нужна а там они более равномерные:)
(вообще какая то поделка получилась, ну и ладно, хоть познакомился:))
← →
antonn © (2006-05-19 14:51) [10]NumFFTBands = 25
← →
MBo © (2006-05-19 14:54) [11]>а то по краям разность не на порядки
про краевые эффекты - см. [7]
← →
tsa (2006-05-19 15:07) [12][8] MBo © (19.05.06 14:34)
>шкалу по частоте логарифмическую используй
Это математически или примерно точно?
Задача - имеем синусоиды одинаковых амплитуд и фаз, но разных частот
каждой синусоиде сделали abs, т.е "выпрямили диодным мостом" :)
Вопрос - найти коэффициент отношения интергралов, взятых по каждой из синусоид после этого abs, пусть на всём промежутке -+бесконечность, и пусть даже через пределы - какой коэффициент будет?
← →
MBo © (2006-05-19 15:20) [13]>tsa (19.05.06 15:07) [12]
единица
← →
MypaBeu (2006-06-20 09:52) [14]Добрый день!
Можно пару вопросиков по этой же теме? Вопрос первый – сигнал какой частоты находится в каждом элементе массива при использовании БПФ (в частности в Bass.dll)?
Выше (см. пост № 9) написано:
// If the sampling rate is (standard) 44100Hz then the frequency of FFTData[x]
// is 44100 / 512 * x, so the representative(or maximum) frequency of each
// band is as followings, BandOut[0] : 86.1Hz ………
Но в Help-е по Bass.dll по функции BASS_ChannelGetData написано следующее: BASS_DATA_FFT512 (512 sample FFT (returns 256 floating-point values)) т.е., как понимаю, задав 512 выборок получим 256 значений БПФ. Соответственно, и средняя частота каждого диапазона будет вдвое большая? Или это не так?
И второй вопрос – если не ошибаюсь, - в каждом элементе массива находится амплитуда сигнала конкретной частоты? (первый элемент массива – нулевая частота, второй элемент – например, частота 86,1 Гц и т.д. )(вроде бы так должно быть по логике при использовании преобразования Фурье)? Но тогда как узнать амплитуду, сигнала, например частотой 40 Гц?
Может у кого имеются интересные ссылочки на литературу по преобразованиям Фурье, и в частности, по БПФ?
← →
antonn © (2006-06-20 16:51) [15]MypaBeu (20.06.06 9:52) [14]
в хелпе к басу сказано, что минимальная частота 80Гц (на оба эквалайзера)
← →
MypaBeu (2006-06-22 12:34) [16]А можно узнать поточнее - в каком месте хелпа это написано?
И еще один момент - ведь при вызове BASS_ChannelGetData - реализуется не эквалайзер, а, можно сказать - анализатор спектра.
← →
Jeer © (2006-06-22 13:59) [17]MypaBeu (22.06.06 12:34) [16]
Эквалайзер через ДПФ есть:
прямое ПФ - gain регулятор - обратное ПФ
← →
antonn © (2006-06-22 15:46) [18]MypaBeu (22.06.06 12:34) [16]
хм, я такое в BASS_FXPARAMEQ прочел:typedef struct {
float fCenter;
float fBandwidth;
float fGain;
} BASS_FXPARAMEQ;
Members
fCenter Center frequency, in hertz, in the range from 80 to 16000. This value cannot exceed one-third of the frequency of the channel.
fBandwidth Bandwidth, in semitones, in the range from 1 to 36.
fGain Gain, in the range from -15 to 15.
аналогично предположил (ну и позже видел на каком то форуме), что и для графического, и для звукового эквалайзера минимум 80.
Страницы: 1 вся ветка
Форум: "Media";
Текущий архив: 2007.02.18;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.046 c