1 //spencer jackson
2 
3 //gpl v2 and all that
4 
5 //a simple and kinda boring lfo implementation
6 #include<stdlib.h>
7 #include<time.h>
8 #include"lfo.h"
9 
10 #define PI 3.1415926535897932384626433832795
11 
Lfo(double sample_rate,uint32_t fragsize)12 Lfo::Lfo(double sample_rate, uint32_t fragsize)
13 {
14     //init public vars that callers will set
15     shape = 0;
16     gain = 0;
17     freq = 0;
18 
19     //init states
20     srand ((unsigned int) time (NULL));
21     phase = 2*PI*rand() / (float)RAND_MAX - PI;
22     y0 = y1 = x1 = 0;
23 
24     //const vars
25     phastep = 2*PI*fragsize/sample_rate;//w = 2*pi*f; sin(wt) = sin(2*pi*f*t) = sin(2*pi*f*n/fs)
26     ro = 2*sample_rate/fragsize;
27 }
28 
~Lfo()29 Lfo::~Lfo()
30 {
31 }
32 
33 float
out(float _shape)34 Lfo::out(float _shape)
35 {
36     shape = _shape;
37     return out();
38 }
39 
40 float
out()41 Lfo::out()
42 {
43     //step
44     phase += phastep*freq;
45     if(phase > PI)
46     {
47         phase -= 2*PI;
48     }
49 
50     // sin approx based on an algorithm by Nicolas Capens
51     // domain [-pi,pi]
52     double y = 1.27323954474*phase - 0.40528473456*phase*(phase>0?phase:-phase);
53     float s =  0.225*(y*(y>0?y:-y) - y) + y;
54 
55     //pink noise method by paul kellet
56     /*
57     float r = 2.0*rand() / (float)RAND_MAX -1.0;
58     y0 = 0.99765 * y0 + r * 0.0990460;
59     y1 = 0.96300 * y1 + r * 0.2965164;
60     y2 = 0.57000 * y2 + r * 1.0526913;
61     r = y0 + y1 + y2 + r * 0.1848;
62     */
63     //this is a LPF with cutoff at freq
64     float r = 3*2.0*rand() / (float)RAND_MAX -1.0;//extra 3 factor because lpf seems to need a bit more gain
65     float a = 2*PI*freq;
66     float b = 1/(ro+a);
67     y0 = a*b*(x1 + r - y1) + ro*b*y1;
68     y1 = y0;
69     x1 = r;
70     //blend shapes
71     return gain*((s-y0)*shape + y0);
72 
73 }
74 
75 void
reset()76 Lfo::reset()
77 {
78     phase = 0;
79     y0 = y1 =  x1 = 0;
80 }
81