/* minmax.c A Csound opcode library implementing ugens for for finding minimum and maximum values. Anthony Kozar April 5, 2005 */ #include "csdl.h" #include typedef struct { OPDS h; MYFLT *accum, *ain; } MINMAXACCUM; typedef struct { OPDS h; MYFLT *xout, *xin1, *xin2toN[VARGMAX]; } MINMAX; /* Which implementation is faster ?? */ void MaxAccumulate(MINMAXACCUM* data) { int nsmps = ksmps; MYFLT* out = data->accum; MYFLT* in = data->ain; do { if (*in > *out) *out = *in; ++out; ++in; } while (--nsmps); return; } void MinAccumulate(MINMAXACCUM* data) { MYFLT curmax, cur; int nsmps = ksmps; MYFLT* out = data->accum; MYFLT* in = data->ain; do { curmax = *out; cur = *in++; if (cur < curmax) *out = cur; ++out; } while (--nsmps); return; } /* Absolute value versions of the above */ void MaxAbsAccumulate(MINMAXACCUM* data) { int nsmps = ksmps; MYFLT* out = data->accum; MYFLT* in = data->ain; MYFLT inabs; do { inabs = (MYFLT)fabs(*in); if (inabs > *out) *out = inabs; ++out; ++in; } while (--nsmps); return; } void MinAbsAccumulate(MINMAXACCUM* data) { int nsmps = ksmps; MYFLT* out = data->accum; MYFLT* in = data->ain; MYFLT inabs; do { inabs = (MYFLT)fabs(*in); if (inabs < *out) *out = inabs; ++out; ++in; } while (--nsmps); return; } /* Multiple input min and max opcodes */ void Max_arate(MINMAX* data) { int i, j; int nsmps = ksmps; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT max, temp; j = 0; do { max = *in1++; for (i= 0; i < nargs; ++i) { temp = in2[i][j]; if (temp > max) max = temp; } *out++ = max; ++j; } while (--nsmps); return; } void Min_arate(MINMAX* data) { int i, j; int nsmps = ksmps; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT min, temp; j = 0; do { min = *in1++; for (i= 0; i < nargs; ++i) { temp = in2[i][j]; if (temp < min) min = temp; } *out++ = min; ++j; } while (--nsmps); return; } /* Absolute value versions of multiple input opcodes */ void MaxAbs_arate(MINMAX* data) { int i, j; int nsmps = ksmps; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT max, temp; j = 0; do { max = (MYFLT)fabs(*in1++); for (i= 0; i < nargs; ++i) { temp = (MYFLT)fabs(in2[i][j]); if (temp > max) max = temp; } *out++ = max; ++j; } while (--nsmps); return; } void MinAbs_arate(MINMAX* data) { int i, j; int nsmps = ksmps; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT min, temp; j = 0; do { min = (MYFLT)fabs(*in1++); for (i= 0; i < nargs; ++i) { temp = (MYFLT)fabs(in2[i][j]); if (temp < min) min = temp; } *out++ = min; ++j; } while (--nsmps); return; } /* k-rate multiple input min and max opcodes */ void Max_krate(MINMAX* data) { int i; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT max, temp; max = *in1; for (i= 0; i < nargs; ++i) { temp = in2[i][0]; if (temp > max) max = temp; } *out = max; return; } void Min_krate(MINMAX* data) { int i; int nsmps = ksmps; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT min, temp; min = *in1; for (i= 0; i < nargs; ++i) { temp = in2[i][0]; if (temp < min) min = temp; } *out = min; return; } /* Absolute value versions of k-rate opcodes */ void MaxAbs_krate(MINMAX* data) { int i; int nsmps = ksmps; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT max, temp; max = (MYFLT)fabs(*in1); for (i= 0; i < nargs; ++i) { temp = (MYFLT)fabs(in2[i][0]); if (temp > max) max = temp; } *out = max; return; } void MinAbs_krate(MINMAX* data) { int i; int nsmps = ksmps; int nargs = ((int) data->INOCOUNT) - 1; MYFLT* out = data->xout; MYFLT* in1 = data->xin1; MYFLT** in2 = data->xin2toN; MYFLT min, temp; min = (MYFLT)fabs(*in1); for (i= 0; i < nargs; ++i) { temp = (MYFLT)fabs(in2[i][0]); if (temp < min) min = temp; } *out = min; return; } /* code for linking dynamic libraries under Csound 4 */ #define S sizeof static OENTRY localops[] = { { "maxaccum", S(MINMAXACCUM), 4, "", "aa", NULL, NULL, (SUBR)MaxAccumulate }, { "minaccum", S(MINMAXACCUM), 4, "", "aa", NULL, NULL, (SUBR)MinAccumulate }, { "maxabsaccum", S(MINMAXACCUM), 4, "", "aa", NULL, NULL, (SUBR)MaxAbsAccumulate }, { "minabsaccum", S(MINMAXACCUM), 4, "", "aa", NULL, NULL, (SUBR)MinAbsAccumulate }, { "max", 0xffff }, { "min", 0xffff }, { "maxabs", 0xffff }, { "minabs", 0xffff }, { "max_a", S(MINMAX), 4, "a", "ay", NULL, NULL, (SUBR)Max_arate }, { "min_a", S(MINMAX), 4, "a", "ay", NULL, NULL, (SUBR)Min_arate }, { "maxabs_a", S(MINMAX), 4, "a", "ay", NULL, NULL, (SUBR)MaxAbs_arate }, { "minabs_a", S(MINMAX), 4, "a", "ay", NULL, NULL, (SUBR)MinAbs_arate }, { "max_k", S(MINMAX), 2, "k", "kz", NULL, (SUBR)Max_krate, NULL }, { "min_k", S(MINMAX), 2, "k", "kz", NULL, (SUBR)Min_krate, NULL }, { "maxabs_k", S(MINMAX), 2, "k", "kz", NULL, (SUBR)MaxAbs_krate, NULL }, { "minabs_k", S(MINMAX), 2, "k", "kz", NULL, (SUBR)MinAbs_krate, NULL } }; long opcode_size(void) { return sizeof(localops); } OENTRY *opcode_init(GLOBALS *xx) { pcglob = xx; return localops; }