/* Math functions for Csound coded by Paris Smaragdis 1994 */ /* Berklee College of Music Csound development team */ #include "cs.h" #include "cmath.h" #include #include /* for random seeding from the time - mkc July 1997 */ #ifndef RAND_MAX #define RAND_MAX (32767) #endif void ipow(POW *p) /* Power for i-rate */ { *p->sr = (float)pow(*p->in, *p->pow); /* sophisticated code! */ } void apow(POW *p) /* Power routine for a-rate */ { long n = ksmps; float *in = p->in, *out = p->sr; do { *out++ = (float)pow(*in++, *p->pow) / *p->norm; } while (--n); } void kpow(POW *p) /* Power routine for k-rate */ { *p->sr = (float)pow(*p->in, *p->pow) / *p->norm; } void seedrand(PRAND *p) { if ((unsigned int)*p->out == 0) { printf("Seeding from current time\n"); srand((unsigned int)time(NULL)); } else { printf("Seeding with %.3f\n", *p->out); srand((unsigned int)*p->out); } } void auniform(PRAND *p) /* Uniform distribution */ { long n = ksmps; float *out = p->out; float arg1 = *p->arg1; do *out++ = unifrand(arg1); while( --n); } void ikuniform(PRAND *p) { float *out = p->out; *out = unifrand(*p->arg1); } void alinear(PRAND *p) /* Linear random functions */ { long n = ksmps; float *out = p->out; do { *out++ = linrand(*p->arg1); } while (--n); } void iklinear(PRAND *p) { float *out = p->out; *out++ = linrand(*p->arg1); } void atrian(PRAND *p) /* Triangle random functions */ { long n = ksmps; float *out = p->out; do { *out++ = trirand(*p->arg1); } while (--n); } void iktrian(PRAND *p) { float *out = p->out; *out++ = trirand(*p->arg1); } void aexp(PRAND *p) /* Exponential random functions */ { long n = ksmps; float *out = p->out; do { *out++ = exprand(*p->arg1); } while (--n); } void ikexp(PRAND *p) { float *out = p->out; *out++ = exprand(*p->arg1); } void abiexp(PRAND *p) /* Bilateral exponential rand. functions */ { long n = ksmps; float *out = p->out; do { *out++ = biexprand(*p->arg1); } while (--n); } void ikbiexp(PRAND *p) { float *out = p->out; *out++ = biexprand(*p->arg1); } void agaus(PRAND *p) /* Gaussian random functions */ { long n = ksmps; float *out = p->out; do { *out++ = gaussrand(*p->arg1); } while (--n); } void ikgaus(PRAND *p) { float *out = p->out; *out++ = gaussrand(*p->arg1); } void acauchy(PRAND *p) /* Cauchy random functions */ { long n = ksmps; float *out = p->out; do { *out++ = cauchrand(*p->arg1); } while (--n); } void ikcauchy(PRAND *p) { float *out = p->out; *out++ = cauchrand(*p->arg1); } void apcauchy(PRAND *p) /* Positive Cauchy random functions */ { long n = ksmps; float *out = p->out; do { *out++ = pcauchrand(*p->arg1); } while (--n); } void ikpcauchy(PRAND *p) { float *out = p->out; *out++ = pcauchrand(*p->arg1); } void abeta(PRAND *p) /* Beta random functions */ { long n = ksmps; float *out = p->out; do { *out++ = betarand(*p->arg1, *p->arg2, *p->arg3); } while (--n); } void ikbeta(PRAND *p) { float *out = p->out; *out++ = betarand(*p->arg1, *p->arg2, *p->arg3); } void aweib(PRAND *p) /* Weibull randon functions */ { long n = ksmps; float *out = p->out; do { *out++ = weibrand(*p->arg1, *p->arg2); } while (--n); } void ikweib(PRAND *p) { float *out = p->out; *out++ = weibrand(*p->arg1, *p->arg2); } void apoiss(PRAND *p) /* Poisson random funcions */ { long n = ksmps; float *out = p->out; do { *out++ = poissrand(*p->arg1); } while (--n); } void ikpoiss(PRAND *p) { float *out = p->out; *out++ = poissrand(*p->arg1); } /* * * * * * RANDOM NUMBER GENERATORS * * * * * */ #define unirand() (float)((double)rand()/(double)RAND_MAX) float unifrand(float range) { return range*unirand(); } float linrand(float range) /* linear distribution routine */ { float r1, r2; r1 = unirand(); r2 = unirand(); if (r1 > r2) r1 = r2; return (r1 * range); } float trirand(float range) /* triangle distribution routine */ { float r1, r2; r1 = unirand(); r2 = unirand(); return (((r1 + r2) - 1.0f) * range); } float exprand(float l) /* exponential distribution routine */ { float r1; if (l < 0.0f) return (0.0f); do { r1 = unirand(); } while (r1 == 0.0f); return (-(float)log(r1 *l)); } float biexprand(float l) /* bilateral exponential distribution routine */ { float r1; if (l < 0.0f) return (0.0f); do { r1 = 2.0f * unirand(); } while (r1 == 0.0f || r1 == 2.0f); if (r1 > 1.0f) { r1 = 2.0f - r1; return (-(float)log(r1 * l)); } return ((float)log(r1 * l)); } float gaussrand(float s) /* gaussian distribution routine */ { float r1 = 0.0f; int n = 12; s /= 3.83f; do { r1 += unirand(); } while (--n); return (s * (r1 - 6.0f)); } float cauchrand(float a) /* cauchy distribution routine */ { float r1; a /= 318.3f; do { do { r1 = unirand(); } while (r1 == 0.5f); r1 = a * (float)tan(pi*(double)r1); } while (r1>1.0f || r1<-1.0f); /* Limit range artificially */ return r1; } float pcauchrand(float a) /* positive cauchy distribution routine */ { float r1; a /= 318.3f; do { do { r1 = unirand(); } while (r1 == 1); r1 = a * (float)tan( pi * 0.5 * r1); } while (r1>1.0f); return r1; } float betarand(float range, float a, float b) /* beta distribution routine */ { float r1, r2; if (a < 0.0f || b < 0.0f ) return (0.0f); do { do { r1 = unirand(); } while (r1 == 0.0f); do { r2 = unirand(); } while (r2 == 0.0f); r1 = (float)pow(r1, 1.0 / (double)a); r2 = (float)pow(r2, 1.0 / (double)b); } while ((r1 + r2) > 1.0f); return ((r1 / (r1 +r2)) * range); } float weibrand(float s, float t) /* weibull distribution routine */ { float r1, r2; if (t < 0.0f ) return (0.0f); do { r1 = unirand(); } while (r1 == 0.0f || r1 == 1.0f); r2 = 1.0f / (1.0f - r1); return (s * (float)pow (log((double)r2), (1.0 /(double)t))); } float poissrand(float l) /* poisson distribution routine */ { float r1, r2, r3; if (l < 0.0f ) return (0.0f); r1 = unirand(); r2 = (float)exp(-l); r3 = 0.0f; while (r1 >= r2) { r3++; r1 *= unirand(); } return (r3); }