Questão Como faço uma máquina “tela em branco” por um período de tempo (como penalidade) se determinados níveis de ruído forem atingidos?


Meus filhos (4 e 5) gritam muito quando jogam no computador. Eu encontrei uma cura eficaz para isso. Quando ouço ruídos altos, eu ssh no computador do jogo e faço:

chvt 3;  sleep 15;  chvt 7 

Isso desligará a tela por 15 segundos no Linux. Eu disse a eles que o computador não gosta de ruídos altos. Eles acreditam totalmente nisso e imploram perdão ao computador. Eles se tornaram muito mais silenciosos, mas não no nível que eu seria feliz, e por isso preciso continuar esse processo educacional. No entanto, nem sempre estou por perto para fazer isso manualmente.

É possível automatizar isso? Um microfone é anexado à caixa. Se o nível de volume ultrapassar algum limite, eu quero executar um comando.


1526


origem


Até que eles aprendam a pressionar CTRL + ALT + F7 - Suici Doga


Respostas:


Usar sox a partir de SoX para analisar uma pequena amostra de áudio:

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

Com -t .wav nós especificamos nós processamos o tipo wav, "|arecord -d 2" executa o arecord   programa por dois segundos, -n saídas para o arquivo nulo e com stat nós especificamos que queremos estatísticas.

A saída deste comando, no meu sistema com algum discurso de fundo, é:

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

A amplitude máxima pode então ser extraída via:

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

Nós grep para a linha que queremos, use tr para cortar os caracteres do espaço e depois cut pelo : personagem e pegue a segunda parte que nos dá 0.068383 neste exemplo. Como sugerido pelos comentários, RMS é uma melhor medida de energia do que a amplitude máxima.

Você pode finalmente usar bc no resultado para comparar valores de ponto flutuante da linha de comando:

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

Se você construir um loop (veja Exemplos de bash) que chama dormir por 1 minuto, testa o volume e depois repete, você pode deixá-lo rodando em segundo plano. O último passo é adicioná-lo aos scripts de inicialização ou arquivos de serviço (dependendo do seu OS / distro), de tal forma que você nem precise ativá-lo manualmente.


637



Eu não recomendaria tomar a amplitude máxima. Não é bom para as crianças quando a tela fica em branco só porque alguém bateu palmas ou algo parecido. Média parece mais apropriada. - orlp
Apenas um esclarecimento, por "média" você quer dizer RMS Amplitude certo? A Amplitude Média será próxima de 0 se o ruído for de intensidade consistente ao longo dos 2 segundos (as metades positiva e negativa cancelam-se mutuamente). - Luke
Um simples detector de "energia" para uma série de amostras é apenas adicionar o valor de todos os picos juntos. Você não teria que calcular a média se não quisesse. Um pico é apenas qualquer ponto onde sample[n]>sample[n-1]&&sample[n]>sample[n+1] Eu usei isso como um mecanismo rudimentar para medir a energia de uma música e funciona muito bem. Basta procurar por um número mágico no qual você esteja satisfeito com o nível de volume. - Kaslai
Eu gostaria de ver um exemplo de saída do seu primeiro comando quando realmente chega a uma criança gritando, por referência. - Alvin Wong
Para o uso descrito (iniciar automaticamente + executar a cada poucos minutos), um cron job é a ferramenta certa para usar. Muito mais simples de configurar e mais robusto do que usar o script init + bash loop + sleep. - m000


Veja como isso pode ser feito com Dados puros:

Kid yell prevention using Pure Data

Metro é um metrônomo, e "metro 100" continua batendo a cada 100 ms.

O áudio está vindo de adc ~, o volume é calculado pelo env ~. "pd dsp 0" desliga o DSP quando bateu, "pd dsp 1" o liga. "shell" executa o comando passado em um shell, eu uso o Linux xrandr API para definir o brilho para o X, você precisa adaptar isso para Wayland.

Como você pode ver, o período de tolerância e o bloqueio ocupam muito mais espaço do que o código de áudio.

Fazer uma solução com buffers de anel e / ou médias móveis deve ser muito mais fácil do que fazê-lo com sox. Então eu não acho uma má idéia usar o Pure Data para isso. Mas a tela em si e o bloqueio não se encaixam no paradigma do fluxo de dados.

O arquivo PD está em gist.github.com: ysangkok - kidsyell.pd.


126



muito agradável! Você poderia fazer isso para ser bastante responsivo usando esta técnica: rastreie o nível médio de som por um minuto, então use isso como linha de base, para que quando as crianças ultrapassarem 20 dB acima da linha de base, ele seja desencadeado. Então, ele se ajustará automaticamente ao nível de som ambiente. - Hans-Christoph Steiner
Sim, isso faz sentido @ Hans-ChristophSteiner. Mas de certa forma, o nível de ruído do ambiente não exigiria que as crianças gritassem mais alto, já que elas representariam uma proporção menor do ruído geral? Isso, é claro, só se aplica se o ruído existente for branco ou rosa ou for ignorado. - Janus Troelsen
se fosse mais silencioso que o normal, como uma manhã de fim de semana, então seria mais sensível, já que seria sempre 20 dB acima do nível do ambiente - Hans-Christoph Steiner
Este é o PD estendido? - nullpotent
@ iccthedral: Eu usei o pd-extended para fazer isso, mas não sei se usei construções específicas para o pd. - Janus Troelsen


Verifica "Como detectar a presença de som / áudio" por Thomer M. Gil.

Basicamente grava o som a cada 5 segundos, do que verifica a amplitude do som, usando soxe decide se aciona um script ou não. Eu acho que você pode facilmente adaptar o ruby roteiro para seus filhos! Ou você pode optar por hackar o script Python (usando PyAudio) que ele forneceu também.


100



E aquelas explosões de menos de 5 segundos que evitam a detecção? - RhysW


Você pode obter informações do microfone fazendo algo como:

arecord -d1 /dev/null -vvv

Você pode ter que brincar um pouco com as configurações, como:

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

A partir daí, é uma questão simples de analisar a saída.


52





Esta é uma das perguntas mais divertidas que eu já vi. eu gostaria de agradecer tucuxi  para uma resposta tão boa; que eu defini como um script 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



Se você começar a correr adicionando uma linha ao /etc/rc4.d/S99rc.local e depois mudar o microfone de entrada de não amplificado para 100%, você também pode acabar sendo jogado para o tty3 (você pode voltar antes que o sono seja com Ctrl + Alt + F7), e se o teclado estiver muito alto para abrir um terminal, execute sudo killall too_loud e depois Ctrl + Alt + F1 e faça o login nele. - Alexx Roche


Meus 2 centavos para a solução C ou C ++: talvez não seja a abordagem mais eficaz, mas no Linux, você pode usar o API da ALSA (built-in biblioteca de manipulação de áudio do Linux) e usar alguma técnica numérica (por exemplo, calcular o nível médio de som a cada segundo) para obter o nível de ruído.

Então você pode verificá-lo em um loop infinito, e se for maior do que um treshold pré-definido, você pode usar o Biblioteca X11 para desligar a tela por alguns segundos, ou alternativamente (menos elegante, mas funciona) invocar o chvt comando usando system("chvt 3; sleep 15; chvt 7 ");.


41



Se usando o comando eu consideraria algo diferente, então chvt. ArchWiki tem bons exemplos. - A.D.