From 57045df5fe3ec557e57dc7434ac1a07b5521bffc Mon Sep 17 00:00:00 2001 From: Guenter Geiger Date: Mon, 29 Jul 2002 17:06:19 +0000 Subject: This commit was generated by cvs2svn to compensate for changes in r58, which included commits to RCS files with non-trunk default branches. svn path=/trunk/; revision=59 --- pd/src/d_osc.c | 531 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 531 insertions(+) create mode 100644 pd/src/d_osc.c (limited to 'pd/src/d_osc.c') diff --git a/pd/src/d_osc.c b/pd/src/d_osc.c new file mode 100644 index 00000000..27dceae9 --- /dev/null +++ b/pd/src/d_osc.c @@ -0,0 +1,531 @@ +/* Copyright (c) 1997-1999 Miller Puckette. +* For information on usage and redistribution, and for a DISCLAIMER OF ALL +* WARRANTIES, see the file, "LICENSE.txt," in this distribution. */ + +/* sinusoidal oscillator and table lookup; see also tabosc4~ in d_array.c. +*/ + +#include "m_pd.h" +#include "math.h" + +#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 */ +#else +#ifdef NT + /* little-endian; most significant byte is at highest address */ +#define HIOFFSET 1 +#define LOWOFFSET 0 +#define int32 long +#else +#ifdef __FreeBSD__ +#include +#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 +#define int32 int32_t +#endif +#ifdef __linux__ + +#include + +#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 +#define int32 int32_t + +#else +#ifdef MACOSX +#define HIOFFSET 0 /* word offset to find MSB */ +#define LOWOFFSET 1 /* word offset to find LSB */ +#define int32 int /* a data type that has 32 bits */ + +#endif /* MACOSX */ +#endif /* __linux__ */ +#endif /* NT */ +#endif /* SGI */ + +union tabfudge +{ + double tf_d; + int32 tf_i[2]; +}; + + +/* -------------------------- phasor~ ------------------------------ */ +static t_class *phasor_class, *scalarphasor_class; + +#if 1 /* in the style of R. Hoeldrich (ICMC 1995 Banff) */ + +typedef struct _phasor +{ + t_object x_obj; + double x_phase; + float x_conv; + float x_f; /* scalar frequency */ +} t_phasor; + +static void *phasor_new(t_floatarg f) +{ + t_phasor *x = (t_phasor *)pd_new(phasor_class); + x->x_f = f; + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_phase = 0; + x->x_conv = 0; + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static t_int *phasor_perform(t_int *w) +{ + t_phasor *x = (t_phasor *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + double dphase = x->x_phase + UNITBIT32; + union tabfudge tf; + int normhipart; + float conv = x->x_conv; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + tf.tf_d = dphase; + + while (n--) + { + tf.tf_i[HIOFFSET] = normhipart; + dphase += *in++ * conv; + *out++ = tf.tf_d - UNITBIT32; + tf.tf_d = dphase; + } + tf.tf_i[HIOFFSET] = normhipart; + x->x_phase = tf.tf_d - UNITBIT32; + return (w+5); +} + +static void phasor_dsp(t_phasor *x, t_signal **sp) +{ + x->x_conv = 1./sp[0]->s_sr; + dsp_add(phasor_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void phasor_ft1(t_phasor *x, t_float f) +{ + x->x_phase = f; +} + +static void phasor_setup(void) +{ + phasor_class = class_new(gensym("phasor~"), (t_newmethod)phasor_new, 0, + sizeof(t_phasor), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(phasor_class, t_phasor, x_f); + class_addmethod(phasor_class, (t_method)phasor_dsp, gensym("dsp"), 0); + class_addmethod(phasor_class, (t_method)phasor_ft1, + gensym("ft1"), A_FLOAT, 0); +} + +#endif /* Hoeldrich version */ + +/* ------------------------ cos~ ----------------------------- */ + +float *cos_table; + +static t_class *cos_class; + +typedef struct _cos +{ + t_object x_obj; + float x_f; +} t_cos; + +static void *cos_new(void) +{ + t_cos *x = (t_cos *)pd_new(cos_class); + outlet_new(&x->x_obj, gensym("signal")); + x->x_f = 0; + return (x); +} + +static t_int *cos_perform(t_int *w) +{ + t_float *in = (t_float *)(w[1]); + t_float *out = (t_float *)(w[2]); + int n = (int)(w[3]); + float *tab = cos_table, *addr, f1, f2, frac; + double dphase; + int normhipart; + union tabfudge tf; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + +#if 0 /* this is the readable version of the code. */ + while (n--) + { + dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32; + tf.tf_d = dphase; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); + } +#endif +#if 1 /* this is the same, unwrapped by hand. */ + dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32; + tf.tf_d = dphase; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + while (--n) + { + dphase = (double)(*in++ * (float)(COSTABSIZE)) + UNITBIT32; + frac = tf.tf_d - UNITBIT32; + tf.tf_d = dphase; + f1 = addr[0]; + f2 = addr[1]; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + *out++ = f1 + frac * (f2 - f1); + tf.tf_i[HIOFFSET] = normhipart; + } + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); +#endif + return (w+4); +} + +static void cos_dsp(t_cos *x, t_signal **sp) +{ + dsp_add(cos_perform, 3, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void cos_maketable(void) +{ + int i; + float *fp, phase, phsinc = (2. * 3.14159) / COSTABSIZE; + union tabfudge tf; + + if (cos_table) return; + cos_table = (float *)getbytes(sizeof(float) * (COSTABSIZE+1)); + for (i = COSTABSIZE + 1, fp = cos_table, phase = 0; i--; + fp++, phase += phsinc) + *fp = cos(phase); + + /* here we check at startup whether the byte alignment + is as we declared it. If not, the code has to be + recompiled the other way. */ + tf.tf_d = UNITBIT32 + 0.5; + if ((unsigned)tf.tf_i[LOWOFFSET] != 0x80000000) + bug("cos~: unexpected machine alignment"); +} + +static void cos_setup(void) +{ + cos_class = class_new(gensym("cos~"), (t_newmethod)cos_new, 0, + sizeof(t_cos), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(cos_class, t_cos, x_f); + class_addmethod(cos_class, (t_method)cos_dsp, gensym("dsp"), 0); + cos_maketable(); +} + +/* ------------------------ osc~ ----------------------------- */ + +static t_class *osc_class, *scalarosc_class; + +typedef struct _osc +{ + t_object x_obj; + double x_phase; + float x_conv; + float x_f; /* frequency if scalar */ +} t_osc; + +static void *osc_new(t_floatarg f) +{ + t_osc *x = (t_osc *)pd_new(osc_class); + x->x_f = f; + outlet_new(&x->x_obj, gensym("signal")); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1")); + x->x_phase = 0; + x->x_conv = 0; + return (x); +} + +static t_int *osc_perform(t_int *w) +{ + t_osc *x = (t_osc *)(w[1]); + t_float *in = (t_float *)(w[2]); + t_float *out = (t_float *)(w[3]); + int n = (int)(w[4]); + float *tab = cos_table, *addr, f1, f2, frac; + double dphase = x->x_phase + UNITBIT32; + int normhipart; + union tabfudge tf; + float conv = x->x_conv; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; +#if 0 + while (n--) + { + tf.tf_d = dphase; + dphase += *in++ * conv; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); + } +#endif +#if 1 + tf.tf_d = dphase; + dphase += *in++ * conv; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + while (--n) + { + tf.tf_d = dphase; + f1 = addr[0]; + dphase += *in++ * conv; + f2 = addr[1]; + addr = tab + (tf.tf_i[HIOFFSET] & (COSTABSIZE-1)); + tf.tf_i[HIOFFSET] = normhipart; + *out++ = f1 + frac * (f2 - f1); + frac = tf.tf_d - UNITBIT32; + } + f1 = addr[0]; + f2 = addr[1]; + *out++ = f1 + frac * (f2 - f1); +#endif + + tf.tf_d = UNITBIT32 * COSTABSIZE; + normhipart = tf.tf_i[HIOFFSET]; + tf.tf_d = dphase + (UNITBIT32 * COSTABSIZE - UNITBIT32); + tf.tf_i[HIOFFSET] = normhipart; + x->x_phase = tf.tf_d - UNITBIT32 * COSTABSIZE; + return (w+5); +} + +static void osc_dsp(t_osc *x, t_signal **sp) +{ + x->x_conv = COSTABSIZE/sp[0]->s_sr; + dsp_add(osc_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n); +} + +static void osc_ft1(t_osc *x, t_float f) +{ + x->x_phase = COSTABSIZE * f; +} + +static void osc_setup(void) +{ + osc_class = class_new(gensym("osc~"), (t_newmethod)osc_new, 0, + sizeof(t_osc), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(osc_class, t_osc, x_f); + class_addmethod(osc_class, (t_method)osc_dsp, gensym("dsp"), 0); + class_addmethod(osc_class, (t_method)osc_ft1, gensym("ft1"), A_FLOAT, 0); + + cos_maketable(); +} + +/* ---------------- vcf~ - 2-pole bandpass filter. ----------------- */ + +typedef struct vcfctl +{ + float c_re; + float c_im; + float c_q; + float c_isr; +} t_vcfctl; + +typedef struct sigvcf +{ + t_object x_obj; + t_vcfctl x_cspace; + t_vcfctl *x_ctl; + float x_f; +} t_sigvcf; + +t_class *sigvcf_class; + +static void *sigvcf_new(t_floatarg q) +{ + t_sigvcf *x = (t_sigvcf *)pd_new(sigvcf_class); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_signal, &s_signal); + inlet_new(&x->x_obj, &x->x_obj.ob_pd, gensym("float"), gensym("ft1")); + outlet_new(&x->x_obj, gensym("signal")); + outlet_new(&x->x_obj, gensym("signal")); + x->x_ctl = &x->x_cspace; + x->x_cspace.c_re = 0; + x->x_cspace.c_im = 0; + x->x_cspace.c_q = q; + x->x_cspace.c_isr = 0; + x->x_f = 0; + return (x); +} + +static void sigvcf_ft1(t_sigvcf *x, t_floatarg f) +{ + x->x_ctl->c_q = (f > 0 ? f : 0.f); +} + +static t_int *sigvcf_perform(t_int *w) +{ + float *in1 = (float *)(w[1]); + float *in2 = (float *)(w[2]); + float *out1 = (float *)(w[3]); + float *out2 = (float *)(w[4]); + t_vcfctl *c = (t_vcfctl *)(w[5]); + int n = (t_int)(w[6]); + int i; + float re = c->c_re, re2; + float im = c->c_im; + float q = c->c_q; + float qinv = (q > 0? 1.0f/q : 0); + float ampcorrect = 2.0f - 2.0f / (q + 2.0f); + float isr = c->c_isr; + float coefr, coefi; + float *tab = cos_table, *addr, f1, f2, frac; + double dphase; + int normhipart, tabindex; + union tabfudge tf; + + tf.tf_d = UNITBIT32; + normhipart = tf.tf_i[HIOFFSET]; + + for (i = 0; i < n; i++) + { + float cf, cfindx, r, oneminusr; + cf = *in2++ * isr; + if (cf < 0) cf = 0; + cfindx = cf * (float)(COSTABSIZE/6.28318f); + r = (qinv > 0 ? 1 - cf * qinv : 0); + if (r < 0) r = 0; + oneminusr = 1.0f - r; + dphase = ((double)(cfindx)) + UNITBIT32; + tf.tf_d = dphase; + tabindex = tf.tf_i[HIOFFSET] & (COSTABSIZE-1); + addr = tab + tabindex; + tf.tf_i[HIOFFSET] = normhipart; + frac = tf.tf_d - UNITBIT32; + f1 = addr[0]; + f2 = addr[1]; + coefr = r * (f1 + frac * (f2 - f1)); + + addr = tab + ((tabindex - (COSTABSIZE/4)) & (COSTABSIZE-1)); + f1 = addr[0]; + f2 = addr[1]; + coefi = r * (f1 + frac * (f2 - f1)); + + f1 = *in1++; + re2 = re; + *out1++ = re = ampcorrect * oneminusr * f1 + + coefr * re2 - coefi * im; + *out2++ = im = coefi * re2 + coefr * im; + } + c->c_re = re; + c->c_im = im; + return (w+7); +} + +static void sigvcf_dsp(t_sigvcf *x, t_signal **sp) +{ + x->x_ctl->c_isr = 6.28318f/sp[0]->s_sr; + dsp_add(sigvcf_perform, 6, + sp[0]->s_vec, sp[1]->s_vec, sp[2]->s_vec, sp[3]->s_vec, + x->x_ctl, sp[0]->s_n); + +} + +void sigvcf_setup(void) +{ + sigvcf_class = class_new(gensym("vcf~"), (t_newmethod)sigvcf_new, 0, + sizeof(t_sigvcf), 0, A_DEFFLOAT, 0); + CLASS_MAINSIGNALIN(sigvcf_class, t_sigvcf, x_f); + class_addmethod(sigvcf_class, (t_method)sigvcf_dsp, gensym("dsp"), 0); + class_addmethod(sigvcf_class, (t_method)sigvcf_ft1, + gensym("ft1"), A_FLOAT, 0); +} + +/* -------------------------- noise~ ------------------------------ */ +static t_class *noise_class; + +typedef struct _noise +{ + t_object x_obj; + int x_val; +} t_noise; + +static void *noise_new(void) +{ + t_noise *x = (t_noise *)pd_new(noise_class); + static int init = 307; + x->x_val = (init *= 1319); + outlet_new(&x->x_obj, gensym("signal")); + return (x); +} + +static t_int *noise_perform(t_int *w) +{ + t_float *out = (t_float *)(w[1]); + int *vp = (int *)(w[2]); + int n = (int)(w[3]); + int val = *vp; + while (n--) + { + *out++ = ((float)((val & 0x7fffffff) - 0x40000000)) * + (float)(1.0 / 0x40000000); + val = val * 435898247 + 382842987; + } + *vp = val; + return (w+4); +} + +static void noise_dsp(t_noise *x, t_signal **sp) +{ + dsp_add(noise_perform, 3, sp[0]->s_vec, &x->x_val, sp[0]->s_n); +} + +static void noise_setup(void) +{ + noise_class = class_new(gensym("noise~"), (t_newmethod)noise_new, 0, + sizeof(t_noise), 0, 0); + class_addmethod(noise_class, (t_method)noise_dsp, gensym("dsp"), 0); +} + + +/* ----------------------- global setup routine ---------------- */ +void d_osc_setup(void) +{ + phasor_setup(); + cos_setup(); + osc_setup(); + sigvcf_setup(); + noise_setup(); +} + -- cgit v1.2.1