1 /*
2  * Author: Harry van Haaren 2014
3  *         harryhaaren@gmail.com
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
18  * MA 02110-1301, USA.
19  */
20 
21 #ifndef OPENAV_DSP_COMPANDER_H
22 #define OPENAV_DSP_COMPANDER_H
23 
24 #include <cstring>
25 #include <cmath>
26 #include <math.h>
27 #include <cmath>
28 #include <cstdlib>
29 #include <stdlib.h>
30 #include <iostream>
31 
32 using namespace std;
33 
34 /** Compander
35  *  A compressor/expander combo: a threshold sets the expander/compressor turn
36  *  point, while a factor control regulates the amount of compression/expansion.
37  *
38  *  Derived from https://github.com/magnetophon/qompander
39 **/
40 class Compander // : Effect
41 {
42 public:
Compander(int sr)43 	Compander(int sr) :
44 		samplerate( sr )
45 	{
46 		_active = true;
47 
48 		init();
49 
50 		attack = 20.f;
51 		release = 20;
52 
53 		threshold = -60.f;
54 		factor = 3.f;
55 	}
56 
getValue()57 	float getValue()
58 	{
59 		return factor;
60 	}
61 
setValue(float v)62 	void setValue(float v)
63 	{
64 		if ( v < 0.f ) v = 0.f;
65 		if ( v > 1.f ) v = 1.f;
66 
67 		factor = 1 + v * 7;
68 	}
69 
setThreshold(float v)70 	void setThreshold( float v )
71 	{
72 		if ( v < 0.f ) v = 0.f;
73 		if ( v > 1.f ) v = 1.f;
74 
75 		// -20 to -80dB range
76 		threshold = (v * 60.f) - 80;
77 	}
78 
setAttack(float v)79 	void setAttack( float v )
80 	{
81 		if ( v < 0.f ) v = 0.f;
82 		if ( v > 1.f ) v = 1.f;
83 		attack = v * 18 + 2;
84 	}
85 
setRelease(float v)86 	void setRelease( float v)
87 	{
88 		if ( v < 0.f ) v = 0.f;
89 		if ( v > 1.f ) v = 1.f;
90 		release = v * 230 + 20;
91 	}
92 
93 
active(bool a)94 	void active(bool a)
95 	{
96 		_active = a;
97 	}
98 
getNumInputs()99 	int getNumInputs()
100 	{
101 		return 1;
102 	}
getNumOutputs()103 	int getNumOutputs()
104 	{
105 		return 1;
106 	}
107 
process(long count,float * input0,float * output0)108 	void process (long count, float* input0, float* output0)
109 	{
110 		if ( _active ) {
111 			float 	fSlow0 = (0.0010000000000000009f * attack);
112 			float 	fSlow1 = (0.0010000000000000009f * release);
113 			float 	fSlow2 = (0.0010000000000000009f * factor);
114 			float 	fSlow3 = (0.0010000000000000009f * threshold);
115 
116 			for (int i=0; i<count; i++) {
117 				fRec1[0] = (fSlow0 + (0.999f * fRec1[1]));
118 				float fTemp0 = expf((0 - (fConst0 / fRec1[0])));
119 				float fTemp1 = (float)input0[i];
120 				fVec0[0] = fTemp1;
121 				fRec6[0] = (fVec0[0] + (0.161758f * fRec6[2]));
122 				fRec5[0] = (((0.733029f * fRec5[2]) + (0.161758f * fRec6[0])) - fRec6[2]);
123 				fRec4[0] = (((0.94535f * fRec4[2]) + (0.733029f * fRec5[0])) - fRec5[2]);
124 				fRec3[0] = (((0.990598f * fRec3[2]) + (0.94535f * fRec4[0])) - fRec4[2]);
125 				float fTemp2 = ((0.990598f * fRec3[0]) - fRec3[2]);
126 				fRec10[0] = ((0.479401f * fRec10[2]) + fVec0[1]);
127 				fRec9[0] = (((0.876218f * fRec9[2]) + (0.479401f * fRec10[0])) - fRec10[2]);
128 				fRec8[0] = (((0.976599f * fRec8[2]) + (0.876218f * fRec9[0])) - fRec9[2]);
129 				fRec7[0] = (((0.9975f * fRec7[2]) + (0.976599f * fRec8[0])) - fRec8[2]);
130 				float fTemp3 = ((0.9975f * fRec7[0]) - fRec7[2]);
131 
132 				//float fTemp4 = fabsf(min((float)100, max(1e-05f, sqrtf( (faustpower<2>(fTemp3) + faustpower<2>(fTemp2))))));
133 				float fTemp4 = fabsf(min((float)100, max(1e-05f, sqrtf( ( pow( fTemp3, 2 ) + pow( fTemp2, 2 ) ) ) ) ) );
134 
135 				fRec11[0] = (fSlow1 + (0.999f * fRec11[1]));
136 				float fTemp5 = expf((0 - (fConst0 / fRec11[0])));
137 				fRec2[0] = (((1.0f - fTemp5) * fTemp4) + (fTemp5 * max(fTemp4, fRec2[1])));
138 				fRec0[0] = ((fRec2[0] * (1.0f - fTemp0)) + (fTemp0 * fRec0[1]));
139 				fRec12[0] = (fSlow2 + (0.999f * fRec12[1]));
140 				fRec13[0] = (fSlow3 + (0.999f * fRec13[1]));
141 				float fTemp6 = powf(10,(0.05f * fRec13[0]));
142 				output0[i] = (float)(0.7071067811865476f * ((powf(min((float)1, max(1e-07f, sinf((1.5707963267948966f * (fRec12[0] * min((1.0f / fRec12[0]), fRec0[0])))))),(logf(fTemp6) / logf(sinf((1.5707963267948966f * (fRec12[0] * fTemp6)))))) * (fTemp3 + fTemp2)) / fRec0[0]));
143 				// post processing
144 				fRec13[1] = fRec13[0];
145 				fRec12[1] = fRec12[0];
146 				fRec0[1] = fRec0[0];
147 				fRec2[1] = fRec2[0];
148 				fRec11[1] = fRec11[0];
149 				fRec7[2] = fRec7[1];
150 				fRec7[1] = fRec7[0];
151 				fRec8[2] = fRec8[1];
152 				fRec8[1] = fRec8[0];
153 				fRec9[2] = fRec9[1];
154 				fRec9[1] = fRec9[0];
155 				fRec10[2] = fRec10[1];
156 				fRec10[1] = fRec10[0];
157 				fRec3[2] = fRec3[1];
158 				fRec3[1] = fRec3[0];
159 				fRec4[2] = fRec4[1];
160 				fRec4[1] = fRec4[0];
161 				fRec5[2] = fRec5[1];
162 				fRec5[1] = fRec5[0];
163 				fRec6[2] = fRec6[1];
164 				fRec6[1] = fRec6[0];
165 				fVec0[1] = fVec0[0];
166 				fRec1[1] = fRec1[0];
167 			}
168 		} else {
169 			// set input -> output
170 			if( output0 != input0 )
171 				memcpy( output0, input0, count * sizeof(float) );
172 		}
173 	}
174 
175 private:
176 	int samplerate;
177 	bool _active;
178 
179 	float attack;
180 	float release;
181 	float factor;
182 	float fRec1[2];
183 	float fConst0;
184 	float fVec0[2];
185 	float fRec6[3];
186 	float fRec5[3];
187 	float fRec4[3];
188 	float fRec3[3];
189 	float fRec10[3];
190 	float fRec9[3];
191 	float fRec8[3];
192 	float fRec7[3];
193 	float fRec11[2];
194 	float fRec2[2];
195 	float fRec0[2];
196 
197 	float fRec12[2];
198 	float threshold;
199 	float fRec13[2];
200 
init()201 	void init()
202 	{
203 		attack = 2.0f;
204 
205 		for (int i=0; i<2; i++) fRec1[i] = 0;
206 		fConst0 = (1e+03f / float(min(192000, max(1, samplerate))));
207 		for (int i=0; i<2; i++) fVec0[i] = 0;
208 		for (int i=0; i<3; i++) fRec6[i] = 0;
209 		for (int i=0; i<3; i++) fRec5[i] = 0;
210 		for (int i=0; i<3; i++) fRec4[i] = 0;
211 		for (int i=0; i<3; i++) fRec3[i] = 0;
212 		for (int i=0; i<3; i++) fRec10[i] = 0;
213 		for (int i=0; i<3; i++) fRec9[i] = 0;
214 		for (int i=0; i<3; i++) fRec8[i] = 0;
215 		for (int i=0; i<3; i++) fRec7[i] = 0;
216 		release = 2e+01f;
217 		for (int i=0; i<2; i++) fRec11[i] = 0;
218 		for (int i=0; i<2; i++) fRec2[i] = 0;
219 		for (int i=0; i<2; i++) fRec0[i] = 0;
220 		factor = 1.0f;
221 		for (int i=0; i<2; i++) fRec12[i] = 0;
222 		threshold = -4e+01f;
223 		for (int i=0; i<2; i++) fRec13[i] = 0;
224 	}
225 
226 };
227 
228 #endif // OPENAV_DSP_COMPANDER_H
229