Comment créer un «écran vide» de la machine pendant un certain temps (à titre de pénalité) si certains niveaux de bruit sont atteints?

1549

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 poursuivre 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.

Leonid Volnitsky
la source
3
Jusqu'à ce qu'ils apprennent à appuyer sur CTRL + ALT + F7
Suici Doga
1
@SuiciDoga Hey; ils ne savent pas ce qui se passe!
wizzwizz4
Féliciter pour une solution technique. Mais je pense qu'il est important de toujours dire la vérité aux enfants.
user259412 le

Réponses:

645

Utilisez soxde SoX pour analyser un échantillon audio court:

sox -t .wav "|arecord -d 2" -n stat

Avec -t .wavnous spécifions nous traitons le type wav, "|arecord -d 2"exécutons le arecord programme pendant deux secondes, les -nsorties dans le fichier null et avec statnous spécifions nous voulons des statistiques.

La sortie de cette commande, sur mon système avec un discours d’arrière-plan, 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, greppour la ligne que nous voulons, utilisons trpour supprimer les caractères de l'espace, puis cutpar le :personnage et prenons la deuxième partie qui nous donne 0.068383dans cet exemple. Comme suggéré par les commentaires, RMS est une meilleure mesure de l'énergie que l'amplitude maximale.

Vous pouvez enfin utiliser bcle résultat pour comparer des valeurs à 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 la veille pendant 1 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 besoin de le lancer manuellement.

tucuxi
la source
282
Je déconseillerais de prendre l'amplitude maximale. Ce n'est pas agréable pour les enfants quand leur écran devient blanc simplement parce que quelqu'un applaudit ou quelque chose de similaire. La moyenne semble plus appropriée.
Orlp
34
Juste une clarification, par "moyenne", vous voulez dire RMS Amplitude right? L'amplitude moyenne sera proche de 0 si le bruit est d'une intensité constante sur les 2 secondes (les moitiés positive et négative s'annulent).
Luc
6
Un simple détecteur "d’énergie" pour une série d’échantillons consiste simplement à additionner la valeur de tous les pics. Vous n'auriez même pas à faire la moyenne si vous ne le vouliez pas. Un pic est n'importe quel point où sample[n]>sample[n-1]&&sample[n]>sample[n+1]j'ai utilisé cela comme un mécanisme rudimentaire pour mesurer l'énergie d'une chanson et cela fonctionne assez bien. Il suffit de rechercher un nombre magique auquel vous êtes satisfait du niveau de volume.
Kaslai
3
J'aimerais voir un exemple de sortie de votre première commande lorsqu'il s'agit vraiment d'un enfant qui crie, pour référence.
Alvin Wong
3
Pour l’utilisation décrite (démarrer automatiquement + exécuter toutes les quelques minutes), un travail cron est le bon outil à utiliser. Beaucoup plus simple à installer et plus robuste que d'utiliser init script + boucle bash + veille.
M000
131

Voici comment cela peut être fait avec Pure Data :

Prévention des hurlements d'enfants à l'aide de Pure Data

Metro est un métronome et "metro 100" n'arrête pas 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 bien 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 sur gist.github.com: ysangkok - kidsyell.pd .

Janus Troelsen
la source
11
très agréable! Vous pouvez faire en sorte que cette technique soit assez réactive: suivez le niveau sonore moyen sur une minute, puis utilisez-la comme base de référence. Ainsi, lorsque les enfants dépassent 20 dB au-dessus de la base, cela se déclenche. Ensuite, il s’ajuste automatiquement au niveau sonore ambiant.
Hans-Christoph Steiner
1
Oui, cela a du sens @ Hans-ChristophSteiner. Mais d’une certaine manière, le niveau de bruit ambiant n’obligerait-il pas les enfants à crier plus fort, puisqu’ils constitueraient une proportion moins importante du bruit général? Cela ne s'appliquerait bien entendu que si le bruit existant est blanc ou rose ou est ignoré.
Janus Troelsen
4
si elle était plus calme que d' habitude, comme un matin de week - end, alors il serait plus sensible, car il serait toujours 20 dB au- dessus du niveau ambiant
Hans-Christoph Steiner
Ceci est le PD étendu?
nullpotent
@iccthedral: J'ai utilisé pd-extended pour le créer, mais je ne sais pas si j'ai utilisé des constructions spécifiques à pd-extended.
Janus Troelsen
103

Cochez "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 son amplitude en utilisant soxet décide si un script doit être déclenché ou non. Je pense que vous pouvez facilement adapter le rubyscript à vos enfants! Ou vous pouvez choisir de pirater le script Python (en utilisant PyAudio) qu'il a également fourni.

Atropo
la source
5
Qu'en est-il des explosions de moins de 5 secondes qui évitent la détection?
RhysW
53

Vous pouvez obtenir des informations à partir du microphone en procédant comme suit:

arecord -d1 /dev/null -vvv

Vous pourriez avoir à jouer avec les paramètres un peu, tels que:

arecord -d1 -Dhw:0 -c2 -fS16_LE /dev/null -vvv

À partir de là, il suffit d'analyser la sortie.

cha0site
la source
44

C'est l'une des questions les plus amusantes que j'ai vues. Je tiens à remercier Tucuxi pour cette réponse satisfaisante. 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
Alexx Roche
la source
7
Si vous démarrez en ajoutant une ligne à /etc/rc4.d/S99rc.local et que vous modifiez ensuite le micro d'entrée de 100% à 100%, vous pouvez également être renvoyé à tty3 (vous pouvez revenir en arrière avant que Ctrl + Alt + F7), et si votre clavier est trop fort pour ouvrir un terminal, exécutez sudo killall too_loud puis Ctrl + Alt + F1 et connectez-vous là.)
Alexx Roche
41

Mes deux cents pour la solution C ou C ++: peut-être pas l'approche la plus efficace, mais sous Linux, vous pouvez utiliser l' API ALSA (bibliothèque de traitement audio intégrée de Linux) et utiliser une technique numérique (par exemple, calculer le son moyen niveler 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 la chvtcommande à l'aide de system("chvt 3; sleep 15; chvt 7 ");.

H2CO3
la source
2
Si vous utilisiez la commande, je considérerais alors quelque chose de différent chvt. ArchWiki a de beaux exemples.
AD