static void specCentroid_analyze(t_specCentroid *x, t_floatarg start, t_floatarg n) { int i, j, oldWindow, window, windowHalf, startSamp, endSamp, lengthSamp; t_float dividend, divisor, centroid, *windowFuncPtr; t_sample *signal_I; t_garray *a; if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) pd_error(x, "%s: no such array", x->x_arrayname->s_name); else if(!garray_getfloatwords(a, &x->x_arrayPoints, &x->x_vec)) pd_error(x, "%s: bad template for specCentroid", x->x_arrayname->s_name); else { startSamp = start; startSamp = (startSamp<0)?0:startSamp; if(n) endSamp = startSamp + n-1; else endSamp = startSamp + x->window-1; if(endSamp > x->x_arrayPoints) endSamp = x->x_arrayPoints-1; lengthSamp = endSamp-startSamp+1; if(endSamp <= startSamp) { error("bad range of samples."); return; } if(lengthSamp > x->powersOfTwo[x->powTwoArrSize-1]) { post("WARNING: specCentroid: window truncated because requested size is larger than the current max_window setting. Use the max_window method to allow larger windows."); lengthSamp = x->powersOfTwo[x->powTwoArrSize-1]; window = lengthSamp; endSamp = startSamp + window - 1; } else { i=0; while(lengthSamp > x->powersOfTwo[i]) i++; window = x->powersOfTwo[i]; } windowHalf = window * 0.5; if(x->window != window) { oldWindow = x->window; x->window = window; x->signal_R = (t_sample *)t_resizebytes(x->signal_R, oldWindow*sizeof(t_sample), x->window*sizeof(t_sample)); } if(x->windowFuncSize != lengthSamp) { x->blackman = (t_float *)t_resizebytes(x->blackman, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float)); x->cosine = (t_float *)t_resizebytes(x->cosine, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float)); x->hamming = (t_float *)t_resizebytes(x->hamming, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float)); x->hann = (t_float *)t_resizebytes(x->hann, x->windowFuncSize*sizeof(t_float), lengthSamp*sizeof(t_float)); x->windowFuncSize = lengthSamp; tIDLib_blackmanWindow(x->blackman, x->windowFuncSize); tIDLib_cosineWindow(x->cosine, x->windowFuncSize); tIDLib_hammingWindow(x->hamming, x->windowFuncSize); tIDLib_hannWindow(x->hann, x->windowFuncSize); } // create local memory signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample)); // construct analysis window for(i=0, j=startSamp; j<=endSamp; i++, j++) x->signal_R[i] = x->x_vec[j].w_float; // set window function windowFuncPtr = x->hann; //default case to get rid of compile warning switch(x->windowFunction) { case 0: break; case 1: windowFuncPtr = x->blackman; break; case 2: windowFuncPtr = x->cosine; break; case 3: windowFuncPtr = x->hamming; break; case 4: windowFuncPtr = x->hann; break; default: break; }; // if windowFunction == 0, skip the windowing (rectangular) if(x->windowFunction>0) for(i=0; i<lengthSamp; i++, windowFuncPtr++) x->signal_R[i] *= *windowFuncPtr; // then zero pad the end for(; i<window; i++) x->signal_R[i] = 0.0; mayer_realfft(window, x->signal_R); tIDLib_realfftUnpack(window, windowHalf, x->signal_R, signal_I); tIDLib_power(windowHalf+1, x->signal_R, signal_I); // power spectrum sometimes generates lower scores than magnitude. make it optional. if(!x->powerSpectrum) tIDLib_mag(windowHalf+1, x->signal_R); dividend=0; divisor=0; centroid=0; for(i=0; i<=windowHalf; i++) dividend += x->signal_R[i]*(i*(x->sr/window)); // weight by bin freq for(i=0; i<=windowHalf; i++) divisor += x->signal_R[i]; if(divisor==0) divisor = 1; // don't divide by zero centroid = dividend/divisor; outlet_float(x->x_centroid, centroid); // free local memory t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample)); } }
static void specFlatness_tilde_bang(t_specFlatness *x) { int i, j, window, windowHalf, bangSample; t_sample *signal_R, *signal_I; t_float dividend, divisor, windowHalfPlusOneRecip, flatness, *windowFuncPtr; double currentTime,timef =0.0; window = x->window; windowHalf = window*0.5; windowHalfPlusOneRecip = 1.0/(t_float)(windowHalf+1); // create local memory signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample)); signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample)); //currentTime = clock_gettimesince(x->lastDspTime); clock_getftime(&timef); currentTime = timef - x->lastDspTime; bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round if (bangSample < 0) bangSample = 0; else if ( bangSample >= x->n ) bangSample = x->n - 1; // construct analysis window using bangSample as the end of the window for(i=0, j=bangSample; i<window; i++, j++) signal_R[i] = x->signal_R[j]; // set window function windowFuncPtr = x->hann; //default case to get rid of compile warning switch(x->windowFunction) { case 0: break; case 1: windowFuncPtr = x->blackman; break; case 2: windowFuncPtr = x->cosine; break; case 3: windowFuncPtr = x->hamming; break; case 4: windowFuncPtr = x->hann; break; default: break; }; // if windowFunction == 0, skip the windowing (rectangular) if(x->windowFunction>0) for(i=0; i<window; i++, windowFuncPtr++) signal_R[i] *= *windowFuncPtr; mayer_realfft(window, signal_R); tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I); tIDLib_power(windowHalf+1, signal_R, signal_I); if(!x->powerSpectrum) tIDLib_mag(windowHalf+1, signal_R); dividend=1; // to get the product of all terms for geometric mean divisor=0; flatness=0; // geometric mean // take the nth roots first so as not to lose data. for(i=0; i<=windowHalf; i++) x->nthRoots[i] = pow(signal_R[i], windowHalfPlusOneRecip); // take the product of nth roots // what to do with values that are zero? for now, ignoring them. for(i=0; i<=windowHalf; i++) if(x->nthRoots[i] != 0) dividend *= x->nthRoots[i]; for(i=0; i<=windowHalf; i++) divisor += signal_R[i]; divisor *= windowHalfPlusOneRecip; // arithmetic mean if(divisor==0) divisor = 1; flatness = dividend/divisor; outlet_float(x->x_flatness, flatness); // free local memory t_freebytes(signal_R, window*sizeof(t_sample)); t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample)); }
static void specRolloff_tilde_bang(t_specRolloff_tilde *x) { int i, j, window, windowHalf, bangSample; t_sample *signal_R, *signal_I; t_float energy, energyTarget, rolloff, *windowFuncPtr; double currentTime; window = x->window; windowHalf = window*0.5; // create local memory signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample)); signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample)); currentTime = clock_gettimesince(x->lastDspTime); bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round if (bangSample < 0) bangSample = 0; else if ( bangSample >= x->n ) bangSample = x->n - 1; // construct analysis window using bangSample as the end of the window for(i=0, j=bangSample; i<window; i++, j++) signal_R[i] = x->signal_R[j]; // set window function windowFuncPtr = x->hann; //default case to get rid of compile warning switch(x->windowFunction) { case 0: break; case 1: windowFuncPtr = x->blackman; break; case 2: windowFuncPtr = x->cosine; break; case 3: windowFuncPtr = x->hamming; break; case 4: windowFuncPtr = x->hann; break; default: break; }; // if windowFunction == 0, skip the windowing (rectangular) if(x->windowFunction>0) for(i=0; i<window; i++, windowFuncPtr++) signal_R[i] *= *windowFuncPtr; mayer_realfft(window, signal_R); tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I); tIDLib_power(windowHalf+1, signal_R, signal_I); if(!x->powerSpectrum) tIDLib_mag(windowHalf+1, signal_R); energyTarget=0; for(i=0; i<=windowHalf; i++) energyTarget += signal_R[i]; energyTarget *= x->concentration; energy=0; i=0; while(energy <= energyTarget) { energy += signal_R[i]; i++; if(i>windowHalf) break; } i = (i==0)?1:i; rolloff = x->binFreqs[i-1]; // back up one because the last one went over... outlet_float(x->x_rolloff, rolloff); // free local memory t_freebytes(signal_R, window*sizeof(t_sample)); t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample)); }
static void barkSpec_tilde_bang(t_barkSpec *x) { int i, j, window, windowHalf, bangSample; t_atom *listOut; t_sample *signal_R, *signal_I; t_float *windowFuncPtr; double currentTime, timef = 0.0; window = x->window; windowHalf = window*0.5; // create local memory listOut = (t_atom *)t_getbytes_(x->numFilters*sizeof(t_atom)); signal_R = (t_sample *)t_getbytes_(window*sizeof(t_sample)); signal_I = (t_sample *)t_getbytes_((windowHalf+1)*sizeof(t_sample)); //currentTime = clock_gettimesince(x->lastDspTime); clock_getftime(&timef); currentTime = timef - x->lastDspTime; bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round if (bangSample < 0) bangSample = 0; else if ( bangSample >= x->n ) bangSample = x->n - 1; // construct analysis window using bangSample as the end of the window for(i=0, j=bangSample; i<window; i++, j++) signal_R[i] = x->signal_R[j]; // set window function windowFuncPtr = x->hann; //default case to get rid of compile warning switch(x->windowFunction) { case 0: break; case 1: windowFuncPtr = x->blackman; break; case 2: windowFuncPtr = x->cosine; break; case 3: windowFuncPtr = x->hamming; break; case 4: windowFuncPtr = x->hann; break; default: break; }; // if windowFunction == 0, skip the windowing (rectangular) if(x->windowFunction>0) for(i=0; i<window; i++, windowFuncPtr++) signal_R[i] *= *windowFuncPtr; mayer_realfft(window, signal_R); tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I); tIDLib_power(windowHalf+1, signal_R, signal_I); // power spectrum sometimes generates lower scores than magnitude. make it optional. if(!x->powerSpectrum) tIDLib_mag(windowHalf+1, signal_R); tIDLib_filterbankMultiply(signal_R, x->normalize, x->filterAvg, x->x_filterbank, x->numFilters); for(i=0; i<x->numFilters; i++) SETFLOAT(listOut+i, signal_R[i]); outlet_list(x->x_featureList, 0, x->numFilters, listOut); // free local memory t_freebytes_(listOut, x->numFilters*sizeof(t_atom)); t_freebytes_(signal_R, window*sizeof(t_sample)); t_freebytes_(signal_I, (windowHalf+1)*sizeof(t_sample)); }
static void specSkewness_tilde_bang(t_specSkewness_tilde *x) { int i, j, window, windowHalf, bangSample; t_sample *signal_R, *signal_I; t_float dividend, centroid, std, divisor, skewness, *windowFuncPtr; double currentTime; window = x->window; windowHalf = window*0.5; // create local memory signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample)); signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample)); currentTime = clock_gettimesince(x->lastDspTime); bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round if (bangSample < 0) bangSample = 0; else if ( bangSample >= x->n ) bangSample = x->n - 1; // construct analysis window using bangSample as the end of the window for(i=0, j=bangSample; i<window; i++, j++) signal_R[i] = x->signal_R[j]; // set window function windowFuncPtr = x->hann; //default case to get rid of compile warning switch(x->windowFunction) { case 0: break; case 1: windowFuncPtr = x->blackman; break; case 2: windowFuncPtr = x->cosine; break; case 3: windowFuncPtr = x->hamming; break; case 4: windowFuncPtr = x->hann; break; default: break; }; // if windowFunction == 0, skip the windowing (rectangular) if(x->windowFunction>0) for(i=0; i<window; i++, windowFuncPtr++) signal_R[i] *= *windowFuncPtr; mayer_realfft(window, signal_R); tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I); tIDLib_power(windowHalf+1, signal_R, signal_I); if(!x->powerSpectrum) tIDLib_mag(windowHalf+1, signal_R); dividend=0; divisor=0; centroid=0; for(i=0; i<=windowHalf; i++) { dividend += signal_R[i] * x->binFreqs[i]; // weight by bin freq divisor += signal_R[i]; } divisor = (divisor==0)?1.0:divisor; // don't divide by zero centroid = dividend/divisor; dividend=0; std=0; for(i=0; i<=windowHalf; i++) dividend += pow((x->binFreqs[i] - centroid), 2) * signal_R[i]; std = sqrt(dividend/divisor); std = pow(std, 3); std = (std==0)?1.0:std; // don't divide by zero dividend=0; skewness=0; for(i=0; i<=windowHalf; i++) dividend += pow((x->binFreqs[i] - centroid), 3) * signal_R[i]; skewness = (dividend/divisor)/std; outlet_float(x->x_skewness, skewness); // free local memory t_freebytes(signal_R, window*sizeof(t_sample)); t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample)); }
static void magSpec_tilde_bang(t_magSpec_tilde *x) { int i, j, window, windowHalf, bangSample; t_atom *listOut; t_sample *signal_R, *signal_I; t_float *windowFuncPtr; double currentTime; window = x->window; windowHalf = window*0.5; // create local memory listOut = (t_atom *)t_getbytes((windowHalf+1)*sizeof(t_atom)); signal_R = (t_sample *)t_getbytes(window*sizeof(t_sample)); signal_I = (t_sample *)t_getbytes((windowHalf+1)*sizeof(t_sample)); currentTime = clock_gettimesince(x->lastDspTime); bangSample = (int)(((currentTime/1000.0)*x->sr)+0.5); // round if (bangSample < 0) bangSample = 0; else if ( bangSample >= x->n ) bangSample = x->n - 1; // construct analysis window using bangSample as the end of the window for(i=0, j=bangSample; i<window; i++, j++) signal_R[i] = x->signal_R[j]; // set window function windowFuncPtr = x->hann; //default case to get rid of compile warning switch(x->windowFunction) { case 0: break; case 1: windowFuncPtr = x->blackman; break; case 2: windowFuncPtr = x->cosine; break; case 3: windowFuncPtr = x->hamming; break; case 4: windowFuncPtr = x->hann; break; default: break; }; // if windowFunction == 0, skip the windowing (rectangular) if(x->windowFunction>0) for(i=0; i<window; i++, windowFuncPtr++) signal_R[i] *= *windowFuncPtr; mayer_realfft(window, signal_R); tIDLib_realfftUnpack(window, windowHalf, signal_R, signal_I); tIDLib_power(windowHalf+1, signal_R, signal_I); if(!x->powerSpectrum) tIDLib_mag(windowHalf+1, signal_R); if(x->normalize) tIDLib_normal(windowHalf+1, signal_R); for(i=0; i<=windowHalf; i++) SETFLOAT(listOut+i, signal_R[i]); outlet_list(x->x_mag, 0, windowHalf+1, listOut); // free local memory t_freebytes(listOut, (windowHalf+1)*sizeof(t_atom)); t_freebytes(signal_R, window*sizeof(t_sample)); t_freebytes(signal_I, (windowHalf+1)*sizeof(t_sample)); }