web-dev-qa-db-fra.com

Comment créer un "écran blanc" sur une machine pendant un certain temps (à titre de pénalité) si certains niveaux de bruit sont atteints?

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.

1542
Leonid Volnitsky

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.

641
tucuxi

Voici comment cela peut être fait avec Pure Data :

Kid yell prevention using 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 .

129
Janus Troelsen

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.

102
Atropo

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.

53
cha0site

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
43
Alexx Roche

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 ");.

41
H2CO3