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