Situatie
Am construit un sistem unificat de gestionare audio care funcționează ca „urechile” dispozitivului Sentinel — un modul care ascultă non-stop mediul înconjurător și identifică în timp real sunete potențial periculoase sau demne de atenție.
Captura audio: Am configurat microfonul intern al dispozitivului M5Stack CoreS3 să captureze audio mono la o rată de eșantionare de 16kHz. La fiecare ciclu, citesc un fragment de 2048 de eșantioane de la microfon. Imediat după citire, aplic o curățare a semnalului: mai întâi elimin offset-ul DC printr-un filtru simplu de ordinul întâi (care scoate componenta continuă pe care microfonul o poate introduce), apoi aplic un noise gate — dacă un eșantion este sub un prag de 250, îl setez la zero, eliminând astfel zgomotul de fond foarte slab care nu are relevanță.
La final, limitez valorile pentru a preveni depășirile. Fragmentele curățate sunt scrise într-un buffer circular alocat în PSRAM, care reține ultimele 5 secunde de audio — când se umple, datele cele mai vechi sunt suprascrise automat.
Procesarea AI: O dată pe secundă, verific dacă am suficiente eșantioane acumulate (16.000 de eșantioane = 1 secundă) și extrag un clip de 1 secundă din buffer. Primul lucru pe care îl fac este să calculez nivelul de volum (RMS) al clipului. Dacă volumul este sub un prag foarte mic, consider că este liniște — în acest caz, raportez direct „Background” cu încredere zero și nu mai rulez AI-ul deloc. Asta economisește resurse semnificative pe un microcontroler cu putere de calcul limitată.
Spectrograma mel: Dacă clipul conține sunet real, trec la etapa de extragere a trăsăturilor. Convert eșantioanele din format întreg (int16) în virgulă mobilă (float, intervalul -1.0 la 1.0), apoi calculez o spectrogramă mel — aceasta transformă sunetul brut într-o reprezentare vizuală compactă a frecvențelor în timp, exact cum face și biblioteca Python librosa. Procesul implică: aplicarea unei ferestre Hann pe fiecare cadru, calculul FFT (transformata Fourier rapidă) pentru a obține componentele de frecvență, apoi multiplicarea cu un filterbank mel care grupează frecvențele în benzi perceptuale (cum aude urechea umană).
Am optimizat acest pas folosind un filterbank mel „sparse” — în loc să stochez toți cei ~10.000 de coeficienți (dintre care majoritatea sunt zero), stochez doar cele ~200 de valori nenule, ceea ce reduce memoria folosită și accelerează calculul. La final, convertesc valorile de putere în decibeli, le limitez la un prag de -80 dB și le normalizez în intervalul 0–1.
Inferența AI: Spectrograma mel rezultată (o matrice de 63 cadre × 40 benzi mel) este trimisă unui model TensorFlow Lite care rulează direct pe dispozitiv. Modelul clasifică sunetul în una din 13 categorii: Background, Gunshot (împușcătură), Explosion (explozie), Screaming (țipăt), Siren (sirenă), Alarm (alarmă), Glass_breaking (spargere de geam), Fire (foc), Dog_alert (lătrat de alertă), Knock (bătaie în ușă), Vehicle_horn (claxon), Screech (scrâșnet) și Slam (trântire).
Aleg categoria cu scorul cel mai mare și stochez atât predicția, cât și nivelul de încredere, pe care le expun prin funcții getter pentru ca restul sistemului (interfața grafică, modulul de alertare etc.) să le poată accesa.
Modul de debug: Am adăugat o funcție specială care rulează întregul pipeline — de la conversia int16→float, la calculul RMS, spectrograma mel și inferența AI — pe un clip WAV de test încorporat direct în firmware. Asta îmi permite să verific că fiecare etapă produce rezultate corecte, comparându-le cu valorile obținute de scripturile Python echivalente, fără să depind de un microfon live sau de condiții acustice reale.
Înregistrarea pe SD: Inițial, sistemul suporta și salvarea audio pe card SD. Am eliminat complet această funcționalitate pentru a optimiza performanța — pe un microcontroler ESP32, operațiile de scriere pe SD introduceau întârzieri care afectau captura audio și inferența. Am lăsat doar funcții stub care returnează valori implicite, pentru a nu strica codul existent care le apelează.
Gestionarea memoriei: Am avut grijă să aloc toate bufferele mari (audio float, features, FFT) în PSRAM (memoria externă), păstrând în DRAM (memoria internă rapidă) doar bufferele FFT necesare bibliotecii ArduinoFFT și coeficienții mel sparse — aceștia din urmă fiind suficient de mici (~800 bytes) pentru a încăpea fără probleme. Această separare este esențială pe ESP32-S3, unde DRAM-ul este limitat dar PSRAM-ul oferă megabyți de spațiu suplimentar.
Leave A Comment?