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 } |