| Flash 10 Аудио, FFT (Fast Fourier Transform) |
|
|
|
| Написао Саша Рудан |
| недеља, 07 децембар 2008 03:41 |
Често нам технологија помаже да учинимо ствари једноставнијима. То је наравно лијепо ;), али када нам помогне да учинимо немогуће ствари могућим, то је онда узбућујућа ствар. То се десило са новом аудио подршком у Флешу 10. У овом посту причам о имплементирању FFT (Fast Fourier Transform) са Flash-ом.
УводЗадњих пар година Флешери су покушавали да извуку више из Флеша што се тиче звука. Flash 9 је омогућио рачунање спектра за аудио сигнал (SoundMixer.computeSpectrum(). Ово је омогућило прављење елегантих визуелизација звука у Флешу 9 са AS3. Међутим, велики проблем је остао са
Међутим са појавом ActionScript 3 брзина извршавања Флеш апликација се драматично повечала омогућујући разне трикове са динамичким генерисањем звука. Један од најфасцинантнијих је везан за динамичко креирање свиф (SWF) фајла који садржи аудио сигнал "спуштен" на Timeline (погледајте popforge библиотеку). Овим се фактичи генерисао аудио сигнал кроз његово паковање у свиф фајл и накнадно учитавање у извршујући свиф и тиме његово репродуковање. Ово је можда прљав, али фасцинантан начин проширивања могућности једнога окружења. Други начин је био коришћење Јава аплета за манипулисање звуком и прослеђивање резултата преко јаваскрипта флешу на накнадну обраду и визуелизацију. Flash 10Flash 10 је унио најзначајније новости везано за рад са звуком у задњих пар верзија. Креирање аудио записа Најкраће речено, сада можемо да из наше AS3 апликације пунимо Sound објекат са аудио сигналом који представља обичан низ аудио семплова. Најузбудљивија ствар је да овај низ ми можемо сами креирати. Исчитавање аудио семплова из аудио записаОво је друга узбудљива могућност која нам даје шансу да у реалном времену очитавамо аудио семплове некога mp3 фајла и нпр. миксујемо га са неким другим mp3 фајлом и тиме направимо једноставну миксету :) ПримјериПримјери везани за ове нове могућности Flash-a 10 заиста није тешко наћи. Занимљив примјер је у самој Flash 10 документацији. Око овога у принципу неа ста даље да се пише, сем да се играјте колико са тим до миле воље :) FFT (Fast Fourier Transform)УводВременски и спектрални сигналВременски сигнал је запис неког сигналакроз вријеме, у случају дигитално семплованог сигнала, то је низ очитаних интензитета сигнала кроз вријеме у равномјерним временским размацима. Спектрални сигнал се математички не разликује много :), међутим концептуално он представља скуп свих фреквенција садржаних у датом сигналу као и њихових интензитета и фаза. Као што је у дигиталном одабирању временски сигнал не садржи све временске вриједности, већ само оне узете у одређеним временским тренуцима, тј постоји Tdelta, тако је и за спектрални домен, у коме постоје само одређене фреквенције са истим размацима међу њима, Fdelta.Одавде је битно закључити да ако желимо да сазнамо заиста која фреквенција је у датом сигналу, ми ћемо оперисати увјек са грешком од Fdelta, мада за предвидив сигнал можемо је смањити интерполацијом. FT (Fourier Transform)FT (Fourier Transform) је најкраће речено, математички апарат који нам омогућава добијање спектралног сигнала из временског сигнала и обрнуто. Дакле, ако сте у могућности да приступите времнском сигналу (у флешу вам је то могућа кроз extract() методу), тада помоћу FT сте у могућности да добијете спектрални сигнал. Мало прецизније, користићете DFT (Discret Fourier Transform). FT је у ствари полиномисање функције, слично Њутновим полиномима, с тим да FT пребацује сигнал у други домен и тиме даје интересантне могућности:
За неке од ових ефеката потребна је и IFT (Inverse Fourier Transform). Она нам омогућава добијање пребацивање сигнала из спектралног домена у временски домен. FFT & IFFTFFT (Fast Fourier Transform) јe FT која је оптимизована и прилагођена рачунарском процесирању. Оптимизација је драматична и без ње многи данашњи алгоритми у реалном времену не би били могући. Inverse FFT нам омогућава да се из спектралног домена вратимо натраг у временски домен. Дакле сценарио је слиједећи:
Један проблем при таквој обради сигнала је тај да ће на граничним зонама доћи до пуцкетања. Одакле ово пуцкетање? Оно је посљедица операција у спектралном домену. Ако сте пребацивање у спектрални домен користили само за очитавање сигнала а не и за модификовање, онда је наравно све у реду. Међутим ако сте га мјењали, тада су се у генералном случају пореметиле фазе. Оне су унутар интервала и непримјетне, али на ивицама нису, и тако помјерене фазе сигнала у једном интервалу и исто тако помјерене у другом интервалу ће изазвати пикове на "зашивеним" спојевима :). Постоје начини да се то отклони, али о томе касније. Примјер - Bandpass филтерУвод Овај примјер је релативно једноставан. Ипак у систему постоји више компоненти.
Компоненте које ћу анализирати су компонента 1, 6 и 7. Остале су овдје само зарад тога да би примјер радио, и оне нису довршене нити тема овога поста, већ неког каснијег. Наравно, слободни сте да истражујете и да их користите :) >>> Сорс код ОписСлиједећа слика описује ток сигнала у овом примјеру: Свака од компоненти је довољно дескриптивна, једино се не види једна компонента а то је компонента која интегрише све друге компоненте. То је компонента која виртуелно повезујсе све компоненте и прослијеђује захтјеве и сигнал из једне у другу компоненту. Ова компонента је садржана у Мain.as фајлу и за сада није најелегантније ријешена и вјероватно је превише комплексна, али разлог за то је што ће се касније развити AudioHeads систем који ће бити скуп Fash компоненти за обраду аудио сигнала и у ту сврху је потребна комплекснија дистрибуција сигнала. Основни начин рада Основни начин рада је представљен слиједећим процесом: излазна аудио компонента шаље захтјеве за аудио узорцима sоund distribution компоненти: var num: int = parent.RequestData(this, this.inputBuffer, length, startPosition); Ова компонента води евиденцију о везама свих компоненти и прослеђује захтјев пријетходној компоненти у току аудио сигнала и враћа резултат излазној аудио компоненти. public function RequestData(requester:AudioComponent, target:ByteArray, Ова метода сазнаје из connectionsComponents матрице ID пријетходне компененте, референцира је из низа компоненти components, и прослијеђује захтјев тој компоненти, а резултат тога захтјева враћа компоненти која је послала захтјев (у овом случају излазној аудио компоненти). Наравно пријетходна компонента ће тражити аудио сигнал од компоненте која њој пријетходи ;) и тако све докомпоненте која је извор звука и тада ће се резултовани звук пропагирати натраг до излазне компоненте. FFT/IFFT компонентаComponent name: FourierTransformation Package: SoundProcessors Ово је најважнија компонента а уједно готово и најједноставнија компонента :) Битне су слиједеће функције: RequestData()Ово је метода коју имају све AudioProvider класе. Она је одговорна за прослијеђивање података аудио компоненти која јој слиједи у аудио ланцу, у овом случају аудио излазу. Као што је већ речено ова метода прво тражи аудио одабирке од аудио компоненте која јој пријетходи у аудио ланцу (у овом случају аудио миксер) и за то се обраћа родитељској компоненти која је у ствари sound dispatcher. У првој петљи, ова метода припрема податке за FFT обраду; пуни реалне и имагинарне одабирке. За случај реалног сигнала, имагинарни одабирци су 0. Такође пуни и излазне аудио одабирке за слиједећу компоненту у низу (у слућају да нема обраде сигнала у фреквентном домену). Након тога се позива DirectFFT метода која израчунава фреквентни спектар из временског.За објашњавање ове методе је потребан не један нови пост већ бар једно поглавље, а основни концепт је објашњен у уводу, тако да овдје нећу ићи у детаље. За вас је вјероватно довољно да знате да она ради :). Интересантно је да она као излаз даје фреквентни спектар у истим низовима који је напуњен са временским спектром, у овом случају inputs_real, inputs_imag. Ипак за кориснике је много битнија метода processOutput која из спектралног домену проналази локалне максимуме тј. носеће фреквенције. Код комплексног сигнала ово може дати пуно хитова, тако да је потребно урадити или налажење глобалног максимума, или поставити праг минималног интензитета. За одређене апликације (као у овом примјеру), позив ове функције није ни потребан. Такође треба размислити о оптималнијем складиштењулокалних максимума, јер се овако "малтретира" Garbage Collector. Након тога у случају да се захтјева филтрирање у фреквентном опсегу, тада се спектрални домен филтрира а затим позива функција за инверзну фуријеову трансформацију.
for( i= 0 ; i < num ; ++i ) Пошто је добијени фреквентни спектар симетричан око Никвистове фреквенције, то се требају очистити и доњи (Low) дио и горњи (High) дио спектра. ОБјашњење за ово је мало математички комплексније. На крају се временски спектар (добијен IFFT-ом) пребацује у низ који представља аудио излаз овог аудио блока. GetIndexForFrequency(frequency:Number, roundToHigher:Boolean)Ова функција израчунава индекс у фреквентном спектру који одговара датој фреквенцији. Као што је речено, семплови у фреквентном спектру су еквидистантни. У случају да фреквенција не одговара тачно фреквенцији одабирка, параметрном roundToHigher се инсистира да се заокружи на вишем индексу (true), или на нижем (false). SetFilter(frequencyLow:Number, frequencyHigh:Number)Ова метода служи за постављање филтер. Она позива функцију GetIndexForFrequency како би нашла одговарајуће индексе, док законима симетрије налази индекс за горњи симетрични дио спектра. GetSamples(spectrum:Vector.<Number>, indexLow:int, indexHigh:int, samplesNo:int)Ова функција враћа скуп одабирака у датом фреквентном интервалу и то задати број семплова. Ова функција би се требала преправити да рачуна усредњену вриједност свих семплова који се пресликавају у један семпл у резултату, а не само да се узме онај који "пада" на датој позицији. DirectFFT(dir:Boolean, m:int, n:int, re:Vector.<Number>, im:Vector.<Number>)Ова метода је већ објашњена у текстуInverseFFT(dir:Boolean, m:int, n:int, re:Vector.<Number>, im:Vector.<Number>)Ова метода се заснива на позиву методе за директну FFT, засновано на симетричности израчунавања FFT и IFFT. createTestInput(input_signals:Vector.<Signal>)Ова метода служи у тестирању и креира тест улазни аудио сигнал у временском спектру DirectDFT()Ово је имплементација класичне FT чијим се позивом може тестирати наша FFT имплементациј и уочити огромна разлика у времену процесирања сигнала у односу на FFT. Spectrum компонентаSpectrum компонента служи за визуелизацију фреквентног спектра.У сваком новом фрејму компонента позива FFT компоненту да би преузела нове вриједности семплова и визуелизовала их као мали правоугаонике којима висина одговара интензитету. Могућа унапређењаОсновни проблем овога приступа филтрирању је пуцкетање. Оно се може ријешити интерполирањем. Наиме, идеја је једноставна али захтјева више процесирања: израчунавају се фреквентни спектруми на половини интервала (N/2). У том случају тај спектар ће преузети доминацију на "шавовима" док ће на осталом дијелу спектра бити доминантнији нормали спектри. Друго побољшање је као што смо рекли у складиштењу детектованих семплвова. Слиједеће побољшање је у начину процесирања сигнала и непотребности копирања сигнала у свакој компоненти (сем у случају миксете или компоненти за кашњење, итд). Тиме временски и меморијски оптимизујемо систем. |
| Последње ажурирано понедељак, 19 јануар 2009 12:12 |
iphone 3g case
Cheers, chase personal loans
would you mind updating your blog with more information?
satellite pc tv
Good efforts...I am also working as a web designer as i am from art background.
I am more interested in flash animations/ sites.
Gratifying work and much success in your business endeavors!!!!
i'm trying to construct a visualisation fitted to the beat of musik. i're in a despaired need of fast band filtering to have time for further computations. posting results asap ...
-
még nem próbáltam ki, de nagyon igéretes, szép munka
én egy olyan vizualizációt próbálok megvalósítani, ami a zene üteméhez igazodik. nagy szükségem volt arra, hogy sávokra tudjam osztani a jelet gyorsan, hogy maradjon idő a további számításokra. az eredményet postolom, amint lehet ...
sry i have to tell that it's creaking. i changed song, like u told, and i found awfull noise when filtering. i think its generated throught ifft from 0 u'r using afther freq cut to keep signal length.
by the way fft algorithm u'r using is a Cooley-Tukey algoritm, rn't u? i belive if u calculate the fine step with dft, it can be usded not just power of 2 number of samples. am i rigth? it called somthing Danielson-Lanczos lemma. im fighting with math can u help me, pls.
with all respect
subject :) It's very hard to find any examples
in this subject... Could you be so nice and post
some code you've mentioned in the article ?
BTW. Do you think that's possible to calculate FFT
via PixelBender in favour of performance gain ?
i am making a automobile racing game, and i think the best way to make a dynamic engine nosie would be to get the mid range rev engine sound and use a pitch control in relation to the car's speed to change how high or low the revs sound.
do you think this would be the best way to do it?
if so are you able to give me some tips or point me in the right direction?
of even better...do it for me? :D
Thanks
Mensagens para Orkut
http://www.kaourantin.net/2008/10/audio-mixing-with-pixel-bender.html
Note that PB Toolkit has been updater recently
so maybe they solved a bug that Tinic refered to in
his post.
I'm in process of building kind of "sound game" in which
accessing sound spectrum data for particular sounds separately (instead of built-in global SoundSpectrum) is essential.
Regarding PB i think that with few hacks it's possible
to force it to process arbitrary data - in form of bytearray or even vector... Main problem may be it's inability of computing more complexed algorithms ( lack of loops, arrays etc ).
I'll post any progress I'll made in this subject :)
Hope to stay in touch :)
Quite informative article on not so well explored
subject :) It's very hard to find any examples
in this subject... Could you be so nice and post
some code you've mentioned in the article ?
BTW. Do you think that's possible to calculate FFT
via PixelBender in favour of performance gain ?
I just put code and working example.
Sorry for missing this out :)
If you want to try it, you need to set correct path to your mp3 file in Main.as (line 125).
If there is any problem just ask.
Sasha
P.S. I hope, it would be possible to speed up with PixelBender. I just started investigating on it. It mainly depends what PB can accept as input. I think it is addressing only few pixels in image, so it seems it cannot work with big arrays that represents audio samples :(
We can play with it together and see if it works :)
In source code you have FFT algorithm