Last active
June 5, 2016 15:55
-
-
Save erm3nda/f6b4a3945e3f2c96f2b5b2faecc989ad to your computer and use it in GitHub Desktop.
Detects applauses and does count them, plus replay them later, looped
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/python | |
## This is an example of a simple sound capture script that counts Applauses (or other louder sounds). | |
## U can adjust the data value to fit your desired sound by it's amount of data lenght value | |
## The script opens an ALSA pcm for sound capture and several modules. Set | |
## various attributes of the capture, and reads in a loop, | |
## Volume is getting porcentual to medium values of starting noise, not just a fixed value, but not bulletproof | |
## Adjust your volume settings or change the desired value on `sound_raise`. | |
## TODO: Ad proper methods names and values | |
## TODO: Convert to a class | |
## TODO: Test with more sound input values settings | |
import os, sys, time, alsaaudio, time, audioop, platform | |
from subprocess import call | |
# Open the device in nonblocking capture mode. The last argument could | |
# just as well have been zero for blocking mode. Then we could have | |
# left out the sleep call in the bottom of the loop | |
inp = alsaaudio.PCM(alsaaudio.PCM_CAPTURE, alsaaudio.PCM_NONBLOCK) | |
# Set attributes: Mono, 8000 Hz, 16 bit little endian samples | |
inp.setchannels(1) | |
inp.setrate(8000) | |
inp.setformat(alsaaudio.PCM_FORMAT_S16_LE) | |
# Create output to replay sound in live mode | |
out = alsaaudio.PCM() | |
out.setrate(8000) | |
out.setchannels(1) # use only one channel of audio (aka mono) | |
# Mixer volume control | |
# 1 generic examples from docs | |
#~ mic = alsaaudio.Mixer('Mic') | |
#~ mic.setvolume(100) | |
# 2 from alsaaudio.mixers() list(['Master', 'Capture']) | |
#~ mixer = alsaaudio.Mixer('Capture') # output volume | |
#~ mixer.setvolume(100) | |
# 3 fking workaround for Linux, didn't look further for Windows as I don't really need to | |
if platform.system() == "Linux": | |
os.system("amixer set Capture 60%") | |
# The period size controls the internal number of frames per period. | |
# The significance of this parameter is documented in the ALSA api. | |
# For our purposes, it is suficcient to know that reads from the device | |
# will return this many frames. Each frame being 2 bytes long. | |
# This means that the reads below will return either 320 bytes of data | |
# or 0 bytes of data. The latter is possible because we are in nonblocking | |
# mode. | |
inp.setperiodsize(160) | |
# some values | |
timer = 0 | |
slist = [] # frame counting | |
applause = [] # contains frames that belongs to an applause ( avoid sound cut :V ) | |
frames_left = 0 # that would keep more frames when an applause is found ( how long applause recorded samples would be ) | |
counter = 0 # a counter of applause loud samples, 1 per loud detection | |
raise_limit = 30000 | |
try: | |
while True and timer < 2400: # passed time, in miliseconds | |
# Read data from device | |
l,data = inp.read() | |
if l: | |
# Return the maximum of the absolute value of all samples in a fragment. | |
print "sample: ", audioop.max(data, 2) | |
slist.append(audioop.max(data, 2)) | |
print "desired value: ", audioop.avg(data, 2)+raise_limit | |
if frames_left >= 1: | |
print "Saving sound buffer." | |
applause.append(data) | |
frames_left -= 1 | |
elif audioop.max(data, 2) > audioop.avg(data, 2)+raise_limit and frames_left == 0: | |
frames_left += 20 # we add extra frames to our capture to get all the related sound frames to be able to reproduce more than just the frame wich fires the function, based on noise increment percentage comparison | |
print "Detected an applause." | |
applause.append(data) | |
counter += 1 | |
if frames_left > 0: | |
print "frames left: ", frames_left | |
time.sleep(0.01) | |
timer += 10 | |
print "Found " + str(len(slist)) + " sound frames and " + str(counter) + " applauses." | |
if counter > 0: | |
#~ print counter | |
shoutmsg = "He_detectado_" + str(counter) + "_aplausos" | |
try: | |
os.system('espeak -ves ' + shoutmsg) # u need espeak package, not included by default. apt-get install espeak -y | |
except: | |
pass | |
time.sleep(1) | |
for i in applause: | |
out.write(i) | |
del out | |
os.execv(sys.executable, [sys.executable] + sys.argv) | |
else: | |
#~ os.system('espeak -ves "No he detectado sonidos."') | |
os.execv(sys.executable, [sys.executable] + sys.argv) | |
except KeyboardInterrupt: | |
print "Finished" | |
time.sleep(2) | |
sys.exit(0) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment