Max 5 API Reference
00001 /** 00002 @file 00003 jit.simple - simple example of a Jitter external 00004 + multiplies an incoming matrix by a constant 00005 + demonstrates some oft-requested example code for using C++ in an extern 00006 00007 @ingroup examples 00008 00009 Copyright 2009 - Cycling '74 00010 Timothy Place, tim@cycling74.com 00011 */ 00012 00013 #include "jit.common.h" 00014 00015 00016 // Our Jitter object instance data 00017 typedef struct _jit_simple { 00018 t_object ob; 00019 double gain; // our attribute (multiplied against each cell in the matrix) 00020 } t_jit_simple; 00021 00022 00023 // prototypes 00024 BEGIN_USING_C_LINKAGE 00025 t_jit_err jit_simple_init (void); 00026 t_jit_simple *jit_simple_new (void); 00027 void jit_simple_free (t_jit_simple *x); 00028 t_jit_err jit_simple_matrix_calc (t_jit_simple *x, void *inputs, void *outputs); 00029 void jit_simple_calculate_ndim (t_jit_simple *x, long dim, long *dimsize, long planecount, t_jit_matrix_info *in_minfo, char *bip, t_jit_matrix_info *out_minfo, char *bop); 00030 END_USING_C_LINKAGE 00031 00032 00033 // globals 00034 static void *s_jit_simple_class = NULL; 00035 00036 00037 /************************************************************************************/ 00038 00039 t_jit_err jit_simple_init(void) 00040 { 00041 long attrflags = JIT_ATTR_GET_DEFER_LOW | JIT_ATTR_SET_USURP_LOW; 00042 t_jit_object *attr; 00043 t_jit_object *mop; 00044 00045 s_jit_simple_class = jit_class_new("jit_simple", (method)jit_simple_new, (method)jit_simple_free, sizeof(t_jit_simple), 0); 00046 00047 // add matrix operator (mop) 00048 mop = (t_jit_object*)jit_object_new(_jit_sym_jit_mop, 1, 1); // args are num inputs and num outputs 00049 jit_class_addadornment(s_jit_simple_class, mop); 00050 00051 // add method(s) 00052 jit_class_addmethod(s_jit_simple_class, (method)jit_simple_matrix_calc, "matrix_calc", A_CANT, 0); 00053 00054 // add attribute(s) 00055 attr = (t_jit_object*)jit_object_new(_jit_sym_jit_attr_offset, 00056 "gain", 00057 _jit_sym_float64, 00058 attrflags, 00059 (method)NULL, (method)NULL, 00060 calcoffset(t_jit_simple, gain)); 00061 jit_class_addattr(s_jit_simple_class, attr); 00062 00063 // finalize class 00064 jit_class_register(s_jit_simple_class); 00065 return JIT_ERR_NONE; 00066 } 00067 00068 00069 /************************************************************************************/ 00070 // Object Life Cycle 00071 00072 t_jit_simple *jit_simple_new(void) 00073 { 00074 t_jit_simple *x = NULL; 00075 00076 x = (t_jit_simple*)jit_object_alloc(s_jit_simple_class); 00077 if (x) { 00078 x->gain = 0.0; 00079 } 00080 return x; 00081 } 00082 00083 00084 void jit_simple_free(t_jit_simple *x) 00085 { 00086 ; // nothing to free for our simple object 00087 } 00088 00089 00090 /************************************************************************************/ 00091 // Methods bound to input/inlets 00092 00093 t_jit_err jit_simple_matrix_calc(t_jit_simple *x, void *inputs, void *outputs) 00094 { 00095 t_jit_err err = JIT_ERR_NONE; 00096 long in_savelock; 00097 long out_savelock; 00098 t_jit_matrix_info in_minfo; 00099 t_jit_matrix_info out_minfo; 00100 char *in_bp; 00101 char *out_bp; 00102 long i; 00103 long dimcount; 00104 long planecount; 00105 long dim[JIT_MATRIX_MAX_DIMCOUNT]; 00106 void *in_matrix; 00107 void *out_matrix; 00108 00109 in_matrix = jit_object_method(inputs,_jit_sym_getindex,0); 00110 out_matrix = jit_object_method(outputs,_jit_sym_getindex,0); 00111 00112 if (x && in_matrix && out_matrix) { 00113 in_savelock = (long) jit_object_method(in_matrix, _jit_sym_lock, 1); 00114 out_savelock = (long) jit_object_method(out_matrix, _jit_sym_lock, 1); 00115 00116 jit_object_method(in_matrix, _jit_sym_getinfo, &in_minfo); 00117 jit_object_method(out_matrix, _jit_sym_getinfo, &out_minfo); 00118 00119 jit_object_method(in_matrix, _jit_sym_getdata, &in_bp); 00120 jit_object_method(out_matrix, _jit_sym_getdata, &out_bp); 00121 00122 if (!in_bp) { 00123 err=JIT_ERR_INVALID_INPUT; 00124 goto out; 00125 } 00126 if (!out_bp) { 00127 err=JIT_ERR_INVALID_OUTPUT; 00128 goto out; 00129 } 00130 if (in_minfo.type != out_minfo.type) { 00131 err = JIT_ERR_MISMATCH_TYPE; 00132 goto out; 00133 } 00134 00135 //get dimensions/planecount 00136 dimcount = out_minfo.dimcount; 00137 planecount = out_minfo.planecount; 00138 00139 for (i=0; i<dimcount; i++) { 00140 //if dimsize is 1, treat as infinite domain across that dimension. 00141 //otherwise truncate if less than the output dimsize 00142 dim[i] = out_minfo.dim[i]; 00143 if ((in_minfo.dim[i]<dim[i]) && in_minfo.dim[i]>1) { 00144 dim[i] = in_minfo.dim[i]; 00145 } 00146 } 00147 00148 jit_parallel_ndim_simplecalc2((method)jit_simple_calculate_ndim, 00149 x, dimcount, dim, planecount, &in_minfo, in_bp, &out_minfo, out_bp, 00150 0 /* flags1 */, 0 /* flags2 */); 00151 00152 } 00153 else 00154 return JIT_ERR_INVALID_PTR; 00155 00156 out: 00157 jit_object_method(out_matrix,_jit_sym_lock,out_savelock); 00158 jit_object_method(in_matrix,_jit_sym_lock,in_savelock); 00159 return err; 00160 } 00161 00162 00163 // We are using a C++ template to process a vector of the matrix for any of the given types. 00164 // Thus, we don't need to duplicate the code for each datatype. 00165 template<typename T> 00166 void jit_simple_vector(t_jit_simple *x, long n, t_jit_op_info *in, t_jit_op_info *out) 00167 { 00168 double gain = x->gain; 00169 T *ip; 00170 T *op; 00171 long is, 00172 os; 00173 long tmp; 00174 00175 ip = ((T *)in->p); 00176 op = ((T *)out->p); 00177 is = in->stride; 00178 os = out->stride; 00179 00180 if ((is==1) && (os==1)) { 00181 ++n; 00182 --op; 00183 --ip; 00184 while (--n) { 00185 tmp = *++ip; 00186 *++op = tmp * gain; 00187 } 00188 } 00189 else { 00190 while (n--) { 00191 tmp = *ip; 00192 *op = tmp * gain; 00193 ip += is; 00194 op += os; 00195 } 00196 } 00197 } 00198 00199 00200 // We also use a C+ template for the loop that wraps the call to jit_simple_vector(), 00201 // further reducing code duplication in jit_simple_calculate_ndim(). 00202 // The calls into these templates should be inlined by the compiler, eliminating concern about any added function call overhead. 00203 template<typename T> 00204 void jit_simple_loop(t_jit_simple *x, long n, t_jit_op_info *in_opinfo, t_jit_op_info *out_opinfo, t_jit_matrix_info *in_minfo, t_jit_matrix_info *out_minfo, char *bip, char *bop, long *dim, long planecount, long datasize) 00205 { 00206 long i; 00207 long j; 00208 00209 for (i=0; i<dim[1]; i++) { 00210 for (j=0; j<planecount; j++) { 00211 in_opinfo->p = bip + i * in_minfo->dimstride[1] + (j % in_minfo->planecount) * datasize; 00212 out_opinfo->p = bop + i * out_minfo->dimstride[1] + (j % out_minfo->planecount) * datasize; 00213 jit_simple_vector<T>(x, n, in_opinfo, out_opinfo); 00214 } 00215 } 00216 } 00217 00218 00219 void jit_simple_calculate_ndim(t_jit_simple *x, long dimcount, long *dim, long planecount, t_jit_matrix_info *in_minfo, char *bip, t_jit_matrix_info *out_minfo, char *bop) 00220 { 00221 long i; 00222 long n; 00223 char *ip; 00224 char *op; 00225 t_jit_op_info in_opinfo; 00226 t_jit_op_info out_opinfo; 00227 00228 if (dimcount < 1) 00229 return; // safety 00230 00231 switch (dimcount) { 00232 case 1: 00233 dim[1]=1; 00234 // (fall-through to next case is intentional) 00235 case 2: 00236 // if planecount is the same then flatten planes - treat as single plane data for speed 00237 n = dim[0]; 00238 if ((in_minfo->dim[0] > 1) && (out_minfo->dim[0] > 1) && (in_minfo->planecount == out_minfo->planecount)) { 00239 in_opinfo.stride = 1; 00240 out_opinfo.stride = 1; 00241 n *= planecount; 00242 planecount = 1; 00243 } 00244 else { 00245 in_opinfo.stride = in_minfo->dim[0]>1 ? in_minfo->planecount : 0; 00246 out_opinfo.stride = out_minfo->dim[0]>1 ? out_minfo->planecount : 0; 00247 } 00248 00249 if (in_minfo->type == _jit_sym_char) 00250 jit_simple_loop<uchar>(x, n, &in_opinfo, &out_opinfo, in_minfo, out_minfo, bip, bop, dim, planecount, 1); 00251 else if (in_minfo->type == _jit_sym_long) 00252 jit_simple_loop<long>(x, n, &in_opinfo, &out_opinfo, in_minfo, out_minfo, bip, bop, dim, planecount, 4); 00253 else if (in_minfo->type == _jit_sym_float32) 00254 jit_simple_loop<float>(x, n, &in_opinfo, &out_opinfo, in_minfo, out_minfo, bip, bop, dim, planecount, 4); 00255 else if (in_minfo->type == _jit_sym_float64) 00256 jit_simple_loop<double>(x, n, &in_opinfo, &out_opinfo, in_minfo, out_minfo, bip, bop, dim, planecount, 8); 00257 break; 00258 default: 00259 for (i=0; i<dim[dimcount-1]; i++) { 00260 ip = bip + i * in_minfo->dimstride[dimcount-1]; 00261 op = bop + i * out_minfo->dimstride[dimcount-1]; 00262 jit_simple_calculate_ndim(x, dimcount-1, dim, planecount, in_minfo, ip, out_minfo, op); 00263 } 00264 } 00265 }
Copyright © 2008, Cycling '74