hello,
Charles Henry a écrit :
On Tue, Jun 10, 2008 at 10:29 AM, cyrille henry <[EMAIL PROTECTED]> wrote:
...
I'm having trouble compiling, due to the garray_getfloatwords symbol. Which version of Pd are you using?
vanilia 0.41.4
I'd like to see the waveform and test it out. Here's my analysis of key points (a=x[-1], b=x[0], c=x[1], d=x[2]) 83 a0 = d - c - a + b; 84 a1 = a - b - a0; 85 a2 = c - a; 86 *out++ = ((a0*frac+a1)*frac+a2)*frac+b; At frac=0, output should be b. Check! At frac=1, output should be c ((a0*1+a1)*1+a2)*1+b =a0+a1+a2+b =d-c-a+b + a-b-(d-c-a+b) + c-a + b =d-c-a+b + a-b-d+c+a-b + c-a + b =d-c-a+b + 2a-2b+c-d + c-a + b =c Check! 1st derivatives: At frac=0, d/dx f(x) = c-a (This quantity really ought to be (c-a)/2, but let's see how the rest comes out) At frac=1, d/dx f(x) = 3*(d-c-a+b) + 2*(a-b-d+c+a-b) + c-a =d-b So, we've got 1st derivatives that match between samples. Check! This looks like a really good plan. I might suggest some new coefficients to try: a0=(3b-a-3c+d)/2 a1=a-5b/2+2c-d/2 a2=(c-a)/2
ok, i don't have time for now to test anything. i'll have more time in 1 or 2 weeks.
The only difference is the 1st derivatives are (c-a)/2 and (d-b)/2, respectively. Maybe you could try a 5th-degree polynomial next and set the 2nd derivatives for continuity. This would involve 4-points as before, but it might introduce a ripple in the interpolation (cubic interpolation can't do that, since it only has two critical points).
i tried a Hermite interpolation. it sound great, but i did not had time yet to explore the tension parametter. here is the code if you wish to explore it.
I'm not keen on doing the spectral analysis, because it would take about 4 hours, to do it by hand. There's something I would like to see (once I can compile it). I made a patch (attached) a while back to view the tabread4~ interpolation function (impulse response). Give it a try if you're inclined to do so, because it might surprise you.
attachement is a pict of the impulse response of tabread4~ and tabread4c~. cyrille
ChuckcyrilleChuck _______________________________________________ [email protected] mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
// GPL // 99% comes from pd. just the interpolation shem is diferent and comes from : // http://local.wasp.uwa.edu.au/~pbourke/other/interpolation/ #include "m_pd.h" /******************** tabosc4h~ ***********************/ /* this is all copied from d_osc.c... what include file could this go in? */ #define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ /* machine-dependent definitions. These ifdefs really should have been by CPU type and not by operating system! */ #ifdef IRIX /* big-endian. Most significant byte is at low address in memory */ #define HIOFFSET 0 /* word offset to find MSB */ #define LOWOFFSET 1 /* word offset to find LSB */ #define int32 long /* a data type that has 32 bits */ #endif /* IRIX */ #ifdef MSW /* little-endian; most significant byte is at highest address */ #define HIOFFSET 1 #define LOWOFFSET 0 #define int32 long #endif #if defined(__FreeBSD__) || defined(__APPLE__) #include <machine/endian.h> #endif #ifdef __linux__ #include <endian.h> #endif #if defined(__unix__) || defined(__APPLE__) #if !defined(BYTE_ORDER) || !defined(LITTLE_ENDIAN) #error No byte order defined #endif #if BYTE_ORDER == LITTLE_ENDIAN #define HIOFFSET 1 #define LOWOFFSET 0 #else #define HIOFFSET 0 /* word offset to find MSB */ #define LOWOFFSET 1 /* word offset to find LSB */ #endif /* __BYTE_ORDER */ #include <sys/types.h> #define int32 int32_t #endif /* __unix__ or __APPLE__*/ union tabfudge { double tf_d; int32 tf_i[2]; }; static t_class *tabosc4h_tilde_class; typedef struct _tabosc4h_tilde { t_object x_obj; t_float x_fnpoints; t_float x_finvnpoints; t_word *x_vec; t_symbol *x_arrayname; t_float x_f; double x_phase; t_float x_conv; } t_tabosc4h_tilde; static void *tabosc4h_tilde_new(t_symbol *s) { t_tabosc4h_tilde *x = (t_tabosc4h_tilde *)pd_new(tabosc4h_tilde_class); x->x_arrayname = s; x->x_vec = 0; x->x_fnpoints = 512.; x->x_finvnpoints = (1./512.); outlet_new(&x->x_obj, gensym("signal")); inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); x->x_f = 0; return (x); } static t_int *tabosc4h_tilde_perform(t_int *w) { t_tabosc4h_tilde *x = (t_tabosc4h_tilde *)(w[1]); t_sample *in = (t_sample *)(w[2]); t_sample *out = (t_sample *)(w[3]); int n = (int)(w[4]); int normhipart; union tabfudge tf; double a0,a1,a2,a3; // CH double m0,m1,mu,mu2,mu3; float tension; t_float fnpoints = x->x_fnpoints; int mask = fnpoints - 1; t_float conv = fnpoints * x->x_conv; int maxindex; t_word *tab = x->x_vec, *addr; int i; double dphase = fnpoints * x->x_phase + UNITBIT32; if (!tab) goto zero; tf.tf_d = UNITBIT32; normhipart = tf.tf_i[HIOFFSET]; #if 1 while (n--) { t_sample frac, a, b, c, d, cminusb; tf.tf_d = dphase; dphase += *in++ * conv; addr = tab + (tf.tf_i[HIOFFSET] & mask); tf.tf_i[HIOFFSET] = normhipart; frac = tf.tf_d - UNITBIT32; a = addr[0].w_float; b = addr[1].w_float; c = addr[2].w_float; d = addr[3].w_float; // cminusb = c-b; // *out++ = b + frac * (cminusb - 0.1666667f * (1.-frac) * ( (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) ) ); // CH mu = frac; mu2 = mu * mu; mu3 = mu2 * mu; tension = 0.3; m0 = (b-a)*(1-tension)/2; m0 += (c-b)*(1-tension)/2; m1 = (c-b)*(1-tension)/2; m1 += (d-c)*(1-tension)/2; a0 = 2*mu3 - 3*mu2 + 1; a1 = mu3 - 2*mu2 + mu; a2 = mu3 - mu2; a3 = -2*mu3 + 3*mu2; *out++ = a0*b+a1*m0+a2*m1+a3*c; } #endif tf.tf_d = UNITBIT32 * fnpoints; normhipart = tf.tf_i[HIOFFSET]; tf.tf_d = dphase + (UNITBIT32 * fnpoints - UNITBIT32); tf.tf_i[HIOFFSET] = normhipart; x->x_phase = (tf.tf_d - UNITBIT32 * fnpoints) * x->x_finvnpoints; return (w+5); zero: while (n--) *out++ = 0; return (w+5); } void tabosc4h_tilde_set(t_tabosc4h_tilde *x, t_symbol *s) { t_garray *a; int npoints, pointsinarray; x->x_arrayname = s; if (!(a = (t_garray *)pd_findbyclass(x->x_arrayname, garray_class))) { if (*s->s_name) pd_error(x, "tabosc4h~: %s: no such array", x->x_arrayname->s_name); x->x_vec = 0; } else if (!garray_getfloatwords(a, &pointsinarray, &x->x_vec)) { pd_error(x, "%s: bad template for tabosc4h~", x->x_arrayname->s_name); x->x_vec = 0; } else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3))) { pd_error(x, "%s: number of points (%d) not a power of 2 plus three", x->x_arrayname->s_name, pointsinarray); x->x_vec = 0; garray_usedindsp(a); } else { x->x_fnpoints = npoints; x->x_finvnpoints = 1./npoints; garray_usedindsp(a); } } static void tabosc4h_tilde_ft1(t_tabosc4h_tilde *x, t_float f) { x->x_phase = f; } static void tabosc4h_tilde_dsp(t_tabosc4h_tilde *x, t_signal **sp) { x->x_conv = 1. / sp[0]->s_sr; tabosc4h_tilde_set(x, x->x_arrayname); dsp_add(tabosc4h_tilde_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); } void tabosc4h_tilde_setup(void) { tabosc4h_tilde_class = class_new(gensym("tabosc4h~"), (t_newmethod)tabosc4h_tilde_new, 0, sizeof(t_tabosc4h_tilde), 0, A_DEFSYM, 0); CLASS_MAINSIGNALIN(tabosc4h_tilde_class, t_tabosc4h_tilde, x_f); class_addmethod(tabosc4h_tilde_class, (t_method)tabosc4h_tilde_dsp, gensym("dsp"), 0); class_addmethod(tabosc4h_tilde_class, (t_method)tabosc4h_tilde_set, gensym("set"), A_SYMBOL, 0); class_addmethod(tabosc4h_tilde_class, (t_method)tabosc4h_tilde_ft1, gensym("ft1"), A_FLOAT, 0); }
<<inline: Capture-view_tabread4~_impulse_response.png>>
_______________________________________________ [email protected] mailing list UNSUBSCRIBE and account-management -> http://lists.puredata.info/listinfo/pd-list
