From 783aafff32c7e02727e73d86918fa524dfc76e22 Mon Sep 17 00:00:00 2001 From: Miller Puckette Date: Fri, 4 Jul 2008 03:53:15 +0000 Subject: many bug fixes. sigmund~ and bonk~ updates (ongoing) some new math objects svn path=/trunk/; revision=10140 --- pd/extra/sigmund~/sigmund~.c | 965 +++++++++++++++++++++++++++---------------- 1 file changed, 610 insertions(+), 355 deletions(-) (limited to 'pd/extra/sigmund~/sigmund~.c') diff --git a/pd/extra/sigmund~/sigmund~.c b/pd/extra/sigmund~/sigmund~.c index ad98bedc..58a3858f 100644 --- a/pd/extra/sigmund~/sigmund~.c +++ b/pd/extra/sigmund~/sigmund~.c @@ -9,11 +9,24 @@ implement block ("-b") mode */ -#include "m_pd.h" +/* From here to the first "#ifdef PD" or "#ifdef Max" should be extractable +and usable in other contexts. The one external requirement is a real +single-precision FFT, invoked as in the Mayer one: */ + +#if (defined(NT) && defined(PD)) /* ignore this, it's just Microsoft nonsense */ +__declspec(dllimport) extern +#endif +void mayer_realfft(int npoints, float *buf); + +/* this routine is passed a buffer of npoints values, and returns the +N/2+1 real parts of the DFT (frequency zero through Nyquist), followed +by the N/2-1 imaginary points, in order of decreasing frequency. Pd 0.41, +for example, defines this in the file d_fft_mayer.c or d_fft_fftsg.c. */ + #include #include #include -#ifdef MSW +#ifdef NT #include #else #include @@ -38,6 +51,8 @@ typedef struct peak /********************** service routines **************************/ +/* these three are dapted from elsewhere in Pd but included here for +cmolpeteness */ static int sigmund_ilog2(int n) { int ret = -1; @@ -49,6 +64,22 @@ static int sigmund_ilog2(int n) return (ret); } +static float sigmund_ftom(float f) +{ + return (f > 0 ? 17.3123405046 * log(.12231220585 * f) : -1500); +} + +#define LOGTEN 2.302585092994 +static float sigmund_powtodb(float f) +{ + if (f <= 0) return (0); + else + { + float val = 100 + 10./LOGTEN * log(f); + return (val < 0 ? 0 : val); + } +} + /* parameters for von Hann window (change these to get Hamming if desired) */ #define W_ALPHA 0.5 #define W_BETA 0.5 @@ -171,8 +202,8 @@ static void sigmund_tweak(int npts, float *ftreal, float *ftimag, ampoutimag = oneovern * ampcorrect * (windreal * sinpidetune + windimag * cospidetune); freqout = (cbin + 2*detune) * fperbin; - if (loud > 1) - post("amp %f, freq %f", ampout, freqout); + /* if (loud > 1) + post("amp %f, freq %f", ampout, freqout); */ peakptrs[peaki]->p_freq = freqout; peakptrs[peaki]->p_amp = ampout; @@ -206,15 +237,15 @@ static void sigmund_getrawpeaks(int npts, float *insamps, float oneovern = 1.0/ (float)npts; float fperbin = 0.5 * srate * oneovern; int npts2 = 2*npts, i, bin; - int count, peakcount = 0; + int peakcount = 0; float *fp1, *fp2; - float *rawpow, *rawreal, *rawimag, *maskbuf, *powbuf; + float *rawreal, *rawimag, *maskbuf, *powbuf; float *bigbuf = alloca(sizeof (float ) * (2*NEGBINS + 6*npts)); int maxbin = hifreq/fperbin; int tweak = (param3 == 0); if (maxbin > npts - NEGBINS) maxbin = npts - NEGBINS; - if (loud) post("tweak %d", tweak); + /* if (loud) post("tweak %d", tweak); */ maskbuf = bigbuf + npts2; powbuf = maskbuf + npts; rawreal = powbuf + npts+NEGBINS; @@ -231,19 +262,6 @@ static void sigmund_getrawpeaks(int npts, float *insamps, rawreal[i] = bigbuf[i]; for (i = 1; i < npts-1; i++) rawimag[i] = bigbuf[npts2-i]; - if (loud && npts == 1024) - { - float bigbuf2[2048]; - for (i = 0; i < 1024; i++) - bigbuf2[i] = insamps[i]; - for (i = 1024; i < 2048; i++) - bigbuf2[i] = 0; - mayer_realfft(2048, bigbuf2); - for (i = 1; i < 10; i++) - post("(%10.2f, %10.2f) -> (%10.2f, %10.2f)", - bigbuf2[i], bigbuf2[2048-i], rawreal[i], rawimag[i]); - } - rawreal[-1] = rawreal[1]; rawreal[-2] = rawreal[2]; rawreal[-3] = rawreal[3]; @@ -265,7 +283,7 @@ static void sigmund_getrawpeaks(int npts, float *insamps, { float pow1, maxpower = 0, totalpower = 0, windreal, windimag, windpower, detune, pidetune, sinpidetune, cospidetune, ampcorrect, ampout, - ampoutreal, ampoutimag, freqout, freqcount1, freqcount2, powmask; + ampoutreal, ampoutimag, freqout, powmask; int bestindex = -1; for (bin = 2, fp1 = rawreal+2, fp2 = rawimag+2; @@ -287,31 +305,27 @@ static void sigmund_getrawpeaks(int npts, float *insamps, fp2 = rawimag+bestindex; *power = 0.5 * totalpower *oneovern * oneovern; powmask = maxpower * exp(-param1 * log(10.) / 10.); - if (loud > 2) + /* if (loud > 2) post("maxpower %f, powmask %f, param1 %f", - maxpower, powmask, param1); + maxpower, powmask, param1); */ sigmund_remask(maxbin, bestindex, powmask, maxpower, maskbuf); - if (loud > 1) - post("best index %d, total power %f", bestindex, totalpower); + /* if (loud > 1) + post("best index %d, total power %f", bestindex, totalpower); */ windreal = fp1[1] - fp1[-1]; windimag = fp2[1] - fp2[-1]; windpower = windreal * windreal + windimag * windimag; detune = ((fp1[1] * fp1[1] - fp1[-1]*fp1[-1]) + (fp2[1] * fp2[1] - fp2[-1]*fp2[-1])) / (2 * windpower); - if (loud > 2) post("(-1) %f %f; (1) %f %f", - fp1[-1], fp2[-1], fp1[1], fp2[1]); - if (loud > 2) post("peak %f %f", - fp1[0], fp2[0]); if (detune > 0.5) detune = 0.5; else if (detune < -0.5) detune = -0.5; - if (loud > 1) + /* if (loud > 1) post("windpower %f, index %d, detune %f", - windpower, bestindex, detune); + windpower, bestindex, detune); */ pidetune = PI * detune; sinpidetune = sin(pidetune); cospidetune = cos(pidetune); @@ -337,8 +351,8 @@ static void sigmund_getrawpeaks(int npts, float *insamps, } for (i = 0; i < peakcount; i++) { - peakv[i].p_pit = ftom(peakv[i].p_freq); - peakv[i].p_db = powtodb(peakv[i].p_amp); + peakv[i].p_pit = sigmund_ftom(peakv[i].p_freq); + peakv[i].p_db = sigmund_powtodb(peakv[i].p_amp); } *nfound = peakcount; } @@ -356,11 +370,9 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp, { float fperbin = 0.5 * srate / npts; int npit = 48 * sigmund_ilog2(npts), i, j, k, nsalient; - float bestbin, bestweight, sumamp, sumweight, sumfreq, sumallamp, - freq; + float bestbin, bestweight, sumamp, sumweight, sumfreq, freq; float *weights = (float *)alloca(sizeof(float) * npit); t_peak *bigpeaks[PITCHNPEAK]; - int nbigpeaks; if (npeak < 1) { freq = 0; @@ -416,13 +428,6 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp, } sumweight += loudness; } -#if 0 - for (i = 0; i < npit; i++) - { - postfloat(weights[i]); - if (!((i+1)%12)) post(""); - } -#endif bestbin = -1; bestweight = -1e20; for (i = 0; i < npit; i++) @@ -466,7 +471,7 @@ static void sigmund_getpitch(int npeak, t_peak *peakv, float *freqp, done: if (!(freq >= 0 || freq <= 0)) { - post("freq nan cancelled"); + /* post("freq nan cancelled"); */ freq = 0; } *freqp = freq; @@ -573,6 +578,7 @@ static void notefinder_doit(t_notefinder *x, float freq, float power, x->n_hist[x->n_histphase].h_power = power; x->n_age++; *note = 0; +#if 0 if (loud) { post("stable %d, age %d, vibmultiple %f, powerthresh %f, hifreq %f", @@ -589,12 +595,13 @@ static void notefinder_doit(t_notefinder *x, float freq, float power, x->n_hist[(x->n_histphase+NHISTPOINT-3)%NHISTPOINT].h_power); for (i = 0, k = x->n_histphase; i < stableperiod; i++) { - post("pit %5.1f pow %f", ftom(x->n_hist[k].h_freq), + post("pit %5.1f pow %f", sigmund_ftom(x->n_hist[k].h_freq), x->n_hist[k].h_power); if (--k < 0) k = NHISTPOINT - 1; } } +#endif /* look for shorter notes than "stableperiod" in length. The amplitude must rise and then fall while the pitch holds steady. */ @@ -713,7 +720,7 @@ static void notefinder_doit(t_notefinder *x, float freq, float power, && maxpow > powerthresh) { /* report new note */ - float sumf = 0, sumw = 0, thisf, thisw; + float sumf = 0, sumw = 0, thisw; for (i = 0, k = x->n_histphase; i < stableperiod; i++) { thisw = x->n_hist[k].h_power; @@ -730,7 +737,7 @@ static void notefinder_doit(t_notefinder *x, float freq, float power, int k3 = x->n_histphase - i; if (k3 < 0) k3 += NHISTPOINT; - startpost("%5.1f ", ftom(x->n_hist[k3].h_freq)); + startpost("%5.1f ", sigmund_ftom(x->n_hist[k3].h_freq)); } post(""); #endif @@ -743,9 +750,26 @@ static void notefinder_doit(t_notefinder *x, float freq, float power, return; } -/*************************** Glue for Pd ************************/ +/**************** object structure for Pd and Max. *********************/ + +/* From here onward, the code is specific to eithr Pd, Max, or both. If +neither "PD 'nor "MSP" is defined, none of this is compiled, so that the +whole file can be included in other, non-PD and non-Max projects. */ +#ifdef PD +#include "m_pd.h" +#endif +#ifdef MSP +#include "ext.h" +#include "z_dsp.h" +#include "ext_support.h" +#include "ext_proto.h" +#include "ext_obex.h" +typedef float t_floatarg; +#define t_resizebytes(a, b, c) t_resizebytes((char *)(a), (b), (c)) +#endif + +#if (defined(PD) || defined (MSP)) -static t_class *sigmund_class; #define NHIST 100 #define MODE_STREAM 1 @@ -773,17 +797,29 @@ static t_class *sigmund_class; typedef struct _varout { +#ifdef PD t_outlet *v_outlet; +#endif /* PD */ +#ifdef MSP + void *v_outlet; +#endif /* MSP */ int v_what; } t_varout; typedef struct _sigmund { +#ifdef PD t_object x_obj; - t_varout *x_varoutv; - int x_nvarout; t_clock *x_clock; float x_f; /* for main signal inlet */ +#endif /* PD */ +#ifdef MSP + t_pxobject x_obj; + void *obex; + void *x_clock; +#endif /* MSP */ + t_varout *x_varoutv; + int x_nvarout; float x_sr; /* sample rate */ int x_mode; /* MODE_STREAM, etc. */ int x_npts; /* number of points in analysis window */ @@ -798,31 +834,19 @@ typedef struct _sigmund float x_stabletime; /* period of stability needed for note */ float x_growth; /* growth to set off a new note */ float x_minpower; /* minimum power, in DB, for a note */ - float x_param1; + float x_param1; /* three parameters for temporary use */ float x_param2; float x_param3; - t_notefinder x_notefinder; - t_peak *x_trackv; - int x_ntrack; - unsigned int x_dopitch:1; + t_notefinder x_notefinder; /* note parsing state */ + t_peak *x_trackv; /* peak tracking state */ + int x_ntrack; /* number of peaks tracked */ + unsigned int x_dopitch:1; /* which things to calculate */ unsigned int x_donote:1; unsigned int x_dotracks:1; } t_sigmund; -static void sigmund_clock(t_sigmund *x); -static void sigmund_clear(t_sigmund *x); -static void sigmund_npts(t_sigmund *x, t_floatarg f); -static void sigmund_hop(t_sigmund *x, t_floatarg f); -static void sigmund_npeak(t_sigmund *x, t_floatarg f); -static void sigmund_maxfreq(t_sigmund *x, t_floatarg f); -static void sigmund_vibrato(t_sigmund *x, t_floatarg f); -static void sigmund_stabletime(t_sigmund *x, t_floatarg f); -static void sigmund_growth(t_sigmund *x, t_floatarg f); -static void sigmund_minpower(t_sigmund *x, t_floatarg f); - -static void *sigmund_new(t_symbol *s, int argc, t_atom *argv) +static void sigmund_preinit(t_sigmund *x) { - t_sigmund *x = (t_sigmund *)pd_new(sigmund_class); x->x_npts = NPOINTS_DEF; x->x_param1 = 0; x->x_param2 = 0.6; @@ -843,89 +867,321 @@ static void *sigmund_new(t_symbol *s, int argc, t_atom *argv) x->x_ntrack = 0; x->x_dopitch = x->x_donote = x->x_dotracks = 0; x->x_inbuf = 0; +} - while (argc > 0) +static void sigmund_npts(t_sigmund *x, t_floatarg f) +{ + int nwas = x->x_npts, npts = f; + /* check parameter ranges */ + if (npts < NPOINTS_MIN) + post("sigmund~: minimum points %d", NPOINTS_MIN), + npts = NPOINTS_MIN; + if (npts != (1 << sigmund_ilog2(npts))) + post("sigmund~: adjusting analysis size to %d points", + (npts = (1 << sigmund_ilog2(npts)))); + if (npts != nwas) + x->x_countdown = x->x_infill = 0; + if (x->x_mode == MODE_STREAM) { - t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); - if (!strcmp(firstarg->s_name, "-t")) - { - x->x_mode = MODE_TABLE; - argc--, argv++; - } - else if (!strcmp(firstarg->s_name, "-s")) - { - x->x_mode = MODE_STREAM; - argc--, argv++; - } -#if 0 - else if (!strcmp(firstarg->s_name, "-b")) - { - x->x_mode = MODE_BLOCK; - argc--, argv++; - } -#endif - else if (!strcmp(firstarg->s_name, "-npts") && argc > 1) - { - x->x_npts = atom_getfloatarg(1, argc, argv); - argc -= 2; argv += 2; - } - else if (!strcmp(firstarg->s_name, "-hop") && argc > 1) - { - sigmund_hop(x, atom_getfloatarg(1, argc, argv)); - argc -= 2; argv += 2; - } - else if (!strcmp(firstarg->s_name, "-npeak") && argc > 1) - { - sigmund_npeak(x, atom_getfloatarg(1, argc, argv)); - argc -= 2; argv += 2; - } - else if (!strcmp(firstarg->s_name, "-maxfreq") && argc > 1) - { - sigmund_maxfreq(x, atom_getfloatarg(1, argc, argv)); - argc -= 2; argv += 2; - } - else if (!strcmp(firstarg->s_name, "-vibrato") && argc > 1) - { - sigmund_vibrato(x, atom_getfloatarg(1, argc, argv)); - argc -= 2; argv += 2; - } - else if (!strcmp(firstarg->s_name, "-stabletime") && argc > 1) - { - sigmund_stabletime(x, atom_getfloatarg(1, argc, argv)); - argc -= 2; argv += 2; - } - else if (!strcmp(firstarg->s_name, "-growth") && argc > 1) + if (x->x_inbuf) + x->x_inbuf = (t_sample *)t_resizebytes(x->x_inbuf, + sizeof(*x->x_inbuf) * nwas, sizeof(*x->x_inbuf) * npts); + else x->x_inbuf = (t_sample *)getbytes(sizeof(*x->x_inbuf) * npts); + } + else x->x_inbuf = 0; + x->x_npts = npts; +} + +static void sigmund_hop(t_sigmund *x, t_floatarg f) +{ + x->x_hop = f; + /* check parameter ranges */ + if (x->x_hop != (1 << sigmund_ilog2(x->x_hop))) + post("sigmund~: adjusting analysis size to %d points", + (x->x_hop = (1 << sigmund_ilog2(x->x_hop)))); +} + +static void sigmund_npeak(t_sigmund *x, t_floatarg f) +{ + if (f < 1) + f = 1; + x->x_npeak = f; +} + +static void sigmund_maxfreq(t_sigmund *x, t_floatarg f) +{ + x->x_maxfreq = f; +} + +static void sigmund_vibrato(t_sigmund *x, t_floatarg f) +{ + if (f < 0) + f = 0; + x->x_vibrato = f; +} + +static void sigmund_stabletime(t_sigmund *x, t_floatarg f) +{ + if (f < 0) + f = 0; + x->x_stabletime = f; +} + +static void sigmund_growth(t_sigmund *x, t_floatarg f) +{ + if (f < 0) + f = 0; + x->x_growth = f; +} + +static void sigmund_minpower(t_sigmund *x, t_floatarg f) +{ + if (f < 0) + f = 0; + x->x_minpower = f; +} + +static void sigmund_doit(t_sigmund *x, int npts, float *arraypoints, + int loud, float srate) +{ + t_peak *peakv = (t_peak *)alloca(sizeof(t_peak) * x->x_npeak); + int nfound, i, cnt; + float freq = 0, power, note = 0; + sigmund_getrawpeaks(npts, arraypoints, x->x_npeak, peakv, + &nfound, &power, srate, loud, x->x_param1, x->x_param2, x->x_param3, + x->x_maxfreq); + if (x->x_dopitch) + sigmund_getpitch(nfound, peakv, &freq, npts, srate, loud); + if (x->x_donote) + notefinder_doit(&x->x_notefinder, freq, power, ¬e, x->x_vibrato, + x->x_stabletime * 0.001f * x->x_sr / (float)x->x_hop, + exp(LOG10*0.1*(x->x_minpower - 100)), x->x_growth, loud); + if (x->x_dotracks) + sigmund_peaktrack(nfound, peakv, x->x_ntrack, x->x_trackv, loud); + + for (cnt = x->x_nvarout; cnt--;) + { + t_varout *v = &x->x_varoutv[cnt]; + switch (v->v_what) { - sigmund_growth(x, atom_getfloatarg(1, argc, argv)); - argc -= 2; argv += 2; + case OUT_PITCH: + outlet_float(v->v_outlet, sigmund_ftom(freq)); + break; + case OUT_ENV: + outlet_float(v->v_outlet, sigmund_powtodb(power)); + break; + case OUT_NOTE: + if (note > 0) + outlet_float(v->v_outlet, sigmund_ftom(note)); + break; + case OUT_PEAKS: + for (i = 0; i < nfound; i++) + { + t_atom at[5]; + SETFLOAT(at, (float)i); + SETFLOAT(at+1, peakv[i].p_freq); + SETFLOAT(at+2, 2*peakv[i].p_amp); + SETFLOAT(at+3, 2*peakv[i].p_ampreal); + SETFLOAT(at+4, 2*peakv[i].p_ampimag); + outlet_list(v->v_outlet, 0, 5, at); + } + break; + case OUT_TRACKS: + for (i = 0; i < x->x_ntrack; i++) + { + t_atom at[4]; + SETFLOAT(at, (float)i); + SETFLOAT(at+1, x->x_trackv[i].p_freq); + SETFLOAT(at+2, 2*x->x_trackv[i].p_amp); + SETFLOAT(at+3, x->x_trackv[i].p_tmp); + outlet_list(v->v_outlet, 0, 4, at); + } + break; } - else if (!strcmp(firstarg->s_name, "-minpower") && argc > 1) + } +} + +static void sigmund_tick(t_sigmund *x) +{ + if (x->x_infill == x->x_npts) + { + sigmund_doit(x, x->x_npts, x->x_inbuf, x->x_loud, x->x_sr); + if (x->x_hop >= x->x_npts) { - sigmund_minpower(x, atom_getfloatarg(1, argc, argv)); - argc -= 2; argv += 2; + x->x_infill = 0; + x->x_countdown = x->x_hop - x->x_npts; } - else if (!strcmp(firstarg->s_name, "pitch")) + else { - int n2 = x->x_nvarout+1; - x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, - x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); - x->x_varoutv[x->x_nvarout].v_outlet = - outlet_new(&x->x_obj, &s_float); - x->x_varoutv[x->x_nvarout].v_what = OUT_PITCH; - x->x_nvarout = n2; - x->x_dopitch = 1; - argc--, argv++; + memmove(x->x_inbuf, x->x_inbuf + x->x_hop, + (x->x_infill = x->x_npts - x->x_hop) * sizeof(*x->x_inbuf)); + x->x_countdown = 0; } - else if (!strcmp(firstarg->s_name, "env")) - { - int n2 = x->x_nvarout+1; - x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, - x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); - x->x_varoutv[x->x_nvarout].v_outlet = - outlet_new(&x->x_obj, &s_float); - x->x_varoutv[x->x_nvarout].v_what = OUT_ENV; - x->x_nvarout = n2; - argc--, argv++; + x->x_loud = 0; + } +} + +static t_int *sigmund_perform(t_int *w) +{ + t_sigmund *x = (t_sigmund *)(w[1]); + float *in = (float *)(w[2]); + int n = (int)(w[3]); + + if (x->x_hop % n) + return (w+4); + if (x->x_countdown > 0) + x->x_countdown -= n; + else if (x->x_infill != x->x_npts) + { + int j; + float *fp = x->x_inbuf + x->x_infill; + for (j = 0; j < n; j++) + *fp++ = *in++; + x->x_infill += n; + if (x->x_infill == x->x_npts) + clock_delay(x->x_clock, 0); + } + return (w+4); +} + +static void sigmund_dsp(t_sigmund *x, t_signal **sp) +{ + if (x->x_mode == MODE_STREAM) + { + if (x->x_hop % sp[0]->s_n) + post("sigmund: adjusting hop size to %d", + (x->x_hop = sp[0]->s_n * (x->x_hop / sp[0]->s_n))); + x->x_sr = sp[0]->s_sr; + dsp_add(sigmund_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); + } +} + +static void sigmund_print(t_sigmund *x) +{ + post("sigmund~ settings:"); + post("npts %d", (int)x->x_npts); + post("hop %d", (int)x->x_hop); + post("npeak %d", (int)x->x_npeak); + post("maxfreq %g", x->x_maxfreq); + post("vibrato %g", x->x_vibrato); + post("stabletime %g", x->x_stabletime); + post("growth %g", x->x_growth); + post("minpower %g", x->x_minpower); +} + +static void sigmund_free(t_sigmund *x) +{ + if (x->x_inbuf) + freebytes(x->x_inbuf, x->x_npts * sizeof(*x->x_inbuf)); + if (x->x_trackv) + freebytes(x->x_trackv, x->x_ntrack * sizeof(*x->x_trackv)); + clock_free(x->x_clock); +} + +#endif /* PD or MSP */ +/*************************** Glue for Pd ************************/ +#ifdef PD + +static t_class *sigmund_class; + +static void sigmund_tick(t_sigmund *x); +static void sigmund_clear(t_sigmund *x); +static void sigmund_npts(t_sigmund *x, t_floatarg f); +static void sigmund_hop(t_sigmund *x, t_floatarg f); +static void sigmund_npeak(t_sigmund *x, t_floatarg f); +static void sigmund_maxfreq(t_sigmund *x, t_floatarg f); +static void sigmund_vibrato(t_sigmund *x, t_floatarg f); +static void sigmund_stabletime(t_sigmund *x, t_floatarg f); +static void sigmund_growth(t_sigmund *x, t_floatarg f); +static void sigmund_minpower(t_sigmund *x, t_floatarg f); + +static void *sigmund_new(t_symbol *s, int argc, t_atom *argv) +{ + t_sigmund *x = (t_sigmund *)pd_new(sigmund_class); + sigmund_preinit(x); + + while (argc > 0) + { + t_symbol *firstarg = atom_getsymbolarg(0, argc, argv); + if (!strcmp(firstarg->s_name, "-t")) + { + x->x_mode = MODE_TABLE; + argc--, argv++; + } + else if (!strcmp(firstarg->s_name, "-s")) + { + x->x_mode = MODE_STREAM; + argc--, argv++; + } +#if 0 + else if (!strcmp(firstarg->s_name, "-b")) + { + x->x_mode = MODE_BLOCK; + argc--, argv++; + } +#endif + else if (!strcmp(firstarg->s_name, "-npts") && argc > 1) + { + x->x_npts = atom_getfloatarg(1, argc, argv); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-hop") && argc > 1) + { + sigmund_hop(x, atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-npeak") && argc > 1) + { + sigmund_npeak(x, atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-maxfreq") && argc > 1) + { + sigmund_maxfreq(x, atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-vibrato") && argc > 1) + { + sigmund_vibrato(x, atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-stabletime") && argc > 1) + { + sigmund_stabletime(x, atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-growth") && argc > 1) + { + sigmund_growth(x, atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "-minpower") && argc > 1) + { + sigmund_minpower(x, atom_getfloatarg(1, argc, argv)); + argc -= 2; argv += 2; + } + else if (!strcmp(firstarg->s_name, "pitch")) + { + int n2 = x->x_nvarout+1; + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); + x->x_varoutv[x->x_nvarout].v_outlet = + outlet_new(&x->x_obj, &s_float); + x->x_varoutv[x->x_nvarout].v_what = OUT_PITCH; + x->x_nvarout = n2; + x->x_dopitch = 1; + argc--, argv++; + } + else if (!strcmp(firstarg->s_name, "env")) + { + int n2 = x->x_nvarout+1; + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); + x->x_varoutv[x->x_nvarout].v_outlet = + outlet_new(&x->x_obj, &s_float); + x->x_varoutv[x->x_nvarout].v_what = OUT_ENV; + x->x_nvarout = n2; + argc--, argv++; } else if (!strcmp(firstarg->s_name, "note") || !strcmp(firstarg->s_name, "notes")) @@ -986,7 +1242,7 @@ static void *sigmund_new(t_symbol *s, int argc, t_atom *argv) x->x_ntrack = x->x_npeak; x->x_trackv = (t_peak *)getbytes(x->x_ntrack * sizeof(*x->x_trackv)); } - x->x_clock = clock_new(&x->x_obj.ob_pd, (t_method)sigmund_clock); + x->x_clock = clock_new(&x->x_obj.ob_pd, (t_method)sigmund_tick); x->x_infill = 0; x->x_countdown = 0; @@ -996,66 +1252,6 @@ static void *sigmund_new(t_symbol *s, int argc, t_atom *argv) return (x); } -static void sigmund_doit(t_sigmund *x, int npts, float *arraypoints, - int loud, float srate) -{ - t_peak *peakv = (t_peak *)alloca(sizeof(t_peak) * x->x_npeak); - int nfound, i, cnt; - float freq = 0, power, note = 0; - sigmund_getrawpeaks(npts, arraypoints, x->x_npeak, peakv, - &nfound, &power, srate, loud, x->x_param1, x->x_param2, x->x_param3, - x->x_maxfreq); - if (x->x_dopitch) - sigmund_getpitch(nfound, peakv, &freq, npts, srate, loud); - if (x->x_donote) - notefinder_doit(&x->x_notefinder, freq, power, ¬e, x->x_vibrato, - x->x_stabletime * 0.001f * x->x_sr / (float)x->x_hop, - exp(LOG10*0.1*(x->x_minpower - 100)), x->x_growth, loud); - if (x->x_dotracks) - sigmund_peaktrack(nfound, peakv, x->x_ntrack, x->x_trackv, loud); - - for (cnt = x->x_nvarout; cnt--;) - { - t_varout *v = &x->x_varoutv[cnt]; - switch (v->v_what) - { - case OUT_PITCH: - outlet_float(v->v_outlet, ftom(freq)); - break; - case OUT_ENV: - outlet_float(v->v_outlet, powtodb(power)); - break; - case OUT_NOTE: - if (note > 0) - outlet_float(v->v_outlet, ftom(note)); - break; - case OUT_PEAKS: - for (i = 0; i < nfound; i++) - { - t_atom at[5]; - SETFLOAT(at, (float)i); - SETFLOAT(at+1, peakv[i].p_freq); - SETFLOAT(at+2, 2*peakv[i].p_amp); - SETFLOAT(at+3, 2*peakv[i].p_ampreal); - SETFLOAT(at+4, 2*peakv[i].p_ampimag); - outlet_list(v->v_outlet, &s_list, 5, at); - } - break; - case OUT_TRACKS: - for (i = 0; i < x->x_ntrack; i++) - { - t_atom at[4]; - SETFLOAT(at, (float)i); - SETFLOAT(at+1, x->x_trackv[i].p_freq); - SETFLOAT(at+2, 2*x->x_trackv[i].p_amp); - SETFLOAT(at+3, x->x_trackv[i].p_tmp); - outlet_list(v->v_outlet, &s_list, 4, at); - } - break; - } - } -} - static void sigmund_list(t_sigmund *x, t_symbol *s, int argc, t_atom *argv) { t_symbol *syminput = atom_getsymbolarg(0, argc, argv); @@ -1124,160 +1320,11 @@ static void sigmund_param3(t_sigmund *x, t_floatarg f) x->x_param3 = f; } -static void sigmund_npts(t_sigmund *x, t_floatarg f) -{ - int nwas = x->x_npts, npts = f; - /* check parameter ranges */ - if (npts < NPOINTS_MIN) - post("sigmund~: minimum points %d", NPOINTS_MIN), - npts = NPOINTS_MIN; - if (npts != (1 << sigmund_ilog2(npts))) - post("sigmund~: adjusting analysis size to %d points", - (npts = (1 << sigmund_ilog2(npts)))); - if (npts != nwas) - x->x_countdown = x->x_infill = 0; - if (x->x_mode == MODE_STREAM) - { - if (x->x_inbuf) - x->x_inbuf = resizebytes(x->x_inbuf, - sizeof(*x->x_inbuf) * nwas, sizeof(*x->x_inbuf) * npts); - else x->x_inbuf = getbytes(sizeof(*x->x_inbuf) * npts); - } - else x->x_inbuf = 0; - x->x_npts = npts; -} - -static void sigmund_hop(t_sigmund *x, t_floatarg f) -{ - x->x_hop = f; - /* check parameter ranges */ - if (x->x_hop != (1 << sigmund_ilog2(x->x_hop))) - post("sigmund~: adjusting analysis size to %d points", - (x->x_hop = (1 << sigmund_ilog2(x->x_hop)))); -} - -static void sigmund_npeak(t_sigmund *x, t_floatarg f) -{ - if (f < 1) - f = 1; - x->x_npeak = f; -} - -static void sigmund_maxfreq(t_sigmund *x, t_floatarg f) -{ - x->x_maxfreq = f; -} - -static void sigmund_vibrato(t_sigmund *x, t_floatarg f) -{ - if (f < 0) - f = 0; - x->x_vibrato = f; -} - -static void sigmund_stabletime(t_sigmund *x, t_floatarg f) -{ - if (f < 0) - f = 0; - x->x_stabletime = f; -} - -static void sigmund_growth(t_sigmund *x, t_floatarg f) -{ - if (f < 0) - f = 0; - x->x_growth = f; -} - -static void sigmund_minpower(t_sigmund *x, t_floatarg f) -{ - if (f < 0) - f = 0; - x->x_minpower = f; -} - -static void sigmund_print(t_sigmund *x) -{ - post("sigmund~ settings:"); - post("npts %d", (int)x->x_npts); - post("hop %d", (int)x->x_hop); - post("npeak %d", (int)x->x_npeak); - post("maxfreq %g", x->x_maxfreq); - post("vibrato %g", x->x_vibrato); - post("stabletime %g", x->x_stabletime); - post("growth %g", x->x_growth); - post("minpower %g", x->x_minpower); -} - static void sigmund_printnext(t_sigmund *x, t_float f) { x->x_loud = f; } -static void sigmund_clock(t_sigmund *x) -{ - if (x->x_infill == x->x_npts) - { - sigmund_doit(x, x->x_npts, x->x_inbuf, x->x_loud, x->x_sr); - if (x->x_hop >= x->x_npts) - { - x->x_infill = 0; - x->x_countdown = x->x_hop - x->x_npts; - } - else - { - memmove(x->x_inbuf, x->x_inbuf + x->x_hop, - (x->x_infill = x->x_npts - x->x_hop) * sizeof(*x->x_inbuf)); - x->x_countdown = 0; - } - x->x_loud = 0; - } -} - -static t_int *sigmund_perform(t_int *w) -{ - t_sigmund *x = (t_sigmund *)(w[1]); - float *in = (float *)(w[2]); - int n = (int)(w[3]); - - if (x->x_hop % n) - return (w+4); - if (x->x_countdown > 0) - x->x_countdown -= n; - else if (x->x_infill != x->x_npts) - { - int i, j; - float *fp = x->x_inbuf + x->x_infill; - for (j = 0; j < n; j++) - *fp++ = *in++; - x->x_infill += n; - if (x->x_infill == x->x_npts) - clock_delay(x->x_clock, 0); - } - return (w+4); -} - -static void sigmund_dsp(t_sigmund *x, t_signal **sp) -{ - if (x->x_mode == MODE_STREAM) - { - if (x->x_hop % sp[0]->s_n) - post("sigmund: adjusting hop size to %d", - (x->x_hop = sp[0]->s_n * (x->x_hop / sp[0]->s_n))); - x->x_sr = sp[0]->s_sr; - dsp_add(sigmund_perform, 3, x, sp[0]->s_vec, sp[0]->s_n); - } -} - -static void sigmund_free(t_sigmund *x) -{ - if (x->x_inbuf) - freebytes(x->x_inbuf, x->x_npts * sizeof(*x->x_inbuf)); - if (x->x_trackv) - freebytes(x->x_trackv, x->x_ntrack * sizeof(*x->x_trackv)); - clock_free(x->x_clock); -} - void sigmund_tilde_setup(void) { sigmund_class = class_new(gensym("sigmund~"), (t_newmethod)sigmund_new, @@ -1311,6 +1358,214 @@ void sigmund_tilde_setup(void) gensym("print"), 0); class_addmethod(sigmund_class, (t_method)sigmund_printnext, gensym("printnext"), A_FLOAT, 0); - post("sigmund version 0.03"); + post("sigmund~ version 0.04"); +} + +#endif /* PD */ + +/************************ Max/MSP glue **********************************/ + +/* -------------------------- MSP glue ------------------------- */ +#ifdef MSP +static void *sigmund_class; + +static void *sigmund_new(t_symbol *s, long ac, t_atom *av) +{ + t_sigmund *x; + t_varout *g; + int i, j; + if (!(x = (t_sigmund *)object_alloc(sigmund_class))) + return (0); + sigmund_preinit(x); + attr_args_process(x, ac, av); + dsp_setup((t_pxobject *)x, 1); + object_obex_store(x, gensym("dumpout"), outlet_new(x, NULL)); + + for (i = 0; i < ac; i++) + if (av[i].a_type == A_SYM) + { + char *s = av[i].a_w.w_sym->s_name; + if (!strcmp(s, "pitch")) + { + int n2 = x->x_nvarout+1; + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); + x->x_varoutv[x->x_nvarout].v_what = OUT_PITCH; + x->x_nvarout = n2; + x->x_dopitch = 1; + } + else if (!strcmp(s, "env")) + { + int n2 = x->x_nvarout+1; + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); + x->x_varoutv[x->x_nvarout].v_what = OUT_ENV; + x->x_nvarout = n2; + } + else if (!strcmp(s, "note") || !strcmp(s, "notes")) + { + int n2 = x->x_nvarout+1; + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); + x->x_varoutv[x->x_nvarout].v_what = OUT_NOTE; + x->x_nvarout = n2; + x->x_dopitch = x->x_donote = 1; + } + else if (!strcmp(s, "peaks")) + { + int n2 = x->x_nvarout+1; + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); + x->x_varoutv[x->x_nvarout].v_what = OUT_PEAKS; + x->x_nvarout = n2; + } + else if (!strcmp(s, "tracks")) + { + int n2 = x->x_nvarout+1; + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + x->x_nvarout*sizeof(t_varout), n2*sizeof(t_varout)); + x->x_varoutv[x->x_nvarout].v_what = OUT_TRACKS; + x->x_nvarout = n2; + x->x_dotracks = 1; + } + else if (s[0] != '@') + post("sigmund: ignoring unknown argument '%s'" ,s); + } + if (!x->x_nvarout) + { + x->x_varoutv = (t_varout *)t_resizebytes(x->x_varoutv, + 0, 2*sizeof(t_varout)); + x->x_varoutv[0].v_what = OUT_PITCH; + x->x_varoutv[1].v_what = OUT_ENV; + x->x_nvarout = 2; + x->x_dopitch = 1; + } + for (j = 0, g = x->x_varoutv + x->x_nvarout-1; j < x->x_nvarout; j++, g--) + g->v_outlet = ((g->v_what == OUT_PITCH || g->v_what == OUT_ENV || + g->v_what == OUT_NOTE) ? + floatout((t_object *)x) : listout((t_object *)x)); + if (x->x_dotracks) + { + x->x_ntrack = x->x_npeak; + x->x_trackv = (t_peak *)getbytes(x->x_ntrack * sizeof(*x->x_trackv)); + } + x->x_clock = clock_new(x, (method)sigmund_tick); + x->x_infill = 0; + x->x_countdown = 0; + sigmund_npts(x, x->x_npts); + notefinder_init(&x->x_notefinder); + return (x); +} + +/* Attribute setters. */ +void sigmund_npts_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_npts(x, atom_getfloat(av)); +} + +void sigmund_hop_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_hop(x, atom_getfloat(av)); +} + +void sigmund_npeak_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_npeak(x, atom_getfloat(av)); +} + +void sigmund_maxfreq_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_maxfreq(x, atom_getfloat(av)); +} + +void sigmund_vibrato_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_vibrato(x, atom_getfloat(av)); } +void sigmund_stabletime_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_stabletime(x, atom_getfloat(av)); +} + +void sigmund_growth_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_growth(x, atom_getfloat(av)); +} + +void sigmund_minpower_set(t_sigmund *x, void *attr, long ac, t_atom *av) +{ + if (ac && av) + sigmund_minpower(x, atom_getfloat(av)); +} + +/* end attr setters */ + +void sigmund_assist(t_sigmund *x, void *b, long m, long a, char *s) +{ +} + +int main() +{ + t_class *c; + long attrflags = 0; + t_symbol *sym_long = gensym("long"), *sym_float32 = gensym("float32"); + + c = class_new("sigmund~", (method)sigmund_new, + (method)sigmund_free, sizeof(t_sigmund), (method)0L, A_GIMME, 0); + + class_obexoffset_set(c, calcoffset(t_sigmund, obex)); + + class_addattr(c, attr_offset_new("npts", sym_long, attrflags, + (method)0L, (method)sigmund_npts_set, + calcoffset(t_sigmund, x_npts))); + class_addattr(c ,attr_offset_new("hop", sym_long, attrflags, + (method)0L, (method)sigmund_hop_set, + calcoffset(t_sigmund, x_hop))); + class_addattr(c ,attr_offset_new("maxfreq", sym_float32, attrflags, + (method)0L, (method)sigmund_maxfreq_set, + calcoffset(t_sigmund, x_maxfreq))); + class_addattr(c ,attr_offset_new("npeak", sym_long, attrflags, + (method)0L, (method)sigmund_npeak_set, + calcoffset(t_sigmund, x_npeak))); + class_addattr(c ,attr_offset_new("vibrato", sym_float32, attrflags, + (method)0L, (method)sigmund_vibrato_set, + calcoffset(t_sigmund, x_vibrato))); + class_addattr(c ,attr_offset_new("stabletime", sym_float32, attrflags, + (method)0L, (method)sigmund_stabletime_set, + calcoffset(t_sigmund, x_stabletime))); + class_addattr(c ,attr_offset_new("growth", sym_float32, attrflags, + (method)0L, (method)sigmund_growth_set, + calcoffset(t_sigmund, x_growth))); + class_addattr(c ,attr_offset_new("minpower", sym_float32, attrflags, + (method)0L, (method)sigmund_minpower_set, + calcoffset(t_sigmund, x_minpower))); + + class_addmethod(c, (method)sigmund_dsp, "dsp", A_CANT, 0); + class_addmethod(c, (method)sigmund_print, "print", 0); + class_addmethod(c, (method)sigmund_print, "printnext", A_DEFFLOAT, 0); + class_addmethod(c, (method)sigmund_assist, "assist", A_CANT, 0); + + class_addmethod(c, (method)object_obex_dumpout, "dumpout", A_CANT, 0); + class_addmethod(c, (method)object_obex_quickref, "quickref", A_CANT, 0); + + class_dspinit(c); + + class_register(CLASS_BOX, c); + sigmund_class = c; + + post("sigmund~ v0.04"); + return (0); +} + + +#endif /* MSP */ + + -- cgit v1.2.1