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