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