From 7abdcca2d7b82c8ad20ee45ada08e31db7c71e82 Mon Sep 17 00:00:00 2001 From: Mohit Nalavadi Date: Tue, 8 Sep 2020 15:58:23 +0200 Subject: [PATCH] update python binding to support python3 ignore compiled python files ignore compiled python files ignore compiled python files --- .gitignore | 6 ++- README.md | 5 ++- modules-and-plug-ins/python-module/INSTALL.md | 9 ++++- .../python-module/btrack_python_module.cpp | 22 ++++++++--- modules-and-plug-ins/python-module/example.py | 35 +++++++++-------- .../python-module/requirements.txt | 2 + modules-and-plug-ins/python-module/setup.py | 39 +++++++++++-------- 7 files changed, 73 insertions(+), 45 deletions(-) create mode 100644 modules-and-plug-ins/python-module/requirements.txt diff --git a/.gitignore b/.gitignore index 8659e4a..0f5dbab 100644 --- a/.gitignore +++ b/.gitignore @@ -1,12 +1,14 @@ -python-module/build unit-tests/Build xcuserdata .DS_Store *.o *.dylib +*.so +*.pyc +*.c *.xcworkspace modules-and-plug-ins/max-external/build -modules-and-plug-ins/python-module/build \ No newline at end of file +modules-and-plug-ins/python-module/build diff --git a/README.md b/README.md index 4daaf9b..b7f5773 100644 --- a/README.md +++ b/README.md @@ -9,7 +9,7 @@ BTrack - A Real-Time Beat Tracker About BTrack ------------ -BTrack is a causal beat tracking algorithm intended for real-time use. It is implemented in C++ with wrappers for Python and the Vamp plug-in framework. +BTrack is a causal beat tracking algorithm intended for real-time use. It is implemented in C++ with wrappers for Python3 and the Vamp plug-in framework. Full details of the working of the algorithm can be found in: @@ -21,6 +21,9 @@ BTrack is made available under the GNU General Public License, version 3. Please Versions -------- +==== 1.0.5 ==== (8th September 2020) + +* Update Python binding to support Python 3. ==== 1.0.4 ==== (18th June 2016) diff --git a/modules-and-plug-ins/python-module/INSTALL.md b/modules-and-plug-ins/python-module/INSTALL.md index 2f38fdb..e60013f 100644 --- a/modules-and-plug-ins/python-module/INSTALL.md +++ b/modules-and-plug-ins/python-module/INSTALL.md @@ -5,14 +5,19 @@ See the main README for other information including usage and license informatio Installation ------------ +Ensure [FFTW is installed](http://fftw.org/download.html). + +Install python requirements (numpy necessary, scipy for reading `.wav` files.) + + pip install -r requirements.txt On the command line, type: - python setup.py build + python setup.py build build_ext --inplace and then: - python setup.py install + python setup.py install You may need to prefix the second command with 'sudo', depending upon your system configuration. diff --git a/modules-and-plug-ins/python-module/btrack_python_module.cpp b/modules-and-plug-ins/python-module/btrack_python_module.cpp index 1c45bb0..c2dde1b 100644 --- a/modules-and-plug-ins/python-module/btrack_python_module.cpp +++ b/modules-and-plug-ins/python-module/btrack_python_module.cpp @@ -292,21 +292,31 @@ static PyMethodDef btrack_methods[] = { }; //======================================================================= -PyMODINIT_FUNC initbtrack(void) +static struct PyModuleDef btrack = +{ + PyModuleDef_HEAD_INIT, + "btrack", /* name of module */ + "", /* module documentation, may be NULL */ + -1, /* size of per-interpreter state of the module, or -1 if the module keeps state in global variables. */ + btrack_methods +}; + +PyMODINIT_FUNC PyInit_btrack(void) { - (void)Py_InitModule("btrack", btrack_methods); import_array(); + return PyModule_Create(&btrack); } //======================================================================= int main(int argc, char *argv[]) { - /* Pass argv[0] to the Python interpreter */ - Py_SetProgramName(argv[0]); - + /* Convert argv[0] from char to wchar_t and pass to the Python interpreter */ + wchar_t *program = Py_DecodeLocale(argv[0], NULL); + Py_SetProgramName(program); + /* Initialize the Python interpreter. Required. */ Py_Initialize(); /* Add a static module */ - initbtrack(); + PyInit_btrack(); } \ No newline at end of file diff --git a/modules-and-plug-ins/python-module/example.py b/modules-and-plug-ins/python-module/example.py index 58375a1..09f2c44 100644 --- a/modules-and-plug-ins/python-module/example.py +++ b/modules-and-plug-ins/python-module/example.py @@ -1,28 +1,29 @@ -# need scikits audiolab for reading audio files -from scikits.audiolab import wavread +import time -# need to import btrack, our beat tracker import btrack +import numpy as np +from scipy.io import wavfile # set the path to an audio file on your machine -audioFilePath = "/path/to/your/audioFile.wav" - -# read the audio file -audioData, fs, enc = wavread(audioFilePath) # extract audio from file +audio_file_path = "/path/to/your/audioFile.wav" +_, audio_data = wavfile.read(audio_file_path) # convert to mono if need be -if (audioData[0].size == 2): - print "converting to mono" - data = np.average(data,axis=1) - -# ========================================== -# Usage A: track beats from audio -beats = btrack.trackBeats(audioData) +if audio_data.shape[1] == 2: + print("converting to mono") + audio_data = np.average(audio_data, axis=1) # ========================================== -# Usage B: extract the onset detection function -onsetDF = btrack.calculateOnsetDF(audioData) +# Usage A: track beats from audio +t0 = time.time() +beats = btrack.trackBeats(audio_data) +print(f"Calculated beats using btrack.trackBeats function in {round(time.time() - t0, 2)}s") +print(beats) # ========================================== -# Usage C: track beats from the onset detection function (calculated in Usage B) +# Usage B: extract the onset detection function +t0 = time.time() +onsetDF = btrack.calculateOnsetDF(audio_data) ODFbeats = btrack.trackBeatsFromOnsetDF(onsetDF) +print(f"Calculated beats using onset detection function in {round(time.time() - t0, 2)}s") +print(ODFbeats) diff --git a/modules-and-plug-ins/python-module/requirements.txt b/modules-and-plug-ins/python-module/requirements.txt new file mode 100644 index 0000000..33b7f09 --- /dev/null +++ b/modules-and-plug-ins/python-module/requirements.txt @@ -0,0 +1,2 @@ +numpy==1.19.1 +scipy==1.5.2 diff --git a/modules-and-plug-ins/python-module/setup.py b/modules-and-plug-ins/python-module/setup.py index 80ed488..18d0711 100644 --- a/modules-and-plug-ins/python-module/setup.py +++ b/modules-and-plug-ins/python-module/setup.py @@ -1,21 +1,26 @@ -# setup.py -# build command : python setup.py build build_ext --inplace from numpy.distutils.core import setup, Extension -import os, numpy +import numpy -name = 'btrack' -sources = ['btrack_python_module.cpp','../../src/OnsetDetectionFunction.cpp','../../src/BTrack.cpp'] +name = "btrack" +sources = [ + "btrack_python_module.cpp", + "../../src/OnsetDetectionFunction.cpp", + "../../src/BTrack.cpp", + "../../libs/kiss_fft130/kiss_fft.c", +] -sources.append ('../../libs/kiss_fft130/kiss_fft.c') +include_dirs = [numpy.get_include(), "/usr/local/include", "../../libs/kiss_fft130"] -include_dirs = [ - numpy.get_include(),'/usr/local/include' - ] - -include_dirs.append ('../../libs/kiss_fft130') - -setup( name = 'BTrack', - include_dirs = include_dirs, - ext_modules = [Extension(name, sources,libraries = ['fftw3','samplerate'],library_dirs = ['/usr/local/lib'],define_macros=[ - ('USE_FFTW', None)])] - ) \ No newline at end of file +setup( + name="BTrack", + include_dirs=include_dirs, + ext_modules=[ + Extension( + name, + sources, + libraries=["fftw3", "samplerate"], + library_dirs=["/usr/local/lib"], + define_macros=[("USE_FFTW", None)], + ) + ], +)