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)12Lfo::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()29Lfo::~Lfo() 30 { 31 } 32 33 float out(float _shape)34Lfo::out(float _shape) 35 { 36 shape = _shape; 37 return out(); 38 } 39 40 float out()41Lfo::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()76Lfo::reset() 77 { 78 phase = 0; 79 y0 = y1 = x1 = 0; 80 } 81