diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..f1ad435 --- /dev/null +++ b/.gitignore @@ -0,0 +1,16 @@ + +# Data +data/ + +# Virtualenv +# http://iamzed.com/2009/05/07/a-primer-on-virtualenv/ +.Python +[Bb]in +[Ii]nclude +[Ll]ib +[Ll]ib64 +[Ll]ocal +[Ss]cripts +pyvenv.cfg +.venv +pip-selfcheck.json diff --git a/README.md b/README.md index ee438fe..eb7553b 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,36 @@ BPM Detector in Python ======================= + + +## Installation + +### Activate virtual environment +``` bash +source ./bin/activate +``` + +### Dependencies +- numpy +- PyWavelets +- scipy +- matplotlib +``` bash +pip install -r requirements.txt +``` + +## Test +``` bash +python ./bpm_detection/bpm_detection.py --filename ./data/*.wav +``` + +## Help + +### Converting mp3 +``` bash +mpg123 -w [path/to/original.mp3] [./data/wavfile.wav] +``` + +## Original Readme Implementation of a Beats Per Minute (BPM) detection algorithm, as presented in the paper of G. Tzanetakis, G. Essl and P. Cook titled: "Audio Analysis using the Discrete Wavelet Transform". You can find it here: http://citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.63.5712 @@ -9,4 +40,3 @@ Based on the work done in the MATLAB code located at github.com/panagiop/the-BPM Process .wav file to determine the Beats Per Minute. Dependencies: scipy, numpy, pywt, matplotlib - diff --git a/bpm_detection/bpm_detection.py b/bpm_detection/bpm_detection.py index 8419d06..59fc8f2 100644 --- a/bpm_detection/bpm_detection.py +++ b/bpm_detection/bpm_detection.py @@ -12,7 +12,7 @@ def read_wav(filename): except IOError, e: print e return - + # test eddit # typ = choose_type( wf.getsampwidth() ) #TODO: implement choose_type nsamps = wf.getnframes(); assert(nsamps > 0); @@ -50,9 +50,9 @@ def bpm_detector(data,fs): cD_sum = [] levels = 4 max_decimation = 2**(levels-1); - min_ndx = 60./ 220 * (fs/max_decimation) - max_ndx = 60./ 40 * (fs/max_decimation) - + min_ndx = int(60./ 220 * (fs/max_decimation)) + max_ndx = int(60./ 40 * (fs/max_decimation)) + for loop in range(0,levels): cD = [] # 1) DWT @@ -90,14 +90,13 @@ def bpm_detector(data,fs): midpoint = 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 - + return bpm,correl,peak_ndx[0][0] if __name__ == '__main__': parser = argparse.ArgumentParser(description='Process .wav file to determine the Beats Per Minute.') @@ -112,13 +111,14 @@ def bpm_detector(data,fs): data = [] correl=[] bpm = 0 - n=0; + #n=0; nsamps = len(samps) - window_samps = int(args.window*fs) - samps_ndx = 0; #first sample in window_ndx + window_samps = int(args.window*fs) # second * frame/second = frames + samps_ndx = 0; #first sample in window_ndx # frames max_window_ndx = nsamps / window_samps; bpms = numpy.zeros(max_window_ndx) + last_bpm = None #iterate through all windows for window_ndx in xrange(0,max_window_ndx): @@ -128,15 +128,23 @@ def bpm_detector(data,fs): if not ((len(data) % window_samps) == 0): raise AssertionError( str(len(data) ) ) - bpm, correl_temp = bpm_detector(data,fs) + bpm, correl_temp, first_ndx = bpm_detector(data,fs) if bpm == None: continue + + time_value = 1.0*(samps_ndx+first_ndx)/fs #frames / (frame/second) = second + bpm_value = bpm[0] + if last_bpm != bpm_value: + last_bpm = bpm_value + + print "(Time, BPM): %.2f, %.2f"% (time_value, bpm_value) + bpms[window_ndx] = bpm correl = correl_temp #iterate at the end of the loop samps_ndx = samps_ndx+window_samps; - n=n+1; #counter for debug... + #n=n+1; #counter for debug... bpm = numpy.median(bpms) print 'Completed. Estimated Beats Per Minute:', bpm diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..27edeb9 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +numpy +PyWavelets +scipy +matplotlib \ No newline at end of file