Jak ustawić „pusty ekran” maszyny na pewien okres czasu (jako karę), jeśli osiągnięty zostanie określony poziom hałasu?

1548

Moje dzieci (4 i 5) dużo krzyczą podczas grania w gry na komputerze. Znalazłem na to skuteczne lekarstwo. Kiedy słyszę głośne dźwięki, ssh do komputera gry i wykonuję:

chvt 3;  sleep 15;  chvt 7 

Spowoduje to wyłączenie ekranu na 15 sekund w systemie Linux. Powiedziałem im, że komputer nie lubi głośnych dźwięków. Całkowicie w to wierzą i błagają komputer o wybaczenie. Stały się znacznie cichsze, ale nie do poziomu, w którym byłbym szczęśliwy, dlatego muszę kontynuować ten proces edukacyjny. Jednak nie zawsze jestem w pobliżu, aby to zrobić ręcznie.

Czy można to zautomatyzować? Mikrofon jest przymocowany do pudełka. Jeśli poziom głośności przekroczy pewien próg, chcę uruchomić polecenie.

Leonid Wołyński
źródło
2
Dopóki nie nauczą się wciskać CTRL + ALT + F7
Suici Doga
1
@SuiciDoga Hej; nie wiedzą, co się dzieje!
wizzwizz4,
Gratuluję rozwiązania technicznego. Myślę jednak, że ważne jest, aby zawsze mówić dzieciom prawdę.
Peter

Odpowiedzi:

645

Skorzystaj soxz SoX analizować krótką próbkę dźwięku:

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

Gdy -t .wavokreślamy, przetwarzamy typ wav, "|arecord -d 2"uruchamiamy arecord program przez dwie sekundy, -ngenerujemy dane wyjściowe do pliku zerowego, a wraz z tym statokreślamy, że chcemy statystyki.

Wynik tego polecenia, w moim systemie z pewną mową w tle, jest następujący:

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

Maksymalną amplitudę można następnie uzyskać:

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

W grepprzypadku linii, którą chcemy, użyj, traby odciąć znaki spacji, a następnie cutprzez :znak i weź drugą część, która daje nam 0.068383w tym przykładzie. Jak sugerują komentarze, RMS jest lepszą miarą energii niż maksymalna amplituda.

Możesz wreszcie użyć bcwyniku, aby porównać wartości zmiennoprzecinkowe z wiersza polecenia:

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

Jeśli zbudujesz pętlę (patrz przykłady Bash ), która wywołuje tryb uśpienia na 1 minutę, testuje wolumin, a następnie powtarza, możesz pozostawić go działający w tle. Ostatnim krokiem jest dodanie go do skryptów inicjujących lub plików serwisowych (w zależności od systemu operacyjnego / dystrybucji), dzięki czemu nie trzeba nawet uruchamiać go ręcznie.

Tucuxi
źródło
280
Odradzałbym przyjmowanie maksymalnej amplitudy. To nie jest miłe dla dzieci, gdy ich ekran gaśnie tylko dlatego, że ktoś klasnął lub coś podobnego. Średnia wydaje się bardziej odpowiednia.
orlp
34
Tylko wyjaśnienie, przez „średni” rozumiesz amplitudę RMS, prawda? Średnia amplituda będzie bliska 0, jeśli hałas ma stałą głośność przez 2 sekundy (dodatnie i ujemne połówki się znoszą).
Łukasz
6
Prostym detektorem „energii” dla serii próbek jest po prostu dodanie wartości wszystkich pików razem. Nie musiałbyś nawet tego uśredniać, gdybyś tego nie chciał. Szczyt to po prostu punkt, w którym sample[n]>sample[n-1]&&sample[n]>sample[n+1]wykorzystałem go jako podstawowy mechanizm pomiaru energii piosenki i działa całkiem dobrze. Po prostu wyszukaj magiczną liczbę, przy której jesteś zadowolony z poziomu głośności.
Kaslai
3
Chciałbym zobaczyć przykładowy wynik twojego pierwszego polecenia, gdy naprawdę chodzi o krzyczące dziecko, w celach informacyjnych.
Alvin Wong
3
Dla opisanego użycia (uruchom automatycznie + uruchamiaj co kilka minut) właściwym narzędziem jest zadanie cron. Znacznie prostszy w konfiguracji i bardziej niezawodny niż użycie skryptu inicjującego + pętli bash + uśpienia.
m000
130

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

