2013-02-01 17:14:09 +0000 2013-02-01 17:14:09 +0000
1554

Wie mache ich eine Maschine für eine gewisse Zeit "bildschirmlos" (als Strafe), wenn bestimmte Geräuschpegel erreicht werden?

Meine Kinder (4 und 5) schreien viel, wenn sie Spiele am Computer spielen. Ich habe ein wirksames Mittel dagegen gefunden. Wenn ich laute Geräusche höre, logge ich mich in den Spielcomputer ein und mache:

chvt 3; sleep 15; chvt 7

Das schaltet den Bildschirm unter Linux für 15 Sekunden aus. Ich habe ihnen gesagt, dass der Computer keine lauten Geräusche mag. Sie glauben das total und betteln den Computer um Verzeihung an. Sie sind viel leiser geworden, aber nicht in dem Maße, dass ich zufrieden wäre, und so muss ich diesen Erziehungsprozess fortsetzen. Allerdings bin ich nicht immer da, um dies manuell zu tun.

Ist es möglich, dies zu automatisieren? An der Box ist ein Mikrofon angebracht. Wenn der Lautstärkepegel eine gewisse Schwelle überschreitet, möchte ich einen Befehl ausführen.

Antworten [6]

647
2013-02-01 17:36:38 +0000

Verwenden Sie sox von * SoX **, um ein kurzes Audio-Sample zu analysieren:

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

Mit -t .wav geben wir an, dass wir den wav-Typ verarbeiten, "|arecord -d 2" führt das Programm arecord für zwei Sekunden aus, -n gibt in die Null-Datei aus und mit stat geben wir an, dass wir eine Statistik wollen.

Die Ausgabe dieses Befehls, auf meinem System mit etwas Hintergrundsprache, ist:

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

Die maximale Amplitude kann dann extrahiert werden über:

grep -e "RMS.*amplitude" | tr -d ' ' | cut -d ':' -f 2

Wir grep für die gewünschte Zeile, verwenden tr , um die Leerzeichen wegzuschneiden und dann cut durch das Zeichen : und nehmen den zweiten Teil, was uns in diesem Beispiel 0.068383 ergibt. Wie in den Kommentaren vorgeschlagen, ist RMS ein besseres Maß für die Energie als die maximale Amplitude.

Sie können schließlich bc auf das Ergebnis anwenden, um Fließkommazahlen von der Kommandozeile aus zu vergleichen:

if (( $(echo "$value > $threshold" | bc -l) )) ; # ...

Wenn Sie eine Schleife bauen (siehe Bash-Beispiele ), die sleep für 1 Minute aufruft, die Lautstärke testet und dann wiederholt, können Sie sie im Hintergrund laufen lassen. Der letzte Schritt ist das Hinzufügen zu den Init-Skripten oder Service-Dateien (je nach Betriebssystem / Distro), so dass Sie es nicht einmal manuell starten müssen.

647
133
2013-02-05 16:20:11 +0000

Hier sehen Sie, wie es mit Pure Data gemacht werden kann:

Kid yell prevention using Pure Data Metro ist ein Metronom, und "metro 100" schlägt alle 100 ms.

Der Ton kommt von adc~, die Lautstärke wird von env~ berechnet. "pd dsp 0" schaltet den DSP beim Klopfen aus, "pd dsp 1" schaltet ihn ein. "shell" führt den übergebenen Befehl in einer Shell aus, ich verwende die Linux xrandr API, um die Helligkeit auf X zu setzen, das müssen Sie für Wayland anpassen.

Wie Sie sehen können, nehmen Gnadenfrist und Sperren viel mehr Platz ein als der Audiocode.

Eine Lösung mit Ringpuffern und/oder gleitenden Durchschnitten zu finden, sollte viel einfacher sein, als es mit sox zu tun. Ich denke also nicht, dass es eine schlechte Idee ist, Pure Data dafür zu verwenden. Aber das Ausblenden des Bildschirms selbst und das Sperren passt nicht zum Datenfluss-Paradigma.

Die PD-Datei ist unter gist.github.com: ysangkok - kidsyell.pd .

133
104
2013-02-01 17:32:18 +0000

Prüfen Sie "How to detect the presence of sound/audio" von Thomer M. Gil .

Grundsätzlich zeichnet es den Ton alle 5 Sekunden auf, prüft dann mit sox die Tonamplitude und entscheidet, ob ein Skript ausgelöst wird oder nicht. Ich denke, Sie können das ruby-Skript leicht für Ihre Kinder anpassen! Oder Sie können das Python-Skript (mit PyAudio), das er ebenfalls zur Verfügung gestellt hat, weiter bearbeiten.

104
54
2013-02-01 17:28:44 +0000

Sie können Informationen vom Mikrofon erhalten, indem Sie etwas wie folgt tun:

arecord -d1 /dev/null -vvv

Möglicherweise müssen Sie ein wenig mit den Einstellungen spielen, etwa so:

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

Von da an ist es eine einfache Angelegenheit, die Ausgabe zu parsen.

54
46
2013-02-08 14:10:44 +0000

Dies ist eine der lustigeren Fragen, die ich gesehen habe. Ich möchte mich bei tucuxi für eine so schöne Antwort bedanken; die ich als Bash-Skript

#!/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
``` eingestellt habe.
46
42
2013-02-01 17:32:58 +0000

Meine 2 Cents für die C- oder C++-Lösung: vielleicht nicht der effektivste Ansatz, aber unter Linux können Sie die ALSA API (eingebaute Audiobearbeitungsbibliothek von Linux) verwenden und eine numerische Technik anwenden (z. B. Berechnung des durchschnittlichen Schallpegels pro Sekunde), um den Geräuschpegel zu erhalten.

Dann können Sie ihn in einer Endlosschleife überprüfen, und wenn er größer als ein voreingestellter Schwellenwert ist, können Sie die X11-Bibliothek verwenden, um den Bildschirm für einige Sekunden abzuschalten, oder alternativ (weniger elegant, aber es funktioniert) den Befehl chvt mit system("chvt 3; sleep 15; chvt 7 "); aufrufen.

42