-
Notifications
You must be signed in to change notification settings - Fork 3
/
Copy pathlfo.cpp
176 lines (151 loc) · 4.42 KB
/
lfo.cpp
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
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
//----------------------------------//
// LFO class for Arduino
// by mo-thunderz
// version 1.1
// last update: 22.05.2021
//----------------------------------//
#include "Arduino.h"
#include "lfo.h"
lfo::lfo(int dacSize)
{
_dacSize = dacSize;
_ampl = dacSize - 1;
_ampl_offset = 0;
}
void lfo::setWaveForm(int l_waveForm)
{
if(l_waveForm < 0)
l_waveForm = 0;
if(l_waveForm > 4)
l_waveForm = 4;
_waveForm = l_waveForm;
}
void lfo::setAmpl(int l_ampl)
{
if(l_ampl < 0)
l_ampl = 0;
if(l_ampl >= _dacSize)
l_ampl = _dacSize - 1;
_ampl = l_ampl;
}
void lfo::setAmplOffset(int l_ampl_offset)
{
if(l_ampl_offset < 0)
l_ampl_offset = 0;
if(l_ampl_offset >= _dacSize)
l_ampl_offset = _dacSize - 1;
_ampl_offset = l_ampl_offset;
}
void lfo::setMode(bool l_mode)
{
_mode = l_mode;
}
void lfo::setMode0Freq(float l_mode0_freq)
{
if(l_mode0_freq < 0)
l_mode0_freq = 0;
_mode0_freq = l_mode0_freq;
}
void lfo::setMode0Freq(float l_mode0_freq, unsigned long l_t)
{
if(l_mode0_freq < 0)
l_mode0_freq = 0;
// synchronize the phase of the old freq with the new freq
float _output_phase_old = (double)(l_t - _t0) * _mode0_freq / 1000000 + _mode0_phase_offset;
float _output_phase_new = (double)(l_t - _t0) * l_mode0_freq / 1000000;
_output_phase_old = _output_phase_old - floor(_output_phase_old);
_output_phase_new = _output_phase_new - floor(_output_phase_new);
_mode0_phase_offset = _output_phase_old - _output_phase_new;
_mode0_freq = l_mode0_freq;
}
void lfo::setMode1Bpm(float l_mode1_bpm)
{
if(l_mode1_bpm < 0)
l_mode1_bpm = 0;
_mode1_bpm = l_mode1_bpm;
}
void lfo::setMode1Rate(float l_mode1_rate)
{
if(l_mode1_rate < 0)
l_mode1_rate = 0;
_mode1_rate = l_mode1_rate;
}
void lfo::setMode1Phase(float l_mode1_phase_offset)
{
_mode1_phase_offset = l_mode1_phase_offset;
}
void lfo::sync(unsigned long l_t)
{
_t0 = l_t;
_mode0_phase_offset = 0;
}
int lfo::getWaveForm()
{
return _waveForm;
}
int lfo::getAmpl()
{
return _ampl;
}
int lfo::getAmplOffset()
{
return _ampl_offset;
}
bool lfo::getMode()
{
return _mode;
}
float lfo::getMode0Freq()
{
return _mode0_freq;
}
float lfo::getMode1Rate()
{
return _mode1_rate;
}
float lfo::getPhase()
{
return _output_phase;
}
int lfo::getWave(unsigned long l_t)
{
int result = 0;
int l_ampl = _ampl;
if(_mode == false) // LFO free running
_output_phase = (float)((unsigned long)(l_t - _t0)) * _mode0_freq / 1000000 + _mode0_phase_offset;
else // LFO synced
_output_phase = (float)((unsigned long)(l_t - _t0)) * (float)_mode1_rate * _mode1_bpm / 60000000 + _mode1_phase_offset;
// Compute correct _ampl_offsetoffset (wave not to exceed 0 to dacSize)
int l_ampl_offset = 0;
int l_ampl_half = (int) l_ampl / 2;
if(_ampl_offset < _dacSize / 2)
l_ampl_offset = ( _ampl_offset > l_ampl_half ) ? _ampl_offset : l_ampl_half; // l_ampl_offset must be large enough not to go below 0
else
l_ampl_offset = ( _dacSize - _ampl_offset > l_ampl_half ) ? _ampl_offset : _dacSize - l_ampl_half - 1;
switch(_waveForm)
{
case 0: // Off
result = _ampl_offset;
return result;
break;
case 1: // Saw
return result = l_ampl * (1 - fmod(_output_phase, 1)) + l_ampl_offset - l_ampl_half;
break;
case 2: // Triangle
if(((int)(2 * _output_phase))%2) // up flank
return result = 2 * l_ampl * fmod(_output_phase, 1) + l_ampl_offset - 3 * l_ampl_half;
else // down flank
return result = l_ampl * (1.5 - 2 * fmod(_output_phase, 1)) + l_ampl_offset - l_ampl;
break;
case 3: // Sin
return result = (int) l_ampl_half * cos(2 * _PI * _output_phase) + l_ampl_offset;
break;
case 4: // Square
if(((int)(2 * _output_phase))%2)
return result = l_ampl_offset - l_ampl_half;
else
return result = l_ampl_offset + l_ampl_half;
break;
}
return result;
}