Mercurial > hg > btrack
comparison modules-and-plug-ins/python-module/btrack_python_module.cpp @ 18:450c53430540 develop
Changed the interface of the algorithm so that onset detection function samples are calculated internally. This makes the call to the algorithm for most cases much simpler. Also added a static function for calculating beat times in seconds based upon sampling frequency, hop size and the current frame number.
author | Adam <adamstark.uk@gmail.com> |
---|---|
date | Wed, 22 Jan 2014 18:47:16 +0000 |
parents | a31841af2bbc |
children | baf35f208814 |
comparison
equal
deleted
inserted
replaced
17:a31841af2bbc | 18:450c53430540 |
---|---|
2 #include <Python.h> | 2 #include <Python.h> |
3 #include "../../src/OnsetDetectionFunction.h" | 3 #include "../../src/OnsetDetectionFunction.h" |
4 #include "../../src/BTrack.h" | 4 #include "../../src/BTrack.h" |
5 #include <numpy/arrayobject.h> | 5 #include <numpy/arrayobject.h> |
6 | 6 |
7 //======================================================================= | |
7 static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args) | 8 static PyObject * btrack_onsetdf(PyObject *dummy, PyObject *args) |
8 { | 9 { |
9 PyObject *arg1=NULL; | 10 PyObject *arg1=NULL; |
10 PyObject *arr1=NULL; | 11 PyObject *arr1=NULL; |
11 | 12 |
27 // get data as array | 28 // get data as array |
28 double* data = (double*) PyArray_DATA(arr1); | 29 double* data = (double*) PyArray_DATA(arr1); |
29 | 30 |
30 // get array size | 31 // get array size |
31 long signal_length = PyArray_Size((PyObject*)arr1); | 32 long signal_length = PyArray_Size((PyObject*)arr1); |
32 //int k = (int) theSize; | |
33 | |
34 // get data type | |
35 //char type = PyArray_DESCR(arr1)->type; | |
36 | 33 |
37 ////////// BEGIN PROCESS /////////////////// | 34 ////////// BEGIN PROCESS /////////////////// |
38 int hsize = 512; | 35 int hopSize = 512; |
39 int fsize = 1024; | 36 int frameSize = 1024; |
40 int df_type = 6; | 37 int df_type = 6; |
41 int numframes; | 38 int numframes; |
42 double buffer[hsize]; // buffer to hold one hopsize worth of audio samples | 39 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples |
43 | 40 |
44 | 41 |
45 // get number of audio frames, given the hop size and signal length | 42 // get number of audio frames, given the hop size and signal length |
46 numframes = (int) floor(((double) signal_length) / ((double) hsize)); | 43 numframes = (int) floor(((double) signal_length) / ((double) hopSize)); |
47 | 44 |
48 OnsetDetectionFunction onset(hsize,fsize,df_type,1); | 45 OnsetDetectionFunction onset(hopSize,frameSize,df_type,1); |
49 | 46 |
50 double df[numframes]; | 47 double df[numframes]; |
51 | 48 |
52 | 49 |
53 | 50 |
55 //////// Begin Processing Loop //////////// | 52 //////// Begin Processing Loop //////////// |
56 | 53 |
57 for (int i=0;i < numframes;i++) | 54 for (int i=0;i < numframes;i++) |
58 { | 55 { |
59 // add new samples to frame | 56 // add new samples to frame |
60 for (int n = 0;n < hsize;n++) | 57 for (int n = 0;n < hopSize;n++) |
61 { | 58 { |
62 buffer[n] = data[(i*hsize)+n]; | 59 buffer[n] = data[(i*hopSize)+n]; |
63 } | 60 } |
64 | 61 |
65 df[i] = onset.getDFsample(buffer); | 62 df[i] = onset.getDFsample(buffer); |
66 | 63 |
67 } | 64 } |
89 Py_DECREF(arr1); | 86 Py_DECREF(arr1); |
90 Py_INCREF(Py_None); | 87 Py_INCREF(Py_None); |
91 //return Py_None; | 88 //return Py_None; |
92 | 89 |
93 return (PyObject *)c; | 90 return (PyObject *)c; |
94 | 91 } |
95 //return Py_BuildValue("c", type); | 92 |
96 //return Py_BuildValue("d", sum); | 93 //======================================================================= |
97 //return Py_BuildValue("i", k); | |
98 /* | |
99 fail: | |
100 Py_XDECREF(arr1); | |
101 Py_XDECREF(arr2); | |
102 PyArray_XDECREF_ERR(oarr); | |
103 return NULL;*/ | |
104 } | |
105 | |
106 | |
107 static PyObject * btrack_btrack(PyObject *dummy, PyObject *args) | 94 static PyObject * btrack_btrack(PyObject *dummy, PyObject *args) |
108 { | 95 { |
109 PyObject *arg1=NULL; | 96 PyObject *arg1=NULL; |
110 PyObject *arr1=NULL; | 97 PyObject *arr1=NULL; |
111 | 98 |
127 // get data as array | 114 // get data as array |
128 double* data = (double*) PyArray_DATA(arr1); | 115 double* data = (double*) PyArray_DATA(arr1); |
129 | 116 |
130 // get array size | 117 // get array size |
131 long signal_length = PyArray_Size((PyObject*)arr1); | 118 long signal_length = PyArray_Size((PyObject*)arr1); |
132 //int k = (int) theSize; | 119 |
133 | |
134 // get data type | |
135 //char type = PyArray_DESCR(arr1)->type; | |
136 | 120 |
137 ////////// BEGIN PROCESS /////////////////// | 121 ////////// BEGIN PROCESS /////////////////// |
138 int hsize = 512; | 122 int hopSize = 512; |
139 int fsize = 1024; | 123 int frameSize = 1024; |
140 int df_type = 6; | 124 |
141 int numframes; | 125 int numframes; |
142 double buffer[hsize]; // buffer to hold one hopsize worth of audio samples | 126 double buffer[hopSize]; // buffer to hold one hopsize worth of audio samples |
143 | 127 |
144 | 128 |
145 // get number of audio frames, given the hop size and signal length | 129 // get number of audio frames, given the hop size and signal length |
146 numframes = (int) floor(((double) signal_length) / ((double) hsize)); | 130 numframes = (int) floor(((double) signal_length) / ((double) hopSize)); |
147 | 131 |
148 OnsetDetectionFunction onset(hsize,fsize,df_type,1); | 132 |
149 BTrack b; | 133 BTrack b(hopSize,frameSize); |
150 | 134 |
151 b.initialise((int) hsize); // initialise beat tracker | 135 |
152 | |
153 // set parameters | |
154 //b.setparams(0.9,5); | |
155 | |
156 double df[numframes]; | |
157 double beats[5000]; | 136 double beats[5000]; |
158 int beatnum = 0; | 137 int beatnum = 0; |
159 | |
160 double df_val; | |
161 | 138 |
162 /////////////////////////////////////////// | 139 /////////////////////////////////////////// |
163 //////// Begin Processing Loop //////////// | 140 //////// Begin Processing Loop //////////// |
164 | 141 |
165 for (int i=0;i < numframes;i++) | 142 for (int i=0;i < numframes;i++) |
166 { | 143 { |
167 // add new samples to frame | 144 // add new samples to frame |
168 for (int n = 0;n < hsize;n++) | 145 for (int n = 0;n < hopSize;n++) |
169 { | 146 { |
170 buffer[n] = data[(i*hsize)+n]; | 147 buffer[n] = data[(i*hopSize)+n]; |
171 } | 148 } |
172 | 149 |
173 df[i] = onset.getDFsample(buffer); | 150 // process the current audio frame |
151 b.processAudioFrame(buffer); | |
174 | 152 |
175 df_val = df[i] + 0.0001; | 153 // if a beat is currently scheduled |
176 | |
177 b.process(df_val); // process df sample in beat tracker | |
178 | |
179 if (b.playbeat == 1) | 154 if (b.playbeat == 1) |
180 { | 155 { |
181 beats[beatnum] = (((double) hsize) / 44100) * ((double) i); | 156 //beats[beatnum] = (((double) hopSize) / 44100) * ((double) i); |
182 beatnum = beatnum + 1; | 157 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100); |
158 beatnum = beatnum + 1; | |
183 } | 159 } |
184 | 160 |
185 } | 161 } |
186 | 162 |
187 ///////// End Processing Loop ///////////// | 163 ///////// End Processing Loop ///////////// |
215 Py_DECREF(arr1); | 191 Py_DECREF(arr1); |
216 Py_INCREF(Py_None); | 192 Py_INCREF(Py_None); |
217 //return Py_None; | 193 //return Py_None; |
218 | 194 |
219 return (PyObject *)c; | 195 return (PyObject *)c; |
220 | 196 } |
221 //return Py_BuildValue("c", type); | 197 |
222 //return Py_BuildValue("d", sum); | 198 //======================================================================= |
223 //return Py_BuildValue("i", k); | |
224 /* | |
225 fail: | |
226 Py_XDECREF(arr1); | |
227 Py_XDECREF(arr2); | |
228 PyArray_XDECREF_ERR(oarr); | |
229 return NULL;*/ | |
230 } | |
231 | |
232 static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args) | 199 static PyObject * btrack_btrack_df(PyObject *dummy, PyObject *args) |
233 { | 200 { |
234 PyObject *arg1=NULL; | 201 PyObject *arg1=NULL; |
235 PyObject *arr1=NULL; | 202 PyObject *arr1=NULL; |
236 | 203 |
252 // get data as array | 219 // get data as array |
253 double* data = (double*) PyArray_DATA(arr1); | 220 double* data = (double*) PyArray_DATA(arr1); |
254 | 221 |
255 // get array size | 222 // get array size |
256 long numframes = PyArray_Size((PyObject*)arr1); | 223 long numframes = PyArray_Size((PyObject*)arr1); |
257 //int k = (int) theSize; | 224 |
258 | |
259 // get data type | |
260 //char type = PyArray_DESCR(arr1)->type; | |
261 | |
262 ////////// BEGIN PROCESS /////////////////// | 225 ////////// BEGIN PROCESS /////////////////// |
263 int hsize = 512; | 226 int hopSize = 512; |
264 | 227 int frameSize = 2*hopSize; |
265 BTrack b; | 228 |
266 | 229 BTrack b(hopSize,frameSize); |
267 b.initialise((int) hsize); // initialise beat tracker | |
268 | |
269 // set parameters | |
270 //b.setparams(0.9,5); | |
271 | 230 |
272 double beats[5000]; | 231 double beats[5000]; |
273 int beatnum = 0; | 232 int beatnum = 0; |
274 double df_val; | 233 double df_val; |
275 | 234 |
278 | 237 |
279 for (long i=0;i < numframes;i++) | 238 for (long i=0;i < numframes;i++) |
280 { | 239 { |
281 df_val = data[i] + 0.0001; | 240 df_val = data[i] + 0.0001; |
282 | 241 |
283 b.process(df_val); // process df sample in beat tracker | 242 b.processOnsetDetectionFunctionSample(df_val); // process df sample in beat tracker |
284 | 243 |
285 if (b.playbeat == 1) | 244 if (b.playbeat == 1) |
286 { | 245 { |
287 beats[beatnum] = (((double) hsize) / 44100) * ((double) i); | 246 //beats[beatnum] = (((double) hopSize) / 44100) * ((double) i); |
247 beats[beatnum] = BTrack::getBeatTimeInSeconds(i,hopSize,44100); | |
288 beatnum = beatnum + 1; | 248 beatnum = beatnum + 1; |
289 } | 249 } |
290 | 250 |
291 } | 251 } |
292 | 252 |
321 Py_DECREF(arr1); | 281 Py_DECREF(arr1); |
322 Py_INCREF(Py_None); | 282 Py_INCREF(Py_None); |
323 //return Py_None; | 283 //return Py_None; |
324 | 284 |
325 return (PyObject *)c; | 285 return (PyObject *)c; |
326 | 286 } |
327 //return Py_BuildValue("c", type); | 287 |
328 //return Py_BuildValue("d", sum); | 288 |
329 //return Py_BuildValue("i", k); | 289 //======================================================================= |
330 /* | |
331 fail: | |
332 Py_XDECREF(arr1); | |
333 Py_XDECREF(arr2); | |
334 PyArray_XDECREF_ERR(oarr); | |
335 return NULL;*/ | |
336 } | |
337 | |
338 | |
339 | |
340 static PyMethodDef btrack_methods[] = { | 290 static PyMethodDef btrack_methods[] = { |
341 { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"}, | 291 { "onsetdf",btrack_onsetdf,METH_VARARGS,"onset detection function"}, |
342 { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"}, | 292 { "btrack",btrack_btrack,METH_VARARGS,"beat tracker"}, |
343 { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"}, | 293 { "btrack_df",btrack_btrack_df,METH_VARARGS,"beat tracker with detection function input"}, |
344 {NULL, NULL, 0, NULL} /* Sentinel */ | 294 {NULL, NULL, 0, NULL} /* Sentinel */ |
345 }; | 295 }; |
346 | 296 |
297 //======================================================================= | |
347 PyMODINIT_FUNC initbtrack(void) | 298 PyMODINIT_FUNC initbtrack(void) |
348 { | 299 { |
349 (void)Py_InitModule("btrack", btrack_methods); | 300 (void)Py_InitModule("btrack", btrack_methods); |
350 import_array(); | 301 import_array(); |
351 } | 302 } |
352 | 303 |
304 //======================================================================= | |
353 int main(int argc, char *argv[]) | 305 int main(int argc, char *argv[]) |
354 { | 306 { |
355 /* Pass argv[0] to the Python interpreter */ | 307 /* Pass argv[0] to the Python interpreter */ |
356 Py_SetProgramName(argv[0]); | 308 Py_SetProgramName(argv[0]); |
357 | 309 |