Pentru a utiliza biblioteca, descărcați fișierul ZIP, despachetați-l și apoi plasați-l în folderul pentru bibliotecile IDE Arduino.
Biblioteca FFT constă din mai multe funcții - astfel încât utilizatorul să o poată adapta la nevoile proprii. Asta este, dacă nu aveți nevoie de fragmente din bibliotecă, puteți să le ștergeți pur și simplu.
Există șapte funcții în bibliotecă: două preliminare fft_reorder () și fft_window (). una fft_run principală () și patru amplitudine, responsabil pentru diferitele formate de date de ieșire: 16 biți liniare, 8 biți liniare, 8 biți logaritmice și 8 biți octavă.
Funcția fft_run () este funcția principală a bibliotecii FFT. Nu are nevoie de argumente, iar ea nu returnează nimic. Dacă executați această funcție, se presupune că datele necesare au fost deja reorganizate și se află în memoria SRAM. Aceste date sunt stocate într-o arhivă numită fft_input []. care conține două valori pe 16 biți - reale și complexe. Dacă completați singur această matrice, atunci valorile reale sunt stocate în eșantioane de ieșire numerotate chiar și cele complexe sunt păstrate ciudate.
Astfel, fft_input [0] - această primă valoare reală, fft_input [1] - o primă valoare complexă, fft_input [2] - a doua valoare reală, fft_input [3] - a doua valoare complexă etc.
În consecință, se obține o dublare, astfel încât numărul de eșantioane din matrice va fi de două ori mai mare decât, de fapt, numărul real de PBF-uri. Dacă utilizați numai numere reale (adică valorile obținute de la ADC), atunci le păstrați în număr egal și introduceți "0" în probe impare.
Rezultatul este stocat în fft_input []. unde chiar citirile sunt responsabile pentru amplitudinile reale și cele ciudate pentru cele complexe. Probele înseși sunt benzi de frecvență (în ordine crescătoare).
Astfel, fft_input [0] și fft_input [1] - este amplitudinea cadrului de referință primul (0Hz -> Fs / N), fft_input [2] și fft_input [3] - este amplitudinea al doilea cadru de referință (Fs / N -> 2FS / N), etc.
Pentru a obține date utile din aceste mostre, va trebui să începeți una dintre cele patru funcții de amplitudine (acestea sunt descrise mai jos).
fft_reorder ()
Funcția fft_reorder () reorganizează datele de intrare, pregătindu-le pentru prelucrare prin algoritmul FFT. Poate că această funcție nu va fi necesară, pentru că această reorganizare poate fi efectuată manual. Funcția fft_reorder () este executată înainte de fft_run (). Nu are nevoie de argumente, iar ea nu returnează nimic. În plus, înainte de a apela această funcție, trebuie să umpleți matricea fft_input []. deoarece ia datele originale de acolo.
fft_window ()
Funcția fft_window () multiplică intrarea cu o funcție de fereastră pentru a crește rezoluția de frecvență a datelor pentru PBF. Nu are nevoie de argumente, iar ea nu returnează nimic. În plus, înainte de a apela această funcție, trebuie să umpleți matricea fft_input []. deoarece ia datele originale de acolo. Funcția fft_reorder () este executată înainte de fft_run () și fft_reorder ().
fft_mag_lin8 ()
Funcția fft_mag_lin8 () dă amplitudinea pentru fiecare probă FFT. Ea rezumă valorile reale și complexe, pătrat, și apoi rădăcina pătrată, rotunjirea rezultatului la valoarea de 8 biți (se folosește un tabel de căutare, ajustând valorile pentru întreaga gamă de 8 biți). Nu are nevoie de argumente, iar ea nu returnează nimic. Datele inițiale pentru acestea sunt date din matricea fft_input []. iar rezultatul este stocat în matricea fft_lin_out8 []. după care aceste date pot fi utilizate în alte scopuri. Amplitudinea se calculează numai pentru prima jumătate a eșantioanelor de ieșire (N / 2), deoarece a doua jumătate a FFT este identică cu prima pentru întregul interval de valori inițiale. Prin urmare, numărul de valori pe 8 biți din matricea fft_lin_out8 [] va fi N / 2. unde fiecare indice va corespunde numărului probei de ieșire (minus "1").
Aceasta este fft_lin_out8 [0] - este amplitudinea cadrului de referință primul (0Hz -> Fs / N), fft_lin_out8 [1] - este amplitudinea al doilea cadru de referință (Fs / N -> 2FS / N), etc.
fft_mag_lin ()
Funcția fft_mag_lin () dă amplitudinea fiecărui eșantion FFT. Sumerează valorile reale și complexe, pătrat, apoi extrage rădăcina pătrată. Pentru a extrage o rădăcină pătrată, se utilizează o tabelă de căutare, astfel încât precizia are anumite limitări. Funcția acoperă o gamă completă pe 16 biți, dar în orice moment din acest interval, rezoluția va fi în continuare de 8 biți.
Aceasta este o valoare pe 8 biți, unde 4 biți sunt alocați comenzii (adică sub exponent). Datele inițiale pentru acestea sunt date din matricea fft_input []. iar rezultatul este stocat în array fft_lin_out []. Totalurile sunt aranjate în ordine succesivă, iar numărul lor total este N / 2. Deoarece a doua jumătate a FFT este identică cu prima pentru întreaga gamă de valori inițiale.
fft_mag_log ()
Funcția fft_mag_log () dă amplitudinea pentru fiecare probă FFT. Se însumează valorile reale și complexe, pătrat, apoi se extrage rădăcina pătrată. Apoi, funcția calculează logaritmul numărului rezultat în raport cu două. Rezultatul va fi prezentat într-un format logaritmic - de fapt, în decibeli. Funcțiile fft_mag_log () nu au nevoie de argumente și nu returnează nimic.
Pentru a extrage rădăcina pătrată, se utilizează o tabelă de căutare și rezultatul este ajustat la întregul interval de 8 biți. Aceasta este, ecuația funcției va fi după cum urmează: 16 * (log2 ((complex2 + action2) 1/2)). Datele inițiale ale funcției sunt date din matricea fft_input []. iar rezultatul este stocat în matricea fft_log_out []. Valorile rezultate sunt de aceeași ordine ca și mostrele de ieșire ale FFT. iar numărul total de eșantioane este N / 2. Deoarece a doua jumătate a FFT este identică cu prima pentru întreaga gamă de valori inițiale.
fft_mag_octave ()
Funcția fft_mag_octave () dă valoarea mediană triunghiulară a tuturor eșantioanelor de ieșire, reprezentând toate acestea în format octavă (dublare frecvență). Acest format este, de obicei, mai util, deoarece este aproape de modul în care oamenii percep sunetul. Nu are nevoie de argumente, iar ea nu returnează nimic. Datele inițiale ale funcției sunt date din matricea fft_input []. iar rezultatul este stocat în array fft_oct_out []. Datele rezultate sunt o valoare pe 8 biți, calculată prin formula 16 * log2 (quad). Numărul probelor de ieșire se calculează după cum urmează:
Aici, de exemplu, 5: 8 este suma tuturor numerelor situate între 5 și 8. Datele din fiecare număr sunt pătrat (atât valori reale, cât și complexe) și apoi sunt însumate cu toate amplitudinile (de asemenea, pătrat) în acel interval. Apoi luați numărul de probe de ieșire și împărțiți-le cu numărul obținut (acest lucru însă poate fi oprit - vezi secțiunea următoare), apoi se extrage rădăcina pătrată și se calculează logaritmul.
Doriți să "priviți sub capotă." Bine, voi încerca să explic, prin ce principii funcționează toate acestea. Două lucruri sunt responsabile pentru accelerarea calculelor în biblioteca FFT.
Mai întâi, în fiecare FFT trebuie să multiplicați setul de valori inițiale cu ajutorul constantelor sinusurilor și cosinuselor. La ATmega, acest lucru necesită resurse de calcul mari, deoarece înmulțirea a 16 biți cu 16 biți necesită 18 cicluri de ceas. Pe de altă parte, adăugarea a 16 biți și 16 biți necesită doar 2 cicluri de ceas. Prin urmare, concluzia că este mai bine să se adauge decât să se înmulțească. Faptul este că constantele sinusului și cosinusului utilizate în FFT sunt pur și simplu "0" și "1". astfel încât nu este nevoie să utilizați operația de multiplicare. este suficient și adăugat. De exemplu, dacă FFT are 256 probe de ieșire. atunci trebuie să efectueze 1024 multiplicări complexe, dintre care 382 sunt "0" sau "1". Aproape jumătate!
Biblioteca FFT pentru Arduino caută condiții în care sunt utilizate aceste "0" și "1". și pur și simplu face acolo plus. Faptul este că aceste constante apar la intervale regulate, deci este destul de ușor să le găsim. Cu toate acestea, odată cu creșterea numărului de probe de ieșire, avantajele acestei metode sunt reduse. Dacă numărul de probe de ieșire din FFT este N, atunci economiile de timp vor fi (1,5 * N - 2), iar numărul total de multiplicări va fi (N / 2) * log2 (N). Astfel, formula prin care se calculează economiile va fi 3 / log2 (N). și cu cât este mai mare N. mai puțin timpul pe care îl puteți salva.
Cea de-a doua metodă, destinată accelerării activității FFT - este o masă de căutare, cu ajutorul căreia se calculează rădăcinile pătrate ale amplitudinii. Complexitatea acestei metode este că datele sursă sunt mult mai mari decât conținutul tabelului de căutare. Astfel, pentru a nu pierde memoria programelor, datele sursă ar trebui comprimate. De exemplu, dacă extrageți rădăcina pătrată a unei valori pe 16 biți. obținem 64 mii de valori de intrare. care trebuie să fie cumva ajustată la 256 valori de ieșire. În memoria programului Arduino, este imposibil să se efectueze un astfel de volum de calcule, astfel încât în bibliotecă se aplică întreaga gamă de date de intrare cu interpolare liniară, ca rezultat al cărora vor fi calculate diferite linii pentru diferite secțiuni. De exemplu, pentru un format liniar de 8 biți, sunt suficiente 3-4 secțiuni liniare. fără pierderea permisiunii.
Astfel, biblioteca calculează valoarea de intrare pentru una dintre aceste secțiuni de linii, apoi extrage rădăcina pătrată și necesită aproximativ 12 cicluri de ceas. Acest lucru este mult mai mic decât cele 150 de cicluri. care sunt necesare în biblioteca standard pentru a extrage rădăcina pătrată.
Versiunea cu date de intrare pe 32 de biți este puțin mai complicată, deoarece acum datele de ieșire trebuie ajustate la 16 biți. iar interpolarea liniară aici nu ajută, deoarece nu știe cum să comprime valori a căror rezoluție este mai mare de 16 biți. Prin urmare, aici este utilizată o abordare hibridă, în care valoarea de intrare este convertită la o valoare de 16 biți cu o comandă pe 8 biți. Acest lucru se poate face foarte repede cu baza "2". care permite utilizarea tabelului de căutări rădăcină pătrată și pentru valori cu o rezoluție mai mare de 16 biți. Dacă valoarea de intrare este comprimată, se efectuează o deplasare de 2 biți spre dreapta. atunci valoarea de ieșire poate fi reconstruită cu o deplasare de 1 bit spre stânga. De regulă, după crearea, ordinea (adică exponentul) este rotunjită la un număr par, în urma căreia rădăcina pătrată poate întoarce o valoare întregă.
Desigur, versiunea pe 32 de biți nu este la fel de precisă ca biblioteca pentru calculul rădăcinii pătrate, dar necesită doar 40 de cicluri. în timp ce această bibliotecă necesită 500. Tabelul de căutare returnează o valoare în care doar primele 8 biți sunt corecte. dar pentru această FFT o astfel de precizie este suficientă. Adâncimea totală a bitului FFT nu este mult inferior celor 12 biți. deoarece foloseste un punct fix (pentru a evita supraincarcarea inainte de a adauga, fiecare valoare trebuie impartita la 2, daca FFT are 256 probe de iesire, aceasta da in cele din urma o diviziune de 256). Precizia depinde de rezoluția datelor de ieșire. Dacă aceasta este o valoare pe 8 biți. atunci precizia va fi maximă. Dacă aceasta este o valoare pe 9 biți. atunci un mic pic poate fi greșit. Dacă aceasta este o valoare de 10 biți. atunci cei doi biți cei mai puțin semnificativi pot fi incorecți etc. Asta este, cel mai rău scenariu este o valoare pe 16 biți, cu o precizie de +/- 0,5%.
Aceste valori vă permit să modificați codul FFT pentru nevoile dvs. Cele mai multe dintre ele permit și dezactivează anumite funcții ale bibliotecii. În mod implicit, majoritatea funcțiilor sunt dezactivate, astfel încât să le utilizați, trebuie mai întâi să le activați. Aceste directive sunt introduse folosind #define construct și trebuie să faceți acest lucru înainte de conectarea bibliotecilor, ceea ce se face prin constructul #include.
- Directiva FFT_N specifică dimensiunea FFT. Opțiunile sunt: 16. 32. 64. 128 și 256. Valoarea implicită este 256.
- Directiva SCALE este responsabilă pentru scalarea în funcția fft_mag_lin8 (). Din moment ce 8 biți sunt o rezoluție destul de slabă, utilizatorul poate doriți să scala datele pentru a le maximiza la întreaga gamă.
- Directiva SCALE înmulțește ieșirea cu o constantă înainte de a extrage rădăcina pătrată, rezultând o ieșire de rezoluție maximizată. Acest lucru va necesita mai puține resurse decât de obicei, dar cheltuielile excesive vor fi foarte mici. În directiva SCALE, puteți specifica orice număr în intervalul de la 1 la 255. Valoarea implicită este 1. Cea mai mică cantitate de resurse este consumată atunci când se utilizează 1. 2. 4. 128 și 256.
- Directiva WINDOW permite și dezactivează funcția de fereastră. Dacă nu utilizați fft_window (). atunci trebuie să introduceți WINDOW 0 (oprit). Valoarea implicită este WINDOW 1 (activată).
- Directiva REORDER permite și dezactivează funcția de reorganizare. Dacă nu utilizați fft_reorder (). atunci trebuie să introduceți READER 0 (oprit). Valoarea implicită este REORDER 1 (activată).
- Directiva LOG_OUT permite și dezactivează funcția pentru formatul logaritmic. Dacă utilizați fft_mag_log (). atunci trebuie să introduceți LOG_OUT 1 (on). Valoarea implicită este LOG_OUT 0 (dezactivată).
- Directiva LIN_OUT permite și dezactivează funcția pentru un format liniar (16 biți). Dacă utilizați fft_mag_lin (). apoi trebuie să introduceți LIN_OUT 1 (on). Valoarea implicită este LIN_OUT 0 (dezactivată).
- Directiva LIN_OUT8 permite și dezactivează funcția pentru un format liniar (8 biți). Dacă utilizați fft_mag_lin8 (). apoi trebuie să introduceți LIN_OUT8 1 (activat). Valoarea implicită este LIN_OUT8 0 (dezactivată).
- Directiva OCTAVE permite și dezactivează funcția pentru formatul octavelor. Dacă utilizați fft_mag_octave (). atunci trebuie să introduceți OCTAVE 1 (on). Valoarea implicită este OCTAVE 0 (oprit).
- Directiva OCT_NORM permite și dezactivează funcția de normalizare a formatului octavelor. Este parte a funcției fft_mag_octave (). care divizează fiecare probă grupată cu numărul mediu de eșantioane. Deoarece multe surse de sunet emite așa-numitul "zgomot roz" (aceasta este scăderea amplitudinii cu frecvență în creștere), aceasta duce la o reducere a scării. Oprit (OCT_NORM 0), această directivă mărește în mod artificial amplitudinea la frecvențe înalte. Implicit, normalizarea este activată (OCT_NORM 1).
- fft adc - Aplicați FFT pe datele de la ADC și trimiteți rezultatul prin scriere ()
- fft adc serial - Aplicați FFT pe datele de la ADC și trimiteți rezultatul prin println ()
- fft codec - Aplicați FFT pe datele din modulul Codec Shield