]> git.sesse.net Git - vlc/blob - modules/audio_filter/spatializer/revmodel.cpp
Spatializer: kill warnings and improve locality
[vlc] / 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 (mode >= 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
129     outL = outR = 0;
130         if (skip > 1)
131            inputR = inputL[1];
132         else
133            inputR = inputL[0];
134         input = (inputL[0] + inputR) * gain;
135
136         // Accumulate comb filters in parallel
137         for(int i=0; i<numcombs; i++)
138         {
139             outL += combL[i].process(input);
140             outR += combR[i].process(input);
141         }
142
143         // Feed through allpasses in series
144         for(int i=0; i<numallpasses; i++)
145         {
146             outL = allpassL[i].process(outL);
147             outR = allpassR[i].process(outR);
148         }
149
150         // Calculate output REPLACING anything already there
151         outputL[0] += (outL*wet1 + outR*wet2 + inputR*dry);
152            if (skip > 1)
153         outputL[1] += (outR*wet1 + outL*wet2 + inputR*dry);
154 }
155
156 void revmodel::update()
157 {
158 // Recalculate internal values after parameter change
159
160     wet1 = wet*(width/2 + 0.5f);
161     wet2 = wet*((1-width)/2);
162
163     if (mode >= freezemode)
164     {
165         roomsize1 = 1;
166         damp1 = 0;
167         gain = muted;
168     }
169     else
170     {
171         roomsize1 = roomsize;
172         damp1 = damp;
173         gain = fixedgain;
174     }
175
176     for(int i=0; i<numcombs; i++)
177     {
178         combL[i].setfeedback(roomsize1);
179         combR[i].setfeedback(roomsize1);
180     }
181
182     for(int i=0; i<numcombs; i++)
183     {
184         combL[i].setdamp(damp1);
185         combR[i].setdamp(damp1);
186     }
187 }
188
189 // The following get/set functions are not inlined, because
190 // speed is never an issue when calling them, and also
191 // because as you develop the reverb model, you may
192 // wish to take dynamic action when they are called.
193
194 void revmodel::setroomsize(float value)
195 {
196     roomsize = (value*scaleroom) + offsetroom;
197     update();
198 }
199
200 float revmodel::getroomsize()
201 {
202     return (roomsize-offsetroom)/scaleroom;
203 }
204
205 void revmodel::setdamp(float value)
206 {
207     damp = value*scaledamp;
208     update();
209 }
210
211 float revmodel::getdamp()
212 {
213     return damp/scaledamp;
214 }
215
216 void revmodel::setwet(float value)
217 {
218     wet = value*scalewet;
219     update();
220 }
221
222 float revmodel::getwet()
223 {
224     return wet/scalewet;
225 }
226
227 void revmodel::setdry(float value)
228 {
229     dry = value*scaledry;
230 }
231
232 float revmodel::getdry()
233 {
234     return dry/scaledry;
235 }
236
237 void revmodel::setwidth(float value)
238 {
239     width = value;
240     update();
241 }
242
243 float revmodel::getwidth()
244 {
245     return width;
246 }
247
248 void revmodel::setmode(float value)
249 {
250     mode = value;
251     update();
252 }
253
254 //ends