annotate modules-and-plug-ins/python-module/btrack_python_module.cpp @ 110:0fdaf082ad1a

Got compiling on M1 mac and Python 3
author Adam Stark <adamstark.uk@gmail.com>
date Sun, 31 Oct 2021 23:34:44 +0000
parents ce806db4468b
children
rev   line source
adamstark@51 1 #include <iostream>
adamstark@51 2 #include <Python.h>
adamstark@51 3 #include "../../src/OnsetDetectionFunction.h"
adamstark@51 4 #include "../../src/BTrack.h"
adamstark@51 5 #include <numpy/arrayobject.h>
adamstark@51 6
adamstark@55 7 //=======================================================================
adamstark@61 8 static PyObject * btrack_trackBeats(PyObject *dummy, PyObject *args)
adamstark@61 9 {
adamstark@61 10 PyObject *arg1=NULL;
adamstark@61 11 PyObject *arr1=NULL;
adamstark@61 12
adamstark@61 13 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@61 14 {
adamstark@61 15 return NULL;
adamstark@61 16 }
adamstark@61 17
adamstark@61 18 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@61 19 if (arr1 == NULL)
adamstark@61 20 {
adamstark@61 21 return NULL;
adamstark@61 22 }
adamstark@61 23
adamstark@61 24
adamstark@61 25
adamstark@61 26 ////////// GET INPUT DATA ///////////////////
adamstark@61 27
adamstark@61 28 // get data as array
adamstark@61 29 double* data = (double*) PyArray_DATA(arr1);
adamstark@61 30
adamstark@61 31 // get array size
adamstark@61 32 long signal_length = PyArray_Size((PyObject*)arr1);
adamstark@61 33
adamstark@61 34
adamstark@61 35 ////////// BEGIN PROCESS ///////////////////
adamstark@61 36 int hopSize = 512;
adamstark@61 37 int frameSize = 1024;
adamstark@61 38
adamstark@61 39 int numframes;
adamstark@61 40 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples
adamstark@61 41
adamstark@61 42
adamstark@61 43 // get number of audio frames, given the hop size and signal length
adamstark@61 44 numframes = (int) floor(((double) signal_length) / ((double) hopSize));
adamstark@61 45
adamstark@61 46
adamstark@61 47 BTrack b(hopSize,frameSize);
adamstark@61 48
adamstark@61 49
adamstark@61 50 double beats[5000];
adamstark@61 51 int beatnum = 0;
adamstark@61 52
adamstark@61 53 ///////////////////////////////////////////
adamstark@61 54 //////// Begin Processing Loop ////////////
adamstark@61 55
adamstark@61 56 for (int i=0;i < numframes;i++)
adamstark@61 57 {
adamstark@61 58 // add new samples to frame
adamstark@61 59 for (int n = 0;n < hopSize;n++)
adamstark@61 60 {
adamstark@61 61 buffer[n] = data[(i*hopSize)+n];
adamstark@61 62 }
adamstark@61 63
adamstark@61 64 // process the current audio frame
adamstark@61 65 b.processAudioFrame(buffer);
adamstark@61 66
adamstark@61 67 // if a beat is currently scheduled
adamstark@61 68 if (b.beatDueInCurrentFrame())
adamstark@61 69 {
adamstark@61 70 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
adamstark@61 71 beatnum = beatnum + 1;
adamstark@61 72 }
adamstark@61 73
adamstark@61 74 }
adamstark@61 75
adamstark@61 76 ///////// End Processing Loop /////////////
adamstark@61 77 ///////////////////////////////////////////
adamstark@61 78
adamstark@61 79
adamstark@61 80 ////////// END PROCESS ///////////////////
adamstark@61 81
adamstark@61 82 double beats_out[beatnum]; // create output array
adamstark@61 83
adamstark@61 84 // copy beats into output array
adamstark@61 85 for (int i = 0;i < beatnum;i++)
adamstark@61 86 {
adamstark@61 87 beats_out[i] = beats[i];
adamstark@61 88 }
adamstark@61 89
adamstark@61 90
adamstark@61 91
adamstark@61 92 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@61 93 int nd=1;
adamstark@61 94 npy_intp m= beatnum;
adamstark@61 95 //double fArray[5] = {0,1,2,3,4};
adamstark@61 96
adamstark@61 97 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@61 98
adamstark@61 99 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@61 100
adamstark@61 101 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@61 102
adamstark@61 103
adamstark@61 104 Py_DECREF(arr1);
adamstark@61 105 Py_INCREF(Py_None);
adamstark@61 106 //return Py_None;
adamstark@61 107
adamstark@61 108 return (PyObject *)c;
adamstark@61 109 }
adamstark@61 110
adamstark@61 111
adamstark@61 112 //=======================================================================
adamstark@61 113 static PyObject * btrack_calculateOnsetDF(PyObject *dummy, PyObject *args)
adamstark@51 114 {
adamstark@51 115 PyObject *arg1=NULL;
adamstark@51 116 PyObject *arr1=NULL;
adamstark@51 117
adamstark@51 118 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 119 {
adamstark@51 120 return NULL;
adamstark@51 121 }
adamstark@51 122
adamstark@51 123 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 124 if (arr1 == NULL)
adamstark@51 125 {
adamstark@51 126 return NULL;
adamstark@51 127 }
adamstark@51 128
adamstark@51 129
adamstark@51 130
adamstark@51 131 ////////// GET INPUT DATA ///////////////////
adamstark@51 132
adamstark@51 133 // get data as array
adamstark@51 134 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 135
adamstark@51 136 // get array size
adamstark@52 137 long signal_length = PyArray_Size((PyObject*)arr1);
adamstark@51 138
adamstark@51 139 ////////// BEGIN PROCESS ///////////////////
adamstark@55 140 int hopSize = 512;
adamstark@55 141 int frameSize = 1024;
adamstark@51 142 int df_type = 6;
adamstark@51 143 int numframes;
adamstark@55 144 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples
adamstark@51 145
adamstark@51 146
adamstark@51 147 // get number of audio frames, given the hop size and signal length
adamstark@55 148 numframes = (int) floor(((double) signal_length) / ((double) hopSize));
adamstark@51 149
adamstark@55 150 OnsetDetectionFunction onset(hopSize,frameSize,df_type,1);
adamstark@51 151
adamstark@51 152 double df[numframes];
adamstark@51 153
adamstark@51 154
adamstark@51 155
adamstark@51 156 ///////////////////////////////////////////
adamstark@51 157 //////// Begin Processing Loop ////////////
adamstark@51 158
adamstark@51 159 for (int i=0;i < numframes;i++)
adamstark@51 160 {
adamstark@51 161 // add new samples to frame
adamstark@55 162 for (int n = 0;n < hopSize;n++)
adamstark@51 163 {
adamstark@55 164 buffer[n] = data[(i*hopSize)+n];
adamstark@51 165 }
adamstark@51 166
adamstark@59 167 df[i] = onset.calculateOnsetDetectionFunctionSample(buffer);
adamstark@51 168
adamstark@51 169 }
adamstark@51 170
adamstark@51 171 ///////// End Processing Loop /////////////
adamstark@51 172 ///////////////////////////////////////////
adamstark@51 173
adamstark@51 174
adamstark@61 175
adamstark@51 176
adamstark@51 177 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 178 int nd=1;
adamstark@51 179 npy_intp m= numframes;
adamstark@61 180
adamstark@51 181
adamstark@51 182 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 183
adamstark@51 184 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 185
adamstark@51 186 memcpy(arr_data, df, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 187
adamstark@51 188
adamstark@51 189 Py_DECREF(arr1);
adamstark@51 190 Py_INCREF(Py_None);
adamstark@51 191 //return Py_None;
adamstark@51 192
adamstark@51 193 return (PyObject *)c;
adamstark@51 194 }
adamstark@51 195
adamstark@51 196
adamstark@55 197 //=======================================================================
adamstark@61 198 static PyObject * btrack_trackBeatsFromOnsetDF(PyObject *dummy, PyObject *args)
adamstark@51 199 {
adamstark@51 200 PyObject *arg1=NULL;
adamstark@51 201 PyObject *arr1=NULL;
adamstark@51 202
adamstark@51 203 if (!PyArg_ParseTuple(args, "O", &arg1))
adamstark@51 204 {
adamstark@51 205 return NULL;
adamstark@51 206 }
adamstark@51 207
adamstark@51 208 arr1 = PyArray_FROM_OTF(arg1, NPY_DOUBLE, NPY_IN_ARRAY);
adamstark@51 209 if (arr1 == NULL)
adamstark@51 210 {
adamstark@51 211 return NULL;
adamstark@51 212 }
adamstark@51 213
adamstark@51 214
adamstark@51 215
adamstark@51 216 ////////// GET INPUT DATA ///////////////////
adamstark@51 217
adamstark@51 218 // get data as array
adamstark@51 219 double* data = (double*) PyArray_DATA(arr1);
adamstark@51 220
adamstark@51 221 // get array size
adamstark@52 222 long numframes = PyArray_Size((PyObject*)arr1);
adamstark@55 223
adamstark@51 224 ////////// BEGIN PROCESS ///////////////////
adamstark@55 225 int hopSize = 512;
adamstark@55 226 int frameSize = 2*hopSize;
adamstark@51 227
adamstark@55 228 BTrack b(hopSize,frameSize);
adamstark@51 229
adamstark@51 230 double beats[5000];
adamstark@51 231 int beatnum = 0;
adamstark@54 232 double df_val;
adamstark@51 233
adamstark@51 234 ///////////////////////////////////////////
adamstark@51 235 //////// Begin Processing Loop ////////////
adamstark@51 236
adamstark@52 237 for (long i=0;i < numframes;i++)
adamstark@51 238 {
adamstark@54 239 df_val = data[i] + 0.0001;
adamstark@51 240
adamstark@55 241 b.processOnsetDetectionFunctionSample(df_val); // process df sample in beat tracker
adamstark@51 242
adamstark@57 243 if (b.beatDueInCurrentFrame())
adamstark@51 244 {
adamstark@55 245 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100);
adamstark@51 246 beatnum = beatnum + 1;
adamstark@51 247 }
adamstark@51 248
adamstark@51 249 }
adamstark@51 250
adamstark@51 251 ///////// End Processing Loop /////////////
adamstark@51 252 ///////////////////////////////////////////
adamstark@51 253
adamstark@51 254
adamstark@51 255 ////////// END PROCESS ///////////////////
adamstark@51 256
adamstark@51 257 double beats_out[beatnum]; // create output array
adamstark@51 258
adamstark@51 259
adamstark@51 260 // copy beats into output array
adamstark@51 261 for (int i = 0;i < beatnum;i++)
adamstark@51 262 {
adamstark@51 263 beats_out[i] = beats[i];
adamstark@51 264 }
adamstark@51 265
adamstark@51 266
adamstark@51 267 ////////// CREATE ARRAY AND RETURN IT ///////////////////
adamstark@51 268 int nd=1;
adamstark@51 269 npy_intp m= beatnum;
adamstark@51 270 //double fArray[5] = {0,1,2,3,4};
adamstark@51 271
adamstark@51 272 PyObject* c=PyArray_SimpleNew(nd, &m, NPY_DOUBLE);
adamstark@51 273
adamstark@51 274 void *arr_data = PyArray_DATA((PyArrayObject*)c);
adamstark@51 275
adamstark@51 276 memcpy(arr_data, beats_out, PyArray_ITEMSIZE((PyArrayObject*) c) * m);
adamstark@51 277
adamstark@51 278
adamstark@51 279 Py_DECREF(arr1);
adamstark@51 280 Py_INCREF(Py_None);
adamstark@51 281 //return Py_None;
adamstark@51 282
adamstark@51 283 return (PyObject *)c;
adamstark@51 284 }
adamstark@51 285
adamstark@55 286 //=======================================================================
adamstark@51 287 static PyMethodDef btrack_methods[] = {
adamstark@61 288 { "calculateOnsetDF",btrack_calculateOnsetDF,METH_VARARGS,"Calculate the onset detection function"},
adamstark@61 289 { "trackBeats",btrack_trackBeats,METH_VARARGS,"Track beats from audio"},
adamstark@61 290 { "trackBeatsFromOnsetDF",btrack_trackBeatsFromOnsetDF,METH_VARARGS,"Track beats from an onset detection function"},
adamstark@51 291 {NULL, NULL, 0, NULL} /* Sentinel */
adamstark@51 292 };
adamstark@51 293
adamstark@55 294 //=======================================================================
adamstark@110 295 static struct PyModuleDef btrack_definition = {
adamstark@110 296 PyModuleDef_HEAD_INIT,
adamstark@110 297 "btrack",
adamstark@110 298 "Python bindings for the BTrack beat tracker",
adamstark@110 299 -1,
adamstark@110 300 btrack_methods
adamstark@110 301 };
adamstark@110 302
adamstark@110 303 //=======================================================================
adamstark@110 304 PyMODINIT_FUNC PyInit_btrack(void)
adamstark@51 305 {
adamstark@51 306 import_array();
adamstark@110 307 return PyModule_Create(&btrack_definition);
adamstark@51 308 }
adamstark@51 309
adamstark@55 310 //=======================================================================
adamstark@51 311 int main(int argc, char *argv[])
adamstark@51 312 {
adamstark@110 313 wchar_t* program = Py_DecodeLocale (argv[0], NULL);
adamstark@110 314 Py_SetProgramName (program);
adamstark@51 315
adamstark@51 316 /* Initialize the Python interpreter. Required. */
adamstark@51 317 Py_Initialize();
adamstark@51 318
adamstark@51 319 /* Add a static module */
adamstark@110 320 PyInit_btrack();
adamstark@51 321 }