1 #include "doomtype.h"
2 #include "tarray.h"
3 #include "s_sound.h"
4 #include "farchive.h"
5 #include "sc_man.h"
6 #include "cmdlib.h"
7 #include "templates.h"
8 #include "w_wad.h"
9 #include "i_system.h"
10 
11 struct FReverbField
12 {
13 	int Min, Max;
14 	float REVERB_PROPERTIES::*Float;
15 	int REVERB_PROPERTIES::*Int;
16 	unsigned int Flag;
17 };
18 
19 static const FReverbField ReverbFields[] =
20 {
21 	{        0,       25, 0, &REVERB_PROPERTIES::Environment, 0 },
22 	{     1000,   100000, &REVERB_PROPERTIES::EnvSize, 0, 0 },
23 	{        0,     1000, &REVERB_PROPERTIES::EnvDiffusion, 0, 0 },
24 	{   -10000,        0, 0, &REVERB_PROPERTIES::Room, 0 },
25 	{   -10000,        0, 0, &REVERB_PROPERTIES::RoomHF, 0 },
26 	{   -10000,        0, 0, &REVERB_PROPERTIES::RoomLF, 0 },
27 	{      100,    20000, &REVERB_PROPERTIES::DecayTime, 0, 0 },
28 	{      100,     2000, &REVERB_PROPERTIES::DecayHFRatio, 0, 0 },
29 	{      100,     2000, &REVERB_PROPERTIES::DecayLFRatio, 0, 0 },
30 	{   -10000,     1000, 0, &REVERB_PROPERTIES::Reflections, 0 },
31 	{        0,      300, &REVERB_PROPERTIES::ReflectionsDelay, 0, 0 },
32 	{ -2000000,  2000000, &REVERB_PROPERTIES::ReflectionsPan0, 0, 0 },
33 	{ -2000000,  2000000, &REVERB_PROPERTIES::ReflectionsPan1, 0, 0 },
34 	{ -2000000,  2000000, &REVERB_PROPERTIES::ReflectionsPan2, 0, 0 },
35 	{   -10000,     2000, 0, &REVERB_PROPERTIES::Reverb, 0 },
36 	{        0,      100, &REVERB_PROPERTIES::ReverbDelay, 0, 0 },
37 	{ -2000000,  2000000, &REVERB_PROPERTIES::ReverbPan0, 0, 0 },
38 	{ -2000000,  2000000, &REVERB_PROPERTIES::ReverbPan1, 0, 0 },
39 	{ -2000000,  2000000, &REVERB_PROPERTIES::ReverbPan2, 0, 0 },
40 	{       75,      250, &REVERB_PROPERTIES::EchoTime, 0, 0 },
41 	{        0,     1000, &REVERB_PROPERTIES::EchoDepth, 0, 0 },
42 	{       40,     4000, &REVERB_PROPERTIES::ModulationTime, 0, 0 },
43 	{        0,     1000, &REVERB_PROPERTIES::ModulationDepth, 0, 0 },
44 	{  -100000,        0, &REVERB_PROPERTIES::AirAbsorptionHF, 0, 0 },
45 	{  1000000, 20000000, &REVERB_PROPERTIES::HFReference, 0, 0 },
46 	{    20000,  1000000, &REVERB_PROPERTIES::LFReference, 0, 0 },
47 	{        0,    10000, &REVERB_PROPERTIES::RoomRolloffFactor, 0, 0 },
48 	{        0,   100000, &REVERB_PROPERTIES::Diffusion, 0, 0 },
49 	{        0,   100000, &REVERB_PROPERTIES::Density, 0, 0 },
50 	{ 0, 0, 0, 0, 1 },
51 	{ 0, 0, 0, 0, 2 },
52 	{ 0, 0, 0, 0, 0 },
53 	{ 0, 0, 0, 0, 5 },
54 	{ 0, 0, 0, 0, 3 },
55 	{ 0, 0, 0, 0, 4 },
56 	{ 0, 0, 0, 0, 6 },
57 	{ 0, 0, 0, 0, 7 }
58 };
59 #define NUM_REVERB_FIELDS (int(countof(ReverbFields)))
60 
61 static const char *ReverbFieldNames[NUM_REVERB_FIELDS+2] =
62 {
63 	"Environment",
64 	"EnvironmentSize",
65 	"EnvironmentDiffusion",
66 	"Room",
67 	"RoomHF",
68 	"RoomLF",
69 	"DecayTime",
70 	"DecayHFRatio",
71 	"DecayLFRatio",
72 	"Reflections",
73 	"ReflectionsDelay",
74 	"ReflectionsPanX",
75 	"ReflectionsPanY",
76 	"ReflectionsPanZ",
77 	"Reverb",
78 	"ReverbDelay",
79 	"ReverbPanX",
80 	"ReverbPanY",
81 	"ReverbPanZ",
82 	"EchoTime",
83 	"EchoDepth",
84 	"ModulationTime",
85 	"ModulationDepth",
86 	"AirAbsorptionHF",
87 	"HFReference",
88 	"LFReference",
89 	"RoomRolloffFactor",
90 	"Diffusion",
91 	"Density",
92 	"bReflectionsScale",
93 	"bReflectionsDelayScale",
94 	"bDecayTimeScale",
95 	"bDecayHFLimit",
96 	"bReverbScale",
97 	"bReverbDelayScale",
98 	"bEchoTimeScale",
99 	"bModulationTimeScale",
100 	"}",
101 	NULL
102 };
103 
104 static const char *BoolNames[3] = { "False", "True", NULL };
105 
106 static ReverbContainer DSPWater =
107 {
108 	// Based on the "off" reverb, this one uses the software water effect,
109 	// which is completely independant from EAX-like reverb.
110 	NULL,
111 	"DSP Water",
112 	0xffff,
113 	true,
114 	false,
115 	{0, 0,	7.5f,	1.00f, -10000, -10000, 0,   1.00f,  1.00f, 1.0f,  -2602, 0.007f, 0.0f,0.0f,0.0f,   200, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f,   0.0f,   0.0f, 0x33f },
116 	true
117 };
118 
119 static ReverbContainer Psychotic =
120 {
121 	&DSPWater,
122 	"Psychotic",
123 	0x1900,
124 	true,
125 	false,
126 	{0,25,	1.0f,	0.50f, -1000,  -151,   0,   7.56f,  0.91f, 1.0f,  -626,  0.020f, 0.0f,0.0f,0.0f,   774, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 4.00f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f },
127 	false
128 };
129 
130 static ReverbContainer Dizzy =
131 {
132 	&Psychotic,
133 	"Dizzy",
134 	0x1800,
135 	true,
136 	false,
137 	{0,24,	1.8f,	0.60f, -1000,  -400,   0,   17.23f, 0.56f, 1.0f,  -1713, 0.020f, 0.0f,0.0f,0.0f,  -613, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 1.00f, 0.81f, 0.310f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f },
138 	false
139 };
140 
141 static ReverbContainer Drugged =
142 {
143 	&Dizzy,
144 	"Drugged",
145 	0x1700,
146 	true,
147 	false,
148 	{0,23,	1.9f,	0.50f, -1000,  0,      0,   8.39f,  1.39f, 1.0f,  -115,  0.002f, 0.0f,0.0f,0.0f,   985, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f },
149 	false
150 };
151 
152 static ReverbContainer Underwater =
153 {
154 	&Drugged,
155 	"Underwater",
156 	0x1600,
157 	true,
158 	false,
159 	{0,22,	1.8f,	1.00f, -1000,  -4000,  0,   1.49f,  0.10f, 1.0f,   -449, 0.007f, 0.0f,0.0f,0.0f,  1700, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 1.18f, 0.348f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
160 	false
161 };
162 
163 static ReverbContainer SewerPipe =
164 {
165 	&Underwater,
166 	"Sewer Pipe",
167 	0x1500,
168 	true,
169 	false,
170 	{0,21,	1.7f,	0.80f, -1000,  -1000,  0,   2.81f,  0.14f, 1.0f,    429, 0.014f, 0.0f,0.0f,0.0f,  1023, 0.021f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f,  80.0f,  60.0f, 0x3f },
171 	false
172 };
173 
174 static ReverbContainer ParkingLot =
175 {
176 	&SewerPipe,
177 	"Parking Lot",
178 	0x1400,
179 	true,
180 	false,
181 	{0,20,	8.3f,	1.00f, -1000,  0,      0,   1.65f,  1.50f, 1.0f,  -1363, 0.008f, 0.0f,0.0f,0.0f, -1153, 0.012f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f },
182 	false
183 };
184 
185 static ReverbContainer Plain =
186 {
187 	&ParkingLot,
188 	"Plain",
189 	0x1300,
190 	true,
191 	false,
192 	{0,19,	42.5f,	0.21f, -1000,  -2000,  0,   1.49f,  0.50f, 1.0f,  -2466, 0.179f, 0.0f,0.0f,0.0f, -1926, 0.100f, 0.0f,0.0f,0.0f, 0.250f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f,  21.0f, 100.0f, 0x3f },
193 	false
194 };
195 
196 static ReverbContainer Quarry =
197 {
198 	&Plain,
199 	"Quarry",
200 	0x1200,
201 	true,
202 	false,
203 	{0,18,	17.5f,	1.00f, -1000,  -1000,  0,   1.49f,  0.83f, 1.0f, -10000, 0.061f, 0.0f,0.0f,0.0f,   500, 0.025f, 0.0f,0.0f,0.0f, 0.125f, 0.70f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
204 	false
205 };
206 
207 static ReverbContainer Mountains =
208 {
209 	&Quarry,
210 	"Mountains",
211 	0x1100,
212 	true,
213 	false,
214 	{0,17,	100.0f, 0.27f, -1000,  -2500,  0,   1.49f,  0.21f, 1.0f,  -2780, 0.300f, 0.0f,0.0f,0.0f, -1434, 0.100f, 0.0f,0.0f,0.0f, 0.250f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f,  27.0f, 100.0f, 0x1f },
215 	false
216 };
217 
218 static ReverbContainer City =
219 {
220 	&Mountains,
221 	"City",
222 	0x1000,
223 	true,
224 	false,
225 	{0,16,	7.5f,	0.50f, -1000,  -800,   0,   1.49f,  0.67f, 1.0f,  -2273, 0.007f, 0.0f,0.0f,0.0f, -1691, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f,  50.0f, 100.0f, 0x3f },
226 	false
227 };
228 
229 static ReverbContainer Forest =
230 {
231 	&City,
232 	"Forest",
233 	0x0F00,
234 	true,
235 	false,
236 	{0,15,	38.0f,	0.30f, -1000,  -3300,  0,   1.49f,  0.54f, 1.0f,  -2560, 0.162f, 0.0f,0.0f,0.0f,  -229, 0.088f, 0.0f,0.0f,0.0f, 0.125f, 1.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f,  79.0f, 100.0f, 0x3f },
237 	false
238 };
239 
240 static ReverbContainer Alley =
241 {
242 	&Forest,
243 	"Alley",
244 	0x0E00,
245 	true,
246 	false,
247 	{0,14,	7.5f,	0.30f, -1000,  -270,   0,   1.49f,  0.86f, 1.0f,  -1204, 0.007f, 0.0f,0.0f,0.0f,    -4, 0.011f, 0.0f,0.0f,0.0f, 0.125f, 0.95f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
248 	false
249 };
250 
251 static ReverbContainer StoneCorridor =
252 {
253 	&Alley,
254 	"Stone Corridor",
255 	0x0D00,
256 	true,
257 	false,
258 	{0,13,	13.5f,	1.00f, -1000,  -237,   0,   2.70f,  0.79f, 1.0f,  -1214, 0.013f, 0.0f,0.0f,0.0f,   395, 0.020f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
259 	false
260 };
261 
262 static ReverbContainer Hallway =
263 {
264 	&StoneCorridor,
265 	"Hallway",
266 	0x0C00,
267 	true,
268 	false,
269 	{0,12,	1.8f,	1.00f, -1000,  -300,   0,   1.49f,  0.59f, 1.0f,  -1219, 0.007f, 0.0f,0.0f,0.0f,   441, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
270 	false
271 };
272 
273 static ReverbContainer CarpettedHallway =
274 {
275 	&Hallway,
276 	"Carpetted Hallway",
277 	0x0B00,
278 	true,
279 	false,
280 	{0,11,	1.9f,	1.00f, -1000,  -4000,  0,   0.30f,  0.10f, 1.0f,  -1831, 0.002f, 0.0f,0.0f,0.0f, -1630, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
281 	false
282 };
283 
284 static ReverbContainer Hangar =
285 {
286 	&CarpettedHallway,
287 	"Hangar",
288 	0x0A00,
289 	true,
290 	false,
291 	{0,10,	50.3f,	1.00f, -1000,  -1000,  0,   10.05f, 0.23f, 1.0f,   -602, 0.020f, 0.0f,0.0f,0.0f,   198, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
292 	false
293 };
294 
295 static ReverbContainer Arena =
296 {
297 	&Hangar,
298 	"Arena",
299 	0x0900,
300 	true,
301 	false,
302 	{0, 9,	36.2f,	1.00f, -1000,  -698,   0,   7.24f,  0.33f, 1.0f,  -1166, 0.020f, 0.0f,0.0f,0.0f,    16, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
303 	false
304 };
305 
306 static ReverbContainer Cave =
307 {
308 	&Arena,
309 	"Cave",
310 	0x0800,
311 	true,
312 	false,
313 	{0, 8,	14.6f,	1.00f, -1000,  0,      0,   2.91f,  1.30f, 1.0f,   -602, 0.015f, 0.0f,0.0f,0.0f,  -302, 0.022f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x1f },
314 	false
315 };
316 
317 static ReverbContainer ConcertHall =
318 {
319 	&Cave,
320 	"Concert Hall",
321 	0x0700,
322 	true,
323 	false,
324 	{0, 7,	19.6f,	1.00f, -1000,  -500,   0,   3.92f,  0.70f, 1.0f,  -1230, 0.020f, 0.0f,0.0f,0.0f,    -2, 0.029f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
325 	false
326 };
327 
328 static ReverbContainer Auditorium =
329 {
330 	&ConcertHall,
331 	"Auditorium",
332 	0x0600,
333 	true,
334 	false,
335 	{0, 6,	21.6f,	1.00f, -1000,  -476,   0,   4.32f,  0.59f, 1.0f,   -789, 0.020f, 0.0f,0.0f,0.0f,  -289, 0.030f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
336 	false
337 };
338 
339 static ReverbContainer StoneRoom =
340 {
341 	&Auditorium,
342 	"Stone Room",
343 	0x0500,
344 	true,
345 	false,
346 	{0, 5,	11.6f,	1.00f, -1000,  -300,   0,   2.31f,  0.64f, 1.0f,   -711, 0.012f, 0.0f,0.0f,0.0f,    83, 0.017f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
347 	false
348 };
349 
350 static ReverbContainer LivingRoom =
351 {
352 	&StoneRoom,
353 	"Living Room",
354 	0x0400,
355 	true,
356 	false,
357 	{0, 4,	2.5f,	1.00f, -1000,  -6000,  0,   0.50f,  0.10f, 1.0f,  -1376, 0.003f, 0.0f,0.0f,0.0f, -1104, 0.004f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
358 	false
359 };
360 
361 static ReverbContainer Bathroom =
362 {
363 	&LivingRoom,
364 	"Bathroom",
365 	0x0300,
366 	true,
367 	false,
368 	{0, 3,	1.4f,	1.00f, -1000,  -1200,  0,   1.49f,  0.54f, 1.0f,   -370, 0.007f, 0.0f,0.0f,0.0f,  1030, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f,  60.0f, 0x3f },
369 	false
370 };
371 
372 static ReverbContainer Room =
373 {
374 	&Bathroom,
375 	"Room",
376 	0x0200,
377 	true,
378 	false,
379 	{0, 2,	1.9f,	1.00f, -1000,  -454,   0,   0.40f,  0.83f, 1.0f,  -1646, 0.002f, 0.0f,0.0f,0.0f,    53, 0.003f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
380 	false
381 };
382 
383 static ReverbContainer PaddedCell =
384 {
385 	&Room,
386 	"Padded Cell",
387 	0x0100,
388 	true,
389 	false,
390 	{0, 1,	1.4f,	1.00f, -1000,  -6000,  0,   0.17f,  0.10f, 1.0f,  -1204, 0.001f, 0.0f,0.0f,0.0f,   207, 0.002f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
391 	false
392 };
393 
394 static ReverbContainer Generic =
395 {
396 	&PaddedCell,
397 	"Generic",
398 	0x0001,
399 	true,
400 	false,
401 	{0, 0,	7.5f,	1.00f, -1000,  -100,   0,   1.49f,  0.83f, 1.0f,  -2602, 0.007f, 0.0f,0.0f,0.0f,   200, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f, 100.0f, 100.0f, 0x3f },
402 	false
403 };
404 
405 static ReverbContainer Off =
406 {
407 	&Generic,
408 	"Off",
409 	0x0000,
410 	true,
411 	false,
412 	{0, 0,	7.5f,	1.00f, -10000, -10000, 0,   1.00f,  1.00f, 1.0f,  -2602, 0.007f, 0.0f,0.0f,0.0f,   200, 0.011f, 0.0f,0.0f,0.0f, 0.250f, 0.00f, 0.25f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.0f,   0.0f,   0.0f, 0x33f },
413 	false
414 };
415 
416 ReverbContainer *DefaultEnvironments[26] =
417 {
418 	&Off, &PaddedCell, &Room, &Bathroom, &LivingRoom, &StoneRoom, &Auditorium,
419 	&ConcertHall, &Cave, &Arena, &Hangar, &CarpettedHallway, &Hallway, &StoneCorridor,
420 	&Alley, &Forest, &City, &Mountains, &Quarry, &Plain, &ParkingLot, &SewerPipe,
421 	&Underwater, &Drugged, &Dizzy, &Psychotic
422 };
423 
424 ReverbContainer *Environments = &Off;
425 
S_FindEnvironment(const char * name)426 ReverbContainer *S_FindEnvironment (const char *name)
427 {
428 	ReverbContainer *probe = Environments;
429 
430 	if (name == NULL)
431 		return NULL;
432 
433 	while (probe != NULL)
434 	{
435 		if (stricmp (probe->Name, name) == 0)
436 		{
437 			return probe;
438 		}
439 		probe = probe->Next;
440 	}
441 	return NULL;
442 }
443 
S_FindEnvironment(int id)444 ReverbContainer *S_FindEnvironment (int id)
445 {
446 	ReverbContainer *probe = Environments;
447 
448 	while (probe != NULL && probe->ID < id)
449 	{
450 		probe = probe->Next;
451 	}
452 	return (probe && probe->ID == id ? probe : NULL);
453 }
454 
S_AddEnvironment(ReverbContainer * settings)455 void S_AddEnvironment (ReverbContainer *settings)
456 {
457 	ReverbContainer *probe = Environments;
458 	ReverbContainer **ptr = &Environments;
459 
460 	while (probe != NULL && probe->ID < settings->ID)
461 	{
462 		ptr = &probe->Next;
463 		probe = probe->Next;
464 	}
465 
466 	if (probe != NULL && probe->ID == settings->ID)
467 	{
468 		// Built-in environments cannot be changed
469 		if (!probe->Builtin)
470 		{
471 			settings->Next = probe->Next;
472 			*ptr = settings;
473 			delete[] const_cast<char *>(probe->Name);
474 			delete probe;
475 		}
476 	}
477 	else
478 	{
479 		settings->Next = probe;
480 		*ptr = settings;
481 	}
482 }
483 
operator <<(FArchive & arc,ReverbContainer * & env)484 FArchive &operator<< (FArchive &arc, ReverbContainer *&env)
485 {
486 	WORD id;
487 
488 	if (arc.IsStoring())
489 	{
490 		if (env != NULL)
491 		{
492 			arc << env->ID;
493 		}
494 		else
495 		{
496 			id = 0;
497 			arc << id;
498 		}
499 	}
500 	else
501 	{
502 		arc << id;
503 		env = S_FindEnvironment (id);
504 	}
505 	return arc;
506 }
507 
ReadReverbDef(int lump)508 static void ReadReverbDef (int lump)
509 {
510 	FScanner sc;
511 	const ReverbContainer *def;
512 	ReverbContainer *newenv;
513 	REVERB_PROPERTIES props;
514 	char *name;
515 	int id1, id2, i, j;
516 	bool inited[NUM_REVERB_FIELDS];
517 	BYTE bools[32];
518 
519 	sc.OpenLumpNum(lump);
520 	while (sc.GetString ())
521 	{
522 		name = copystring (sc.String);
523 		sc.MustGetNumber ();
524 		id1 = sc.Number;
525 		sc.MustGetNumber ();
526 		id2 = sc.Number;
527 		sc.MustGetStringName ("{");
528 		memset (inited, 0, sizeof(inited));
529 		props.Instance = 0;
530 		props.Flags = 0;
531 		while (sc.MustGetString (), NUM_REVERB_FIELDS > (i = sc.MustMatchString (ReverbFieldNames)))
532 		{
533 			if (ReverbFields[i].Float)
534 			{
535 				sc.MustGetFloat ();
536 				props.*ReverbFields[i].Float = (float)clamp (sc.Float,
537 					double(ReverbFields[i].Min)/1000,
538 					double(ReverbFields[i].Max)/1000);
539 			}
540 			else if (ReverbFields[i].Int)
541 			{
542 				sc.MustGetNumber ();
543 				props.*ReverbFields[i].Int = (j = clamp (sc.Number,
544 					ReverbFields[i].Min, ReverbFields[i].Max));
545 				if (i == 0 && j != sc.Number)
546 				{
547 					sc.ScriptError ("The Environment field is out of range.");
548 				}
549 			}
550 			else
551 			{
552 				sc.MustGetString ();
553 				bools[ReverbFields[i].Flag] = sc.MustMatchString (BoolNames);
554 			}
555 			inited[i] = true;
556 		}
557 		if (!inited[0])
558 		{
559 			sc.ScriptError ("Sound %s is missing an Environment field.", name);
560 		}
561 
562 		// Add the new environment to the list, filling in uninitialized fields
563 		// with values from the standard environment specified.
564 		def = DefaultEnvironments[props.Environment];
565 		for (i = 0; i < NUM_REVERB_FIELDS; ++i)
566 		{
567 			if (ReverbFields[i].Float)
568 			{
569 				if (!inited[i])
570 				{
571 					props.*ReverbFields[i].Float = def->Properties.*ReverbFields[i].Float;
572 				}
573 			}
574 			else if (ReverbFields[i].Int)
575 			{
576 				if (!inited[i])
577 				{
578 					props.*ReverbFields[i].Int = def->Properties.*ReverbFields[i].Int;
579 				}
580 			}
581 			else
582 			{
583 				if (!inited[i])
584 				{
585 					int mask = 1 << ReverbFields[i].Flag;
586 					if (def->Properties.Flags & mask)
587 					{
588 						props.Flags |= mask;
589 					}
590 				}
591 				else
592 				{
593 					if (bools[ReverbFields[i].Flag])
594 					{
595 						props.Flags |= 1 << ReverbFields[i].Flag;
596 					}
597 				}
598 			}
599 		}
600 
601 		newenv = new ReverbContainer;
602 		newenv->Next = NULL;
603 		newenv->Name = name;
604 		newenv->ID = (id1 << 8) | id2;
605 		newenv->Builtin = false;
606 		newenv->Properties = props;
607 		newenv->SoftwareWater = false;
608 		S_AddEnvironment (newenv);
609 	}
610 }
611 
S_ParseReverbDef()612 void S_ParseReverbDef ()
613 {
614 	int lump, lastlump = 0;
615 
616 	atterm (S_UnloadReverbDef);
617 	S_UnloadReverbDef ();
618 
619 	while ((lump = Wads.FindLump ("REVERBS", &lastlump)) != -1)
620 	{
621 		ReadReverbDef (lump);
622 	}
623 }
624 
S_UnloadReverbDef()625 void S_UnloadReverbDef ()
626 {
627 	ReverbContainer *probe = Environments;
628 	ReverbContainer **pNext = NULL;
629 
630 	while (probe != NULL)
631 	{
632 		ReverbContainer *next = probe->Next;
633 		if (!probe->Builtin)
634 		{
635 			if (pNext != NULL) *pNext = probe->Next;
636 			delete[] const_cast<char *>(probe->Name);
637 			delete probe;
638 		}
639 		else
640 		{
641 			pNext = &probe->Next;
642 		}
643 		probe = next;
644 	}
645 	Environments = &Off;
646 }
647