2013-02-01 17:14:09 +0000 2013-02-01 17:14:09 +0000
1554

Hoe maak ik een machine "blanco scherm" voor een bepaalde tijd (als straf) als bepaalde geluidsniveaus worden bereikt?

Mijn kinderen (4 en 5) schreeuwen veel als ze spelletjes spelen op de computer. Ik heb hier een effectieve remedie voor gevonden. Als ik harde geluiden hoor, ssh ik in de spelcomputer en doe:

chvt 3; sleep 15; chvt 7

Dit zet het scherm voor 15 seconden uit op Linux. Ik heb ze verteld dat de computer niet van harde geluiden houdt. Ze geloven dit helemaal en smeken de computer om vergeving. Ze zijn veel stiller geworden, maar niet tot het niveau dat ik gelukkig zou zijn, en dus moet ik dit leerproces voortzetten. Ik ben echter niet altijd in de buurt om dit handmatig te doen.

Is het mogelijk om dit te automatiseren? Er wordt een microfoon aan de box bevestigd. Als het geluidsniveau een bepaalde drempel passeert, wil ik een commando uitvoeren.

Antwoorden [6]

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

Gebruik sox van * SoX ** om een kort geluidsvoorbeeld te analyseren:

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

Met -t .wav geven we aan dat we het wav-type verwerken, "|arecord -d 2" voert het arecord programma gedurende twee seconden uit, -n voert uit naar het null-bestand en met stat geven we aan dat we statistieken willen.

De uitvoer van dit commando, op mijn systeem met wat achtergrondspraak, 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

De maximale amplitude kan dan worden geëxtraheerd via:

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

We grep voor de regel die we willen, gebruiken tr om de spaties weg te knippen en dan cut het door het : teken en nemen het tweede deel wat ons 0.068383 geeft in dit voorbeeld. Zoals commentaar suggereerde, is RMS een betere maatstaf voor energie dan maximale amplitude.

U kunt tenslotte bc op het resultaat gebruiken om floating-point waarden vanaf de command-line te vergelijken:

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

Als u een lus maakt (zie Bash voorbeelden ) die sleep gedurende 1 minuut aanroept, het volume test, en dan herhaalt, kunt u het op de achtergrond laten draaien. De laatste stap is om het toe te voegen aan de init-scripts of service-bestanden (afhankelijk van uw OS / distro), zodat u het niet eens handmatig hoeft te starten.

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

Hier is hoe het gedaan kan worden met Pure Data :

Kid yell prevention using Pure Data Metro is een metronoom, en "metro 100" blijft elke 100 ms bonken.

Het geluid komt van adc~, het volume wordt berekend door env~. "pd dsp 0" zet de DSP uit als er gebonkt wordt, "pd dsp 1" zet hem aan. "shell" voert het doorgegeven commando uit in een shell, ik gebruik de Linux xrandr API om de helderheid op X in te stellen, je moet dit aanpassen voor Wayland.

Zoals je kunt zien, nemen respijtperiode en vergrendeling veel meer ruimte in beslag dan de audio code.

Een oplossing maken met ring buffers en/of bewegende gemiddelden zou veel makkelijker moeten zijn dan het te doen met sox. Dus ik denk niet dat het een slecht idee is om Pure Data hiervoor te gebruiken. Maar het blanco maken van het scherm zelf en het vergrendelen past niet in het dataflow paradigma.

Het PD bestand is op gist.github.com: ysangkok - kidsyell.pd .

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

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

In principe neemt het elke 5 seconden het geluid op, controleert dan de geluidsamplitude, met behulp van sox, en beslist of er een script wordt gestart of niet. Ik denk dat je het ruby script gemakkelijk kunt aanpassen voor je kinderen! Of je kunt ervoor kiezen om het Python script (met PyAudio), dat hij ook heeft geleverd, te hacken.

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

U kunt informatie uit de microfoon krijgen door iets te doen als:

arecord -d1 /dev/null -vvv

Misschien moet je een beetje spelen met de instellingen, zoals:

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

Vanaf daar is het een eenvoudige kwestie van de output te ontleden.

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

Dit is een van de leukere vragen die ik heb gezien. Ik wil tucuxi bedanken voor zo'n fijn antwoord; dat ik als een bash-script heb ingesteld

#!/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

Mijn 2 cent voor de C of C++ oplossing: misschien niet de meest effectieve aanpak, maar op Linux, kun je de ALSA API (ingebouwde audio afhandelingsbibliotheek van Linux) gebruiken en een of andere numerieke techniek gebruiken (bijvoorbeeld het gemiddelde geluidsniveau elke seconde berekenen) om het niveau van het geluid te verkrijgen.

Dan kun je het in een oneindige lus controleren, en als het hoger is dan een vooraf ingestelde treshold, kun je de X11 bibliotheek gebruiken om het scherm een paar seconden uit te zetten, of als alternatief (minder elegant, maar het werkt) het commando chvt aanroepen met behulp van system("chvt 3; sleep 15; chvt 7 ");.

42