Mercurial > hg > btrack
changeset 14:18fc3c248436 develop
Added a unit testing project, and did some commenting. Also moved python-module into a modules-and-plug-ins folder
author | Adam <adamstark.uk@gmail.com> |
---|---|
date | Tue, 21 Jan 2014 10:24:33 +0000 |
parents | 7ce3f8718da1 |
children | 2b94d3d2fb9d |
files | .hgignore modules-and-plug-ins/python-module/btrack_python_module.cpp modules-and-plug-ins/python-module/setup.py python-module/btrack_python_module.cpp python-module/setup.py src/BTrack.cpp src/BTrack.h unit-tests/BTrack Tests.xcodeproj/project.pbxproj unit-tests/BTrack Tests/BTrack_Tests.1 unit-tests/BTrack Tests/main.cpp |
diffstat | 10 files changed, 811 insertions(+), 451 deletions(-) [+] |
line wrap: on
line diff
--- a/.hgignore Tue Jan 21 01:45:36 2014 +0000 +++ b/.hgignore Tue Jan 21 10:24:33 2014 +0000 @@ -1,1 +1,8 @@ -python-module/build \ No newline at end of file +syntax: glob + +python-module/build +unit-tests/Build +xcuserdata +.DS_Store + +*.xcworkspace \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules-and-plug-ins/python-module/btrack_python_module.cpp Tue Jan 21 10:24:33 2014 +0000 @@ -0,0 +1,362 @@ +#include <iostream> +#include <Python.h> +#include "../../src/OnsetDetectionFunction.h" +#include "../../src/BTrack.h" +#include <numpy/arrayobject.h> + +static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args) +{ + PyObject *arg1=NULL; + PyObject *arr1=NULL; + + if (!PyArg_ParseTuple(args, "O", &arg1)) + { + return NULL; + } + + arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); + if (arr1 == NULL) + { + return NULL; + } + + + + ////////// GET INPUT DATA /////////////////// + + // get data as array + double* data = (double*) PyArray_DATA(arr1); + + // get array size + int signal_length = PyArray_Size((PyObject*)arr1); + //int k = (int) theSize; + + // get data type + char type = PyArray_DESCR(arr1)->type; + + ////////// BEGIN PROCESS /////////////////// + int hsize = 512; + int fsize = 1024; + int df_type = 6; + int numframes; + double buffer[hsize]; // buffer to hold one hopsize worth of audio samples + + + // get number of audio frames, given the hop size and signal length + numframes = (int) floor(((double) signal_length) / ((double) hsize)); + + OnsetDetectionFunction onset(hsize,fsize,df_type,1); + + double df[numframes]; + + + + /////////////////////////////////////////// + //////// Begin Processing Loop //////////// + + for (int i=0;i < numframes;i++) + { + // add new samples to frame + for (int n = 0;n < hsize;n++) + { + buffer[n] = data[(i*hsize)+n]; + } + + df[i] = onset.getDFsample(buffer); + + } + + ///////// End Processing Loop ///////////// + /////////////////////////////////////////// + + + ////////// END PROCESS /////////////////// + + + + ////////// CREATE ARRAY AND RETURN IT /////////////////// + int nd=1; + npy_intp m= numframes; + //double fArray[5] = {0,1,2,3,4}; + + PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE); + + void *arr_data = PyArray_DATA((PyArrayObject*)c); + + memcpy(arr_data, df, PyArray_ITEMSIZE((PyArrayObject*) c) * m); + + + Py_DECREF(arr1); + Py_INCREF(Py_None); + //return Py_None; + + return (PyObject *)c; + + //return Py_BuildValue("c", type); + //return Py_BuildValue("d", sum); + //return Py_BuildValue("i", k); +/* +fail: + Py_XDECREF(arr1); + Py_XDECREF(arr2); + PyArray_XDECREF_ERR(oarr); + return NULL;*/ +} + + +static PyObject * btrack_btrack(PyObject *dummy, PyObject *args) +{ + PyObject *arg1=NULL; + PyObject *arr1=NULL; + + if (!PyArg_ParseTuple(args, "O", &arg1)) + { + return NULL; + } + + arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); + if (arr1 == NULL) + { + return NULL; + } + + + + ////////// GET INPUT DATA /////////////////// + + // get data as array + double* data = (double*) PyArray_DATA(arr1); + + // get array size + int signal_length = PyArray_Size((PyObject*)arr1); + //int k = (int) theSize; + + // get data type + char type = PyArray_DESCR(arr1)->type; + + ////////// BEGIN PROCESS /////////////////// + int hsize = 512; + int fsize = 1024; + int df_type = 6; + int numframes; + double buffer[hsize]; // buffer to hold one hopsize worth of audio samples + + + // get number of audio frames, given the hop size and signal length + numframes = (int) floor(((double) signal_length) / ((double) hsize)); + + OnsetDetectionFunction onset(hsize,fsize,df_type,1); + BTrack b; + + b.initialise((int) hsize); // initialise beat tracker + + // set parameters + //b.setparams(0.9,5); + + double df[numframes]; + double beats[5000]; + int beatnum = 0; + float df_val; + + /////////////////////////////////////////// + //////// Begin Processing Loop //////////// + + for (int i=0;i < numframes;i++) + { + // add new samples to frame + for (int n = 0;n < hsize;n++) + { + buffer[n] = data[(i*hsize)+n]; + } + + df[i] = onset.getDFsample(buffer); + + df_val = (float) (df[i] + 0.0001); + + b.process(df_val); // process df sample in beat tracker + + if (b.playbeat == 1) + { + beats[beatnum] = (((double) hsize) / 44100) * ((double) i); + beatnum = beatnum + 1; + } + + } + + ///////// End Processing Loop ///////////// + /////////////////////////////////////////// + + + ////////// END PROCESS /////////////////// + + double beats_out[beatnum]; // create output array + + // copy beats into output array + for (int i = 0;i < beatnum;i++) + { + beats_out[i] = beats[i]; + } + + + + ////////// CREATE ARRAY AND RETURN IT /////////////////// + int nd=1; + npy_intp m= beatnum; + //double fArray[5] = {0,1,2,3,4}; + + PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE); + + void *arr_data = PyArray_DATA((PyArrayObject*)c); + + memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m); + + + Py_DECREF(arr1); + Py_INCREF(Py_None); + //return Py_None; + + return (PyObject *)c; + + //return Py_BuildValue("c", type); + //return Py_BuildValue("d", sum); + //return Py_BuildValue("i", k); + /* + fail: + Py_XDECREF(arr1); + Py_XDECREF(arr2); + PyArray_XDECREF_ERR(oarr); + return NULL;*/ +} + +static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args) +{ + PyObject *arg1=NULL; + PyObject *arr1=NULL; + + if (!PyArg_ParseTuple(args, "O", &arg1)) + { + return NULL; + } + + arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); + if (arr1 == NULL) + { + return NULL; + } + + + + ////////// GET INPUT DATA /////////////////// + + // get data as array + double* data = (double*) PyArray_DATA(arr1); + + // get array size + int numframes = PyArray_Size((PyObject*)arr1); + //int k = (int) theSize; + + // get data type + char type = PyArray_DESCR(arr1)->type; + + ////////// BEGIN PROCESS /////////////////// + int hsize = 512; + + BTrack b; + + b.initialise((int) hsize); // initialise beat tracker + + // set parameters + //b.setparams(0.9,5); + + double beats[5000]; + int beatnum = 0; + float df_val; + + /////////////////////////////////////////// + //////// Begin Processing Loop //////////// + + for (int i=0;i < numframes;i++) + { + df_val = (float) (data[i] + 0.0001); + + b.process(df_val); // process df sample in beat tracker + + if (b.playbeat == 1) + { + beats[beatnum] = (((double) hsize) / 44100) * ((double) i); + beatnum = beatnum + 1; + } + + } + + ///////// End Processing Loop ///////////// + /////////////////////////////////////////// + + + ////////// END PROCESS /////////////////// + + double beats_out[beatnum]; // create output array + + + // copy beats into output array + for (int i = 0;i < beatnum;i++) + { + beats_out[i] = beats[i]; + } + + + ////////// CREATE ARRAY AND RETURN IT /////////////////// + int nd=1; + npy_intp m= beatnum; + //double fArray[5] = {0,1,2,3,4}; + + PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE); + + void *arr_data = PyArray_DATA((PyArrayObject*)c); + + memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m); + + + Py_DECREF(arr1); + Py_INCREF(Py_None); + //return Py_None; + + return (PyObject *)c; + + //return Py_BuildValue("c", type); + //return Py_BuildValue("d", sum); + //return Py_BuildValue("i", k); + /* + fail: + Py_XDECREF(arr1); + Py_XDECREF(arr2); + PyArray_XDECREF_ERR(oarr); + return NULL;*/ +} + + + +static PyMethodDef btrack_methods[] = { + { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"}, + { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"}, + { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"}, + {NULL, NULL, 0, NULL} /* Sentinel */ +}; + +PyMODINIT_FUNC initbtrack(void) +{ + (void)Py_InitModule("btrack", btrack_methods); + import_array(); +} + +int main(int argc, char *argv[]) +{ + /* Pass argv[0] to the Python interpreter */ + Py_SetProgramName(argv[0]); + + /* Initialize the Python interpreter. Required. */ + Py_Initialize(); + + /* Add a static module */ + initbtrack(); +} \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/modules-and-plug-ins/python-module/setup.py Tue Jan 21 10:24:33 2014 +0000 @@ -0,0 +1,16 @@ +# setup.py +# build command : python setup.py build build_ext --inplace +from numpy.distutils.core import setup, Extension +import os, numpy + +name = 'btrack' +sources = ['btrack_python_module.cpp','../../src/OnsetDetectionFunction.cpp','../../src/BTrack.cpp'] + +include_dirs = [ + numpy.get_include(),'/usr/local/include' + ] + +setup( name = 'BTrack', + include_dirs = include_dirs, + ext_modules = [Extension(name, sources,libraries = ['fftw3','samplerate'])] + ) \ No newline at end of file
--- a/python-module/btrack_python_module.cpp Tue Jan 21 01:45:36 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,362 +0,0 @@ -#include <iostream> -#include <Python.h> -#include "../src/OnsetDetectionFunction.h" -#include "../src/BTrack.h" -#include <numpy/arrayobject.h> - -static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args) -{ - PyObject *arg1=NULL; - PyObject *arr1=NULL; - - if (!PyArg_ParseTuple(args, "O", &arg1)) - { - return NULL; - } - - arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); - if (arr1 == NULL) - { - return NULL; - } - - - - ////////// GET INPUT DATA /////////////////// - - // get data as array - double* data = (double*) PyArray_DATA(arr1); - - // get array size - int signal_length = PyArray_Size((PyObject*)arr1); - //int k = (int) theSize; - - // get data type - char type = PyArray_DESCR(arr1)->type; - - ////////// BEGIN PROCESS /////////////////// - int hsize = 512; - int fsize = 1024; - int df_type = 6; - int numframes; - double buffer[hsize]; // buffer to hold one hopsize worth of audio samples - - - // get number of audio frames, given the hop size and signal length - numframes = (int) floor(((double) signal_length) / ((double) hsize)); - - OnsetDetectionFunction onset(hsize,fsize,df_type,1); - - double df[numframes]; - - - - /////////////////////////////////////////// - //////// Begin Processing Loop //////////// - - for (int i=0;i < numframes;i++) - { - // add new samples to frame - for (int n = 0;n < hsize;n++) - { - buffer[n] = data[(i*hsize)+n]; - } - - df[i] = onset.getDFsample(buffer); - - } - - ///////// End Processing Loop ///////////// - /////////////////////////////////////////// - - - ////////// END PROCESS /////////////////// - - - - ////////// CREATE ARRAY AND RETURN IT /////////////////// - int nd=1; - npy_intp m= numframes; - //double fArray[5] = {0,1,2,3,4}; - - PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE); - - void *arr_data = PyArray_DATA((PyArrayObject*)c); - - memcpy(arr_data, df, PyArray_ITEMSIZE((PyArrayObject*) c) * m); - - - Py_DECREF(arr1); - Py_INCREF(Py_None); - //return Py_None; - - return (PyObject *)c; - - //return Py_BuildValue("c", type); - //return Py_BuildValue("d", sum); - //return Py_BuildValue("i", k); -/* -fail: - Py_XDECREF(arr1); - Py_XDECREF(arr2); - PyArray_XDECREF_ERR(oarr); - return NULL;*/ -} - - -static PyObject * btrack_btrack(PyObject *dummy, PyObject *args) -{ - PyObject *arg1=NULL; - PyObject *arr1=NULL; - - if (!PyArg_ParseTuple(args, "O", &arg1)) - { - return NULL; - } - - arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); - if (arr1 == NULL) - { - return NULL; - } - - - - ////////// GET INPUT DATA /////////////////// - - // get data as array - double* data = (double*) PyArray_DATA(arr1); - - // get array size - int signal_length = PyArray_Size((PyObject*)arr1); - //int k = (int) theSize; - - // get data type - char type = PyArray_DESCR(arr1)->type; - - ////////// BEGIN PROCESS /////////////////// - int hsize = 512; - int fsize = 1024; - int df_type = 6; - int numframes; - double buffer[hsize]; // buffer to hold one hopsize worth of audio samples - - - // get number of audio frames, given the hop size and signal length - numframes = (int) floor(((double) signal_length) / ((double) hsize)); - - OnsetDetectionFunction onset(hsize,fsize,df_type,1); - BTrack b; - - b.initialise((int) hsize); // initialise beat tracker - - // set parameters - //b.setparams(0.9,5); - - double df[numframes]; - double beats[5000]; - int beatnum = 0; - float df_val; - - /////////////////////////////////////////// - //////// Begin Processing Loop //////////// - - for (int i=0;i < numframes;i++) - { - // add new samples to frame - for (int n = 0;n < hsize;n++) - { - buffer[n] = data[(i*hsize)+n]; - } - - df[i] = onset.getDFsample(buffer); - - df_val = (float) (df[i] + 0.0001); - - b.process(df_val); // process df sample in beat tracker - - if (b.playbeat == 1) - { - beats[beatnum] = (((double) hsize) / 44100) * ((double) i); - beatnum = beatnum + 1; - } - - } - - ///////// End Processing Loop ///////////// - /////////////////////////////////////////// - - - ////////// END PROCESS /////////////////// - - double beats_out[beatnum]; // create output array - - // copy beats into output array - for (int i = 0;i < beatnum;i++) - { - beats_out[i] = beats[i]; - } - - - - ////////// CREATE ARRAY AND RETURN IT /////////////////// - int nd=1; - npy_intp m= beatnum; - //double fArray[5] = {0,1,2,3,4}; - - PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE); - - void *arr_data = PyArray_DATA((PyArrayObject*)c); - - memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m); - - - Py_DECREF(arr1); - Py_INCREF(Py_None); - //return Py_None; - - return (PyObject *)c; - - //return Py_BuildValue("c", type); - //return Py_BuildValue("d", sum); - //return Py_BuildValue("i", k); - /* - fail: - Py_XDECREF(arr1); - Py_XDECREF(arr2); - PyArray_XDECREF_ERR(oarr); - return NULL;*/ -} - -static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args) -{ - PyObject *arg1=NULL; - PyObject *arr1=NULL; - - if (!PyArg_ParseTuple(args, "O", &arg1)) - { - return NULL; - } - - arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY); - if (arr1 == NULL) - { - return NULL; - } - - - - ////////// GET INPUT DATA /////////////////// - - // get data as array - double* data = (double*) PyArray_DATA(arr1); - - // get array size - int numframes = PyArray_Size((PyObject*)arr1); - //int k = (int) theSize; - - // get data type - char type = PyArray_DESCR(arr1)->type; - - ////////// BEGIN PROCESS /////////////////// - int hsize = 512; - - BTrack b; - - b.initialise((int) hsize); // initialise beat tracker - - // set parameters - //b.setparams(0.9,5); - - double beats[5000]; - int beatnum = 0; - float df_val; - - /////////////////////////////////////////// - //////// Begin Processing Loop //////////// - - for (int i=0;i < numframes;i++) - { - df_val = (float) (data[i] + 0.0001); - - b.process(df_val); // process df sample in beat tracker - - if (b.playbeat == 1) - { - beats[beatnum] = (((double) hsize) / 44100) * ((double) i); - beatnum = beatnum + 1; - } - - } - - ///////// End Processing Loop ///////////// - /////////////////////////////////////////// - - - ////////// END PROCESS /////////////////// - - double beats_out[beatnum]; // create output array - - - // copy beats into output array - for (int i = 0;i < beatnum;i++) - { - beats_out[i] = beats[i]; - } - - - ////////// CREATE ARRAY AND RETURN IT /////////////////// - int nd=1; - npy_intp m= beatnum; - //double fArray[5] = {0,1,2,3,4}; - - PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE); - - void *arr_data = PyArray_DATA((PyArrayObject*)c); - - memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m); - - - Py_DECREF(arr1); - Py_INCREF(Py_None); - //return Py_None; - - return (PyObject *)c; - - //return Py_BuildValue("c", type); - //return Py_BuildValue("d", sum); - //return Py_BuildValue("i", k); - /* - fail: - Py_XDECREF(arr1); - Py_XDECREF(arr2); - PyArray_XDECREF_ERR(oarr); - return NULL;*/ -} - - - -static PyMethodDef btrack_methods[] = { - { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"}, - { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"}, - { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"}, - {NULL, NULL, 0, NULL} /* Sentinel */ -}; - -PyMODINIT_FUNC initbtrack(void) -{ - (void)Py_InitModule("btrack", btrack_methods); - import_array(); -} - -int main(int argc, char *argv[]) -{ - /* Pass argv[0] to the Python interpreter */ - Py_SetProgramName(argv[0]); - - /* Initialize the Python interpreter. Required. */ - Py_Initialize(); - - /* Add a static module */ - initbtrack(); -} \ No newline at end of file
--- a/python-module/setup.py Tue Jan 21 01:45:36 2014 +0000 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -# setup.py -# build command : python setup.py build build_ext --inplace -from numpy.distutils.core import setup, Extension -import os, numpy - -name = 'btrack' -sources = ['btrack_python_module.cpp','../src/OnsetDetectionFunction.cpp','../src/BTrack.cpp'] - -include_dirs = [ - numpy.get_include(),'/usr/local/include' - ] - -setup( name = 'BTrack', - include_dirs = include_dirs, - ext_modules = [Extension(name, sources,libraries = ['fftw3','samplerate'])] - ) \ No newline at end of file
--- a/src/BTrack.cpp Tue Jan 21 01:45:36 2014 +0000 +++ b/src/BTrack.cpp Tue Jan 21 10:24:33 2014 +0000 @@ -28,8 +28,7 @@ -//------------------------------------------------------------------------------- -// Constructor +//======================================================================= BTrack :: BTrack() { float rayparam = 43; @@ -82,15 +81,15 @@ tempofix = 0; } -//------------------------------------------------------------------------------- -// Destructor +//======================================================================= BTrack :: ~BTrack() { } -//------------------------------------------------------------------------------- -// Initialise with frame size and set all frame sizes accordingly + + +//======================================================================= void BTrack :: initialise(int fsize) { framesize = fsize; @@ -116,8 +115,7 @@ } } -//------------------------------------------------------------------------------- -// Add new sample to buffer and apply beat tracking +//======================================================================= void BTrack :: process(float df_sample) { m0--; @@ -153,8 +151,7 @@ } } -//------------------------------------------------------------------------------- -// Set the tempo of the beat tracker +//======================================================================= void BTrack :: settempo(float tempo) { @@ -221,9 +218,7 @@ m0 = (int) round(((float) new_bperiod)/2); } - -//------------------------------------------------------------------------------- -// fix tempo to roughly around some value +//======================================================================= void BTrack :: fixtempo(float tempo) { // firstly make sure tempo is between 80 and 160 bpm.. @@ -253,16 +248,14 @@ tempofix = 1; } -//------------------------------------------------------------------------------- -// do not fix the tempo anymore +//======================================================================= void BTrack :: unfixtempo() { // set the tempo fix flag tempofix = 0; } -//------------------------------------------------------------------------------- -// Convert detection function from N samples to 512 +//======================================================================= void BTrack :: dfconvert() { float output[512]; @@ -291,8 +284,7 @@ } } -//------------------------------------------------------------------------------- -// To calculate the current tempo expressed as the beat period in detection function samples +//======================================================================= void BTrack :: calcTempo() { // adaptive threshold on input @@ -378,8 +370,7 @@ //cout << bperiod << endl; } -//------------------------------------------------------------------------------- -// calculates an adaptive threshold which is used to remove low level energy from detection function and emphasise peaks +//======================================================================= void BTrack :: adapt_thresh(float x[],int N) { //int N = 512; // length of df @@ -421,8 +412,7 @@ } } -//------------------------------------------------------------------------------- -// returns the output of the comb filter +//======================================================================= void BTrack :: getrcfoutput() { int numelem; @@ -446,8 +436,7 @@ } } -//------------------------------------------------------------------------------- -// calculates the balanced autocorrelation of the smoothed detection function +//======================================================================= void BTrack :: acf_bal(float df_thresh[]) { int l, n = 0; @@ -469,9 +458,7 @@ } } - -//------------------------------------------------------------------------------- -// calculates the mean of values in an array from index locations [start,end] +//======================================================================= float BTrack :: mean_array(float array[],int start,int end) { int i; @@ -495,8 +482,7 @@ } } -//------------------------------------------------------------------------------- -// normalise the array +//======================================================================= void BTrack :: normalise(float array[],int N) { double sum = 0; @@ -518,20 +504,7 @@ } } -//------------------------------------------------------------------------------- -// plot contents of detection function buffer -void BTrack :: plotdfbuffer() -{ - for (int i=0;i < dfbuffer_size;i++) - { - cout << dfbuffer[i] << endl; - } - - cout << "--------------------------------" << endl; -} - -//------------------------------------------------------------------------------- -// update the cumulative score +//======================================================================= void BTrack :: updatecumscore(float df_sample) { int start, end, winsize; @@ -583,8 +556,7 @@ } -//------------------------------------------------------------------------------- -// plot contents of detection function buffer +//======================================================================= void BTrack :: predictbeat() { int winsize = (int) bperiod; @@ -664,7 +636,7 @@ // set beat - beat = beat; + //beat = beat; // set next prediction time m0 = beat+round(bperiod/2);
--- a/src/BTrack.h Tue Jan 21 01:45:36 2014 +0000 +++ b/src/BTrack.h Tue Jan 21 10:24:33 2014 +0000 @@ -22,28 +22,29 @@ #ifndef __BTRACK_H #define __BTRACK_H -//#include "fftw3.h" - class BTrack { public: - BTrack(); // constructor - ~BTrack(); // destructor + + /** constructor */ + BTrack(); + + /** destructor */ + ~BTrack(); + /** Initialise with frame size and set all frame sizes accordingly */ void initialise(int fsize); + + /** Add new sample to buffer and apply beat tracking */ void process(float df_sample); - void plotdfbuffer(); - void updatecumscore(float df_sample); - void predictbeat(); - void dfconvert(); - void calcTempo(); - void adapt_thresh(float x[],int N); - float mean_array(float array[],int start,int end); - void normalise(float array[],int N); - void acf_bal(float df_thresh[]); - void getrcfoutput(); + + /** Set the tempo of the beat tracker */ void settempo(float tempo); + + /** fix tempo to roughly around some value */ void fixtempo(float tempo); + + /** do not fix the tempo anymore */ void unfixtempo(); int playbeat; @@ -51,24 +52,53 @@ float est_tempo; private: + + /** Convert detection function from N samples to 512 */ + void dfconvert(); + + /** update the cumulative score */ + void updatecumscore(float df_sample); + + /** predicts the next beat */ + void predictbeat(); + + /** Calculates the current tempo expressed as the beat period in detection function samples */ + void calcTempo(); + + /** calculates an adaptive threshold which is used to remove low level energy from detection + * function and emphasise peaks + */ + void adapt_thresh(float x[],int N); + + /** calculates the mean of values in an array from index locations [start,end] */ + float mean_array(float array[],int start,int end); + + /** normalises a given array */ + void normalise(float array[],int N); + + /** calculates the balanced autocorrelation of the smoothed detection function */ + void acf_bal(float df_thresh[]); + + /** returns the output of the comb filter */ + void getrcfoutput(); // buffers - float *dfbuffer; // to hold detection function - float df512[512]; // to hold resampled detection function - float *cumscore; // to hold cumulative score + float *dfbuffer; /**< to hold detection function */ + float df512[512]; /**< to hold resampled detection function */ + float *cumscore; /**< to hold cumulative score */ - float acf[512]; // to hold autocorrelation function + float acf[512]; /**< to hold autocorrelation function */ - float wv[128]; // to hold weighting vector + float wv[128]; /**< to hold weighting vector */ - float rcf[128]; // to hold comb filter output - float t_obs[41]; // to hold tempo version of comb filter output + float rcf[128]; /**< to hold comb filter output */ + float t_obs[41]; /**< to hold tempo version of comb filter output */ - float delta[41]; // to hold final tempo candidate array - float prev_delta[41]; // previous delta - float prev_delta_fix[41]; // fixed tempo version of previous delta + float delta[41]; /**< to hold final tempo candidate array */ + float prev_delta[41]; /**< previous delta */ + float prev_delta_fix[41]; /**< fixed tempo version of previous delta */ - float t_tmat[41][41]; // transition matrix + float t_tmat[41][41]; /**< transition matrix */ // parameters
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unit-tests/BTrack Tests.xcodeproj/project.pbxproj Tue Jan 21 10:24:33 2014 +0000 @@ -0,0 +1,254 @@ +// !$*UTF8*$! +{ + archiveVersion = 1; + classes = { + }; + objectVersion = 46; + objects = { + +/* Begin PBXBuildFile section */ + E38214F0188E7AED00DDD7C8 /* main.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E38214EF188E7AED00DDD7C8 /* main.cpp */; }; + E38214F2188E7AED00DDD7C8 /* BTrack_Tests.1 in CopyFiles */ = {isa = PBXBuildFile; fileRef = E38214F1188E7AED00DDD7C8 /* BTrack_Tests.1 */; }; + E3A45DB9188E7BCD00B48CE4 /* BTrack.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3A45DB5188E7BCD00B48CE4 /* BTrack.cpp */; }; + E3A45DBA188E7BCD00B48CE4 /* OnsetDetectionFunction.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E3A45DB7188E7BCD00B48CE4 /* OnsetDetectionFunction.cpp */; }; +/* End PBXBuildFile section */ + +/* Begin PBXCopyFilesBuildPhase section */ + E38214EA188E7AED00DDD7C8 /* CopyFiles */ = { + isa = PBXCopyFilesBuildPhase; + buildActionMask = 2147483647; + dstPath = /usr/share/man/man1/; + dstSubfolderSpec = 0; + files = ( + E38214F2188E7AED00DDD7C8 /* BTrack_Tests.1 in CopyFiles */, + ); + runOnlyForDeploymentPostprocessing = 1; + }; +/* End PBXCopyFilesBuildPhase section */ + +/* Begin PBXFileReference section */ + E38214EC188E7AED00DDD7C8 /* BTrack Tests */ = {isa = PBXFileReference; explicitFileType = "compiled.mach-o.executable"; includeInIndex = 0; path = "BTrack Tests"; sourceTree = BUILT_PRODUCTS_DIR; }; + E38214EF188E7AED00DDD7C8 /* main.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; path = main.cpp; sourceTree = "<group>"; }; + E38214F1188E7AED00DDD7C8 /* BTrack_Tests.1 */ = {isa = PBXFileReference; lastKnownFileType = text.man; path = BTrack_Tests.1; sourceTree = "<group>"; }; + E3A45DB5188E7BCD00B48CE4 /* BTrack.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = BTrack.cpp; sourceTree = "<group>"; }; + E3A45DB6188E7BCD00B48CE4 /* BTrack.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = BTrack.h; sourceTree = "<group>"; }; + E3A45DB7188E7BCD00B48CE4 /* OnsetDetectionFunction.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = OnsetDetectionFunction.cpp; sourceTree = "<group>"; }; + E3A45DB8188E7BCD00B48CE4 /* OnsetDetectionFunction.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = OnsetDetectionFunction.h; sourceTree = "<group>"; }; +/* End PBXFileReference section */ + +/* Begin PBXFrameworksBuildPhase section */ + E38214E9188E7AED00DDD7C8 /* Frameworks */ = { + isa = PBXFrameworksBuildPhase; + buildActionMask = 2147483647; + files = ( + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXFrameworksBuildPhase section */ + +/* Begin PBXGroup section */ + E38214E3188E7AED00DDD7C8 = { + isa = PBXGroup; + children = ( + E38214EE188E7AED00DDD7C8 /* BTrack Tests */, + E38214ED188E7AED00DDD7C8 /* Products */, + ); + sourceTree = "<group>"; + }; + E38214ED188E7AED00DDD7C8 /* Products */ = { + isa = PBXGroup; + children = ( + E38214EC188E7AED00DDD7C8 /* BTrack Tests */, + ); + name = Products; + sourceTree = "<group>"; + }; + E38214EE188E7AED00DDD7C8 /* BTrack Tests */ = { + isa = PBXGroup; + children = ( + E38214EF188E7AED00DDD7C8 /* main.cpp */, + E3A45DB4188E7BCD00B48CE4 /* src */, + E38214F1188E7AED00DDD7C8 /* BTrack_Tests.1 */, + ); + path = "BTrack Tests"; + sourceTree = "<group>"; + }; + E3A45DB4188E7BCD00B48CE4 /* src */ = { + isa = PBXGroup; + children = ( + E3A45DB5188E7BCD00B48CE4 /* BTrack.cpp */, + E3A45DB6188E7BCD00B48CE4 /* BTrack.h */, + E3A45DB7188E7BCD00B48CE4 /* OnsetDetectionFunction.cpp */, + E3A45DB8188E7BCD00B48CE4 /* OnsetDetectionFunction.h */, + ); + name = src; + path = ../../src; + sourceTree = "<group>"; + }; +/* End PBXGroup section */ + +/* Begin PBXNativeTarget section */ + E38214EB188E7AED00DDD7C8 /* BTrack Tests */ = { + isa = PBXNativeTarget; + buildConfigurationList = E38214F5188E7AED00DDD7C8 /* Build configuration list for PBXNativeTarget "BTrack Tests" */; + buildPhases = ( + E38214E8188E7AED00DDD7C8 /* Sources */, + E38214E9188E7AED00DDD7C8 /* Frameworks */, + E38214EA188E7AED00DDD7C8 /* CopyFiles */, + ); + buildRules = ( + ); + dependencies = ( + ); + name = "BTrack Tests"; + productName = "BTrack Tests"; + productReference = E38214EC188E7AED00DDD7C8 /* BTrack Tests */; + productType = "com.apple.product-type.tool"; + }; +/* End PBXNativeTarget section */ + +/* Begin PBXProject section */ + E38214E4188E7AED00DDD7C8 /* Project object */ = { + isa = PBXProject; + attributes = { + LastUpgradeCheck = 0500; + ORGANIZATIONNAME = "Adam Stark"; + }; + buildConfigurationList = E38214E7188E7AED00DDD7C8 /* Build configuration list for PBXProject "BTrack Tests" */; + compatibilityVersion = "Xcode 3.2"; + developmentRegion = English; + hasScannedForEncodings = 0; + knownRegions = ( + en, + ); + mainGroup = E38214E3188E7AED00DDD7C8; + productRefGroup = E38214ED188E7AED00DDD7C8 /* Products */; + projectDirPath = ""; + projectRoot = ""; + targets = ( + E38214EB188E7AED00DDD7C8 /* BTrack Tests */, + ); + }; +/* End PBXProject section */ + +/* Begin PBXSourcesBuildPhase section */ + E38214E8188E7AED00DDD7C8 /* Sources */ = { + isa = PBXSourcesBuildPhase; + buildActionMask = 2147483647; + files = ( + E3A45DBA188E7BCD00B48CE4 /* OnsetDetectionFunction.cpp in Sources */, + E3A45DB9188E7BCD00B48CE4 /* BTrack.cpp in Sources */, + E38214F0188E7AED00DDD7C8 /* main.cpp in Sources */, + ); + runOnlyForDeploymentPostprocessing = 0; + }; +/* End PBXSourcesBuildPhase section */ + +/* Begin XCBuildConfiguration section */ + E38214F3188E7AED00DDD7C8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_DYNAMIC_NO_PIC = NO; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_OPTIMIZATION_LEVEL = 0; + GCC_PREPROCESSOR_DEFINITIONS = ( + "DEBUG=1", + "$(inherited)", + ); + GCC_SYMBOLS_PRIVATE_EXTERN = NO; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + ONLY_ACTIVE_ARCH = YES; + SDKROOT = macosx; + }; + name = Debug; + }; + E38214F4188E7AED00DDD7C8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; + CLANG_CXX_LIBRARY = "libc++"; + CLANG_ENABLE_OBJC_ARC = YES; + CLANG_WARN_BOOL_CONVERSION = YES; + CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; + CLANG_WARN_EMPTY_BODY = YES; + CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INT_CONVERSION = YES; + CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; + COPY_PHASE_STRIP = YES; + DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; + ENABLE_NS_ASSERTIONS = NO; + GCC_C_LANGUAGE_STANDARD = gnu99; + GCC_ENABLE_OBJC_EXCEPTIONS = YES; + GCC_WARN_64_TO_32_BIT_CONVERSION = YES; + GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; + GCC_WARN_UNDECLARED_SELECTOR = YES; + GCC_WARN_UNINITIALIZED_AUTOS = YES; + GCC_WARN_UNUSED_FUNCTION = YES; + GCC_WARN_UNUSED_VARIABLE = YES; + MACOSX_DEPLOYMENT_TARGET = 10.9; + SDKROOT = macosx; + }; + name = Release; + }; + E38214F6188E7AED00DDD7C8 /* Debug */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Debug; + }; + E38214F7188E7AED00DDD7C8 /* Release */ = { + isa = XCBuildConfiguration; + buildSettings = { + PRODUCT_NAME = "$(TARGET_NAME)"; + }; + name = Release; + }; +/* End XCBuildConfiguration section */ + +/* Begin XCConfigurationList section */ + E38214E7188E7AED00DDD7C8 /* Build configuration list for PBXProject "BTrack Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E38214F3188E7AED00DDD7C8 /* Debug */, + E38214F4188E7AED00DDD7C8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; + E38214F5188E7AED00DDD7C8 /* Build configuration list for PBXNativeTarget "BTrack Tests" */ = { + isa = XCConfigurationList; + buildConfigurations = ( + E38214F6188E7AED00DDD7C8 /* Debug */, + E38214F7188E7AED00DDD7C8 /* Release */, + ); + defaultConfigurationIsVisible = 0; + defaultConfigurationName = Release; + }; +/* End XCConfigurationList section */ + }; + rootObject = E38214E4188E7AED00DDD7C8 /* Project object */; +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unit-tests/BTrack Tests/BTrack_Tests.1 Tue Jan 21 10:24:33 2014 +0000 @@ -0,0 +1,79 @@ +.\"Modified from man(1) of FreeBSD, the NetBSD mdoc.template, and mdoc.samples. +.\"See Also: +.\"man mdoc.samples for a complete listing of options +.\"man mdoc for the short list of editing options +.\"/usr/share/misc/mdoc.template +.Dd 21/01/2014 \" DATE +.Dt BTrack Tests 1 \" Program name and manual section number +.Os Darwin +.Sh NAME \" Section Header - required - don't modify +.Nm BTrack Tests, +.\" The following lines are read in generating the apropos(man -k) database. Use only key +.\" words here as the database is built based on the words here and in the .ND line. +.Nm Other_name_for_same_program(), +.Nm Yet another name for the same program. +.\" Use .Nm macro to designate other names for the documented program. +.Nd This line parsed for whatis database. +.Sh SYNOPSIS \" Section Header - required - don't modify +.Nm +.Op Fl abcd \" [-abcd] +.Op Fl a Ar path \" [-a path] +.Op Ar file \" [file] +.Op Ar \" [file ...] +.Ar arg0 \" Underlined argument - use .Ar anywhere to underline +arg2 ... \" Arguments +.Sh DESCRIPTION \" Section Header - required - don't modify +Use the .Nm macro to refer to your program throughout the man page like such: +.Nm +Underlining is accomplished with the .Ar macro like this: +.Ar underlined text . +.Pp \" Inserts a space +A list of items with descriptions: +.Bl -tag -width -indent \" Begins a tagged list +.It item a \" Each item preceded by .It macro +Description of item a +.It item b +Description of item b +.El \" Ends the list +.Pp +A list of flags and their descriptions: +.Bl -tag -width -indent \" Differs from above in tag removed +.It Fl a \"-a flag as a list item +Description of -a flag +.It Fl b +Description of -b flag +.El \" Ends the list +.Pp +.\" .Sh ENVIRONMENT \" May not be needed +.\" .Bl -tag -width "ENV_VAR_1" -indent \" ENV_VAR_1 is width of the string ENV_VAR_1 +.\" .It Ev ENV_VAR_1 +.\" Description of ENV_VAR_1 +.\" .It Ev ENV_VAR_2 +.\" Description of ENV_VAR_2 +.\" .El +.Sh FILES \" File used or created by the topic of the man page +.Bl -tag -width "/Users/joeuser/Library/really_long_file_name" -compact +.It Pa /usr/share/file_name +FILE_1 description +.It Pa /Users/joeuser/Library/really_long_file_name +FILE_2 description +.El \" Ends the list +.\" .Sh DIAGNOSTICS \" May not be needed +.\" .Bl -diag +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .It Diagnostic Tag +.\" Diagnostic informtion here. +.\" .El +.Sh SEE ALSO +.\" List links in ascending order by section, alphabetically within a section. +.\" Please do not reference files that do not exist without filing a bug report +.Xr a 1 , +.Xr b 1 , +.Xr c 1 , +.Xr a 2 , +.Xr b 2 , +.Xr a 3 , +.Xr b 3 +.\" .Sh BUGS \" Document known, unremedied bugs +.\" .Sh HISTORY \" Document history if command behaves in a unique manner \ No newline at end of file
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/unit-tests/BTrack Tests/main.cpp Tue Jan 21 10:24:33 2014 +0000 @@ -0,0 +1,18 @@ +// +// main.cpp +// BTrack Tests +// +// Created by Adam Stark on 21/01/2014. +// Copyright (c) 2014 Adam Stark. All rights reserved. +// + +#include <iostream> + +int main(int argc, const char * argv[]) +{ + + // insert code here... + std::cout << "Hello, World!\n"; + return 0; +} +