Как сделать машину «пустым экраном» на некоторое время (в качестве штрафа), если достигнут определенный уровень шума?

1549

Мои дети (4 и 5) много кричат, играя в игры на компьютере. Я нашел эффективное лекарство от этого. Когда я слышу громкие звуки, я захожу в игровой компьютер и делаю:

chvt 3;  sleep 15;  chvt 7 

Это выключит экран на 15 секунд в Linux. Я сказал им, что компьютер не любит громкие звуки. Они полностью верят в это и просят у компьютера прощения. Они стали намного тише, но не до того уровня, на котором я был бы счастлив, и поэтому мне нужно продолжить этот образовательный процесс. Тем не менее, я не всегда готов сделать это вручную.

Можно ли это автоматизировать? Микрофон прикреплен к коробке. Если уровень громкости превышает некоторый порог, тогда я хочу запустить команду.

Леонид Вольницкий
источник
3
Пока они не научатся нажимать CTRL + ALT + F7
Suici Doga
1
@SuiciDoga Привет; они не знают, что происходит!
wizzwizz4
Поздравляем за техническое решение. Но я думаю, важно всегда говорить правду детям.
user259412

Ответы:

645

Используйте 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 ), который вызывает сон в течение 1 минуты, проверяет громкость, а затем повторяет, вы можете оставить его работающим в фоновом режиме. Последний шаг - добавить его в сценарии инициализации или служебные файлы (в зависимости от вашей ОС / дистрибутива), чтобы вам даже не пришлось запускать его вручную.

белый дельфин
источник
282
Я бы не рекомендовал брать максимальную амплитуду. Детям не нравится, когда их экран гаснет только потому, что кто-то хлопнул или что-то в этом роде. Среднее кажется более подходящим.
13
34
Просто уточнение, под «средним» вы подразумеваете среднеквадратичную амплитуду, верно? Средняя амплитуда будет близка к 0, если шум имеет постоянную громкость в течение 2 секунд (положительная и отрицательная половины компенсируют друг друга).
Люк
6
Простой «энергетический» детектор для серии образцов - это просто сложение значений всех пиков вместе. Вам бы не пришлось даже усреднять это, если вы не хотите. Пик - это просто точка, где sample[n]>sample[n-1]&&sample[n]>sample[n+1]я использовал это как элементарный механизм для измерения энергии песни, и он работает довольно хорошо. Просто найдите магическое число, на котором вы довольны уровнем громкости.
Каслай
3
Я хотел бы увидеть пример вывода вашей первой команды, когда дело доходит до крика ребенка, для справки.
Элвин Вонг
3
Для описанного использования (запуск автоматически + запуск каждые несколько минут) задание cron является правильным инструментом для использования. Гораздо проще в настройке и более надежным, чем использование скрипта инициализации + цикла bash + сна.
m000
131

Вот как это можно сделать с помощью Pure Data :

Профилактика криков малыша с использованием Pure Data

Метро - это метроном, и «Метро 100» продолжает стучать каждые 100 мс.

Звук идет от adc ~, громкость рассчитывается по env ~. «pd dsp 0» отключает DSP при ударе, «pd dsp 1» включает его. «shell» выполняет переданную команду в оболочке, я использую Linux Xrandr API для установки яркости на X, вам нужно адаптировать это для Wayland.

Как видите, льготный период и блокировка занимают намного больше места, чем аудиокод.

Создание решения с кольцевыми буферами и / или скользящими средними должно быть намного проще, чем с ним sox. Поэтому я не считаю плохой идеей использовать для этого Чистые данные. Но экран сам по себе гаснет, и блокировка не соответствует парадигме потока данных.

Файл PD находится по адресу gist.github.com: ysangkok - kidsyell.pd .

Янус Троелсен
источник
11
очень хорошо! Вы можете сделать так, чтобы это было очень отзывчиво, используя эту технику: отслеживайте средний уровень звука за минуту, затем используйте его в качестве базовой линии, чтобы, когда дети превышали базовую линию на 20 дБ, это срабатывало. Затем он автоматически адаптируется к уровню окружающего звука.
Ганс-Кристоф Штайнер,
1
Да, это имеет смысл @ Hans-ChristophSteiner. Но в некотором смысле, разве уровень окружающего шума на самом деле не требует, чтобы дети кричали громче, поскольку они составляют меньшую долю общего шума? Это, конечно, применимо только в том случае, если существующий шум является белым или розовым или иным образом игнорируется.
Янус Троелсен
4
если бы он был тише, чем обычно, как утром в выходные, то это сделало бы его более чувствительным, поскольку он всегда был бы на 20 дБ выше уровня окружающей среды
Ханс-Кристоф Штайнер,
Это расширенный ПД?
Нульпотент
@iccthedral: я использовал pd-extended, но я не знаю, использовал ли я pd-extended определенные конструкции.
Янус Троелсен
103

Проверка "Как обнаружить наличие звука / звука" от Thomer M. Gil .

В основном он записывает звук каждые 5 секунд, затем проверяет амплитуду звука, используя sox, и решает, запускать сценарий или нет. Я думаю, что вы можете легко адаптировать rubyсценарий для ваших детей! Или вы можете выбрать взломать скрипт Python (используя PyAudio), который он также предоставил.

Atropo
источник
5
А как насчет тех вспышек менее 5 секунд, которые избегают обнаружения?
RhysW
53

Вы можете получить информацию с микрофона, выполнив что-то вроде:

arecord -d1 /dev/null -vvv

Возможно, вам придется немного поиграть с настройками, такими как:

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

С этого момента, это просто вопрос анализа результатов.

cha0site
источник
44

Это один из самых забавных вопросов, которые я видел. Я хотел бы поблагодарить 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
Алекс Рош
источник
7
Если вы начнете эту работу, добавив строку в /etc/rc4.d/S99rc.local, а затем измените входной микрофон с неусиленного на 100%, вы тоже можете в конечном итоге быть сброшенным на tty3 (вы можете отскочить назад, пока сон с Ctrl + Alt + F7), и если ваша клавиатура слишком громкая, чтобы открыть терминал, чтобы запустить sudo killall too_loud, тогда Ctrl + Alt + F1 и войдите в нее.)
Alexx Roche
41

Мои 2 цента за решение C или C ++: возможно, не самый эффективный подход, но в Linux вы можете использовать ALSA API (встроенную библиотеку обработки звука в Linux) и использовать некоторые числовые методы (например, вычисление среднего звука). уровень каждую секунду), чтобы получить уровень шума.

Затем вы можете проверить это в бесконечном цикле, и, если он превышает заданный порог, вы можете использовать библиотеку X11, чтобы отключить экран на несколько секунд, или, альтернативно (менее элегантно, но это работает), вызвать chvtкоманду, используя system("chvt 3; sleep 15; chvt 7 ");.

Н2СО3
источник
2
Если использовать команду, я бы подумал о чем-то другом chvt. ArchWiki имеет хорошие примеры.
AD