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