題 如果達到某些噪音水平,如何使機器“空白屏幕”一段時間(作為罰款)?


在電腦上玩遊戲時,我的孩子(4和5)大喊大叫。我找到了有效的治療方法。當我聽到吵鬧的聲音時,我會闖入遊戲電腦並做:

chvt 3;  sleep 15;  chvt 7 

這將在Linux上關閉屏幕15秒。我告訴他們電腦不喜歡大聲的噪音。他們完全相信這一點,並乞求計算機的寬恕。他們變得更安靜,但達不到我會高興的水平,所以我需要繼續這個教育過程。但是,我並不總是手動執行此操作。

是否有可能實現自動化?麥克風連接到盒子上。如果響度水平超過某個閾值,那麼我想運行一個命令。


1534
2018-02-01 17:14


起源


直到他們學會按CTRL + ALT + F7 - Suici Doga
@SuiciDoga嘿;他們不知道發生了什麼! - wizzwizz4


答案:


使用 sox 從 短襪 分析一個簡短的音頻樣本:

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

-t .wav 我們指定我們處理wav類型, "|arecord -d 2" 執行 arecord   程序兩秒鐘, -n 輸出到空文件並使用 stat 我們指定我們想要統計。

這個命令的輸出,在我的系統上有一些背景語音,是:

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

然後可以通過以下方式提取最大振幅:

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

我們 grep 對於我們想要的線路,請使用 tr 修剪空間字符然後 cut 它由 : 性格,並採取給我們的第二部分 0.068383 在這個例子中。正如評論所示, RMS 比最大振幅更能衡量能量。

你終於可以用了 bc 在結果上比較來自命令行的浮點值:

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

如果你構建一個循環(參見 Bash示例那個電話 睡覺 1分鐘,測試音量,然後重複,你可以讓它在後台運行。最後一步是將它添加到init腳本或服務文件(取決於您的OS /發行版),這樣您甚至不必手動啟動它。


640
2018-02-01 17:36



我會建議採取最大振幅。對於孩子來說,當他們的屏幕因為有人拍手或類似的東西而空白時,這並不好。平均值似乎更合適。 - orlp
只是澄清,“平均”你的意思是RMS Amplitude對嗎?如果噪聲在2秒內具有一致的響度,則平均振幅將接近0(正半部和負半部將相互抵消)。 - Luke
一系列樣品的簡單“能量”檢測器只是將所有峰的值加在一起。如果你不想,你甚至不必平均它。峰值就在任何地方 sample[n]>sample[n-1]&&sample[n]>sample[n+1] 我用這個作為測量歌曲能量的基本機制,效果很好。只需搜索您對音量水平感到滿意的幻數。 - Kaslai
我希望看到你的第一個命令的示例輸出,當它真正讓一個孩子大喊大叫,作為參考。 - Alvin Wong
對於所描述的用法(自動啟動+每隔幾分鐘運行一次),cron作業是正確的工具。比使用init腳本+ bash循環+睡眠更簡單的設置和更強大。 - m000


以下是如何完成的 純數據

Kid yell prevention using Pure Data

地鐵 是一個節拍器,“地鐵100”每100毫秒持續敲打。

音頻來自adc~,音量由env~計算。 “pd dsp 0”在被撞擊時關閉DSP,“pd dsp 1”將其打開。 “shell”在shell中執行傳遞的命令,我使用Linux xrandr API將亮度設置為X,你需要為Wayland調整它。

如您所見,寬限期和鎖定佔用的空間比音頻代碼更多。

使用環形緩衝區和/或移動平均線製作解決方案應該比使用它更容易 sox。所以我認為使用純數據並不是一個壞主意。但屏幕消隱和鎖定不符合數據流範例。

PD文件位於 gist.github.com:ysangkok - kidsyell.pd


128
2018-02-05 16:20



非常好!您可以使用這種技術使其響應非常靈敏:跟踪一分鐘內的平均聲級,然後將其用作基線,這樣當孩子超過基線超過20 dB時,就會觸發。然後它會自動調整到環境聲級。 - Hans-Christoph Steiner
是的,這很有道理@ Hans-ChristophSteiner。但在某種程度上,環境噪音水平是否真的要求孩子們大聲喊叫,因為它們會佔整體噪音的一小部分?當然,這僅適用於現有噪音為白色或粉紅色或以其他方式忽略的情況。 - Janus Troelsen
如果比平常更安靜,比如周末早上,那麼它會使它更敏感,因為它總是比環境水平高20分貝 - Hans-Christoph Steiner
這是擴展的PD? - nullpotent
@iccthedral:我用pd-extended來製作它,但我不知道我是否使用了任何pd擴展的特定結構。 - Janus Troelsen


校驗 Thomer M. Gil“如何檢測聲音/音頻的存在”

基本上它每5秒記錄一次聲音,而不是檢查聲音幅度 sox,並決定是否觸發腳本。我想你可以很容易地適應 ruby 給你孩子的劇本!或者你可以選擇破解他提供的Python腳本(使用PyAudio)。


101
2018-02-01 17:32



那些不到5秒的爆發可以避免被發現? - RhysW


您可以通過以下操作從麥克風獲取信息:

arecord -d1 /dev/null -vvv

您可能需要稍微使用設置,例如:

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

從那以後,解析輸出就是一件簡單的事情。


52
2018-02-01 17:28





這是我見過的更有趣的問題之一。我想要感謝 南美長吻海豚  這麼好的答案;我已經設置為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
2018-02-08 14:10



如果你通過在/etc/rc4.d/S99rc.local中添加一行來開始運行,然後將輸入麥克風從未放大更改為100%,你也可能最終被扔到tty3(你可以在睡眠之前跳回來)使用Ctrl + Alt + F7),如果您的鍵盤太大而無法打開終端,則運行sudo killall too_loud然後按Ctrl + Alt + F1並登錄。) - Alexx Roche


我對C或C ++解決方案的2美分:可能不是最有效的方法,但在Linux上,你可以使用 ALSA API (內置Linux的音頻處理庫)並使用一些數字技術(例如,每秒計算平均聲級)來獲得噪聲級別。

然後你可以在無限循環中檢查它,如果它大於預設的閾值,你可以使用 X11庫 關閉屏幕幾秒鐘,或者(不太優雅,但它的工作原理)調用 chvt 命令使用 system("chvt 3; sleep 15; chvt 7 ");


41
2018-02-01 17:32



如果使用命令我會考慮不同的東西 chvt。 ArchWiki 有很好的例子。 - A.D.