I finished a first draft of an external, called tabread4a~ (which gratuitously borrows tabread4~). It compiles fine, but when loaded by Pd, it returns an error: "Symbol "tabread4a_tilde_setup" not found" Can anyone tell me where I've gone wrong here?
Chuck
Enclosed is the text of tabread4a~.c:
/******************** tabread4a~ ***********************/ /* The guts of this external are "borrowed" from tabread4~. For normal or slower playback speeds, this external is intended to simply run the same as tabread4~. For faster speeds, the interpolation polynomial is modified to eliminate aliased frequencies. */
#include<m_pd.h> #include<math.h>
float interp(float x) { float absx=fabsf(x); return ((absx<2.0f)*((absx<1.0f)?(1-absx*(0.5f+absx*(1-0.5f*absx))):(1-absx*(1.833333f-absx*(1.0f-0.1666666f*absx))))); }
static t_class *tabread4a_tilde_class;
typedef struct _tabread4a_tilde { t_object x_obj; int x_npoints; float *x_vec; t_symbol *x_arrayname; float x_f; float last_input; } t_tabread4a_tilde;
static void *tabread4a_tilde_new(t_symbol *s) { t_tabread4a_tilde *x = (t_tabread4a_tilde *)pd_new(tabread4a_tilde_class); x->x_arrayname = s; x->x_vec = 0; outlet_new(&x->x_obj, gensym("signal")); x->x_f = 0; x->last_input=0; return (x); }
static t_int *tabread4a_tilde_perform(t_int *w) { t_tabread4a_tilde *x = (t_tabread4a_tilde *)(w[1]); t_float *in = (t_float *)(w[2]); t_float *out = (t_float *)(w[3]); int n = (int)(w[4]); int maxindex; float *buf = x->x_vec, *fp; int i; float diff, findex;
maxindex = x->x_npoints - 3;
if (!buf) goto zero;
#if 0 /* test for spam -- I'm not ready to deal with this */ for (i = 0, xmax = 0, xmin = maxindex, fp = in1; i < n; i++, fp++) { float f = *in1; if (f < xmin) xmin = f; else if (f > xmax) xmax = f; } if (xmax < xmin + x->c_maxextent) xmax = xmin + x->c_maxextent; for (i = 0, splitlo = xmin+ x->c_maxextent, splithi = xmax - x->c_maxextent, fp = in1; i < n; i++, fp++) { float f = *in1; if (f > splitlo && f < splithi) goto zero; } #endif
findex = *in; diff=fabsf(findex-x->last_input); if (diff > ((float) (maxindex/2))) diff=((float) maxindex) - diff; for (i = 0; i < n; i++) { if (diff <= 1.0f) { int index = findex; float frac, a, b, c, d, cminusb; static int count; if (index < 1) index = 1, frac = 0; else if (index > maxindex) index = maxindex, frac = 1; else frac = findex - index; fp = buf + index; a = fp[-1]; b = fp[0]; c = fp[1]; d = fp[2]; /* if (!i && !(count++ & 1023)) post("fp = %lx, shit = %lx, b = %f", fp, buf->b_shit, b); */ cminusb = c-b; *out++ = b + frac * ( cminusb - 0.1666667f * (1.-frac) * ( (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) ) ); } else { int a,b,c, itemp, itemp2, itemp3; float sum_left, sum_right; a=ceilf(findex-2*diff); //lowest value used in interpolation b=findex; //floor( findex) c=findex+2*diff; // highest value used, floor(findex+2*diff)
if ((a>0)&&(c<=maxindex)) { fp=buf+a; sum_left=(*fp++)*interp((findex-a)/diff); while((a++)<b) sum_left+=(*(fp++))*interp((findex-a)/diff); fp=buf+c; sum_right=(*(fp--))*interp((c-findex)/diff); itemp=b+1; while((c--)>itemp) sum_right+=(*(fp--))*interp((c-findex)/diff); } else { itemp=a; while(itemp<1) itemp+=maxindex; fp=buf+itemp; sum_left=(*fp++)*interp((findex-a++)/diff); while(a<=b) { itemp2=b-a+1; itemp3=maxindex-itemp+1; itemp=(itemp2<itemp3)?itemp2:itemp3; while(itemp--) sum_left+=(*fp++)*interp((findex-a++)/diff); fp=buf+1; } itemp=c; while(itemp>maxindex) itemp-=maxindex; fp=buf+itemp; sum_right=(*fp--)*interp(((c--)-findex)/diff); while(c>b) { itemp2=c-b; itemp3=itemp-1; itemp=(itemp2<itemp3)?itemp2:itemp3; while(itemp--) sum_right+=(*fp--)*interp(((c--)-findex)/diff); fp=buf+maxindex; } } *out++=(sum_left+sum_right)/diff; } in++; diff=fabsf(*in-findex); if (diff > ((float) (maxindex/2))) diff=((float) maxindex) - diff; findex = *in; } return (w+5); zero: while (n--) *out++ = 0;
return (w+5); }
void tabread4a_tilde_set(t_tabread4a_tilde *x, t_symbol *s) { t_garray *a;
x->x_arrayname = s; if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) { if (*s->s_name) pd_error(x, "tabread4a~: %s: no such array", x->x_arrayname->s_name); x->x_vec = 0; } else if (!garray_getfloatarray(a, &x->x_npoints, &x->x_vec)) { pd_error(x, "%s: bad template for tabread4a~", x->x_arrayname->s_name); x->x_vec = 0; } else garray_usedindsp(a); }
static void tabread4a_tilde_dsp(t_tabread4a_tilde *x, t_signal **sp) { tabread4a_tilde_set(x, x->x_arrayname);
dsp_add(tabread4a_tilde_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}
static void tabread4a_tilde_free(t_tabread4a_tilde *x) { }
static void tabread4a_tilde_setup(void) { tabread4a_tilde_class = class_new(gensym("tabread4a~"), (t_newmethod)tabread4a_tilde_new, (t_method)tabread4a_tilde_free, sizeof(t_tabread4a_tilde), 0, A_DEFSYM, 0); CLASS_MAINSIGNALIN(tabread4a_tilde_class, t_tabread4a_tilde, x_f); class_addmethod(tabread4a_tilde_class, (t_method)tabread4a_tilde_dsp, gensym("dsp"), 0); class_addmethod(tabread4a_tilde_class, (t_method)tabread4a_tilde_set, gensym("set"), A_SYMBOL, 0); }
Charles Henry wrote:
I finished a first draft of an external, called tabread4a~ (which gratuitously borrows tabread4~). It compiles fine, but when loaded by Pd, it returns an error: "Symbol "tabread4a_tilde_setup" not found" Can anyone tell me where I've gone wrong here?
you have to make the setup-function available to the calling application (pd).
declaring a function as "static" will make it _local_ to your file (and inaccessible from other files, even if they are statically linked together) according to the C language specs.
on super-secure operating systems (like w32) you will also have to explicitly declare a function in a dll to be "exported" for use from the calling app. do this by using the EXTERN macro in m_pd.h
(using the macro is clever, since you won't have to deal with the different OS; miller will do that for you)
mfa.sdr IOhannes