diff options
author | N.N. <matju@users.sourceforge.net> | 2010-01-05 22:49:36 +0000 |
---|---|---|
committer | N.N. <matju@users.sourceforge.net> | 2010-01-05 22:49:36 +0000 |
commit | 8dbec761cf858ea65900c8a094599857208d8c3a (patch) | |
tree | 3228c023f87f23a354da3b57fdc2afe5b7052032 /desiredata/src/builtins_dsp.c | |
parent | 529e59635598e2d90a7a49f6b4c676f8366109ba (diff) |
svn path=/trunk/; revision=12907
Diffstat (limited to 'desiredata/src/builtins_dsp.c')
-rw-r--r-- | desiredata/src/builtins_dsp.c | 3632 |
1 files changed, 0 insertions, 3632 deletions
diff --git a/desiredata/src/builtins_dsp.c b/desiredata/src/builtins_dsp.c deleted file mode 100644 index 2f0aec63..00000000 --- a/desiredata/src/builtins_dsp.c +++ /dev/null @@ -1,3632 +0,0 @@ -/* Copyright (c) 2007 Mathieu Bouchard - 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. */ - -/* arithmetic binops (+, -, *, /). -If no creation argument is given, there are two signal inlets for vector/vector -operation; otherwise it's vector/scalar and the second inlet takes a float -to reset the value. -*/ - -//#define HAVE_LIBFFTW3F - -#define PD_PLUSPLUS_FACE -#include "desire.h" -using namespace desire; -#include "m_simd.h" -#include <math.h> -#include <stdio.h> -#include <string.h> -#include <stdlib.h> -extern int ugen_getsortno (); -#define DEFDELVS 64 /* LATER get this from canvas at DSP time */ -#ifdef HAVE_LIBFFTW3F -#include <fftw3.h> -#endif -#define DEFSENDVS 64 /* LATER get send to get this from canvas */ -#define LOGTEN 2.302585092994 -#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ -#define int32 int -#ifdef BIGENDIAN -#define HIOFFSET 0 /* word offset to find MSB */ -#define LOWOFFSET 1 /* word offset to find LSB */ -#else -#define HIOFFSET 1 -#define LOWOFFSET 0 -#endif - -#undef CLASS_MAINSIGNALIN -/* because C++ bitches about null pointers, we'll use 8 instead (really): */ -#define CLASS_MAINSIGNALIN(c, type, field) class_domainsignalin(c, (char *)(&((type *)8)->field) - (char *)8) - -#define clock_new(a,b) clock_new(a,(t_method)b) - -#undef min -#undef max - -/* ----------------------------- plus ----------------------------- */ - -struct t_dop : t_object { - float a; - t_float b; /* inlet value, if necessary */ -}; - -#define DSPDECL(NAME) static t_class *NAME##_class, *scalar##NAME##_class; typedef t_dop t_##NAME, t_scalar##NAME; -DSPDECL(plus) -DSPDECL(minus) -DSPDECL(times) -DSPDECL(over) -DSPDECL(max) -DSPDECL(min) -DSPDECL(lt) -DSPDECL(gt) -DSPDECL(le) -DSPDECL(ge) -DSPDECL(eq) -DSPDECL(ne) - -#define DSPNEW(NAME,SYM) \ -static void *NAME##_new(t_symbol *s, int argc, t_atom *argv) { \ - if (argc > 1) error("extra arguments ignored"); \ - t_dop *x = (t_dop *)pd_new(argc ? scalar##NAME##_class : NAME##_class); \ - if (argc) { \ - floatinlet_new(x, &x->b); \ - x->b = atom_getfloatarg(0, argc, argv); \ - } else inlet_new(x, x, &s_signal, &s_signal); \ - outlet_new(x, &s_signal); \ - x->a = 0; \ - return x;} \ -static void NAME##_setup() { \ - t_class *c = NAME##_class = class_new2(SYM,NAME##_new,0,sizeof(t_dop),0,"*"); \ - class_addmethod2(c, NAME##_dsp, "dsp",""); \ - CLASS_MAINSIGNALIN(c, t_dop, a); \ - class_sethelpsymbol(NAME##_class, gensym("sigbinops")); \ - c = scalar##NAME##_class = class_new2(SYM,0,0,sizeof(t_dop),0,""); \ - CLASS_MAINSIGNALIN(c, t_dop, a); \ - class_addmethod2(c, scalar##NAME##_dsp, "dsp",""); \ - class_sethelpsymbol(scalar##NAME##_class, gensym("sigbinops"));} - -/* use when simd functions are present */ -#define DSPDSP(NAME) \ -static void NAME##_dsp(t_minus *x, t_signal **sp) { \ - const int n = sp[0]->n; \ - if(n&7) dsp_add(NAME##_perform, 4, sp[0]->v, sp[1]->v, sp[2]->v, n); \ - else if(SIMD_CHECK3(n,sp[0]->v,sp[1]->v,sp[2]->v)) \ - dsp_add(NAME##_perf_simd, 4, sp[0]->v, sp[1]->v, sp[2]->v, n); \ - else dsp_add(NAME##_perf8, 4, sp[0]->v, sp[1]->v, sp[2]->v, n);} \ -static void scalar##NAME##_dsp(t_scalarminus *x, t_signal **sp) { \ - const int n = sp[0]->n;\ - if(n&7) dsp_add(scalar##NAME##_perform, 4, sp[0]->v, &x->b,sp[1]->v, n);\ - else if(SIMD_CHECK2(n,sp[0]->v,sp[1]->v)) \ - dsp_add(scalar##NAME##_perf_simd, 4, sp[0]->v, &x->b, sp[1]->v, n);\ - else dsp_add(scalar##NAME##_perf8, 4, sp[0]->v, &x->b, sp[1]->v, n);} - -/* use when simd functions are missing */ -#define DSPDSP2(NAME) \ -static void NAME##_dsp(t_minus *x, t_signal **sp) { \ - const int n = sp[0]->n; \ - if(n&7) dsp_add(NAME##_perform, 4, sp[0]->v, sp[1]->v, sp[2]->v, n); \ - else dsp_add(NAME##_perf8, 4, sp[0]->v, sp[1]->v, sp[2]->v, n);} \ -static void scalar##NAME##_dsp(t_scalarminus *x, t_signal **sp) { \ - const int n = sp[0]->n;\ - if(n&7) dsp_add(scalar##NAME##_perform, 4, sp[0]->v, &x->b,sp[1]->v, n);\ - else dsp_add(scalar##NAME##_perf8, 4, sp[0]->v, &x->b, sp[1]->v, n);} - -#define PERFORM(NAME,EXPR) \ -t_int *NAME##_perform(t_int *w) { \ - PERFORM4ARGS(t_float *,in1, t_float *,in2, t_float *,out, int,n); \ - while (n--) {t_float a=*in1++, b=*in2++; *out++ = (EXPR);} \ - return w+5;} \ -t_int *NAME##_perf8(t_int *w) { \ - PERFORM4ARGS(t_float *,in1, t_float *,in2, t_float *,out, int,n); \ - for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) { \ - {t_float a=in1[0], b=in2[0]; out[0] = (EXPR);} \ - {t_float a=in1[1], b=in2[1]; out[1] = (EXPR);} \ - {t_float a=in1[2], b=in2[2]; out[2] = (EXPR);} \ - {t_float a=in1[3], b=in2[3]; out[3] = (EXPR);} \ - {t_float a=in1[4], b=in2[4]; out[4] = (EXPR);} \ - {t_float a=in1[5], b=in2[5]; out[5] = (EXPR);} \ - {t_float a=in1[6], b=in2[6]; out[6] = (EXPR);} \ - {t_float a=in1[7], b=in2[7]; out[7] = (EXPR);}} \ - return w+5;} \ -t_int *scalar##NAME##_perform(t_int *w) { \ - PERFORM4ARGS(t_float *,in, t_float *,in2, t_float *,out, int,n); t_float b=*in2; \ - while (n--) {t_float a=*in++; *out++ = (EXPR);} \ - return w+5;} \ -t_int *scalar##NAME##_perf8(t_int *w) { \ - PERFORM4ARGS(t_float *,in, t_float *,in2, t_float *,out, int,n); t_float b=*in2; \ - for (; n; n -= 8, in += 8, out += 8) { \ - {t_float a=in[0]; out[0] = (EXPR);} \ - {t_float a=in[1]; out[1] = (EXPR);} \ - {t_float a=in[2]; out[2] = (EXPR);} \ - {t_float a=in[3]; out[3] = (EXPR);} \ - {t_float a=in[4]; out[4] = (EXPR);} \ - {t_float a=in[5]; out[5] = (EXPR);} \ - {t_float a=in[6]; out[6] = (EXPR);} \ - {t_float a=in[7]; out[7] = (EXPR);}} \ - return w+5;} - -void dsp_add_plus(t_sample *in1, t_sample *in2, t_sample *out, int n) { - if (n&7) dsp_add(plus_perform, 4, in1, in2, out, n); - else if(SIMD_CHECK3(n,in1,in2,out)) dsp_add(plus_perf_simd, 4, in1, in2, out, n); - else dsp_add(plus_perf8, 4, in1, in2, out, n); -} - -/* T.Grill - squaring: optimized * for equal input signals */ -t_int *sqr_perf8(t_int *w) { - PERFORM3ARGS(t_float *,in, t_float *,out, int,n); - for (; n; n -= 8, in += 8, out += 8) { - float f0 = in[0], f1 = in[1], f2 = in[2], f3 = in[3]; - float f4 = in[4], f5 = in[5], f6 = in[6], f7 = in[7]; - out[0] = f0 * f0; out[1] = f1 * f1; out[2] = f2 * f2; out[3] = f3 * f3; - out[4] = f4 * f4; out[5] = f5 * f5; out[6] = f6 * f6; out[7] = f7 * f7; - } - return w+4; -} - -/* T.Grill - added optimization for equal input signals */ -static void times_dsp(t_times *x, t_signal **sp) { - const int n = sp[0]->n; - if (n&7) dsp_add(times_perform, 4, sp[0]->v, sp[1]->v, sp[2]->v, n); - else if(sp[0]->v == sp[1]->v) { - if(SIMD_CHECK2(n,sp[0]->v,sp[2]->v)) dsp_add(sqr_perf_simd, 3, sp[0]->v, sp[2]->v, n); - else dsp_add(sqr_perf8, 3, sp[0]->v, sp[2]->v, n); - } else { - if(SIMD_CHECK3(n,sp[0]->v,sp[1]->v,sp[2]->v)) dsp_add(times_perf_simd, 4, sp[0]->v, sp[1]->v, sp[2]->v, n); - else dsp_add(times_perf8, 4, sp[0]->v, sp[1]->v, sp[2]->v, n); - } -} -static void scalartimes_dsp(t_scalartimes *x, t_signal **sp) { - const int n = sp[0]->n; - if (n&7) dsp_add(scalartimes_perform, 4, sp[0]->v, &x->b, sp[1]->v, n); - else if(SIMD_CHECK2(n,sp[0]->v,sp[1]->v)) dsp_add(scalartimes_perf_simd, 4, sp[0]->v, &x->b, sp[1]->v, n); - else dsp_add(scalartimes_perf8, 4, sp[0]->v, &x->b, sp[1]->v, n); -} - -PERFORM(plus ,a+b) DSPDSP(plus) DSPNEW(plus ,"+~") -PERFORM(minus,a-b) DSPDSP(minus) DSPNEW(minus,"-~") -PERFORM(times,a*b) /*DSPDSP(times)*/ DSPNEW(times,"*~") -/*PERFORM(over,a/b)*/ DSPDSP(over) DSPNEW(over ,"/~") -PERFORM(min ,a<b?a:b) DSPDSP(min) DSPNEW(min ,"min~") -PERFORM(max ,a>b?a:b) DSPDSP(max) DSPNEW(max ,"max~") -PERFORM(lt ,a<b) DSPDSP2(lt) DSPNEW(lt ,"<~") -PERFORM(gt ,a>b) DSPDSP2(gt) DSPNEW(gt ,">~") -PERFORM(le ,a<=b) DSPDSP2(le) DSPNEW(le ,"<=~") -PERFORM(ge ,a>=b) DSPDSP2(ge) DSPNEW(ge ,">=~") -PERFORM(eq ,a==b) DSPDSP2(eq) DSPNEW(eq ,"==~") -PERFORM(ne ,a!=b) DSPDSP2(ne) DSPNEW(ne ,"!=~") - -t_int *over_perform(t_int *w) { - PERFORM4ARGS(t_float *,in1, t_float *,in2, t_float *,out, int,n); - while (n--) { - float g = *in2++; - *out++ = (g ? *in1++ / g : 0); - } - return w+5; -} -t_int *over_perf8(t_int *w) { - PERFORM4ARGS(t_float *,in1, t_float *,in2, t_float *,out, int,n); - for (; n; n -= 8, in1 += 8, in2 += 8, out += 8) { - float f0 = in1[0], f1 = in1[1], f2 = in1[2], f3 = in1[3]; - float f4 = in1[4], f5 = in1[5], f6 = in1[6], f7 = in1[7]; - float g0 = in2[0], g1 = in2[1], g2 = in2[2], g3 = in2[3]; - float g4 = in2[4], g5 = in2[5], g6 = in2[6], g7 = in2[7]; - out[0] = (g0? f0 / g0 : 0); - out[1] = (g1? f1 / g1 : 0); - out[2] = (g2? f2 / g2 : 0); - out[3] = (g3? f3 / g3 : 0); - out[4] = (g4? f4 / g4 : 0); - out[5] = (g5? f5 / g5 : 0); - out[6] = (g6? f6 / g6 : 0); - out[7] = (g7? f7 / g7 : 0); - } - return w+5; -} -/* T.Grill - added check for zero */ -t_int *scalarover_perform(t_int *w) { - PERFORM4ARGS(t_float *,in, t_float,f, t_float *,out, int,n); - if(f) f = 1./f; - while (n--) *out++ = *in++ * f; - return w+5; -} -t_int *scalarover_perf8(t_int *w) { - PERFORM4ARGS(t_float *,in, t_float,f, t_float *,out, int,n); - if (f) f = 1.f / f; - for (; n; n -= 8, in += 8, out += 8) { - out[0] = in[0]*f; out[1] = in[1]*f; out[2] = in[2]*f; out[3] = in[3]*f; - out[4] = in[4]*f; out[5] = in[5]*f; out[6] = in[6]*f; out[7] = in[7]*f; - } - return w+5; -} - -/* ------------------------- tabwrite~ -------------------------- */ -static t_class *tabwrite_tilde_class; -struct t_tabwrite_tilde : t_object { - int phase; - int nsampsintab; - float *vec; - t_symbol *arrayname; - float a; -}; -static void *tabwrite_tilde_new(t_symbol *s) { - t_tabwrite_tilde *x = (t_tabwrite_tilde *)pd_new(tabwrite_tilde_class); - x->phase = 0x7fffffff; - x->arrayname = s; - x->a = 0; - return x; -} -static void tabwrite_tilde_redraw(t_tabwrite_tilde *x) { - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) bug("tabwrite_tilde_redraw"); - else garray_redraw(a); -} -static t_int *tabwrite_tilde_perform(t_int *w) { - PERFORM3ARGS(t_tabwrite_tilde *,x, t_float *,in, int,n); - int phase = x->phase, endphase = x->nsampsintab; - if (!x->vec) goto bad; - if (endphase > phase) { - int nxfer = endphase - phase; - float *fp = x->vec + phase; - if (nxfer > n) nxfer = n; - phase += nxfer; - testcopyvec(fp, in, nxfer); - if (phase >= endphase) { - tabwrite_tilde_redraw(x); - phase = 0x7fffffff; - } - x->phase = phase; - } else x->phase = 0x7fffffff; -bad: - return w+4; -} -static t_int *tabwrite_tilde_perf_simd(t_int *w) { - PERFORM3ARGS(t_tabwrite_tilde *,x, t_float *,in, int,n); - int phase = x->phase, endphase = x->nsampsintab; - if (!x->vec) goto bad; - if (endphase > phase) { - int nxfer = endphase - phase; - float *fp = x->vec + phase; - if (nxfer > n) nxfer = n; - phase += nxfer; - if (SIMD_CHKCNT(nxfer)) testcopyvec_simd(fp, in, nxfer); - else testcopyvec(fp, in, nxfer); - if (phase >= endphase) { - tabwrite_tilde_redraw(x); - phase = 0x7fffffff; - } - x->phase = phase; - } else x->phase = 0x7fffffff; -bad: - return w+4; -} -void tabwrite_tilde_set(t_tabwrite_tilde *x, t_symbol *s) { - x->arrayname = s; - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) { - if (*s->name) error("tabwrite~: %s: no such array", x->arrayname->name); - x->vec = 0; - } else if (!garray_getfloatarray(a, &x->nsampsintab, &x->vec)) { - error("%s: bad template for tabwrite~", x->arrayname->name); - x->vec = 0; - } else garray_usedindsp(a); -} -static void tabwrite_tilde_dsp(t_tabwrite_tilde *x, t_signal **sp) { - tabwrite_tilde_set(x, x->arrayname); - if (SIMD_CHECK1(sp[0]->n, sp[0]->v)) - dsp_add(tabwrite_tilde_perf_simd, 3, x, sp[0]->v, sp[0]->n); - else dsp_add(tabwrite_tilde_perform, 3, x, sp[0]->v, sp[0]->n); -} -static void tabwrite_tilde_bang(t_tabwrite_tilde *x) {x->phase = 0;} -static void tabwrite_tilde_start(t_tabwrite_tilde *x, t_floatarg f) {x->phase = (int)max((int)f,0);} -static void tabwrite_tilde_stop(t_tabwrite_tilde *x) { - if (x->phase != 0x7fffffff) { - tabwrite_tilde_redraw(x); - x->phase = 0x7fffffff; - } -} - -/* ------------ tabplay~ - non-transposing sample playback --------------- */ -static t_class *tabplay_tilde_class; -struct t_tabplay_tilde : t_object { - int phase; - int nsampsintab; - int limit; - float *vec; - t_symbol *arrayname; - t_clock *clock; -}; -static void tabplay_tilde_tick(t_tabplay_tilde *x); -static void *tabplay_tilde_new(t_symbol *s) { - t_tabplay_tilde *x = (t_tabplay_tilde *)pd_new(tabplay_tilde_class); - x->clock = clock_new(x, tabplay_tilde_tick); - x->phase = 0x7fffffff; - x->limit = 0; - x->arrayname = s; - outlet_new(x, &s_signal); - outlet_new(x, &s_bang); - return x; -} -static t_int *tabplay_tilde_perform(t_int *w) { - PERFORM3ARGS(t_tabplay_tilde *,x, t_float *,out, int,n); - t_float *fp; - int phase = x->phase, endphase = (x->nsampsintab < x->limit ? x->nsampsintab : x->limit), nxfer, n3; - if (!x->vec || phase >= endphase) {while (n--) *out++ = 0; goto bye;} - nxfer = min(endphase-phase,n); - fp = x->vec + phase; - n3 = n - nxfer; - phase += nxfer; - while (nxfer--) *out++ = *fp++; - if (phase >= endphase) { - clock_delay(x->clock, 0); - x->phase = 0x7fffffff; - while (n3--) *out++ = 0; - } else x->phase = phase; -bye: - return w+4; -} -void tabplay_tilde_set(t_tabplay_tilde *x, t_symbol *s) { - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - x->arrayname = s; - if (!a) { - if (*s->name) error("tabplay~: %s: no such array", x->arrayname->name); - x->vec = 0; - } else if (!garray_getfloatarray(a, &x->nsampsintab, &x->vec)) { - error("%s: bad template for tabplay~", x->arrayname->name); - x->vec = 0; - } else garray_usedindsp(a); -} -static void tabplay_tilde_dsp(t_tabplay_tilde *x, t_signal **sp) { - tabplay_tilde_set(x, x->arrayname); - dsp_add(tabplay_tilde_perform, 3, x, sp[0]->v, sp[0]->n); -} -static void tabplay_tilde_list(t_tabplay_tilde *x, t_symbol *s, int argc, t_atom *argv) { - long start = atom_getintarg(0, argc, argv); - long length = atom_getintarg(1, argc, argv); - if (start < 0) start = 0; - if (length <= 0) x->limit = 0x7fffffff; else x->limit = start + length; - x->phase = start; -} -static void tabplay_tilde_stop(t_tabplay_tilde *x) {x->phase = 0x7fffffff;} -static void tabplay_tilde_tick(t_tabplay_tilde *x) {x->out(1)->send();} -static void tabplay_tilde_free(t_tabplay_tilde *x) {clock_free(x->clock);} - -/******************** tabread~ ***********************/ -static t_class *tabread_tilde_class; -struct t_tabread_tilde : t_object { - int npoints; - float *vec; - t_symbol *arrayname; - float a; -}; -static void *tabread_tilde_new(t_symbol *s) { - t_tabread_tilde *x = (t_tabread_tilde *)pd_new(tabread_tilde_class); - x->arrayname = s; - x->vec = 0; - outlet_new(x, &s_signal); - x->a = 0; - return x; -} -static t_int *tabread_tilde_perform(t_int *w) { - PERFORM4ARGS(t_tabread_tilde *,x, t_float *,in, t_float *,out, int,n); - float *buf = x->vec; - int maxindex = x->npoints - 1; - if (!buf) {while (n--) *out++ = 0; goto bad;} - for (int i = 0; i < n; i++) { - int index = (int)*in++; - if (index < 0) index = 0; else if (index > maxindex) index = maxindex; - *out++ = buf[index]; - } -bad:return w+5; -} -void tabread_tilde_set(t_tabread_tilde *x, t_symbol *s) { - x->arrayname = s; - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) { - if (*s->name) error("tabread~: %s: no such array", x->arrayname->name); - x->vec = 0; - } else if (!garray_getfloatarray(a, &x->npoints, &x->vec)) { - error("%s: bad template for tabread~", x->arrayname->name); - x->vec = 0; - } else garray_usedindsp(a); -} -static void tabread_tilde_dsp(t_tabread_tilde *x, t_signal **sp) { - tabread_tilde_set(x, x->arrayname); - dsp_add(tabread_tilde_perform, 4, x, sp[0]->v, sp[1]->v, sp[0]->n); -} -static void tabread_tilde_free(t_tabread_tilde *x) {} - -/******************** tabread4~ ***********************/ -static t_class *tabread4_tilde_class; -struct t_tabread4_tilde : t_object { - int npoints; - float *vec; - t_symbol *arrayname; - float a; -}; -static void *tabread4_tilde_new(t_symbol *s) { - t_tabread4_tilde *x = (t_tabread4_tilde *)pd_new(tabread4_tilde_class); - x->arrayname = s; - x->vec = 0; - outlet_new(x, &s_signal); - x->a = 0; - return x; -} -static t_int *tabread4_tilde_perform(t_int *w) { - PERFORM4ARGS(t_tabread4_tilde *,x, t_float *,in, t_float *,out, int,n); - int maxindex; - float *buf = x->vec, *fp; - maxindex = x->npoints - 3; - if (!buf) goto zero; - for (int i=0; i<n; i++) { - float findex = *in++; - int index = (int)findex; - float frac; - if (index < 1) index = 1, frac = 0; - else if (index > maxindex) index = maxindex, frac = 1; - else frac = findex - index; - fp = buf + index; - float 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); */ - 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))); - } - return w+5; - zero: - while (n--) *out++ = 0; - return w+5; -} -void tabread4_tilde_set(t_tabread4_tilde *x, t_symbol *s) { - x->arrayname = s; - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) { - if (*s->name) error("tabread4~: %s: no such array", x->arrayname->name); - x->vec = 0; - } else if (!garray_getfloatarray(a, &x->npoints, &x->vec)) { - error("%s: bad template for tabread4~", x->arrayname->name); - x->vec = 0; - } else garray_usedindsp(a); -} -static void tabread4_tilde_dsp(t_tabread4_tilde *x, t_signal **sp) { - tabread4_tilde_set(x, x->arrayname); - dsp_add(tabread4_tilde_perform, 4, x, sp[0]->v, sp[1]->v, sp[0]->n); -} -static void tabread4_tilde_free(t_tabread4_tilde *x) {} - -/******************** tabosc4~ ***********************/ - -#define UNITBIT32 1572864. /* 3*2^19; bit 32 has place value 1 */ - -#ifdef BIGENDIAN -#define HIOFFSET 0 /* word offset to find MSB */ -#define LOWOFFSET 1 /* word offset to find LSB */ -#else -#define HIOFFSET 1 -#define LOWOFFSET 0 -#endif -#include <sys/types.h> -//#define int32 int32_t -#define int32 int - -union tabfudge { - double d; - int32 i[2]; -}; -static t_class *tabosc4_tilde_class; -struct t_tabosc4_tilde : t_object { - float fnpoints; - float finvnpoints; - float *vec; - t_symbol *arrayname; - float a; - double phase; - float conv; -}; -static void *tabosc4_tilde_new(t_symbol *s) { - t_tabosc4_tilde *x = (t_tabosc4_tilde *)pd_new(tabosc4_tilde_class); - x->arrayname = s; - x->vec = 0; - x->fnpoints = 512.; - x->finvnpoints = (1./512.); - outlet_new(x, &s_signal); - inlet_new(x, x, &s_float, gensym("ft1")); - x->a = 0; - return x; -} -static t_int *tabosc4_tilde_perform(t_int *w) { - PERFORM4ARGS(t_tabosc4_tilde *,x, t_float *,in, t_float *,out, int,n); - union tabfudge tf; - float fnpoints = x->fnpoints; - int mask = (int)(fnpoints-1); - float conv = fnpoints * x->conv; - float *tab = x->vec, *addr; - double dphase = fnpoints * x->phase + UNITBIT32; - if (!tab) {while (n--) *out++ = 0; return w+5;} - tf.d = UNITBIT32; - int normhipart = tf.i[HIOFFSET]; - while (n--) { - tf.d = dphase; - dphase += *in++ * conv; - addr = tab + (tf.i[HIOFFSET] & mask); - tf.i[HIOFFSET] = normhipart; - float frac = tf.d - UNITBIT32; - float a = addr[0]; - float b = addr[1]; - float c = addr[2]; - float d = addr[3]; - 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))); - } - tf.d = UNITBIT32 * fnpoints; - normhipart = tf.i[HIOFFSET]; - tf.d = dphase + (UNITBIT32 * fnpoints - UNITBIT32); - tf.i[HIOFFSET] = normhipart; - x->phase = (tf.d - UNITBIT32 * fnpoints) * x->finvnpoints; - return w+5; -} -void tabosc4_tilde_set(t_tabosc4_tilde *x, t_symbol *s) { - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - int npoints, pointsinarray; - x->arrayname = s; - if (!a) { - if (*s->name) error("tabosc4~: %s: no such array", x->arrayname->name); - x->vec = 0; - } else if (!garray_getfloatarray(a, &pointsinarray, &x->vec)) { - error("%s: bad template for tabosc4~", x->arrayname->name); - x->vec = 0; - } else if ((npoints = pointsinarray - 3) != (1 << ilog2(pointsinarray - 3))) { - error("%s: number of points (%d) not a power of 2 plus three", x->arrayname->name, pointsinarray); - x->vec = 0; - garray_usedindsp(a); - } else { - x->fnpoints = npoints; - x->finvnpoints = 1./npoints; - garray_usedindsp(a); - } -} -static void tabosc4_tilde_ft1(t_tabosc4_tilde *x, t_float f) { - x->phase = f; -} -static void tabosc4_tilde_dsp(t_tabosc4_tilde *x, t_signal **sp) { - x->conv = 1. / sp[0]->sr; - tabosc4_tilde_set(x, x->arrayname); - dsp_add(tabosc4_tilde_perform, 4, x, sp[0]->v, sp[1]->v, sp[0]->n); -} -static void tabosc4_tilde_setup() { -} - -static void tab_tilde_setup() { - t_class *c; - c = tabwrite_tilde_class = class_new2("tabwrite~",tabwrite_tilde_new,0,sizeof(t_tabwrite_tilde),0,"S"); - CLASS_MAINSIGNALIN(c, t_tabwrite_tilde, a); - class_addmethod2(c, tabwrite_tilde_dsp, "dsp",""); - class_addmethod2(c, tabwrite_tilde_set, "set","s"); - class_addmethod2(c, tabwrite_tilde_stop,"stop",""); - class_addmethod2(c, tabwrite_tilde_start,"start","F"); - class_addbang(c, tabwrite_tilde_bang); - c = tabplay_tilde_class = class_new2("tabplay~",tabplay_tilde_new,tabplay_tilde_free,sizeof(t_tabplay_tilde),0,"S"); - class_addmethod2(c, tabplay_tilde_dsp, "dsp",""); - class_addmethod2(c, tabplay_tilde_stop, "stop",""); - class_addmethod2(c, tabplay_tilde_set, "set","S"); - class_addlist(c, tabplay_tilde_list); - c = tabread_tilde_class = class_new2("tabread~",tabread_tilde_new,tabread_tilde_free, sizeof(t_tabread_tilde),0,"S"); - CLASS_MAINSIGNALIN(c, t_tabread_tilde, a); - class_addmethod2(c, tabread_tilde_dsp, "dsp",""); - class_addmethod2(c, tabread_tilde_set, "set","s"); - c = tabread4_tilde_class = class_new2("tabread4~",tabread4_tilde_new,tabread4_tilde_free,sizeof(t_tabread4_tilde),0,"S"); - CLASS_MAINSIGNALIN(c, t_tabread4_tilde, a); - class_addmethod2(c, tabread4_tilde_dsp, "dsp",""); - class_addmethod2(c, tabread4_tilde_set, "set","s"); - c = tabosc4_tilde_class = class_new2("tabosc4~",tabosc4_tilde_new,0,sizeof(t_tabosc4_tilde),0,"S"); - CLASS_MAINSIGNALIN(c, t_tabosc4_tilde, a); - class_addmethod2(c, tabosc4_tilde_dsp, "dsp",""); - class_addmethod2(c, tabosc4_tilde_set, "set","s"); - class_addmethod2(c, tabosc4_tilde_ft1, "ft1","f"); -} - -/* ------------------------ tabsend~ ------------------------- */ -static t_class *tabsend_class; -struct t_tabsend : t_object { - float *vec; - int graphperiod; - int graphcount; - t_symbol *arrayname; - float a; -}; -static void *tabsend_new(t_symbol *s) { - t_tabsend *x = (t_tabsend *)pd_new(tabsend_class); - x->graphcount = 0; - x->arrayname = s; - x->a = 0; - return x; -} -static t_int *tabsend_perform(t_int *w) { - PERFORM3ARGS(t_tabsend *,x, t_float *,in, int,n); - t_float *dest = x->vec; - int i = x->graphcount; - if (!x->vec) goto bad; - testcopyvec(dest,in,n); - if (!i--) { - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) bug("tabsend_dsp"); - else garray_redraw(a); - i = x->graphperiod; - } - x->graphcount = i; -bad: - return w+4; -} -static t_int *tabsend_perf_simd(t_int *w) { - PERFORM3ARGS(t_tabsend *,x, t_float *,in, int,n); - t_float *dest = x->vec; - int i = x->graphcount; - if (!x->vec) goto bad; - testcopyvec_simd(dest,in,n); - if (!i--) { - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) bug("tabsend_dsp"); - else garray_redraw(a); - i = x->graphperiod; - } - x->graphcount = i; -bad: - return w+4; -} -static void tabsend_dsp(t_tabsend *x, t_signal **sp) { - int vecsize; - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) { - if (*x->arrayname->name) {error("tabsend~: %s: no such array", x->arrayname->name); return;} - } else if (!garray_getfloatarray(a, &vecsize, &x->vec)) { - error("%s: bad template for tabsend~", x->arrayname->name); return; - } else { - int n = sp[0]->n; - int ticksper = (int)(sp[0]->sr/n); - if (ticksper < 1) ticksper = 1; - x->graphperiod = ticksper; - if (x->graphcount > ticksper) x->graphcount = ticksper; - if (n < vecsize) vecsize = n; - garray_usedindsp(a); - if(SIMD_CHECK1(vecsize,sp[0]->v)) - dsp_add(tabsend_perf_simd, 3, x, sp[0]->v, vecsize); - else dsp_add(tabsend_perform, 3, x, sp[0]->v, vecsize); - } -} - -static void tabsend_setup() { - tabsend_class = class_new2("tabsend~",tabsend_new,0,sizeof(t_tabsend),0,"S"); - CLASS_MAINSIGNALIN(tabsend_class, t_tabsend, a); - class_addmethod2(tabsend_class, tabsend_dsp, "dsp",""); -} - -/* ------------------------ tabreceive~ ------------------------- */ -static t_class *tabreceive_class; -struct t_tabreceive : t_object { - float *vec; - int vecsize; - t_symbol *arrayname; -}; -static t_int *tabreceive_perform(t_int *w) { - PERFORM3ARGS(t_tabreceive *,x, t_float *,out, int,n); - t_float *from = x->vec; - if (from) { - int vecsize = x->vecsize; while (vecsize--) *out++ = *from++; - vecsize = n - x->vecsize; while (vecsize--) *out++ = 0; - } else while (n--) *out++ = 0; - return w+4; -} -static t_int *tabreceive_perf8(t_int *w) { - PERFORM3ARGS(t_tabreceive *,x, t_float *,out, int,n); - t_float *from = x->vec; - if (from) copyvec_8(out,from,n); - else zerovec_8(out, n); - return w+4; -} -static t_int *tabreceive_perfsimd(t_int *w) { - PERFORM3ARGS(t_tabreceive *,x, t_float *,out, int,n); - t_float *from = x->vec; - if(from) copyvec_simd(out,from,n); - else zerovec_simd(out, n); - return w+4; -} -static void tabreceive_dsp(t_tabreceive *x, t_signal **sp) { - t_garray *a; - if (!(a = (t_garray *)pd_findbyclass(x->arrayname, garray_class))) { - if (*x->arrayname->name) error("tabsend~: %s: no such array", x->arrayname->name); - } else if (!garray_getfloatarray(a, &x->vecsize, &x->vec)) { - error("%s: bad template for tabreceive~", x->arrayname->name); - } else { - if (x->vecsize > sp[0]->n) x->vecsize = sp[0]->n; - garray_usedindsp(a); - /* the array is aligned in any case */ - if(sp[0]->n&7) dsp_add(tabreceive_perform, 3, x, sp[0]->v, sp[0]->n); - else if(SIMD_CHECK1(sp[0]->n,sp[0]->v)) - dsp_add(tabreceive_perfsimd, 3, x, sp[0]->v, sp[0]->n); - else dsp_add(tabreceive_perf8, 3, x, sp[0]->v, sp[0]->n); - } -} -static void *tabreceive_new(t_symbol *s) { - t_tabreceive *x = (t_tabreceive *)pd_new(tabreceive_class); - x->arrayname = s; - outlet_new(x, &s_signal); - return x; -} -static void tabreceive_setup() { - tabreceive_class = class_new2("tabreceive~",tabreceive_new,0,sizeof(t_tabreceive),0,"S"); - class_addmethod2(tabreceive_class, tabreceive_dsp, "dsp",""); -} - -/* ---------- tabread: control, non-interpolating ------------------------ */ -static t_class *tabread_class; -struct t_tabread : t_object { - t_symbol *arrayname; -}; -static void tabread_float(t_tabread *x, t_float f) { - int npoints; - t_float *vec; - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - if (!a) {error("%s: no such array", x->arrayname->name); return;} - if (!garray_getfloatarray(a, &npoints, &vec)) {error("%s: bad template for tabread", x->arrayname->name); return;} - int n = clip(int(f),0,npoints-1); - x->outlet->send(npoints ? vec[n] : 0); -} -static void tabread_set(t_tabread *x, t_symbol *s) { - x->arrayname = s; -} -static void *tabread_new(t_symbol *s) { - t_tabread *x = (t_tabread *)pd_new(tabread_class); - x->arrayname = s; - outlet_new(x, &s_float); - return x; -} -static void tabread_setup() { - tabread_class = class_new2("tabread",tabread_new,0,sizeof(t_tabread),0,"S"); - class_addfloat(tabread_class, tabread_float); - class_addmethod2(tabread_class, tabread_set, "set","s"); -} - -/* ---------- tabread4: control, 4-point interpolation --------------- */ -static t_class *tabread4_class; -struct t_tabread4 : t_object { - t_symbol *arrayname; -}; -static void tabread4_float(t_tabread4 *x, t_float f) { - t_garray *ar = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - int npoints; - t_float *vec; - if (!ar) {error("%s: no such array", x->arrayname->name); return;} - if (!garray_getfloatarray(ar, &npoints, &vec)) {error("%s: bad template for tabread4", x->arrayname->name); return;} - if (npoints < 4) {x->outlet->send(0.); return;} - if (f <= 1) {x->outlet->send(vec[1]); return;} - if (f >= npoints-2) {x->outlet->send(vec[npoints-2]); return;} - int n = min(int(f),npoints-3); - float *fp = vec + n; - float frac = f - n; - float a=fp[-1], b=fp[0], c=fp[1], d=fp[2]; - float cminusb = c-b; - x->outlet->send (b + frac * (cminusb - 0.1666667f * (1.-frac) * ((d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b)))); -} -static void tabread4_set(t_tabread4 *x, t_symbol *s) {x->arrayname = s;} -static void *tabread4_new(t_symbol *s) { - t_tabread4 *x = (t_tabread4 *)pd_new(tabread4_class); - x->arrayname = s; - outlet_new(x, &s_float); - return x; -} -static void tabread4_setup() { - tabread4_class = class_new2("tabread4",tabread4_new,0,sizeof(t_tabread4),0,"S"); - class_addfloat(tabread4_class, tabread4_float); - class_addmethod2(tabread4_class, tabread4_set, "set","s"); -} - -/* ------------------ tabwrite: control ------------------------ */ -static t_class *tabwrite_class; -struct t_tabwrite : t_object { - t_symbol *arrayname; - float ft1; -}; -static void tabwrite_float(t_tabwrite *x, t_float f) { - int vecsize; - t_garray *a = (t_garray *)pd_findbyclass(x->arrayname, garray_class); - t_float *vec; - if (!a) {error("%s: no such array", x->arrayname->name); return;} - if (!garray_getfloatarray(a, &vecsize, &vec)) {error("%s: bad template for tabwrite", x->arrayname->name); return;} - int n = (int)x->ft1; - if (n < 0) n = 0; else if (n > vecsize-1) n = vecsize-1; - vec[n] = f; - garray_redraw(a); -} -static void tabwrite_set(t_tabwrite *x, t_symbol *s) {x->arrayname = s;} -static void *tabwrite_new(t_symbol *s) { - t_tabwrite *x = (t_tabwrite *)pd_new(tabwrite_class); - x->ft1 = 0; - x->arrayname = s; - floatinlet_new(x, &x->ft1); - return x; -} -void tabwrite_setup() { - tabwrite_class = class_new2("tabwrite",tabwrite_new,0,sizeof(t_tabwrite),0,"S"); - class_addfloat(tabwrite_class, tabwrite_float); - class_addmethod2(tabwrite_class, tabwrite_set, "set","s"); -} - -/* -------------------------- sig~ ------------------------------ */ -static t_class *sig_tilde_class; -struct t_sig : t_object { - float a; -}; -t_int *sig_tilde_perform(t_int *w) { - PERFORM3ARGS(t_float *,f, t_float *,out, int,n); - t_float g=*f; - while (n--) *out++ = g; - return w+4; -} -t_int *sig_tilde_perf8(t_int *w) { - PERFORM3ARGS(t_float,f, t_float *,out, int,n); - for (; n; n -= 8, out += 8) { - out[0] = f; out[1] = f; - out[2] = f; out[3] = f; - out[4] = f; out[5] = f; - out[6] = f; out[7] = f; - } - return w+4; -} -void dsp_add_scalarcopy(t_sample *in, t_sample *out, int n) { - if (n&7) dsp_add(sig_tilde_perform, 3, in, out, n); - else if(SIMD_CHECK1(n,out)) dsp_add(sig_tilde_perf_simd, 3, in, out, n); - else dsp_add(sig_tilde_perf8, 3, in, out, n); -} -static void sig_tilde_float(t_sig *x, t_float f) { - x->a = f; -} -static void sig_tilde_dsp(t_sig *x, t_signal **sp) { -/* dsp_add(sig_tilde_perform, 3, &x->a, sp[0]->v, sp[0]->n); */ - /* T.Grill - use chance of unrolling */ - dsp_add_scalarcopy(&x->a, sp[0]->v, sp[0]->n); -} -static void *sig_tilde_new(t_floatarg f) { - t_sig *x = (t_sig *)pd_new(sig_tilde_class); - x->a = f; - outlet_new(x, &s_signal); - return x; -} -static void sig_tilde_setup() { - sig_tilde_class = class_new2("sig~",sig_tilde_new,0,sizeof(t_sig),0,"F"); - class_addfloat(sig_tilde_class, sig_tilde_float); - class_addmethod2(sig_tilde_class, sig_tilde_dsp,"dsp",""); -} - -/* -------------------------- line~ ------------------------------ */ -static t_class *line_tilde_class; -struct t_line : t_object { - float target; - float value; - float biginc; - float inc; - float oneovern; - float dspticktomsec; - float inletvalue; - float inletwas; - int ticksleft; - int retarget; - float* slopes; /* tb: for simd-optimized line */ - float slopestep; /* tb: 4*x->inc */ -}; -static t_int *line_tilde_perform(t_int *w) { - PERFORM3ARGS(t_line *,x, t_float *,out, int,n); - float f = x->value; - if (PD_BIGORSMALL(f)) x->value = f = 0; - if (x->retarget) { - int nticks = (int)(x->inletwas * x->dspticktomsec); - if (!nticks) nticks = 1; - x->ticksleft = nticks; - x->biginc = (x->target - x->value)/(float)nticks; - x->inc = x->oneovern * x->biginc; - x->retarget = 0; - } - if (x->ticksleft) { - float f = x->value; - float slope = x->inc; /* tb: make sure, x->inc is loaded to a register */ - while (n--) *out++ = f, f += slope; - x->value += x->biginc; - x->ticksleft--; - } else { - float g = x->value = x->target; - while (n--) - *out++ = g; - } - return w+4; -} -/* tb: vectorized / simd version { */ -static void line_tilde_slope(t_float* out, t_int n, t_float* value, t_float* slopes, t_float* slopestep) { - t_float slope = slopes[1]; - t_float f = *value; - n>>=3; - while (n--) { - *out++ = f;f += slope; - *out++ = f;f += slope; - *out++ = f;f += slope; - *out++ = f;f += slope; - *out++ = f;f += slope; - *out++ = f;f += slope; - *out++ = f;f += slope; - *out++ = f;f += slope; - } -} -static t_int *line_tilde_perf8(t_int *w) { - PERFORM3ARGS(t_line *,x, t_float *,out, int,n); - float f = x->value; - if (PD_BIGORSMALL(f)) x->value = f = 0; - if (x->retarget) { - int nticks = (int)(x->inletwas * x->dspticktomsec); - if (!nticks) nticks = 1; - x->ticksleft = nticks; - x->biginc = (x->target - x->value)/(float)nticks; - x->inc = x->oneovern * x->biginc; - x->retarget = 0; - /* tb: rethink!!! this is ugly */ - for (int i = 0; i != 4; ++i) x->slopes[i] = i*x->inc; - x->slopestep = 4 * x->inc; - } - if (x->ticksleft) { - line_tilde_slope(out, n, &x->value, x->slopes, &x->slopestep); - x->value += x->biginc; - x->ticksleft--; - } else { - float f = x->value = x->target; - setvec_8(out,f,n); - } - return w+4; -} -static t_int *line_tilde_perfsimd(t_int *w) { - PERFORM3ARGS(t_line *,x, t_float *,out, int,n); - float f = x->value; - if (PD_BIGORSMALL(f)) x->value = f = 0; - if (x->retarget) { - int nticks = (int)(x->inletwas * x->dspticktomsec); - if (!nticks) nticks = 1; - x->ticksleft = nticks; - x->biginc = (x->target - x->value)/(float)nticks; - x->inc = x->oneovern * x->biginc; - x->retarget = 0; - for (int i = 0; i != 4; ++i) x->slopes[i] = i*x->inc; - x->slopestep = 4 * x->inc; - } - if (x->ticksleft) { - line_tilde_slope_simd(out, n, &x->value, x->slopes, &x->slopestep); - x->value += x->biginc; - x->ticksleft--; - } else { - float f = x->value = x->target; - setvec_simd(out,f,n); - } - return w+4; -} -/* tb } */ -static void line_tilde_float(t_line *x, t_float f) { - if (x->inletvalue <= 0) { - x->target = x->value = f; - x->ticksleft = x->retarget = 0; - } else { - x->target = f; - x->retarget = 1; - x->inletwas = x->inletvalue; - x->inletvalue = 0; - } -} -static void line_tilde_stop(t_line *x) { - x->target = x->value; - x->ticksleft = x->retarget = 0; -} -static void line_tilde_dsp(t_line *x, t_signal **sp) { - if(sp[0]->n&7) dsp_add(line_tilde_perform, 3, x, sp[0]->v, sp[0]->n); - else if (SIMD_CHECK1(sp[0]->n,sp[0]->v)) dsp_add(line_tilde_perfsimd, 3, x, sp[0]->v, sp[0]->n); - else dsp_add(line_tilde_perf8, 3, x, sp[0]->v, sp[0]->n); - x->oneovern = 1./sp[0]->n; - x->dspticktomsec = sp[0]->sr / (1000 * sp[0]->n); -} -/* tb: modified for simd-optimized line~ */ -static void *line_tilde_new() { - t_line *x = (t_line *)pd_new(line_tilde_class); - outlet_new(x, &s_signal); - floatinlet_new(x, &x->inletvalue); - x->ticksleft = x->retarget = 0; - x->value = x->target = x->inletvalue = x->inletwas = 0; - x->slopes = (t_float *)getalignedbytes(4*sizeof(t_float)); - return x; -} - -static void line_tilde_free(t_line * x) { - freealignedbytes(x->slopes, 4*sizeof(t_float)); -} -static void line_tilde_setup() { - line_tilde_class = class_new2("line~",line_tilde_new,line_tilde_free,sizeof(t_line),0,""); - class_addfloat(line_tilde_class, line_tilde_float); - class_addmethod2(line_tilde_class, line_tilde_dsp, "dsp",""); - class_addmethod2(line_tilde_class, line_tilde_stop,"stop",""); -} - -/* -------------------------- vline~ ------------------------------ */ -static t_class *vline_tilde_class; -struct t_vseg { - double s_targettime; - double s_starttime; - float s_target; - t_vseg *s_next; -}; -struct t_vline : t_object { - double value; - double inc; - double referencetime; - double samppermsec; - double msecpersamp; - double targettime; - float target; - float inlet1; - float inlet2; - t_vseg *list; -}; -static t_int *vline_tilde_perform(t_int *w) { - PERFORM3ARGS(t_vline *,x, t_float *,out, int,n); - double f = x->value; - double inc = x->inc; - double msecpersamp = x->msecpersamp; - double timenow = clock_gettimesince(x->referencetime) - n * msecpersamp; - t_vseg *s = x->list; - for (int i=0; i<n; i++) { - double timenext = timenow + msecpersamp; - checknext: - if (s) { - /* has starttime elapsed? If so update value and increment */ - if (s->s_starttime < timenext) { - if (x->targettime <= timenext) - f = x->target, inc = 0; - /* if zero-length segment bash output value */ - if (s->s_targettime <= s->s_starttime) { - f = s->s_target; - inc = 0; - } else { - double incpermsec = (s->s_target - f)/ - (s->s_targettime - s->s_starttime); - f = f + incpermsec * (timenext - s->s_starttime); - inc = incpermsec * msecpersamp; - } - x->inc = inc; - x->target = s->s_target; - x->targettime = s->s_targettime; - x->list = s->s_next; - free(s); - s = x->list; - goto checknext; - } - } - if (x->targettime <= timenext) - f = x->target, inc = x->inc = 0, x->targettime = 1e20; - *out++ = f; - f = f + inc; - timenow = timenext; - } - x->value = f; - return w+4; -} -static void vline_tilde_stop(t_vline *x) { - t_vseg *s1, *s2; - for (s1 = x->list; s1; s1 = s2) - s2 = s1->s_next, free(s1); - x->list = 0; - x->inc = 0; - x->inlet1 = x->inlet2 = 0; - x->target = x->value; - x->targettime = 1e20; -} -static void vline_tilde_float(t_vline *x, t_float f) { - double timenow = clock_gettimesince(x->referencetime); - float inlet1 = (x->inlet1 < 0 ? 0 : x->inlet1); - float inlet2 = x->inlet2; - double starttime = timenow + inlet2; - t_vseg *s1, *s2, *deletefrom = 0, *snew; - if (PD_BIGORSMALL(f)) f = 0; - /* negative delay input means stop and jump immediately to new value */ - if (inlet2 < 0) { - x->value = f; - vline_tilde_stop(x); - return; - } - snew = (t_vseg *)t_getbytes(sizeof(*snew)); - /* check if we supplant the first item in the list. We supplant - an item by having an earlier starttime, or an equal starttime unless - the equal one was instantaneous and the new one isn't (in which case - we'll do a jump-and-slide starting at that time.) */ - if (!x->list || x->list->s_starttime > starttime || - (x->list->s_starttime == starttime && - (x->list->s_targettime > x->list->s_starttime || inlet1 <= 0))) { - deletefrom = x->list; - x->list = snew; - } else { - for (s1 = x->list; (s2 = s1->s_next); s1 = s2) { - if (s2->s_starttime > starttime || - (s2->s_starttime == starttime && - (s2->s_targettime > s2->s_starttime || inlet1 <= 0))) { - deletefrom = s2; - s1->s_next = snew; - goto didit; - } - } - s1->s_next = snew; - deletefrom = 0; - didit: ; - } - while (deletefrom) { - s1 = deletefrom->s_next; - free(deletefrom); - deletefrom = s1; - } - snew->s_next = 0; - snew->s_target = f; - snew->s_starttime = starttime; - snew->s_targettime = starttime + inlet1; - x->inlet1 = x->inlet2 = 0; -} -static void vline_tilde_dsp(t_vline *x, t_signal **sp) { - dsp_add(vline_tilde_perform, 3, x, sp[0]->v, sp[0]->n); - x->samppermsec = ((double)(sp[0]->sr)) / 1000; - x->msecpersamp = ((double)1000) / sp[0]->sr; -} -static void *vline_tilde_new() { - t_vline *x = (t_vline *)pd_new(vline_tilde_class); - outlet_new(x, &s_signal); - floatinlet_new(x, &x->inlet1); - floatinlet_new(x, &x->inlet2); - x->inlet1 = x->inlet2 = 0; - x->value = x->inc = 0; - x->referencetime = clock_getlogicaltime(); - x->list = 0; - x->samppermsec = 0; - x->targettime = 1e20; - return x; -} -static void vline_tilde_setup() { - vline_tilde_class = class_new2("vline~",vline_tilde_new,vline_tilde_stop,sizeof(t_vline),0,""); - class_addfloat(vline_tilde_class, vline_tilde_float); - class_addmethod2(vline_tilde_class, vline_tilde_dsp, "dsp",""); - class_addmethod2(vline_tilde_class, vline_tilde_stop,"stop",""); -} - -/* -------------------------- snapshot~ ------------------------------ */ -static t_class *snapshot_tilde_class; -struct t_snapshot : t_object { - t_sample value; - float a; -}; -static void *snapshot_tilde_new() { - t_snapshot *x = (t_snapshot *)pd_new(snapshot_tilde_class); - x->value = 0; - outlet_new(x, &s_float); - x->a = 0; - return x; -} -static t_int *snapshot_tilde_perform(t_int *w) { - PERFORM2ARGS(t_float *,in, t_float *,out); - *out = *in; - return w+3; -} -static void snapshot_tilde_dsp(t_snapshot *x, t_signal **sp) { - dsp_add(snapshot_tilde_perform, 2, sp[0]->v + (sp[0]->n-1), &x->value); -} -static void snapshot_tilde_bang(t_snapshot *x) {x->outlet->send(x->value);} -static void snapshot_tilde_set(t_snapshot *x, t_floatarg f) {x->value = f;} -static void snapshot_tilde_setup() { - snapshot_tilde_class = class_new2("snapshot~",snapshot_tilde_new,0,sizeof(t_snapshot),0,""); - CLASS_MAINSIGNALIN(snapshot_tilde_class, t_snapshot, a); - class_addmethod2(snapshot_tilde_class, snapshot_tilde_dsp, "dsp",""); - class_addmethod2(snapshot_tilde_class, snapshot_tilde_set, "set","s"); - class_addbang(snapshot_tilde_class, snapshot_tilde_bang); -} - -/* -------------------------- vsnapshot~ ------------------------------ */ -static t_class *vsnapshot_tilde_class; -struct t_vsnapshot : t_object { - int n; - int gotone; - t_sample *vec; - float a; - float sampspermsec; - double time; -}; -static void *vsnapshot_tilde_new() { - t_vsnapshot *x = (t_vsnapshot *)pd_new(vsnapshot_tilde_class); - outlet_new(x, &s_float); - x->a = 0; - x->n = 0; - x->vec = 0; - x->gotone = 0; - return x; -} -static t_int *vsnapshot_tilde_perform(t_int *w) { - PERFORM2ARGS(t_float *,in, t_vsnapshot *,x); - t_float *out = x->vec; - int n = x->n, i; - for (i = 0; i < n; i++) out[i] = in[i]; - x->time = clock_getlogicaltime(); - x->gotone = 1; - return w+3; -} -static void vsnapshot_tilde_dsp(t_vsnapshot *x, t_signal **sp) { - int n = sp[0]->n; - if (n != x->n) { - if (x->vec) free(x->vec); - x->vec = (t_sample *)getbytes(n * sizeof(t_sample)); - x->gotone = 0; - x->n = n; - } - x->sampspermsec = sp[0]->sr / 1000; - dsp_add(vsnapshot_tilde_perform, 2, sp[0]->v, x); -} -static void vsnapshot_tilde_bang(t_vsnapshot *x) { - float val; - if (x->gotone) { - int indx = clip((int)(clock_gettimesince(x->time) * x->sampspermsec),0,x->n-1); - val = x->vec[indx]; - } else val = 0; - x->outlet->send(val); -} -static void vsnapshot_tilde_ff(t_vsnapshot *x) { - if (x->vec) free(x->vec); -} -static void vsnapshot_tilde_setup() { - vsnapshot_tilde_class = - class_new2("vsnapshot~",vsnapshot_tilde_new, vsnapshot_tilde_ff,sizeof(t_vsnapshot), 0,""); - CLASS_MAINSIGNALIN(vsnapshot_tilde_class, t_vsnapshot, a); - class_addmethod2(vsnapshot_tilde_class, vsnapshot_tilde_dsp, "dsp",""); - class_addbang(vsnapshot_tilde_class, vsnapshot_tilde_bang); -} - -/* ---------------- env~ - simple envelope follower. ----------------- */ -#define MAXOVERLAP 10 -#define MAXVSTAKEN 64 -struct t_sigenv : t_object { - t_clock *clock; /* a "clock" object */ - float *buf; /* a Hanning window */ - int phase; /* number of points since last output */ - int period; /* requested period of output */ - int realperiod; /* period rounded up to vecsize multiple */ - int npoints; /* analysis window size in samples */ - float result; /* result to output */ - float sumbuf[MAXOVERLAP]; /* summing buffer */ - float a; -}; -t_class *env_tilde_class; -static void env_tilde_tick(t_sigenv *x); -static void *env_tilde_new(t_floatarg fnpoints, t_floatarg fperiod) { - int npoints = (int)fnpoints; - int period = (int)fperiod; - float *buf; - if (npoints < 1) npoints = 1024; - if (period < 1) period = npoints/2; - if (period < npoints / MAXOVERLAP + 1) - period = npoints / MAXOVERLAP + 1; - if (!(buf = (float *)getalignedbytes(sizeof(float) * (npoints + MAXVSTAKEN)))) { - error("env: couldn't allocate buffer"); - return 0; - } - t_sigenv *x = (t_sigenv *)pd_new(env_tilde_class); - x->buf = buf; - x->npoints = npoints; - x->phase = 0; - x->period = period; - int i; - for (i = 0; i < MAXOVERLAP; i++) x->sumbuf[i] = 0; - for (i = 0; i < npoints; i++) buf[i] = (1. - cos((2 * 3.14159 * i) / npoints))/npoints; - for (; i < npoints+MAXVSTAKEN; i++) buf[i] = 0; - x->clock = clock_new(x, env_tilde_tick); - x->outlet = outlet_new(x, &s_float); - x->a = 0; - return x; -} -static t_int *env_tilde_perform(t_int *w) { - PERFORM3ARGS(t_sigenv *,x, t_float *,in, int,n); - float *sump = x->sumbuf; - in += n; - for (int count = x->phase; count < x->npoints; count += x->realperiod, sump++) { - float *hp = x->buf + count; - float *fp = in; - float sum = *sump; - for (int i = 0; i < n; i++) { - fp--; - sum += *hp++ * (*fp * *fp); - } - *sump = sum; - } - sump[0] = 0; - x->phase -= n; - if (x->phase < 0) { - x->result = x->sumbuf[0]; - sump = x->sumbuf; - for (int count = x->realperiod; count < x->npoints; count += x->realperiod, sump++) sump[0] = sump[1]; - sump[0] = 0; - x->phase = x->realperiod - n; - clock_delay(x->clock, 0L); - } - return w+4; -} -/* tb: loop unrolling and simd */ -static float env_tilde_accum_8(t_float* in, t_float* hp, t_int n) { - float ret = 0; - n>>=3; - for (int i = 0; i !=n; ++i) { - in--; ret += *hp++ * (*in * *in); - in--; ret += *hp++ * (*in * *in); - in--; ret += *hp++ * (*in * *in); - in--; ret += *hp++ * (*in * *in); - in--; ret += *hp++ * (*in * *in); - in--; ret += *hp++ * (*in * *in); - in--; ret += *hp++ * (*in * *in); - in--; ret += *hp++ * (*in * *in); - } - return ret; -} -static t_int *env_tilde_perf8(t_int *w) { - PERFORM3ARGS(t_sigenv *,x, t_float *,in, int,n); - float *sump = x->sumbuf; - in += n; - for (int count = x->phase; count < x->npoints; count += x->realperiod, sump++) { - *sump += env_tilde_accum_8(in, x->buf + count, n); - } - sump[0] = 0; - x->phase -= n; - if (x->phase < 0) { - x->result = x->sumbuf[0]; - float *sump = x->sumbuf; - for (int count = x->realperiod; count < x->npoints; count += x->realperiod, sump++) sump[0] = sump[1]; - sump[0] = 0; - x->phase = x->realperiod - n; - clock_delay(x->clock, 0L); - } - return w+4; -} -static t_int *env_tilde_perf_simd(t_int *w) { - PERFORM3ARGS(t_sigenv *,x, t_float *,in, int,n); - float *sump = x->sumbuf; - in += n; - for (int count = x->phase; count < x->npoints; count += x->realperiod, sump++) { - *sump += env_tilde_accum_simd(in, x->buf + count, n); - } - sump[0] = 0; - x->phase -= n; - if (x->phase < 0) { - x->result = x->sumbuf[0]; - float *sump = x->sumbuf; - for (int count = x->realperiod; count < x->npoints; count += x->realperiod, sump++) sump[0] = sump[1]; - sump[0] = 0; - x->phase = x->realperiod - n; - clock_delay(x->clock, 0L); - } - return w+4; -} -static void env_tilde_dsp(t_sigenv *x, t_signal **sp) { - int mod = x->period % sp[0]->n; - if (mod) x->realperiod = x->period + sp[0]->n - mod; else x->realperiod = x->period; - if (sp[0]->n & 7) - dsp_add(env_tilde_perform, 3, x, sp[0]->v, sp[0]->n); - else if (SIMD_CHECK1(sp[0]->n, sp[0]->v)) - dsp_add(env_tilde_perf_simd, 3, x, sp[0]->v, sp[0]->n); - else dsp_add(env_tilde_perf8, 3, x, sp[0]->v, sp[0]->n); - if (sp[0]->n > MAXVSTAKEN) bug("env_tilde_dsp"); -} -static void env_tilde_tick(t_sigenv *x) {x->outlet->send(powtodb(x->result));} -static void env_tilde_ff(t_sigenv *x) { - clock_free(x->clock); - freealignedbytes(x->buf, (x->npoints + MAXVSTAKEN) * sizeof(float)); -} -void env_tilde_setup() { - env_tilde_class = class_new2("env~",env_tilde_new,env_tilde_ff,sizeof(t_sigenv),0,"FF"); - CLASS_MAINSIGNALIN(env_tilde_class, t_sigenv, a); - class_addmethod2(env_tilde_class, env_tilde_dsp, "dsp",""); -} - -/* --------------------- threshold~ ----------------------------- */ -static t_class *threshold_tilde_class; -struct t_threshold_tilde : t_object { - t_clock *clock; /* wakeup for message output */ - float a; /* scalar inlet */ - int state; /* 1 = high, 0 = low */ - float hithresh; /* value of high threshold */ - float lothresh; /* value of low threshold */ - float deadwait; /* msec remaining in dead period */ - float msecpertick; /* msec per DSP tick */ - float hideadtime; /* hi dead time in msec */ - float lodeadtime; /* lo dead time in msec */ -}; -static void threshold_tilde_tick(t_threshold_tilde *x); -/* "set" message to specify thresholds and dead times */ -static void threshold_tilde_set(t_threshold_tilde *x, - t_floatarg hithresh, t_floatarg hideadtime, - t_floatarg lothresh, t_floatarg lodeadtime) { - if (lothresh > hithresh) lothresh = hithresh; - x->hithresh = hithresh; x->hideadtime = hideadtime; - x->lothresh = lothresh; x->lodeadtime = lodeadtime; -} -static t_threshold_tilde *threshold_tilde_new(t_floatarg hithresh, - t_floatarg hideadtime, t_floatarg lothresh, t_floatarg lodeadtime) { - t_threshold_tilde *x = (t_threshold_tilde *)pd_new(threshold_tilde_class); - x->state = 0; /* low state */ - x->deadwait = 0; /* no dead time */ - x->clock = clock_new(x, threshold_tilde_tick); - outlet_new(x, &s_bang); - outlet_new(x, &s_bang); - inlet_new(x, x, &s_float, gensym("ft1")); - x->msecpertick = 0.; - x->a = 0; - threshold_tilde_set(x, hithresh, hideadtime, lothresh, lodeadtime); - return x; -} -/* number in inlet sets state -- note incompatible with JMAX which used - "int" message for this, impossible here because of auto signal conversion */ -static void threshold_tilde_ft1(t_threshold_tilde *x, t_floatarg f) { - x->state = (f != 0); - x->deadwait = 0; -} -static void threshold_tilde_tick(t_threshold_tilde *x) {x->out(!x->state)->send();} -static t_int *threshold_tilde_perform(t_int *w) { - PERFORM3ARGS(float *,in1, t_threshold_tilde *,x, int,n); - if (x->deadwait > 0) - x->deadwait -= x->msecpertick; - else if (x->state) { - /* we're high; look for low sample */ - for (; n--; in1++) { - if (*in1 < x->lothresh) { - clock_delay(x->clock, 0L); - x->state = 0; - x->deadwait = x->lodeadtime; - goto done; - } - } - } else { - /* we're low; look for high sample */ - for (; n--; in1++) { - if (*in1 >= x->hithresh) { - clock_delay(x->clock, 0L); - x->state = 1; - x->deadwait = x->hideadtime; - goto done; - } - } - } -done: - return w+4; -} -void threshold_tilde_dsp(t_threshold_tilde *x, t_signal **sp) { - x->msecpertick = 1000. * sp[0]->n / sp[0]->sr; - dsp_add(threshold_tilde_perform, 3, sp[0]->v, x, sp[0]->n); -} -static void threshold_tilde_ff(t_threshold_tilde *x) {clock_free(x->clock);} -static void threshold_tilde_setup() { - t_class *c = threshold_tilde_class = - class_new2("threshold~",threshold_tilde_new,threshold_tilde_ff,sizeof(t_threshold_tilde), 0, "FFFF"); - CLASS_MAINSIGNALIN(c, t_threshold_tilde, a); - class_addmethod2(c, threshold_tilde_set, "set","ffff"); - class_addmethod2(c, threshold_tilde_ft1, "ft1","f"); - class_addmethod2(c, threshold_tilde_dsp, "dsp",""); -} - -/* ----------------------------- dac~ --------------------------- */ -static t_class *dac_class; -struct t_dac : t_object { - t_int n; - t_int *vec; - float a; -}; -static void *dac_new(t_symbol *s, int argc, t_atom *argv) { - t_dac *x = (t_dac *)pd_new(dac_class); - t_atom defarg[2]; - if (!argc) { - argv = defarg; - argc = 2; - SETFLOAT(&defarg[0], 1); - SETFLOAT(&defarg[1], 2); - } - x->n = argc; - x->vec = (t_int *)getbytes(argc * sizeof(*x->vec)); - for (int i = 0; i < argc; i++) x->vec[i] = atom_getintarg(i, argc, argv); - for (int i = 1; i < argc; i++) inlet_new(x, x, &s_signal, &s_signal); - x->a = 0; - return x; -} -static void dac_dsp(t_dac *x, t_signal **sp) { - t_int i, *ip; - t_signal **sp2; - for (i = x->n, ip = x->vec, sp2 = sp; i--; ip++, sp2++) { - int ch = *ip - 1; - if ((*sp2)->n != sys_dacblocksize) error("dac~: bad vector size"); - else if (ch >= 0 && ch < sys_get_outchannels()) { - if(SIMD_CHECK3(sys_dacblocksize,sys_soundout + sys_dacblocksize*ch, (*sp2)->v,sys_soundout + sys_dacblocksize*ch)) - dsp_add(plus_perf_simd, 4, sys_soundout + sys_dacblocksize*ch, - (*sp2)->v, sys_soundout + sys_dacblocksize*ch, sys_dacblocksize); - else - dsp_add(plus_perform, 4, sys_soundout + sys_dacblocksize*ch, (*sp2)->v, sys_soundout + sys_dacblocksize*ch, - sys_dacblocksize); - } - } -} -static void dac_free(t_dac *x) {free(x->vec);} -static void dac_setup() { - dac_class = class_new2("dac~",dac_new,dac_free,sizeof(t_dac),0,"*"); - CLASS_MAINSIGNALIN(dac_class, t_dac, a); - class_addmethod2(dac_class, dac_dsp, "dsp","!"); - class_sethelpsymbol(dac_class, gensym("adc~_dac~")); -} - -/* ----------------------------- adc~ --------------------------- */ -static t_class *adc_class; -struct t_adc : t_object { - t_int n; - t_int *vec; -}; -static void *adc_new(t_symbol *s, int argc, t_atom *argv) { - t_adc *x = (t_adc *)pd_new(adc_class); - t_atom defarg[2]; - if (!argc) { - argv = defarg; - argc = 2; - SETFLOAT(&defarg[0], 1); - SETFLOAT(&defarg[1], 2); - } - x->n = argc; - x->vec = (t_int *)getbytes(argc * sizeof(*x->vec)); - for (int i = 0; i < argc; i++) x->vec[i] = atom_getintarg(i, argc, argv); - for (int i = 0; i < argc; i++) outlet_new(x, &s_signal); - return x; -} -t_int *copy_perform(t_int *w) { - PERFORM3ARGS(t_float *,in1, t_float *,out, int,n); - while (n--) *out++ = *in1++; - return w+4; -} -t_int *copy_perf8(t_int *w) { - PERFORM3ARGS(t_float *,in1, t_float *,out, int,n); - for (; n; n -= 8, in1 += 8, out += 8) { - out[0] = in1[0]; - out[1] = in1[1]; - out[2] = in1[2]; - out[3] = in1[3]; - out[4] = in1[4]; - out[5] = in1[5]; - out[6] = in1[6]; - out[7] = in1[7]; - } - return w+4; -} -void dsp_add_copy(t_sample *in, t_sample *out, int n) { - if (n&7) dsp_add(copy_perform, 3, in, out, n); - else if (SIMD_CHECK2(n,in,out)) dsp_add(copy_perf_simd, 3, in, out, n); - else dsp_add(copy_perf8, 3, in, out, n); -} -static void adc_dsp(t_adc *x, t_signal **sp) { - t_int i, *ip; - t_signal **sp2; - for (i = x->n, ip = x->vec, sp2 = sp; i--; ip++, sp2++) { - int ch = *ip - 1; - if ((*sp2)->n != sys_dacblocksize) - error("adc~: bad vector size"); - else if (ch >= 0 && ch < sys_get_inchannels()) - dsp_add_copy(sys_soundin + sys_dacblocksize*ch, (*sp2)->v, sys_dacblocksize); - else dsp_add_zero((*sp2)->v, sys_dacblocksize); - } -} -static void adc_free(t_adc *x) {free(x->vec);} -static void adc_setup() { - adc_class = class_new2("adc~",adc_new,adc_free,sizeof(t_adc),0,"*"); - class_addmethod2(adc_class, adc_dsp, "dsp","!"); - class_sethelpsymbol(adc_class, gensym("adc~_dac~")); -} - -/* ----------------------------- delwrite~ ----------------------------- */ -static t_class *sigdelwrite_class; -struct t_delwritectl { - int c_n; - float *c_vec; - int c_phase; -}; -struct t_sigdelwrite : t_object { - t_symbol *sym; - t_delwritectl cspace; - int sortno; /* DSP sort number at which this was last put on chain */ - int rsortno; /* DSP sort # for first delread or write in chain */ - int vecsize; /* vector size for delread~ to use */ - float a; -}; -#define XTRASAMPS 4 -#define SAMPBLK 4 -/* routine to check that all delwrites/delreads/vds have same vecsize */ -static void sigdelwrite_checkvecsize(t_sigdelwrite *x, int vecsize) { - if (x->rsortno != ugen_getsortno()) { - x->vecsize = vecsize; - x->rsortno = ugen_getsortno(); - } - /* LATER this should really check sample rate and blocking, once that is supported. - Probably we don't actually care about vecsize. For now just suppress this check. */ -#if 0 - else if (vecsize != x->vecsize) error("delread/delwrite/vd vector size mismatch"); -#endif -} -static void *sigdelwrite_new(t_symbol *s, t_floatarg msec) { - t_sigdelwrite *x = (t_sigdelwrite *)pd_new(sigdelwrite_class); - if (!*s->name) s = gensym("delwrite~"); - pd_bind(x, s); - x->sym = s; - int nsamps = (int)(msec * sys_getsr() * (float)(0.001f)); - if (nsamps < 1) nsamps = 1; - nsamps += ((- nsamps) & (SAMPBLK - 1)); - nsamps += DEFDELVS; -#ifdef SIMD_BYTEALIGN - nsamps += (SIMD_BYTEALIGN - nsamps) % SIMD_BYTEALIGN; /* tb: for simd */ -#endif - x->cspace.c_n = nsamps; - x->cspace.c_vec = (float *)getalignedbytes((nsamps + XTRASAMPS) * sizeof(float)); - x->cspace.c_phase = XTRASAMPS; - x->sortno = 0; - x->vecsize = 0; - x->a = 0; - return x; -} -static t_int *sigdelwrite_perform(t_int *w) { - PERFORM3ARGS(t_float *,in, t_delwritectl *,c, int,n); - int phase = c->c_phase, nsamps = c->c_n; - float *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS); - phase += n; - while (n--) { - float f = *in++; - if (PD_BIGORSMALL(f)) - f = 0; - *bp++ = f; - if (bp == ep) { - vp[0] = ep[-4]; - vp[1] = ep[-3]; - vp[2] = ep[-2]; - vp[3] = ep[-1]; - bp = vp + XTRASAMPS; - phase -= nsamps; - } - } - c->c_phase = phase; - return w+4; -} -static t_int *sigdelwrite_perf8(t_int *w) { - PERFORM3ARGS(t_float *,in, t_delwritectl *,c, int,n); - int phase = c->c_phase, nsamps = c->c_n; - float *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS); - phase += n; - if (phase > nsamps) - while (n--) { - float f = *in++; - if (PD_BIGORSMALL(f)) f = 0; - *bp++ = f; - if (bp == ep) { - vp[0] = ep[-4]; - vp[1] = ep[-3]; - vp[2] = ep[-2]; - vp[3] = ep[-1]; - bp = vp + XTRASAMPS; - phase -= nsamps; - } - } - else testcopyvec_8(bp, in, n); - c->c_phase = phase; - return w+4; -} -static t_int *sigdelwrite_perfsimd(t_int *w) { - PERFORM3ARGS(t_float *,in, t_delwritectl *,c, int,n); - int phase = c->c_phase, nsamps = c->c_n; - float *vp = c->c_vec, *bp = vp + phase, *ep = vp + (c->c_n + XTRASAMPS); - phase += n; - if (phase > nsamps ) - while (n--) { - float f = *in++; - if (PD_BIGORSMALL(f)) f = 0; - *bp++ = f; - if (bp == ep) { - vp[0] = ep[-4]; - vp[1] = ep[-3]; - vp[2] = ep[-2]; - vp[3] = ep[-1]; - bp = vp + XTRASAMPS; - phase -= nsamps; - } - } - else testcopyvec_simd(bp, in, n); - c->c_phase = phase; - return w+4; -} -static void sigdelwrite_dsp(t_sigdelwrite *x, t_signal **sp) { - if (sp[0]->n & 7) dsp_add(sigdelwrite_perform, 3, sp[0]->v, &x->cspace, sp[0]->n); - else if (SIMD_CHECK1(sp[0]->n, sp[0]->v)) dsp_add(sigdelwrite_perfsimd, 3, sp[0]->v, &x->cspace, sp[0]->n); - else dsp_add(sigdelwrite_perf8, 3, sp[0]->v, &x->cspace, sp[0]->n); - x->sortno = ugen_getsortno(); - sigdelwrite_checkvecsize(x, sp[0]->n); -} -static void sigdelwrite_free(t_sigdelwrite *x) { - pd_unbind(x, x->sym); - freealignedbytes(x->cspace.c_vec, (x->cspace.c_n + XTRASAMPS) * sizeof(float)); -} -static void sigdelwrite_setup() { - sigdelwrite_class = class_new2("delwrite~",sigdelwrite_new,sigdelwrite_free,sizeof(t_sigdelwrite),0,"SF"); - CLASS_MAINSIGNALIN(sigdelwrite_class, t_sigdelwrite, a); - class_addmethod2(sigdelwrite_class, sigdelwrite_dsp,"dsp",""); -} - -/* ----------------------------- delread~ ----------------------------- */ -static t_class *sigdelread_class; -struct t_sigdelread : t_object { - t_symbol *sym; - t_float deltime; /* delay in msec */ - int delsamps; /* delay in samples */ - t_float sr; /* samples per msec */ - t_float n; /* vector size */ - int zerodel; /* 0 or vecsize depending on read/write order */ - void (*copy_fp)(t_float*, const t_float*, int); /* tb: copy function */ -}; -static void sigdelread_float(t_sigdelread *x, t_float f); -static void *sigdelread_new(t_symbol *s, t_floatarg f) { - t_sigdelread *x = (t_sigdelread *)pd_new(sigdelread_class); - x->sym = s; - x->sr = 1; - x->n = 1; - x->zerodel = 0; - sigdelread_float(x, f); - outlet_new(x, &s_signal); - return x; -} -static void sigdelread_float(t_sigdelread *x, t_float f) { - t_sigdelwrite *delwriter = (t_sigdelwrite *)pd_findbyclass(x->sym, sigdelwrite_class); - x->deltime = f; - if (delwriter) { - x->delsamps = (int)(0.5 + x->sr * x->deltime + x->n - x->zerodel); - if (x->delsamps < x->n) x->delsamps = (int)x->n; - else if (x->delsamps > delwriter->cspace.c_n - DEFDELVS) - x->delsamps = (int)(delwriter->cspace.c_n - DEFDELVS); - } - if (SIMD_CHKCNT(x->delsamps)) x->copy_fp = copyvec_simd; - else x->copy_fp = copyvec_simd_unalignedsrc; -} -static t_int *sigdelread_perform(t_int *w) { - PERFORM4ARGS(t_float *,out, t_delwritectl *,c, int *,delsampsp, int,n); - int delsamps = *delsampsp; - int phase = c->c_phase - delsamps, nsamps = c->c_n; - float *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS); - if (phase < 0) phase += nsamps; - bp = vp + phase; - while (n--) { - *out++ = *bp++; - if (bp == ep) bp -= nsamps; - } - return w+5; -} -static t_int *sigdelread_perf8(t_int *w) { - PERFORM4ARGS(t_float *,out, t_delwritectl *,c, int *,delsampsp, int,n); - int delsamps = *delsampsp; - int phase = c->c_phase - delsamps, nsamps = c->c_n; - float *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS); - if (phase < 0) phase += nsamps; - bp = vp + phase; - if (phase + n > nsamps) - while (n--) { - *out++ = *bp++; - if (bp == ep) bp -= nsamps; - } - else copyvec_8(out, bp, n); - return w+5; -} -static t_int *sigdelread_perfsimd(t_int *w) { - PERFORM5ARGS(t_float *,out, t_delwritectl *,c, int *,delsampsp, int,n, t_sigdelread *,x); - int delsamps = *delsampsp; - int phase = c->c_phase - delsamps, nsamps = c->c_n; - float *vp = c->c_vec, *bp, *ep = vp + (c->c_n + XTRASAMPS); - if (phase < 0) phase += nsamps; - bp = vp + phase; - if (phase + n > nsamps) while (n--) {*out++ = *bp++; if (bp == ep) bp -= nsamps;} - else x->copy_fp(out, bp, n); - return w+6; -} -static void sigdelread_dsp(t_sigdelread *x, t_signal **sp) { - t_sigdelwrite *delwriter = (t_sigdelwrite *)pd_findbyclass(x->sym, sigdelwrite_class); - x->sr = sp[0]->sr * 0.001; - x->n = sp[0]->n; - if (delwriter) { - sigdelwrite_checkvecsize(delwriter, sp[0]->n); - x->zerodel = (delwriter->sortno == ugen_getsortno() ? - 0 : delwriter->vecsize); - sigdelread_float(x, x->deltime); - if (sp[0]->n & 7) - dsp_add(sigdelread_perform, 4, sp[0]->v, &delwriter->cspace, &x->delsamps, sp[0]->n); - else if (SIMD_CHECK1(sp[0]->n, sp[0]->v)) - dsp_add(sigdelread_perfsimd, 5, sp[0]->v, &delwriter->cspace, &x->delsamps, sp[0]->n, x); - else dsp_add(sigdelread_perf8, 4, sp[0]->v, &delwriter->cspace, &x->delsamps, sp[0]->n); - } else if (*x->sym->name) error("delread~: %s: no such delwrite~",x->sym->name); -} -static void sigdelread_setup() { - sigdelread_class = class_new2("delread~",sigdelread_new,0,sizeof(t_sigdelread),0,"SF"); - class_addmethod2(sigdelread_class, sigdelread_dsp,"dsp",""); - class_addfloat(sigdelread_class, sigdelread_float); -} - -/* ----------------------------- vd~ ----------------------------- */ -static t_class *sigvd_class; -struct t_sigvd : t_object { - t_symbol *sym; - t_float sr; /* samples per msec */ - int zerodel; /* 0 or vecsize depending on read/write order */ - float a; -}; -static void *sigvd_new(t_symbol *s) { - t_sigvd *x = (t_sigvd *)pd_new(sigvd_class); - if (!*s->name) s = gensym("vd~"); - x->sym = s; - x->sr = 1; - x->zerodel = 0; - outlet_new(x, &s_signal); - x->a = 0; - return x; -} -static t_int *sigvd_perform(t_int *w) { - PERFORM5ARGS(t_float *,in, t_float *,out, t_delwritectl *,ctl, t_sigvd *,x, int,n); - int nsamps = ctl->c_n; - float limit = nsamps - n - 1; - float fn = n-1; - float *vp = ctl->c_vec, *bp, *wp = vp + ctl->c_phase; - float zerodel = x->zerodel; - while (n--) { - float delsamps = x->sr * *in++ - zerodel, frac; - int idelsamps; - float a, b, c, d, cminusb; - if (delsamps < 1.00001f) delsamps = 1.00001f; - if (delsamps > limit) delsamps = limit; - delsamps += fn; - fn = fn - 1.0f; - idelsamps = (int)delsamps; - frac = delsamps - (float)idelsamps; - bp = wp - idelsamps; - if (bp < vp + 4) bp += nsamps; - d = bp[-3]; - c = bp[-2]; - b = bp[-1]; - a = bp[0]; - cminusb = c-b; - *out++ = b + frac * ( - cminusb - 0.1666667f * (1.-frac) * ( - (d - a - 3.0f * cminusb) * frac + (d + 2.0f*a - 3.0f*b) - ) - ); - } - return w+6; -} -static void sigvd_dsp(t_sigvd *x, t_signal **sp) { - t_sigdelwrite *delwriter = (t_sigdelwrite *)pd_findbyclass(x->sym, sigdelwrite_class); - x->sr = sp[0]->sr * 0.001; - if (delwriter) { - sigdelwrite_checkvecsize(delwriter, sp[0]->n); - x->zerodel = (delwriter->sortno == ugen_getsortno() ? 0 : delwriter->vecsize); - dsp_add(sigvd_perform, 5, sp[0]->v, sp[1]->v, &delwriter->cspace, x, sp[0]->n); - } else error("vd~: %s: no such delwrite~",x->sym->name); -} -static void sigvd_setup() { - sigvd_class = class_new2("vd~",sigvd_new,0,sizeof(t_sigvd),0,"S"); - class_addmethod2(sigvd_class, sigvd_dsp, "dsp",""); - CLASS_MAINSIGNALIN(sigvd_class, t_sigvd, a); -} - -#ifndef HAVE_LIBFFTW3F -/* ------------------------ fft~ and ifft~ -------------------------------- */ -/* ----------------------- rfft~ -------------------------------- */ -/* ----------------------- rifft~ -------------------------------- */ -static t_class *sigfft_class; struct t_sigfft : t_object {float a;}; -static t_class *sigifft_class; struct t_sigifft : t_object {float a;}; -static t_class *sigrfft_class; struct t_sigrfft : t_object {float a;}; -static t_class *sigrifft_class; struct t_sigrifft : t_object {float a;}; - -static void *sigfft_new() { - t_sigfft *x = (t_sigfft *)pd_new(sigfft_class); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - inlet_new(x, x, &s_signal, &s_signal); x->a=0; return x;} -static void *sigifft_new() { - t_sigifft *x = (t_sigifft *)pd_new(sigifft_class); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - inlet_new(x, x, &s_signal, &s_signal); x->a=0; return x;} -static void *sigrfft_new() { - t_sigrfft *x = (t_sigrfft *)pd_new(sigrfft_class); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - x->a = 0; return x;} -static void *sigrifft_new() { - t_sigrifft *x = (t_sigrifft *)pd_new(sigrifft_class); - inlet_new(x, x, &s_signal, &s_signal); - outlet_new(x, &s_signal); - x->a = 0; return x;} - -static t_int *sigfft_swap(t_int *w) { - PERFORM3ARGS(float *,in1, float *,in2, int,n); - for (;n--; in1++, in2++) { - float f = *in1; - *in1 = *in2; - *in2 = f; - } - return w+4; -} -static t_int * sigfft_perform(t_int *w) {float *in1=(t_float *)w[1], *in2=(t_float *)w[2]; int n=w[3]; mayer_fft(n,in1,in2); return w+4;} -static t_int * sigifft_perform(t_int *w) {float *in1=(t_float *)w[1], *in2=(t_float *)w[2]; int n=w[3]; mayer_ifft(n,in1,in2); return w+4;} -static t_int * sigrfft_perform(t_int *w) {float *in =(t_float *)w[1]; int n = w[2]; mayer_realfft(n, in); return w+3;} -static t_int *sigrifft_perform(t_int *w) {float *in =(t_float *)w[1]; int n = w[2]; mayer_realifft(n, in); return w+3;} - -static void sigfft_dspx(t_sigfft *x, t_signal **sp, t_int *(*f)(t_int *w)) { - int n = sp[0]->n; - float *in1 = sp[0]->v; - float *in2 = sp[1]->v; - float *out1 = sp[2]->v; - float *out2 = sp[3]->v; - if (out1 == in2 && out2 == in1) - dsp_add(sigfft_swap, 3, out1, out2, n); - else if (out1 == in2) { - dsp_add(copy_perform, 3, in2, out2, n); - dsp_add(copy_perform, 3, in1, out1, n); - } else { - if (out1 != in1) dsp_add(copy_perform, 3, in1, out1, n); - if (out2 != in2) dsp_add(copy_perform, 3, in2, out2, n); - } - dsp_add(f, 3, sp[2]->v, sp[3]->v, n); -} -static void sigfft_dsp(t_sigfft *x, t_signal **sp) {sigfft_dspx(x, sp, sigfft_perform);} -static void sigifft_dsp(t_sigfft *x, t_signal **sp) {sigfft_dspx(x, sp, sigifft_perform);} - -static t_int *sigrfft_flip(t_int *w) { - PERFORM3ARGS(float *,in, float *,out, int,n); - while (n--) *(--out) = *in++; - *(--out) = 0; /* to hell with it */ - return w+4; -} -static void sigrfft_dsp(t_sigrfft *x, t_signal **sp) { - int n = sp[0]->n, n2 = (n>>1); - float *in1 = sp[0]->v; - float *out1 = sp[1]->v; - float *out2 = sp[2]->v; - if (n < 4) { - error("fft: minimum 4 points"); - return; - } - /* this probably never happens */ - if (in1 == out2) { - dsp_add(sigrfft_perform, 2, out2, n); - dsp_add(copy_perform, 3, out2, out1, n2); - dsp_add(sigrfft_flip, 3, out2 + (n2+1), out2 + n2, n2-1); - } else { - if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n); - dsp_add(sigrfft_perform, 2, out1, n); - dsp_add(sigrfft_flip, 3, out1 + (n2+1), out2 + n2, n2-1); - } - dsp_add_zero(out1 + n2, n2); - dsp_add_zero(out2 + n2, n2); -} - -static void sigrifft_dsp(t_sigrifft *x, t_signal **sp) { - int n = sp[0]->n, n2 = (n>>1); - float *in1 = sp[0]->v; - float *in2 = sp[1]->v; - float *out1 = sp[2]->v; - if (n < 4) {error("fft: minimum 4 points"); return;} - if (in2 == out1) { - dsp_add(sigrfft_flip, 3, out1+1, out1 + n, (n2-1)); - dsp_add(copy_perform, 3, in1, out1, n2); - } else { - if (in1 != out1) dsp_add(copy_perform, 3, in1, out1, n2); - dsp_add(sigrfft_flip, 3, in2+1, out1 + n, n2-1); - } - dsp_add(sigrifft_perform, 2, out1, n); -} -static void sigfft_setup() { - sigfft_class = class_new2("fft~", sigfft_new, 0,sizeof(t_sigfft), 0,""); - sigifft_class = class_new2("ifft~", sigifft_new, 0,sizeof(t_sigfft), 0,""); - sigrfft_class = class_new2("rfft~", sigrfft_new, 0,sizeof(t_sigrfft), 0,""); - sigrifft_class = class_new2("rifft~",sigrifft_new,0,sizeof(t_sigrifft),0,""); - CLASS_MAINSIGNALIN(sigfft_class, t_sigfft, a); - CLASS_MAINSIGNALIN(sigifft_class, t_sigfft, a); - CLASS_MAINSIGNALIN(sigrfft_class, t_sigrfft, a); - CLASS_MAINSIGNALIN(sigrifft_class,t_sigrifft,a); - class_addmethod2(sigfft_class, sigfft_dsp, "dsp",""); - class_addmethod2(sigifft_class, sigifft_dsp, "dsp",""); - class_addmethod2(sigrfft_class, sigrfft_dsp, "dsp",""); - class_addmethod2(sigrifft_class,sigrifft_dsp,"dsp",""); - class_sethelpsymbol(sigifft_class, gensym("fft~")); - class_sethelpsymbol(sigrfft_class, gensym("fft~")); - class_sethelpsymbol(sigrifft_class,gensym("fft~")); -} - -#else -/* Support for fftw3 by Tim Blechmann */ -/* ------------------------ fft~ and ifft~ -------------------------------- */ -/* ----------------------- rfft~ --------------------------------- */ -/* ----------------------- rifft~ -------------------------------- */ - -static t_class *sigfftw_class; struct t_sigfftw : t_object {float a; fftwf_plan plan; fftwf_iodim dim;}; -static t_class *sigifftw_class; struct t_sigifftw : t_object {float a; fftwf_plan plan; fftwf_iodim dim;}; -static t_class *sigrfftw_class; struct t_sigrfftw : t_object {float a; fftwf_plan plan; fftwf_iodim dim;}; -static t_class *sigrifftw_class;struct t_sigrifftw : t_object {float a; fftwf_plan plan; fftwf_iodim dim;}; - -static void *sigfftw_new() { - t_sigfftw *x = (t_sigfftw *)pd_new(sigfftw_class); outlet_new(x, &s_signal); outlet_new(x, &s_signal); - inlet_new(x, x, &s_signal, &s_signal); x->a=0; return x;} -static void *sigifftw_new() { - t_sigifftw *x = (t_sigifftw *)pd_new(sigfftw_class); outlet_new(x, &s_signal); outlet_new(x, &s_signal); - inlet_new(x, x, &s_signal, &s_signal); x->a=0; return x;} -static void *sigrfftw_new() { - t_sigrfftw *x = (t_sigrfftw *)pd_new(sigrfftw_class); - outlet_new(x, &s_signal); outlet_new(x, &s_signal); x->a=0; return x;} -static void *sigrifftw_new() { - t_sigrifftw *x = (t_sigrifftw *)pd_new(sigrifftw_class); - inlet_new(x, x, &s_signal, &s_signal); - outlet_new(x, &s_signal); x->a=0; return x;} - -static void sigfftw_free( t_sigfftw *x) {fftwf_destroy_plan(x->plan);} -static void sigifftw_free( t_sigifftw *x) {fftwf_destroy_plan(x->plan);} -static void sigrfftw_free( t_sigrfftw *x) {fftwf_destroy_plan(x->plan);} -static void sigrifftw_free(t_sigrifftw *x) {fftwf_destroy_plan(x->plan);} - -/* for compatibility reasons with the mayer fft, we'll have to invert some samples. this is ugly, but someone might rely on that. */ -static void sigrfftw_invert(t_sample * s, t_int n) { - while (n!=0) {--n; s[n]=-s[n];} -} -static t_int *sigfftw_perform(t_int *w) { - fftwf_execute(*(fftwf_plan *)w[1]); - return w+2; -} -static t_int *sigrfftw_perform(t_int *w) { - fftwf_execute(*(fftwf_plan*)w[1]); - sigrfftw_invert((t_sample*)w[2],(t_int)w[3]); - return w+4; -} -static t_int *sigrifftw_perform(t_int *w) { - sigrfftw_invert((t_sample *)w[2],w[3]); - fftwf_execute(*(fftwf_plan*)w[1]); - return w+4; -} - -static void sigfftw_dsp(t_sigfftw *x, t_signal **sp) { - int n = sp[0]->n; - float *in1 = sp[0]->v; - float *in2 = sp[1]->v; - float *out1 = sp[2]->v; - float *out2 = sp[3]->v; - x->dim.n=n; - x->dim.is=1; - x->dim.os=1; - x->plan = fftwf_plan_guru_split_dft(1, &(x->dim), 0, NULL, in1, in2, out1, out2, FFTW_ESTIMATE); - dsp_add(sigfftw_perform, 1, &x->plan); -} -static void sigifftw_dsp(t_sigfftw *x, t_signal **sp) { - int n = sp[0]->n; - float *in1 = sp[0]->v; - float *in2 = sp[1]->v; - float *out1 = sp[2]->v; - float *out2 = sp[3]->v; - x->dim.n=n; - x->dim.is=1; - x->dim.os=1; - x->plan = fftwf_plan_guru_split_dft(1, &(x->dim), 0, NULL, in2, in1, out2, out1, FFTW_ESTIMATE); - dsp_add(sigfftw_perform, 1, &x->plan); -} - -static void sigrfftw_dsp(t_sigrfftw *x, t_signal **sp) { - int n = sp[0]->n, n2 = (n>>1); - float *in = sp[0]->v; - float *out1 = sp[1]->v; - float *out2 = sp[2]->v; - if (n < 4) {error("fft: minimum 4 points"); return;} - x->dim.n=n; - x->dim.is=1; - x->dim.os=1; - x->plan = fftwf_plan_guru_split_dft_r2c(1, &(x->dim), 0, NULL, in, out1, out2, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT); - dsp_add(sigrfftw_perform,3,&x->plan,out2+1,n2-1); - dsp_add_zero(out1 + n2, n2); - dsp_add_zero(out2 + n2, n2); -} - -static void sigrifftw_dsp(t_sigrifftw *x, t_signal **sp) { - int n = sp[0]->n, n2 = (n>>1); - float *in1 = sp[0]->v; - float *in2 = sp[1]->v; - float *out = sp[2]->v; - if (n < 4) {error("fft: minimum 4 points"); return;} - x->dim.n=n; - x->dim.is=1; - x->dim.os=1; - x->plan = fftwf_plan_guru_split_dft_c2r(1, &(x->dim), 0, NULL, in1, in2, out, FFTW_ESTIMATE | FFTW_PRESERVE_INPUT); - dsp_add_zero(in1+ n/2, n/2); - dsp_add(sigrifftw_perform,3,&x->plan,in2,n2); -} -static void sigfftw_setup() { - sigfftw_class = class_new2( "fft~",sigfftw_new, sigfftw_free, sizeof(t_sigfftw), 0,""); - sigifftw_class = class_new2( "ifft~",sigifftw_new, sigifftw_free, sizeof(t_sigfftw), 0,""); - sigrfftw_class = class_new2( "rfft~",sigrfftw_new, sigrfftw_free, sizeof(t_sigrfftw), 0,""); - sigrifftw_class = class_new2("rifft~",sigrifftw_new,sigrifftw_free,sizeof(t_sigrifftw),0,""); - CLASS_MAINSIGNALIN(sigfftw_class, t_sigfftw, a); - CLASS_MAINSIGNALIN(sigifftw_class, t_sigfftw, a); - CLASS_MAINSIGNALIN(sigrfftw_class, t_sigrfftw, a); - CLASS_MAINSIGNALIN(sigrifftw_class,t_sigrifftw,a); - class_addmethod2(sigfftw_class, sigfftw_dsp, "dsp",""); - class_addmethod2(sigifftw_class, sigifftw_dsp, "dsp",""); - class_addmethod2(sigrfftw_class, sigrfftw_dsp, "dsp",""); - class_addmethod2(sigrifftw_class, sigrifftw_dsp,"dsp",""); - class_sethelpsymbol(sigifftw_class, gensym("fft~")); - class_sethelpsymbol(sigrfftw_class, gensym("fft~")); - class_sethelpsymbol(sigrifftw_class,gensym("fft~")); -} -#endif /* HAVE_LIBFFTW3F */ -/* end of FFTW support */ - -/* ----------------------- framp~ -------------------------------- */ -static t_class *sigframp_class; -struct t_sigframp : t_object { - float a; -}; -static void *sigframp_new() { - t_sigframp *x = (t_sigframp *)pd_new(sigframp_class); - inlet_new(x, x, &s_signal, &s_signal); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - x->a = 0; - return x; -} -static t_int *sigframp_perform(t_int *w) { - PERFORM5ARGS(float *,inreal, float *,inimag, float *,outfreq, float *,outamp, int,n); - float lastreal = 0, currentreal = inreal[0], nextreal = inreal[1]; - float lastimag = 0, currentimag = inimag[0], nextimag = inimag[1]; - int m = n + 1; - float fbin = 1, oneovern2 = 1.f/((float)n * (float)n); - inreal += 2; - inimag += 2; - *outamp++ = *outfreq++ = 0; - n -= 2; - while (n--) { - float re, im, pow, freq; - lastreal = currentreal; - currentreal = nextreal; - nextreal = *inreal++; - lastimag = currentimag; - currentimag = nextimag; - nextimag = *inimag++; - re = currentreal - 0.5f * (lastreal + nextreal); - im = currentimag - 0.5f * (lastimag + nextimag); - pow = re * re + im * im; - if (pow > 1e-19) { - float detune = ((lastreal - nextreal) * re + - (lastimag - nextimag) * im) / (2.0f * pow); - if (detune > 2 || detune < -2) freq = pow = 0; - else freq = fbin + detune; - } - else freq = pow = 0; - *outfreq++ = freq; - *outamp++ = oneovern2 * pow; - fbin += 1.0f; - } - while (m--) *outamp++ = *outfreq++ = 0; - return w+6; -} -t_int *sigsqrt_perform(t_int *w); -static void sigframp_dsp(t_sigframp *x, t_signal **sp) { - int n = sp[0]->n, n2 = (n>>1); - if (n < 4) { - error("framp: minimum 4 points"); - return; - } - dsp_add(sigframp_perform, 5, sp[0]->v, sp[1]->v, - sp[2]->v, sp[3]->v, n2); - dsp_add(sigsqrt_perform, 3, sp[3]->v, sp[3]->v, n2); -} -static void sigframp_setup() { - sigframp_class = class_new2("framp~",sigframp_new,0,sizeof(t_sigframp),0,""); - CLASS_MAINSIGNALIN(sigframp_class, t_sigframp, a); - class_addmethod2(sigframp_class, sigframp_dsp, "dsp",""); -} - -/* ---------------- hip~ - 1-pole 1-zero hipass filter. ----------------- */ -/* ---------------- lop~ - 1-pole lopass filter. ----------------- */ -t_class *sighip_class; struct t_hipctl {float x; float coef;}; -t_class *siglop_class; struct t_lopctl {float x; float coef;}; -struct t_sighip : t_object {float sr; float hz; t_hipctl cspace; t_hipctl *ctl; float a;}; -struct t_siglop : t_object {float sr; float hz; t_lopctl cspace; t_lopctl *ctl; float a;}; - -static void sighip_ft1(t_sighip *x, t_floatarg f) {x->hz = max(f,0.f); x->ctl->coef = clip(1-f*(2*3.14159)/x->sr,0.,1.);} -static void siglop_ft1(t_siglop *x, t_floatarg f) {x->hz = max(f,0.f); x->ctl->coef = clip( f*(2*3.14159)/x->sr,0.,1.);} - -static void *sighip_new(t_floatarg f) { - t_sighip *x = (t_sighip *)pd_new(sighip_class); - inlet_new(x, x, &s_float, gensym("ft1")); outlet_new(x, &s_signal); - x->sr = 44100; x->ctl = &x->cspace; x->cspace.x = 0; sighip_ft1(x, f); x->a = 0; return x;} -static void *siglop_new(t_floatarg f) { - t_siglop *x = (t_siglop *)pd_new(siglop_class); - inlet_new(x, x, &s_float, gensym("ft1")); outlet_new(x, &s_signal); - x->sr = 44100; x->ctl = &x->cspace; x->cspace.x = 0; siglop_ft1(x, f); x->a = 0; return x;} - -static void sighip_clear(t_sighip *x, t_floatarg q) {x->cspace.x = 0;} -static void siglop_clear(t_siglop *x, t_floatarg q) {x->cspace.x = 0;} - -static t_int *sighip_perform(t_int *w) { - PERFORM4ARGS(float *,in, float *,out, t_hipctl *,c, int,n); - float last = c->x; - float coef = c->coef; - if (coef < 1) { - for (int i = 0; i < n; i++) { - float noo = *in++ + coef * last; - *out++ = noo - last; - last = noo; - } - if (PD_BIGORSMALL(last)) last = 0; - c->x = last; - } else { - for (int i = 0; i < n; i++) *out++ = *in++; - c->x = 0; - } - return w+5; -} -static t_int *siglop_perform(t_int *w) { - PERFORM4ARGS(float *,in, float *,out, t_lopctl *,c, int,n); - float last = c->x; - float coef = c->coef; - float feedback = 1 - coef; - for (int i = 0; i < n; i++) last = *out++ = coef * *in++ + feedback * last; - if (PD_BIGORSMALL(last)) last = 0; - c->x = last; - return w+5; -} -static void sighip_dsp(t_sighip *x, t_signal **sp) {x->sr = sp[0]->sr; sighip_ft1(x,x->hz); - dsp_add(sighip_perform,4,sp[0]->v,sp[1]->v,x->ctl,sp[0]->n);} -static void siglop_dsp(t_siglop *x, t_signal **sp) {x->sr = sp[0]->sr; siglop_ft1(x,x->hz); - dsp_add(siglop_perform,4,sp[0]->v,sp[1]->v,x->ctl,sp[0]->n);} - -void sighip_setup() { - sighip_class = class_new2("hip~",sighip_new,0,sizeof(t_sighip),0,"F"); - CLASS_MAINSIGNALIN(sighip_class, t_sighip, a); - class_addmethod2(sighip_class, sighip_dsp, "dsp",""); - class_addmethod2(sighip_class, sighip_ft1, "ft1","f"); - class_addmethod2(sighip_class, sighip_clear,"clear",""); -} -void siglop_setup() { - siglop_class = class_new2("lop~",siglop_new,0,sizeof(t_siglop),0,"F"); - CLASS_MAINSIGNALIN(siglop_class, t_siglop, a); - class_addmethod2(siglop_class, siglop_dsp, "dsp",""); - class_addmethod2(siglop_class, siglop_ft1, "ft1","f"); - class_addmethod2(siglop_class, siglop_clear, "clear",""); -} - -/* ---------------- bp~ - 2-pole bandpass filter. ----------------- */ -struct t_bpctl { - float x1; - float x2; - float coef1; - float coef2; - float gain; -}; -struct t_sigbp : t_object { - float sr; - float freq; - float q; - t_bpctl cspace; - t_bpctl *ctl; - float a; -}; -t_class *sigbp_class; -static void sigbp_docoef(t_sigbp *x, t_floatarg f, t_floatarg q); -static void *sigbp_new(t_floatarg f, t_floatarg q) { - t_sigbp *x = (t_sigbp *)pd_new(sigbp_class); - inlet_new(x, x, &s_float, gensym("ft1")); - inlet_new(x, x, &s_float, gensym("ft2")); - outlet_new(x, &s_signal); - x->sr = 44100; - x->ctl = &x->cspace; - x->cspace.x1 = 0; - x->cspace.x2 = 0; - sigbp_docoef(x, f, q); - x->a = 0; - return x; -} -static float sigbp_qcos(float f) { - if (f >= -(0.5f*3.14159f) && f <= 0.5f*3.14159f) { - float g = f*f; - return ((g*g*g * (-1.0f/720.0f) + g*g*(1.0f/24.0f)) - g*0.5) + 1; - } else return 0; -} -static void sigbp_docoef(t_sigbp *x, t_floatarg f, t_floatarg q) { - float r, oneminusr, omega; - if (f < 0.001) f = 10; - if (q < 0) q = 0; - x->freq = f; - x->q = q; - omega = f * (2.0f * 3.14159f) / x->sr; - if (q < 0.001) oneminusr = 1.0f; - else oneminusr = omega/q; - if (oneminusr > 1.0f) oneminusr = 1.0f; - r = 1.0f - oneminusr; - x->ctl->coef1 = 2.0f * sigbp_qcos(omega) * r; - x->ctl->coef2 = - r * r; - x->ctl->gain = 2 * oneminusr * (oneminusr + r * omega); - /* post("r %f, omega %f, coef1 %f, coef2 %f", r, omega, x->ctl->coef1, x->ctl->coef2); */ -} -static void sigbp_ft1(t_sigbp *x, t_floatarg f) {sigbp_docoef(x, f, x->q);} -static void sigbp_ft2(t_sigbp *x, t_floatarg q) {sigbp_docoef(x, x->freq, q);} -static void sigbp_clear(t_sigbp *x, t_floatarg q) {x->ctl->x1 = x->ctl->x2 = 0;} -static t_int *sigbp_perform(t_int *w) { - PERFORM4ARGS(float *,in, float *,out, t_bpctl *,c, int,n); - float last = c->x1; - float prev = c->x2; - float coef1 = c->coef1; - float coef2 = c->coef2; - float gain = c->gain; - for (int i = 0; i < n; i++) { - float output = *in++ + coef1 * last + coef2 * prev; - *out++ = gain * output; - prev = last; - last = output; - } - if (PD_BIGORSMALL(last)) last = 0; - if (PD_BIGORSMALL(prev)) prev = 0; - c->x1 = last; - c->x2 = prev; - return w+5; -} -static void sigbp_dsp(t_sigbp *x, t_signal **sp) { - x->sr = sp[0]->sr; - sigbp_docoef(x, x->freq, x->q); - dsp_add(sigbp_perform, 4, sp[0]->v, sp[1]->v, x->ctl, sp[0]->n); - -} -void sigbp_setup() { - sigbp_class = class_new2("bp~",sigbp_new,0,sizeof(t_sigbp),0,"FF"); - CLASS_MAINSIGNALIN(sigbp_class, t_sigbp, a); - class_addmethod2(sigbp_class, sigbp_dsp, "dsp",""); - class_addmethod2(sigbp_class, sigbp_ft1, "ft1","f"); - class_addmethod2(sigbp_class, sigbp_ft2, "ft2","f"); - class_addmethod2(sigbp_class, sigbp_clear, "clear",""); -} - -/* ---------------- biquad~ - raw biquad filter ----------------- */ -struct t_biquadctl { - float x1; - float x2; - float fb1; - float fb2; - float ff1; - float ff2; - float ff3; -}; -struct t_sigbiquad : t_object { - float a; - t_biquadctl cspace; - t_biquadctl *ctl; -}; -t_class *sigbiquad_class; -static void sigbiquad_list(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv); -static void *sigbiquad_new(t_symbol *s, int argc, t_atom *argv) { - t_sigbiquad *x = (t_sigbiquad *)pd_new(sigbiquad_class); - outlet_new(x, &s_signal); - x->ctl = &x->cspace; - x->cspace.x1 = x->cspace.x2 = 0; - sigbiquad_list(x, s, argc, argv); - x->a = 0; - return x; -} -static t_int *sigbiquad_perform(t_int *w) { - PERFORM4ARGS(float *,in, float *,out, t_biquadctl *,c, int,n); - float last = c->x1; - float prev = c->x2; - float fb1 = c->fb1; - float fb2 = c->fb2; - float ff1 = c->ff1; - float ff2 = c->ff2; - float ff3 = c->ff3; - for (int i = 0; i < n; i++) { - float output = *in++ + fb1 * last + fb2 * prev; - if (PD_BIGORSMALL(output)) output = 0; - *out++ = ff1 * output + ff2 * last + ff3 * prev; - prev = last; - last = output; - } - c->x1 = last; - c->x2 = prev; - return w+5; -} -/* tb: some loop unrolling & do some relaxed denormal bashing */ -/* (denormal bashing = non-Pentium4 penalised for Pentium4's failings) */ -static t_int *sigbiquad_perf8(t_int *w) { - PERFORM4ARGS(float *,in, float *,out, t_biquadctl *,c, int,n); - n>>=3; - float last = c->x1; - float prev = c->x2; - float fb1 = c->fb1; - float fb2 = c->fb2; - float ff1 = c->ff1; - float ff2 = c->ff2; - float ff3 = c->ff3; - for (int i = 0; i < n; i++) { - float output = *in++ + fb1*last + fb2*prev; - if (PD_BIGORSMALL(output)) output = 0; - *out++ = ff1 * output + ff2*last + ff3*prev; prev=last; last=output; output = *in++ + fb1*last + fb2*prev; - if (PD_BIGORSMALL(output)) output = 0; - *out++ = ff1 * output + ff2*last + ff3*prev; prev=last; last=output; output = *in++ + fb1*last + fb2*prev; - *out++ = ff1 * output + ff2*last + ff3*prev; prev=last; last=output; output = *in++ + fb1*last + fb2*prev; - *out++ = ff1 * output + ff2*last + ff3*prev; prev=last; last=output; output = *in++ + fb1*last + fb2*prev; - output += 1e-10; - output -= 1e-10; - *out++ = ff1*output + ff2*last + ff3*prev; prev=last; last=output; output = *in++ + fb1*last + fb2*prev; - *out++ = ff1*output + ff2*last + ff3*prev; prev=last; last=output; output = *in++ + fb1*last + fb2*prev; - *out++ = ff1*output + ff2*last + ff3*prev; prev=last; last=output; output = *in++ + fb1*last + fb2*prev; - *out++ = ff1*output + ff2*last + ff3*prev; prev=last; last=output; - } - c->x1 = last; - c->x2 = prev; - return w+5; -} -static void sigbiquad_list(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv) { - float fb1 = atom_getfloatarg(0, argc, argv); - float fb2 = atom_getfloatarg(1, argc, argv); - float ff1 = atom_getfloatarg(2, argc, argv); - float ff2 = atom_getfloatarg(3, argc, argv); - float ff3 = atom_getfloatarg(4, argc, argv); - float discriminant = fb1 * fb1 + 4 * fb2; - t_biquadctl *c = x->ctl; - /* imaginary roots -- resonant filter */ - if (discriminant < 0) { - /* they're conjugates so we just check that the product is less than one */ - if (fb2 >= -1.0f) goto stable; - } else { /* real roots */ - /* check that the parabola 1 - fb1 x - fb2 x^2 has a - vertex between -1 and 1, and that it's nonnegative - at both ends, which implies both roots are in [1-,1]. */ - if (fb1 <= 2.0f && fb1 >= -2.0f && 1.0f - fb1 -fb2 >= 0 && 1.0f + fb1 - fb2 >= 0) goto stable; - } - /* if unstable, just bash to zero */ - fb1 = fb2 = ff1 = ff2 = ff3 = 0; -stable: - c->fb1 = fb1; - c->fb2 = fb2; - c->ff1 = ff1; - c->ff2 = ff2; - c->ff3 = ff3; -} -static void sigbiquad_set(t_sigbiquad *x, t_symbol *s, int argc, t_atom *argv) { - t_biquadctl *c = x->ctl; - c->x1 = atom_getfloatarg(0, argc, argv); - c->x2 = atom_getfloatarg(1, argc, argv); -} -static void sigbiquad_dsp(t_sigbiquad *x, t_signal **sp) { - const int n = sp[0]->n; - if (n&7) dsp_add(sigbiquad_perform, 4, sp[0]->v, sp[1]->v, x->ctl, sp[0]->n); - else dsp_add(sigbiquad_perf8, 4, sp[0]->v, sp[1]->v, x->ctl, sp[0]->n); -} -void sigbiquad_setup() { - sigbiquad_class = class_new2("biquad~",sigbiquad_new,0,sizeof(t_sigbiquad),0,"*"); - CLASS_MAINSIGNALIN(sigbiquad_class, t_sigbiquad, a); - class_addmethod2(sigbiquad_class, sigbiquad_dsp, "dsp",""); - class_addlist(sigbiquad_class, sigbiquad_list); - class_addmethod2(sigbiquad_class, sigbiquad_set, "set","*"); - class_addmethod2(sigbiquad_class, sigbiquad_set, "clear","*"); -} - -/* ---------------- samphold~ - sample and hold ----------------- */ -struct t_sigsamphold : t_object { - float a; - float lastin; - float lastout; -}; -t_class *sigsamphold_class; -static void *sigsamphold_new() { - t_sigsamphold *x = (t_sigsamphold *)pd_new(sigsamphold_class); - inlet_new(x, x, &s_signal, &s_signal); - outlet_new(x, &s_signal); - x->lastin = 0; - x->lastout = 0; - x->a = 0; - return x; -} -static t_int *sigsamphold_perform(t_int *w) { - PERFORM5ARGS(float *,in1, float *,in2, float *,out, t_sigsamphold *,x, int,n); - float lastin = x->lastin; - float lastout = x->lastout; - for (int i = 0; i < n; i++, *in1++) { - float next = *in2++; - if (next < lastin) lastout = *in1; - *out++ = lastout; - lastin = next; - } - x->lastin = lastin; - x->lastout = lastout; - return w+6; -} -static void sigsamphold_dsp(t_sigsamphold *x, t_signal **sp) { - dsp_add(sigsamphold_perform, 5, sp[0]->v, sp[1]->v, sp[2]->v, x, sp[0]->n); -} -static void sigsamphold_reset(t_sigsamphold *x, t_symbol *s, int argc, t_atom *argv) { - x->lastin = ((argc > 0 && (argv[0].a_type == A_FLOAT)) ? argv[0].a_w.w_float : 1e20); -} -static void sigsamphold_set(t_sigsamphold *x, t_float f) { - x->lastout = f; -} -void sigsamphold_setup() { - sigsamphold_class = class_new2("samphold~",sigsamphold_new,0,sizeof(t_sigsamphold),0,""); - CLASS_MAINSIGNALIN(sigsamphold_class, t_sigsamphold, a); - class_addmethod2(sigsamphold_class, sigsamphold_set, "set","F"); - class_addmethod2(sigsamphold_class, sigsamphold_reset, "reset","*"); - class_addmethod2(sigsamphold_class, sigsamphold_dsp, "dsp",""); -} - -/* ---------------- rpole~ - real one-pole filter (raw) ----------------- */ -/* ---------------- rzero~ - real one-zero filter (raw) ----------------- */ -/* --- rzero_rev~ - real, reverse one-zero filter (raw) ----------------- */ -t_class *sigrpole_class; struct t_sigrpole : t_object {float a; float last;}; -t_class *sigrzero_class; struct t_sigrzero : t_object {float a; float last;}; -t_class *sigrzrev_class; struct t_sigrzrev : t_object {float a; float last;}; - -static void *sigrpole_new(t_float f) { - t_sigrpole *x = (t_sigrpole *)pd_new(sigrpole_class); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), f); outlet_new(x, &s_signal); x->last=0; return x;} -static void *sigrzero_new(t_float f) { - t_sigrzero *x = (t_sigrzero *)pd_new(sigrzero_class); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), f); outlet_new(x, &s_signal); x->last=0; return x;} -static void *sigrzrev_new(t_float f) { - t_sigrzrev *x = (t_sigrzrev *)pd_new(sigrzrev_class); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), f); outlet_new(x, &s_signal); x->last=0; return x;} - -static t_int *sigrpole_perform(t_int *w) { - PERFORM5ARGS(float *,in1, float *,in2, float *,out, t_sigrpole *,x, t_int,n); - float last = x->last; - for (int i=0; i<n; i++) { - float next = *in1++, coef = *in2++; - *out++ = last = coef*last + next; - } - if (PD_BIGORSMALL(last)) last = 0; - x->last = last; - return w+6; -} -static t_int *sigrzero_perform(t_int *w) { - PERFORM5ARGS(float *,in1, float *,in2, float *,out, t_sigrzero *,x, t_int,n); - float last = x->last; - for (int i = 0; i < n; i++) { - float next = *in1++, coef = *in2++; - *out++ = next - coef*last; - last = next; - } - x->last = last; - return w+6; -} -static t_int *sigrzrev_perform(t_int *w) { - PERFORM5ARGS(float *,in1, float *,in2, float *,out, t_sigrzrev *,x, t_int,n); - float last = x->last; - for (int i = 0; i < n; i++) { - float next = *in1++, coef = *in2++; - *out++ = last - coef*next; - last = next; - } - x->last = last; - return w+6; -} - -static void sigrpole_dsp(t_sigrpole *x, t_signal **sp) {dsp_add(sigrpole_perform, 5, sp[0]->v, sp[1]->v, sp[2]->v, x, sp[0]->n);} -static void sigrzero_dsp(t_sigrzero *x, t_signal **sp) {dsp_add(sigrzero_perform, 5, sp[0]->v, sp[1]->v, sp[2]->v, x, sp[0]->n);} -static void sigrzrev_dsp(t_sigrzrev *x, t_signal **sp) {dsp_add(sigrzrev_perform, 5, sp[0]->v, sp[1]->v, sp[2]->v, x, sp[0]->n);} -static void sigrpole_clear(t_sigrpole *x) {x->last = 0;} -static void sigrzero_clear(t_sigrzero *x) {x->last = 0;} -static void sigrzrev_clear(t_sigrzrev *x) {x->last = 0;} -static void sigrpole_set(t_sigrpole *x, t_float f) {x->last = f;} -static void sigrzero_set(t_sigrzero *x, t_float f) {x->last = f;} -static void sigrzrev_set(t_sigrzrev *x, t_float f) {x->last = f;} -void sigr_setup() { - sigrpole_class = class_new2("rpole~", sigrpole_new,0,sizeof(t_sigrpole),0,"F"); - sigrzero_class = class_new2("rzero~", sigrzero_new,0,sizeof(t_sigrzero),0,"F"); - sigrzrev_class = class_new2("rzero_rev~",sigrzrev_new,0,sizeof(t_sigrzrev),0,"F"); - CLASS_MAINSIGNALIN(sigrpole_class, t_sigrpole, a); - CLASS_MAINSIGNALIN(sigrzero_class, t_sigrzero, a); - CLASS_MAINSIGNALIN(sigrzrev_class, t_sigrzrev, a); - class_addmethod2(sigrpole_class, sigrpole_set, "set","F"); - class_addmethod2(sigrzero_class, sigrzero_set, "set","F"); - class_addmethod2(sigrzrev_class, sigrzrev_set, "set","F"); - class_addmethod2(sigrpole_class, sigrpole_clear,"clear",""); - class_addmethod2(sigrzero_class, sigrzero_clear,"clear",""); - class_addmethod2(sigrzrev_class, sigrzrev_clear,"clear",""); - class_addmethod2(sigrpole_class, sigrpole_dsp, "dsp",""); - class_addmethod2(sigrzero_class, sigrzero_dsp, "dsp",""); - class_addmethod2(sigrzrev_class, sigrzrev_dsp, "dsp",""); -} - -/* -------------- cpole~ - complex one-pole filter (raw) --------------- */ -/* -------------- czero~ - complex one-pole filter (raw) --------------- */ -/* ---------- czero_rev~ - complex one-pole filter (raw) --------------- */ - -t_class *sigcpole_class; struct t_sigcpole : t_object {float a; float lastre; float lastim;}; -t_class *sigczero_class; struct t_sigczero : t_object {float a; float lastre; float lastim;}; -t_class *sigczrev_class; struct t_sigczrev : t_object {float a; float lastre; float lastim;}; - -static void *sigcpole_new(t_float re, t_float im) { - t_sigcpole *x = (t_sigcpole *)pd_new(sigcpole_class); - inlet_new(x, x, &s_signal, &s_signal); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), re); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), im); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - x->lastre = x->lastim = 0; - x->a = 0; - return x; -} -static void *sigczero_new(t_float re, t_float im) { - t_sigczero *x = (t_sigczero *)pd_new(sigczero_class); - inlet_new(x, x, &s_signal, &s_signal); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), re); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), im); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - x->lastre = x->lastim = 0; - x->a = 0; - return x; -} -static void *sigczrev_new(t_float re, t_float im) { - t_sigczrev *x = (t_sigczrev *)pd_new(sigczrev_class); - inlet_new(x, x, &s_signal, &s_signal); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), re); - pd_float((t_pd *)inlet_new(x, x, &s_signal, &s_signal), im); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - x->lastre = x->lastim = 0; - x->a = 0; - return x; -} - -static t_int *sigcpole_perform(t_int *w) { - PERFORM8ARGS(float *,inre1, float *,inim1, float *,inre2, float *,inim2, float *,outre, float *,outim, t_sigcpole *,x, int,n); - float lastre = x->lastre; - float lastim = x->lastim; - for (int i = 0; i < n; i++) { - float nextre = *inre1++, nextim = *inim1++; - float coefre = *inre2++, coefim = *inim2++; - float tempre = *outre++ = nextre + lastre * coefre - lastim * coefim; - lastim = *outim++ = nextim + lastre * coefim + lastim * coefre; - lastre = tempre; - } - if (PD_BIGORSMALL(lastre)) lastre = 0; - if (PD_BIGORSMALL(lastim)) lastim = 0; - x->lastre = lastre; - x->lastim = lastim; - return w+9; -} -static t_int *sigczero_perform(t_int *w) { - PERFORM8ARGS(float *,inre1, float *,inim1, float *,inre2, float *,inim2, float *,outre, float *,outim, t_sigczero *,x, int,n); - float lastre = x->lastre; - float lastim = x->lastim; - for (int i = 0; i < n; i++) { - float nextre = *inre1++, nextim = *inim1++; - float coefre = *inre2++, coefim = *inim2++; - *outre++ = nextre - lastre * coefre + lastim * coefim; - *outim++ = nextim - lastre * coefim - lastim * coefre; - lastre = nextre; - lastim = nextim; - } - x->lastre = lastre; - x->lastim = lastim; - return w+9; -} -static t_int *sigczrev_perform(t_int *w) { - PERFORM8ARGS(float *,inre1, float *,inim1, float *,inre2, float *,inim2, float *,outre, float *,outim, t_sigczrev *,x, int,n); - float lastre = x->lastre; - float lastim = x->lastim; - for (int i = 0; i < n; i++) { - float nextre = *inre1++, nextim = *inim1++; - float coefre = *inre2++, coefim = *inim2++; - /* transfer function is (A bar) - Z^-1, for the same frequency response as 1 - AZ^-1 from czero_tilde. */ - *outre++ = lastre - nextre * coefre - nextim * coefim; - *outim++ = lastim - nextre * coefim + nextim * coefre; - lastre = nextre; - lastim = nextim; - } - x->lastre = lastre; - x->lastim = lastim; - return w+9; -} - -static void sigcpole_dsp(t_sigcpole *x, t_signal **sp) { - dsp_add(sigcpole_perform,8,sp[0]->v,sp[1]->v,sp[2]->v,sp[3]->v,sp[4]->v,sp[5]->v,x,sp[0]->n);} -static void sigczero_dsp(t_sigczero *x, t_signal **sp) { - dsp_add(sigczero_perform,8,sp[0]->v,sp[1]->v,sp[2]->v,sp[3]->v,sp[4]->v,sp[5]->v,x,sp[0]->n);} -static void sigczrev_dsp(t_sigczrev *x, t_signal **sp) { - dsp_add(sigczrev_perform,8,sp[0]->v,sp[1]->v,sp[2]->v,sp[3]->v,sp[4]->v,sp[5]->v,x,sp[0]->n);} - -static void sigcpole_clear(t_sigcpole *x) {x->lastre = x->lastim = 0;} -static void sigczero_clear(t_sigczero *x) {x->lastre = x->lastim = 0;} -static void sigczrev_clear(t_sigczrev *x) {x->lastre = x->lastim = 0;} -static void sigcpole_set(t_sigcpole *x, t_float re, t_float im) {x->lastre = re; x->lastim = im;} -static void sigczero_set(t_sigczero *x, t_float re, t_float im) {x->lastre = re; x->lastim = im;} -static void sigczrev_set(t_sigczrev *x, t_float re, t_float im) {x->lastre = re; x->lastim = im;} - -void sigc_setup() { - sigcpole_class = class_new2("cpole~", sigcpole_new,0,sizeof(t_sigcpole),0,"FF"); - sigczero_class = class_new2("czero~", sigczero_new,0,sizeof(t_sigczero),0,"FF"); - sigczrev_class = class_new2("czero_rev~",sigczrev_new,0,sizeof(t_sigczrev),0,"FF"); - CLASS_MAINSIGNALIN(sigcpole_class, t_sigcpole, a); - CLASS_MAINSIGNALIN(sigczero_class, t_sigczero, a); - CLASS_MAINSIGNALIN(sigczrev_class, t_sigczrev, a); - class_addmethod2(sigcpole_class, sigcpole_set, "set","FF"); - class_addmethod2(sigczero_class, sigczero_set, "set","FF"); - class_addmethod2(sigczrev_class, sigczrev_set, "set","FF"); - class_addmethod2(sigcpole_class, sigcpole_clear,"clear",""); - class_addmethod2(sigczero_class, sigczero_clear, "clear",""); - class_addmethod2(sigczrev_class, sigczrev_clear, "clear",""); - class_addmethod2(sigcpole_class, sigcpole_dsp, "dsp",""); - class_addmethod2(sigczero_class, sigczero_dsp, "dsp",""); - class_addmethod2(sigczrev_class, sigczrev_dsp, "dsp",""); -} - -/* ----------------------------- send~ ----------------------------- */ -static t_class *sigsend_class; -struct t_sigsend : t_object { - t_symbol *sym; - int n; - float *vec; - float a; -}; -static void *sigsend_new(t_symbol *s) { - t_sigsend *x = (t_sigsend *)pd_new(sigsend_class); - pd_bind(x, s); - x->sym = s; - x->n = DEFSENDVS; - x->vec = (float *)getalignedbytes(DEFSENDVS * sizeof(float)); - memset((char *)(x->vec), 0, DEFSENDVS * sizeof(float)); - x->a = 0; - return x; -} -static t_int *sigsend_perform(t_int *w) {testcopyvec( (t_float *)w[2],(t_float *)w[1],w[3]); return w+4;} -static t_int *sigsend_perfsimd(t_int *w) {testcopyvec_simd((t_float *)w[2],(t_float *)w[1],w[3]); return w+4;} // T.Grill -static void sigsend_dsp(t_sigsend *x, t_signal **sp) { - const int n = x->n; - if(n != sp[0]->n) {error("sigsend %s: unexpected vector size", x->sym->name); return;} - if(SIMD_CHECK1(n,sp[0]->v)) /* x->vec is aligned in any case */ - dsp_add(sigsend_perfsimd, 3, sp[0]->v, x->vec, n); - else dsp_add(sigsend_perform, 3, sp[0]->v, x->vec, n); -} -static void sigsend_free(t_sigsend *x) { - pd_unbind(x, x->sym); - freealignedbytes(x->vec,x->n* sizeof(float)); -} -static void sigsend_setup() { - sigsend_class = class_new2("send~",sigsend_new,sigsend_free,sizeof(t_sigsend),0,"S"); - class_addcreator2("s~",sigsend_new,"S"); - CLASS_MAINSIGNALIN(sigsend_class, t_sigsend, a); - class_addmethod2(sigsend_class, sigsend_dsp,"dsp",""); -} - -/* ----------------------------- receive~ ----------------------------- */ -static t_class *sigreceive_class; -struct t_sigreceive : t_object { - t_symbol *sym; - t_float *wherefrom; - int n; -}; -static void *sigreceive_new(t_symbol *s) { - t_sigreceive *x = (t_sigreceive *)pd_new(sigreceive_class); - x->n = DEFSENDVS; /* LATER find our vector size correctly */ - x->sym = s; - x->wherefrom = 0; - outlet_new(x, &s_signal); - return x; -} -static t_int *sigreceive_perform(t_int *w) { - PERFORM3ARGS(t_sigreceive *,x, t_float *,out, int,n); - t_float *in = x->wherefrom; - if (in) { - while (n--) *out++ = *in++; - } else { - while (n--) *out++ = 0; - } - return w+4; -} -/* tb: vectorized receive function */ -static t_int *sigreceive_perf8(t_int *w) { - PERFORM3ARGS(t_sigreceive *,x, t_float *,out, int,n); - t_float *in = x->wherefrom; - if (in) copyvec_8(out,in,n); - else zerovec_8(out, n); - return w+4; -} -/* T.Grill - SIMD version */ -static t_int *sigreceive_perfsimd(t_int *w) { - PERFORM3ARGS(t_sigreceive *,x, t_float *,out, int,n); - t_float *in = x->wherefrom; - if(in) copyvec_simd(out,in,n); - else zerovec_simd(out, n); - return w+4; -} -static void sigreceive_set(t_sigreceive *x, t_symbol *s) { - t_sigsend *sender = (t_sigsend *)pd_findbyclass((x->sym = s), - sigsend_class); - if (sender) { - if (sender->n == x->n) - x->wherefrom = sender->vec; - else { - error("receive~ %s: vector size mismatch", x->sym->name); - x->wherefrom = 0; - } - } else { - error("receive~ %s: no matching send", x->sym->name); - x->wherefrom = 0; - } -} -static void sigreceive_dsp(t_sigreceive *x, t_signal **sp) { - const int n = x->n; - if (sp[0]->n != n) {error("receive~ %s: vector size mismatch", x->sym->name); return;} - sigreceive_set(x, x->sym); - /* x->wherefrom is aligned because we aligned the sender memory buffer */ - if(n&7) dsp_add(sigreceive_perform, 3, x, sp[0]->v, n); - else if(SIMD_CHECK1(n,sp[0]->v)) dsp_add(sigreceive_perfsimd, 3, x, sp[0]->v, n); - else dsp_add(sigreceive_perf8, 3, x, sp[0]->v, n); -} -static void sigreceive_setup() { - sigreceive_class = class_new2("receive~",sigreceive_new,0,sizeof(t_sigreceive),0,"S"); - class_addcreator2("r~",sigreceive_new,"S"); - class_addmethod2(sigreceive_class, sigreceive_set, "set","s"); - class_addmethod2(sigreceive_class, sigreceive_dsp, "dsp",""); - class_sethelpsymbol(sigreceive_class, gensym("send~")); -} - -/* ----------------------------- catch~ ----------------------------- */ -static t_class *sigcatch_class; -struct t_sigcatch : t_object { - t_symbol *sym; - int n; - float *vec; -}; -static void *sigcatch_new(t_symbol *s) { - t_sigcatch *x = (t_sigcatch *)pd_new(sigcatch_class); - pd_bind(x, s); - x->sym = s; - x->n = DEFSENDVS; - x->vec = (float *)getalignedbytes(DEFSENDVS * sizeof(float)); - memset((char *)(x->vec), 0, DEFSENDVS * sizeof(float)); - outlet_new(x, &s_signal); - return x; -} -static t_int *sigcatch_perform(t_int *w) { - PERFORM3ARGS(t_float *,in, t_float *,out, int,n); - while (n--) *out++ = *in, *in++ = 0; - return w+4; -} -/* tb: vectorized catch function */ -static t_int *sigcatch_perf8(t_int *w) { - PERFORM3ARGS(t_float *,in, t_float *,out, int,n); - copyvec_8(out,in,n); - zerovec_8( in,n); - return w+4; -} -/* T.Grill: SIMD catch function */ -static t_int *sigcatch_perfsimd(t_int *w) { - PERFORM3ARGS(t_float *,in, t_float *,out, int,n); - copyvec_simd(out,in,n); - zerovec_simd( in,n); - return w+4; -} -static void sigcatch_dsp(t_sigcatch *x, t_signal **sp) { - const int n = sp[0]->n; - if (x->n != n) {error("sigcatch %s: unexpected vector size", x->sym->name); return;} - if(n&7) dsp_add(sigcatch_perform, 3, x->vec, sp[0]->v, n); - else if(SIMD_CHECK2(n,x->vec,sp[0]->v)) dsp_add(sigcatch_perfsimd,3, x->vec, sp[0]->v, n); - else dsp_add(sigcatch_perf8, 3, x->vec, sp[0]->v, n); -} -static void sigcatch_free(t_sigcatch *x) { - pd_unbind(x, x->sym); - freealignedbytes(x->vec,x->n*sizeof(float)); -} -static void sigcatch_setup() { - sigcatch_class = class_new2("catch~",sigcatch_new,sigcatch_free,sizeof(t_sigcatch),CLASS_NOINLET,"S"); - class_addmethod2(sigcatch_class, sigcatch_dsp, "dsp",""); - class_sethelpsymbol(sigcatch_class, gensym("throw~")); -} - -/* ----------------------------- throw~ ----------------------------- */ -static t_class *sigthrow_class; -struct t_sigthrow : t_object { - t_symbol *sym; - t_float *whereto; - int n; - t_float a; -}; -static void *sigthrow_new(t_symbol *s) { - t_sigthrow *x = (t_sigthrow *)pd_new(sigthrow_class); - x->sym = s; - x->whereto = 0; - x->n = DEFSENDVS; - x->a = 0; - return x; -} -static t_int *sigthrow_perform(t_int *w) { - t_sigthrow *x = (t_sigthrow *)w[1]; - t_float *out = x->whereto; - if(out) testaddvec(out,(t_float *)w[2],w[3]); - return w+4; -} -/* T.Grill - SIMD version */ -static t_int *sigthrow_perfsimd(t_int *w) { - t_sigthrow *x = (t_sigthrow *)w[1]; - t_float *out = x->whereto; - if(out) testaddvec_simd(out,(t_float *)w[2],w[3]); - return w+4; -} -static void sigthrow_set(t_sigthrow *x, t_symbol *s) { - x->sym = s; - t_sigcatch *catcher = (t_sigcatch *)pd_findbyclass(s,sigcatch_class); - x->whereto = 0; - if (catcher) { - if (catcher->n == x->n) x->whereto = catcher->vec; - else error("throw~ %s: vector size mismatch", x->sym->name); - } else error("throw~ %s: no matching catch", x->sym->name); -} -static void sigthrow_dsp(t_sigthrow *x, t_signal **sp) { - const int n = x->n; - if (sp[0]->n != n) {error("throw~ %s: vector size mismatch", x->sym->name); return;} - sigthrow_set(x, x->sym); - if(SIMD_CHECK1(n,sp[0]->v)) /* the memory of the catcher is aligned in any case */ - dsp_add(sigthrow_perfsimd, 3, x, sp[0]->v, n); - else dsp_add(sigthrow_perform, 3, x, sp[0]->v, n); -} -static void sigthrow_setup() { - sigthrow_class = class_new2("throw~",sigthrow_new,0,sizeof(t_sigthrow),0,"S"); - class_addmethod2(sigthrow_class, sigthrow_set, "set","s"); - CLASS_MAINSIGNALIN(sigthrow_class, t_sigthrow, a); - class_addmethod2(sigthrow_class, sigthrow_dsp, "dsp",""); -} - -/* ------------------------- clip~ -------------------------- */ -static t_class *clip_class; -struct t_clip : t_object { - float a; - t_sample lo; - t_sample hi; -}; -static void *clip_new(t_floatarg lo, t_floatarg hi) { - t_clip *x = (t_clip *)pd_new(clip_class); - x->lo = lo; - x->hi = hi; - outlet_new(x, &s_signal); - floatinlet_new(x, &x->lo); - floatinlet_new(x, &x->hi); - x->a = 0; - return x; -} -/* T.Grill - changed function interface so that class pointer needn't be passed */ -t_int *clip_perform(t_int *w) { - PERFORM5ARGS(t_float *,in, t_float *,out, t_float *,lop, t_float *,hip, int,n); - t_float lo=*lop, hi=*hip; - while (n--) *out++ = clip(*in++,lo,hi); - return w+6; -} -static void clip_dsp(t_clip *x, t_signal **sp) { - if(SIMD_CHECK2(sp[0]->n,sp[0]->v,sp[1]->v)) - dsp_add(clip_perf_simd, 5, sp[0]->v, sp[1]->v, &x->lo, &x->hi, sp[0]->n); - else dsp_add(clip_perform, 5, sp[0]->v, sp[1]->v, &x->lo, &x->hi, sp[0]->n); -} -static void clip_setup() { - clip_class = class_new2("clip~",clip_new,0,sizeof(t_clip),0,"FF"); - CLASS_MAINSIGNALIN(clip_class, t_clip, a); - class_addmethod2(clip_class, clip_dsp, "dsp",""); -} - -/* sigrsqrt - reciprocal square root good to 8 mantissa bits */ -/* sigsqrt - square root good to 8 mantissa bits */ - -#define DUMTAB1SIZE 256 -#define DUMTAB2SIZE 1024 -static float rsqrt_exptab[DUMTAB1SIZE], rsqrt_mantissatab[DUMTAB2SIZE]; -static void init_rsqrt() { - for (int i = 0; i < DUMTAB1SIZE; i++) { - float f; - long l = (i ? (i == DUMTAB1SIZE-1 ? DUMTAB1SIZE-2 : i) : 1)<< 23; - *(int *)(&f) = l; - rsqrt_exptab[i] = 1./sqrt(f); - } - for (int i = 0; i < DUMTAB2SIZE; i++) { - float f = 1 + (1./DUMTAB2SIZE) * i; - rsqrt_mantissatab[i] = 1./sqrt(f); - } -} -/* these are used in externs like "bonk" */ -float q8_rsqrt(float f) { - long l = *(long *)(&f); - if (f < 0) return 0; - return rsqrt_exptab[(l >> 23) & 0xff] * - rsqrt_mantissatab[(l >> 13) & 0x3ff]; -} -float q8_sqrt(float f) { - long l = *(long *)(&f); - if (f < 0) return 0; - return f * rsqrt_exptab[(l >> 23) & 0xff] * - rsqrt_mantissatab[(l >> 13) & 0x3ff]; -} - -/* the old names are OK unless we're in IRIX N32 */ -#ifndef N32 -float qsqrt(float f) {return q8_sqrt(f);} -float qrsqrt(float f) {return q8_rsqrt(f);} -#endif -static t_class *sigrsqrt_class; struct t_sigrsqrt : t_object {float a;}; -static t_class * sigsqrt_class; struct t_sigsqrt : t_object {float a;}; -static void *sigrsqrt_new() { - t_sigrsqrt *x = (t_sigrsqrt *)pd_new(sigrsqrt_class); - outlet_new(x, &s_signal); - x->a = 0; - return x; -} -static void *sigsqrt_new() { - t_sigsqrt *x = (t_sigsqrt *)pd_new(sigsqrt_class); - outlet_new(x, &s_signal); - x->a = 0; - return x; -} - -static t_int *sigrsqrt_perform(t_int *w) { - float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2); - t_int n = *(t_int *)(w+3); - while (n--) { - float f = *in; - long l = *(long *)(in++); - if (f < 0) *out++ = 0; - else { - float g = rsqrt_exptab[(l >> 23) & 0xff] * - rsqrt_mantissatab[(l >> 13) & 0x3ff]; - *out++ = 1.5 * g - 0.5 * g * g * g * f; - } - } - return w+4; -} -/* not static; also used in d_fft.c */ -t_int *sigsqrt_perform(t_int *w) { - float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2); - t_int n = *(t_int *)(w+3); - while (n--) { - float f = *in; - long l = *(long *)(in++); - if (f < 0) *out++ = 0; - else { - float g = rsqrt_exptab[(l >> 23) & 0xff] * - rsqrt_mantissatab[(l >> 13) & 0x3ff]; - *out++ = f * (1.5 * g - 0.5 * g * g * g * f); - } - } - return w+4; -} - -static void sigrsqrt_dsp(t_sigrsqrt *x, t_signal **sp) { - if(SIMD_CHECK2(sp[0]->n,sp[0]->v,sp[1]->v)) - dsp_add(sigrsqrt_perf_simd, 3, sp[0]->v, sp[1]->v, sp[0]->n); - else dsp_add(sigrsqrt_perform, 3, sp[0]->v, sp[1]->v, sp[0]->n); -} -static void sigsqrt_dsp(t_sigsqrt *x, t_signal **sp) { - if(SIMD_CHECK2(sp[0]->n,sp[0]->v,sp[1]->v)) - dsp_add(sigsqrt_perf_simd, 3, sp[0]->v, sp[1]->v, sp[0]->n); - else dsp_add(sigsqrt_perform, 3, sp[0]->v, sp[1]->v, sp[0]->n); -} - -void sigsqrt_setup() { - init_rsqrt(); - sigrsqrt_class = class_new2("rsqrt~",sigrsqrt_new,0,sizeof(t_sigrsqrt),0,""); - sigsqrt_class = class_new2( "sqrt~", sigsqrt_new,0, sizeof(t_sigsqrt),0,""); - CLASS_MAINSIGNALIN(sigrsqrt_class,t_sigrsqrt,a); - CLASS_MAINSIGNALIN( sigsqrt_class, t_sigsqrt,a); - class_addmethod2( sigsqrt_class, sigsqrt_dsp,"dsp",""); - class_addmethod2(sigrsqrt_class,sigrsqrt_dsp,"dsp",""); - class_addcreator2("q8_rsqrt~",sigrsqrt_new,""); - class_addcreator2("q8_sqrt~", sigsqrt_new,""); -} - -/* ------------------------------ wrap~ -------------------------- */ -struct t_sigwrap : t_object {float a;}; -t_class *sigwrap_class; -static void *sigwrap_new() { - t_sigwrap *x = (t_sigwrap *)pd_new(sigwrap_class); - outlet_new(x, &s_signal); - x->a = 0; - return x; -} -static t_int *sigwrap_perform(t_int *w) { - float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2); - t_int n = *(t_int *)(w+3); - while (n--) { - float f = *in++; - int k = (int)f; - if (f > 0) *out++ = f-k; - else *out++ = f - (k-1); - } - return w+4; -} -static void sigwrap_dsp(t_sigwrap *x, t_signal **sp) { - if(SIMD_CHECK2(sp[0]->n,sp[0]->v,sp[1]->v)) - dsp_add(sigwrap_perf_simd, 3, sp[0]->v, sp[1]->v, sp[0]->n); - else dsp_add(sigwrap_perform, 3, sp[0]->v, sp[1]->v, sp[0]->n); -} -void sigwrap_setup() { - sigwrap_class = class_new2("wrap~",sigwrap_new,0,sizeof(t_sigwrap),0,""); - CLASS_MAINSIGNALIN(sigwrap_class, t_sigwrap, a); - class_addmethod2(sigwrap_class, sigwrap_dsp, "dsp",""); -} - -/* ------------------------------ mtof_tilde~ and such -------------------------- */ -struct t_func1 : t_object {float a;}; -t_class *mtof_tilde_class, *ftom_tilde_class; -t_class *dbtorms_tilde_class, *rmstodb_tilde_class; -t_class *dbtopow_tilde_class, *powtodb_tilde_class; - -#define FUNC1(NAME,EXPR) \ -static t_int *NAME##_perform(t_int *w) { \ - float *in = *(t_float **)(w+1), *out = *(t_float **)(w+2); \ - for (t_int n = *(t_int *)(w+3); n--; in++, out++) { float a = *in; *out = (EXPR); } \ - return w+4;} \ -static void *NAME##_new() {t_func1 *x = (t_func1 *)pd_new(NAME##_class); \ - outlet_new(x,&s_signal); x->a = 0; return x;} \ -static void NAME##_dsp(t_func1 *x, t_signal **sp) { \ - dsp_add(NAME##_perform, 3, sp[0]->v, sp[1]->v, sp[0]->n);} - - -FUNC1(mtof_tilde, a<=-1500 ? 0 : 8.17579891564 * exp(.0577622650 * min(a,1499.f))) -FUNC1(ftom_tilde, a>0 ? 17.3123405046 * log(.12231220585 * a) : -1500) -FUNC1(dbtorms_tilde, a<=0 ? 0 : exp((LOGTEN * 0.05) * (min(a,485.f)-100.))) -FUNC1(dbtopow_tilde, a<=0 ? 0 : max(100 + 20./LOGTEN * log(a),0.)) -FUNC1(rmstodb_tilde, a<=0 ? 0 : exp((LOGTEN * 0.1) * (min(a,870.f)-100.))) -FUNC1(powtodb_tilde, a<=0 ? 0 : max(100 + 10./LOGTEN * log(a),0.)) - -#define FUNC1DECL(NAME,SYM) \ - NAME##_class = class_new2(SYM,NAME##_new,0,sizeof(t_func1),0,""); \ - CLASS_MAINSIGNALIN(NAME##_class,t_func1,a); \ - class_addmethod2(NAME##_class, NAME##_dsp, "dsp",""); - -void mtof_tilde_setup() { - FUNC1DECL(mtof_tilde,"mtof~") - FUNC1DECL(ftom_tilde,"ftom~") - FUNC1DECL(dbtorms_tilde,"dbtorms~") - FUNC1DECL(dbtopow_tilde,"dbtopow~") - FUNC1DECL(rmstodb_tilde,"rmstodb~") - FUNC1DECL(powtodb_tilde,"powtodb~") - t_symbol *s = gensym("acoustics~.pd"); - class_sethelpsymbol(mtof_tilde_class, s); - class_sethelpsymbol(ftom_tilde_class, s); - class_sethelpsymbol(dbtorms_tilde_class, s); - class_sethelpsymbol(rmstodb_tilde_class, s); - class_sethelpsymbol(dbtopow_tilde_class, s); - class_sethelpsymbol(powtodb_tilde_class, s); -} - -static t_class *print_class; -struct t_print : t_object { - float a; - t_symbol *sym; - int count; -}; -static t_int *print_perform(t_int *w) { - PERFORM3ARGS(t_print *,x, t_float *,in, int,n); - if (x->count) { - post("%s:", x->sym->name); - if (n == 1) post("%8g", in[0]); - else if (n == 2) post("%8g %8g", in[0], in[1]); - else if (n == 4) post("%8g %8g %8g %8g", in[0], in[1], in[2], in[3]); - else while (n > 0) { - post("%-8.5g %-8.5g %-8.5g %-8.5g %-8.5g %-8.5g %-8.5g %-8.5g", - in[0], in[1], in[2], in[3], in[4], in[5], in[6], in[7]); - n -= 8; - in += 8; - } - x->count--; - } - return w+4; -} -static void print_dsp(t_print *x, t_signal **sp) {dsp_add(print_perform, 3, x, sp[0]->v, sp[0]->n);} -static void print_float(t_print *x, t_float f) {x->count = max(0,(int)f);} -static void print_bang(t_print *x) {x->count = 1;} -static void *print_new(t_symbol *s) { - t_print *x = (t_print *)pd_new(print_class); - x->sym = s->name[0] ? s : gensym("print~"); - x->count = 0; - x->a = 0; - return x; -} -static void print_setup() { - print_class = class_new2("print~",print_new,0,sizeof(t_print),0,"S"); - CLASS_MAINSIGNALIN(print_class, t_print, a); - class_addmethod2(print_class, print_dsp, "dsp",""); - class_addbang(print_class, print_bang); - class_addfloat(print_class, print_float); -} - -/* ------------------------ bang~ -------------------------- */ -static t_class *bang_tilde_class; -struct t_bang : t_object { - t_clock *clock; -}; -static t_int *bang_tilde_perform(t_int *w) { - PERFORM1ARGS(t_bang *,x); - clock_delay(x->clock, 0); - return w+2; -} -static void bang_tilde_dsp(t_bang *x, t_signal **sp) {dsp_add(bang_tilde_perform, 1, x);} -static void bang_tilde_tick(t_bang *x) {x->outlet->send();} -static void bang_tilde_free(t_bang *x) {clock_free(x->clock);} -static void *bang_tilde_new(t_symbol *s) { - t_bang *x = (t_bang *)pd_new(bang_tilde_class); - x->clock = clock_new(x, bang_tilde_tick); - outlet_new(x, &s_bang); - return x; -} -static void bang_tilde_setup() { - bang_tilde_class = class_new2("bang~",bang_tilde_new,bang_tilde_free,sizeof(t_bang),0,""); - class_addmethod2(bang_tilde_class, bang_tilde_dsp, "dsp",""); -} - -/* -------------------------- phasor~ ------------------------------ */ -static t_class *phasor_class; -/* in the style of R. Hoeldrich (ICMC 1995 Banff) */ -struct t_phasor : t_object { - double phase; - float conv; - float a; /* scalar frequency */ -}; -static void *phasor_new(t_floatarg f) { - t_phasor *x = (t_phasor *)pd_new(phasor_class); - x->a = f; - inlet_new(x, x, &s_float, gensym("ft1")); - x->phase = 0; - x->conv = 0; - outlet_new(x, &s_signal); - return x; -} -static t_int *phasor_perform(t_int *w) { - PERFORM4ARGS(t_phasor *,x, t_float *,in, t_float *,out, int,n); - double dphase = x->phase + UNITBIT32; - union tabfudge tf; - int normhipart; - float conv = x->conv; - tf.d = UNITBIT32; - normhipart = tf.i[HIOFFSET]; - tf.d = dphase; - while (n--) { - tf.i[HIOFFSET] = normhipart; - dphase += *in++ * conv; - *out++ = tf.d - UNITBIT32; - tf.d = dphase; - } - tf.i[HIOFFSET] = normhipart; - x->phase = tf.d - UNITBIT32; - return w+5; -} -static void phasor_dsp(t_phasor *x, t_signal **sp) { - x->conv = 1./sp[0]->sr; - dsp_add(phasor_perform, 4, x, sp[0]->v, sp[1]->v, sp[0]->n); -} -static void phasor_ft1(t_phasor *x, t_float f) { - x->phase = f; -} -static void phasor_setup() { - phasor_class = class_new2("phasor~",phasor_new,0,sizeof(t_phasor),0,"F"); - CLASS_MAINSIGNALIN(phasor_class, t_phasor, a); - class_addmethod2(phasor_class, phasor_dsp, "dsp",""); - class_addmethod2(phasor_class, phasor_ft1,"ft1","f"); -} -/* </Hoeldrich-version> */ - -/* ------------------------ cos~ ----------------------------- */ -float *cos_table; -static t_class *cos_class; -struct t_cos : t_object { - float a; -}; -static void *cos_new() { - t_cos *x = (t_cos *)pd_new(cos_class); - outlet_new(x,&s_signal); - x->a = 0; - return x; -} -static t_int *cos_perform(t_int *w) { - PERFORM3ARGS(t_float *,in, t_float *,out, int,n); - float *tab = cos_table, *addr, f1, f2, frac; - double dphase; - int normhipart; - union tabfudge tf; - tf.d = UNITBIT32; - normhipart = tf.i[HIOFFSET]; - -#if 0 /* this is the readable version of the code. */ - while (n--) { - dphase = double(*in++ * float(COSTABSIZE)) + UNITBIT32; - tf.d = dphase; - addr = tab + (tf.i[HIOFFSET] & (COSTABSIZE-1)); - tf.i[HIOFFSET] = normhipart; - frac = tf.d - UNITBIT32; - f1 = addr[0]; - f2 = addr[1]; - *out++ = f1 + frac * (f2 - f1); - } -#else /* this is the same, unwrapped by hand. */ - dphase = double(*in++ * float(COSTABSIZE)) + UNITBIT32; - tf.d = dphase; - addr = tab + (tf.i[HIOFFSET] & (COSTABSIZE-1)); - tf.i[HIOFFSET] = normhipart; - while (--n) { - dphase = double(*in++ * float(COSTABSIZE)) + UNITBIT32; - frac = tf.d - UNITBIT32; - tf.d = dphase; - f1 = addr[0]; - f2 = addr[1]; - addr = tab + (tf.i[HIOFFSET] & (COSTABSIZE-1)); - *out++ = f1 + frac * (f2 - f1); - tf.i[HIOFFSET] = normhipart; - } - frac = 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]->v, sp[1]->v, sp[0]->n); -} -static void cos_maketable() { - float phsinc = (2. * 3.14159) / COSTABSIZE; - union tabfudge tf; - if (cos_table) return; - cos_table = (float *)getbytes(sizeof(float) * (COSTABSIZE+1)); - float phase=0; - float *fp = cos_table; - for (int i = COSTABSIZE + 1; 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.d = UNITBIT32 + 0.5; - if ((unsigned)tf.i[LOWOFFSET] != 0x80000000) bug("cos~: unexpected machine alignment"); -} -static void cos_setup() { - cos_class = class_new2("cos~",cos_new,0,sizeof(t_cos),0,"F"); - CLASS_MAINSIGNALIN(cos_class, t_cos, a); - class_addmethod2(cos_class, cos_dsp, "dsp",""); - cos_maketable(); -} - -/* ------------------------ osc~ ----------------------------- */ -static t_class *osc_class; -struct t_osc : t_object { - double phase; - float conv; - float a; /* frequency if scalar */ -}; -static void *osc_new(t_floatarg f) { - t_osc *x = (t_osc *)pd_new(osc_class); - x->a = f; - outlet_new(x,&s_signal); - inlet_new(x, x, &s_float, gensym("ft1")); - inlet_settip(x->inlet,gensym("phase")); - x->phase = 0; - x->conv = 0; - return x; -} -static t_int *osc_perform(t_int *w) { - PERFORM4ARGS(t_osc *,x, t_float *,in, t_float *,out, int,n); - float *tab = cos_table, *addr, f1, f2, frac; - double dphase = x->phase + UNITBIT32; - int normhipart; - union tabfudge tf; - float conv = x->conv; - tf.d = UNITBIT32; - normhipart = tf.i[HIOFFSET]; - tf.d = dphase; - dphase += *in++ * conv; - addr = tab + (tf.i[HIOFFSET] & (COSTABSIZE-1)); - tf.i[HIOFFSET] = normhipart; - frac = tf.d - UNITBIT32; - while (--n) { - tf.d = dphase; - f1 = addr[0]; - dphase += *in++ * conv; - f2 = addr[1]; - addr = tab + (tf.i[HIOFFSET] & (COSTABSIZE-1)); - tf.i[HIOFFSET] = normhipart; - *out++ = f1 + frac * (f2 - f1); - frac = tf.d - UNITBIT32; - } - f1 = addr[0]; - f2 = addr[1]; - *out++ = f1 + frac * (f2 - f1); - tf.d = UNITBIT32 * COSTABSIZE; - normhipart = tf.i[HIOFFSET]; - tf.d = dphase + (UNITBIT32 * COSTABSIZE - UNITBIT32); - tf.i[HIOFFSET] = normhipart; - x->phase = tf.d - UNITBIT32 * COSTABSIZE; - return w+5; -} -static void osc_dsp(t_osc *x, t_signal **sp) { - x->conv = COSTABSIZE/sp[0]->sr; - dsp_add(osc_perform, 4, x, sp[0]->v, sp[1]->v, sp[0]->n); -} -static void osc_ft1(t_osc *x, t_float f) {x->phase = COSTABSIZE * f;} -static void osc_setup() { - osc_class = class_new2("osc~",osc_new,0,sizeof(t_osc),0,"F"); - CLASS_MAINSIGNALIN(osc_class, t_osc, a); - class_addmethod2(osc_class, osc_dsp, "dsp",""); - class_addmethod2(osc_class, osc_ft1, "ft1","f"); - class_settip(osc_class,gensym("frequency")); - cos_maketable(); -} - -/* ---------------- vcf~ - 2-pole bandpass filter. ----------------- */ -struct t_vcfctl { - float re; - float im; - float q; - float isr; -}; -struct t_sigvcf : t_object { - t_vcfctl cspace; - t_vcfctl *ctl; - float a; -}; -t_class *sigvcf_class; -static void *sigvcf_new(t_floatarg q) { - t_sigvcf *x = (t_sigvcf *)pd_new(sigvcf_class); - inlet_new(x, x, &s_signal, &s_signal); - inlet_new(x, x, &s_float, gensym("ft1")); - outlet_new(x, &s_signal); - outlet_new(x, &s_signal); - x->ctl = &x->cspace; - x->cspace.re = 0; - x->cspace.im = 0; - x->cspace.q = q; - x->cspace.isr = 0; - x->a = 0; - return x; -} -static void sigvcf_ft1(t_sigvcf *x, t_floatarg f) { - x->ctl->q = (f > 0 ? f : 0.f); -} -static t_int *sigvcf_perform(t_int *w) { - PERFORM6ARGS(float *,in1, float *,in2, float *,out1, float *,out2, t_vcfctl *,c, int,n); - float re = c->re, re2; - float im = c->im; - float q = c->q; - float qinv = (q > 0? 1.0f/q : 0); - float ampcorrect = 2.0f - 2.0f / (q + 2.0f); - float isr = c->isr; - float coefr, coefi; - float *tab = cos_table, *addr, f1, f2, frac; - double dphase; - int normhipart, tabindex; - union tabfudge tf; - tf.d = UNITBIT32; - normhipart = tf.i[HIOFFSET]; - for (int 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.d = dphase; - tabindex = tf.i[HIOFFSET] & (COSTABSIZE-1); - addr = tab + tabindex; - tf.i[HIOFFSET] = normhipart; - frac = 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; - } - if (PD_BIGORSMALL(re)) re = 0; - if (PD_BIGORSMALL(im)) im = 0; - c->re = re; - c->im = im; - return w+7; -} -static void sigvcf_dsp(t_sigvcf *x, t_signal **sp) { - x->ctl->isr = 6.28318f/sp[0]->sr; - dsp_add(sigvcf_perform, 6, sp[0]->v, sp[1]->v, sp[2]->v, sp[3]->v, x->ctl, sp[0]->n); - -} -void sigvcf_setup() { - sigvcf_class = class_new2("vcf~",sigvcf_new,0,sizeof(t_sigvcf),0,"F"); - CLASS_MAINSIGNALIN(sigvcf_class, t_sigvcf, a); - class_addmethod2(sigvcf_class, sigvcf_dsp, "dsp",""); - class_addmethod2(sigvcf_class, sigvcf_ft1, "ft1","f"); -} - -/* -------------------------- noise~ ------------------------------ */ -static t_class *noise_class; -struct t_noise : t_object { - int val; -}; -static void *noise_new() { - t_noise *x = (t_noise *)pd_new(noise_class); - static int init = 307; - x->val = (init *= 1319); - outlet_new(x, &s_signal); - return x; -} -static t_int *noise_perform(t_int *w) { - PERFORM3ARGS(t_float *,out, int *,vp, int,n); - 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]->v, &x->val, sp[0]->n); -} -static void noise_setup() { - noise_class = class_new2("noise~",noise_new,0,sizeof(t_noise),0,""); - class_addmethod2(noise_class, noise_dsp, "dsp",""); -} -void builtins_dsp_setup() { - plus_setup(); minus_setup(); - times_setup(); over_setup(); - max_setup(); min_setup(); - lt_setup(); gt_setup(); - le_setup(); ge_setup(); - eq_setup(); ne_setup(); - //abs_setup(); - - tab_tilde_setup(); - tabosc4_tilde_setup(); - tabsend_setup(); - tabreceive_setup(); - tabread_setup(); - tabread4_setup(); - tabwrite_setup(); - - sig_tilde_setup(); - line_tilde_setup(); snapshot_tilde_setup(); - vline_tilde_setup(); vsnapshot_tilde_setup(); - env_tilde_setup(); - threshold_tilde_setup(); - - dac_setup(); - adc_setup(); - - sigdelwrite_setup(); - sigdelread_setup(); - sigvd_setup(); - - sigframp_setup(); -#ifdef HAVE_LIBFFTW3F - sigfftw_setup(); /* added by Tim Blechmann to support fftw */ -#else - sigfft_setup(); -#endif /* HAVE_LIBFFTW3F */ - - sighip_setup(); - siglop_setup(); - sigbp_setup(); - sigbiquad_setup(); - sigsamphold_setup(); - sigr_setup(); - sigc_setup(); - - sigsend_setup(); - sigreceive_setup(); - sigcatch_setup(); - sigthrow_setup(); - - clip_setup(); - sigsqrt_setup(); - sigwrap_setup(); - mtof_tilde_setup(); - print_setup(); - bang_tilde_setup(); - - phasor_setup(); - cos_setup(); - osc_setup(); - sigvcf_setup(); - noise_setup(); -} |