-
Notifications
You must be signed in to change notification settings - Fork 10
/
compressor.h
225 lines (186 loc) · 6.39 KB
/
compressor.h
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
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
#pragma once
#ifndef DSY_COMPRESSOR_H
#define DSY_COMPRESSOR_H
/** dynamics compressor
influenced by compressor in soundpipe (from faust).
Modifications made to do:
- Less calculations during each process loop (coefficients recalculated on parameter change).
- C++-ified
- added sidechain support
- pulled gain apart for monitoring and multichannel support
- improved readability
- improved makeup-gain calculations
- changing controls now costs a lot less
- a lot less expensive
by: shensley, improved upon by AvAars
\todo Add soft/hard knee settings
*/
class Compressor
{
public:
Compressor() {}
~Compressor() {}
/** Initializes compressor
\param sample_rate rate at which samples will be produced by the audio engine.
*/
void Init(float sample_rate);
/** Compress the audio input signal, saves the calculated gain
\param in audio input signal
*/
float Process(float in);
/** Compresses the audio input signal, keyed by a secondary input.
\param in audio input signal (to be compressed)
\param key audio input that will be used to side-chain the compressor
*/
float Process(float in, float key)
{
Process(key);
return Apply(in);
}
/** Apply compression to the audio signal, based on the previously calculated gain
\param in audio input signal
*/
float Apply(float in) { return gain_ * in; }
/** Compresses a block of audio
\param in audio input signal
\param out audio output signal
\param size the size of the block
*/
void ProcessBlock(float *in, float *out, size_t size)
{
ProcessBlock(in, out, in, size);
}
/** Compresses a block of audio, keyed by a secondary input
\param in audio input signal (to be compressed)
\param out audio output signal
\param key audio input that will be used to side-chain the compressor
\param size the size of the block
*/
void ProcessBlock(float *in, float *out, float *key, size_t size);
/** Compresses a block of multiple channels of audio, keyed by a secondary input
\param in audio input signals (to be compressed)
\param out audio output signals
\param key audio input that will be used to side-chain the compressor
\param channels the number of audio channels
\param size the size of the block
*/
void ProcessBlock(float **in,
float **out,
float * key,
size_t channels,
size_t size);
/** Gets the amount of gain reduction */
float GetRatio() { return ratio_; }
/** Sets the amount of gain reduction applied to compressed signals
\param ratio Expects 1.0 -> 40. (untested with values < 1.0)
*/
void SetRatio(float ratio)
{
ratio_ = ratio;
RecalculateRatio();
}
/** Gets the threshold in dB */
float GetThreshold() { return thresh_; }
/** Sets the threshold in dB at which compression will be applied
\param threshold Expects 0.0 -> -80.
*/
void SetThreshold(float threshold)
{
thresh_ = threshold;
RecalculateMakeup();
}
/** Gets the envelope time for onset of compression */
float GetAttack() { return atk_; }
/** Sets the envelope time for onset of compression for signals above the threshold.
\param attack Expects 0.001 -> 10
*/
void SetAttack(float attack)
{
atk_ = attack;
RecalculateAttack();
}
/** Gets the envelope time for release of compression */
float GetRelease() { return rel_; }
/** Sets the envelope time for release of compression as input signal falls below threshold.
\param release Expects 0.001 -> 10
*/
void SetRelease(float release)
{
rel_ = release;
RecalculateRelease();
}
/** Gets the additional gain to make up for the compression */
float GetMakeup() { return makeup_gain_; }
/** Manually sets the additional gain to make up for the compression
\param gain Expects 0.0 -> 80
*/
void SetMakeup(float gain) { makeup_gain_ = gain; }
/** Enables or disables the automatic makeup gain. Disabling sets the makeup gain to 0.0
\param enable true to enable, false to disable
*/
void AutoMakeup(bool enable)
{
makeup_auto_ = enable;
makeup_gain_ = 0.0f;
RecalculateMakeup();
}
/** Gets the gain reduction in dB
*/
float GetGain() { return fastlog10f(gain_) * 20.0f; }
private:
float ratio_, thresh_, atk_, rel_;
float makeup_gain_;
float gain_;
// Recorded slope and gain, used in next sample
float slope_rec_, gain_rec_;
// Internals from faust
float atk_slo2_, ratio_mul_, atk_slo_, rel_slo_;
int sample_rate_;
float sample_rate_inv2_, sample_rate_inv_;
// Auto makeup gain enable
bool makeup_auto_;
// Methods for recalculating internals
void RecalculateRatio()
{
ratio_mul_ = ((1.0f - atk_slo2_) * ((1.0f / ratio_) - 1.0f));
}
void RecalculateAttack()
{
atk_slo_ = expf(-(sample_rate_inv_ / atk_));
atk_slo2_ = expf(-(sample_rate_inv2_ / atk_));
RecalculateRatio();
}
void RecalculateRelease() { rel_slo_ = expf((-(sample_rate_inv_ / rel_))); }
void RecalculateMakeup()
{
if(makeup_auto_)
makeup_gain_ = fabsf(thresh_ - thresh_ / ratio_) * 0.5f;
}
inline float pow10f(float f)
{
return expf(2.302585092994046f * f);
}
/* Original code for fastlog2f by Dr. Paul Beckmann from the ARM community forum, adapted from the CMSIS-DSP library
About 25% performance increase over std::log10f
*/
inline float fastlog2f(float f)
{
float frac;
int exp;
frac = frexpf(fabsf(f), &exp);
f = 1.23149591368684f;
f *= frac;
f += -4.11852516267426f;
f *= frac;
f += 6.02197014179219f;
f *= frac;
f += -3.13396450166353f;
f += exp;
return (f);
}
inline float fastlog10f(float f)
{
return fastlog2f(f) * 0.3010299956639812f;
}
};
#endif // DSY_COMPRESSOR_H