Mercurial > hg > aubio-onset-detector
view Source/aubioOnsetDetect~.cpp @ 1:a7b9c6885eb8
added in a best slope function, a mix between max increase in the recent df function and the gradient of this increase
author | Andrew N Robertson <andrew.robertson@eecs.qmul.ac.uk> |
---|---|
date | Tue, 18 Oct 2011 14:52:27 +0100 |
parents | 8f67db3c0b01 |
children | b4c899822b4e |
line wrap: on
line source
/** @file aubioOnsetDetect - an MSP object shell jeremy bernstein - jeremy@bootsquad.com @ingroup examples */ #include "ext.h" // standard Max include, always required (except in Jitter) #include "ext_obex.h" // required for new style objects #include "z_dsp.h" // required for MSP objects #include "AubioOnsetDetector.h" #include "aubio.h" ////////////////////////// object struct typedef struct _aubioOnsetDetect { t_pxobject ob; // the object itself (t_pxobject in MSP) t_float threshold; t_float threshold2; t_int bufsize; t_int hopsize; AubioOnsetDetector *onsetDetector; void *bangoutlet; void *medianBangOutlet; void *detectionFunctionOutlet; void *rawDetectionFunctionOutlet; void *medianDetectionFunctionOutlet; bool useMedianOnsetDetection;//(true) //rather than Paul B's peak picking (false) } t_aubioOnsetDetect; ///////////////////////// function prototypes //// standard set void *aubioOnsetDetect_new(t_symbol *s, long argc, t_atom *argv); void aubioOnsetDetect_free(t_aubioOnsetDetect *x); void aubioOnsetDetect_assist(t_aubioOnsetDetect *x, void *b, long m, long a, char *s); void aubioOnsetDetect_float(t_aubioOnsetDetect *x, double f); void aubioOnsetDetect_energy(t_aubioOnsetDetect *x); void aubioOnsetDetect_hfc(t_aubioOnsetDetect *x); void aubioOnsetDetect_complex(t_aubioOnsetDetect *x); void aubioOnsetDetect_phase(t_aubioOnsetDetect *x); void aubioOnsetDetect_specdiff(t_aubioOnsetDetect *x); void aubioOnsetDetect_kl(t_aubioOnsetDetect *x); void aubioOnsetDetect_mkl(t_aubioOnsetDetect *x); void aubioOnsetDetect_dsp(t_aubioOnsetDetect *x, t_signal **sp, short *count); t_int *aubioOnsetDetect_perform(t_int *w); //////////////////////// global class pointer variable void *aubioOnsetDetect_class; int main(void) { // object initialization, note the use of dsp_free for the freemethod, which is required // unless you need to free allocated memory, in which case you should call dsp_free from // your custom free function. // NEW METHOD t_class *c; c = class_new("aubioOnsetDetect~", (method)aubioOnsetDetect_new, (method)dsp_free, (long)sizeof(t_aubioOnsetDetect), 0L, A_GIMME, 0); class_addmethod(c, (method)aubioOnsetDetect_float, (char*)"float", A_FLOAT, 0); class_addmethod(c, (method)aubioOnsetDetect_dsp, (char*) "dsp", A_CANT, 0); class_addmethod(c, (method)aubioOnsetDetect_assist, (char*)"assist", A_CANT, 0); class_addmethod(c, (method)aubioOnsetDetect_energy, (char*)"energy", 0); class_addmethod(c, (method)aubioOnsetDetect_hfc, (char*)"hfc", 0); class_addmethod(c, (method)aubioOnsetDetect_phase, (char*)"phase", 0); class_addmethod(c, (method)aubioOnsetDetect_complex, (char*)"complex", 0); class_addmethod(c, (method)aubioOnsetDetect_specdiff, (char*)"specdiff", 0); class_addmethod(c, (method)aubioOnsetDetect_kl, (char*)"kl", 0); class_addmethod(c, (method)aubioOnsetDetect_mkl, (char*)"mkl", 0); class_register(CLASS_BOX, c); // register class as a box class class_dspinit(c); // new style object version of dsp_initclass(); CLASS_ATTR_FLOAT(c, "threshold", 0, t_aubioOnsetDetect, threshold);//threshold is an attribute and can be set in info page for object aubioOnsetDetect_class = c; return 0; } void aubioOnsetDetect_float(t_aubioOnsetDetect *x, double f) { if (f < 10 || f > 0.1){ x->threshold = f; x->onsetDetector->threshold = f; } //post("Threshold is %f", x->threshold); } void aubioOnsetDetect_energy(t_aubioOnsetDetect *x){ x->onsetDetector->onsetclass_energy(); post("Energy based onset detection now used by aubioOnsetDetect~."); } void aubioOnsetDetect_hfc(t_aubioOnsetDetect *x){ /** High Frequency Content onset detection function This method computes the High Frequency Content (HFC) of the input spectral frame. The resulting function is efficient at detecting percussive onsets. Paul Masri. Computer modeling of Sound for Transformation and Synthesis of Musical Signal. PhD dissertation, University of Bristol, UK, 1996.*/ x->onsetDetector->onsetclass_hfc(); post("High Frequency Content (Masri '96) detection now used by aubioOnsetDetect~."); } void aubioOnsetDetect_complex(t_aubioOnsetDetect *x){ //Complex Domain Method onset detection function //Christopher Duxbury, Mike E. Davies, and Mark B. Sandler. Complex domain //onset detection for musical signals. In Proceedings of the Digital Audio //Effects Conference, DAFx-03, pages 90-93, London, UK, 2003. x->onsetDetector->onsetclass_complex(); post("Complex domain onset detection (Duxbury et al., DaFx '03) now used by aubioOnsetDetect~."); } void aubioOnsetDetect_phase(t_aubioOnsetDetect *x){ /** Phase Based Method onset detection function Juan-Pablo Bello, Mike P. Davies, and Mark B. Sandler. Phase-based note onset detection for music signals. In Proceedings of the IEEE International Conference on Acoustics Speech and Signal Processing, pages 441444, Hong-Kong, 2003.*/ x->onsetDetector->onsetclass_phase(); object_post((t_object *) x, "Phase-based detection (Bello et al., IEEE '03) now used by aubioOnsetDetect~."); } void aubioOnsetDetect_specdiff(t_aubioOnsetDetect *x){ /* Spectral difference method onset detection function Jonhatan Foote and Shingo Uchihashi. The beat spectrum: a new approach to rhythm analysis. In IEEE International Conference on Multimedia and Expo (ICME 2001), pages 881884, Tokyo, Japan, August 2001. */ //aubio_onsetdetection_type //aubio_onsetdetection_free (x->o); x->onsetDetector->onsetclass_specdiff(); post("Spectral Difference (Foote and Shingo Uchihashi, ICME '01) detection now used by aubioOnsetDetect~."); } void aubioOnsetDetect_kl(t_aubioOnsetDetect *x){ //aubio_onsetdetection_type //aubio_onsetdetection_free (x->o); /** Kullback-Liebler onset detection function Stephen Hainsworth and Malcom Macleod. Onset detection in music audio signals. In Proceedings of the International Computer Music Conference (ICMC), Singapore, 2003. */ x->onsetDetector->onsetclass_kl(); post("Kullback-Liebler (Hainsworth and McLeod, ICMC '03) detection now used by aubioOnsetDetect~."); } void aubioOnsetDetect_mkl(t_aubioOnsetDetect *x){ /** Modified Kullback-Liebler onset detection function Paul Brossier, ``Automatic annotation of musical audio for interactive systems'', Chapter 2, Temporal segmentation, PhD thesis, Centre for Digital music, Queen Mary University of London, London, UK, 2003.*/ x->onsetDetector->onsetclass_mkl(); post("Modified Kullback-Liebler (Brossier, PhD thesis '03) detection now used by aubioOnsetDetect~."); } // this function is called when the DAC is enabled, and "registers" a function // for the signal chain. in this case, "aubioOnsetDetect_perform" void aubioOnsetDetect_dsp(t_aubioOnsetDetect *x, t_signal **sp, short *count) { // dsp_add // 1: (t_perfroutine p) perform method // 2: (long argc) number of args to your perform method // 3...: argc additional arguments, all must be sizeof(pointer) or long // these can be whatever, so you might want to include your object pointer in there // so that you have access to the info, if you need it. dsp_add(aubioOnsetDetect_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } t_int *aubioOnsetDetect_perform(t_int *w) { // DO NOT CALL post IN HERE, but you can call defer_low (not defer) // args are in a vector, sized as specified in aubioOnsetDetect_dsp method // w[0] contains &aubioOnsetDetect_perform, so we start at w[1] t_aubioOnsetDetect *x = (t_aubioOnsetDetect *)(w[1]); t_float *inL = (t_float *)(w[2]); t_float *outL = (t_float *)(w[3]); int n = (int)w[4]; float frame[n]; int j; for (j=0;j<n;j++) { frame[j] = (float) inL[j];//must cast to float or is type t_float } // aubio onset detector then processes current frame - returns bool true when new detection is output if (x->onsetDetector->processframe(frame, n)){ //if buffer full and new result is processed (buffer is 1024 with hopsize 512 - can be set to other values) outlet_float(x->medianDetectionFunctionOutlet, x->onsetDetector->medianDetectionValue); outlet_float(x->rawDetectionFunctionOutlet, x->onsetDetector->rawDetectionValue); // outlet_float(x->detectionFunctionOutlet, x->onsetDetector->peakPickedDetectionValue); outlet_float(x->detectionFunctionOutlet, x->onsetDetector->bestSlopeValue); if (x->onsetDetector->anrMedianProcessedOnsetFound) outlet_bang(x->medianBangOutlet); if (x->onsetDetector->aubioOnsetFound) outlet_bang(x->bangoutlet); }//end if new aubio onset detection result outL[j] = inL[j];//have added this so signal is "see through": outputting the input signal // you have to return the NEXT pointer in the array OR MAX WILL CRASH return w + 5; } void aubioOnsetDetect_assist(t_aubioOnsetDetect *x, void *b, long m, long a, char *s) { if (m == ASSIST_INLET) { //inlet sprintf(s, "Inlet %ld", a); switch (a){ case 0: sprintf(s, "Input signal and float (between 0.1 and 10) for aubio detection threshold."); break; case 1: sprintf(s, "no inlet 1"); break; } } else { // outlet switch (a){ case 0: sprintf(s, "Outlet %ld is the original signal.", a); break; case 1: sprintf(s, "Bang out when onset is detected."); break; case 2: sprintf(s, "Peak Picked detection function."); break; case 3: sprintf(s, "Raw aubio detection function result."); break; } } } // NOT CALLED!, we use dsp_free for a generic free function void aubioOnsetDetect_free(t_aubioOnsetDetect *x) { ; } void *aubioOnsetDetect_new(t_symbol *s, long argc, t_atom *argv) { t_aubioOnsetDetect *x = NULL; // NEW VERSION if (x = (t_aubioOnsetDetect *)object_alloc((t_class *) aubioOnsetDetect_class)) { dsp_setup((t_pxobject *)x, 1); // MSP inlets: arg is # of inlets and is REQUIRED! // use 0 if you don't need inlets x->medianDetectionFunctionOutlet = floatout(x); x->medianBangOutlet = bangout(x); x->rawDetectionFunctionOutlet = floatout(x); x->detectionFunctionOutlet = floatout(x); x->bangoutlet = bangout(x); outlet_new(x, "signal"); // signal outlet (note "signal" rather than NULL) x->threshold = 1; x->threshold2 = -70.; x->bufsize = 1024;//using fixed buffer size here. x->hopsize = x->bufsize / 2; //set this up in AubioOnsetDetector class instead x->onsetDetector = new AubioOnsetDetector(); x->onsetDetector->buffersize = x->bufsize; x->onsetDetector->hopsize = x->hopsize; x->onsetDetector->threshold = x->threshold; x->onsetDetector->threshold2 = x->threshold2; x->onsetDetector->initialise(); // if (argc == 1){//i.e. there is an argument on creation like [aubioOnsetDetect~ 0.3] t_atom my_atom = argv[0]; object_post((t_object*)x, (char*) "Aubio Onset Detect found, created by Andrew Robertson from work by Paul Brossier, Queen Mary University"); object_post((t_object*)x, (char*) "Threshold set to %f ", atom_getfloat(&my_atom)); x->threshold = atom_getfloat(&my_atom); if (x->threshold > 10) x->threshold = 10; if (x->threshold < 0.1) x->threshold = 0.1; x->onsetDetector->threshold = x->threshold; } x->useMedianOnsetDetection = true; } return (x); }