-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathgauss.c
92 lines (75 loc) · 2.16 KB
/
gauss.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
// guass.c
// an external for Pure Data
// returns a number using gaussian distribution based on mean and variance
// based on python's random.gauss() function
// Jeremy Muller ©2015
#include "m_pd.h"
#include <stdlib.h>
#include <math.h>
// object struct
typedef struct _gauss {
t_object x_obj; // needed and must be listed first in struct
t_float mean;
t_float stddev;
} t_gauss;
// prototypes
static t_class *gauss_class;
void bangGenerateNum(t_gauss *x);
double rand_gauss(double mean, double stddev);
// constructor
void *gauss_new(t_floatarg mean, t_floatarg stddev)
{
t_gauss *x = (t_gauss *)pd_new(gauss_class);
x->mean = mean;
x->stddev = stddev;
floatinlet_new(&x->x_obj, &x->mean);
floatinlet_new(&x->x_obj, &x->stddev);
outlet_new(&x->x_obj, &s_float);
return (void *)x;
}
// setup routine
void gauss_setup(void)
{
post("gauss, outputs a number based on gaussian distribution, version 0.1");
post("by Jeremy Muller, 2015\n");
gauss_class = class_new(gensym("gauss"),
(t_newmethod)gauss_new, 0,
sizeof(t_gauss),
CLASS_DEFAULT,
A_DEFFLOAT,
A_DEFFLOAT, 0);
class_addbang(gauss_class, bangGenerateNum);
class_sethelpsymbol(gauss_class, gensym("help-gauss"));
}
// handles bang from inlet
void bangGenerateNum(t_gauss *x)
{
t_float num = rand_gauss(x->mean, x->stddev);
outlet_float(x->x_obj.ob_outlet, num);
}
// function that computes gaussian distribution
double rand_gauss(double mean, double stddev)
{
// this math taken from:
// http://en.literateprograms.org/Box-Muller_transform_(C)#chunk%20def:complete%20Box-Muller%20function
static double n2 = 0.0;
static int n2_cached = 0;
if (!n2_cached) {
double x, y, r;
do
{
x = 2.0 * rand() / RAND_MAX - 1;
y = 2.0 * rand() / RAND_MAX - 1;
r = x*x + y*y;
} while (r == 0.0 || r > 1.0);
double d = sqrt(-2.0 * log(r)/r);
double n1 = x*d;
n2 = y*d;
double result = n1 * stddev + mean;
n2_cached = 1;
return result;
} else {
n2_cached = 0;
return n2 * stddev + mean;
}
}