Перейти к содержимому

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

1536

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

chvt 3; sleep 15; chvt 7 

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

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

157 244 просмотра
Leonid Volnitsky спросил 13 лет назад
L 4 803

6 ответов

642

Use sox from SoX to analyze a short audio sample:

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

With -t .wav we specify we process the wav type, "|arecord -d 2" executes the arecord program for two seconds, -n outputs to the null file and with stat we specify we want statistics.

The output of this command, on my system with some background speech, is:

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 

The maximum amplitude can then be extracted via:

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

We grep for the line we want, use tr to trim away the space characters and then cut it by the : character and take the second part which gives us 0.068383 in this example. As suggested by comments, RMS is a better measure of energy than maximum amplitude.

You can finally use bc on the result to compare floating-point values from the command-line:

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

If you build a loop (see Bash examples) that calls sleep for 1 minute, tests the volume, and then repeats, you can leave it running in the background. The last step is to add it to the init scripts or service files (depending on your OS / distro), such that you do not even have to launch it manually.

Я бы не рекомендовал брать максимальную амплитуду. Детям не нравится, когда их экран гаснет только потому, что кто-то хлопнул или что-то подобное. Среднее кажется более подходящим.

orlp · 13 лет назад · 277

Просто уточнение, под «средним» вы подразумеваете среднеквадратичную амплитуду, верно? Средняя амплитуда будет близка к 0, если шум имеет постоянную громкость в течение 2 секунд (положительная и отрицательная половины компенсируют друг друга).

Luke · 13 лет назад · 33

Простой «энергетический» детектор для серии образцов - это просто сложение значений всех пиков вместе. Вам не нужно было бы даже усреднять это, если вы не хотите. Пик - это просто любая точка, где sample [n]> sample [n-1] && sample [n]> sample [n + 1] Я использовал это как элементарный механизм для измерения энергии песни, и это работает неплохо. Просто найдите магическое число, на котором вы довольны уровнем громкости.

Kaslai · 13 лет назад · 6

Я хотел бы увидеть пример вывода вашей первой команды, когда дело доходит до крика ребенка, для справки.

Alvin Wong · 13 лет назад · 3

Если вы спите в течение минуты каждый раз, а затем тестируете только 2 секунды звука, разве вы не пропустите ни одного (возможно, прерывистого) крика? Я бы предложил немного увеличить время записи и значительно сократить время отдыха между тестами. Может быть 5с спать, 5с тест?

jozzas · 13 лет назад · 0

Я бы заменил "grep -e" RMS. * Ampitude "| tr -d '' | cut -d ':' -f 2с помощьюsed -En 's # RMS [[: space:]] + амплитуда: [[: space:]] + ([. [: digit:]] +) $ # \ 1 # p'`

jcayzac · 13 лет назад · 1

Для описанного использования (запуск автоматически + запуск каждые несколько минут) задание cron является правильным инструментом для использования. Гораздо проще в настройке и более надежным, чем использование скрипта инициализации + цикла bash + сна.

m000 · 13 лет назад · 3

Добавить к комментарию @ nightcracker. Сначала вы должны взять несколько образцов записей, когда дети будут кричать, чтобы вы получили представление о вашем пороге с точки зрения амплитуды / энергии с микрофона. Затем, когда вы запустите свою программу мониторинга, выполните согласованную фильтрацию с этой записью сэмпла, прежде чем вычислять амплитуду / энергию сигнала, которая должна позаботиться о том, чтобы другой источник шума не вызвал ложную тревогу.

LWZ · 13 лет назад · 0

Я попытался построить сценарий оболочки на основе решения выше. Построил его для Mac с использованием OSX Yosemite (10.10.2). Сценарий можно найти здесь: https://github.com/ohenrik/hush

Ole Henrik Skogstrøm · 11 лет назад · 0
tucuxi ответил 13 лет назад
T 4 363
129

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

Kid yell prevention using 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 .

очень хорошо! Используя эту технику, вы можете сделать так, чтобы она была достаточно отзывчивой: отслеживайте средний уровень звука за минуту, затем используйте его в качестве базовой линии, чтобы, когда дети превышали базовую линию на 20 дБ, это срабатывало. Затем он автоматически адаптируется к уровню окружающего звука.

Hans-Christoph Steiner · 13 лет назад · 11

Да, это имеет смысл @ Hans-ChristophSteiner. Но в некотором смысле, разве уровень окружающего шума на самом деле не требует, чтобы дети кричали громче, так как они составляли бы меньшую долю общего шума? Это, конечно, применимо только в том случае, если существующий шум является белым или розовым или иным образом игнорируется.

Janus Troelsen · 13 лет назад · 1

если бы он был тише, чем обычно, например утром в выходные дни, то это сделало бы его более чувствительным, поскольку оно всегда было бы на 20 дБ выше уровня окружающей среды

Hans-Christoph Steiner · 13 лет назад · 4

Это расширенный ПД?

nullpotent · 13 лет назад · 0

@iccthedral: я использовал pd-extended для этого, но я не знаю, использовал ли я pd-extended определенные конструкции.

Janus Troelsen · 13 лет назад · 0

Я написал почти то же самое решение - но я не смог вызвать оболочку, как вы. Я закончил тем, что делал это с привязками Си. Так что я думаю, что это конкретно для расширенной версии. Я предпочитаю PD-vanilla, так как часто портирую патчи PD на Android. Тем не менее, я люблю это решение. PD такой мощный.

nullpotent · 13 лет назад · 0

@JanusTroelsen Включение этого файла PD непосредственно в ваш ответ (с помощью Ctrl + K или 4 пробелов) не приведет к превышению ограничения на количество символов.

wizzwizz4 · 7 лет назад · 0

@ wizzwizz4, так как он не совсем читается человеком, я бы предпочел не

Janus Troelsen · 7 лет назад · 0
Janus Troelsen ответил 13 лет назад
J 1 733
102

Check "How to detect the presence of sound/audio" by Thomer M. Gil.

Basically it records the sound every 5 seconds, than checks for the sound amplitude, using sox, and decides if trigger a script or not. I think you can easily adapt the ruby script for your children! Or you can choose to hack away on the Python script (using PyAudio) that he has provided as well.

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

RhysW · 13 лет назад · 5
Atropo ответил 13 лет назад
A 1 485
53

You can get information from the microphone by doing something like:

arecord -d1 /dev/null -vvv 

You might have to play with the settings a little, such as:

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

From there on out, it's a simple matter of parsing the output.

cha0site ответил 13 лет назад
C 702
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 

Если вы запустите этот процесс, добавив строку в /etc/rc4.d/S99rc.local, а затем измените входной микрофон с неусиленного на 100%, вы тоже можете в конечном итоге быть сброшенным на tty3 (вы можете отскочить назад до того, как наступит сон с Ctrl + Alt + F7), и если ваша клавиатура слишком громкая, чтобы открыть терминал, чтобы запустить sudo killall too_loud, тогда Ctrl + Alt + F1 и войдите в нее.)

Alexx Roche · 13 лет назад · 7
Alexx Roche ответил 13 лет назад
A 671
41

My 2 cents for the C or C++ solution: maybe not the most effective approach, but on Linux, you can use the ALSA API (built-in audio handling library of Linux) and use some numerical technique (for example, calculating the average sound level each second) to obtain the level of noise.

Then you can check it in an infinite loop, and if it's greater than a preset treshold, you can use the X11 library to turn off the screen for some seconds, or alternatively (less elegant, but it works) invoke the chvt command using system("chvt 3; sleep 15; chvt 7 ");.

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

A.D. · 13 лет назад · 0
H2CO3 ответил 13 лет назад
H 904