Should remove the big white noise that was produced
[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 /*****************************************************************************
84  *  Transforms the audio stream
85  * /param float *inputL     input buffer
86  * /param float *outputL   output buffer
87  * /param long numsamples  number of samples to be processed
88  * /param int skip             number of channels in the audio stream
89  *****************************************************************************/
90 void revmodel::processreplace(float *inputL, float *outputL, long numsamples, int skip)
91 {
92     float outL,outR,input;
93     float inputR;
94     int i;
95
96     outL = outR = 0;
97         /* TODO this module supports only 2 audio channels, let's improve this */
98         if (skip > 1)
99            inputR = inputL[1];
100         else
101            inputR = inputL[0];
102         input = (inputL[0] + inputR) * gain;
103
104         // Accumulate comb filters in parallel
105         for(i=0; i<numcombs; i++)
106         {
107             outL += combL[i].process(input);
108             outR += combR[i].process(input);
109         }
110
111         // Feed through allpasses in series
112         for(i=0; i<numallpasses; i++)
113         {
114             outL = allpassL[i].process(outL);
115             outR = allpassR[i].process(outR);
116         }
117
118         // Calculate output REPLACING anything already there
119         outputL[0] = (outL*wet1 + outR*wet2 + inputR*dry);
120            if (skip > 1)
121         outputL[1] = (outR*wet1 + outL*wet2 + inputR*dry);
122 }
123
124 void revmodel::processmix(float *inputL, float *outputL, long numsamples, int skip)
125 {
126     float outL,outR,input;
127     float inputR;
128     int i;
129
130     outL = outR = 0;
131         if (skip > 1)
132            inputR = inputL[1];
133         else
134            inputR = inputL[0];
135         input = (inputL[0] + inputR) * gain;
136
137         // Accumulate comb filters in parallel
138         for(i=0; i<numcombs; i++)
139         {
140             outL += combL[i].process(input);
141             outR += combR[i].process(input);
142         }
143
144         // Feed through allpasses in series
145         for(i=0; i<numallpasses; i++)
146         {
147             outL = allpassL[i].process(outL);
148             outR = allpassR[i].process(outR);
149         }
150
151         // Calculate output REPLACING anything already there
152         outputL[0] += (outL*wet1 + outR*wet2 + inputR*dry);
153            if (skip > 1)
154         outputL[1] += (outR*wet1 + outL*wet2 + inputR*dry);
155 }
156
157 void revmodel::update()
158 {
159 // Recalculate internal values after parameter change
160
161     int i;
162
163     wet1 = wet*(width/2 + 0.5f);
164     wet2 = wet*((1-width)/2);
165
166     if (mode >= freezemode)
167     {
168         roomsize1 = 1;
169         damp1 = 0;
170         gain = muted;
171     }
172     else
173     {
174         roomsize1 = roomsize;
175         damp1 = damp;
176         gain = fixedgain;
177     }
178
179     for(i=0; i<numcombs; i++)
180     {
181         combL[i].setfeedback(roomsize1);
182         combR[i].setfeedback(roomsize1);
183     }
184
185     for(i=0; i<numcombs; i++)
186     {
187         combL[i].setdamp(damp1);
188         combR[i].setdamp(damp1);
189     }
190 }
191
192 // The following get/set functions are not inlined, because
193 // speed is never an issue when calling them, and also
194 // because as you develop the reverb model, you may
195 // wish to take dynamic action when they are called.
196
197 void revmodel::setroomsize(float value)
198 {
199     roomsize = (value*scaleroom) + offsetroom;
200     update();
201 }
202
203 float revmodel::getroomsize()
204 {
205     return (roomsize-offsetroom)/scaleroom;
206 }
207
208 void revmodel::setdamp(float value)
209 {
210     damp = value*scaledamp;
211     update();
212 }
213
214 float revmodel::getdamp()
215 {
216     return damp/scaledamp;
217 }
218
219 void revmodel::setwet(float value)
220 {
221     wet = value*scalewet;
222     update();
223 }
224
225 float revmodel::getwet()
226 {
227     return wet/scalewet;
228 }
229
230 void revmodel::setdry(float value)
231 {
232     dry = value*scaledry;
233 }
234
235 float revmodel::getdry()
236 {
237     return dry/scaledry;
238 }
239
240 void revmodel::setwidth(float value)
241 {
242     width = value;
243     update();
244 }
245
246 float revmodel::getwidth()
247 {
248     return width;
249 }
250
251 void revmodel::setmode(float value)
252 {
253     mode = value;
254     update();
255 }
256
257 float revmodel::getmode()
258 {
259     if (mode >= freezemode)
260         return 1;
261     else
262         return 0;
263 }
264
265 //ends