1538

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

chvt 3;  sleep 15;  chvt 7 

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

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

6 ответов6

642

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

129

Вот как это можно сделать с помощью 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.

102

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

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

53

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

arecord -d1 /dev/null -vvv

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

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

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

43

Это один из самых забавных вопросов, которые я видел. Я хотел бы поблагодарить 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
41

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

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

Всё ещё ищете ответ? Посмотрите другие вопросы с метками .