Skip to content

Instantly share code, notes, and snippets.

@SlimeBOOS
Last active May 15, 2020 15:52
Show Gist options
  • Save SlimeBOOS/0c036d2a667456d413f7c704aa7ed592 to your computer and use it in GitHub Desktop.
Save SlimeBOOS/0c036d2a667456d413f7c704aa7ed592 to your computer and use it in GitHub Desktop.
Clap twice and pewdiepies subreddit will open.
# Things that need to be installed via pip:
# - PyAudio
import pyaudio
import struct
import math
import webbrowser
import asyncio
import time
# If claps are not being detected increase INITIAL_TAP_THRESHOLD
# If claps are being over detected decrease INITIAL_TAP_THRESHOLD
INITIAL_TAP_THRESHOLD = 0.1
INPUT_BLOCK_TIME = 0.05
# if the noise was longer than this many blocks, it's not a 'tap'
MAX_TAP_BLOCKS = 0.15/INPUT_BLOCK_TIME
class ClapDetector(object):
pa = pyaudio.PyAudio()
def __init__(self, tap_threshold=None):
self.tap_threshold = tap_threshold or INITIAL_TAP_THRESHOLD
self.noisycount = MAX_TAP_BLOCKS+1
self.quietcount = 0
self.errorcount = 0
self.stream = None
self.device = None
self.start()
def __del__(self):
if self.stream != None:
self.stop()
@staticmethod
def getInputDevices():
input_devices = []
for i in range(ClapDetector.pa.get_device_count() ):
device_info = ClapDetector.pa.get_device_info_by_index(i)
if device_info["maxInputChannels"] > 0:
input_devices.append(device_info)
return input_devices
@staticmethod
def getRMS(block):
# RMS amplitude is defined as the square root of the
# mean over time of the square of the amplitude.
# so we need to convert this string of bytes into
# a string of 16-bit samples...
# we will get one short out for each
# two chars in the string.
count = len(block)/2
shorts = struct.unpack( "%dh"%(count), block )
# iterate over the block.
sum_squares = 0.0
for sample in shorts:
# sample is a signed short in +/- 32768.
# normalize it to 1.0
sum_squares += (sample / 32768.0)**2
return math.sqrt( sum_squares / count )
def stop(self):
if self.stream != None:
self.stream.close()
return True
else:
print("Tried to close an already closed stream")
return False
def start(self):
if self.device == None:
self.device = ClapDetector.getInputDevices()[0]
if self.device == None:
print("No input devices found")
return False
self.stream = self.pa.open(format = pyaudio.paInt16,
channels = self.device["maxInputChannels"],
rate = int(self.device["defaultSampleRate"]),
input = True,
input_device_index = self.device["index"],
frames_per_buffer = int(self.device["defaultSampleRate"]*INPUT_BLOCK_TIME))
return True
def listen(self):
if self.stream == None:
print("Stream is not opened")
return False
try:
block = self.stream.read(self.stream._frames_per_buffer)
except Exception as e:
# dammit.
self.errorcount += 1
print( "(%d) Error recording: %s"%(self.errorcount,e) )
self.noisycount = 1
return
rms = ClapDetector.getRMS(block)
if rms > self.tap_threshold:
# noisy block
self.quietcount = 0
self.noisycount += 1
else:
# quiet block.
is_clap = (1 <= self.noisycount <= MAX_TAP_BLOCKS)
self.noisycount = 0
self.quietcount += 1
return is_clap
return False
if __name__ == "__main__":
last_clap = 0
clap_detector = ClapDetector()
clap_detector.device = ClapDetector.getInputDevices()[1]
print("Listening on "+clap_detector.device["name"])
while True:
if clap_detector.listen():
current_time = time.time()
print("CLAP:", current_time)
diff = current_time - last_clap
if diff >= 0.2:
if diff <= 1.5:
webbrowser.open("https://www.reddit.com/r/PewdiepieSubmissions/")
last_clap = 0
else:
last_clap = current_time
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment