From eb7f743c55770e6dfae4b0caf66a5363ba233c9e Mon Sep 17 00:00:00 2001 From: Paul Brossier Date: Fri, 2 Oct 2009 06:11:07 +0200 Subject: [PATCH] src/mathutils.{c,h}: loop over channels when possible, improve documentation, indent --- src/mathutils.c | 397 ++++++++++++++++++++++----------------- src/mathutils.h | 489 ++++++++++++++++++++++++++++++++---------------- 2 files changed, 550 insertions(+), 336 deletions(-) diff --git a/src/mathutils.c b/src/mathutils.c index b49bb0f4..66dab58e 100644 --- a/src/mathutils.c +++ b/src/mathutils.c @@ -25,7 +25,9 @@ #include "mathutils.h" #include "config.h" -fvec_t * new_aubio_window(uint_t size, aubio_window_type wintype) { +fvec_t * +new_aubio_window (uint_t size, aubio_window_type wintype) +{ // create fvec of size x 1 channel fvec_t * win = new_fvec( size, 1); smpl_t * w = win->data[0]; @@ -78,133 +80,168 @@ fvec_t * new_aubio_window(uint_t size, aubio_window_type wintype) { return win; } -smpl_t aubio_unwrap2pi(smpl_t phase) { +smpl_t +aubio_unwrap2pi (smpl_t phase) +{ /* mod(phase+pi,-2pi)+pi */ - return phase + TWO_PI * (1. + FLOOR(-(phase+PI)/TWO_PI)); + return phase + TWO_PI * (1. + FLOOR (-(phase + PI) / TWO_PI)); } -smpl_t fvec_mean(fvec_t *s) { - uint_t i,j; +smpl_t +fvec_mean (fvec_t * s) +{ + uint_t i, j; smpl_t tmp = 0.0; - for (i=0; i < s->channels; i++) - for (j=0; j < s->length; j++) + for (i = 0; i < s->channels; i++) + for (j = 0; j < s->length; j++) tmp += s->data[i][j]; - return tmp/(smpl_t)(s->length); + return tmp / (smpl_t) (s->length); } -smpl_t fvec_sum(fvec_t *s) { - uint_t i,j; +smpl_t +fvec_sum (fvec_t * s) +{ + uint_t i, j; smpl_t tmp = 0.0; - for (i=0; i < s->channels; i++) - for (j=0; j < s->length; j++) + for (i = 0; i < s->channels; i++) { + for (j = 0; j < s->length; j++) { tmp += s->data[i][j]; + } + } return tmp; } -smpl_t fvec_max(fvec_t *s) { - uint_t i,j; +smpl_t +fvec_max (fvec_t * s) +{ + uint_t i, j; smpl_t tmp = 0.0; - for (i=0; i < s->channels; i++) - for (j=0; j < s->length; j++) - tmp = (tmp > s->data[i][j])? tmp : s->data[i][j]; + for (i = 0; i < s->channels; i++) { + for (j = 0; j < s->length; j++) { + tmp = (tmp > s->data[i][j]) ? tmp : s->data[i][j]; + } + } return tmp; } -smpl_t fvec_min(fvec_t *s) { - uint_t i,j; +smpl_t +fvec_min (fvec_t * s) +{ + uint_t i, j; smpl_t tmp = s->data[0][0]; - for (i=0; i < s->channels; i++) - for (j=0; j < s->length; j++) - tmp = (tmp < s->data[i][j])? tmp : s->data[i][j] ; + for (i = 0; i < s->channels; i++) { + for (j = 0; j < s->length; j++) { + tmp = (tmp < s->data[i][j]) ? tmp : s->data[i][j]; + } + } return tmp; } -uint_t fvec_min_elem(fvec_t *s) { - uint_t i,j=0, pos=0.; +uint_t +fvec_min_elem (fvec_t * s) +{ + uint_t i, j = 0, pos = 0.; smpl_t tmp = s->data[0][0]; - for (i=0; i < s->channels; i++) - for (j=0; j < s->length; j++) { - pos = (tmp < s->data[i][j])? pos : j; - tmp = (tmp < s->data[i][j])? tmp : s->data[i][j] ; + for (i = 0; i < s->channels; i++) { + for (j = 0; j < s->length; j++) { + pos = (tmp < s->data[i][j]) ? pos : j; + tmp = (tmp < s->data[i][j]) ? tmp : s->data[i][j]; } + } return pos; } -uint_t fvec_max_elem(fvec_t *s) { - uint_t i,j=0, pos=0.; +uint_t +fvec_max_elem (fvec_t * s) +{ + uint_t i, j, pos; smpl_t tmp = 0.0; - for (i=0; i < s->channels; i++) - for (j=0; j < s->length; j++) { - pos = (tmp > s->data[i][j])? pos : j; - tmp = (tmp > s->data[i][j])? tmp : s->data[i][j] ; + for (i = 0; i < s->channels; i++) { + for (j = 0; j < s->length; j++) { + pos = (tmp > s->data[i][j]) ? pos : j; + tmp = (tmp > s->data[i][j]) ? tmp : s->data[i][j]; } + } return pos; } -void fvec_shift(fvec_t *s) { - uint_t i,j; - //smpl_t tmp = 0.0; - for (i=0; i < s->channels; i++) - for (j=0; j < s->length / 2 ; j++) { - //tmp = s->data[i][j]; - //s->data[i][j] = s->data[i][j+s->length/2]; - //s->data[i][j+s->length/2] = tmp; - ELEM_SWAP(s->data[i][j],s->data[i][j+s->length/2]); +void +fvec_shift (fvec_t * s) +{ + uint_t i, j; + for (i = 0; i < s->channels; i++) { + for (j = 0; j < s->length / 2; j++) { + ELEM_SWAP (s->data[i][j], s->data[i][j + s->length / 2]); } + } } -smpl_t fvec_local_energy(fvec_t * f) { - smpl_t locE = 0.; - uint_t i,j; - for (i=0;ichannels;i++) - for (j=0;jlength;j++) - locE+=SQR(f->data[i][j]); - return locE; +smpl_t +fvec_local_energy (fvec_t * f) +{ + smpl_t energy = 0.; + uint_t i, j; + for (i = 0; i < f->channels; i++) { + for (j = 0; j < f->length; j++) { + energy += SQR (f->data[i][j]); + } + } + return energy; } -smpl_t fvec_local_hfc(fvec_t * f) { - smpl_t locE = 0.; - uint_t i,j; - for (i=0;ichannels;i++) - for (j=0;jlength;j++) - locE+=(i+1)*f->data[i][j]; - return locE; +smpl_t +fvec_local_hfc (fvec_t * v) +{ + smpl_t hfc = 0.; + uint_t i, j; + for (i = 0; i < v->channels; i++) { + for (j = 0; j < v->length; j++) { + hfc += (i + 1) * v->data[i][j]; + } + } + return hfc; } -smpl_t fvec_alpha_norm(fvec_t * DF, smpl_t alpha) { - smpl_t tmp = 0.; - uint_t i,j; - for (i=0;ichannels;i++) - for (j=0;jlength;j++) - tmp += POW(ABS(DF->data[i][j]),alpha); - return POW(tmp/DF->length,1./alpha); +void +fvec_min_removal (fvec_t * v) +{ + smpl_t v_min = fvec_min (v); + fvec_add (v, - v_min ); } -void -fvec_min_removal (fvec_t * o) +smpl_t +fvec_alpha_norm (fvec_t * o, smpl_t alpha) { uint_t i, j; - smpl_t mini = fvec_min (o); + smpl_t tmp = 0.; for (i = 0; i < o->channels; i++) { for (j = 0; j < o->length; j++) { - o->data[i][j] -= mini; + tmp += POW (ABS (o->data[i][j]), alpha); } } + return POW (tmp / o->length, 1. / alpha); } -void fvec_alpha_normalise(fvec_t * mag, uint_t alpha) { - smpl_t alphan = 1.; - uint_t length = mag->length, i=0, j; - alphan = fvec_alpha_norm(mag,alpha); - for (j=0;jdata[i][j] /= alphan; +void +fvec_alpha_normalise (fvec_t * o, smpl_t alpha) +{ + uint_t i, j; + smpl_t norm = fvec_alpha_norm (o, alpha); + for (i = 0; i < o->channels; i++) { + for (j = 0; j < o->length; j++) { + o->data[i][j] /= norm; + } } } -void fvec_add(fvec_t * mag, smpl_t threshold) { - uint_t length = mag->length, i=0, j; - for (j=0;jdata[i][j] += threshold; +void +fvec_add (fvec_t * o, smpl_t val) +{ + uint_t i, j; + for (i = 0; i < o->channels; i++) { + for (j = 0; j < o->length; j++) { + o->data[i][j] += val; + } } } @@ -216,30 +253,32 @@ void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp, } } -smpl_t fvec_moving_thres(fvec_t * vec, fvec_t * tmpvec, - uint_t post, uint_t pre, uint_t pos) { - smpl_t * medar = (smpl_t *)tmpvec->data[0]; +smpl_t +fvec_moving_thres (fvec_t * vec, fvec_t * tmpvec, + uint_t post, uint_t pre, uint_t pos) +{ + smpl_t *medar = (smpl_t *) tmpvec->data[0]; uint_t k; - uint_t win_length = post+pre+1; - uint_t length = vec->length; + uint_t win_length = post + pre + 1; + uint_t length = vec->length; /* post part of the buffer does not exist */ - if (posdata[0][k+pos-post]; - /* the buffer is fully defined */ - } else if (pos+predata[0][k+pos-post]; - /* pre part of the buffer does not exist */ + if (pos < post + 1) { + for (k = 0; k < post + 1 - pos; k++) + medar[k] = 0.; /* 0-padding at the beginning */ + for (k = post + 1 - pos; k < win_length; k++) + medar[k] = vec->data[0][k + pos - post]; + /* the buffer is fully defined */ + } else if (pos + pre < length) { + for (k = 0; k < win_length; k++) + medar[k] = vec->data[0][k + pos - post]; + /* pre part of the buffer does not exist */ } else { - for (k=0;kdata[0][k+pos-post]; - for (k=length-pos+post;kdata[0][k + pos - post]; + for (k = length - pos + post; k < win_length; k++) + medar[k] = 0.; /* 0-padding at the end */ } - return fvec_median(tmpvec); + return fvec_median (tmpvec); } smpl_t fvec_median(fvec_t * input) { @@ -300,16 +339,11 @@ smpl_t fvec_quadint(fvec_t * x,uint_t pos, uint_t span) { if (x0 == pos) return (x->data[0][pos] <= x->data[0][x2]) ? pos : x2; if (x2 == pos) return (x->data[0][pos] <= x->data[0][x0]) ? pos : x0; s0 = x->data[0][x0]; - s1 = x->data[0][pos] ; + s1 = x->data[0][pos]; s2 = x->data[0][x2]; return pos + 0.5 * (s2 - s0 ) / (s2 - 2.* s1 + s0); } -smpl_t aubio_quadfrac(smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf) { - smpl_t tmp = s0 + (pf/2.) * (pf * ( s0 - 2.*s1 + s2 ) - 3.*s0 + 4.*s1 - s2); - return tmp; -} - uint_t fvec_peakpick(fvec_t * onset, uint_t pos) { uint_t i=0, tmp=0; /*for (i=0;ichannels;i++)*/ @@ -319,118 +353,137 @@ uint_t fvec_peakpick(fvec_t * onset, uint_t pos) { return tmp; } -smpl_t aubio_freqtomidi(smpl_t freq) { +smpl_t +aubio_quadfrac (smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf) +{ + smpl_t tmp = + s0 + (pf / 2.) * (pf * (s0 - 2. * s1 + s2) - 3. * s0 + 4. * s1 - s2); + return tmp; +} + +smpl_t +aubio_freqtomidi (smpl_t freq) +{ /* log(freq/A-2)/log(2) */ - smpl_t midi = freq/6.875; - midi = LOG(midi)/0.69314718055995; + smpl_t midi = freq / 6.875; + midi = LOG (midi) / 0.69314718055995; midi *= 12; midi -= 3; return midi; } -smpl_t aubio_miditofreq(smpl_t midi) { - smpl_t freq = (midi+3.)/12.; - freq = EXP(freq*0.69314718055995); +smpl_t +aubio_miditofreq (smpl_t midi) +{ + smpl_t freq = (midi + 3.) / 12.; + freq = EXP (freq * 0.69314718055995); freq *= 6.875; return freq; } -smpl_t aubio_bintofreq(smpl_t bin, smpl_t samplerate, smpl_t fftsize) { - smpl_t freq = samplerate/fftsize; - return freq*bin; +smpl_t +aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize) +{ + smpl_t freq = samplerate / fftsize; + return freq * bin; } -smpl_t aubio_bintomidi(smpl_t bin, smpl_t samplerate, smpl_t fftsize) { - smpl_t midi = aubio_bintofreq(bin,samplerate,fftsize); - return aubio_freqtomidi(midi); +smpl_t +aubio_bintomidi (smpl_t bin, smpl_t samplerate, smpl_t fftsize) +{ + smpl_t midi = aubio_bintofreq (bin, samplerate, fftsize); + return aubio_freqtomidi (midi); } -smpl_t aubio_freqtobin(smpl_t freq, smpl_t samplerate, smpl_t fftsize) { - smpl_t bin = fftsize/samplerate; - return freq*bin; +smpl_t +aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize) +{ + smpl_t bin = fftsize / samplerate; + return freq * bin; } -smpl_t aubio_miditobin(smpl_t midi, smpl_t samplerate, smpl_t fftsize) { - smpl_t freq = aubio_miditofreq(midi); - return aubio_freqtobin(freq,samplerate,fftsize); +smpl_t +aubio_miditobin (smpl_t midi, smpl_t samplerate, smpl_t fftsize) +{ + smpl_t freq = aubio_miditofreq (midi); + return aubio_freqtobin (freq, samplerate, fftsize); } -/** returns 1 if wassilence is 0 and RMS(ibuf)length;j++) { - loudness += SQR(ibuf->data[i][j]); - } - loudness = SQRT(loudness); - loudness /= (smpl_t)ibuf->length; - loudness = LIN2DB(loudness); - - return (loudness < threshold); +smpl_t +aubio_db_spl (fvec_t * o) +{ + smpl_t val = SQRT (fvec_local_energy (o)); + val /= (smpl_t) o->length; + return LIN2DB (val); } -/** returns level log(RMS(ibuf)) if < threshold, 1 otherwise - * \bug mono - */ -smpl_t aubio_level_detection(fvec_t * ibuf, smpl_t threshold) { - smpl_t loudness = 0; - uint_t i=0,j; - for (j=0;jlength;j++) { - loudness += SQR(ibuf->data[i][j]); - } - loudness = SQRT(loudness); - loudness /= (smpl_t)ibuf->length; - loudness = LIN2DB(loudness); +uint_t +aubio_silence_detection (fvec_t * o, smpl_t threshold) +{ + return (aubio_db_spl (o) < threshold); +} - if (loudness < threshold) +smpl_t +aubio_level_detection (fvec_t * o, smpl_t threshold) +{ + smpl_t db_spl = aubio_db_spl (o); + if (db_spl < threshold) { return 1.; - else - return loudness; + } else { + return db_spl; + } } -smpl_t aubio_zero_crossing_rate(fvec_t * input) { - uint_t i=0,j; +smpl_t +aubio_zero_crossing_rate (fvec_t * input) +{ + uint_t i = 0, j; uint_t zcr = 0; - for ( j = 1; j < input->length; j++ ) { + for (j = 1; j < input->length; j++) { // previous was strictly negative - if( input->data[i][j-1] < 0. ) { + if (input->data[i][j - 1] < 0.) { // current is positive or null - if ( input->data[i][j] >= 0. ) { + if (input->data[i][j] >= 0.) { zcr += 1; } - // previous was positive or null + // previous was positive or null } else { // current is strictly negative - if ( input->data[i][j] < 0. ) { + if (input->data[i][j] < 0.) { zcr += 1; } } } - return zcr/(smpl_t)input->length; + return zcr / (smpl_t) input->length; } -void aubio_autocorr(fvec_t * input, fvec_t * output) { - uint_t i = 0, j = 0, length = input->length; - smpl_t * data = input->data[0]; - smpl_t * acf = output->data[0]; - smpl_t tmp =0.; - for(i=0;ilength; + smpl_t *data, *acf; + smpl_t tmp = 0; + for (k = 0; k < input->channels; k++) { + data = input->data[k]; + acf = output->data[k]; + for (i = 0; i < length; i++) { + tmp = 0.; + for (j = i; j < length; j++) { + tmp += data[j - i] * data[j]; + } + acf[i] = tmp / (smpl_t) (length - i); } - acf[i] = tmp /(smpl_t)(length-i); - tmp = 0.0; } } -void aubio_cleanup(void) { +void +aubio_cleanup (void) +{ #if HAVE_FFTW3 - fftw_cleanup(); + fftw_cleanup (); #else #if HAVE_FFTW3F - fftwf_cleanup(); + fftwf_cleanup (); #endif #endif } diff --git a/src/mathutils.h b/src/mathutils.h index f01bee12..d71cf77f 100644 --- a/src/mathutils.h +++ b/src/mathutils.h @@ -20,11 +20,6 @@ /** @file * various math functions - * - * \todo multichannel (each function should return -or set- an array sized to - * the number of channel in the input vector) - * - * \todo appropriate switches depending on types.h content */ #ifndef MATHUTILS_H @@ -35,184 +30,350 @@ extern "C" { #endif /** Window types - * - * inspired from - * - * - dafx : http://profs.sci.univr.it/%7Edafx/Final-Papers/ps/Bernardini.ps.gz - * - freqtweak : http://freqtweak.sf.net/ - * - extace : http://extace.sf.net/ - */ -typedef enum { - aubio_win_rectangle, - aubio_win_hamming, - aubio_win_hanning, - aubio_win_hanningz, - aubio_win_blackman, - aubio_win_blackman_harris, - aubio_win_gaussian, - aubio_win_welch, - aubio_win_parzen + + References: + + - Window +function on Wikipedia + - Amalia de Götzen, Nicolas Bernardini, and Daniel Arfib. Traditional (?) +implementations of a phase vocoder: the tricks of the trade. In Proceedings of +the International Conference on Digital Audio Effects (DAFx-00), pages 37–44, +Uni- versity of Verona, Italy, 2000. + ( + ps.gz) + +*/ +typedef enum +{ + aubio_win_rectangle, + aubio_win_hamming, + aubio_win_hanning, + aubio_win_hanningz, + aubio_win_blackman, + aubio_win_blackman_harris, + aubio_win_gaussian, + aubio_win_welch, + aubio_win_parzen } aubio_window_type; /** create window */ -fvec_t * new_aubio_window(uint_t size, aubio_window_type wintype); +fvec_t *new_aubio_window (uint_t size, aubio_window_type wintype); -/** principal argument - * - * mod(phase+PI,-TWO_PI)+PI - */ +/** compute the principal argument + + This function maps the input phase to its corresponding value wrapped in the +range \f$ [-\pi, \pi] \f$. + + \param phase unwrapped phase to map to the unit circle + + \return equivalent phase wrapped to the unit circle + +*/ smpl_t aubio_unwrap2pi (smpl_t phase); -/** calculates the mean of a vector - * - * \bug mono - */ -smpl_t fvec_mean(fvec_t *s); -/** returns the max of a vector - * - * \bug mono - */ -smpl_t fvec_max(fvec_t *s); -/** returns the min of a vector - * - * \bug mono - */ -smpl_t fvec_min(fvec_t *s); -/** returns the index of the min of a vector - * - * \bug mono - */ -uint_t fvec_min_elem(fvec_t *s); -/** returns the index of the max of a vector - * - * \bug mono - */ -uint_t fvec_max_elem(fvec_t *s); -/** implement 'fftshift' like function - * - * a[0]...,a[n/2],a[n/2+1],...a[n] - * - * becomes - * - * a[n/2+1],...a[n],a[0]...,a[n/2] - */ -void fvec_shift(fvec_t *s); -/** returns sum */ -smpl_t fvec_sum(fvec_t *s); +/** compute the mean of a vector -/** returns energy - * - * \bug mono - */ -smpl_t fvec_local_energy(fvec_t * f); -/** returns High Frequency Energy Content - * - * \bug mono */ -smpl_t fvec_local_hfc(fvec_t * f); -/** return alpha norm. - * - * alpha=2 means normalise variance. - * alpha=1 means normalise abs value. - * as alpha goes large, tends to normalisation - * by max value. - * - * \bug should not use POW :( - */ -smpl_t fvec_alpha_norm(fvec_t * DF, smpl_t alpha); -/** min removal */ -void fvec_min_removal(fvec_t * mag); -/** alpha normalisation */ -void fvec_alpha_normalise(fvec_t * mag, uint_t alpha); -/** add a constant to all members of a vector */ -void fvec_add(fvec_t * mag, smpl_t threshold); - -/** compute adaptive threshold of input vector */ -void fvec_adapt_thres(fvec_t * vec, fvec_t * tmp, - uint_t win_post, uint_t win_pre); -/** adaptative thresholding - * - * y=fn_thresh(fn,x,post,pre) - * compute adaptive threshold at each time - * fn : a function name or pointer, eg 'median' - * x: signal vector - * post: window length, causal part - * pre: window length, anti-causal part - * Returns: - * y: signal the same length as x - * - * Formerly median_thresh, used compute median over a - * window of post+pre+1 samples, but now works with any - * function that takes a vector or matrix and returns a - * 'representative' value for each column, eg - * medians=fn_thresh(median,x,8,8) - * minima=fn_thresh(min,x,8,8) - * see SPARMS for explanation of post and pre - */ -smpl_t fvec_moving_thres(fvec_t * vec, fvec_t * tmp, - uint_t win_post, uint_t win_pre, uint_t win_pos); - -/** returns the median of the vector - * - * This Quickselect routine is based on the algorithm described in - * "Numerical recipes in C", Second Edition, - * Cambridge University Press, 1992, Section 8.5, ISBN 0-521-43108-5 - * - * This code by Nicolas Devillard - 1998. Public domain, - * available at http://ndevilla.free.fr/median/median/ - */ -smpl_t fvec_median(fvec_t * input); + \param s vector to compute norm from + + \return the mean of v + +*/ +smpl_t fvec_mean (fvec_t * s); + +/** find the max of a vector + + \param s vector to get the max from + + \return the value of the minimum of v + +*/ +smpl_t fvec_max (fvec_t * s); + +/** find the min of a vector + + \param s vector to get the min from + + \return the value of the maximum of v + +*/ +smpl_t fvec_min (fvec_t * s); + +/** find the index of the min of a vector + + \param s vector to get the index from + + \return the index of the minimum element of v + +*/ +uint_t fvec_min_elem (fvec_t * s); + +/** find the index of the max of a vector + + \param s vector to get the index from + + \return the index of the maximum element of v + +*/ +uint_t fvec_max_elem (fvec_t * s); + +/** swap the left and right halves of a vector + + This function swaps the left part of the signal with the right part of the +signal. Therefore + + \f$ a[0], a[1], ..., a[\frac{N}{2}], a[\frac{N}{2}+1], ..., a[N-1], a[N] \f$ + + becomes + + \f$ a[\frac{N}{2}+1], ..., a[N-1], a[N], a[0], a[1], ..., a[\frac{N}{2}] \f$ + + This operation, known as 'fftshift' in the Matlab Signal Processing Toolbox, +can be used before computing the FFT to simplify the phase relationship of the +resulting spectrum. See Amalia de Götzen's paper referred to above. + +*/ +void fvec_shift (fvec_t * v); + +/** compute the sum of all elements of a vector + + \param v vector to compute the sum of + + \return the sum of v + +*/ +smpl_t fvec_sum (fvec_t * v); + +/** compute the energy of a vector + + This function compute the sum of the squared elements of a vector. + + \param v vector to get the energy from + + \return the energy of v + +*/ +smpl_t fvec_local_energy (fvec_t * v); + +/** compute the High Frequency Content of a vector + + The High Frequency Content is defined as \f$ \sum_0^{N-1} (k+1) v[k] \f$. + + \param v vector to get the energy from + + \return the HFC of v + +*/ +smpl_t fvec_local_hfc (fvec_t * v); + +/** computes the p-norm of a vector + + Computes the p-norm of a vector for \f$ p = \alpha \f$ + + \f$ L^p = ||x||_p = (|x_1|^p + |x_2|^p + ... + |x_n|^p ) ^ \frac{1}{p} \f$ + + If p = 1, the result is the Manhattan distance. + + If p = 2, the result is the Euclidean distance. + + As p tends towards large values, \f$ L^p \f$ tends towards the maximum of the +input vector. + + References: + + - \f$L^p\f$ space on + Wikipedia + + \param v vector to compute norm from + \param p order of the computed norm + + \return the p-norm of v + +*/ +smpl_t fvec_alpha_norm (fvec_t * v, smpl_t p); + +/** alpha normalisation + + This function divides all elements of a vector by the p-norm as computed by +fvec_alpha_norm(). + + \param v vector to compute norm from + \param p order of the computed norm + +*/ +void fvec_alpha_normalise (fvec_t * v, smpl_t p); + +/** add a constant to each elements of a vector + + \param v vector to add constant to + \param c constant to add to v + +*/ +void fvec_add (fvec_t * v, smpl_t c); + +/** remove the minimum value of the vector to each elements + + \param v vector to remove minimum from + +*/ +void fvec_min_removal (fvec_t * v); + +/** compute moving median theshold of a vector + + This function computes the moving median threshold value of at the given +position of a vector, taking the median amongs post elements before and up to +pre elements after pos. + + \param v input vector + \param tmp temporary vector of length post+1+pre + \param post length of causal part to take before pos + \param pre length of anti-causal part to take after pos + \param pos index to compute threshold for + + \return moving median threshold value + +*/ +smpl_t fvec_moving_thres (fvec_t * v, fvec_t * tmp, uint_t post, uint_t pre, + uint_t pos); + +/** apply adaptive threshold to a vector + + For each points at position p of an input vector, this function remove the +moving median threshold computed at p. + + \param v input vector + \param tmp temporary vector of length post+1+pre + \param post length of causal part to take before pos + \param pre length of anti-causal part to take after pos + +*/ +void fvec_adapt_thres (fvec_t * v, fvec_t * tmp, uint_t post, uint_t pre); + +/** returns the median of a vector + + The QuickSelect routine is based on the algorithm described in "Numerical +recipes in C", Second Edition, Cambridge University Press, 1992, Section 8.5, +ISBN 0-521-43108-5 + + This implementation of the QuickSelect routine is based on Nicolas +Devillard's implementation, available at http://ndevilla.free.fr/median/median/ +and in the Public Domain. + + \param v vector to get median from + + \return the median of v + +*/ +smpl_t fvec_median (fvec_t * v); /** finds exact peak index by quadratic interpolation*/ -smpl_t fvec_quadint(fvec_t * x, uint_t pos, uint_t span); +smpl_t fvec_quadint (fvec_t * x, uint_t pos, uint_t span); /** Quadratic interpolation using Lagrange polynomial. - * - * inspired from ``Comparison of interpolation algorithms in real-time sound - * processing'', Vladimir Arnost, - * - * estimate = s0 + (pf/2.)*((pf-3.)*s0-2.*(pf-2.)*s1+(pf-1.)*s2); - * where - * \param s0,s1,s2 are 3 known points on the curve, - * \param pf is the floating point index [0;2] - */ -smpl_t aubio_quadfrac(smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf); + + Inspired from ``Comparison of interpolation algorithms in real-time sound +processing'', Vladimir Arnost, + + \param s0,s1,s2 are 3 consecutive samples of a curve + \param pf is the floating point index [0;2] + + \return s0 + (pf/2.)*((pf-3.)*s0-2.*(pf-2.)*s1+(pf-1.)*s2); + +*/ +smpl_t aubio_quadfrac (smpl_t s0, smpl_t s1, smpl_t s2, smpl_t pf); -/** returns 1 if X1 is a peak and positive */ -uint_t fvec_peakpick(fvec_t * input, uint_t pos); +/** return 1 if v[p] is a peak and positive, 0 otherwise + + This function returns 1 if a peak is found at index p in the vector v. The +peak is defined as follows: + + - v[p] is positive + - v[p-1] < v[p] + - v[p] > v[p+1] + + \param v input vector + \param p position of supposed for peak + + \return 1 if a peak is found, 0 otherwise + +*/ +uint_t fvec_peakpick (fvec_t * v, uint_t p); /** convert frequency bin to midi value */ -smpl_t aubio_bintomidi(smpl_t bin, smpl_t samplerate, smpl_t fftsize); +smpl_t aubio_bintomidi (smpl_t bin, smpl_t samplerate, smpl_t fftsize); + /** convert midi value to frequency bin */ -smpl_t aubio_miditobin(smpl_t midi, smpl_t samplerate, smpl_t fftsize); +smpl_t aubio_miditobin (smpl_t midi, smpl_t samplerate, smpl_t fftsize); + /** convert frequency bin to frequency (Hz) */ -smpl_t aubio_bintofreq(smpl_t bin, smpl_t samplerate, smpl_t fftsize); +smpl_t aubio_bintofreq (smpl_t bin, smpl_t samplerate, smpl_t fftsize); + /** convert frequency (Hz) to frequency bin */ -smpl_t aubio_freqtobin(smpl_t freq, smpl_t samplerate, smpl_t fftsize); +smpl_t aubio_freqtobin (smpl_t freq, smpl_t samplerate, smpl_t fftsize); + /** convert frequency (Hz) to midi value (0-128) */ -smpl_t aubio_freqtomidi(smpl_t freq); +smpl_t aubio_freqtomidi (smpl_t freq); + /** convert midi value (0-128) to frequency (Hz) */ -smpl_t aubio_miditofreq(smpl_t midi); - -/** check if current buffer level is under a given threshold */ -uint_t aubio_silence_detection(fvec_t * ibuf, smpl_t threshold); -/** get the current buffer level */ -smpl_t aubio_level_detection(fvec_t * ibuf, smpl_t threshold); -/** - * calculate normalised autocorrelation function - */ -void aubio_autocorr(fvec_t * input, fvec_t * output); -/** - * zero-crossing rate (number of zero cross per sample) - */ -smpl_t aubio_zero_crossing_rate(fvec_t * input); -/** - * clean up cached memory at the end of program - * - * use this function at the end of programs to purge all - * cached memory. so far this function is only used to clean - * fftw cache. - */ -void aubio_cleanup(void); +smpl_t aubio_miditofreq (smpl_t midi); + +/** compute sound pressure level (SPL) in dB + + This quantity is often wrongly called 'loudness'. + + \param v vector to compute dB SPL from + + \return level of v in dB SPL + +*/ +smpl_t aubio_db_spl (fvec_t * v); + +/** check if buffer level in dB SPL is under a given threshold + + \param v vector to get level from + \param threshold threshold in dB SPL + + \return 0 if level is under the given threshold, 1 otherwise + +*/ +uint_t aubio_silence_detection (fvec_t * v, smpl_t threshold); + +/** get buffer level if level >= threshold, 1. otherwise + + \param v vector to get level from + \param threshold threshold in dB SPL + + \return level in dB SPL if level >= threshold, 1. otherwise + +*/ +smpl_t aubio_level_detection (fvec_t * v, smpl_t threshold); + +/** compute normalised autocorrelation function + + \param input vector to compute autocorrelation from + \param output vector to store autocorrelation function to + +*/ +void aubio_autocorr (fvec_t * input, fvec_t * output); + +/** zero-crossing rate (ZCR) + + The zero-crossing rate is the number of times a signal changes sign, + divided by the length of this signal. + + \param v vector to compute ZCR from + + \return zero-crossing rate of v + +*/ +smpl_t aubio_zero_crossing_rate (fvec_t * v); + +/** clean up cached memory at the end of program + + This function should be used at the end of programs to purge all cached + memory. So far it is only useful to clean FFTW's cache. + +*/ +void aubio_cleanup (void); #ifdef __cplusplus } -- 2.26.2