Hi,

On 19/12/2019 20:01, IOhannes m zmölnig wrote:
the high-performance phase-wrapping algorithm
For reference: https://github.com/pure-data/pure-data/blob/e3a78da5b7d825bf8b9f5d313e4ea55e5e32e8f1/src/d_osc.c#L91-L97 (current master at time of writing)

Using a [phasor~] with x -= floor(x); for wrapping is about twice as slow as the built-in tabfudge version, provided I compile with -march=native on my AMD Ryzen 7 2700X Eight-Core Processor.  When compiled with pd-lib-builder's default -march=core2, the floor version is over five times slower.  I can run tests on other hardware in early January if more data points are desired.

Benchmark methodology: time how long running 1000 copies of [phasor~ 440] takes in pd -batch, with a timeout.pd that quits pd after 1 minute of logical time.  The tabfudge version finishes in 3 seconds.  I used the /usr/bin/pd in 0.49.0-3 (Debian Buster).

I suppose it's not so hard to load a custom phasor~ library (source attached), if you need the extra accuracy of the floor version, and can live with the slowdown.  I did this already in one project for a vcf~ with internal double precision feedback state.


Claude
--
https://mathr.co.uk

PDLIBBUILDER_DIR=../pd-lib-builder/
lib.name = phasor~
class.sources = phasor~.c
include $(PDLIBBUILDER_DIR)/Makefile.pdlibbuilder
#include <m_pd.h>
#include <math.h>

/* -------------------------- phasor~ ------------------------------ */
static t_class *phasor_class;

typedef struct _phasor
{
    t_object x_obj;
    double x_phase;
    float x_conv;
    float x_f;      /* scalar frequency */
} t_phasor;

static void *phasor_new(t_floatarg f)
{
    t_phasor *x = (t_phasor *)pd_new(phasor_class);
    x->x_f = f;
    inlet_new(&x->x_obj, &x->x_obj.ob_pd, &s_float, gensym("ft1"));
    x->x_phase = 0;
    x->x_conv = 0;
    outlet_new(&x->x_obj, gensym("signal"));
    return (x);
}

static t_int *phasor_perform(t_int *w)
{
    t_phasor *x = (t_phasor *)(w[1]);
    t_float *in = (t_float *)(w[2]);
    t_float *out = (t_float *)(w[3]);
    int n = (int)(w[4]);
    double dphase = x->x_phase;
    float conv = x->x_conv;

    while (n--)
    {
        dphase += *in++ * conv;
        dphase -= floor(dphase);
        *out++ = dphase;
    }
    x->x_phase = dphase;
    return (w+5);
}

static void phasor_dsp(t_phasor *x, t_signal **sp)
{
    x->x_conv = 1./sp[0]->s_sr;
    dsp_add(phasor_perform, 4, x, sp[0]->s_vec, sp[1]->s_vec, sp[0]->s_n);
}

static void phasor_ft1(t_phasor *x, t_float f)
{
    x->x_phase = f;
}

extern void phasor_tilde_setup(void)
{
    phasor_class = class_new(gensym("phasor~"), (t_newmethod)phasor_new, 0,
        sizeof(t_phasor), 0, A_DEFFLOAT, 0);
    CLASS_MAINSIGNALIN(phasor_class, t_phasor, x_f);
    class_addmethod(phasor_class, (t_method)phasor_dsp,
        gensym("dsp"), A_CANT, 0);
    class_addmethod(phasor_class, (t_method)phasor_ft1,
        gensym("ft1"), A_FLOAT, 0);
}
_______________________________________________
Pd-dev mailing list
[email protected]
https://lists.puredata.info/listinfo/pd-dev

Reply via email to