예제 #1
0
static void sliceplay_set(t_sliceplay *x)
{
	t_garray *array;
	int arraysize, logloopsize;
	
	if(!(array = (t_garray *)pd_findbyclass(x->arrayname, garray_class)))
	{
		if (x->arrayname->s_name) pd_error(x, "sliceplay~: %s: no such array", 
            x->arrayname->s_name);
		x->arraypointer = 0;
	}
	
	else if (!garray_getfloatwords(array, &arraysize, &x->arraypointer))
	{
		pd_error(x, "%s: bad template for sliceplay~", x->arrayname->s_name);
		x->arraypointer = 0;
	}
	
	else
	{
		logloopsize = ilog2(arraysize-3);	// arraysize must be at least loopsize + 1 sample
		x->loopsize = 1<<logloopsize;		// loopsize is rounded to a power of two
		x->loopmask = x->loopsize - 1;		// bitwise-and mask for loopsize
		garray_usedindsp(array);
	}
}
예제 #2
0
파일: cybuf.c 프로젝트: porres/pd-cyclone
/* on failure *bufsize is not modified */
t_word *cybuf_get(t_cybuf *c, t_symbol * name, int *bufsize, int indsp, int complain){
//in dsp = used in dsp, 
  
    if (name && name != &s_){
	t_garray *ap = (t_garray *)pd_findbyclass(name, garray_class);
	if (ap){
	    int bufsz;
	    t_word *vec;
	    if (garray_getfloatwords(ap, &bufsz, &vec)){
   	        //c->c_len = garray_npoints(ap);
		if (indsp) garray_usedindsp(ap);
		if (bufsize) *bufsize = bufsz;
		return (vec);
	    }
	     else pd_error(c->c_owner,  /* always complain */
			"bad template of array '%s'", name->s_name);
        }
	else{
            if(complain){
	        pd_error(c->c_owner, "no such array '%s'", name->s_name);
            };
	};
    }
    return (0);
}
예제 #3
0
static void tabosc4_tilde_set(t_tabosc4_tilde *x, t_symbol *s)
{
    t_garray *a;
    int npoints, pointsinarray;

    x->x_arrayname = s;
    if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
    {
        if (*s->s_name)
            pd_error(x, "tabosc4~: %s: no such array", x->x_arrayname->s_name);
        x->x_vec = 0;
    }
    else if (!garray_getfloatwords(a, &pointsinarray, &x->x_vec))
    {
        pd_error(x, "%s: bad template for tabosc4~", x->x_arrayname->s_name);
        x->x_vec = 0;
    }
    else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3)))
    {
        pd_error(x, "%s: number of points (%d) not a power of 2 plus three",
            x->x_arrayname->s_name, pointsinarray);
        x->x_vec = 0;
        garray_usedindsp(a);
    }
    else
    {
        x->x_fnpoints = npoints;
        x->x_finvnpoints = 1./npoints;
        garray_usedindsp(a);
    }
}
예제 #4
0
파일: bark.c 프로젝트: avilleret/timbreID
static void bark_print(t_bark *x)
{
	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_array_points, &x->x_vec))
    	pd_error(x, "%s: bad template for bark", x->x_arrayname->s_name);
	else
		post("total frames: %i", (int)floor((x->x_array_points - x->window)/x->hop));

	post("window size: %i", (int)x->window);
	post("hop: %i", x->hop);
	post("Bark spacing: %0.2f", x->barkSpacing);
	post("no. of filters: %i", x->numFilters);
	post("bin range: %i through %i (inclusive)", x->loBin, x->hiBin);
	post("low thresh: %0.2f, high thresh: %0.2f", x->loThresh, x->hiThresh);
	post("minvel: %f", x->minvel);
	post("mask periods: %i, mask decay: %0.2f", x->maskPeriods, x->maskDecay);
	post("debounce time: %0.2f", x->debounceTime);
	post("normalization: %i", x->normalize);
	post("filter averaging: %i", x->filterAvg);
	post("power spectrum: %i", x->powerSpectrum);
	post("loudness weights: %i", x->useWeights);
	post("spew mode: %i", x->spew);
	post("debug mode: %i", x->debug);
}
예제 #5
0
파일: trento.c 프로젝트: amurtet/pd-dis
int clear(t_trento *x)
{
  t_garray *a;
  t_symbol *b_name;
  t_word *b_samples;
  int b_frames;
  x->b_valid = 0;
  b_name = x->b_name;
  int i;

  if (!(a = (t_garray *)pd_findbyclass(b_name,garray_class))) {
    if (b_name->s_name)
      pd_error(x,"trento: %s: no such array",b_name->s_name);
    return x->b_valid;
  }

  if (!garray_getfloatwords(a, &b_frames, &b_samples)) {
    pd_error(x, "trento: bad array for %s", b_name->s_name);
    return x->b_valid;
  }
  else {
    for (i=0;i<b_frames;i++)
      b_samples[i].w_float = 0.f;
    x->b_valid = 1;
  }
  return x->b_valid;
}
예제 #6
0
파일: trento.c 프로젝트: amurtet/pd-dis
int attach_array(t_trento *x)
{
  t_garray *a;
  t_symbol *b_name;
  t_word *b_samples;
  int b_frames;
  x->b_valid = 0;
  b_name = x->b_name;

  if (!(a = (t_garray *)pd_findbyclass(b_name,garray_class))) {
    if (b_name->s_name)
      pd_error(x,"trento: %s: no such array",b_name->s_name);
    return x->b_valid;
  }

  if (!garray_getfloatwords(a, &b_frames, &b_samples)) {
    pd_error(x, "trento: bad array for %s", b_name->s_name);
    return x->b_valid;
  }
  else {
    x->b_valid = 1;
    x->b_frames = b_frames;
    x->b_samples = b_samples;
    x->buffy = a;
  }
  return x->b_valid;
}
예제 #7
0
파일: trento.c 프로젝트: amurtet/pd-dis
int init(t_trento *x)
{
  t_garray *a;
  t_symbol *b_name;
  t_word *b_samples;
  int b_frames;
  x->b_valid = 0;
  b_name = x->b_name;
  x->loadcomplete = 1;
  x->graincomplete = 1;
  x->sr = sys_getsr();
  if(x->sr <= 0)
    x->sr = 44100;
  int i;
  x->seed = time(NULL);
  srand(x->seed);

  if (!(a = (t_garray *)pd_findbyclass(b_name,garray_class))) {
    if (b_name->s_name)
      pd_error(x,"trento: %s: no such array",b_name->s_name);
    return x->b_valid;
  }

  if (!garray_getfloatwords(a, &b_frames, &b_samples)) {
    pd_error(x, "trento: bad array for %s", b_name->s_name);
    return x->b_valid;
  }
  else {
    for (i=0;i<b_frames;i++)
      b_samples[i].w_float = 0.f;
    x->b_valid = 1;
  }
  return x->b_valid;
}
예제 #8
0
static void tabread4_float(t_tabread4 *x, t_float f)
{
    t_garray *a;
    int npoints;
    t_word *vec;

    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, &npoints, &vec))
        pd_error(x, "%s: bad template for tabread4", x->x_arrayname->s_name);
    else if (npoints < 4)
        outlet_float(x->x_obj.ob_outlet, 0);
    else if (f <= 1)
        outlet_float(x->x_obj.ob_outlet, vec[1].w_float);
    else if (f >= npoints - 2)
        outlet_float(x->x_obj.ob_outlet, vec[npoints - 2].w_float);
    else
    {
        int n = f;
        float a, b, c, d, cminusb, frac;
        t_word *wp;
        if (n >= npoints - 2)
            n = npoints - 3;
        wp = vec + n;
        frac = f - n;
        a = wp[-1].w_float;
        b = wp[0].w_float;
        c = wp[1].w_float;
        d = wp[2].w_float;
        cminusb = c-b;
        outlet_float(x->x_obj.ob_outlet, b + frac * (
            cminusb - 0.1666667f * (1.-frac) * (
                (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b))));
    }
}
예제 #9
0
// analyze the whole damn array
static void specCentroid_bang(t_specCentroid *x)
{
	int window, startSamp, lengthSamp;
	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 = 0;
	lengthSamp = x->x_arrayPoints;

	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. Sizes of more than 131072 may produce unreliable results.");
		lengthSamp = x->powersOfTwo[x->powTwoArrSize-1];
		window = lengthSamp;
	}

	specCentroid_analyze(x, startSamp, lengthSamp);

	}
}
예제 #10
0
static void *specCentroid_new(t_symbol *s)
{
    t_specCentroid *x = (t_specCentroid *)pd_new(specCentroid_class);
	int i;
	t_garray *a;

	x->x_centroid = outlet_new(&x->x_obj, &s_float);
	
	if(s)
	{
		x->x_arrayname = s;

	    if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
	        ;
	    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
		error("specCentroid: no array specified.");

	x->sr = 44100.0;
	x->window = 1; // should be a bogus size initially to force the proper resizes when a real _analyze request comes through
	x->windowFuncSize = 1;
	x->windowFunction = 4; // 4 is hann window
	x->powerSpectrum = 0; // choose mag (0) or power (1) spec in the specCentroid computation

	x->maxWindowSize = MAXWINDOWSIZE; // this seems to be the maximum size allowable by mayer_realfft();
	x->powersOfTwo = (int *)t_getbytes(sizeof(int));

	x->powersOfTwo[0] = 64; // must have at least this large of a window

	i=1;
	while(x->powersOfTwo[i-1] < x->maxWindowSize)
	{
		x->powersOfTwo = (int *)t_resizebytes(x->powersOfTwo, i*sizeof(int), (i+1)*sizeof(int));
		x->powersOfTwo[i] = pow(2, i+6); // +6 because we're starting at 2**6
		i++;
	}

	x->powTwoArrSize = i;

	x->signal_R = (t_sample *)t_getbytes(x->window*sizeof(t_sample));

	for(i=0; i<x->window; i++)
		x->signal_R[i] = 0.0;

  	x->blackman = (t_float *)t_getbytes(x->windowFuncSize*sizeof(t_float));
  	x->cosine = (t_float *)t_getbytes(x->windowFuncSize*sizeof(t_float));
  	x->hamming = (t_float *)t_getbytes(x->windowFuncSize*sizeof(t_float));
  	x->hann = (t_float *)t_getbytes(x->windowFuncSize*sizeof(t_float));

 	// initialize signal windowing functions
	tIDLib_blackmanWindow(x->blackman, x->windowFuncSize);
	tIDLib_cosineWindow(x->cosine, x->windowFuncSize);
	tIDLib_hammingWindow(x->hamming, x->windowFuncSize);
	tIDLib_hannWindow(x->hann, x->windowFuncSize);

    return (x);
}
예제 #11
0
void fofsynth_usearray(t_symbol* s,int* points,t_word** vec)
{
     t_garray *a;
     if (!(a = (t_garray *)pd_findbyclass(s, garray_class))) 
	  error("%s: no such array", s->s_name);
     else if (!garray_getfloatwords(a,points,vec))
	  error("%s: bad template for fof~", s->s_name);
     else
	  garray_usedindsp(a); 
}
예제 #12
0
void granulesf_setbuf(t_granulesf *x, t_symbol *wavename, t_symbol *windowname)
{
    t_garray *a;
    int frames;
    
    x->hosed = 0;
    x->wavebuf->b_frames = 0;
    x->windowbuf->b_frames = 0;
    x->wavebuf->b_nchans = 1;//unused, should kill
    x->windowbuf->b_nchans = 1;  //unused, should kill
    x->b_nchans = 1;
    
    /* load up sample array */
    if (!(a = (t_garray *)pd_findbyclass(wavename, garray_class))) {
        if (*wavename->s_name) pd_error(x, "granulesf~: %s: no such array", wavename->s_name);
        x->hosed = 1;
    }
    else if (!garray_getfloatwords(a, &frames, &x->wavebuf->b_samples)) {
        pd_error(x, "%s: bad template for granulesf~", wavename->s_name);
        x->hosed = 1;
    }
    else  {
        x->wavebuf->b_frames = frames;
        x->b_nchans = 1; // Pd buffers are always mono (so far)
        garray_usedindsp(a);
    }
    
    /* load up envelope array*/
    if (!(a = (t_garray *)pd_findbyclass(windowname, garray_class))) {
        if (*wavename->s_name) pd_error(x, "granulesf~: %s: no such array", windowname->s_name);
        x->hosed = 1;
    }
    else if (!garray_getfloatwords(a, &frames, &x->windowbuf->b_samples)) {
        pd_error(x, "%s: bad template for granulesf~", windowname->s_name);
        x->hosed = 1;
    }
    else  {
        x->windowbuf->b_frames = frames;
        garray_usedindsp(a);
    }
    
    x->maxskip = x->wavebuf->b_frames - 1;
}
예제 #13
0
void annealing_bang(t_annealing *x)
{
    t_garray *a;
    int npoints;
    t_word *vec;
    
    if (!(a = (t_garray *)pd_findbyclass(x->arrayname, garray_class)))
        pd_error(x, "%s: no such array", x->arrayname->s_name);
    else if (!garray_getfloatwords(a, &npoints, &vec))
        pd_error(x, "%s: bad template for annealing", x->arrayname->s_name);
    else
    {
        if (x->pIndex == -1)
            x->pIndex = (int)(arc4random() % npoints);
        if (x->pIndex < 0)
            x->pIndex = 0;
        else if (x->pIndex >= npoints)
            x->pIndex = npoints - 1;
        
        x->parent = vec[x->pIndex].w_float;
        
        int cIndex = (int)(arc4random() % npoints); // this uses random index
        
        // this uses a random index surrounding the current index
        // int cIndex = getNewIndex(x->pIndex, npoints);
        float child = vec[cIndex].w_float;
        float diff = child - x->parent;
        if (diff > 0) {
            x->pIndex = cIndex;
            x->parent = child;
        } else {
            if (x->temp < 0)
                x->temp = 1;
            float p = pow(M_E, ((diff * x->scalingFactor / x->temp)));
            // post("Difference is: %f. P is = %f", diff, p);
            
            float r = (rand() % 100) / 100.0;
            // float r = (arc4random() % 1000) / 1000.0;
            if (p > r) {
                // post("The switch to a lower solution happened. R is = %f", r);
                x->pIndex = cIndex;
                x->parent = child;
            }
        }
        
        // keep the best solution in case parent leaves it
        if (x->parent > x->bestSol) x->bestSol = x->parent;
        
        // post("PARENT: %f", x->parent);
        // post("BEST SOLUTION: %f", x->bestSol);
        
        outlet_float(x->parentOut, (npoints ? x->parent : 0));
        outlet_float(x->bestOut, x->bestSol);
    }
}
예제 #14
0
static void specCentroid_set(t_specCentroid *x, t_symbol *s)
{
	t_garray *a;

	if(!(a = (t_garray *)pd_findbyclass(s, garray_class)))
		pd_error(x, "%s: no such array", s->s_name);
	else if(!garray_getfloatwords(a, &x->x_arrayPoints, &x->x_vec))
		pd_error(x, "%s: bad template for specCentroid", s->s_name);
	else
	    x->x_arrayname = s;
}
예제 #15
0
파일: pique.c 프로젝트: Gaz5700/pd-double
static void pique_list(t_pique *x, t_symbol *s, int argc, t_atom *argv)
{
    int npts = atom_getintarg(0, argc, argv);
    t_symbol *symreal = atom_getsymbolarg(1, argc, argv);
    t_symbol *symimag = atom_getsymbolarg(2, argc, argv);
    int npeak = atom_getintarg(3, argc, argv);
    int n;
    t_garray *a;
    t_word *fpreal, *fpimag;
    if (npts < 8 || npeak < 1) error("pique: bad npoints or npeak");
    if (npeak > x->x_n) npeak = x->x_n;
    if (!(a = (t_garray *)pd_findbyclass(symreal, garray_class)) ||
        !garray_getfloatwords(a, &n, &fpreal) ||
            n < npts)
                error("%s: missing or bad array", symreal->s_name);
    else if (!(a = (t_garray *)pd_findbyclass(symimag, garray_class)) ||
        !garray_getfloatwords(a, &n, &fpimag) ||
            n < npts)
                error("%s: missing or bad array", symimag->s_name);
    else
    {
        int nfound, i;
        t_float *fpfreq = x->x_freq;
        t_float *fpamp = x->x_amp;
        t_float *fpampre = x->x_ampre;
        t_float *fpampim = x->x_ampim;
        pique_doit(npts, fpreal, fpimag, npeak,
            &nfound, fpfreq, fpamp, fpampre, fpampim, x->x_errthresh);
        for (i = 0; i < nfound; i++, fpamp++, fpfreq++, fpampre++, fpampim++)
        {
            t_atom at[5];
            SETFLOAT(at, (t_float)i);
            SETFLOAT(at+1, *fpfreq);
            SETFLOAT(at+2, *fpamp);
            SETFLOAT(at+3, *fpampre);
            SETFLOAT(at+4, *fpampim);
            outlet_list(x->x_obj.ob_outlet, &s_list, 5, at);   
        }
    }
}
예제 #16
0
파일: trento.c 프로젝트: amurtet/pd-dis
int load_two(t_trento *x, t_symbol *name1, t_symbol *name2)
{
  t_garray *b1;
  t_garray *b2;
  int flag = 0;
  int frames1;
  int frames2;
  t_word *samples1;
  t_word *samples2;
  if (!(b1 = (t_garray *)pd_findbyclass(name1,garray_class))) {
    if (name1->s_name)
      pd_error(x,"trento: %s: no such array",name1->s_name);
    return flag;
  }
  if (!(b2 = (t_garray *)pd_findbyclass(name2,garray_class))) {
    if (name2->s_name)
      pd_error(x,"trento: %s: no such array",name2->s_name);
    return flag;
  }
  if (!garray_getfloatwords(b1, &frames1, &samples1)) {
    pd_error(x, "trento: bad array for %s", name1->s_name);
    return flag;
  }
  if(!garray_getfloatwords(b2, &frames2, &samples2)) {
    pd_error(x, "trento: bad array for %s", name2->s_name);
    return flag;
  }
  else {
    flag = 1;
    x->inc_frames1 = frames1;
    x->inc_frames2 = frames2;
    x->inc_samples1 = samples1;
    x->inc_samples2 = samples2;
    x->inc_buff1 = b1;
    x->inc_buff2 = b2;
  }
  return flag;
}
예제 #17
0
static void *specCentroid_new(t_symbol *s)
{
    t_specCentroid *x = (t_specCentroid *)pd_new(specCentroid_class);
	int i;
	t_garray *a;

	x->x_centroid = outlet_new(&x->x_obj, &s_float);

	if(s)
	{
		x->x_arrayname = s;

	    if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
	        ;
	    else if(!garray_getfloatwords(a, &x->x_array_points, &x->x_vec))
	    	pd_error(x, "%s: bad template for specCentroid", x->x_arrayname->s_name);
	}
	else
		error("specCentroid: no array specified.");

	x->sr = 44100.0;
	x->window = 1; // should be a bogus size initially to force the proper resizes when a real _analyze request comes through
	x->window_func_size = 1;
	x->window_function = 3;
	x->power_spectrum = 0;

	x->max_window_size = 131072; // this seems to be the maximum size allowable by mayer_realfft();
	x->powers_of_two = (int *)getbytes(sizeof(int));

	x->powers_of_two[0] = 64; // must have at least this large of a window

	i=1;
	while(x->powers_of_two[i-1] < x->max_window_size)
	{
		x->powers_of_two = (int *)t_resizebytes(x->powers_of_two, i*sizeof(int), (i+1)*sizeof(int));
		x->powers_of_two[i] = pow(2, i+6); // +6 because we're starting at 2**6
		i++;
	}

	x->pow_two_arr_size = i;

	x->signal_R = (t_sample *)getbytes(x->window*sizeof(t_sample));

	// initialize signal_R
	memset(x->signal_R, 0, x->window*sizeof(t_sample));
	
    return (x);
}
예제 #18
0
파일: x_vexp_if.c 프로젝트: Angeldude/pd
/*
 * max_ex_tab -- evaluate this table access
 *               eptr is the name of the table and arg is the index we
 *               have to put the result in optr
 *               return 1 on error and 0 otherwise
 *
 * Arguments:
 *  the expr object
 *  table
 *  the argument
 *  the result pointer
 */
int
max_ex_tab(struct expr *expr, fts_symbol_t s, struct ex_ex *arg,
    struct ex_ex *optr)
{
#ifdef PD
        t_garray *garray;
        int size, indx;
        t_word *wvec;

        if (!s || !(garray = (t_garray *)pd_findbyclass(s, garray_class)) ||
            !garray_getfloatwords(garray, &size, &wvec))
        {
                optr->ex_type = ET_FLT;
                optr->ex_flt = 0;
                pd_error(expr, "no such table '%s'", s->s_name);
                return (1);
        }
        optr->ex_type = ET_FLT;

        switch (arg->ex_type) {
        case ET_INT:
                indx = arg->ex_int;
                break;
        case ET_FLT:
                /* strange interpolation code deleted here -msp */
                indx = arg->ex_flt;
                break;

        default:        /* do something with strings */
                pd_error(expr, "expr: bad argument for table '%s'\n", fts_symbol_name(s));
                indx = 0;
        }
        if (indx < 0) indx = 0;
        else if (indx >= size) indx = size - 1;
        optr->ex_flt = wvec[indx].w_float;
#else /* MSP */
        /*
         * table lookup not done for MSP yet
         */
        post("max_ex_tab: not complete for MSP yet!");
        optr->ex_type = ET_FLT;
        optr->ex_flt = 0;
#endif
        return (0);
}
예제 #19
0
static void tabwrite_tilde_set(t_tabwrite_tilde *x, t_symbol *s)
{
    t_garray *a;

    x->x_arrayname = s;
    if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
    {
        if (*s->s_name) pd_error(x, "tabwrite~: %s: no such array",
            x->x_arrayname->s_name);
        x->x_vec = 0;
    }
    else if (!garray_getfloatwords(a, &x->x_nsampsintab, &x->x_vec))
    {
        pd_error(x, "%s: bad template for tabwrite~", x->x_arrayname->s_name);
        x->x_vec = 0;
    }
    else garray_usedindsp(a);
}
예제 #20
0
static void tabread_float(t_tabread *x, t_float f)
{
    t_garray *a;
    int npoints;
    t_word *vec;

    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, &npoints, &vec))
        pd_error(x, "%s: bad template for tabread", x->x_arrayname->s_name);
    else
    {
        int n = f;
        if (n < 0) n = 0;
        else if (n >= npoints) n = npoints - 1;
        outlet_float(x->x_obj.ob_outlet, (npoints ? vec[n].w_float : 0));
    }
}
예제 #21
0
파일: mill~.c 프로젝트: ollierik/pd-mill
void mill_tilde_set(t_mill_tilde *x, t_symbol *s)
{
     t_garray *a;

     x->arrayname = s;
     if (!(a = (t_garray *)pd_findbyclass(x->arrayname, garray_class)))
     {
         if (*s->s_name)
             pd_error(x, "tabread~: %s: no such array", x->arrayname->s_name);
         x->x_vec = 0;
     }
     else if (!garray_getfloatwords(a, &x->arraysize, &x->x_vec))
     {
         pd_error(x, "%s: bad template for tabread~", x->arrayname->s_name);
         x->x_vec = 0;
     }
     else garray_usedindsp(a);
}
예제 #22
0
void function_setbuf(t_function *x, t_symbol *wavename)
{
    int frames;
    t_garray *a;
    
    x->b_frames = 0;
    x->b_nchans = 1;
    if (!(a = (t_garray *)pd_findbyclass(wavename, garray_class))) {
        if (*wavename->s_name) pd_error(x, "function~: %s: no such array", wavename->s_name);
    }
    else if (!garray_getfloatwords(a, &frames, &x->b_samples)) {
        pd_error(x, "%s: bad template for function~", wavename->s_name);
    }
    else  {
        x->b_frames = frames;
        garray_usedindsp(a);
        // post("%d frames in buffer", x->b_frames);
    }
}
예제 #23
0
파일: moop~.c 프로젝트: sebshader/shadylib
void moop_tilde_set(t_moop *x, t_symbol *s) {
    t_garray *a;
    int points;
    x->x_arrayname = s;
    if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
    {
        if (*s->s_name)
            pd_error(x, "moop~: %s: no such array", x->x_arrayname->s_name);
        x->x_buf.x_vec = 0;
    }
    else if (!garray_getfloatwords(a, &points, &x->x_buf.x_vec))
    {
        pd_error(x, "%s: bad template for moop~", x->x_arrayname->s_name);
        x->x_buf.x_vec = 0;
    } else {
    	x->x_buf.x_npoints = points - 4;
    	garray_usedindsp(a);
    }
}
예제 #24
0
static void tabwrite_float(t_tabwrite *x, t_float f)
{
    int i, vecsize;
    t_garray *a;
    t_word *vec;

    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, &vecsize, &vec))
        pd_error(x, "%s: bad template for tabwrite", x->x_arrayname->s_name);
    else
    {
        int n = x->x_ft1;
        if (n < 0)
            n = 0;
        else if (n >= vecsize)
            n = vecsize-1;
        vec[n].w_float = f;
        garray_redraw(a);
    }
}
예제 #25
0
/*
void function_rcos(t_function *x)
{
    int i;
    long b_frames;
    t_word *b_samples;
    t_symbol *wavename = x->wavename;
    int frames;
    t_garray *a;
    
    x->b_frames = 0;
    x->b_nchans = 1;
    // open array
    if (!(a = (t_garray *)pd_findbyclass(wavename, garray_class))) {
        if (*wavename->s_name) pd_error(x, "function~: %s: no such array", wavename->s_name);
    }
    else if (!garray_getfloatwords(a, &frames, &x->b_samples)) {
        pd_error(x, "%s: bad template for function~", wavename->s_name);
    }
    else  {
        x->b_frames = frames;
        garray_usedindsp(a);
    }
    b_frames = x->b_frames;
    post("rcos generating %d frames", b_frames); // correct
    // put samples into array
    for(i=0;i<b_frames;i++){
        x->b_samples[i].w_float = (t_float) (0.5 - 0.5 * cos(TWOPI * (t_float)i/(t_float)b_frames));
    }
    if (!(a = (t_garray *)pd_findbyclass(x->wavename, garray_class))) {
        if (*x->wavename->s_name) pd_error(x, "function~: %s: no such array", x->wavename->s_name);
    }
    else  {
        garray_redraw(a);
    }
    // printed samples are correct
    for(i=0;i<b_frames;i++){
        post("%f", x->b_samples[i].w_float);
    }
}
*/
void function_print(t_function *x)
{
    int frames;
    t_garray *a;
    int i;
    x->b_frames = 0;
    x->b_nchans = 1;
    if (!(a = (t_garray *)pd_findbyclass(x->wavename, garray_class))) {
        if (*x->wavename->s_name) pd_error(x, "function~: %s: no such array", x->wavename->s_name);
    }
    else if (!garray_getfloatwords(a, &frames, &x->b_samples)) {
        pd_error(x, "%s: bad template for function~", x->wavename->s_name);
    }
    else  {
        x->b_frames = frames;
        garray_usedindsp(a);
        for(i = 0; i < frames; i++){
            post("%d: %f",i, x->b_samples[i].w_float);
        }
    }
}
예제 #26
0
void bvplay_set(t_bvplay *x, t_symbol *wavename)
{
    
	t_garray *a;
	int b_frames;
	t_word *b_samples;
	if (!(a = (t_garray *)pd_findbyclass(wavename, garray_class))) {
		if (*wavename->s_name) pd_error(x, "%s: %s: no such array",OBJECT_NAME,wavename->s_name);
		x->wavebuf->b_valid = 0;
    }
	else if (!garray_getfloatwords(a, &b_frames, &b_samples)) {
		pd_error(x, "%s: bad array for %s", wavename->s_name,OBJECT_NAME);
		x->wavebuf->b_valid = 0;
    }
	else  {
		x->wavebuf->b_valid = 1;
		x->wavebuf->b_frames = b_frames;
		x->wavebuf->b_nchans = 1;
		x->wavebuf->b_samples = b_samples;
		garray_usedindsp(a);
	}
    
}
예제 #27
0
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));
	}
}
예제 #28
0
파일: bark.c 프로젝트: avilleret/timbreID
static void *bark_new(t_symbol *s, t_floatarg w, t_floatarg h, t_floatarg bs)
{
    t_bark *x = (t_bark *)pd_new(bark_class);
	int i, isPow2;
	t_garray *a;

	x->x_timeOut = outlet_new(&x->x_obj, &s_float);
	x->x_growthOut = outlet_new(&x->x_obj, &s_float);
	x->x_outputList = outlet_new(&x->x_obj, gensym("list"));

	if(bs)
	{
		x->x_arrayname = s;

	    if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
	        ;
	    else if(!garray_getfloatwords(a, &x->x_array_points, &x->x_vec))
	    	pd_error(x, "%s: bad template for bark", x->x_arrayname->s_name);

		isPow2 = (int)w && !( ((int)w-1) & (int)w );

		if( !isPow2 )
		{
			error("requested window size is not a power of 2. using default value of 2048 instead.");
			x->window = 2048;
		}
		else
			x->window = w;

		if(h<0)
		{
			error("hop value must be > 0. default value of 128 samples used instead.");
			x->hop = 128;
		}
		else
			x->hop = h;

		x->barkSpacing = bs;
	}
	else if(h)
	{
		x->x_arrayname = s;

	    if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
	        ;
	    else if(!garray_getfloatwords(a, &x->x_array_points, &x->x_vec))
	    	pd_error(x, "%s: bad template for bark", x->x_arrayname->s_name);

		isPow2 = (int)w && !( ((int)w-1) & (int)w );

		if( !isPow2 )
		{
			error("requested window size is not a power of 2. using default value of 2048 instead.");
			x->window = 2048;
		}
		else
			x->window = w;

		if(h<0)
		{
			error("hop value must be > 0. default value of 128 samples used instead.");
			x->hop = 128;
		}
		else
			x->hop = h;

		x->barkSpacing = 0.5;
	}
	else if(w)
	{
		x->x_arrayname = s;

	    if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
	        ;
	    else if(!garray_getfloatwords(a, &x->x_array_points, &x->x_vec))
	    	pd_error(x, "%s: bad template for bark", x->x_arrayname->s_name);

		isPow2 = (int)w && !( ((int)w-1) & (int)w );

		if( !isPow2 )
		{
			error("requested window size is not a power of 2. using default value of 2048 instead.");
			x->window = 2048;
		}
		else
			x->window = w;

		x->hop = 128;

		x->barkSpacing = 0.5;
	}
	else if(s)
	{
		x->x_arrayname = s;

	    if(!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class)))
	        ;
	    else if(!garray_getfloatwords(a, &x->x_array_points, &x->x_vec))
	    	pd_error(x, "%s: bad template for bark", x->x_arrayname->s_name);

		x->window = 2048;
		x->hop = 128;
		x->barkSpacing = 0.5;
	}
	else
	{
		error("bark: no array specified.");
		x->window = 2048;
		x->hop = 128;
		x->barkSpacing = 0.5;
	}

	x->debug = 0;
	x->sr = 44100.0;
	x->n = BLOCKSIZE;
	x->windowFunction = 4; // 4 is hann window
	x->powerSpectrum = 1; // choose mag (0) or power (1) spec
	x->normalize = 0;
	x->filterAvg = 0;
	x->loThresh = 3;
	x->hiThresh = 7;
	x->minvel = 1.0;
	x->haveHit = 0;
	x->debounceTime = 20;
	x->debounceSamp = x->debounceTime*0.001*x->sr;
	x->debounceActive = -1;
	x->maskDecay = 0.7;
	x->maskPeriods = 4;
	x->numFilters = 0;
	x->prevTotalGrowth = 0.0;
	x->useWeights = 0;
	x->spew = 0;

	x->signalBuf = (t_sample *)t_getbytes(x->window * sizeof(t_sample));
	x->analysisBuf = (t_float *)t_getbytes(x->window * sizeof(t_float));

	for(i=0; i<x->window; i++)
	{
		x->signalBuf[i] = 0.0;
		x->analysisBuf[i] = 0.0;
	}

  	x->blackman = (t_float *)t_getbytes(x->window*sizeof(t_float));
  	x->cosine = (t_float *)t_getbytes(x->window*sizeof(t_float));
  	x->hamming = (t_float *)t_getbytes(x->window*sizeof(t_float));
  	x->hann = (t_float *)t_getbytes(x->window*sizeof(t_float));

 	// initialize signal windowing functions
	tIDLib_blackmanWindow(x->blackman, x->window);
	tIDLib_cosineWindow(x->cosine, x->window);
	tIDLib_hammingWindow(x->hamming, x->window);
	tIDLib_hannWindow(x->hann, x->window);

	// grab memory
	x->x_filterbank = (t_filter *)t_getbytes(0);
	x->x_filterFreqs = (t_float *)t_getbytes(0);

	x->numFilters = tIDLib_getBarkFilterSpacing(&x->x_filterFreqs, x->sizeFilterFreqs, x->barkSpacing, x->sr);

	x->sizeFilterFreqs = x->numFilters+2;

	tIDLib_createFilterbank(x->x_filterFreqs, &x->x_filterbank, 0, x->numFilters, x->window, x->sr);

	x->loBin = 0;
	x->hiBin = x->numFilters-1;

	x->mask = (t_float *)t_getbytes(x->numFilters*sizeof(t_float));
	x->growth = (t_float *)t_getbytes(x->numFilters*sizeof(t_float));
	x->numPeriods = (int *)t_getbytes(x->numFilters*sizeof(int));
	x->growthList = (t_atom *)t_getbytes(x->numFilters*sizeof(t_atom));
	x->loudWeights = (t_float *)t_getbytes(x->numFilters*sizeof(t_float));

	for(i=0; i<x->numFilters; i++)
	{
		x->mask[i] = 0.0;
		x->growth[i] = 0.0;
		x->numPeriods[i] = 0.0;
		SETFLOAT(x->growthList+i, 0.0);
		x->loudWeights[i] = 0.0;
	}

	bark_create_loudness_weighting(x);

    post("bark 0.0.6: window size: %i, hop: %i", (int)x->window, x->hop);

    return (x);
}
예제 #29
0
파일: bark.c 프로젝트: avilleret/timbreID
static void bark_analyze(t_bark *x, t_floatarg startTime, t_floatarg endTime)
{
    int i, j, window, windowHalf, hop, nFrames, frame, sampRange, startSamp, endSamp;
    t_float totalGrowth, totalVel, *windowFuncPtr;
	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_array_points, &x->x_vec))
    	pd_error(x, "%s: bad template for bark", x->x_arrayname->s_name);
	else
	{
		window = x->window;
		windowHalf = window*0.5;
		hop = x->hop;

		if(endTime)
		{
			startSamp = floor(startTime*x->sr);
			endSamp = floor(endTime*x->sr);

			if(startSamp>=0 && endSamp<x->x_array_points)
				sampRange = endSamp-startSamp+1;
			else
			{
				error("invalid time range");
				return;
			}
		}
		else
		{
			sampRange = x->x_array_points;
			startSamp = 0;
			endSamp = x->x_array_points-1;
		}

		nFrames = floor((sampRange-window)/hop);

		// init mask to zero
		for(i=0; i<x->numFilters; i++)
			x->mask[i] = 0.0;

		for(frame=0; frame<nFrames; frame++)
		{
			// fill buffer with <window> samples
			for(i=0, j=frame*hop+startSamp; i<window; i++, j++)
				x->signalBuf[i] = x->x_vec[j].w_float;

			totalGrowth = 0.0;
			totalVel = 0.0;

		    // 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++)
				    x->analysisBuf[i] = x->signalBuf[i] * *windowFuncPtr;
		    else
			    for(i=0; i<window; i++, windowFuncPtr++)
				    x->analysisBuf[i] = x->signalBuf[i];

			mayer_realfft(window, x->analysisBuf);

			// calculate the power spectrum in place. we'll overwrite the first N/2+1 points in x->analysisBuf with the magnitude spectrum, as this is all that's used below in filterbank_multiply()
			x->analysisBuf[0] = x->analysisBuf[0] * x->analysisBuf[0];  // DC
			x->analysisBuf[windowHalf] = x->analysisBuf[windowHalf] * x->analysisBuf[windowHalf];  // Nyquist

			for(i=(window-1), j=1; i>windowHalf; i--, j++)
				x->analysisBuf[j] = (x->analysisBuf[j]*x->analysisBuf[j]) + (x->analysisBuf[i]*x->analysisBuf[i]);

			// optional use of power/magnitude spectrum
			if(!x->powerSpectrum)
				for(i=0; i<=windowHalf; i++)
					x->analysisBuf[i] = sqrt(x->analysisBuf[i]);

			tIDLib_filterbankMultiply(x->analysisBuf, x->normalize, x->filterAvg, x->x_filterbank, x->numFilters);

			// optional loudness weighting
			if(x->useWeights)
				for(i=0; i<x->numFilters; i++)
					x->analysisBuf[i] *= x->loudWeights[i];

			for(i=0; i<x->numFilters; i++)
				totalVel += x->analysisBuf[i];

			// init growth list to zero
			for(i=0; i<x->numFilters; i++)
				x->growth[i] = 0.0;

			for(i=0; i<x->numFilters; i++)
			{
				// from p.3 of Puckette/Apel/Zicarelli, 1998
				// salt divisor with + 1.0e-15 in case previous power was zero
				if(x->analysisBuf[i] > x->mask[i])
					x->growth[i] = x->analysisBuf[i]/(x->mask[i] + 1.0e-15) - 1.0;

				if(i>=x->loBin && i<=x->hiBin && x->growth[i]>0)
					totalGrowth += x->growth[i];

				SETFLOAT(x->growthList+i, x->growth[i]);
			}

			if(frame*hop+startSamp >= x->debounceActive)
			    x->debounceActive = -1;

			if(totalVel >= x->minvel && totalGrowth > x->hiThresh && !x->haveHit && x->debounceActive < 0)
			{
				if(x->debug)
					post("peak: %f", totalGrowth);

				x->haveHit = 1;
				x->debounceActive = frame*hop+startSamp + x->debounceSamp;
			}
			else if(x->haveHit && x->loThresh>0 && totalGrowth < x->loThresh) // if loThresh is an actual value (not -1), then wait until growth drops below that value before reporting attack
			{
				if(x->debug)
					post("drop: %f", totalGrowth);

				x->haveHit = 0;

				// don't output data if spew will do it anyway below
				if(!x->spew)
				{
					outlet_list(x->x_outputList, 0, x->numFilters, x->growthList);
					outlet_float(x->x_growthOut, totalGrowth);
				}

				// add half a window of samples as a fudge factor. note that since this NRT and we can look into the future, all attack reports will be roughly a half window EARLY.  in RT, everything is a half window LATE because the point of reference is the END of the window.  here, it's the BEGINNING of the window.
				outlet_float(x->x_timeOut, (frame*hop+startSamp + windowHalf)/x->sr);
			}
			else if(x->haveHit && x->loThresh<0 && totalGrowth < x->prevTotalGrowth) // if loThresh == -1, report attack as soon as growth shows any decay at all
			{
				if(x->debug)
					post("drop: %f", totalGrowth);

				x->haveHit = 0;

				// don't output data if spew will do it anyway below
				if(!x->spew)
				{
					outlet_list(x->x_outputList, 0, x->numFilters, x->growthList);
					outlet_float(x->x_growthOut, totalGrowth);
				}

				// add half a window of samples as a fudge factor. note that since this NRT and we can look into the future, all attack reports will be roughly a half window EARLY.  in RT, everything is a half window LATE because the point of reference is the END of the window.  here, it's the BEGINNING of the window.
				outlet_float(x->x_timeOut, (frame*hop+startSamp + windowHalf)/x->sr);
			}

			if(x->spew)
			{
				outlet_list(x->x_outputList, 0, x->numFilters, x->growthList);
				outlet_float(x->x_growthOut, totalGrowth);
			}

			// update mask
			for(i=0; i<x->numFilters; i++)
			{
				if(x->analysisBuf[i] > x->mask[i])
				{
					x->mask[i] = x->analysisBuf[i];
					x->numPeriods[i] = 0;
				}
				else
					if(++x->numPeriods[i] >= x->maskPeriods)
						x->mask[i] *= x->maskDecay;
			}

			x->prevTotalGrowth = totalGrowth;
		}
	}

	post("analyzed %i frames", nFrames);
}
예제 #30
0
static void specCentroid_analyze(t_specCentroid *x, t_floatarg start, t_floatarg n)
{
	int i, j, old_window, window, window_half, start_samp, end_samp, length_samp;
	float *window_func_ptr;
    float dividend, divisor, centroid;
	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_array_points, &x->x_vec))
    	pd_error(x, "%s: bad template for specCentroid", x->x_arrayname->s_name);
	else
	{

	start_samp = start;
	
	if(start_samp < 0)
		start_samp = 0;

	if(n)
		end_samp = start_samp + n-1;
	else
		end_samp = start_samp + x->window-1;
		
	if(end_samp > x->x_array_points)
		end_samp = x->x_array_points-1;

	length_samp = end_samp - start_samp + 1;

	if(end_samp <= start_samp)
	{
		error("bad range of samples.");
		return;
	}
		
	if(length_samp > x->powers_of_two[x->pow_two_arr_size-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. Sizes of more than 131072 may produce unreliable results.");
		length_samp = x->powers_of_two[x->pow_two_arr_size-1];
		window = length_samp;
		end_samp = start_samp + window - 1;
	}
	else
	{
		i=0;
		while(length_samp > x->powers_of_two[i])
			i++;

		window = x->powers_of_two[i];
	}

	window_half = window * 0.5;

	if(x->window != window)
	{
		old_window = x->window;
		x->window = window;
		x->signal_R = (t_sample *)t_resizebytes(x->signal_R, old_window*sizeof(t_sample), window*sizeof(t_sample));
	}
	
	if(x->window_func_size != length_samp)
	{
		x->blackman = (float *)t_resizebytes(x->blackman, x->window_func_size*sizeof(float), length_samp*sizeof(float));
		x->cosine = (float *)t_resizebytes(x->cosine, x->window_func_size*sizeof(float), length_samp*sizeof(float));
		x->hamming = (float *)t_resizebytes(x->hamming, x->window_func_size*sizeof(float), length_samp*sizeof(float));
		x->hann = (float *)t_resizebytes(x->hann, x->window_func_size*sizeof(float), length_samp*sizeof(float));

		x->window_func_size = length_samp;
		
		specCentroid_blackman_window(x->blackman, x->window_func_size);
		specCentroid_cosine_window(x->cosine, x->window_func_size);
		specCentroid_hamming_window(x->hamming, x->window_func_size);
		specCentroid_hann_window(x->hann, x->window_func_size);
	}

	// create local memory
	signal_I = (t_sample *)getbytes(window_half*sizeof(t_sample));

	// construct analysis window
	for(i=0, j=start_samp; j<=end_samp; i++, j++)
		x->signal_R[i] = x->x_vec[j].w_float;

	// set window
	window_func_ptr = x->hann; //default case to get rid of compile warning
	switch(x->window_function)
	{
		case 0:
			window_func_ptr = x->blackman;
			break;
		case 1:
			window_func_ptr = x->cosine;
			break;
		case 2:
			window_func_ptr = x->hamming;
			break;
		case 3:
			window_func_ptr = x->hann;
			break;
		default:
			break;
	};
	
	// then multiply against the chosen window
	for(i=0; i<length_samp; i++, window_func_ptr++)
		x->signal_R[i] *= *window_func_ptr;

	// then zero pad the end
	for(; i<window; i++)
		x->signal_R[i] = 0.0;

	mayer_realfft(window, x->signal_R);
	specCentroid_realfft_unpack(window, window_half, x->signal_R, signal_I);
	specCentroid_power(window_half, x->signal_R, signal_I);

	if(!x->power_spectrum)
		specCentroid_mag(window_half, x->signal_R);

	dividend=0;
	divisor=0;
	centroid=0;
	
	for(i=0; i<window_half; i++)
		dividend += x->signal_R[i]*(i*(x->sr/window));  // weight by bin freq

	for(i=0; i<window_half; 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, window_half*sizeof(t_sample));

	}
}