void multigrain_info(t_multigrain *x)
{
	int tcount = 0;
    t_buffer_obj	*buffer = buffer_ref_getobject(x->wavebuf);
	t_grain *grains = x->grains;
	int i;
	
	for(i = 0; i < MAXGRAINS; i++ ){
		if(grains[i].active)
			++tcount;
	}
	post("%d active grains", tcount);
	post("wavename %s", x->wavename->s_name);
	post("windowname %s", x->windowname->s_name);
	post("sample size: %d",buffer_getframecount(buffer));
}
Exemple #2
0
void buff_get_param(t_buff_info *buff)
{
  // If the buffer has no object
  if (buff->has_obj == false) {
    buff->has_file = false;
    return; }

  // Get the buffer variables  
  buff->fr_cnt = (t_uint32)buffer_getframecount(buff->obj);
  buff->ch_cnt = (t_uint8)buffer_getchannelcount(buff->obj);
  buff->msr     = buffer_getmillisamplerate(buff->obj);
    
  // Test the buffer variables
  if ((buff->fr_cnt == 0) || (buff->ch_cnt == 0) || (buff->msr == 0)) {
    buff->has_file = false; }

  // Otherwise the buffer is linked and a file is loaded.
  else {
    buff->has_file = true; }
}
void multigrain_setbuf(t_multigrain *x, t_symbol *wavename, t_symbol *windowname)
{
    t_buffer_obj *b;
    int i;
    

    buffer_ref_set(x->wavebuf, wavename);
    buffer_ref_set(x->windowbuf, windowname);


    b = buffer_ref_getobject(x->wavebuf);
    if(b == NULL){
        post("invalid sound buffer %s", wavename->s_name);
        return;
    } 
    x->b_frames = buffer_getframecount(b);

    x->hosed = 0;
    // kill all current grains
    for(i = 0; i < MAXGRAINS; i++){
        x->grains[i].active = 0;
    }
    if( buffer_getchannelcount(b) > 2 ){
        error("wavetable must be a mono or stereo buffer");
        x->hosed = 1;
    }
    
    b = buffer_ref_getobject(x->windowbuf);
    if(b == NULL){
        post("invalid window buffer %s", windowname->s_name);
        return;
    }
    if( buffer_getchannelcount(b) != 1 ){
        error("window must be a mono buffer");
        x->hosed = 1;
    }
    x->wavename = wavename;
    x->windowname = windowname;
    x->maxskip = x->b_frames - 1;

}
/********************************************************************************
void grainstream_setwin(t_grainstream *x, t_symbol *s)

inputs:			x		-- pointer to this object
				s		-- name of buffer to link
description:	links buffer holding the grain window 
returns:		nothing
********************************************************************************/
void grainstream_setwin(t_grainstream *x, t_symbol *s)
{
    t_buffer_ref *b = buffer_ref_new((t_object*)x, s);
    
    if (buffer_ref_exists(b)) {
        t_buffer_obj	*b_object = buffer_ref_getobject(b);
        
        if (buffer_getchannelcount(b_object) != 1) {
			error("%s: buffer~ > %s < must be mono", OBJECT_NAME, s->s_name);
			x->next_win_buf_ptr = NULL;		//added 2002.07.15
		} else {
			if (x->win_buf_ptr == NULL) { // if first buffer make current buffer
				x->win_sym = s;
				x->win_buf_ptr = b;
				//x->win_last_out = 0.0;	//removed 2005.02.03
				x->win_last_index = buffer_getframecount(b_object);
				
				#ifdef DEBUG
					post("%s: current window set to buffer~ > %s <", OBJECT_NAME, s->s_name);
				#endif /* DEBUG */
			} else { // else defer to next buffer
				x->win_sym = s;
				x->next_win_buf_ptr = b;
				//x->win_buf_length = b->b_frames;	//removed 2002.07.11
				//x->win_last_out = 0.0;		//removed 2002.07.24
				
				#ifdef DEBUG
					post("%s: next window set to buffer~ > %s <", OBJECT_NAME, s->s_name);
				#endif /* DEBUG */
			}
		}
	} else {
		error("%s: no buffer~ > %s < found", OBJECT_NAME, s->s_name);
		x->next_win_buf_ptr = NULL;
	}
}
Exemple #5
0
void breakgen_writebuf(t_breakgen *x, t_symbol *s, long argc, t_atom *argv)
{
    t_atom *ap;
    t_atom_long framecount;
    long num_frames;
    t_buffer_obj *buf;  // need to free this
    float *bufframe;
    t_max_err buferror;
    int i;
    
    ap = argv;
    
    if (atom_gettype(ap) == A_SYM) {
        x->buffy = buffer_ref_new((t_object *)x, atom_getsym(ap));
        if (buffer_ref_exists(x->buffy) != 0) {
            buf = buffer_ref_getobject(x->buffy);
            framecount = buffer_getframecount(buf);
            ap++;
            if (atom_gettype(ap) == A_LONG) {
                num_frames = atom_getlong(ap);
                if (num_frames < framecount) framecount = num_frames;
                bufframe = buffer_locksamples(buf);
                if (bufframe) {
                    for (i = 0; i < framecount; i++) {
                        *bufframe = output_val(x) - 1.0;
                        bufframe++;
                    }
                }
                buferror = buffer_setdirty(buf);
                buffer_unlocksamples(buf);
            }
        } else {
            post("buffer doesn't exist");
        };
    }
}
Exemple #6
0
void index_perform64(t_index *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
{
	t_double	*in = ins[0];
	t_double	*out = outs[0];
	int			n = sampleframes;
	t_float		*tab;
	double		temp;
	double		f;
	long		index, chan, frames, nc;
	t_buffer_obj	*buffer = buffer_ref_getobject(x->l_buffer_reference);

	tab = buffer_locksamples(buffer);
	if (!tab)
		goto zero;

	frames = buffer_getframecount(buffer);
	nc = buffer_getchannelcount(buffer);
	chan = MIN(x->l_chan, nc);
	while (n--) {
		temp = *in++;
		f = temp + 0.5;
		index = f;
		if (index < 0)
			index = 0;
		else if (index >= frames)
			index = frames - 1;
		if (nc > 1)
			index = index * nc + chan;
		*out++ = tab[index];
	}
	buffer_unlocksamples(buffer);
	return;
zero:
	while (n--)
		*out++ = 0.0;
}
void buffi_autofunc(t_buffi *x, t_floatarg minval, t_floatarg maxval, t_symbol *buffername)
{
    int minpoints, maxpoints, segpoints, i;
    int pointcount = 0;
    double target, lastval;
    double m1, m2;
    t_buffer_ref *tablebuf_ref;
    t_buffer_obj *dbuf;
    long b_nchans;
    long b_frames;
    float *b_samples;
    
    /////

    tablebuf_ref = buffer_ref_new((t_object*)x, buffername);

    dbuf = buffer_ref_getobject(tablebuf_ref);
    if(dbuf == NULL){
        object_post((t_object*)x,"%s: nonexistent buffer ( %s )",
                    OBJECT_NAME, buffername->s_name);
        return;
    }
    b_nchans = buffer_getchannelcount(dbuf);
    b_frames = buffer_getframecount(dbuf);
    if(b_nchans != 1){
        post("%s: table must be mono",OBJECT_NAME);
        return;
    }
    x->warpfunc = (float *)sysmem_newptr(b_frames * sizeof(float));
    
    minpoints = 0.05 * (float) b_frames;
    maxpoints = 0.25 * (float) b_frames;
    if( minval > 1000.0 || minval < .001 ){
        minval = 0.5;
    }
    if( maxval < 0.01 || maxval > 1000.0 ){
        minval = 2.0;
    }
    
    lastval = buffi_randf(minval, maxval);
    // post("automate: min %d max %d",minpoints, maxpoints);
    while( pointcount < b_frames ){
        target = buffi_randf(minval, maxval);
        segpoints = minpoints + (rand() % (maxpoints-minpoints));
        if( pointcount + segpoints > b_frames ){
            segpoints = b_frames - pointcount;
        }
        for( i = 0; i < segpoints; i++ ){
            m2 = (float)i / (float) segpoints ;
            m1 = 1.0 - m2;
            x->warpfunc[ pointcount + i ] = m1 * lastval + m2 * target;
        }
        lastval = target;
        pointcount += segpoints;
    }
    // buffer stuffer
    b_samples = buffer_locksamples(dbuf);
    for(i = 0; i < b_frames; i++){
        b_samples[i] = x->warpfunc[i];
    }
    buffer_unlocksamples(dbuf);
    sysmem_freeptr( (void *) x->warpfunc );
    object_method(dbuf, gensym("dirty"));
}
void *multigrain_grain(t_multigrain *x, t_symbol *msg, short argc, t_atom *argv)
{
	short inserted;
	int j;
	float duration, incr, amplitude, pan;
	t_grain *grains;
	long eframes;
	long frames;
	float sr;
	float skip;
	if(!sys_getdspstate()){
		error("scheduler halted until DSP is turned on.");
		return NIL;
	}
	grains = x->grains;
     eframes = buffer_getframecount(buffer_ref_getobject(x->windowbuf));
	frames = buffer_getframecount(buffer_ref_getobject(x->wavebuf));

	sr = x->sr;
	
	if(argc < 5){
		error("grain takes 5 arguments, not %d",argc);
		post("duration increment amplitude pan skip(in ms)");
		return NIL;
	}
	duration = atom_getintarg(0,argc,argv);
	incr = atom_getfloatarg(1,argc,argv); // in ms
	amplitude = atom_getfloatarg(2,argc,argv);
	pan = atom_getfloatarg(3,argc,argv);
	skip = atom_getfloatarg(4,argc,argv) * .001 * sr;
	if(skip < 0){
		error("negative skip is illegal");
		return NIL;
	}
	if(skip >= frames){
		error("skip exceeds length of buffer");
		return NIL;
	}
	if(incr == 0.0){
		error("zero increment prohibited");
		return NIL;
	}
	if(duration <= 0.0){
		error("illegal duration:%f",duration);
		return NIL;
	}
	if(pan < 0.0 || pan > 1.0){
		error("illegal pan:%f",pan);
		return NIL;
	}
	inserted = 0;
	for(j = 0; j < MAXGRAINS; j++ ){
		if(!grains[j].active){
			grains[j].delay = 0.0;// immediate deployment
			grains[j].duration = (long) (.001 * x->sr * duration);
			grains[j].phase = skip;
			grains[j].ephase = 0.0;
			grains[j].amplitude = amplitude * .707;
//			grains[j].panL = amplitude * cos(pan * PIOVERTWO);
//			grains[j].panR = amplitude * sin(pan * PIOVERTWO);
			grains[j].esi =  (float)eframes / (float)grains[j].duration;
			grains[j].si = incr;
			grains[j].active = 1;
			return NIL;
		}
	}
	
	error("could not insert grain");
	return NIL;
	
}
void multigrain_spray(t_multigrain *x)
{
	int i,j;
	long grainframes;
	long eframes = buffer_getframecount(buffer_ref_getobject(x->windowbuf));
	long b_frames = buffer_getframecount(buffer_ref_getobject(x->wavebuf));
	long horizon = x->horizon; // length of block for random events
	float mindur = x->mindur;
	float maxdur = x->maxdur;
	float min_incr = x->min_incr; // minimum incr for a grain (must be positive!)
	float max_incr = x->max_incr; // maximum incr for a grain (must be positive!)
	float minpan = x->minpan; // minimum pan for a grain
	float maxpan = x->maxpan; // maxium pan for a grain
	float minamp = x->minamp; // minimum amplitude for a grain
	float maxamp = x->maxamp; // maximum amplitude for a grain
	float transpose = x->transpose; // pitch scalar
	long minskip = x->minskip;
	long maxskip = x->maxskip;
	short steady = x->steady;
	float retro_odds = x->retro_odds;
	float pan;
	t_grain *grains = x->grains;
	short inserted;
	float tmp;
    long minchanr = x->minchanr;
    long maxchanr = x->maxchanr;
    long *changroup = x->changroup;
    long changroup_length = x->changroup_length;
    long dex;
    long groupflag = x->groupflag;
	if( !sys_getdspstate() ){
		return;
	}
	for( i = 0; i < x->events; i++ ){
		inserted = 0;
		for(j = 0; j < MAXGRAINS; j++ ){
			if(!grains[j].active){
				grains[j].active = 1;
				if(steady){
					grains[j].delay = (float)(i * horizon) / (float) x->events ;
				} else {
    				grains[j].delay = multigrain_boundrand(0.0,(float) horizon);
    			}
   				grains[j].duration = (long) multigrain_boundrand(mindur, maxdur);//frames for this grain
    			grains[j].ephase = 0.0;
    			pan = multigrain_boundrand(minpan, maxpan);
     			grains[j].amplitude = multigrain_boundrand(minamp, maxamp);
				grains[j].si = transpose * multigrain_boundrand(min_incr, max_incr);

                
                
                if(groupflag == 1){
                    dex = random() % changroup_length;
                    grains[j].output_channel = changroup[dex];
                } else {
                    grains[j].output_channel = minchanr + (random() % (maxchanr - minchanr));
                }
				grainframes = grains[j].duration * grains[j].si;//frames to be read from buffer
				grains[j].esi =  (float) eframes / (float) grains[j].duration;
				if(grainframes >= b_frames ){
				  	error("grain size %.0f is too long for buffer which is %d",grainframes, b_frames);
				  	grains[j].active = 0;
				  	goto nextgrain;
				}
				if(minskip > b_frames - grainframes){//bad minskip
				  	error("minskip time is illegal");
				  	grains[j].phase = 0.0;
				  	grains[j].endframe = grainframes - 1;
				} else {
					if(maxskip > b_frames - grainframes){
					  	grains[j].phase = multigrain_boundrand((float)minskip, (float) (b_frames - grainframes));
					  	//post("1. minskip %d maxskip %d",minskip,b_frames - grainframes);
					} else {
					  	grains[j].phase = multigrain_boundrand((float)minskip, (float)maxskip);
					  	//post("2. minskip %d maxskip %d",minskip,maxskip);
					}
					grains[j].endframe = grains[j].phase + grainframes - 1;
				}
				
				if( multigrain_boundrand(0.0,1.0) < retro_odds){//go backwards - make sure to test both boundaries
				  	grains[j].si *= -1.0;
				  	tmp = grains[j].phase;
				  	grains[j].phase = grains[j].endframe;
				  	grains[j].endframe = tmp;
				}
    			inserted = 1;
    			goto nextgrain;
    		}
		}
		if(! inserted){
			error("multigrain~: could not insert grain");
			return;
		}
	nextgrain: ;
	}
}
void multigrain_pitchspray(t_multigrain *x)
{
	int i,j;
	long grainframes;
    long eframes = buffer_getframecount(buffer_ref_getobject(x->windowbuf));
	long b_frames = buffer_getframecount(buffer_ref_getobject(x->wavebuf));
	long minskip = x->minskip;
	long maxskip = x->maxskip;
	float retro_odds = x->retro_odds;
	long horizon = x->horizon; // length of block for random events
	float mindur = x->mindur;
	float maxdur = x->maxdur;
	float min_incr = x->min_incr; // minimum frequency for a grain
	float max_incr = x->max_incr; // maximum frequency for a grain
	float minamp = x->minamp; // minimum amplitude for a grain
	float maxamp = x->maxamp; // maximum amplitude for a grain
	float transpose = x->transpose; // pitch scalar
	float lowblock_increment = x->lowblock_increment;
	float highblock_increment = x->highblock_increment;
	short steady = x->steady;
	float pitch_deviation = x->pitch_deviation;
	float pdev = 0;
	float pdev_invert = 0;
	int index_min, index_max;
	int steps = x->pitchsteps;
	float *scale = x->pitchscale;
	int windex;
	short inserted = 0;
	short constrain_scale = x->constrain_scale;
	t_grain *grains = x->grains;
	float tmp;
	
	if(! sys_getdspstate()){
		// error("scheduler halted until DSP is turned on.");
		return;
	}
	
	if( steps < 2 ){
		error("scale is undefined");
		return;
	}
	if( pitch_deviation ){
		pdev = 1.0 + pitch_deviation;
		pdev_invert = 1.0 / pdev;
	}
	for( i = 0; i < x->events; i++ ){
		inserted = 0;
		for(j = 0; j < MAXGRAINS; j++ ){
			if(!grains[j].active){
				if(steady){
					grains[j].delay = (float)(i * horizon) / (float) x->events ;
				} else {
					grains[j].delay = multigrain_boundrand(0.0,(float) horizon);
    			}
    			grains[j].duration = (long) multigrain_boundrand(mindur, maxdur);
    			grains[j].phase = 0.0;
    			grains[j].ephase = 0.0;
    			grains[j].amplitude = multigrain_boundrand(minamp, maxamp);
    			grains[j].amplitude *= .707;//used directly only for "nopan"
                grains[j].output_channel = random() % x->output_channels;
    			
				if(constrain_scale){
					multigrain_constrain(&index_min,&index_max,min_incr, max_incr, scale, steps);
					windex = (int) multigrain_boundrand((float)index_min, (float)index_max);
				} else {
					windex = (int) multigrain_boundrand(0.0, (float)(steps));
				}
    			grains[j].si = transpose * scale[windex];
				//	post("windex %d scale[w] %f transpose %f si %f",windex, scale[windex], transpose, grains[j].si );
    			grainframes = grains[j].duration * grains[j].si;
    			grains[j].esi =  (float) eframes / (float) grains[j].duration;
    			
    			if( pitch_deviation ){
    				grains[j].si *= multigrain_boundrand(pdev_invert,pdev);
    			}
    			// post("new si: %f", grains[j].si);
    			/* must add this code to spray, and also do for high frequencies
				 */
    			if(lowblock_increment > 0.0) {
    				if(grains[j].si < lowblock_increment){
    					post("lowblock: aborted grain with %f frequency",grains[j].si);
    					grains[j].active = 0; // abort grain
    					goto nextgrain;
    				}
    			}
    			if(highblock_increment > 0.0) {
    				if(grains[j].si > highblock_increment){
    					post("highblock: aborted grain with %f frequency, greater than %f",
							 grains[j].si, highblock_increment);
    					grains[j].active = 0; // abort grain
    					goto nextgrain;
    				}
    			}
				/* set skip time into sample */
				if(grainframes >= b_frames ){
				  	error("grain size %.0f is too long for buffer which is %d",grainframes, b_frames);
				  	grains[j].active = 0;
				  	goto nextgrain;
				}
				if(minskip > b_frames - grainframes){//bad minskip
				  	error("minskip time is illegal");
				  	grains[j].phase = 0.0;
				  	grains[j].endframe = grainframes - 1;
				} else {
					if(maxskip > b_frames - grainframes){
					  	grains[j].phase = multigrain_boundrand((float)minskip, (float) (b_frames - grainframes));
					  	//post("1. minskip %d maxskip %d",minskip,b_frames - grainframes);
					} else {
					  	grains[j].phase = multigrain_boundrand((float)minskip, (float)maxskip);
					  	//post("2. minskip %d maxskip %d",minskip,maxskip);
					}
					grains[j].endframe = grains[j].phase + grainframes - 1;
				}
				
				
				if( multigrain_boundrand(0.0,1.0) < retro_odds){//go backwards - make sure to test both boundaries
				  	grains[j].si *= -1.0;
				  	tmp = grains[j].phase;
				  	grains[j].phase = grains[j].endframe;
				  	grains[j].endframe = tmp;
				}
				/*post("grain: grainframes %d phase %f endframe %f amp %f",
				 grainframes, grains[j].phase, grains[j].endframe, grains[j].amplitude);*/
				grains[j].active = 1;
    			inserted = 1;
    			goto nextgrain;
    		}
		}
		if(!inserted){
			error("could not insert grain with increment %f",grains[j].si);
			return;
		}
	nextgrain: ;
	}
}
/********************************************************************************
 void grainstream_initGrain()
 
 inputs:			x					-- pointer to this object
 in_freq			-- frequency of grain production
 in_pos_start		-- offset within sampled buffer
 in_pitch_mult		-- sample playback speed, 1 = normal
 in_gain_mult		-- scales gain output, 1 = no change
 description:	initializes grain vars; called from perform method when pulse is
 received
 returns:		nothing
 ********************************************************************************/
void grainstream_initGrain(t_grainstream *x, float in_freq, float in_pos_start, float in_pitch_mult, float in_gain_mult)
{
    #ifdef DEBUG
        post("%s: initializing grain", OBJECT_NAME);
    #endif /* DEBUG */
    
    /* should the buffers be updated ? */
    
    t_buffer_obj	*snd_object;
    t_buffer_obj	*win_object;
    
    if (x->next_snd_buf_ptr != NULL) {
        x->snd_buf_ptr = x->next_snd_buf_ptr;
        x->next_snd_buf_ptr = NULL;
        
        #ifdef DEBUG
            post("%s: sound buffer pointer updated", OBJECT_NAME);
        #endif /* DEBUG */
    }
    if (x->next_win_buf_ptr != NULL) {
        x->win_buf_ptr = x->next_win_buf_ptr;
        x->next_win_buf_ptr = NULL;
        
        #ifdef DEBUG
            post("%s: window buffer pointer updated", OBJECT_NAME);
        #endif /* DEBUG */
    }
    
    snd_object = buffer_ref_getobject(x->snd_buf_ptr);
    win_object = buffer_ref_getobject(x->win_buf_ptr);
    
    /* should input variables be at audio or control rate ? */
    
    x->grain_freq = x->grain_freq_connected ? in_freq : x->next_grain_freq;
    
    // temporarily stash here as milliseconds
    x->grain_pos_start = x->grain_pos_start_connected ? in_pos_start : x->next_grain_pos_start;
    
    x->grain_pitch = x->grain_pitch_connected ? in_pitch_mult : x->next_grain_pitch;
    
    x->grain_gain = x->grain_gain_connected ? in_gain_mult : x->next_grain_gain;
    
    /* compute dependent variables */
    
    // grain_freq must be positive and above 0.01 Hz or 1.66 min duration
    if (x->grain_freq < 0.) x->grain_freq *= -1;
    if (x->grain_freq < 0.01) x->grain_freq = 0.01;
    x->grain_length = 1000. / x->grain_freq;
    
    // compute window buffer step size per vector sample
    x->win_step_size = (double)(buffer_getframecount(win_object)) * x->grain_freq * x->output_1oversr;
    if (x->win_step_size < 0.) x->win_step_size *= -1.; // needs to be positive to prevent buffer overruns
    
    // compute sound buffer step size per vector sample
    x->snd_step_size = x->grain_pitch * buffer_getsamplerate(snd_object) * x->output_1oversr;
    if (x->snd_step_size < 0.) x->snd_step_size *= -1.; // needs to be positive to prevent buffer overruns
    
    // compute amount of sound file for grain
    x->grain_sound_length = x->grain_length * x->grain_pitch;
    if (x->grain_sound_length < 0.) x->grain_sound_length *= -1.; // needs to be positive to prevent buffer overruns
    
    // update direction option
    x->grain_direction = x->next_grain_direction;
    
    if (x->grain_direction == FORWARD_GRAINS) {	// if forward...
        x->grain_pos_start = x->grain_pos_start * buffer_getmillisamplerate(snd_object);
        x->curr_snd_pos = x->grain_pos_start - x->snd_step_size;
    } else {	// if reverse...
        x->grain_pos_start = (x->grain_pos_start + x->grain_sound_length) * buffer_getmillisamplerate(snd_object);
        x->curr_snd_pos = x->grain_pos_start + x->snd_step_size;
    }
    
    x->curr_win_pos = 0.0;
    
    // reset history
    x->curr_count_samp = -1;
    
    #ifdef DEBUG
        post("%s: beginning of grain", OBJECT_NAME);
        post("%s: win step size = %f samps", OBJECT_NAME, x->win_step_size);
        post("%s: snd step size = %f samps", OBJECT_NAME, x->snd_step_size);
    #endif /* DEBUG */
    
    return;
    
}
/********************************************************************************
 void *grainstream_perform64()
 
 inputs:	x		--
 dsp64   --
 ins     --
 numins  --
 outs    --
 numouts --
 vectorsize --
 flags   --
 userparam  --
 description:	called at interrupt level to compute object's output at 64-bit
 returns:		nothing
 ********************************************************************************/
void grainstream_perform64(t_grainstream *x, t_object *dsp64, double **ins, long numins, double **outs,
                          long numouts, long vectorsize, long flags, void *userparam)
{
    // local vars outlets and inlets
    t_double *in_freq = ins[0];
    t_double *in_sound_start = ins[1];
    t_double *in_sample_increment = ins[2];
    t_double *in_gain = ins[3];
    t_double *out_signal = outs[0];
    t_double *out_signal2 = outs[1];
    t_double *out_sample_count = outs[2];
    
    // local vars for snd and win buffer
    t_buffer_obj *snd_object, *win_object;
    t_float *tab_s, *tab_w;
    double snd_out, win_out;
    long size_s, size_w;
    
    // local vars for object vars and while loop
    double index_s, index_w, temp_index_frac;
    long n, count_samp, temp_index_int;
    double s_step_size, w_step_size, w_last_index, g_gain;
    short interp_s, interp_w, g_direction;
    
    // check to make sure buffers are loaded with proper file types
    if (x->x_obj.z_disabled)		// and object is enabled
        goto out;
    if (x->snd_buf_ptr == NULL || (x->win_buf_ptr == NULL))
        goto zero;
    
    // get sound buffer info
    snd_object = buffer_ref_getobject(x->snd_buf_ptr);
    tab_s = buffer_locksamples(snd_object);
    if (!tab_s)		// buffer samples were not accessible
        goto zero;
    size_s = buffer_getframecount(snd_object);
    
    // get window buffer info
    win_object = buffer_ref_getobject(x->win_buf_ptr);
    tab_w = buffer_locksamples(win_object);
    if (!tab_w)		// buffer samples were not accessible
        goto zero;
    size_w = buffer_getframecount(win_object);
    
    // get snd and win index info
    index_s = x->curr_snd_pos;
    s_step_size = x->snd_step_size;
    index_w = x->curr_win_pos;
    w_step_size = x->win_step_size;
    
    // get grain options
    interp_s = x->snd_interp;
    interp_w = x->win_interp;
    g_gain = x->grain_gain;
    g_direction = x->grain_direction;
    
    // get history from last vector
    count_samp = x->curr_count_samp;
    w_last_index = x->win_last_index;
    
    n = vectorsize;
    while(n--) {
        
        // advance window index
        index_w += w_step_size;
        
        // wrap to make index in bounds
        while (index_w < 0.)
            index_w += size_w;
        while (index_w >= size_w)
            index_w -= size_w;
        
        if (index_w < w_last_index) {   // if window has wrapped...
            if (index_w < 10.0) {       // and it is beginning...
                buffer_unlocksamples(snd_object);
                buffer_unlocksamples(win_object);
                
                grainstream_initGrain(x, *in_freq, *in_sound_start, *in_sample_increment, *in_gain);
                
                // get snd buffer info
                snd_object = buffer_ref_getobject(x->snd_buf_ptr);
                tab_s = buffer_locksamples(snd_object);
                if (!tab_s)	{	// buffer samples were not accessible
                    *out_signal = 0.0;
                    *out_signal2 = 0.0;
                    *out_sample_count = (double)count_samp;
                    w_last_index = index_w;
                    goto advance_pointers;
                }
                size_s = buffer_getframecount(snd_object);
                
                // get win buffer info
                win_object = buffer_ref_getobject(x->win_buf_ptr);
                tab_w = buffer_locksamples(win_object);
                if (!tab_w)	{	// buffer samples were not accessible
                    *out_signal = 0.0;
                    *out_signal2 = 0.0;
                    *out_sample_count = (double)count_samp;
                    w_last_index = index_w;
                    goto advance_pointers;
                }
                size_w = buffer_getframecount(win_object);
                
                // get snd and win index info
                index_s = x->curr_snd_pos;
                s_step_size = x->snd_step_size;
                index_w = x->curr_win_pos;
                w_step_size = x->win_step_size;
                
                // get grain options
                interp_s = x->snd_interp;
                interp_w = x->win_interp;
                g_gain = x->grain_gain;
                g_direction = x->grain_direction;
                
                // get history
                count_samp = x->curr_count_samp;
            }
        }
        
        // if we made it here, then we actually start counting
        ++count_samp;
        
        // advance sound index
        if (g_direction == FORWARD_GRAINS) {
            index_s += s_step_size;     // addition
        } else {
            index_s -= s_step_size;     // subtract
        }
        
        // wrap to make index in bounds
        while (index_s < 0.)
            index_s += size_s;
        while (index_s >= size_s)
            index_s -= size_s;
        
        // WINDOW OUT
        
        // compute temporary vars for interpolation
        temp_index_int = (long)(index_w); // integer portion of index
        temp_index_frac = index_w - (double)temp_index_int; // fractional portion of index
        
        // get value from win buffer samples
        if (interp_w == INTERP_ON) {
            win_out = mcLinearInterp(tab_w, temp_index_int, temp_index_frac, size_w, 1);
        } else {
            win_out = tab_w[temp_index_int];
        }
        
        // SOUND OUT
        
        // compute temporary vars for interpolation
        temp_index_int = (long)(index_s); // integer portion of index
        temp_index_frac = index_s - (double)temp_index_int; // fractional portion of index
        
        // get value from snd buffer samples
        if (interp_s == INTERP_ON) {
            snd_out = mcLinearInterp(tab_s, temp_index_int, temp_index_frac, size_s, 1);
        } else {
            snd_out = tab_s[temp_index_int];
        }
        
        // OUTLETS
        
        *out_signal = snd_out * win_out * g_gain;
        *out_signal2 = 0.;
        *out_sample_count = (double)count_samp;
        
        // update vars for last output
        w_last_index = index_w;
    
advance_pointers:
        // advance all pointers
        ++in_freq, ++in_sound_start, ++in_sample_increment, ++in_gain;
        ++out_signal, ++out_signal2, ++out_sample_count;
    }

    // update object history for next vector
    x->curr_snd_pos = index_s;
    x->curr_win_pos = index_w;
    x->curr_count_samp = count_samp;
    x->win_last_index = w_last_index;

    buffer_unlocksamples(snd_object);
    buffer_unlocksamples(win_object);
    return;

    // alternate blank output
zero:
    n = vectorsize;
    while(n--)
    {
        *out_signal = 0.;
        *out_signal2 = 0.;
        *out_sample_count = -1.;
    }

out:
    return;
}
/********************************************************************************
t_int *grainstream_perform(t_int *w)

inputs:			w		-- array of signal vectors specified in "grainstream_dsp"
description:	called at interrupt level to compute object's output; used when
		outlets are connected; tests inlet 2 & 3 to use either control or audio
		rate data
returns:		pointer to the next 
********************************************************************************/
t_int *grainstream_perform(t_int *w)
{
	t_grainstream *x = (t_grainstream *)(w[1]);
	float *in_freq = (float *)(w[2]);
	float *in_pos_start = (float *)(w[3]);
	float *in_pitch_mult = (float *)(w[4]);
	float *out = (t_float *)(w[5]);
	int vec_size = (int)(w[6]);
	float out_1oversr = (float)x->output_1oversr;
	
	t_buffer_obj *snd_object, *win_object;
	float *tab_s, *tab_w;
	double s_step_size, w_step_size;
	double  snd_out, win_out;//, last_s, last_w;	//removed 2005.02.03
	double index_s, index_w, last_index_w, temp_index_frac;
	long size_s, size_w, temp_index_int;
	short interp_s, interp_w, g_direction;
	
	vec_size += 1;		//increase by one for pre-decrement
	--out;				//decrease by one for pre-increment
	
	if (x->x_obj.z_disabled)					// object is enabled
		goto out;
    if ((x->snd_buf_ptr == NULL) || (x->win_buf_ptr == NULL))		// buffer pointers are defined
        goto zero;
	
    // get sound buffer info
    snd_object = buffer_ref_getobject(x->snd_buf_ptr);
    tab_s = buffer_locksamples(snd_object);
    if (!tab_s)		// buffer samples were not accessible
        goto zero;
    size_s = buffer_getframecount(snd_object);
    
    // get window buffer info
    win_object = buffer_ref_getobject(x->win_buf_ptr);
    tab_w = buffer_locksamples(win_object);
    if (!tab_w)		// buffer samples were not accessible
        goto zero;
    size_w = buffer_getframecount(win_object);
	
	// get option settings
	interp_s = x->snd_interp;
	interp_w = x->win_interp;
	g_direction = x->grain_direction;
	// get pointer info
	s_step_size = x->snd_step_size;
	w_step_size = x->win_step_size;
	index_s = x->curr_snd_pos;
	index_w = x->curr_win_pos;
	// history
	last_index_w = x->win_last_index;
	
	while (--vec_size) {
		index_w += w_step_size;
		
		/* check bounds of window index */
		while (index_w < 0)
			index_w += size_w;
		while (index_w >= size_w)
			index_w -= size_w;
			
		if (index_w < last_index_w) {		// if window has wrapped...
			if (index_w < 10.0) {			// and is at beginning...
				// ...then begin a new grain
				
				if (x->next_snd_buf_ptr != NULL) {	//added 2002.07.24
                    buffer_unlocksamples(snd_object);
                    x->snd_buf_ptr = x->next_snd_buf_ptr;
                    x->next_snd_buf_ptr = NULL;
                    
                    snd_object = buffer_ref_getobject(x->snd_buf_ptr);
                    tab_s = buffer_locksamples(snd_object);
                    if (!tab_s)		// buffer samples were not accessible
                        goto zero;
                    size_s = buffer_getframecount(snd_object);
					
					#ifdef DEBUG
						post("%s: sound buffer pointer updated", OBJECT_NAME);
					#endif /* DEBUG */
				}
				if (x->next_win_buf_ptr != NULL) {	//added 2002.07.24
                    buffer_unlocksamples(win_object);
                    x->win_buf_ptr = x->next_win_buf_ptr;
                    x->next_win_buf_ptr = NULL;
                    
                    win_object = buffer_ref_getobject(x->win_buf_ptr);
                    tab_w = buffer_locksamples(win_object);
                    if (!tab_w)	{	// buffer samples were not accessible
                        goto zero;
                    }
                    size_w = buffer_getframecount(win_object);
					
					#ifdef DEBUG
						post("%s: window buffer pointer updated", OBJECT_NAME);
					#endif /* DEBUG */
				}
				
				//
				//
				
				x->grain_direction = x->next_grain_direction;
				g_direction = x->grain_direction;
				
				// test if freq should be at audio or control rate
				if (x->grain_freq_connected) { // if freq is at audio rate
					if (*in_freq != 0.0) x->grain_freq = *in_freq;
				} else { // if freq is at control rate
					if (x->next_grain_freq != 0.0) x->grain_freq = x->next_grain_freq;
				}
				x->grain_length = 1000.0 / x->grain_freq;
				
				// test if pitch should be at audio or control rate
				if (x->grain_pitch_connected) { // if pitch is at audio rate
					x->grain_pitch = *in_pitch_mult;
				} else { // if pitch is at control rate
					x->grain_pitch = x->next_grain_pitch;
				}
				x->grain_sound_length = x->grain_length * x->grain_pitch;
				
				// test if pos_start should be at audio or control rate
				if (x->grain_pos_start_connected) { // if position is at audio rate
					if (x->grain_direction == FORWARD_GRAINS) {	// if forward...
						x->grain_pos_start = *in_pos_start * buffer_getmillisamplerate(snd_object);
					} else {	// if reverse...
						x->grain_pos_start = (*in_pos_start + x->grain_sound_length) * buffer_getmillisamplerate(snd_object);
					}
				} else { // if position is at control rate
					if (x->grain_direction == FORWARD_GRAINS) {	// if forward...
						x->grain_pos_start = x->next_grain_pos_start * buffer_getmillisamplerate(snd_object);
					} else {	// if reverse...
						x->grain_pos_start = (x->next_grain_pos_start + x->grain_sound_length) * buffer_getmillisamplerate(snd_object);
					}
				}
				// compute window buffer step size per vector sample 
				x->win_step_size = size_w * x->grain_freq * out_1oversr;
				// compute sound buffer step size per vector sample
				x->snd_step_size = x->grain_pitch * buffer_getsamplerate(snd_object) * out_1oversr;
				// reset position tracking variables
				if (x->grain_direction == FORWARD_GRAINS) {	// if forward...
					x->curr_snd_pos = x->grain_pos_start - x->snd_step_size;
				} else {	// if reverse...
					x->curr_snd_pos = x->grain_pos_start + x->snd_step_size;
				}
				x->curr_win_pos = 0.0;
				// reset history
				//x->snd_last_out = x->win_last_out = 0.0;	//removed 2005.02.03
				
				// update local vars
				s_step_size = x->snd_step_size;
				w_step_size = x->win_step_size;
				index_s = x->curr_snd_pos;
				index_w = x->curr_win_pos;
				
				#ifdef DEBUG
					post("%s: beginning of grain", OBJECT_NAME);
				#endif /* DEBUG */
					
			}
		}
		
		/* sound index is a double because it uses interp */
		if (g_direction == FORWARD_GRAINS) {	// if forward...
			index_s += s_step_size;		// add to sound index
		} else {	// if reverse...
			index_s -= s_step_size;		// subtract from sound index
		}
		
		/* check bounds of sound index */
		while (index_s < 0)
			index_s += size_s;
		while (index_s >= size_s)
			index_s -= size_s;
		
		//WINDOW OUT
		
		/* handle temporary vars for interpolation */
		temp_index_int = (long)(index_w); // integer portion of index
		temp_index_frac = index_w - (double)temp_index_int; // fractional portion of index
		
		/*
		if (nc_w > 1) // if buffer has multiple channels...
		{
			// get index to sample from within the interleaved frame
			temp_index_int = temp_index_int * nc_w + chan_w;
		}
		*/
		
		switch (interp_w) {
			case INTERP_ON:
				// perform linear interpolation on window buffer output
				win_out = mcLinearInterp(tab_w, temp_index_int, temp_index_frac, size_w, 1);
				break;
			case INTERP_OFF:
				// interpolation sounds better than following, but uses more CPU
				win_out = tab_w[temp_index_int];
				break;
		}
		
		//SOUND OUT
		
		/* handle temporary vars for interpolation */
		temp_index_int = (long)(index_s); // integer portion of index
		temp_index_frac = index_s - (double)temp_index_int; // fractional portion of index
		
		/*
		if (nc_s > 1) // if buffer has multiple channels...
		{
			// get index to sample from within the interleaved frame
			temp_index_int = temp_index_int * nc_s + chan_s;
		}
		*/
		
		switch (interp_s) {
			case INTERP_ON:
				// perform linear interpolation on sound buffer output
				snd_out = mcLinearInterp(tab_s, temp_index_int, temp_index_frac, size_s, 1);
				break;
			case INTERP_OFF:
				// interpolation sounds better than following, but uses more CPU
				snd_out = tab_s[temp_index_int];
				break;
		}
		
		/* multiply snd_out by win_out */
		*++out = snd_out * win_out;
		
		/* update last output variables */
		//last_s = snd_out;	//removed 2005.02.03
		//last_w = win_out;	//removed 2005.02.03
		last_index_w = index_w;
		
		/* advance other pointers */
		++in_freq, ++in_pos_start, ++in_pitch_mult;
	}
	
	/* update global position and step_size vars */
	x->curr_snd_pos = index_s;
	x->curr_win_pos = index_w;
	x->snd_step_size = s_step_size;
	x->win_step_size = w_step_size;
	
	/* update last output variables */
	//x->snd_last_out = last_s;	//removed 2005.02.03
	//x->win_last_out = last_w;	//removed 2005.02.03
	x->win_last_index = index_w;
	
    buffer_unlocksamples(snd_object);
    buffer_unlocksamples(win_object);
	
	return (w + 7);
	
zero:
	while (--vec_size >= 0) *++out = 0.;
out:
	return (w + 7);
}
Exemple #14
0
void polywave_perform64(t_polywave *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
{

    int i;
    t_double		*out = outs[0];
    t_double		*in1 = ins[0];
    t_double		*in2 = ins[1];
    int	n = sampleframes;

    if(x->numbufs == 0 || !x->w_connected[0])
    {
        while (n--)
            *out++ = 0.;
        return;
    }

    int             idx_connected = x->w_connected[1];
    long            numbufs = x->numbufs;
    long            frames[numbufs], nchans[numbufs];

    t_buffer_obj    *buffer[numbufs];
    t_float         *tab[numbufs];
    int             valid[numbufs], modified[numbufs];
    
    

    for (i=0; i<numbufs; i++) {
        buffer[i] = buffer_ref_getobject(x->buf_proxy[i]->ref);
        
        if(!buffer[i])
            valid[i] = 0;
        else
        {
            tab[i] = buffer_locksamples(buffer[i]);
            
            if(!tab[i])
                valid[i] = 0;
            else
            {
                modified[i] = x->buf_proxy[i]->buffer_modified;

                if(modified[i])
                {
                    frames[i] = buffer_getframecount(buffer[i]);
                    nchans[i] = buffer_getchannelcount(buffer[i]);
                    x->buf_proxy[i]->nframes = frames[i];
                    x->buf_proxy[i]->nchans = nchans[i];
                    x->buf_proxy[i]->buffer_modified = false;
                }
                else
                {
                    frames[i] = x->buf_proxy[i]->nframes;
                    nchans[i] = x->buf_proxy[i]->nchans;
                }
     
                valid[i] = (nchans[i] > 0 && frames[i] > 0);

            }
        }
    }

    t_polywave_interp interp = x->interp_type;
   
    double p, pSamp, upperVal, lowerSamp, upperSamp, frac, a, b, c, d;
    long  bindx = 0;
    
    switch (interp) {
        case CUBIC:
            while(n--)
            {
                p = *in1++;
                p = CLAMP(p, 0, 1);
                
                if(idx_connected)
                {
                    bindx = (long)*in2++;
                    bindx = CLAMP(bindx, 0, numbufs-1);
                }
                
                
                if(valid[bindx])
                {
                    pSamp = frames[bindx] * p;
                    lowerSamp = floor(pSamp);
                    frac = pSamp - lowerSamp;
                    
                    a = (long)lowerSamp - 1 < 0 ? 0 : tab[bindx][ nchans[bindx] * ((long)lowerSamp - 1)];
                    b = tab[bindx][ nchans[bindx] * (long)lowerSamp];
                    c = (long)lowerSamp + 1 > frames[bindx] ? 0 : tab[bindx][ nchans[bindx] * ((long)lowerSamp + 1)];
                    d = (long)lowerSamp + 2 > frames[bindx] ? 0 : tab[bindx][ nchans[bindx] * ((long)lowerSamp + 2)];
                    
                    
                    *out++ = cubicInterpolate(a,b,c,d,frac);
                    
                }
                else
                    *out++ = 0.0;
            }
            break;
        case LINEAR:
            while(n--)
            {
                p = *in1++;
                p = CLAMP(p, 0, 1);
                
                if(idx_connected)
                {
                    bindx = (long)*in2++;
                    bindx = CLAMP(bindx, 0, numbufs-1);
                }
                
                if(valid[bindx])
                {
                    pSamp = frames[bindx] * p;
                    lowerSamp = floor(pSamp);
                    upperSamp = ceil(pSamp);
                    upperVal = (upperSamp < frames[bindx]) ? tab[bindx][ nchans[bindx] * (long)upperSamp ] : 0.0;
                    
                    *out++ = linear_interp(tab[bindx][ nchans[bindx] * (long)lowerSamp  ], upperVal, pSamp - lowerSamp);
                }
                else
                    *out++ = 0.0;
                
            }
            break;
        default:
        case NONE:
            while(n--)
            {
                p = *in1++;
                p = CLAMP(p, 0, 1);
                
                if(idx_connected)
                {
                    bindx = (long)*in2++;
                    bindx = CLAMP(bindx, 0, numbufs-1);
                }
                
                if(valid[bindx])
                {
                    *out++ = tab[bindx][nchans[bindx] * (long)(frames[bindx] * p)];
                }
                else
                    *out++ = 0.0;
                
            }
            break;
    }
    
    for(i=0; i<numbufs; i++)
    {
        if(valid[i])
            buffer_unlocksamples(buffer[i]);
    }

    return;
    
}
void cmbuffercloud_perform64(t_cmbuffercloud *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam) {
	// VARIABLE DECLARATIONS
	short trigger = 0; // trigger occurred yes/no
	long i, limit; // for loop counterS
	long n = sampleframes; // number of samples per signal vector
	double tr_curr; // current trigger value
	double distance; // floating point index for reading from buffers
	long index; // truncated index for reading from buffers
	double w_read, b_read; // current sample read from the window buffer
	double outsample_left = 0.0; // temporary left output sample used for adding up all grain samples
	double outsample_right = 0.0; // temporary right output sample used for adding up all grain samples
	int slot = 0; // variable for the current slot in the arrays to write grain info to
	cm_panstruct panstruct; // struct for holding the calculated constant power left and right stereo values
	
	// OUTLETS
	t_double *out_left 	= (t_double *)outs[0]; // assign pointer to left output
	t_double *out_right = (t_double *)outs[1]; // assign pointer to right output
	
	// BUFFER VARIABLE DECLARATIONS
	t_buffer_obj *buffer = buffer_ref_getobject(x->buffer);
	t_buffer_obj *w_buffer = buffer_ref_getobject(x->w_buffer);
	float *b_sample = buffer_locksamples(buffer);
	float *w_sample = buffer_locksamples(w_buffer);
	long b_framecount; // number of frames in the sample buffer
	long w_framecount; // number of frames in the window buffer
	t_atom_long b_channelcount; // number of channels in the sample buffer
	t_atom_long w_channelcount; // number of channels in the window buffer
	
	// BUFFER CHECKS
	if (!b_sample || !w_sample) { // if the sample buffer does not exist
		goto zero;
	}
	
	// GET BUFFER INFORMATION
	b_framecount = buffer_getframecount(buffer); // get number of frames in the sample buffer
	w_framecount = buffer_getframecount(w_buffer); // get number of frames in the window buffer
	b_channelcount = buffer_getchannelcount(buffer); // get number of channels in the sample buffer
	w_channelcount = buffer_getchannelcount(w_buffer); // get number of channels in the sample buffer
	
	// GET INLET VALUES
	t_double *tr_sigin 	= (t_double *)ins[0]; // get trigger input signal from 1st inlet
	
	x->grain_params[0] = x->connect_status[0] ? *ins[1] * x->m_sr : x->object_inlets[0] * x->m_sr;	// start min
	x->grain_params[1] = x->connect_status[1] ? *ins[2] * x->m_sr : x->object_inlets[1] * x->m_sr;	// start max
	x->grain_params[2] = x->connect_status[2] ? *ins[3] * x->m_sr : x->object_inlets[2] * x->m_sr;	// length min
	x->grain_params[3] = x->connect_status[3] ? *ins[4] * x->m_sr : x->object_inlets[3] * x->m_sr;	// length max
	x->grain_params[4] = x->connect_status[4] ? *ins[5] : x->object_inlets[4];						// pitch min
	x->grain_params[5] = x->connect_status[5] ? *ins[6] : x->object_inlets[5];						// pitch max
	x->grain_params[6] = x->connect_status[6] ? *ins[7] : x->object_inlets[6];						// pan min
	x->grain_params[7] = x->connect_status[7] ? *ins[8] : x->object_inlets[7];						// pan max
	x->grain_params[8] = x->connect_status[8] ? *ins[9] : x->object_inlets[8];						// gain min
	x->grain_params[9] = x->connect_status[9] ? *ins[10] : x->object_inlets[9];						// gain max
	
	
	// DSP LOOP
	while (n--) {
		tr_curr = *tr_sigin++; // get current trigger value
		
		if (x->attr_zero) {
			if (signbit(tr_curr) != signbit(x->tr_prev)) { // zero crossing from negative to positive
				trigger = 1;
			}
			else if (x->bang_trigger) {
				trigger = 1;
				x->bang_trigger = 0;
			}
		}
		else {
			if (x->tr_prev > tr_curr) {
				trigger = 1;
			}
			else if (x->bang_trigger) {
				trigger = 1;
				x->bang_trigger = 0;
			}
		}
		
		if (x->buffer_modified) { // reset all playback information when any of the buffers was modified
			for (i = 0; i < MAXGRAINS; i++) {
				x->busy[i] = 0;
			}
			x->grains_count = 0;
			x->buffer_modified = 0;
		}
		/************************************************************************************************************************/
		// IN CASE OF TRIGGER, LIMIT NOT MODIFIED AND GRAINS COUNT IN THE LEGAL RANGE (AVAILABLE SLOTS)
		if (trigger && x->grains_count < x->grains_limit && !x->limit_modified) { // based on zero crossing --> when ramp from 0-1 restarts.
			trigger = 0; // reset trigger
			x->grains_count++; // increment grains_count
			// FIND A FREE SLOT FOR THE NEW GRAIN
			i = 0;
			while (i < x->grains_limit) {
				if (!x->busy[i]) {
					x->busy[i] = 1;
					slot = i;
					break;
				}
				i++;
			}
			
			// randomize the grain parameters and write them into the randomized array
			x->randomized[0] = cm_random(&x->grain_params[0], &x->grain_params[1]); // start
			x->randomized[1] = cm_random(&x->grain_params[2], &x->grain_params[3]); // length
			x->randomized[2] = cm_random(&x->grain_params[4], &x->grain_params[5]); // pitch
			x->randomized[3] = cm_random(&x->grain_params[6], &x->grain_params[7]); // pan
			x->randomized[4] = cm_random(&x->grain_params[8], &x->grain_params[9]); // gain
			
			// check for parameter sanity of the length value
			if (x->randomized[1] < x->testvalues[2]) {
				x->randomized[1] = x->testvalues[2];
			}
			else if (x->randomized[1] > x->testvalues[3]) {
				x->randomized[1] = x->testvalues[3];
			}
			
			// check for parameter sanity of the pitch value
			if (x->randomized[2] < x->testvalues[4]) {
				x->randomized[2] = x->testvalues[4];
			}
			else if (x->randomized[2] > x->testvalues[5]) {
				x->randomized[2] = x->testvalues[5];
			}
			
			// check for parameter sanity of the pan value
			if (x->randomized[3] < x->testvalues[6]) {
				x->randomized[3] = x->testvalues[6];
			}
			else if (x->randomized[3] > x->testvalues[7]) {
				x->randomized[3] = x->testvalues[7];
			}
			
			// check for parameter sanity of the gain value
			if (x->randomized[4] < x->testvalues[8]) {
				x->randomized[4] = x->testvalues[8];
			}
			else if (x->randomized[4] > x->testvalues[9]) {
				x->randomized[4] = x->testvalues[9];
			}
			
			// write grain lenght slot (non-pitch)
			x->smp_length[slot] = x->randomized[1];
			x->pitch_length[slot] = x->smp_length[slot] * x->randomized[2]; // length * pitch
			// check that grain length is not larger than size of buffer
			if (x->pitch_length[slot] > b_framecount) {
				x->pitch_length[slot] = b_framecount;
			}
			// write start position
			x->start[slot] = x->randomized[0];
			// start position sanity testing
			if (x->start[slot] > b_framecount - x->pitch_length[slot]) {
				x->start[slot] = b_framecount - x->pitch_length[slot];
			}
			if (x->start[slot] < 0) {
				x->start[slot] = 0;
			}
			// compute pan values
			cm_panning(&panstruct, &x->randomized[3], x); // calculate pan values in panstruct
			x->pan_left[slot] = panstruct.left;
			x->pan_right[slot] = panstruct.right;
			// write gain value
			x->gain[slot] = x->randomized[4];
		}
		/************************************************************************************************************************/
		// CONTINUE WITH THE PLAYBACK ROUTINE
		if (x->grains_count == 0 || !b_sample || !w_sample) { // if grains count is zero, there is no playback to be calculated
			*out_left++ = 0.0;
			*out_right++ = 0.0;
		}
		else {
			if (x->limit_modified) {
				limit = x->grains_limit_old;
			}
			else {
				limit = x->grains_limit;
			}
			for (i = 0; i < limit; i++) {
				if (x->busy[i]) { // if the current slot contains grain playback information
					// GET WINDOW SAMPLE FROM WINDOW BUFFER
					if (x->attr_winterp) {
						distance = ((double)x->grainpos[i] / (double)x->smp_length[i]) * (double)w_framecount;
						w_read = cm_lininterp(distance, w_sample, w_channelcount, 0);
					}
					else {
						index = (long)(((double)x->grainpos[i] / (double)x->smp_length[i]) * (double)w_framecount);
						w_read = w_sample[index];
					}
					// GET GRAIN SAMPLE FROM SAMPLE BUFFER
					distance = x->start[i] + (((double)x->grainpos[i]++ / (double)x->smp_length[i]) * (double)x->pitch_length[i]);
					
					if (b_channelcount > 1 && x->attr_stereo) { // if more than one channel
						if (x->attr_sinterp) {
							outsample_left += ((cm_lininterp(distance, b_sample, b_channelcount, 0) * w_read) * x->pan_left[i]) * x->gain[i]; // get interpolated sample
							outsample_right += ((cm_lininterp(distance, b_sample, b_channelcount, 1) * w_read) * x->pan_right[i]) * x->gain[i];
						}
						else {
							outsample_left += ((b_sample[(long)distance * b_channelcount] * w_read) * x->pan_left[i]) * x->gain[i];
							outsample_right += ((b_sample[((long)distance * b_channelcount) + 1] * w_read) * x->pan_right[i]) * x->gain[i];
						}
					}
					else {
						if (x->attr_sinterp) {
							b_read = cm_lininterp(distance, b_sample, b_channelcount, 0) * w_read; // get interpolated sample
							outsample_left += (b_read * x->pan_left[i]) * x->gain[i];
							outsample_right += (b_read * x->pan_right[i]) * x->gain[i];
						}
						else {
							outsample_left += ((b_sample[(long)distance * b_channelcount] * w_read) * x->pan_left[i]) * x->gain[i];
							outsample_right += ((b_sample[(long)distance * b_channelcount] * w_read) * x->pan_right[i]) * x->gain[i];
						}
					}
					if (x->grainpos[i] == x->smp_length[i]) { // if current grain has reached the end position
						x->grainpos[i] = 0; // reset parameters for overwrite
						x->busy[i] = 0;
						x->grains_count--;
						if (x->grains_count < 0) {
							x->grains_count = 0;
						}
					}
				}
			}
			*out_left++ = outsample_left; // write added sample values to left output vector
			*out_right++ = outsample_right; // write added sample values to right output vector
		}
		// CHECK IF GRAINS COUNT IS ZERO, THEN RESET LIMIT_MODIFIED CHECKFLAG
		if (x->grains_count == 0) {
			x->limit_modified = 0; // reset limit modified checkflag
		}
		
		/************************************************************************************************************************/
		x->tr_prev = tr_curr; // store current trigger value in object structure
		outsample_left = 0.0;
		outsample_right = 0.0;
	}
	
	/************************************************************************************************************************/
	// STORE UPDATED RUNNING VALUES INTO THE OBJECT STRUCTURE
	buffer_unlocksamples(buffer);
	buffer_unlocksamples(w_buffer);
	outlet_int(x->grains_count_out, x->grains_count); // send number of currently playing grains to the outlet
	return;
	
zero:
	while (n--) {
		*out_left++ = 0.0;
		*out_right++ = 0.0;
	}
	buffer_unlocksamples(buffer);
	buffer_unlocksamples(w_buffer);
	return; // THIS RETURN WAS MISSING FOR A LONG, LONG TIME. MAYBE THIS HELPS WITH STABILITY!?
}
void buffi_perform64(t_buffi *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
{
    t_double	*in = ins[0];
    t_double	*out = outs[0];
    t_float		*src1tab,*src2tab,*desttab;
    long src1nc, src2nc, destnc;
    long src1frames, src2frames, destframes;
    double		phase;
    int i,j;
//    int k;
    long dexter;
    float hybrid; // Max buffers are still 32-bit
    
    t_buffer_obj	*src1 = buffer_ref_getobject(x->src1_buffer_ref);
    t_buffer_obj	*src2 = buffer_ref_getobject(x->src2_buffer_ref);
    t_buffer_obj	*dest = buffer_ref_getobject(x->dest_buffer_ref);
    
    src1tab = buffer_locksamples(src1);
    src2tab = buffer_locksamples(src2);
    desttab = buffer_locksamples(dest);
    if (!src1tab || !src2tab || !desttab){
        goto zero;

    }
    src1frames = buffer_getframecount(src1);
    src1nc = buffer_getchannelcount(src1);
    src2frames = buffer_getframecount(src2);
    src2nc = buffer_getchannelcount(src2);
    destframes = buffer_getframecount(dest);
    destnc = buffer_getchannelcount(dest);
    
    // test for lengths match (otherwise jet)
    
    if( (src1frames != destframes) || (src2frames != destframes) ){
        goto zero;
    }
    
    // test for channels match

    if( (src1nc != src2nc) || (src2nc != destnc) ){
        goto zero;
    }
    
    phase = *in; // only read the first sample of the vector

  
    for(i = 0; i < src1frames; i++){
        for(j = 0; j < src1nc; j++){
            dexter = (i*src1nc) + j;
            hybrid = (src1tab[dexter] * phase) + (src2tab[dexter] * (1 - phase));
            desttab[dexter] = hybrid;
        }
    }

    
    buffer_unlocksamples(src1);
    buffer_unlocksamples(src2);
    buffer_unlocksamples(dest);
    return;
zero:
    for(i = 0; i < sampleframes; i++){
        *out++ = 0.0;
    }
}
void cmgrainlabs_perform64(t_cmgrainlabs *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam) {
	// VARIABLE DECLARATIONS
	short trigger = 0; // trigger occurred yes/no
	long i, limit; // for loop counterS
	long n = sampleframes; // number of samples per signal vector
	double tr_curr; // current trigger value
	double pan; // temporary random pan information
	double pitch; // temporary pitch for new grains
	double distance; // floating point index for reading from buffers
	long index; // truncated index for reading from buffers
	double w_read, b_read; // current sample read from the window buffer
	double outsample_left = 0.0; // temporary left output sample used for adding up all grain samples
	double outsample_right = 0.0; // temporary right output sample used for adding up all grain samples
	int slot = 0; // variable for the current slot in the arrays to write grain info to
	cm_panstruct panstruct; // struct for holding the calculated constant power left and right stereo values
	
	// OUTLETS
	t_double *out_left 	= (t_double *)outs[0]; // assign pointer to left output
	t_double *out_right = (t_double *)outs[1]; // assign pointer to right output
	
	// BUFFER VARIABLE DECLARATIONS
	t_buffer_obj *buffer = buffer_ref_getobject(x->buffer);
	t_buffer_obj *w_buffer = buffer_ref_getobject(x->w_buffer);
	float *b_sample = buffer_locksamples(buffer);
	float *w_sample = buffer_locksamples(w_buffer);
	long b_framecount; // number of frames in the sample buffer
	long w_framecount; // number of frames in the window buffer
	t_atom_long b_channelcount; // number of channels in the sample buffer
	t_atom_long w_channelcount; // number of channels in the window buffer
	
	// BUFFER CHECKS
	if (!b_sample) { // if the sample buffer does not exist
		goto zero;
	}
	if (!w_sample) { // if the window buffer does not exist
		goto zero;
	}
		
	// GET BUFFER INFORMATION
	b_framecount = buffer_getframecount(buffer); // get number of frames in the sample buffer
	w_framecount = buffer_getframecount(w_buffer); // get number of frames in the window buffer
	b_channelcount = buffer_getchannelcount(buffer); // get number of channels in the sample buffer
	w_channelcount = buffer_getchannelcount(w_buffer); // get number of channels in the sample buffer
		
	// GET INLET VALUES
	t_double *tr_sigin 	= (t_double *)ins[0]; // get trigger input signal from 1st inlet
	t_double startmin 	= x->connect_status[0]? *ins[1] * x->m_sr : x->startmin_float * x->m_sr; // get start min input signal from 2nd inlet
	t_double startmax 	= x->connect_status[1]? *ins[2] * x->m_sr : x->startmax_float * x->m_sr; // get start max input signal from 3rd inlet
	t_double lengthmin 	= x->connect_status[2]? *ins[3] * x->m_sr : x->lengthmin_float * x->m_sr; // get grain min length input signal from 4th inlet
	t_double lengthmax 	= x->connect_status[3]? *ins[4] * x->m_sr : x->lengthmax_float * x->m_sr; // get grain max length input signal from 5th inlet
	t_double pitchmin 	= x->connect_status[4]? *ins[5] : x->pitchmin_float; // get pitch min input signal from 6th inlet
	t_double pitchmax 	= x->connect_status[5]? *ins[6] : x->pitchmax_float; // get pitch max input signal from 7th inlet
	t_double panmin 	= x->connect_status[6]? *ins[7] : x->panmin_float; // get min pan input signal from 8th inlet
	t_double panmax 	= x->connect_status[7]? *ins[8] : x->panmax_float; // get max pan input signal from 9th inlet
	t_double gainmin 	= x->connect_status[8]? *ins[9] : x->gainmin_float; // get min gain input signal from 10th inlet
	t_double gainmax 	= x->connect_status[9]? *ins[10] : x->gainmax_float; // get max gain input signal from 10th inlet
	
	// DSP LOOP
	while (n--) {
		tr_curr = *tr_sigin++; // get current trigger value
		
		if (x->attr_zero) {
			if (tr_curr > 0.0 && x->tr_prev < 0.0) { // zero crossing from negative to positive
				trigger = 1;
			}
		}
		else {
			if ((x->tr_prev - tr_curr) > 0.9) {
				trigger = 1;
			}
		}
		
		if (x->buffer_modified) { // reset all playback information when any of the buffers was modified
			for (i = 0; i < MAXGRAINS; i++) {
				x->busy[i] = 0;
			}
			x->grains_count = 0;
			x->buffer_modified = 0;
		}
		/************************************************************************************************************************/
		// IN CASE OF TRIGGER, LIMIT NOT MODIFIED AND GRAINS COUNT IN THE LEGAL RANGE (AVAILABLE SLOTS)
		if (trigger && x->grains_count < x->grains_limit && !x->limit_modified) { // based on zero crossing --> when ramp from 0-1 restarts.
			trigger = 0; // reset trigger
			x->grains_count++; // increment grains_count
			// FIND A FREE SLOT FOR THE NEW GRAIN
			i = 0;
			while (i < x->grains_limit) {
				if (!x->busy[i]) {
					x->busy[i] = 1;
					slot = i;
					break;
				}
				i++;
			}
			/************************************************************************************************************************/
			// GET RANDOM START POSITION
			if (startmin != startmax) { // only call random function when min and max values are not the same!
				x->start[slot] = (long)cm_random(&startmin, &startmax);
			}
			else {
				x->start[slot] = startmin;
			}
			/************************************************************************************************************************/
			// GET RANDOM LENGTH
			if (lengthmin != lengthmax) { // only call random function when min and max values are not the same!
				x->t_length[slot] = (long)cm_random(&lengthmin, &lengthmax);
			}
			else {
				x->t_length[slot] = lengthmin;
			}
			// CHECK IF THE VALUE FOR PERCEPTIBLE GRAIN LENGTH IS LEGAL
			if (x->t_length[slot] > MAX_GRAINLENGTH * x->m_sr) { // if grain length is larger than the max grain length
				x->t_length[slot] = MAX_GRAINLENGTH * x->m_sr; // set grain length to max grain length
			}
			else if (x->t_length[slot] < MIN_GRAINLENGTH * x->m_sr) { // if grain length is samller than the min grain length
				x->t_length[slot] = MIN_GRAINLENGTH * x->m_sr; // set grain length to min grain length
			}
			/************************************************************************************************************************/
			// GET RANDOM PAN
			if (panmin != panmax) { // only call random function when min and max values are not the same!
				pan = cm_random(&panmin, &panmax);
			}
			else {
				pan = panmin;
			}
			// SOME SANITY TESTING
			if (pan < -1.0) {
				pan = -1.0;
			}
			if (pan > 1.0) {
				pan = 1.0;
			}
			cm_panning(&panstruct, &pan); // calculate pan values in panstruct
			x->pan_left[slot] = panstruct.left;
			x->pan_right[slot] = panstruct.right;
			/************************************************************************************************************************/
			// GET RANDOM PITCH
			if (pitchmin != pitchmax) { // only call random function when min and max values are not the same!
				pitch = cm_random(&pitchmin, &pitchmax);
			}
			else {
				pitch = pitchmin;
			}
			// CHECK IF THE PITCH VALUE IS LEGAL
			if (pitch < 0.001) {
				pitch = 0.001;
			}
			if (pitch > MAX_PITCH) {
				pitch = MAX_PITCH;
			}
			/************************************************************************************************************************/
			// GET RANDOM GAIN
			if (gainmin != gainmax) {
				x->gain[slot] = cm_random(&gainmin, &gainmax);
			}
			else {
				x->gain[slot] = gainmin;
			}
			// CHECK IF THE GAIN VALUE IS LEGAL
			if (x->gain[slot] < 0.0) {
				x->gain[slot] = 0.0;
			}
			if (x->gain[slot] > MAX_GAIN) {
				x->gain[slot] = MAX_GAIN;
			}
			/************************************************************************************************************************/
			// CALCULATE THE ACTUAL GRAIN LENGTH (SAMPLES) ACCORDING TO PITCH
			x->gr_length[slot] = x->t_length[slot] * pitch;
			// CHECK THAT GRAIN LENGTH IS NOT LARGER THAN SIZE OF BUFFER
			if (x->gr_length[slot] > b_framecount) {
				x->gr_length[slot] = b_framecount;
			}
			/************************************************************************************************************************/
			// CHECK IF START POSITION IS LEGAL ACCORDING TO GRAINzLENGTH (SAMPLES) AND BUFFER SIZE
			if (x->start[slot] > b_framecount - x->gr_length[slot]) {
				x->start[slot] = b_framecount - x->gr_length[slot];
			}
			if (x->start[slot] < 0) {
				x->start[slot] = 0;
			}
		}
		/************************************************************************************************************************/
		// CONTINUE WITH THE PLAYBACK ROUTINE
		if (x->grains_count == 0) { // if grains count is zero, there is no playback to be calculated
			*out_left++ = 0.0;
			*out_right++ = 0.0;
		}
		else if (!b_sample) {
			*out_left++ = 0.0;
			*out_right++ = 0.0;
		}
		else if (!w_sample) {
			*out_left++ = 0.0;
			*out_right++ = 0.0;
		}
		else {
			if (x->limit_modified) {
				limit = x->grains_limit_old;
			}
			else {
				limit = x->grains_limit;
			}
			for (i = 0; i < limit; i++) {
				if (x->busy[i]) { // if the current slot contains grain playback information
					// GET WINDOW SAMPLE FROM WINDOW BUFFER
					if (x->attr_winterp) {
						distance = ((double)x->grainpos[i] / (double)x->t_length[i]) * (double)w_framecount;
						w_read = cm_lininterp(distance, w_sample, w_channelcount, 0);
					}
					else {
						index = (long)(((double)x->grainpos[i] / (double)x->t_length[i]) * (double)w_framecount);
						w_read = w_sample[index];
					}
					// GET GRAIN SAMPLE FROM SAMPLE BUFFER
					distance = x->start[i] + (((double)x->grainpos[i]++ / (double)x->t_length[i]) * (double)x->gr_length[i]);
					
					if (b_channelcount > 1 && x->attr_stereo) { // if more than one channel
						if (x->attr_sinterp) {
							outsample_left += ((cm_lininterp(distance, b_sample, b_channelcount, 0) * w_read) * x->pan_left[i]) * x->gain[i]; // get interpolated sample
							outsample_right += ((cm_lininterp(distance, b_sample, b_channelcount, 1) * w_read) * x->pan_right[i]) * x->gain[i];
						}
						else {
							outsample_left += ((b_sample[(long)distance * b_channelcount] * w_read) * x->pan_left[i]) * x->gain[i];
							outsample_right += ((b_sample[((long)distance * b_channelcount) + 1] * w_read) * x->pan_right[i]) * x->gain[i];
						}
					}
					else {
						if (x->attr_sinterp) {
							b_read = cm_lininterp(distance, b_sample, b_channelcount, 0) * w_read; // get interpolated sample
							outsample_left += (b_read * x->pan_left[i]) * x->gain[i];
							outsample_right += (b_read * x->pan_right[i]) * x->gain[i];
						}
						else {
							outsample_left += ((b_sample[(long)distance * b_channelcount] * w_read) * x->pan_left[i]) * x->gain[i];
							outsample_right += ((b_sample[(long)distance * b_channelcount] * w_read) * x->pan_right[i]) * x->gain[i];
						}
					}
					if (x->grainpos[i] == x->t_length[i]) { // if current grain has reached the end position
						x->grainpos[i] = 0; // reset parameters for overwrite
						x->busy[i] = 0;
						x->grains_count--;
						if (x->grains_count < 0) {
							x->grains_count = 0;
						}
					}
				}
			}
			*out_left++ = outsample_left; // write added sample values to left output vector
			*out_right++ = outsample_right; // write added sample values to right output vector
		}
		// CHECK IF GRAINS COUNT IS ZERO, THEN RESET LIMIT_MODIFIED CHECKFLAG
		if (x->grains_count == 0) {
			x->limit_modified = 0; // reset limit modified checkflag
		}
		
		/************************************************************************************************************************/
		x->tr_prev = tr_curr; // store current trigger value in object structure
		outsample_left = 0.0;
		outsample_right = 0.0;
	}
	
	/************************************************************************************************************************/
	// STORE UPDATED RUNNING VALUES INTO THE OBJECT STRUCTURE
	buffer_unlocksamples(buffer);
	buffer_unlocksamples(w_buffer);
	outlet_int(x->grains_count_out, x->grains_count); // send number of currently playing grains to the outlet
	return;
	
zero:
	while (n--) {
		*out_left++ = 0.0;
		*out_right++ = 0.0;
	}
	buffer_unlocksamples(buffer);
	buffer_unlocksamples(w_buffer);
	return; // THIS RETURN WAS MISSING FOR A LONG, LONG TIME. MAYBE THIS HELPS WITH STABILITY!?
}
Exemple #18
0
void pokef_perform64(t_pokef *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
{
    float *in = (float *)(ins[0]);
    t_double *index = (t_double *)(ins[1]);
    t_double *fcoeff = (t_double *)(ins[2]);
    t_double *out = (t_double *)(outs[0]);
    int n = sampleframes;
    
    double alpha, om_alpha;
    
	t_float *tab;
	t_double temp, input, coeff;
	t_double chan, frames, nc, length;
	
	long pokef, pokef_next, pokef_nextnext, pokef_nextnextnext;
	
	t_buffer_obj *buffer = buffer_ref_getobject(x->l_buffer);
	
	tab = buffer_locksamples(buffer);
	if (!tab)
		goto zero;
	
	chan = (t_double)x->l_chan;
	frames = buffer_getframecount(buffer);
	nc = buffer_getchannelcount(buffer);
	length = (t_double)x->length;
	if (length <= 0.) length = frames;
	else if (length >= frames) length = frames;
	
	while (n--) {
		input 	= *in++;
		temp 	= *index++;
		coeff 	= *fcoeff++;
        
		temp += 0.5;
		
		if (temp < 0.)
			temp = 0.;
		else while (temp >= length)
			temp -= length;
        
		temp = temp * nc + chan;
        
		pokef = (long)temp;
		//bufsample = tab[pokef];
        
		alpha = temp - (double)pokef;
		om_alpha = 1. - alpha;
		
		pokef_next = pokef + nc;
		while (pokef_next >= length*nc) pokef_next -= length*nc;
		pokef_nextnext = pokef_next + nc;
		while (pokef_nextnext >= length*nc) pokef_nextnext -= length*nc;
		pokef_nextnextnext = pokef_nextnext + nc;
		while (pokef_nextnextnext >= length*nc) pokef_nextnextnext -= length*nc;
		
		//output two ahead of record point...., with interpolation
		//*out++ = tab[pokef_nextnext]*om_alpha + tab[pokef_nextnextnext]*alpha;
		//*out++ = tab[pokef_next]*om_alpha + tab[pokef_nextnext]*alpha;
		*out++ = tab[pokef_next];
		
		//interpolate recording...
		//tab[pokef] = coeff * tab[pokef] + om_alpha*input;
		//tab[pokef_next] = coeff * tab[pokef_next] + alpha*input;
		//or not....
		tab[pokef] = coeff * tab[pokef] + input;
        
		//*out++ = bufsample;
		//tab[pokef] = coeff * bufsample + input;
        
	}
	buffer_unlocksamples(buffer);
	return;
zero:
	while (n--)
		*out++ = 0.0;
}
Exemple #19
0
void munger_perform64(t_munger *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
{
	t_double *in = (t_double *)(ins[0]);
	
	t_double grate 		= x->grate_connected? 		*(t_double *)(ins[0]) : x->grate;
	t_double grate_var 	= x->grate_var_connected? 	*(t_double *)(ins[1]) : x->grate_var;
	t_double glen 		= x->glen_connected? 		*(t_double *)(ins[2]) : x->glen;
	t_double glen_var 	= x->glen_var_connected? 	*(t_double *)(ins[3]) : x->glen_var;
	t_double gpitch 	= x->gpitch_connected? 		*(t_double *)(ins[4]) : x->gpitch;
	t_double gpitch_var	= x->gpitch_var_connected? 	*(t_double *)(ins[5]) : x->gpitch_var;
	t_double gpan_spread= x->gpan_spread_connected? *(t_double *)(ins[6]) : x->gpan_spread;
	
	t_double outsamp[MAXCHANNELS], samp;
	int newvoice, i, j;
	long n;
	t_double *out[MAXCHANNELS];
	//t_double *outL = (t_double *)(w[10]);
	//t_double *outR = (t_double *)(w[11]);
	
	for (i=0;i<x->num_channels;i++) {
		out[i] = (t_double *)(outs[i]);
	}
	n = sampleframes;
	
	//make sure vars are updated if signals are connected; stupid, lazy, boob.
	x->grate = grate;
	x->grate_var = grate_var;
	x->glen = glen;
	x->glen_var = glen_var;
	x->gpitch = gpitch;
	x->gpitch_var = gpitch_var;
	x->gpan_spread = gpan_spread;
		
	//grate = grate + RAND01 * grate_var;
	//grate = grate + ((t_double)rand() - 16384.) * ONE_OVER_HALFRAND * grate_var;
	//gimme = x->srate_ms * grate; //grate is actually time-distance between grains

	if(gpan_spread > 1.) gpan_spread = 1.;
	if(gpan_spread < 0.) gpan_spread = 0.;

	if(!x->power) {
		while(n--) { 	//copy and zero out when unpowered (this is slightly less efficient than
						//the z_disabled approach, but some users expect it now
			for(i=0;i<x->num_channels;i++) {
				*out[i]++ = 0.;
			}
		}
	}
	else {
		t_buffer_obj	*buffer = buffer_ref_getobject(x->l_buffer);
		t_float			*tab = buffer_locksamples(buffer);
		double			frames = 0;
		double			nc = 0;

		if (tab) {
			frames = buffer_getframecount(buffer);
			nc = buffer_getchannelcount(buffer);
		}
		
		while(n--) {
			//outsampL = outsampR = 0.;
			for(i=0;i<x->num_channels;i++) outsamp[i] = 0.;
			
			//record a sample
			//if(x->recordOn) recordSamp(x, *in++);
			recordSamp(x, *in++);
			
			//grab a note if requested; works in oneshot mode or otherwise
			while(x->newnote > 0) {
				newvoice = findVoice(x);
				if(newvoice >= 0) {
					x->gvoiceCurrent[newvoice] = newNote(x, newvoice, x->newnote, frames);
				}
				x->newnote--;
			}
			
			//find a voice if it's time (high resolution). ignore if in "oneshot" mode		
			if(!x->oneshot) {
				if(x->time >= (long)x->gimme) {
					x->time = 0;
					newvoice = findVoice(x);
					if(newvoice >= 0) {
						x->gvoiceCurrent[newvoice] = newSetup(x, newvoice, frames);
					}
					grate = grate + ((t_double)rand() - RAND_MAX * 0.5) * ONE_OVER_HALFRAND * grate_var;
					x->gimme = x->srate_ms * grate; //grate is actually time-distance between grains
				}
			} 
			x->time++;
			
			//mix 'em, pan 'em
			for(i=0; i< x->maxvoices; i++) {
			//for(i=0; i<x->voices; i++) {
				if(x->gvoiceOn[i]) {
					//get a sample, envelope it
					if(x->externalBuffer) samp = getExternalSamp(x, x->gvoiceCurrent[i], tab, frames, nc);
					else samp = getSamp(x, x->gvoiceCurrent[i]);
					if (!x->gvoiceADSRon[i]) samp = envelope(x, i, samp) * x->gvoiceGain[i];
					else samp = samp * ADSR_ADRtick(&x->gvoiceADSR[i]) * x->gvoiceGain[i];
					
					//pan it
					if(x->num_channels == 2) {
						outsamp[0] += samp * x->gvoiceLPan[i];
						outsamp[1] += samp * x->gvoiceRPan[i];
					}
					else { //multichannel subroutine
						for(j=0;j<x->num_channels;j++) {
							outsamp[j] += samp * x->gvoiceSpat[i][j];
						}
					}
					
					//see if grain is done after jumping to next sample point
					x->gvoiceCurrent[i] += (double)x->gvoiceDirection[i] * (double)x->gvoiceSpeed[i];
					if (!x->gvoiceADSRon[i]) {
						if(++x->gvoiceDone[i] >= x->gvoiceSize[i]) x->gvoiceOn[i] = 0;
					}
					else {
						if(ADSR_getState(&x->gvoiceADSR[i]) == DONE) x->gvoiceOn[i] = 0;
					}
				}
			}
			for(i=0;i<x->num_channels;i++) {
				*out[i]++ = outsamp[i];
			}
		}
		if (tab)
			buffer_unlocksamples(buffer);
	}
}
void multigrain_perform64(t_multigrain *x, t_object *dsp64, double **ins,
                         long numins, double **outs,long numouts, long n,
                         long flags, void *userparam)
{
    t_buffer_obj *wavebuf_b;
    t_buffer_obj *windowbuf_b;
    float *wavetable;
    float *window;
    t_grain *grains = x->grains;
    long b_nchans;
    long b_frames;
    short interpolate_envelope = x->interpolate_envelope;
    float sample1;
    float envelope;
    float amplitude;
    float si;
    float esi;
    float phase;
    float ephase;
    long delay;
    long eframes;
    long current_index;
    float tsmp1, tsmp2;
    float frac;
    int i,j,k;
    long output_channel; // randomly selected channel for output

 // we really need this clean operation:
    for(i = 0; i < x->output_channels; i++){
        for(j = 0; j < n; j++){
            outs[i][j] = 0.0;
        }
    }
    
    buffer_ref_set(x->wavebuf, x->wavename);
    buffer_ref_set(x->windowbuf, x->windowname);
    wavebuf_b = buffer_ref_getobject(x->wavebuf);
    windowbuf_b = buffer_ref_getobject(x->windowbuf);
    if(wavebuf_b == NULL || windowbuf_b == NULL){
        for(k = 0; k < MAXGRAINS; k++){
            grains[k].active = 0;
        }
        goto deliverance;
    }
    b_nchans = buffer_getchannelcount(wavebuf_b);
    b_frames= buffer_getframecount(wavebuf_b);
    eframes = buffer_getframecount(windowbuf_b);
    if(b_nchans != 1){
        goto deliverance;
    }
    if(eframes == 0 || b_frames == 0){
        for(k = 0; k < MAXGRAINS; k++){
            grains[k].active = 0;
        }
        goto deliverance;
    }
    wavetable = buffer_locksamples(wavebuf_b);
    window = buffer_locksamples(windowbuf_b);
    if(!wavetable || !window ){
        goto deliverance;
    }

    
    for (j=0; j<MAXGRAINS; j++) {
        
        if(!grains[j].active){
            goto nextgrain;
        }
        amplitude = grains[j].amplitude;
        si =  grains[j].si;
        esi = grains[j].esi;
        phase =  grains[j].phase;
        ephase = grains[j].ephase;
        delay =  grains[j].delay;
        output_channel = grains[j].output_channel;
        
        for(i = 0; i < n; i++ ){
            
            if( delay > 0 ){
                --delay;
            }
            if( delay <= 0 && ephase < eframes){
                
                if(interpolate_envelope){
                    current_index = floor((double)ephase);
                    frac = ephase - current_index;
                    if(current_index == 0 || current_index == eframes - 1 || frac == 0.0){// boundary conditions
                        envelope = window[current_index];
                    } else {
                        tsmp1 = window[current_index];
                        tsmp2 = window[current_index + 1];
                        envelope = tsmp1 + frac * (tsmp2 - tsmp1);
                    }
                } else {
                    envelope = window[(int)ephase];
                }

                if(phase < 0 || phase >= b_frames){
                    error("phase %f is out of bounds",phase);
                    goto nextgrain;
                }
                current_index = floor((double)phase);
                frac = phase - current_index;
                if(current_index == 0 || current_index == b_frames - 1 || frac == 0.0){// boundary conditions
                    sample1 = wavetable[current_index] * amplitude; // amplitude * is new code
                } else {
                    tsmp1 = wavetable[current_index];
                    tsmp2 = wavetable[current_index + 1];
                    sample1 = tsmp1 + frac * (tsmp2 - tsmp1);
                }
                sample1 *= envelope;
                outs[output_channel][i] += sample1;


                
                phase += si;
                if(phase < 0 || phase >= b_frames){
                    // error("phase %f out of bounds",phase);
                    grains[j].active = 0;
                    goto nextgrain;
                }
                ephase += esi;
                
                
                if( ephase >= eframes ){
                    grains[j].active = 0;
                    goto nextgrain; // must escape loop now
                }
                
            }
        }
        grains[j].phase = phase;
        grains[j].ephase = ephase;
        grains[j].delay = delay;
        
    nextgrain: ;
    }
deliverance:
    buffer_unlocksamples(wavebuf_b);
    buffer_unlocksamples(windowbuf_b);
    ;
}
Exemple #21
0
void polywave_perform64_two(t_polywave *x, t_object *dsp64, double **ins, long numins, double **outs, long numouts, long sampleframes, long flags, void *userparam)
{
    
    int i;
    t_double		*out = outs[0];
    t_double		*x1_in = ins[0];
    t_double		*x2_in = ins[1];
    t_double        *interp_in = ins[2];
    t_double		*idx1_in = ins[3];
    t_double		*idx2_in = ins[4];
    int	n = sampleframes;
    
    if(x->numbufs == 0 || !x->w_connected[0])
    {
        while (n--)
            *out++ = 0.;
        return;
    }
    
    int             *connected = x->w_connected;

    long            numbufs = x->numbufs;
    long            frames[numbufs], nchans[numbufs];
    
    t_buffer_obj    *buffer[numbufs];
    t_float         *tab[numbufs];
    int             valid[numbufs], modified[numbufs];
    
    t_polywave_interp interp_t = x->interp_type;
   // post("%d %d", x->interp_type, x->backup);
    
    for (i=0; i<numbufs; i++) {
        buffer[i] = buffer_ref_getobject(x->buf_proxy[i]->ref);
        
        if(!buffer[i])
            valid[i] = 0;
        else
        {
            tab[i] = buffer_locksamples(buffer[i]);
            
            if(!tab[i])
                valid[i] = 0;
            else
            {
                modified[i] = x->buf_proxy[i]->buffer_modified;
                
                if(modified[i])
                {
                    frames[i] = buffer_getframecount(buffer[i]);
                    nchans[i] = buffer_getchannelcount(buffer[i]);
                    x->buf_proxy[i]->nframes = frames[i];
                    x->buf_proxy[i]->nchans = nchans[i];
                    x->buf_proxy[i]->buffer_modified = false;
                }
                else
                {
                    frames[i] = x->buf_proxy[i]->nframes;
                    nchans[i] = x->buf_proxy[i]->nchans;
                }
                
                valid[i] = (nchans[i] > 0 && frames[i] > 0);
                
            }
        }
    }
    
    double x1_p, x2_p, interp_p = 0, pSamp1, pSamp2, upperVal, lowerSamp, upperSamp, frac, a1, a2, b, c, d;
    long  idx1 = 0, idx2 = 0;
    
    switch (interp_t) {
        case CUBIC:
            while(n--)
            {
                x1_p = *x1_in++;
                x1_p = CLAMP(x1_p, 0, 1);
                
                if(connected[1])
                {
                    x2_p = *x2_in++;
                    x2_p = CLAMP(x2_p, 0, 1);
                } else {
                    x2_p = x1_p;
                }
                
                if (connected[2]) {
                    interp_p = *interp_in++;
                    interp_p = CLAMP(interp_p, 0, 1);
                }
                
                if(connected[3])
                {
                    idx1 = (long)*idx1_in++;
                    idx1 = CLAMP(idx1, 0, numbufs-1);
                }
                
                if(connected[4])
                {
                    idx2 = (long)*idx2_in++;
                    idx2 = CLAMP(idx2, 0, numbufs-1);
                }
                
                if(valid[idx1] && valid[idx2])
                {
                    pSamp1 = frames[idx1] * x1_p;
                    lowerSamp = floor(pSamp1);
                    frac = pSamp1 - lowerSamp;
                    
                    a1 = (long)lowerSamp - 1 < 0 ? 0 : tab[idx1][ nchans[idx1] * ((long)lowerSamp - 1)];
                    b = tab[idx1][ nchans[idx1] * (long)lowerSamp];
                    c = (long)lowerSamp + 1 > frames[idx1] ? 0 : tab[idx1][ nchans[idx1] * ((long)lowerSamp + 1)];
                    d = (long)lowerSamp + 2 > frames[idx1] ? 0 : tab[idx1][ nchans[idx1] * ((long)lowerSamp + 2)];
                    
                    pSamp1 = cubicInterpolate(a1,b,c,d,frac);
                    
                    pSamp2 = frames[idx2] * x2_p;
                    lowerSamp = floor(pSamp2);
                    frac = pSamp2 - lowerSamp;
                    
                    a2 = (long)lowerSamp - 1 < 0 ? 0 : tab[idx2][ nchans[idx2] * ((long)lowerSamp - 1)];
                    b = tab[idx2][ nchans[idx2] * (long)lowerSamp];
                    c = (long)lowerSamp + 1 > frames[idx2] ? 0 : tab[idx2][ nchans[idx2] * ((long)lowerSamp + 1)];
                    d = (long)lowerSamp + 2 > frames[idx2] ? 0 : tab[idx2][ nchans[idx2] * ((long)lowerSamp + 2)];
                    
                    pSamp2 = cubicInterpolate(a2,b,c,d,frac);
                    
                    *out++ = cubicInterpolate(a1,pSamp1,pSamp2,d,interp_p);
                }
                else
                    *out++ = 0.0;
            }
            break;
        case LINEAR:
            while(n--)
            {
                x1_p = *x1_in++;
                x1_p = CLAMP(x1_p, 0, 1);
                
                if(connected[1])
                {
                    x2_p = *x2_in++;
                    x2_p = CLAMP(x2_p, 0, 1);
                } else {
                    x2_p = x1_p;
                }
                
                if (connected[2]) {
                    interp_p = *interp_in++;
                    interp_p = CLAMP(interp_p, 0, 1);
                }
                
                if(connected[3])
                {
                    idx1 = (long)*idx1_in++;
                    idx1 = CLAMP(idx1, 0, numbufs-1);
                }
                
                if(connected[4])
                {
                    idx2 = (long)*idx2_in++;
                    idx2 = CLAMP(idx2, 0, numbufs-1);
                }

                
                if(valid[idx1] && valid[idx2])
                {
                    pSamp1 = frames[idx1] * x1_p;
                    lowerSamp = floor(pSamp1);
                    upperSamp = ceil(pSamp1);
                    upperVal = (upperSamp < frames[idx1]) ? tab[idx1][ nchans[idx1] * (long)upperSamp ] : 0.0;
                    
                    pSamp1 = linear_interp(tab[idx1][ nchans[idx1] * (long)lowerSamp  ], upperVal, pSamp1 - lowerSamp);

                    pSamp2 = frames[idx2] * x2_p;
                    lowerSamp = floor(pSamp2);
                    upperSamp = ceil(pSamp2);
                    upperVal = (upperSamp < frames[idx2]) ? tab[idx2][ nchans[idx2] * (long)upperSamp ] : 0.0;
                    
                    pSamp2 = linear_interp(tab[idx2][ nchans[idx2] * (long)lowerSamp  ], upperVal, pSamp2 - lowerSamp);

                    *out++ = linear_interp(pSamp1, pSamp2, interp_p);
                }
                else
                    *out++ = 0.0;
                
            }
            break;
        default:
        case NONE:
            while(n--)
            {
                x1_p = *x1_in++;
                x1_p = CLAMP(x1_p, 0, 1);
                
                if(connected[2])
                {
                    idx1 = (long)*idx1_in++;
                    idx1 = CLAMP(idx1, 0, numbufs-1);
                }
                
                if(valid[idx1])
                {
                    *out++ = tab[idx1][nchans[idx1] * (long)(frames[idx1] * x1_p)];
                }
                else
                    *out++ = 0.0;
                
            }
            break;
    }
    
    for(i=0; i<numbufs; i++)
    {
        if(valid[i])
            buffer_unlocksamples(buffer[i]);
    }
    
    return;
    
}