1 /*
2  * Randi
3  *
4  * This code has been extracted from the Csound opcode "randi".
5  * It has been modified to work as a Soundpipe module.
6  *
7  * Original Author(s): Barry Vercoe, John ffitch
8  * Year: 1991
9  * Location: OOps/ugens4.c
10  *
11  * Randi needs the ftbl Soundpipe module in order to work.
12  *
13  */
14 
15 #include <stdlib.h>
16 #include <math.h>
17 #include "soundpipe.h"
18 
19 #define sp_oneUp31Bit      (4.656612875245796924105750827168e-10)
20 
21 #define sp_randGab   ((SPFLOAT)     \
22         (((p->holdrand = p->holdrand * 214013 + 2531011) >> 1)  \
23          & 0x7fffffff) * sp_oneUp31Bit)
24 
25 
sp_randi_create(sp_randi ** p)26 int sp_randi_create(sp_randi **p)
27 {
28     *p = malloc(sizeof(sp_randi));
29     return SP_OK;
30 }
31 
sp_randi_destroy(sp_randi ** p)32 int sp_randi_destroy(sp_randi **p)
33 {
34     free(*p);
35     return SP_OK;
36 }
37 
sp_randi_init(sp_data * sp,sp_randi * p)38 int sp_randi_init(sp_data *sp, sp_randi *p)
39 {
40     p->sicvt = 1.0 * SP_FT_MAXLEN / sp->sr;
41     p->phs = 0;
42     p->min = 0;
43     p->max = 1;
44     p->cps = 3;
45     p->mode = 3;
46     p->holdrand = sp_rand(sp);
47     p->fstval = 0;
48 
49     int mode = (int)(p->mode);
50     switch (mode) {
51     case 1: /* immediate interpolation between kmin and 1st random number */
52         p->num1 = 0.0;
53         p->num2 = sp_randGab;
54         p->dfdmax = (p->num2 - p->num1) / SP_FT_MAXLEN * 1.0;
55         break;
56     case 2: /* immediate interpolation between ifirstval and 1st random number */
57         p->num1 = (p->max - p->min) ?
58           (p->fstval - p->min) / (p->max - p->min) : 0.0;
59         p->num2 = sp_randGab;
60         p->dfdmax = (p->num2 - p->num1) / SP_FT_MAXLEN * 1.0;
61         break;
62     case 3: /* immediate interpolation between 1st and 2nd random number */
63         p->num1 = sp_randGab;
64         p->num2 = sp_randGab;
65         p->dfdmax = (p->num2 - p->num1) / SP_FT_MAXLEN * 1.0;
66         break;
67     default: /* old behaviour as developped by Gabriel */
68         p->num1 = p->num2 = 0.0;
69         p->dfdmax = 0.0;
70     }
71     return SP_OK;
72 }
73 
sp_randi_compute(sp_data * sp,sp_randi * p,SPFLOAT * in,SPFLOAT * out)74 int sp_randi_compute(sp_data *sp, sp_randi *p, SPFLOAT *in, SPFLOAT *out)
75 {
76     int32_t phs = p->phs, inc;
77     SPFLOAT cpsp;
78     SPFLOAT amp, min;
79 
80     cpsp = p->cps;
81     min = p->min;
82     amp =  (p->max - min);
83     inc = (int32_t)(cpsp * p->sicvt);
84 
85     *out = (p->num1 + (SPFLOAT)phs * p->dfdmax) * amp + min;
86     phs += inc;
87     if (phs >= SP_FT_MAXLEN) {
88         phs &= SP_FT_PHMASK;
89         p->num1 = p->num2;
90         p->num2 = sp_randGab;
91         p->dfdmax = 1.0 * (p->num2 - p->num1) / SP_FT_MAXLEN;
92     }
93     p->phs = phs;
94 
95     return SP_OK;
96 }
97