Mes enfants (4 et 5 ans) hurlent beaucoup en jouant à des jeux sur l'ordinateur. J'ai trouvé un traitement efficace pour cela. Quand j'entends des bruits forts, je ssh dans l'ordinateur de jeu et je fais:
chvt 3; sleep 15; chvt 7
Cela éteindra l'écran pendant 15 secondes sous Linux. Je leur ai dit que l'ordinateur n'aime pas les bruits forts. Ils y croient totalement et demandent pardon à l'ordinateur. Ils sont devenus beaucoup plus calmes, mais pas au niveau où je serais heureux, et je dois donc continuer ce processus éducatif. Cependant, je ne suis pas toujours là pour le faire manuellement.
Est-il possible d'automatiser cela? Un microphone est attaché à la boîte. Si le niveau de volume dépasse un certain seuil, je souhaite exécuter une commande.
Utilisez sox
à partir deSoXpour analyser un bref échantillon audio:
sox -t .wav "|arecord -d 2" -n stat
Avec -t .wav
nous spécifions que nous traitons le type wav, "|arecord -d 2"
exécute le programme arecord
pendant deux secondes, -n
est affiché dans le fichier null et avec stat
nous spécifions nous voulons des statistiques.
La sortie de cette commande, sur mon système avec quelques paroles de fond, est la suivante:
Recording WAVE 'stdin' : Unsigned 8 bit, Rate 8000 Hz, Mono
Samples read: 16000
Length (seconds): 2.000000
Scaled by: 2147483647.0
Maximum amplitude: 0.312500
Minimum amplitude: -0.421875
Midline amplitude: -0.054688
Mean norm: 0.046831
Mean amplitude: -0.000044
RMS amplitude: 0.068383
Maximum delta: 0.414063
Minimum delta: 0.000000
Mean delta: 0.021912
RMS delta: 0.036752
Rough frequency: 684
Volume adjustment: 2.370
L’amplitude maximale peut alors être extraite via:
grep -e "RMS.*amplitude" | tr -d ' ' | cut -d ':' -f 2
Nous grep
pour la ligne désirée, utilisons tr
pour supprimer les espaces, puis cut
it par le caractère :
et prenons la deuxième partie qui nous donne 0.068383
dans cet exemple. Comme suggéré par les commentaires, RMS est une meilleure mesure de l'énergie que l'amplitude maximale.
Vous pouvez enfin utiliser bc
sur le résultat pour comparer les valeurs en virgule flottante à partir de la ligne de commande:
if (( $(echo "$value > $threshold" | bc -l) )) ; # ...
Si vous créez une boucle (voir Exemples Bash ) qui appelle sleep pendant une minute, teste le volume, puis se répète, vous pouvez la laisser fonctionner en arrière-plan. La dernière étape consiste à l'ajouter aux scripts d'initialisation ou aux fichiers de service (selon votre système d'exploitation/distribution), de sorte que vous n'ayez même pas à le lancer manuellement.
Voici comment cela peut être fait avec Pure Data :
Metro est un métronome, et "metro 100" continue de frapper toutes les 100 ms.
Le son vient de adc ~, le volume est calculé par env ~. "pd dsp 0" désactive le DSP lorsqu'il est activé, "pd dsp 1" l'allume. "Shell" exécute la commande passée dans un shell. J'utilise l'API xrandr de Linux pour définir la luminosité sur X. Vous devez l'adapter à Wayland.
Comme vous pouvez le constater, le délai de grâce et le verrouillage prennent beaucoup plus de place que le code audio.
Faire une solution avec des anneaux tampons et/ou des moyennes mobiles devrait être beaucoup plus facile que de le faire avec sox
. Donc, je ne pense pas que ce soit une mauvaise idée d'utiliser Pure Data pour cela. Mais le masquage d'écran et le verrouillage ne cadrent pas avec le paradigme du flux de données.
Le fichier PD se trouve dans Gist.github.com: ysangkok - kidsyell.pd .
Vérifiez "Comment détecter la présence de son/audio" de Thomer M. Gil .
Fondamentalement, il enregistre le son toutes les 5 secondes, puis vérifie l’amplitude du son, en utilisant sox
, et décide si un script doit être déclenché ou non. Je pense que vous pouvez facilement adapter le script Ruby
à vos enfants! Ou vous pouvez choisir de pirater le script Python (en utilisant PyAudio) qu'il a également fourni.
Vous pouvez obtenir des informations à partir du microphone en procédant comme suit:
arecord -d1 /dev/null -vvv
Vous devrez peut-être jouer un peu avec les paramètres, tels que:
arecord -d1 -Dhw:0 -c2 -fS16_LE /dev/null -vvv
À partir de là, il suffit d'analyser la sortie.
C'est l'une des questions les plus amusantes que j'ai rencontrées. Je voudrais remercier tucuxi pour cette bonne réponse; que j'ai défini comme script bash
#!/bin/bash
threshold=0.001
# we should check that sox and arecord are installed
if [ $1 ]; then threshold=$1; fi
while [ 1 -gt 0 ]; do
if(( $(echo "$(sox -t .wav '|arecord -d 2' -n stat 2>&1|grep -e 'RMS.*amplitude'|tr -d ' '|cut -d ':' -f 2 ) > $threshold"|bc -l) ))
then
chvt 3; sleep 5; chvt 7;
fi
done
Mes 2 centimes pour la solution C ou C++: peut-être pas l'approche la plus efficace, mais sous Linux, vous pouvez utiliser le ALSA API (bibliothèque de traitement audio intégrée de Linux) et utiliser une technique numérique (par exemple, calculer le niveau sonore moyen chaque seconde) pour obtenir le niveau de bruit.
Ensuite, vous pouvez le vérifier dans une boucle infinie, et s’il est supérieur à un seuil prédéfini, vous pouvez utiliser la bibliothèque X11 pour éteindre l’écran pendant quelques secondes, ou bien (moins élégant, mais cela fonctionne) invoquer le bouton Commande chvt
utilisant system("chvt 3; sleep 15; chvt 7 ");
.