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

Jak sprawić, by maszyna "wygaszała ekran" na pewien czas (jako karę), jeśli osiągnięty zostanie określony poziom hałasu?

Moje dzieci (4 i 5 lat) dużo krzyczą podczas grania w gry na komputerze. Znalazłem na to skuteczne lekarstwo. Kiedy słyszę głośne dźwięki, wchodzę na komputer z grą i robię:

chvt 3; sleep 15; chvt 7

To wyłączy ekran na 15 sekund na Linuksie. Powiedziałem im, że komputer nie lubi głośnych dźwięków. Oni całkowicie w to uwierzyli i błagali komputer o przebaczenie. Stały się dużo cichsze, ale nie do poziomu, który by mnie zadowalał, więc muszę kontynuować ten proces edukacyjny. Jednak nie zawsze jestem w pobliżu, aby zrobić to ręcznie.

Czy można to zautomatyzować? Mikrofon jest podłączony do pudełka. Jeśli poziom głośności przekroczy jakiś próg, to chcę uruchomić komendę.

Odpowiedzi (6)

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

Użyj sox z * SoX ** do przeanalizowania krótkiej próbki audio:

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

Za pomocą -t .wav określamy, że przetwarzamy typ wav, "|arecord -d 2" wykonuje program arecord przez dwie sekundy, -n wysyła dane do pliku null, a za pomocą stat określamy, że chcemy statystyki.

Wyjście tego polecenia, na moim systemie z mową w tle, to:

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

Maksymalna amplituda może być wyodrębniona przez:

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

We grep dla linii, którą chcemy, użyj tr do obcięcia znaków spacji, a następnie cut go przez znak : i weź drugą część, która daje nam 0.068383 w tym przykładzie. Jak sugerują komentarze, RMS jest lepszą miarą energii niż maksymalna amplituda.

Możesz w końcu użyć bc na wyniku, aby porównać wartości zmiennoprzecinkowe z linii poleceń:

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

Jeśli zbudujesz pętlę (zobacz Bash examples ), która wywołuje sleep przez 1 minutę, testuje głośność, a następnie powtarza, możesz zostawić ją działającą w tle. Ostatnim krokiem jest dodanie go do skryptów init lub plików usług (w zależności od systemu operacyjnego / distro), tak, że nie trzeba nawet uruchamiać go ręcznie.

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

Oto jak można to zrobić za pomocą Pure Data :

Metro jest metronomem, a “metro 100” wali co 100 ms.

Dźwięk pochodzi z adc~, głośność jest obliczana przez env~. “pd dsp 0” wyłącza DSP przy waleniu, “pd dsp 1” włącza go. “shell” wykonuje przekazane polecenie w powłoce, ja używam linuksowego API xrandr do ustawienia jasności na X, musisz to dostosować do Waylanda.

Jak widać, okres karencji i blokada zajmują o wiele więcej miejsca niż kod audio.

Zrobienie rozwiązania z buforami pierścieniowymi i/lub średnimi kroczącymi powinno być o wiele łatwiejsze niż zrobienie tego z sox. Nie sądzę więc, że użycie Pure Data do tego celu jest złym pomysłem. Ale samo wygaszanie ekranu i blokowanie nie pasuje do paradygmatu przepływu danych.

Plik PD znajduje się pod adresem gist.github.com: ysangkok - kidsyell.pd .

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

Sprawdź “How to detect the presence of sound/audio” by Thomer M. Gil .

Zasadniczo nagrywa dźwięk co 5 sekund, następnie sprawdza amplitudę dźwięku, używając sox, i decyduje czy uruchomić skrypt czy nie. Myślę, że możesz łatwo dostosować skrypt ruby dla swoich dzieci! Możesz też zdecydować się na zhakowanie skryptu Pythona (używając PyAudio), który on również dostarczył.

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

Możesz uzyskać informacje z mikrofonu, wykonując coś w stylu:

arecord -d1 /dev/null -vvv

Być może będziesz musiał pobawić się trochę z ustawieniami, np:

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

Od tego momentu jest to prosta sprawa parsowania danych wyjściowych.

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

Jest to jedno z zabawniejszych pytań, jakie widziałem. Chciałbym podziękować tucuxi za tak wspaniałą odpowiedź; którą ustawiłem jako skrypt 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
```.
42
42
42
2013-02-01 17:32:58 +0000

Moje 2 centy dla rozwiązania w C lub C++: może nie jest to najbardziej efektywne podejście, ale na Linuksie, możesz użyć ALSA API (wbudowana biblioteka obsługi audio Linuksa) i użyć jakiejś techniki numerycznej (na przykład, obliczając średni poziom dźwięku w każdej sekundzie), aby uzyskać poziom hałasu.

Następnie możesz sprawdzić go w nieskończonej pętli i jeśli jest większy niż ustawiony próg, możesz użyć biblioteki X11 do wyłączenia ekranu na kilka sekund, lub alternatywnie (mniej elegancko, ale działa) wywołać polecenie chvt używając system("chvt 3; sleep 15; chvt 7 ");.