02bf6984e8dbbac20b58fe0e8e7d5f9b1304fcf6
[vlc.git] / modules / audio_filter / spatializer / revmodel.cpp
1 // Reverb model implementation
2 //
3 //
4 // Google Summer of Code 2007
5 //
6 // Authors: Biodun Osunkunle <biodun@videolan.org>
7 //
8 // Mentor : Jean-Baptiste Kempf <jb@videolan.org>
9 //
10 // Original written by Jezar at Dreampoint, June 2000
11
12 // This code is public domain
13
14 #include "revmodel.hpp"
15 #include <stdlib.h>
16
17 revmodel::revmodel()
18 {
19     // Tie the components to their buffers
20     combL[0].setbuffer(bufcombL1,combtuningL1);
21     combR[0].setbuffer(bufcombR1,combtuningR1);
22     combL[1].setbuffer(bufcombL2,combtuningL2);
23     combR[1].setbuffer(bufcombR2,combtuningR2);
24     combL[2].setbuffer(bufcombL3,combtuningL3);
25     combR[2].setbuffer(bufcombR3,combtuningR3);
26     combL[3].setbuffer(bufcombL4,combtuningL4);
27     combR[3].setbuffer(bufcombR4,combtuningR4);
28     combL[4].setbuffer(bufcombL5,combtuningL5);
29     combR[4].setbuffer(bufcombR5,combtuningR5);
30     combL[5].setbuffer(bufcombL6,combtuningL6);
31     combR[5].setbuffer(bufcombR6,combtuningR6);
32     combL[6].setbuffer(bufcombL7,combtuningL7);
33     combR[6].setbuffer(bufcombR7,combtuningR7);
34     combL[7].setbuffer(bufcombL8,combtuningL8);
35     combR[7].setbuffer(bufcombR8,combtuningR8);
36     allpassL[0].setbuffer(bufallpassL1,allpasstuningL1);
37     allpassR[0].setbuffer(bufallpassR1,allpasstuningR1);
38     allpassL[1].setbuffer(bufallpassL2,allpasstuningL2);
39     allpassR[1].setbuffer(bufallpassR2,allpasstuningR2);
40     allpassL[2].setbuffer(bufallpassL3,allpasstuningL3);
41     allpassR[2].setbuffer(bufallpassR3,allpasstuningR3);
42     allpassL[3].setbuffer(bufallpassL4,allpasstuningL4);
43     allpassR[3].setbuffer(bufallpassR4,allpasstuningR4);
44
45     // Set default values
46     allpassL[0].setfeedback(0.5f);
47     allpassR[0].setfeedback(0.5f);
48     allpassL[1].setfeedback(0.5f);
49     allpassR[1].setfeedback(0.5f);
50     allpassL[2].setfeedback(0.5f);
51     allpassR[2].setfeedback(0.5f);
52     allpassL[3].setfeedback(0.5f);
53     allpassR[3].setfeedback(0.5f);
54     setwet(initialwet);
55     setroomsize(initialroom);
56     setdry(initialdry);
57     setdamp(initialdamp);
58     setwidth(initialwidth);
59     setmode(initialmode);
60
61     // Buffer will be full of rubbish - so we MUST mute them
62     mute();
63 }
64
65 void revmodel::mute()
66 {
67     int i;
68     if (getmode() >= freezemode)
69         return;
70
71     for (i = 0 ; i < numcombs ; i++)
72     {
73         combL[i].mute();
74         combR[i].mute();
75     }
76     for (i=0;i<numallpasses;i++)
77     {
78         allpassL[i].mute();
79         allpassR[i].mute();
80     }
81 }
82
83 void revmodel::processreplace(float *inputL, float *outputL, long numsamples, int skip)
84 {
85     float outL,outR,input;
86     float inputR;
87     int i;
88
89     outL = outR = 0;
90         if (skip > 1)
91            inputR = inputL[1];
92         else
93            inputR = inputL[0];
94         input = (inputL[0] + inputR) * gain;
95
96         // Accumulate comb filters in parallel
97         for(i=0; i<numcombs; i++)
98         {
99             outL += combL[i].process(input);
100             outR += combR[i].process(input);
101         }
102
103         // Feed through allpasses in series
104         for(i=0; i<numallpasses; i++)
105         {
106             outL = allpassL[i].process(outL);
107             outR = allpassR[i].process(outR);
108         }
109
110         // Calculate output REPLACING anything already there
111         outputL[0] = (outL*wet1 + outR*wet2 + inputR*dry);
112            if (skip > 1)
113         outputL[1] = (outR*wet1 + outL*wet2 + inputR*dry);
114 }
115
116 void revmodel::processmix(float *inputL, float *outputL, long numsamples, int skip)
117 {
118     float outL,outR,input;
119     float inputR;
120     int i;
121
122     outL = outR = 0;
123         if (skip > 1)
124            inputR = inputL[1];
125         else
126            inputR = inputL[0];
127         input = (inputL[0] + inputR) * gain;
128
129         // Accumulate comb filters in parallel
130         for(i=0; i<numcombs; i++)
131         {
132             outL += combL[i].process(input);
133             outR += combR[i].process(input);
134         }
135
136         // Feed through allpasses in series
137         for(i=0; i<numallpasses; i++)
138         {
139             outL = allpassL[i].process(outL);
140             outR = allpassR[i].process(outR);
141         }
142
143         // Calculate output REPLACING anything already there
144         outputL[0] += (outL*wet1 + outR*wet2 + inputR*dry);
145            if (skip > 1)
146         outputL[1] += (outR*wet1 + outL*wet2 + inputR*dry);
147 }
148
149 void revmodel::update()
150 {
151 // Recalculate internal values after parameter change
152
153     int i;
154
155     wet1 = wet*(width/2 + 0.5f);
156     wet2 = wet*((1-width)/2);
157
158     if (mode >= freezemode)
159     {
160         roomsize1 = 1;
161         damp1 = 0;
162         gain = muted;
163     }
164     else
165     {
166         roomsize1 = roomsize;
167         damp1 = damp;
168         gain = fixedgain;
169     }
170
171     for(i=0; i<numcombs; i++)
172     {
173         combL[i].setfeedback(roomsize1);
174         combR[i].setfeedback(roomsize1);
175     }
176
177     for(i=0; i<numcombs; i++)
178     {
179         combL[i].setdamp(damp1);
180         combR[i].setdamp(damp1);
181     }
182 }
183
184 // The following get/set functions are not inlined, because
185 // speed is never an issue when calling them, and also
186 // because as you develop the reverb model, you may
187 // wish to take dynamic action when they are called.
188
189 void revmodel::setroomsize(float value)
190 {
191     roomsize = (value*scaleroom) + offsetroom;
192     update();
193 }
194
195 float revmodel::getroomsize()
196 {
197     return (roomsize-offsetroom)/scaleroom;
198 }
199
200 void revmodel::setdamp(float value)
201 {
202     damp = value*scaledamp;
203     update();
204 }
205
206 float revmodel::getdamp()
207 {
208     return damp/scaledamp;
209 }
210
211 void revmodel::setwet(float value)
212 {
213     wet = value*scalewet;
214     update();
215 }
216
217 float revmodel::getwet()
218 {
219     return wet/scalewet;
220 }
221
222 void revmodel::setdry(float value)
223 {
224     dry = value*scaledry;
225 }
226
227 float revmodel::getdry()
228 {
229     return dry/scaledry;
230 }
231
232 void revmodel::setwidth(float value)
233 {
234     width = value;
235     update();
236 }
237
238 float revmodel::getwidth()
239 {
240     return width;
241 }
242
243 void revmodel::setmode(float value)
244 {
245     mode = value;
246     update();
247 }
248
249 float revmodel::getmode()
250 {
251     if (mode >= freezemode)
252         return 1;
253     else
254         return 0;
255 }
256
257 //ends