Questo è di nuovo il mio rilevatore di russare.
Sono diventato abbastanza bravo a rilevare un segnale quando c'è qualcosa lì - posso rintracciare da un russare peeling a parete al respiro che non riesci nemmeno a sentire nella registrazione. Il problema è che non riesco a capire quando il segnale è sceso sotto il livello rilevabile e l'app sta semplicemente "ascoltando le cose". E, sfortunatamente, russare / respirare è spesso abbastanza irregolare che è improbabile che una semplice autocorrelazione o un simile schema di temporizzazione degli intervalli possano aiutare molto. (Ed è in realtà probabile che in alcuni casi il rumore sia più regolare della respirazione.)
Quindi, ci sono dei trucchi che mi mancano per capire quando non c'è segnale? In un certo senso sembra che mi trovo in un posto difficile qui, dato che il "segnale" è così simile al rumore per cominciare.
(E forse questo è correlato a un altro problema che sto riscontrando: stranamente, non riesco a misurare con precisione (o anche approssimativamente) il livello del segnale anche quando è abbastanza forte. Dato che ho bisogno di usare medie mobili e rapporti per rilevare il segnale comunque, il tipo di informazione di livello si perde. Sto cercando alcuni trucchi per ricostituirla.)
Tecnica di base
(Per Yoda)
Il segnale audio viene campionato (generalmente a 8000Hz, per vari motivi), quindi trasformato in 1024 blocchi. (Nei miei esperimenti i filtri di Hamming e i blocchi sovrapposti sembrano avere scarso effetto, sebbene possano essere rivisitati in seguito.)
La FFT è divisa in "bande" (attualmente 5, leggermente inclinate nelle dimensioni per posizionare più dettagli nella parte bassa) e viene sommata la "differenza spettrale" e il livello di ciascuna banda. Le medie a lungo termine dei valori di picco limitati vengono utilizzate come "soglie" e ulteriori aggiustamenti di polarizzazione vengono utilizzati per mantenere un tasso di "oltre soglia" di circa il 20%.
A ciascun valore "sopra soglia" viene assegnato un peso di 1 (sotto soglia viene assegnato un peso di 0), ma poi quel peso viene regolato dall'apparente "variabilità" (a circa 2Hz) nella banda, per dare più peso alle bande che portano un segnale più apparente.
I pesi delle bande vengono sommati e quindi i pesi sommati dei blocchi successivi vengono sommati per circa un secondo per produrre una "partitura" corrente. Questo viene nuovamente confrontato con una soglia media corrente (più diverse euristiche) per rilevare l'insorgenza / offset del russare.
Aggiornare
Improvvisamente mi è venuto in mente che se il mio algoritmo mantiene efficacemente un segnale di livello costante (per il mio problema di livello del segnale), il modo per misurare efficacemente SNR è misurare il rumore quando non c'è segnale.
Convenientemente, i russamenti sono intermittenti, con molta "aria morta" nel mezzo. E sto già rilevando le buste del russare. Quindi qualsiasi cosa al di fuori dell'inviluppo (tra la fine di un russare e l'inizio del successivo) è presumibilmente rumore! Questo posso (con un certo grado di precisione / ripetibilità) misurare. (Ci sono voluti tre tentativi per trovare un algoritmo decente a metà strada, ovviamente - la realtà non corrisponde mai alla teoria.)
Quindi non ho ancora la risposta completa, ma ho fatto progressi.
(Mentre la tecnica di cui sopra mi dà un proxy abbastanza buono per SNR, sto ancora avendo problemi a stimare il livello effettivo del segnale. Le mie indicazioni di "livello relativo" possono essere fuori scala per un respiro a malapena udibile e così per un sonaglio di finestra. Ho bisogno di una sorta di proxy per il livello assoluto.)