// -------------------------------------------------------------- // -------------------------------------------------------------- #include #include #include #include #include "synth_defs.h" #include "noise.h" // -------------------------------------------------------------- // internal funcs // -------------------------------------------------------------- #define PM_IA 16807 #define PM_IM 2147483647 #define PM_AM (1.0/PM_IM) #define PM_IQ 127773 #define PM_IR 2836 #define PM_MASK 123459876 // 'Minimal' random number generator of Park and Miller. Returns a uniform random deviate // between 0.0 and 1.0. Set or resetidumto any integer value (except the unlikely value MASK) // to initialize the sequence; idummust not be altered between calls for successive deviates in // a sequence. double ran0(long *idum) { long k; double ans; *idum ^= PM_MASK; // XORing with MASKallows use of zero and other k=(*idum)/PM_IQ; // simple bit patterns for idum. *idum=PM_IA*(*idum-k*PM_IQ)-PM_IR *k; // Compute idum=(IA*idum) % IM without over- // flows by Schrage’s method. if (*idum < 0) *idum += PM_IM; ans=PM_AM*(*idum); // Convert idumto a floating result. *idum ^= PM_MASK; // Unmask before return. return ans; } // -------------------------------------------------------------- // Exported functions // -------------------------------------------------------------- void Noise_Init(noise_gen_t *pObj, UINT32 seed) { pObj->state = (long)(seed & NOISE_LFSR_MAX); } void Noise_Free(noise_gen_t *pObj) { } synth_float_t Noise_Uniform(noise_gen_t *pObj, synth_float_t var, synth_float_t mu) { /* if (pObj->lfsr & 0x800000) pObj->lfsr = ((pObj->lfsr << 1) | 1) ^ NOISE_LFSR_POLY; else pObj->lfsr = (pObj->lfsr << 1); pObj->lfsr &= NOISE_LFSR_MAX; */ /* taps: 32 31 29 1; characteristic polynomial: x^32 + x^31 + x^29 + x + 1 */ // pObj->lfsr = (pObj->lfsr >> 1) ^ (-(pObj->lfsr & 1) & NOISE_LFSR_POLY); // return var * ((synth_float_t)rand()/(RAND_MAX+1) + mu -0.5); return var*(ran0(&pObj->state) + mu -0.5); } synth_float_t Noise_Gaussian(noise_gen_t *pObj, synth_float_t std, synth_float_t mu) { synth_float_t U1, U2, V1, V2, S, Y; do { U1 = Noise_Uniform(pObj, 1, 0.5); // U1=[0,1] U2 = Noise_Uniform(pObj, 1, 0.5); // U2=[0,1] V1 = 2 * U1 - 1; // V1=[-1,1] V2 = 2 * U2 - 1; // V2=[-1,1] S = V1 * V1 + V2 * V2; } while (S >= 1); // X = sqrt(-2 * log(S) / S) * V1; Y = sqrt(-2 * log(S) / S) * V2; Y = mu + std*Y; return Y; }