|
1 |
/**
|
|
2 |
This file is part of "onsetsds".
|
|
3 |
(c) 2011 Dan Stowell and Queen Mary University of London
|
|
4 |
All rights reserved.
|
|
5 |
|
|
6 |
onsetsds is free software: you can redistribute it and/or modify
|
|
7 |
it under the terms of the GNU General Public License as published by
|
|
8 |
the Free Software Foundation, either version 3 of the License, or
|
|
9 |
(at your option) any later version.
|
|
10 |
|
|
11 |
onsetsds is distributed in the hope that it will be useful,
|
|
12 |
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
13 |
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
14 |
GNU General Public License for more details.
|
|
15 |
|
|
16 |
You should have received a copy of the GNU General Public License
|
|
17 |
along with kdpee. If not, see <http://www.gnu.org/licenses/>.
|
|
18 |
*/
|
|
19 |
|
|
20 |
#include "math.h"
|
|
21 |
#include "mex.h"
|
|
22 |
#include "onsetsds.h"
|
|
23 |
|
|
24 |
////////////////////////////////////////////////////////////////////////
|
|
25 |
// MATLAB ENTRY FUNCTION:
|
|
26 |
void mexFunction(int nlhs, mxArray *plhs[], int nrhs, const mxArray *prhs[])
|
|
27 |
{
|
|
28 |
// implementation of: onsetsds(fftdata, odftype, medspan, srate)
|
|
29 |
|
|
30 |
// Get the star of the show, the fft data
|
|
31 |
const mxArray *fftdata;
|
|
32 |
fftdata = prhs[0];
|
|
33 |
if(!mxIsComplex(fftdata)){
|
|
34 |
mexErrMsgTxt("onsetsds expects a matrix of complex data (e.g. from fft()).\n");
|
|
35 |
}
|
|
36 |
const size_t fftframesize = mxGetM(fftdata);
|
|
37 |
const size_t numframes = mxGetN(fftdata);
|
|
38 |
|
|
39 |
const double* real = mxGetPr(fftdata);
|
|
40 |
const double* imag = mxGetPi(fftdata);
|
|
41 |
|
|
42 |
// optional args
|
|
43 |
int odftype = ODS_ODF_RCOMPLEX;
|
|
44 |
if(nrhs>1){
|
|
45 |
odftype = mxGetScalar(prhs[1]);
|
|
46 |
if((odftype < 0) || (newodftype > 6))
|
|
47 |
mexErrMsgTxt("onsetsds: unrecognised ODF type.\n");
|
|
48 |
}
|
|
49 |
const unsigned int medspan
|
|
50 |
= (nrhs<3) ? 11 : (unsigned int) mxGetScalar(prhs[2]);
|
|
51 |
const float srate = (nrhs<4) ? 44100.f : (float) mxGetScalar(prhs[3]);
|
|
52 |
|
|
53 |
// set up the ods
|
|
54 |
OnsetsDS ods;
|
|
55 |
float* odsdata = (float*) malloc( onsetsds_memneeded(odftype, fftframesize, medspan) );
|
|
56 |
onsetsds_init(&ods, odsdata, ODS_FFT_SC3_COMPLEX, odftype, fftframesize, medspan, srate);
|
|
57 |
|
|
58 |
// This is where we'll repack an individual frame
|
|
59 |
float* packeddata = malloc(fftframesize * sizeof(float));
|
|
60 |
|
|
61 |
// set up the output array, size numframes
|
|
62 |
double *results = (double*) mxCalloc(numframes, sizeof(double));
|
|
63 |
if(!results){
|
|
64 |
mexErrMsgTxt("onsetsds error, could not create results array (out of memory?).\n");
|
|
65 |
}
|
|
66 |
|
|
67 |
////////////////////////////////////////////////////////////////////////////
|
|
68 |
// iterate the frames, converting to expected format and onset-detecting
|
|
69 |
size_t i;
|
|
70 |
for(i=0; i<numframes; ++i){
|
|
71 |
// copy the data into an array in ODS_FFT_SC3_COMPLEX format.
|
|
72 |
// note that here we're discarding stuff above nyquist, since assuming real-valued input.
|
|
73 |
size_t frameoffset = fftframesize * i;
|
|
74 |
packeddata[0] = (float) real[frameoffset];
|
|
75 |
packeddata[1] = (float) real[frameoffset + fftframesize / 2];
|
|
76 |
size_t j;
|
|
77 |
for(j=1; j< fftframesize/2; ++j){
|
|
78 |
packeddata[j+j] = (float) real[frameoffset + j];
|
|
79 |
packeddata[j+j+1] = (float) imag[frameoffset + j];
|
|
80 |
}
|
|
81 |
bool onset = onsetsds_process(&ods, packeddata);
|
|
82 |
// printf("%i ", onset);
|
|
83 |
// printf("[%i] %i", i, onset);
|
|
84 |
results[i] = (onset ? 1.0 : 0.0);
|
|
85 |
// printf("[%i] %g", i, results[i]);
|
|
86 |
}
|
|
87 |
|
|
88 |
// Copy the results from double-array into matlab format
|
|
89 |
// mwSize *dims = (mwSize*) mxCalloc(2, sizeof(mwSize));
|
|
90 |
// dims[0] = 1;
|
|
91 |
// dims[1] = numframes;
|
|
92 |
// mxArray *resultsM = mxCreateNumericArray(2, dims, mxINT8_CLASS, mxREAL);
|
|
93 |
mxArray *resultsM = mxCreateDoubleMatrix(1,numframes,mxREAL);
|
|
94 |
// mxSetPr(resultsM, results);
|
|
95 |
memcpy(mxGetPr(resultsM), results, numframes * sizeof(double));
|
|
96 |
plhs[0] = resultsM;
|
|
97 |
|
|
98 |
// destroy the ods correctly, and any matlabby things that need to go too.
|
|
99 |
free(ods.data);
|
|
100 |
free(packeddata);
|
|
101 |
// mxFree(dims);
|
|
102 |
mxFree(results);
|
|
103 |
// *resultsM ? no I think that lives on in matlabworld
|
|
104 |
}
|