Zapobieganie krzyczeniu dzieci za pomocą Pure Data

Metro to metronom, a „metro 100” nieustannie uderza w każde 100 ms.

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

Jak widać, okres karencji i blokowanie zajmuje znacznie więcej miejsca niż kod dźwiękowy.

Stworzenie rozwiązania z buforami pierścieniowymi i / lub średnimi ruchomymi powinno być znacznie łatwiejsze niż zrobienie tego sox. Nie sądzę więc, aby używanie do tego Pure Data było złym pomysłem. Ale sam ekran wygasa, a blokowanie nie pasuje do paradygmatu przepływu danych.

Plik PD znajduje się na stronie gist.github.com: ysangkok - kidsyell.pd .

Janus Troelsen
źródło
11
bardzo dobrze! Możesz sprawić, że będzie to dość responsywne przy użyciu tej techniki: śledź średni poziom dźwięku w ciągu minuty, a następnie użyj go jako linii podstawowej, aby gdy dzieci przekroczyły 20 dB powyżej linii podstawowej, wyzwalało się. Następnie automatycznie dostosuje się do poziomu dźwięku otoczenia.
Hans-Christoph Steiner
1
Tak, to ma sens @ Hans-ChristophSteiner. Ale w pewnym sensie, czy poziom hałasu w otoczeniu nie wymagałby od dzieci głośniej krzyczeć, ponieważ stanowiłyby mniejszą część ogólnego hałasu? Oczywiście miałoby to zastosowanie tylko wtedy, gdy istniejący hałas jest biały lub różowy lub w inny sposób zignorowany.
Janus Troelsen
4
gdyby było ciszej niż zwykle, jak w weekendowy poranek, to uczyniłoby to bardziej czułym, ponieważ zawsze byłoby 20 dB powyżej poziomu otoczenia
Hans-Christoph Steiner
To jest rozszerzone PD?
nullpotent
@iccthedral: Użyłem do tego pd-Extended, ale nie wiem, czy użyłem jakichś specyficznych konstrukcji pd-Extended.
Janus Troelsen
102

Sprawdź „Jak wykryć obecność dźwięku / dźwięku” Thomer M. Gil .

Zasadniczo rejestruje dźwięk co 5 sekund, a następnie sprawdza amplitudę dźwięku za pomocą soxi decyduje, czy uruchomić skrypt, czy nie. Myślę, że możesz łatwo dostosować rubyskrypt dla swoich dzieci! Możesz też zhakować skrypt Pythona (używając PyAudio), który on również dostarczył.

Atropo
źródło
5
Co z wybuchami krótszymi niż 5 sekund, które unikają wykrycia?
RhysW
53

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

arecord -d1 /dev/null -vvv

Być może będziesz musiał trochę pograć z ustawieniami, takimi jak:

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

Odtąd analizowanie wyników jest proste.

cha0site
źródło
43

To jedno z ciekawszych pytań, jakie widziałem. Chciałbym podziękować tucuxi za tak dobrą odpowiedź; które 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
Alexx Roche
źródło
7
Jeśli zaczniesz to uruchamiać od dodania linii do /etc/rc4.d/S99rc.local, a następnie zmień mikrofon wejściowy z nieamplifikowanego na 100%, możesz również zostać wyrzucony na tty3 (możesz odskoczyć przed snem) Ctrl + Alt + F7), a jeśli twoja klawiatura jest zbyt głośna, aby otworzyć terminal, aby uruchomić sudo killall too_loud, to Ctrl + Alt + F1 i zaloguj się tam.)
Alexx Roche 10'13
41

Moje 2 centy za rozwiązanie C lub C ++: może nie jest to najbardziej efektywne podejście, ale w systemie Linux możesz użyć interfejsu API ALSA (wbudowana biblioteka obsługi dźwięku w systemie Linux) i zastosować technikę numeryczną (na przykład obliczenie średniego dźwięku poziom co sekundę), aby uzyskać poziom hałasu.

Następnie możesz to sprawdzić w nieskończonej pętli, a jeśli jest większy niż wstępnie ustawiony próg, możesz użyć biblioteki X11, aby wyłączyć ekran na kilka sekund, lub alternatywnie (mniej elegancko, ale działa) wywołać chvtpolecenie za pomocą system("chvt 3; sleep 15; chvt 7 ");.

H2CO3
źródło
2
Jeśli użyję polecenia, rozważę coś innego chvt. ArchWiki ma ładne przykłady.
AD