1 //**************************************************************************
2 //**
3 //**	##   ##    ##    ##   ##   ####     ####   ###     ###
4 //**	##   ##  ##  ##  ##   ##  ##  ##   ##  ##  ####   ####
5 //**	 ## ##  ##    ##  ## ##  ##    ## ##    ## ## ## ## ##
6 //**	 ## ##  ########  ## ##  ##    ## ##    ## ##  ###  ##
7 //**	  ###   ##    ##   ###    ##  ##   ##  ##  ##       ##
8 //**	   #    ##    ##    #      ####     ####   ##       ##
9 //**
10 //**	$Id: snd_reverbs.cpp 4297 2010-06-03 22:49:00Z firebrand_kh $
11 //**
12 //**	Copyright (C) 1999-2006 Jānis Legzdiņš
13 //**
14 //**	This program is free software; you can redistribute it and/or
15 //**  modify it under the terms of the GNU General Public License
16 //**  as published by the Free Software Foundation; either version 2
17 //**  of the License, or (at your option) any later version.
18 //**
19 //**	This program is distributed in the hope that it will be useful,
20 //**  but WITHOUT ANY WARRANTY; without even the implied warranty of
21 //**  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
22 //**  GNU General Public License for more details.
23 //**
24 //**************************************************************************
25 
26 // HEADER FILES ------------------------------------------------------------
27 
28 #include "gamedefs.h"
29 #include "snd_local.h"
30 
31 // MACROS ------------------------------------------------------------------
32 
33 // TYPES -------------------------------------------------------------------
34 
35 // EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
36 
37 // PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
38 
39 // PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
40 
41 // EXTERNAL DATA DECLARATIONS ----------------------------------------------
42 
43 // PUBLIC DATA DEFINITIONS -------------------------------------------------
44 
45 // PRIVATE DATA DEFINITIONS ------------------------------------------------
46 
47 static VReverbInfo Psychotic =
48 {
49 	NULL,
50 	"Psychotic",
51 	0x1900,
52 	true,
53 	{ 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 }
54 };
55 
56 static VReverbInfo Dizzy =
57 {
58 	&Psychotic,
59 	"Dizzy",
60 	0x1800,
61 	true,
62 	{ 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 }
63 };
64 
65 static VReverbInfo Drugged =
66 {
67 	&Dizzy,
68 	"Drugged",
69 	0x1700,
70 	true,
71 	{ 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 }
72 };
73 
74 static VReverbInfo Underwater =
75 {
76 	&Drugged,
77 	"Underwater",
78 	0x1600,
79 	true,
80 	{ 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 }
81 };
82 
83 static VReverbInfo SewerPipe =
84 {
85 	&Underwater,
86 	"Sewer Pipe",
87 	0x1500,
88 	true,
89 	{ 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 }
90 };
91 
92 static VReverbInfo ParkingLot =
93 {
94 	&SewerPipe,
95 	"Parking Lot",
96 	0x1400,
97 	true,
98 	{ 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 }
99 };
100 
101 static VReverbInfo Plain =
102 {
103 	&ParkingLot,
104 	"Plain",
105 	0x1300,
106 	true,
107 	{ 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 }
108 };
109 
110 static VReverbInfo Quarry =
111 {
112 	&Plain,
113 	"Quarry",
114 	0x1200,
115 	true,
116 	{ 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 }
117 };
118 
119 static VReverbInfo Mountains =
120 {
121 	&Quarry,
122 	"Mountains",
123 	0x1100,
124 	true,
125 	{ 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 }
126 };
127 
128 static VReverbInfo City =
129 {
130 	&Mountains,
131 	"City",
132 	0x1000,
133 	true,
134 	{ 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 }
135 };
136 
137 static VReverbInfo Forest =
138 {
139 	&City,
140 	"Forest",
141 	0x0F00,
142 	true,
143 	{ 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 }
144 };
145 
146 static VReverbInfo Alley =
147 {
148 	&Forest,
149 	"Alley",
150 	0x0E00,
151 	true,
152 	{ 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 }
153 };
154 
155 static VReverbInfo StoneCorridor =
156 {
157 	&Alley,
158 	"Stone Corridor",
159 	0x0D00,
160 	true,
161 	{ 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 }
162 };
163 
164 static VReverbInfo Hallway =
165 {
166 	&StoneCorridor,
167 	"Hallway",
168 	0x0C00,
169 	true,
170 	{ 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 }
171 };
172 
173 static VReverbInfo CarpettedHallway =
174 {
175 	&Hallway,
176 	"Carpetted Hallway",
177 	0x0B00,
178 	true,
179 	{ 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 }
180 };
181 
182 static VReverbInfo Hangar =
183 {
184 	&CarpettedHallway,
185 	"Hangar",
186 	0x0A00,
187 	true,
188 	{ 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 }
189 };
190 
191 static VReverbInfo Arena =
192 {
193 	&Hangar,
194 	"Arena",
195 	0x0900,
196 	true,
197 	{ 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 }
198 };
199 
200 static VReverbInfo Cave =
201 {
202 	&Arena,
203 	"Cave",
204 	0x0800,
205 	true,
206 	{ 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 }
207 };
208 
209 static VReverbInfo ConcertHall =
210 {
211 	&Cave,
212 	"Concert Hall",
213 	0x0700,
214 	true,
215 	{ 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 }
216 };
217 
218 static VReverbInfo Auditorium =
219 {
220 	&ConcertHall,
221 	"Auditorium",
222 	0x0600,
223 	true,
224 	{ 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 }
225 };
226 
227 static VReverbInfo StoneRoom =
228 {
229 	&Auditorium,
230 	"Stone Room",
231 	0x0500,
232 	true,
233 	{ 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 }
234 };
235 
236 static VReverbInfo LivingRoom =
237 {
238 	&StoneRoom,
239 	"Living Room",
240 	0x0400,
241 	true,
242 	{ 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 }
243 };
244 
245 static VReverbInfo Bathroom =
246 {
247 	&LivingRoom,
248 	"Bathroom",
249 	0x0300,
250 	true,
251 	{ 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 }
252 };
253 
254 static VReverbInfo Room =
255 {
256 	&Bathroom,
257 	"Room",
258 	0x0200,
259 	true,
260 	{ 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 }
261 };
262 
263 static VReverbInfo PaddedCell =
264 {
265 	&Room,
266 	"Padded Cell",
267 	0x0100,
268 	true,
269 	{ 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 }
270 };
271 
272 static VReverbInfo Generic =
273 {
274 	&PaddedCell,
275 	"Generic",
276 	0x0001,
277 	true,
278 	{ 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 }
279 };
280 
281 static VReverbInfo Off =
282 {
283 	&Generic,
284 	"Off",
285 	0x0000,
286 	true,
287 	{ 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 }
288 };
289 
290 static const VReverbInfo* const DefaultEnvironments[26] =
291 {
292 	&Off, &PaddedCell, &Room, &Bathroom, &LivingRoom, &StoneRoom, &Auditorium,
293 	&ConcertHall, &Cave, &Arena, &Hangar, &CarpettedHallway, &Hallway,
294 	&StoneCorridor, &Alley, &Forest, &City, &Mountains, &Quarry, &Plain,
295 	&ParkingLot, &SewerPipe, &Underwater, &Drugged, &Dizzy, &Psychotic
296 };
297 
298 // CODE --------------------------------------------------------------------
299 
300 //==========================================================================
301 //
302 //	DoInt
303 //
304 //==========================================================================
305 
DoInt(VScriptParser * sc,int & Val,int Min,int Max)306 static void DoInt(VScriptParser* sc, int& Val, int Min, int Max)
307 {
308 	sc->ExpectNumber();
309 	Val = MID(Min, sc->Number, Max);
310 }
311 
312 //==========================================================================
313 //
314 //	DoFloat
315 //
316 //==========================================================================
317 
DoFloat(VScriptParser * sc,float & Val,float Min,float Max)318 static void DoFloat(VScriptParser* sc, float& Val, float Min, float Max)
319 {
320 	sc->ExpectFloat();
321 	Val = MID(Min, sc->Float, Max);
322 }
323 
324 //==========================================================================
325 //
326 //	DoBool
327 //
328 //==========================================================================
329 
DoBool(VScriptParser * sc,int & Flags,int Mask)330 static void DoBool(VScriptParser* sc, int& Flags, int Mask)
331 {
332 	if (sc->Check("true"))
333 	{
334 		Flags |= Mask;
335 	}
336 	else if (sc->Check("false"))
337 	{
338 		Flags &= ~Mask;
339 	}
340 	else
341 	{
342 		sc->Error("Bad syntax");
343 	}
344 }
345 
346 //==========================================================================
347 //
348 //	VSoundManager::ParseReverbs
349 //
350 //==========================================================================
351 
ParseReverbs(VScriptParser * sc)352 void VSoundManager::ParseReverbs(VScriptParser* sc)
353 {
354 	guard(VSoundManager::ParseReverbs);
355 	if (!Environments)
356 	{
357 		Environments = &Off;
358 	}
359 
360 	while (!sc->AtEnd())
361 	{
362 		//	Name and ID.
363 		sc->ExpectString();
364 		VStr Name = sc->String;
365 		sc->ExpectNumber();
366 		int Id1 = sc->Number;
367 		sc->ExpectNumber();
368 		int Id2 = sc->Number;
369 
370 		VReverbProperties Prop;
371 		Prop.Flags = 0;
372 
373 		bool HaveEnvironment = false;
374 		bool HaveEnvironmentSize = false;
375 		bool HaveEnvironmentDiffusion = false;
376 		bool HaveRoom = false;
377 		bool HaveRoomHF = false;
378 		bool HaveRoomLF = false;
379 		bool HaveDecayTime = false;
380 		bool HaveDecayHFRatio = false;
381 		bool HaveDecayLFRatio = false;
382 		bool HaveReflections = false;
383 		bool HaveReflectionsDelay = false;
384 		bool HaveReflectionsPanX = false;
385 		bool HaveReflectionsPanY = false;
386 		bool HaveReflectionsPanZ = false;
387 		bool HaveReverb = false;
388 		bool HaveReverbDelay = false;
389 		bool HaveReverbPanX = false;
390 		bool HaveReverbPanY = false;
391 		bool HaveReverbPanZ = false;
392 		bool HaveEchoTime = false;
393 		bool HaveEchoDepth = false;
394 		bool HaveModulationTime = false;
395 		bool HaveModulationDepth = false;
396 		bool HaveAirAbsorptionHF = false;
397 		bool HaveHFReference = false;
398 		bool HaveLFReference = false;
399 		bool HaveRoomRolloffFactor = false;
400 		bool HaveDiffusion = false;
401 		bool HaveDensity = false;
402 		int HaveFlags = 0;
403 
404 		sc->Expect("{");
405 		while (!sc->Check("}"))
406 		{
407 			if (sc->Check("Environment"))
408 			{
409 				sc->ExpectNumber();
410 				if (sc->Number < 0 || sc->Number > 25)
411 				{
412 					sc->Error("Environment number out of range");
413 				}
414 				Prop.Environment = sc->Number;
415 				HaveEnvironment = true;
416 			}
417 			else if (sc->Check("EnvironmentSize"))
418 			{
419 				DoFloat(sc, Prop.EnvironmentSize, 1.0, 100.0);
420 				HaveEnvironmentSize = true;
421 			}
422 			else if (sc->Check("EnvironmentDiffusion"))
423 			{
424 				DoFloat(sc, Prop.EnvironmentDiffusion, 0.0, 1.0);
425 				HaveEnvironmentDiffusion = true;
426 			}
427 			else if (sc->Check("Room"))
428 			{
429 				DoInt(sc, Prop.Room, -10000, 0);
430 				HaveRoom = true;
431 			}
432 			else if (sc->Check("RoomHF"))
433 			{
434 				DoInt(sc, Prop.RoomHF, -10000, 0);
435 				HaveRoomHF = true;
436 			}
437 			else if (sc->Check("RoomLF"))
438 			{
439 				DoInt(sc, Prop.RoomLF, -10000, 0);
440 				HaveRoomLF = true;
441 			}
442 			else if (sc->Check("DecayTime"))
443 			{
444 				DoFloat(sc, Prop.DecayTime, 0.1, 20.0);
445 				HaveDecayTime = true;
446 			}
447 			else if (sc->Check("DecayHFRatio"))
448 			{
449 				DoFloat(sc, Prop.DecayHFRatio, 0.1, 2.0);
450 				HaveDecayHFRatio = true;
451 			}
452 			else if (sc->Check("DecayLFRatio"))
453 			{
454 				DoFloat(sc, Prop.DecayLFRatio, 0.1, 2.0);
455 				HaveDecayLFRatio = true;
456 			}
457 			else if (sc->Check("Reflections"))
458 			{
459 				DoInt(sc, Prop.Reflections, -10000, 1000);
460 				HaveReflections = true;
461 			}
462 			else if (sc->Check("ReflectionsDelay"))
463 			{
464 				DoFloat(sc, Prop.ReflectionsDelay, 0.0, 0.3);
465 				HaveReflectionsDelay = true;
466 			}
467 			else if (sc->Check("ReflectionsPanX"))
468 			{
469 				DoFloat(sc, Prop.ReflectionsPanX, -2000.0, 2000.0);
470 				HaveReflectionsPanX = true;
471 			}
472 			else if (sc->Check("ReflectionsPanY"))
473 			{
474 				DoFloat(sc, Prop.ReflectionsPanY, -2000.0, 2000.0);
475 				HaveReflectionsPanY = true;
476 			}
477 			else if (sc->Check("ReflectionsPanZ"))
478 			{
479 				DoFloat(sc, Prop.ReflectionsPanZ, -2000.0, 2000.0);
480 				HaveReflectionsPanZ = true;
481 			}
482 			else if (sc->Check("Reverb"))
483 			{
484 				DoInt(sc, Prop.Reverb, -10000, 2000);
485 				HaveReverb = true;
486 			}
487 			else if (sc->Check("ReverbDelay"))
488 			{
489 				DoFloat(sc, Prop.ReverbDelay, 0.0, 0.1);
490 				HaveReverbDelay = true;
491 			}
492 			else if (sc->Check("ReverbPanX"))
493 			{
494 				DoFloat(sc, Prop.ReverbPanX, -2000.0, 2000.0);
495 				HaveReverbPanX = true;
496 			}
497 			else if (sc->Check("ReverbPanY"))
498 			{
499 				DoFloat(sc, Prop.ReverbPanY, -2000.0, 2000.0);
500 				HaveReverbPanY = true;
501 			}
502 			else if (sc->Check("ReverbPanZ"))
503 			{
504 				DoFloat(sc, Prop.ReverbPanZ, -2000.0, 2000.0);
505 				HaveReverbPanZ = true;
506 			}
507 			else if (sc->Check("EchoTime"))
508 			{
509 				DoFloat(sc, Prop.EchoTime, 0.075, 0.25);
510 				HaveEchoTime = true;
511 			}
512 			else if (sc->Check("EchoDepth"))
513 			{
514 				DoFloat(sc, Prop.EchoDepth, 0.0, 1.0);
515 				HaveEchoDepth = true;
516 			}
517 			else if (sc->Check("ModulationTime"))
518 			{
519 				DoFloat(sc, Prop.ModulationTime, 0.04, 4.0);
520 				HaveModulationTime = true;
521 			}
522 			else if (sc->Check("ModulationDepth"))
523 			{
524 				DoFloat(sc, Prop.ModulationDepth, 0.0, 1.0);
525 				HaveModulationDepth = true;
526 			}
527 			else if (sc->Check("AirAbsorptionHF"))
528 			{
529 				DoFloat(sc, Prop.AirAbsorptionHF, -100.0, 0.0);
530 				HaveAirAbsorptionHF = true;
531 			}
532 			else if (sc->Check("HFReference"))
533 			{
534 				DoFloat(sc, Prop.HFReference, 1000.0, 20000.0);
535 				HaveHFReference = true;
536 			}
537 			else if (sc->Check("LFReference"))
538 			{
539 				DoFloat(sc, Prop.LFReference, 20.0, 1000.0);
540 				HaveLFReference = true;
541 			}
542 			else if (sc->Check("RoomRolloffFactor"))
543 			{
544 				DoFloat(sc, Prop.RoomRolloffFactor, 0.0, 10.0);
545 				HaveRoomRolloffFactor = true;
546 			}
547 			else if (sc->Check("Diffusion"))
548 			{
549 				DoFloat(sc, Prop.Diffusion, 0.0, 100.0);
550 				HaveDiffusion = true;
551 			}
552 			else if (sc->Check("Density"))
553 			{
554 				DoFloat(sc, Prop.Density, 0.0, 100.0);
555 				HaveDensity = true;
556 			}
557 			else if (sc->Check("bReflectionsScale"))
558 			{
559 				DoBool(sc, Prop.Flags, REVERBF_ReflectionsScale);
560 				HaveFlags |= REVERBF_ReflectionsScale;
561 			}
562 			else if (sc->Check("bReflectionsDelayScale"))
563 			{
564 				DoBool(sc, Prop.Flags, REVERBF_ReflectionsDelayScale);
565 				HaveFlags |= REVERBF_ReflectionsDelayScale;
566 			}
567 			else if (sc->Check("bDecayTimeScale"))
568 			{
569 				DoBool(sc, Prop.Flags, REVERBF_DecayTimeScale);
570 				HaveFlags |= REVERBF_DecayTimeScale;
571 			}
572 			else if (sc->Check("bDecayHFLimit"))
573 			{
574 				DoBool(sc, Prop.Flags, REVERBF_DecayHFLimit);
575 				HaveFlags |= REVERBF_DecayHFLimit;
576 			}
577 			else if (sc->Check("bReverbScale"))
578 			{
579 				DoBool(sc, Prop.Flags, REVERBF_ReverbScale);
580 				HaveFlags |= REVERBF_ReverbScale;
581 			}
582 			else if (sc->Check("bReverbDelayScale"))
583 			{
584 				DoBool(sc, Prop.Flags, REVERBF_ReverbDelayScale);
585 				HaveFlags |= REVERBF_ReverbDelayScale;
586 			}
587 			else if (sc->Check("bEchoTimeScale"))
588 			{
589 				DoBool(sc, Prop.Flags, REVERBF_EchoTimeScale);
590 				HaveFlags |= REVERBF_EchoTimeScale;
591 			}
592 			else if (sc->Check("bModulationTimeScale"))
593 			{
594 				DoBool(sc, Prop.Flags, REVERBF_ModulationTimeScale);
595 				HaveFlags |= REVERBF_ModulationTimeScale;
596 			}
597 			else
598 			{
599 				sc->Error("Bad syntax");
600 			}
601 		}
602 
603 		if (!HaveEnvironment)
604 		{
605 			sc->Error(va("Environment %s is mising an Environment field", *Name));
606 		}
607 
608 		const VReverbProperties& Def = DefaultEnvironments[Prop.Environment]->Props;
609 		if (!HaveEnvironmentSize)
610 		{
611 			Prop.EnvironmentSize = Def.EnvironmentSize;
612 		}
613 		if (!HaveEnvironmentDiffusion)
614 		{
615 			Prop.EnvironmentDiffusion = Def.EnvironmentDiffusion;
616 		}
617 		if (!HaveRoom)
618 		{
619 			Prop.Room = Def.Room;
620 		}
621 		if (!HaveRoomHF)
622 		{
623 			Prop.RoomHF = Def.RoomHF;
624 		}
625 		if (!HaveRoomLF)
626 		{
627 			Prop.RoomLF = Def.RoomLF;
628 		}
629 		if (!HaveDecayTime)
630 		{
631 			Prop.DecayTime = Def.DecayTime;
632 		}
633 		if (!HaveDecayHFRatio)
634 		{
635 			Prop.DecayHFRatio = Def.DecayHFRatio;
636 		}
637 		if (!HaveDecayLFRatio)
638 		{
639 			Prop.DecayLFRatio = Def.DecayLFRatio;
640 		}
641 		if (!HaveReflections)
642 		{
643 			Prop.Reflections = Def.Reflections;
644 		}
645 		if (!HaveReflectionsDelay)
646 		{
647 			Prop.ReflectionsDelay = Def.ReflectionsDelay;
648 		}
649 		if (!HaveReflectionsPanX)
650 		{
651 			Prop.ReflectionsPanX = Def.ReflectionsPanX;
652 		}
653 		if (!HaveReflectionsPanY)
654 		{
655 			Prop.ReflectionsPanY = Def.ReflectionsPanY;
656 		}
657 		if (!HaveReflectionsPanZ)
658 		{
659 			Prop.ReflectionsPanZ = Def.ReflectionsPanZ;
660 		}
661 		if (!HaveReverb)
662 		{
663 			Prop.Reverb = Def.Reverb;
664 		}
665 		if (!HaveReverbDelay)
666 		{
667 			Prop.ReverbDelay = Def.ReverbDelay;
668 		}
669 		if (!HaveReverbPanX)
670 		{
671 			Prop.ReverbPanX = Def.ReverbPanX;
672 		}
673 		if (!HaveReverbPanY)
674 		{
675 			Prop.ReverbPanY = Def.ReverbPanY;
676 		}
677 		if (!HaveReverbPanZ)
678 		{
679 			Prop.ReverbPanZ = Def.ReverbPanZ;
680 		}
681 		if (!HaveEchoTime)
682 		{
683 			Prop.EchoTime = Def.EchoTime;
684 		}
685 		if (!HaveEchoDepth)
686 		{
687 			Prop.EchoDepth = Def.EchoDepth;
688 		}
689 		if (!HaveModulationTime)
690 		{
691 			Prop.ModulationTime = Def.ModulationTime;
692 		}
693 		if (!HaveModulationDepth)
694 		{
695 			Prop.ModulationDepth = Def.ModulationDepth;
696 		}
697 		if (!HaveAirAbsorptionHF)
698 		{
699 			Prop.AirAbsorptionHF = Def.AirAbsorptionHF;
700 		}
701 		if (!HaveHFReference)
702 		{
703 			Prop.HFReference = Def.HFReference;
704 		}
705 		if (!HaveLFReference)
706 		{
707 			Prop.LFReference = Def.LFReference;
708 		}
709 		if (!HaveRoomRolloffFactor)
710 		{
711 			Prop.RoomRolloffFactor = Def.RoomRolloffFactor;
712 		}
713 		if (!HaveDiffusion)
714 		{
715 			Prop.Diffusion = Def.Diffusion;
716 		}
717 		if (!HaveDensity)
718 		{
719 			Prop.Density = Def.Density;
720 		}
721 		Prop.Flags |= Def.Flags & ~HaveFlags;
722 
723 		VReverbInfo* NewEnv = new VReverbInfo;
724 		char* NewName = new char[Name.Length() + 1];
725 		strcpy(NewName, *Name);
726 		NewEnv->Next = NULL;
727 		NewEnv->Name = NewName;
728 		NewEnv->Id = (Id1 << 8) | Id2;
729 		NewEnv->Builtin = false;
730 		NewEnv->Props = Prop;
731 
732 		//	Find a slot for the new environment.
733 		VReverbInfo* Check = Environments;
734 		VReverbInfo** Ptr = &Environments;
735 		while (Check && Check->Id < NewEnv->Id)
736 		{
737 			Ptr = &Check->Next;
738 			Check = Check->Next;
739 		}
740 
741 		//	Check for redeclared environment.
742 		if (Check && Check->Id == NewEnv->Id)
743 		{
744 			//	Don't allow replacements of builtin environments.
745 			if (!Check->Builtin)
746 			{
747 				NewEnv->Next = Check->Next;
748 				*Ptr = NewEnv;
749 				delete[] const_cast<char*>(Check->Name);
750 				Check->Name = NULL;
751 				delete Check;
752 				Check = NULL;
753 			}
754 			else
755 			{
756 				delete[] NewName;
757 				delete NewEnv;
758 				NewEnv = NULL;
759 			}
760 		}
761 		else
762 		{
763 			NewEnv->Next = Check;
764 			*Ptr = NewEnv;
765 		}
766 	}
767 	delete sc;
768 	sc = NULL;
769 	unguard;
770 }
771 
772 //==========================================================================
773 //
774 //	VSoundManager::FindEnvironment
775 //
776 //==========================================================================
777 
FindEnvironment(int Id)778 VReverbInfo* VSoundManager::FindEnvironment(int Id)
779 {
780 	guard(VSoundManager::FindEnvironment);
781 	VReverbInfo* Check = Environments;
782 	while (Check->Next && Check->Next->Id <= Id)
783 	{
784 		Check = Check->Next;
785 	}
786 	return Check;
787 	unguard;
788 }
789