Spaces:
Running
Running
| """ | |
| modules/clap.py — clap / loud-sound trigger detector | |
| Listens for a double-clap pattern to toggle FRIDAY on/off. | |
| """ | |
| import threading | |
| import time | |
| try: | |
| import numpy as np | |
| import sounddevice as sd | |
| AUDIO_OK = True | |
| except ImportError: | |
| AUDIO_OK = False | |
| CLAP_THRESHOLD = 0.55 # RMS amplitude level | |
| CLAP_WINDOW = 0.8 # seconds between two claps to count as double-clap | |
| COOLDOWN = 2.0 # seconds to ignore after trigger | |
| def watch_clap(callback, running_flag: list): | |
| """ | |
| Run in a daemon thread. Calls callback() on double-clap detection. | |
| running_flag is a mutable [True] list; set [False] to stop. | |
| """ | |
| if not AUDIO_OK: | |
| return | |
| last_clap = 0.0 | |
| last_trigger = 0.0 | |
| def _audio_cb(indata, frames, time_info, status): | |
| nonlocal last_clap, last_trigger | |
| now = time.time() | |
| # cooldown guard | |
| if now - last_trigger < COOLDOWN: | |
| return | |
| rms = float(np.sqrt(np.mean(indata ** 2))) | |
| if rms > CLAP_THRESHOLD: | |
| if now - last_clap < CLAP_WINDOW: | |
| # double clap! | |
| last_trigger = now | |
| threading.Thread(target=callback, daemon=True).start() | |
| last_clap = 0.0 # reset | |
| else: | |
| last_clap = now | |
| try: | |
| with sd.InputStream(channels=1, samplerate=22050, | |
| blocksize=1024, callback=_audio_cb): | |
| while running_flag[0]: | |
| time.sleep(0.1) | |
| except Exception: | |
| pass |