From dc23f63b8e2c4e9eb5fbd17659219da90befbbe8 Mon Sep 17 00:00:00 2001 From: Jimmy Date: Sun, 27 Jul 2025 14:16:31 +1200 Subject: [PATCH] Basic beat detection --- main.py | 68 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 68 insertions(+) create mode 100644 main.py diff --git a/main.py b/main.py new file mode 100644 index 0000000..c10cb48 --- /dev/null +++ b/main.py @@ -0,0 +1,68 @@ +#!/usr/bin/python + + +import pyaudio +import aubio +import numpy as np +from time import sleep + + +seconds = 10 # how long this script should run + +bufferSize = 512 +windowSizeMultiple = 2 # or 4 for higher accuracy, but more computational cost + +audioInputDeviceIndex = 7 # use 'arecord -l' to check available audio devices +audioInputChannels = 1 + + +pa = pyaudio.PyAudio() + +info = pa.get_host_api_info_by_index(0) +num_devices = info.get('deviceCount') +for i in range(0, num_devices): + if (pa.get_device_info_by_host_api_device_index(0, i).get('maxInputChannels')) > 0: + print("Input Device id ", i, " - ", pa.get_device_info_by_host_api_device_index(0, i).get('name')) + + +audioInputDevice = pa.get_device_info_by_index(audioInputDeviceIndex) +audioInputSampleRate = int(audioInputDevice['defaultSampleRate']) + +# create the aubio tempo detection: +hopSize = bufferSize +winSize = hopSize * windowSizeMultiple +tempoDetection = aubio.tempo(method='default', buf_size=winSize, hop_size=hopSize, samplerate=audioInputSampleRate) + + +# this function gets called by the input stream, as soon as enough samples are collected from the audio input: +def readAudioFrames(in_data, frame_count, time_info, status): + + signal = np.frombuffer(in_data, dtype=np.float32) + + beat = tempoDetection(signal) + if beat: + bpm = tempoDetection.get_bpm() + print("beat! (running with "+str(bpm)+" bpm)") + + return (in_data, pyaudio.paContinue) + + +# create and start the input stream + +inputStream = pa.open(format=pyaudio.paFloat32, + input=True, + channels=audioInputChannels, + input_device_index=audioInputDeviceIndex, + frames_per_buffer=bufferSize, + rate=audioInputSampleRate, + stream_callback=readAudioFrames) + +while True: + pass + +# because the input stream runs asynchronously, we just wait for a few seconds here before stopping the script: +sleep(seconds) + +inputStream.stop_stream() +inputStream.close() +pa.terminate()