Max 5 API Reference
00001 /** 00002 @file 00003 simpwave~ - a simple wavetable oscillator using buffer~ 00004 00005 @ingroup examples 00006 */ 00007 00008 #include "ext.h" 00009 #include "z_dsp.h" 00010 #include "math.h" 00011 #include "buffer.h" 00012 #include "ext_atomic.h" 00013 #include "ext_obex.h" 00014 00015 #ifdef WIN_VERSION 00016 #define snprintf _snprintf 00017 #endif // WIN_VERSION 00018 00019 static t_class *s_simpwave_class; 00020 00021 typedef struct _simpwave 00022 { 00023 t_pxobject w_obj; 00024 t_buffer *w_buf; 00025 t_symbol *w_name; 00026 long w_begin; 00027 long w_len; 00028 float w_start; 00029 float w_end; 00030 float w_msr; 00031 long w_nchans; 00032 short w_connected[2]; 00033 long w_bframes; 00034 long w_bmodtime; 00035 } t_simpwave; 00036 00037 t_int *simpwave_perform1(t_int *w); 00038 void simpwave_dsp(t_simpwave *x, t_signal **sp, short *count); 00039 void simpwave_assist(t_simpwave *x, void *b, long m, long a, char *s); 00040 void simpwave_dblclick(t_simpwave *x); 00041 void simpwave_setup(t_simpwave *x, t_symbol *s, double sr); 00042 void simpwave_limits(t_simpwave *x, t_buffer *b); 00043 void simpwave_set(t_simpwave *x, t_symbol *s, long ac, t_atom *av); 00044 void simpwave_float(t_simpwave *x, double f); 00045 void simpwave_int(t_simpwave *x, long n); 00046 void *simpwave_new(t_symbol *s, long argc, t_atom *argv); 00047 00048 t_symbol *ps_nothing, *ps_buffer; 00049 00050 int main(void) 00051 { 00052 t_class *c; 00053 00054 c = class_new("simpwave~", (method)simpwave_new, (method)dsp_free, sizeof(t_simpwave), 0L, 00055 A_GIMME, 0); 00056 class_addmethod(c, (method)simpwave_dsp, "dsp", A_CANT, 0); 00057 class_addmethod(c, (method)simpwave_float, "float", A_FLOAT, 0); 00058 class_addmethod(c, (method)simpwave_int, "int", A_LONG, 0); 00059 class_addmethod(c, (method)simpwave_set, "set", A_GIMME, 0); 00060 class_addmethod(c, (method)simpwave_assist, "assist", A_CANT, 0); 00061 class_addmethod(c, (method)simpwave_dblclick, "dblclick", A_CANT, 0); 00062 00063 class_dspinit(c); 00064 class_register(CLASS_BOX, c); 00065 s_simpwave_class = c; 00066 00067 ps_nothing = gensym(""); 00068 ps_buffer = gensym("buffer~"); 00069 00070 return 0; 00071 } 00072 00073 t_int *simpwave_perform1(t_int *w) 00074 { 00075 t_float *in = (t_float *)(w[1]); 00076 t_float *out = (t_float *)(w[2]); 00077 t_simpwave *x = (t_simpwave *)(w[3]); 00078 t_float min = x->w_connected[0]? (*(t_float *)(w[4])) : x->w_start; 00079 t_float max = x->w_connected[1]? (*(t_float *)(w[5])) : x->w_end; 00080 int n = w[6]; 00081 float *b; 00082 long len,dex,framesize; 00083 double v; 00084 00085 if (x->w_obj.z_disabled) 00086 goto out; 00087 if (!x->w_buf) 00088 goto zero; 00089 ATOMIC_INCREMENT(&x->w_buf->b_inuse); 00090 if (!x->w_buf->b_valid) { 00091 ATOMIC_DECREMENT(&x->w_buf->b_inuse); 00092 goto zero; 00093 } 00094 b = x->w_buf->b_samples; 00095 framesize = x->w_buf->b_nchans; 00096 if ((x->w_bframes != x->w_buf->b_frames)|| 00097 (x->w_bmodtime != x->w_buf->b_modtime)) 00098 { // buffer has changed 00099 simpwave_limits(x,x->w_buf); 00100 if (!x->w_connected[0]) 00101 min = x->w_start; 00102 if (!x->w_connected[1]) 00103 max = x->w_end; 00104 } 00105 if (min != x->w_start || max != x->w_end) { 00106 if (min < 0.) 00107 min = 0.; 00108 if (max < 0.) 00109 max = 0.; 00110 if (min > max) 00111 x->w_end = x->w_start = min; 00112 else { 00113 x->w_start = min; 00114 x->w_end = max; 00115 } 00116 simpwave_limits(x,x->w_buf); 00117 } 00118 b += x->w_begin; 00119 len = x->w_len; 00120 00121 if (framesize == 1) { 00122 while (n--) { 00123 v = *in++; 00124 if (v < 0) 00125 v = 0; 00126 if (v > 1) 00127 v = 1; 00128 dex = v * (double)len; 00129 if (dex>len-1) 00130 dex = len-1; 00131 *out++ = b[dex]; 00132 } 00133 } else if (framesize > 1) { 00134 while (n--) { 00135 v = *in++; 00136 if (v < 0) 00137 v = 0; 00138 if (v > 1) 00139 v = 1; 00140 dex = (long)(v * (double)len) * framesize; 00141 if (dex>(len-1)*framesize) 00142 dex = (len-1)*framesize; 00143 *out++ = b[dex]; 00144 } 00145 } 00146 ATOMIC_DECREMENT(&x->w_buf->b_inuse); 00147 return (w + 7); 00148 zero: 00149 while (n--) *out++ = 0.; 00150 out: 00151 return (w + 7); 00152 } 00153 00154 void simpwave_dsp(t_simpwave *x, t_signal **sp, short *count) 00155 { 00156 simpwave_setup(x,x->w_name,sp[0]->s_sr); 00157 x->w_connected[0] = count[1]; 00158 x->w_connected[1] = count[2]; 00159 if (x->w_nchans == 1) 00160 dsp_add(simpwave_perform1, 6, sp[0]->s_vec, sp[3]->s_vec, x, sp[1]->s_vec, sp[2]->s_vec, sp[0]->s_n); 00161 else 00162 object_error((t_object *)x, "too simple for your buffer~"); 00163 // just in case buffer was added after float message received 00164 simpwave_limits(x,x->w_buf); 00165 } 00166 00167 void simpwave_setup(t_simpwave *x, t_symbol *s, double sr) 00168 { 00169 t_buffer *b; 00170 00171 if (sr) 00172 x->w_msr = sr * .001; 00173 if (s != ps_nothing) { 00174 if ((b = (t_buffer *)(s->s_thing)) && ob_sym(b) == ps_buffer) { 00175 simpwave_limits(x,b); 00176 x->w_buf = b; 00177 } else 00178 x->w_buf = 0; 00179 } else 00180 x->w_buf = 0; 00181 x->w_name = s; 00182 } 00183 00184 void simpwave_limits(t_simpwave *x, t_buffer *b) 00185 { 00186 long framesize; 00187 00188 if (b) { 00189 framesize = b->b_nchans; // floats in a frame, not bytes 00190 00191 x->w_bframes = b->b_frames; 00192 x->w_bmodtime = b->b_modtime; 00193 00194 x->w_begin = (long)(x->w_start * b->b_msr) * framesize;//buffer sr-jkc 00195 if (!x->w_end) {// use entire table, eek! 00196 x->w_len = b->b_frames; 00197 } else { 00198 x->w_len = (x->w_end - x->w_start) * b->b_msr; //buffer sr-jkc 00199 } 00200 // now restrict these values 00201 if (x->w_begin < 0) 00202 x->w_begin = 0; 00203 else if (x->w_begin >= b->b_frames * framesize) 00204 x->w_begin = (b->b_frames - 1) * framesize; 00205 if (x->w_begin + (x->w_len * framesize) >= b->b_frames * framesize) { 00206 x->w_len = b->b_frames - (x->w_begin / framesize); 00207 } 00208 } 00209 } 00210 00211 void simpwave_set(t_simpwave *x, t_symbol *s, long ac, t_atom *av) 00212 { 00213 t_symbol *name; 00214 double start, end; 00215 00216 name = (ac) ? atom_getsym(av) : gensym(""); 00217 start = (ac>1) ? atom_getfloat(av+1) : 0.; 00218 end = (ac>2) ? atom_getfloat(av+2) : 0.; 00219 00220 if (start < 0) 00221 start = 0; 00222 if (end < 0) 00223 end = 0; 00224 x->w_start = start; 00225 x->w_end = end; 00226 simpwave_setup(x,name,0); 00227 } 00228 00229 void simpwave_float(t_simpwave *x, double f) 00230 { 00231 long in = proxy_getinlet((t_object *)x); 00232 00233 if (in == 1) { // set min 00234 if (f < 0) 00235 f = 0; 00236 if (f > x->w_end) 00237 x->w_end = f; 00238 x->w_start = f; 00239 simpwave_limits(x,x->w_buf); 00240 } else if (in == 2) { // set max 00241 if (f < 0) 00242 f = 0; 00243 if (f < x->w_start) 00244 x->w_start = f; 00245 x->w_end = f; 00246 simpwave_limits(x,x->w_buf); 00247 } 00248 } 00249 00250 void simpwave_int(t_simpwave *x, long n) 00251 { 00252 simpwave_float(x,(double)n); 00253 } 00254 00255 void simpwave_assist(t_simpwave *x, void *b, long m, long a, char *s) 00256 { 00257 if (m == ASSIST_INLET) { // inlets 00258 switch (a) { 00259 case 0: snprintf(s, 256, "(signal) Table Position (from 0 to 1)"); break; 00260 case 1: snprintf(s, 256, "(signal/float) Starting Table Location in ms"); break; 00261 case 2: snprintf(s, 256, "(signal/float) Ending Table Location in ms"); break; 00262 } 00263 } else { // outlet 00264 snprintf(s, 256, "(signal) Output %ld", a+1); 00265 } 00266 00267 } 00268 00269 void simpwave_dblclick(t_simpwave *x) 00270 { 00271 t_buffer *b; 00272 00273 if ((b = (t_buffer *)(x->w_name->s_thing)) && ob_sym(b) == ps_buffer) 00274 mess0((struct object *)b,gensym("dblclick")); 00275 } 00276 00277 void *simpwave_new(t_symbol *s, long argc, t_atom *argv) 00278 { 00279 t_simpwave *x = (t_simpwave *)object_alloc(s_simpwave_class); 00280 t_symbol *buf=0; 00281 float start=0., end=0.; 00282 dsp_setup((t_pxobject *)x,3); 00283 // x->w_phase = 0; 00284 buf = atom_getsymarg(0,argc,argv); 00285 start = atom_getfloatarg(1,argc,argv); 00286 end = atom_getfloatarg(2,argc,argv); 00287 00288 x->w_name = buf; 00289 x->w_msr = sys_getsr() * 0.001; 00290 x->w_start = start; 00291 x->w_end = end; 00292 x->w_begin = start * x->w_msr; 00293 x->w_len = (end - start) * x->w_msr; 00294 x->w_buf = 0; 00295 x->w_nchans = 1; 00296 outlet_new((t_object *)x, "signal"); // audio outlet 00297 return (x); 00298 }
Copyright © 2008, Cycling '74