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 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"); }; } }
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); ; }
/******************************************************************************** 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); }
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 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 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; }
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 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!? }
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 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 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; }