Git Product home page Git Product logo

the-bpm-detector-python's People

Contributors

scaperot avatar simplicityguy avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

the-bpm-detector-python's Issues

Not suitable for Python3 (solution)

Hey :) love this program. It didn't work with python3 so I did some fixes if you want:

`
import wave, array, math, time, argparse, sys
import numpy, pywt
from scipy import signal
import pdb
import matplotlib.pyplot as plt

def read_wav(filename):
try:
wf = wave.open(filename,'rb')
except IOError as e:
print(e)
return

nsamps = wf.getnframes();
assert(nsamps > 0);

fs = wf.getframerate()
assert(fs > 0)

samps = list(array.array('i',wf.readframes(nsamps)))

try:
    assert(nsamps == len(samps))
except AssertionError as e:
    print(nsamps, "not equal to", len(samps))

return samps, fs

def no_audio_data():
print("No audio data for sample, skipping...")
return None, None

def peak_detect(data):
max_val = numpy.amax(numpy.abs(data))
peak_ndx = numpy.where(data==max_val)
if len(peak_ndx[0]) == 0:
peak_ndx = numpy.where(data==-max_val)
return peak_ndx

def bpm_detector(data,fs):
cA = []
cD = []
correl = []
cD_sum = []
levels = 4
max_decimation = 2**(levels-1);
min_ndx = int(60./ 220 * (fs/max_decimation))
max_ndx = int(60./ 40 * (fs/max_decimation))

for loop in range(0,levels):
    cD = []
   if loop == 0:
        [cA,cD] = pywt.dwt(data,'db4');
        cD_minlen = int(len(cD)/max_decimation+1);
        cD_sum = numpy.zeros(cD_minlen);
    else:
        [cA,cD] = pywt.dwt(cA,'db4');

    cD = signal.lfilter([0.01],[1 -0.99],cD);

    cD = numpy.abs(cD[::(2**(levels-loop-1))]);
    cD = cD - numpy.mean(cD);

    cD_sum = cD[0:cD_minlen] + cD_sum;

if [b for b in cA if b != 0.0] == []:
    return no_audio_data()

cA = signal.lfilter([0.01],[1 -0.99],cA);
cA = numpy.abs(cA);
cA = cA - numpy.mean(cA);
cD_sum = cA[0:cD_minlen] + cD_sum;


correl = numpy.correlate(cD_sum,cD_sum,'full')

midpoint = int(len(correl) / 2)
correl_midpoint_tmp = correl[midpoint:]
peak_ndx = peak_detect(correl_midpoint_tmp[min_ndx:max_ndx]);
if len(peak_ndx) > 1:
    return no_audio_data()

peak_ndx_adjusted = peak_ndx[0]+min_ndx;
bpm = 60./ peak_ndx_adjusted * (fs/max_decimation)
print(bpm)
return bpm,correl

if name == 'main':
parser = argparse.ArgumentParser(description='Process .wav file to determine the Beats Per Minute.')
parser.add_argument('--filename', required=True,
help='.wav file for processing')
parser.add_argument('--window', type=float, default=3,
help='size of the the window (seconds) that will be scanned to determine the bpm. Typically less than 10 seconds. [3]')

args = parser.parse_args()
samps,fs = read_wav(args.filename)

data = []
correl=[]
bpm = 0
n=0;
nsamps = len(samps)
window_samps = int(args.window*fs)
print("this is window_samps: " +str(window_samps))
samps_ndx = 0;  #first sample in window_ndx
max_window_ndx = int(nsamps / window_samps);
bpms = numpy.zeros(max_window_ndx)


for window_ndx in range(0,max_window_ndx):


    data = samps[samps_ndx:samps_ndx+window_samps]
    if not ((len(data) % window_samps) == 0):
        raise AssertionError( str(len(data) ) )

    bpm, correl_temp = bpm_detector(data,fs)
    if bpm == None:
        continue
    bpms[window_ndx] = bpm
    correl = correl_temp

    samps_ndx = samps_ndx+window_samps;
    n=n+1;

bpm = numpy.median(bpms)
print('Completed.  Estimated Beats Per Minute:', bpm)

n = range(0,len(correl))
plt.plot(n,numpy.abs(correl));
plt.show(False);
time.sleep(10);
plt.close();

`

pywt does not exist?

I'm testing this code and it seems the module pywt does not exist and cannot be downloaded from anywhere?

BPM intervals not equal to total .wav length?

I've analyzed a 15 minute long .wav file and set the window for 060 seconds, and I get only 13 distinct
BPM estimations. Does the script ignore sections of the file that it cannot get a rythym from (ie, in the 15 minute file, only 13 minute's worth were able to be analyzed.) Thanks!

doesn't work(((

this error:
Traceback (most recent call last):
File "C:\Users\user\PycharmProjects\pythonProject22\TuneBot.py", line 111, in
parser.add_argument(x, required=False, help=".wav file for processing")
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\argparse.py", line 1405, in add_argument
kwargs = self._get_positional_kwargs(*args, **kwargs)
File "C:\Users\user\AppData\Local\Programs\Python\Python310\lib\argparse.py", line 1521, in _get_positional_kwargs
raise TypeError(msg)
TypeError: 'required' is an invalid argument for positionals

files with silent parts fail to work

Find a wav file with no audio for a part of the song (longer than the 'window' period) and the script fails to correlate.

Here is a gist of the changes I made (probably not the best solution):

detects 80bpm click track as 160bpm

I have two files, both generated in GarageBand. They were played along with a click track, and quantized to quarter notes, so the timing should be pretty spot on. The 120bpm sample gets detected correctly, but the 80bpm sample gets detected as 160bpm.

clicktrack.zip

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.