Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.04 c
15-1169621895
vajo
2007-01-24 09:58
2007.02.18
Ищу файлменеджер


2-1170065544
GrayFace
2007-01-29 13:12
2007.02.18
Не показывать конструктор родителя при overload нутом своем?


2-1170316509
Tornado
2007-02-01 10:55
2007.02.18
Отследить закрытие чужого приложения


2-1170330701
Alek_1
2007-02-01 14:51
2007.02.18
вывести дату...


2-1169971490
LiteStone
2007-01-28 11:04
2007.02.18
Глюк





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский