C'est à nouveau mon détecteur de ronflement.
Je suis devenu assez bon pour détecter un signal quand il y a quelque chose - peut suivre un ronflement qui s'écaille sur le mur jusqu'à une respiration que vous ne pouvez même pas entendre dans l'enregistrement. Le problème est que je ne peux pas dire quand le signal est tombé en dessous du niveau détectable et que l'application "entend des choses". Et, malheureusement, le ronflement / la respiration est souvent suffisamment irrégulier pour qu'une simple autocorrélation ou un schéma de synchronisation d'intervalle similaire ne soit pas d'un grand secours. (Et il est en fait probable que dans certains cas, le bruit soit plus régulier que la respiration.)
Alors, y a-t-il des astuces qui me manquent pour déterminer quand il n'y a pas de signal? Il semble que je sois confronté à un endroit difficile ici, étant donné que le "signal" est si bruyant pour commencer.
(Et peut-être que cela est lié à un autre problème que je rencontre: étrangement, je ne peux pas mesurer avec précision (ou même approximativement) le niveau du signal même lorsqu'il est assez fort. Étant donné que je dois utiliser des moyennes et des ratios roulants pour détecter le signal de toute façon, le niveau d'information se perd. Je cherche des astuces pour le reconstituer.)
Technique de base
(Pour Yoda)
Le signal audio est échantillonné (généralement à 8000 Hz, pour diverses raisons), puis FFT en 1024 blocs. (Dans mes expériences, les filtres de Hamming et les blocs qui se chevauchent semblent avoir peu d'effet, bien que ceux-ci puissent être revus plus tard.)
La FFT est divisée en "bandes" (actuellement 5, de taille légèrement asymétrique pour donner plus de détails sur le bas) et la "différence spectrale" et le niveau de chaque bande sont additionnés. Les moyennes à long terme des valeurs limitées de crête sont utilisées comme «seuils», et d'autres ajustements de biais sont utilisés pour maintenir un taux «supérieur au seuil» d'environ 20%.
Chaque valeur "au-dessus du seuil" reçoit un poids de 1 (sous le seuil est donné un poids de 0), mais ensuite ce poids est ajusté par la "variabilité" apparente (à environ 2 Hz) dans la bande, pour donner plus de poids aux bandes qui transportent un signal plus apparent.
Les poids des bandes sont additionnés, puis les poids additionnés des blocs suivants sont additionnés sur environ une seconde pour produire un "score" courant. Ceci est à nouveau comparé à un seuil moyen courant (plus plusieurs heuristiques) pour détecter le début / décalage du ronflement.
Mettre à jour
Il m'est soudain venu à l'esprit que si mon algorithme maintient efficacement un signal de niveau constant (par mon problème de niveau de signal), le moyen de mesurer efficacement le SNR est de mesurer le bruit lorsqu'il n'y a pas de signal.
Idéalement, les ronflements sont intermittents, avec beaucoup "d'air mort" entre les deux. Et je détecte déjà les enveloppes de ronflement. Donc, tout ce qui se trouve en dehors de l'enveloppe (entre la fin d'un ronflement et le début du suivant) est probablement du bruit! Je peux le mesurer (avec un degré modeste de précision / répétabilité). (Il a fallu trois essais pour arriver à un algorithme à moitié décent, bien sûr - la réalité ne correspond jamais à la théorie.)
Je n'ai donc pas encore la réponse complète, mais j'ai progressé.
(Bien que la technique ci-dessus me donne un assez bon proxy pour le SNR, j'ai toujours du mal à estimer le niveau de signal réel. Mes indications de "niveau relatif" peuvent être hors échelle pour un souffle à peine audible et ainsi de suite pour un cliquetis de fenêtre. J'ai besoin d'une sorte de proxy pour le niveau absolu.)