软件用户
2013-02-01 17:14:09 +0000 2013-02-01 17:14:09 +0000
1554

如果达到一定的噪音水平,如何让机器在一段时间内 "白屏"(作为惩罚)?

我的孩子(4岁和5岁)在电脑上玩游戏时经常大叫。我找到了一个有效的治疗方法。当我听到吵闹的声音时,我就会进入游戏电脑进行ssh操作。

chvt 3; sleep 15; chvt 7

这在Linux系统下会关闭屏幕15秒。我已经告诉他们,电脑不喜欢大声的噪音。他们完全相信这一点,并向电脑求饶。他们变得安静了许多,但还没有达到我高兴的程度,所以我需要继续这个教育过程。然而,我并不总是在身边手动操作。

是否有可能实现自动化?盒子上连接着一个麦克风。如果响度超过某个阈值,那么我想运行一个命令。

答案 [6]

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

使用* SoX **中的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例子 ),调用 sleep 1分钟,测试音量,然后重复,你可以让它在后台运行。最后一步是将它添加到init脚本或服务文件中(取决于你的操作系统/发行版),这样你甚至不用手动启动它。

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

下面就用 纯数据 来实现。

Kid yell prevention using Pure Data Metro 是一个节拍器,"Metro 100 "每100毫秒都在敲击。

音频来自adc~,音量由env~计算。"pd dsp 0 "敲击时关闭DSP,"pd dsp 1 "打开。"shell "在shell中执行传来的命令,我用Linux的xrandr API将亮度设置为X,你需要适应Wayland的要求。

如你所见,宽限期和锁定比音频代码占用的空间大得多。

用环形缓冲器和/或移动平均数做一个解决方案应该比用sox做要容易得多。所以我觉得用Pure Data来解决这个问题并不是一个坏主意。但是屏幕空白本身和锁定不符合数据流范式。

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

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

检查"如何检测声音/音频的存在",作者Thormer M. Gil

基本上它每5秒记录一次声音,然后检查声音的振幅,使用sox,并决定是否触发一个脚本。我想你可以很容易的为你的孩子改编ruby脚本! 或者你也可以选择黑掉他提供的Python脚本(使用PyAudio)。

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

你可以通过这样的方式从麦克风中获取信息。

arecord -d1 /dev/null -vvv

你可能需要稍微调整一下设置,比如:

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

从那里开始,就是简单的解析输出的问题。

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

这是我见过的比较有趣的问题之一。我要感谢 tucuxi 提供了这么好的答案;我把它设置为 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
```。
46
42
2013-02-01 17:32:58 +0000

对于C或C++的解决方案,我的2分钱:也许不是最有效的方法,但在Linux上,你可以使用 ALSA API (Linux内置的音频处理库),使用一些数值技术(比如计算每秒的平均声级)来获得噪声的水平。

然后你可以无限循环检查,如果大于预设的treshold,你可以使用 X11库 来关闭屏幕几秒钟,或者用chvt调用system("chvt 3; sleep 15; chvt 7 ");命令(不那么优雅,但很有效)。

42