-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathchorus.h
More file actions
142 lines (113 loc) · 4.04 KB
/
chorus.h
File metadata and controls
142 lines (113 loc) · 4.04 KB
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
/*
==============================================================================
This file is part of Tal-NoiseMaker by Patrick Kunz.
Copyright(c) 2005-2010 Patrick Kunz, TAL
Togu Audio Line, Inc.
http://kunz.corrupt.ch
This file may be licensed under the terms of of the
GNU General Public License Version 2 (the ``GPL'').
Software distributed under the License is distributed
on an ``AS IS'' basis, WITHOUT WARRANTY OF ANY KIND, either
express or implied. See the GPL for the specific language
governing rights and limitations.
You should have received a copy of the GPL along with this
program. If not, go to http://www.gnu.org/licenses/gpl.html
or write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
==============================================================================
*/
#if !defined(__Chorus_h)
#define __Chorus_h
#include "lp.h"
#include "math.h"
class Chorus {
public:
float *delayLineStart;
float *delayLineEnd;
float *writePtr;
int delayLineLength;
float rate;
float delayLineOutput;
float sampleRate;
float delayTime;
// Runtime variables
float offset, diff, frac, *ptr, *ptr2;
int readPos;
OnePoleLP *lp;
float z1;
float mult, sign;
// lfo
float lfoPhase, lfoStepSize, lfoSign;
Chorus(float sampleRate, float phase, float rate, float delayTime) {
this->rate = rate;
this->sampleRate = sampleRate;
this->delayTime = delayTime;
z1 = 0.0f;
sign = 0;
lfoPhase = phase * 2.0f - 1.0f;
lfoStepSize = (4.0f * rate / sampleRate);
lfoSign = 1.0f;
// Compute required buffer size for desired delay and allocate it
// Add extra point to aid in interpolation later
delayLineLength = ((int)floorf(delayTime * sampleRate * 0.001f) * 2);
delayLineStart = new float[delayLineLength];
// Set up pointers for delay line
delayLineEnd = delayLineStart + delayLineLength;
writePtr = delayLineStart;
// Zero out the buffer (silence)
do {
*writePtr = 0.0f;
}
while (++writePtr < delayLineEnd);
// Set read pointer to end of delayline. Setting it to the end
// ensures the interpolation below works correctly to produce
// the first non-zero sample.
writePtr = delayLineStart + delayLineLength -1;
delayLineOutput = 0.0f;
lp = new OnePoleLP();
}
~Chorus() {
delete[] delayLineStart;
delete lp;
}
void setLfoRate(float rate) {
lfoStepSize = (4.0f * rate / sampleRate);
}
float process(float *sample) {
// Get delay time
offset = (nextLFO() * 0.3f + 0.4f) * delayTime * sampleRate * 0.001f;
// Compute the largest read pointer based on the offset. If ptr
// is before the first delayline location, wrap around end point
ptr = writePtr - (int)floorf(offset);
if (ptr < delayLineStart)
ptr += delayLineLength;
ptr2 = ptr - 1;
if (ptr2 < delayLineStart)
ptr2 += delayLineLength;
frac = offset - (int)floorf(offset);
delayLineOutput = *ptr2 + *ptr * (1 - frac) - (1 - frac) * z1;
z1 = delayLineOutput;
// Low pass
lp->tick(&delayLineOutput, 0.95f);
// Write the input sample and any feedback to delayline
*writePtr = *sample;
// Increment buffer index and wrap if necesary
if (++writePtr >= delayLineEnd) {
writePtr = delayLineStart;
}
return delayLineOutput;
}
inline float nextLFO() {
if (lfoPhase >= 1.0f)
{
lfoSign = -1.0f;
}
else if (lfoPhase <= -1.0f)
{
lfoSign = +1.0f;
}
lfoPhase += lfoStepSize * lfoSign;
return lfoPhase;
}
};
#endif