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