Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.02.18;
Скачать: CL | DM;

Вниз

получить спектр звука с микрофона   Найти похожие ветки 

 
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 вся ветка

Текущий архив: 2007.02.18;
Скачать: CL | DM;

Наверх




Память: 0.52 MB
Время: 0.18 c
2-1170270359
Bagos
2007-01-31 22:05
2007.02.18
beep при OnKeyDown


15-1170072129
Ученик чародея
2007-01-29 15:02
2007.02.18
Какое количество ошибок в программе можно считать нормальным?


2-1170347053
Garacio
2007-02-01 19:24
2007.02.18
настройки Button


15-1169771344
IMHO
2007-01-26 03:29
2007.02.18
Viewer для BDB файлов


3-1164626798
Wolf82
2006-11-27 14:26
2007.02.18
Отчет в Делфи