static void barkSpec_tilde_dsp(t_barkSpec_tilde *x, t_signal **sp) { int i, oldNumFilters; dsp_add( barkSpec_tilde_perform, 3, x, sp[0]->s_vec, sp[0]->s_n ); // compare n to stored n and recalculate filterbank if different if( sp[0]->s_sr != (x->sr*x->overlap) || sp[0]->s_n != x->n ) { x->signal_R = (t_sample *)t_resizebytes(x->signal_R, (x->window+x->n) * sizeof(t_sample), (x->window+sp[0]->s_n) * sizeof(t_sample)); x->sr = sp[0]->s_sr/x->overlap; x->n = sp[0]->s_n; // init signal buffer for(i=0; i<x->window+x->n; i++) x->signal_R[i] = 0.0; oldNumFilters = x->numFilters; 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, oldNumFilters, x->numFilters, x->window, x->sr); post("barkSpec~: window size: %i. sampling rate: %i, block size: %i", (int)x->window, (int)x->sr, (int)x->n); }; };
static void barkSpec_tilde_createFilterbank(t_barkSpec *x, t_float bs) { int oldNumFilters; x->barkSpacing = bs; oldNumFilters = x->numFilters; 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, oldNumFilters, x->numFilters, x->window, x->sr); }
// this is the Max 6 version of the dsp method -- it registers a function for the signal chain in Max 6, // which operates on 64-bit audio signals. void barkSpec_dsp64(t_barkSpec *x, t_object *dsp64, short *count, double samplerate, long maxvectorsize, long flags) { int i, oldNumFilters; double timef; post("my sample rate is: %f", samplerate); // instead of calling dsp_add(), we send the "dsp_add64" message to the object representing the dsp chain // the dsp_add64 arguments are: // 1: the dsp64 object passed-in by the calling function // 2: a pointer to your object // 3: a pointer to your 64-bit perform method // 4: flags to alter how the signal chain handles your object -- just pass 0 // 5: a generic pointer that you can use to pass any additional data to your perform method object_method(dsp64, gensym("dsp_add64"), x, barkSpec_perform64, 0, NULL); // compare n to stored n and recalculate filterbank if different if(samplerate != (x->sr*x->overlap) || maxvectorsize != x->n) { x->signal_R = (t_sample *)t_resizebytes_(x->signal_R, (x->window+x->n) * sizeof(t_sample), (x->window+maxvectorsize) * sizeof(t_sample)); x->sr = samplerate/x->overlap; x->n = maxvectorsize; //x->lastDspTime = clock_getlogicaltime(); clock_getftime(&timef); x->lastDspTime = timef; // init signal buffer for(i=0; i<(x->window+x->n); i++) x->signal_R[i] = 0.0; oldNumFilters = x->numFilters; 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, oldNumFilters, x->numFilters, x->window, x->sr); post("barkSpec~: window size: %i. sampling rate: %i, block size: %i", (int)x->window, (int)x->sr, (int)x->n); }; }
static void barkSpec_tilde_window(t_barkSpec *x, int w) { int i, window, isPow2, oldNumFilters; window = w; isPow2 = window && !( (window-1) & window ); if( !isPow2 ) error("requested window size is not a power of 2"); else { x->signal_R = (t_sample *)t_resizebytes_(x->signal_R, (x->window+x->n) * sizeof(t_sample), (window+x->n) * sizeof(t_sample)); x->blackman = (t_float *)t_resizebytes_(x->blackman, x->window*sizeof(t_float), window*sizeof(t_float)); x->cosine = (t_float *)t_resizebytes_(x->cosine, x->window*sizeof(t_float), window*sizeof(t_float)); x->hamming = (t_float *)t_resizebytes_(x->hamming, x->window*sizeof(t_float), window*sizeof(t_float)); x->hann = (t_float *)t_resizebytes_(x->hann, x->window*sizeof(t_float), window*sizeof(t_float)); x->window = (t_float)window; // re-init window 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); // init signal buffer for(i=0; i<(x->window+x->n); i++) x->signal_R[i] = 0.0; oldNumFilters = x->numFilters; 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, oldNumFilters, x->numFilters, x->window, x->sr); post("window size: %i", (int)x->window); } }
// this function is called when the DAC is enabled, and "registers" a function for the signal chain in Max 5 and earlier. // In this case we register the 32-bit, "barkSpec_perform" method. void barkSpec_dsp(t_barkSpec *x, t_signal **sp, short *count) { int i, oldNumFilters; double timef; post("my sample rate is: %f", sp[0]->s_sr); // 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(barkSpec_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); // compare n to stored n and recalculate filterbank if different if(sp[0]->s_sr != (x->sr*x->overlap) || sp[0]->s_n != x->n) { x->signal_R = (t_sample *)t_resizebytes_(x->signal_R, (x->window+x->n) * sizeof(t_sample), (x->window+sp[0]->s_n) * sizeof(t_sample)); x->sr = sp[0]->s_sr/x->overlap; x->n = sp[0]->s_n; //x->lastDspTime = clock_getlogicaltime(); clock_getftime(&timef); x->lastDspTime = timef; // init signal buffer for(i=0; i<(x->window+x->n); i++) x->signal_R[i] = 0.0; oldNumFilters = x->numFilters; 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, oldNumFilters, x->numFilters, x->window, x->sr); post("barkSpec~: window size: %i. sampling rate: %i, block size: %i", (int)x->window, (int)x->sr, (int)x->n); }; }
static void bark_samplerate(t_bark *x, t_floatarg sr) { int i, oldNumFilters; oldNumFilters = x->numFilters; if(sr<=0) { error("samplerate must be > 0. default value of 44100 used instead."); x->sr = 44100; } else x->sr = sr; x->debounceSamp = x->debounceTime*0.001*x->sr; 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, oldNumFilters, x->numFilters, x->window, x->sr); x->loBin = 0; x->hiBin = x->numFilters-1; x->mask = (t_float *)t_resizebytes(x->mask, oldNumFilters*sizeof(t_float), x->numFilters*sizeof(t_float)); x->growth = (t_float *)t_resizebytes(x->growth, oldNumFilters*sizeof(t_float), x->numFilters*sizeof(t_float)); x->numPeriods = (int *)t_resizebytes(x->numPeriods, oldNumFilters*sizeof(int), x->numFilters*sizeof(int)); x->growthList = (t_atom *)t_resizebytes(x->growthList, oldNumFilters*sizeof(t_atom), x->numFilters*sizeof(t_atom)); x->loudWeights = (t_float *)t_resizebytes(x->loudWeights, oldNumFilters*sizeof(t_float), 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; } }
void *barkSpec_new(t_symbol *s, long argc, t_atom *argv) { t_barkSpec *x = (t_barkSpec *)object_alloc(barkSpec_class); int i, isPow2; double timef = 0.0; //s=s; if (x) { dsp_setup((t_pxobject *)x, 1); // MSP inlets: arg is # of inlets and is REQUIRED! // use 0 if you don't need inlets //outlet_new(x, "signal"); // signal outlet (note "signal" rather than NULL) //x->offset = 0.0; x->x_featureList = listout(x); //x->x_featureList = outlet_new(&x->x_obj, &s_float); if(argc > 1) { x->window = atom_getlong(argv); // should perform a check for >64 && power of two isPow2 = (int)x->window && !( ((int)x->window-1) & (int)x->window ); if(!isPow2) { error("requested window size is not a power of 2. default value of 1024 used instead."); x->window = 1024; }; x->barkSpacing = atom_getfloat(argv+1); } else if(argc > 0) { x->window = atom_getlong(argv); isPow2 = (int)x->window && !( ((int)x->window-1) & (int)x->window ); if(!isPow2) { error("requested window size is not a power of 2. default value of 1024 used instead."); x->window = 1024; }; x->barkSpacing = 0.5; } else { x->window = 1024; x->barkSpacing = 0.5; } x->sr = 44100.0; x->n = 64.0; x->overlap = 1; x->windowFunction = 4; // 4 is hann window x->powerSpectrum = 0; // choose mag (0) or power (1) spec x->normalize = 1; // this is generally a good thing, but should be off for concatenative synth x->filterAvg = 0; //x->lastDspTime = clock_getlogicaltime(); clock_getftime(&timef); x->lastDspTime = timef; x->sizeFilterFreqs = 0; x->numFilters = 0; // this is just an init size that will be updated in createFilterbank anyway. x->signal_R = (t_sample *)t_getbytes_((x->window+x->n)*sizeof(t_sample)); // initialize signal buffer for(i=0; i<x->window+x->n; i++) x->signal_R[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); } return (x); }
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); }
static void *barkSpec_tilde_new(t_symbol *s, int argc, t_atom *argv) { t_barkSpec_tilde *x = (t_barkSpec_tilde *)pd_new(barkSpec_tilde_class); int i, isPow2; s=s; x->x_featureList = outlet_new(&x->x_obj, gensym("list")); if(argc > 1) { x->window = atom_getfloat(argv); // should perform a check for >64 && power of two isPow2 = (int)x->window && !( ((int)x->window-1) & (int)x->window ); if(!isPow2) { error("requested window size is not a power of 2. default value of 1024 used instead."); x->window = 1024; }; x->barkSpacing = atom_getfloat(argv+1); } else if(argc > 0) { x->window = atom_getfloat(argv); isPow2 = (int)x->window && !( ((int)x->window-1) & (int)x->window ); if(!isPow2) { error("requested window size is not a power of 2. default value of 1024 used instead."); x->window = 1024; }; x->barkSpacing = 0.5; } else { x->window = 1024; x->barkSpacing = 0.5; } x->sr = 44100.0; x->n = 64.0; x->overlap = 1; x->windowFunction = 4; // 4 is hann window x->powerSpectrum = 0; // choose mag (0) or power (1) spec x->normalize = 1; // this is generally a good thing, but should be off for concatenative synth x->filterAvg = 0; x->lastDspTime = clock_getlogicaltime(); x->sizeFilterFreqs = 0; x->numFilters = 0; // this is just an init size that will be updated in createFilterbank anyway. x->signal_R = (t_sample *)t_getbytes((x->window+x->n)*sizeof(t_sample)); // initialize signal buffer for(i=0; i<x->window+x->n; i++) x->signal_R[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); return (x); }