Skip to content

Instantly share code, notes, and snippets.

@erm3nda
Last active June 5, 2016 15:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save erm3nda/f6b4a3945e3f2c96f2b5b2faecc989ad to your computer and use it in GitHub Desktop.
Save erm3nda/f6b4a3945e3f2c96f2b5b2faecc989ad to your computer and use it in GitHub Desktop.
Detects applauses and does count them, plus replay them later, looped
#!/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