1 // MODULE FOR SOUND SYSTEM
2
3 #include "Directories.h"
4 #include "Sound_Control.h"
5 #include "SoundMan.h"
6 #include "Overhead.h"
7 #include "Isometric_Utils.h"
8 #include "RenderWorld.h"
9 #include <math.h>
10
11
12 #define SOUND_FAR_VOLUME_MOD 25
13
14 static UINT32 guiSpeechVolume = MIDVOLUME;
15 static UINT32 guiSoundEffectsVolume = MIDVOLUME;
16
17 static char const* const szSoundEffects[NUM_SAMPLES] =
18 {
19 SOUNDSDIR "/ricochet 01.wav", // 0
20 SOUNDSDIR "/ricochet 02.wav", // 1
21 SOUNDSDIR "/ricochet 01.wav", // 2
22 SOUNDSDIR "/ricochet 02.wav", // 3
23 SOUNDSDIR "/ricochet 01.wav", // 4
24 SOUNDSDIR "/ricochet 02.wav", // 5
25 SOUNDSDIR "/ricochet 01.wav", // 6
26 SOUNDSDIR "/ricochet 02.wav", // 7
27 SOUNDSDIR "/dirt impact 01.wav", // 8
28 SOUNDSDIR "/dirt impact 01.wav", // 9
29 SOUNDSDIR "/knife hit ground.wav", // 10
30 SOUNDSDIR "/fall to knees 01.wav", // 11
31 SOUNDSDIR "/fall to knees 02.wav", // 12
32 SOUNDSDIR "/knees to dirt 01.wav", // 13
33 SOUNDSDIR "/knees to dirt 02.wav", // 14
34 SOUNDSDIR "/knees to dirt 03.wav", // 15
35 SOUNDSDIR "/heavy fall 01.wav", // 16
36 SOUNDSDIR "/body_splat.wav", // 17
37 SOUNDSDIR "/glass_break1.wav", // 18
38 SOUNDSDIR "/glass_break2.wav", // 19
39 SOUNDSDIR "/door open 01.wav", // 20
40 SOUNDSDIR "/door open 02.wav", // 21
41 SOUNDSDIR "/door open 03.wav", // 22
42 SOUNDSDIR "/door close 01.wav", // 23
43 SOUNDSDIR "/door close 02.wav", // 24
44 SOUNDSDIR "/unlock lock.wav", // 25
45 SOUNDSDIR "/kickin lock.wav", // 26
46 SOUNDSDIR "/break lock.wav", // 27
47 SOUNDSDIR "/picking lock.wav", // 28
48 SOUNDSDIR "/garage door open.wav", // 29
49 SOUNDSDIR "/garage door close.wav", // 30
50 NULL, // 31
51 NULL, // 32
52 NULL, // 33
53 NULL, // 34
54 SOUNDSDIR "/curtains door open.wav", // 35
55 SOUNDSDIR "/curtains door close.wav", // 36
56 SOUNDSDIR "/metal door open.wav", // 37
57 SOUNDSDIR "/metal door close.wav", // 38
58 SOUNDSDIR "/ftp gravel 01.wav", // 39
59 SOUNDSDIR "/ftp gravel 02.wav", // 40
60 SOUNDSDIR "/ftp gravel 03.wav", // 41
61 SOUNDSDIR "/ftp gravel 04.wav", // 42
62 SOUNDSDIR "/ftp gritty 01.wav", // 43
63 SOUNDSDIR "/ftp gritty 02.wav", // 44
64 SOUNDSDIR "/ftp gritty 03.wav", // 45
65 SOUNDSDIR "/ftp gritty 04.wav", // 46
66 SOUNDSDIR "/ftp leaves 01.wav", // 47
67 SOUNDSDIR "/ftp leaves 02.wav", // 48
68 SOUNDSDIR "/ftp leaves 03.wav", // 49
69 SOUNDSDIR "/ftp leaves 04.wav", // 50
70 SOUNDSDIR "/crawling 01.wav", // 51
71 SOUNDSDIR "/crawling 02.wav", // 52
72 SOUNDSDIR "/crawling 03.wav", // 53
73 SOUNDSDIR "/crawling 04.wav", // 54
74 SOUNDSDIR "/beep2.wav", // 55
75 SOUNDSDIR "/endturn.wav", // 56
76 SOUNDSDIR "/ja2 death hit.wav", // 57
77 SOUNDSDIR "/doorcr.wav", // 58
78 SOUNDSDIR "/head exploding 01.wav", // 59
79 SOUNDSDIR "/body exploding.wav", // 60
80 SOUNDSDIR "/explode1.wav", // 61
81 SOUNDSDIR "/crow exploding.wav", // 62
82 SOUNDSDIR "/small explosion 01.wav", // 63
83 SOUNDSDIR "/heli1.wav", // 64
84 SOUNDSDIR "/bullet impact 01.wav", // 65
85 SOUNDSDIR "/bullet impact 02.wav", // 66
86 SOUNDSDIR "/bullet impact 02.wav", // 67
87 STSOUNDSDIR "/blah.wav", // 68 URE ATTACK
88 SOUNDSDIR "/step into water.wav", // 69
89 SOUNDSDIR "/splash from shallow to deep.wav", // 70
90 SOUNDSDIR "/cow hit.wav", // 71 COW HIT
91 SOUNDSDIR "/cow die.wav", // 72 COW DIE
92 SOUNDSDIR "/line 02 fx.wav", // 73
93 SOUNDSDIR "/line 01 fx.wav", // 74
94 SOUNDSDIR "/line 03 fx.wav", // 75
95 SOUNDSDIR "/cave collapsing.wav", // 76 CAVE_COLLAPSE
96 SOUNDSDIR "/raid whistle.wav", // 77 RAID
97 SOUNDSDIR "/raid ambient.wav", // 78
98 SOUNDSDIR "/raid dive.wav", // 79
99 SOUNDSDIR "/raid dive.wav", // 80
100 SOUNDSDIR "/raid whistle.wav", // 81 RAID
101 SOUNDSDIR "/driving 01.wav", // 82 DRIVING
102 SOUNDSDIR "/engine start.wav", // 83 ON
103 SOUNDSDIR "/engine off.wav", // 84 OFF
104 SOUNDSDIR "/into vehicle.wav", // 85 INTO
105 SOUNDSDIR "/weapons/dry fire 1.wav", // 86 Dry fire sound ( for gun jam )
106 SOUNDSDIR "/wood impact 01a.wav", // 87 S_WOOD_IMPACT1
107 SOUNDSDIR "/wood impact 01b.wav", // 88
108 SOUNDSDIR "/wood impact 01a.wav", // 89
109 SOUNDSDIR "/porcelain impact.wav", // 90
110 SOUNDSDIR "/tire impact 01.wav", // 91
111 SOUNDSDIR "/stone impact 01.wav", // 92
112 SOUNDSDIR "/water impact 01.wav", // 93
113 SOUNDSDIR "/veg impact 01.wav", // 94
114 SOUNDSDIR "/metal hit 01.wav", // 95 S_METAL_HIT1
115 SOUNDSDIR "/metal hit 01.wav", // 96
116 SOUNDSDIR "/metal hit 01.wav", // 97
117 SOUNDSDIR "/slap_impact.wav", // 98
118 SOUNDSDIR "/weapons/revolver reload.wav", // 99 REVOLVER
119 SOUNDSDIR "/weapons/pistol reload.wav", // 100 PISTOL
120 SOUNDSDIR "/weapons/smg reload.wav", // 101 SMG
121 SOUNDSDIR "/weapons/rifle reload.wav", // 102 RIFLE
122 SOUNDSDIR "/weapons/shotgun reload.wav", // 103 SHOTGUN
123 SOUNDSDIR "/weapons/lmg reload.wav", // 104 LMG
124 SOUNDSDIR "/weapons/revolver lnl.wav", // 105 REVOLVER
125 SOUNDSDIR "/weapons/pistol lnl.wav", // 106 PISTOL
126 SOUNDSDIR "/weapons/smg lnl.wav", // 107 SMG
127 SOUNDSDIR "/weapons/rifle lnl.wav", // 108 RIFLE
128 SOUNDSDIR "/weapons/shotgun lnl.wav", // 109 SHOTGUN
129 SOUNDSDIR "/weapons/lmg lnl.wav", // 110 LMG
130 NULL, // 111
131 NULL, // 112
132 NULL, // 113
133 NULL, // 114
134 NULL, // 115
135 NULL, // 116
136 NULL, // 117
137 NULL, // 118
138 NULL, // 119
139 NULL, // 120
140 NULL, // 121
141 NULL, // 122
142 NULL, // 123
143 NULL, // 124
144 NULL, // 125
145 NULL, // 126
146 NULL, // 127
147 NULL, // 128
148 NULL, // 129
149 NULL, // 130
150 NULL, // 131
151 NULL, // 132
152 NULL, // 133
153 NULL, // 134
154 NULL, // 135
155 NULL, // 136
156 NULL, // 137
157 NULL, // 138
158 NULL, // 139
159 NULL, // 140
160 NULL, // 141
161 NULL, // 142
162 NULL, // 143
163 NULL, // 144
164 NULL, // 145
165 NULL, // 146
166 NULL, // 147
167 NULL, // 148
168 NULL, // 149
169 NULL, // 150
170 NULL, // 151
171 NULL, // 152
172 NULL, // 153
173 NULL, // 154
174 NULL, // 155
175 SOUNDSDIR "/weapons/silencer 02.wav", // 156
176 SOUNDSDIR "/weapons/silencer 03.wav", // 157
177 SOUNDSDIR "/swoosh 01.wav", // 158
178 SOUNDSDIR "/swoosh 03.wav", // 159
179 SOUNDSDIR "/swoosh 05.wav", // 160
180 SOUNDSDIR "/swoosh 06.wav", // 161
181 SOUNDSDIR "/swoosh 11.wav", // 162
182 SOUNDSDIR "/swoosh 14.wav", // 163
183 SOUNDSDIR "/adult fall 01.wav", // 164
184 SOUNDSDIR "/adult step 01.wav", // 165
185 SOUNDSDIR "/adult step 02.wav", // 166
186 SOUNDSDIR "/adult swipe 01.wav", // 167
187 SOUNDSDIR "/eating_flesh 01.wav", // 168
188 SOUNDSDIR "/adult crippled.wav", // 169
189 SOUNDSDIR "/adult dying part 1.wav", // 170
190 SOUNDSDIR "/adult dying part 2.wav", // 171
191 SOUNDSDIR "/adult lunge 01.wav", // 172
192 SOUNDSDIR "/adult smells threat.wav", // 173
193 SOUNDSDIR "/adult smells prey.wav", // 174
194 SOUNDSDIR "/adult spit.wav", // 175
195 SOUNDSDIR "/baby dying 01.wav", // 176
196 SOUNDSDIR "/baby dragging 01.wav", // 177
197 SOUNDSDIR "/baby shriek 01.wav", // 178
198 NULL, // 179
199 SOUNDSDIR "/larvae movement 01.wav", // 180
200 SOUNDSDIR "/larvae rupture 01.wav", // 181
201 SOUNDSDIR "/queen shriek 01.wav", // 182
202 SOUNDSDIR "/queen dying 01.wav", // 183
203 SOUNDSDIR "/queen enraged attack.wav", // 184
204 SOUNDSDIR "/queen rupturing.wav", // 185
205 SOUNDSDIR "/queen crippled.wav", // 186
206 SOUNDSDIR "/queen smells threat.wav", // 187
207 SOUNDSDIR "/queen whip attack.wav", // 188
208 SOUNDSDIR "/rock hit 01.wav", // 189
209 SOUNDSDIR "/rock hit 02.wav", // 190
210 SOUNDSDIR "/scratch.wav", // 191
211 SOUNDSDIR "/armpit.wav", // 192
212 SOUNDSDIR "/cracking back.wav", // 193
213 SOUNDSDIR "/weapons/auto resolve composite 02 (8-22).wav", // 194 The FF sound in autoresolve interface
214 SOUNDSDIR "/email alert 01.wav", // 195
215 SOUNDSDIR "/entering text 02.wav", // 196
216 SOUNDSDIR "/removing text 02.wav", // 197
217 SOUNDSDIR "/computer beep 01 in.wav", // 198
218 SOUNDSDIR "/computer beep 01 out.wav", // 199
219 SOUNDSDIR "/computer switch 01 in.wav", // 200
220 SOUNDSDIR "/computer switch 01 out.wav", // 201
221 SOUNDSDIR "/very small switch 01 in.wav", // 202
222 SOUNDSDIR "/very small switch 01 out.wav", // 203
223 SOUNDSDIR "/very small switch 02 in.wav", // 204
224 SOUNDSDIR "/very small switch 02 out.wav", // 205
225 SOUNDSDIR "/small switch 01 in.wav", // 206
226 SOUNDSDIR "/small switch 01 out.wav", // 207
227 SOUNDSDIR "/small switch 02 in.wav", // 208
228 SOUNDSDIR "/small switch 02 out.wav", // 209
229 SOUNDSDIR "/small switch 03 in.wav", // 210
230 SOUNDSDIR "/small switch 03 out.wav", // 211
231 SOUNDSDIR "/big switch 03 in.wav", // 212
232 SOUNDSDIR "/big switch 03 out.wav", // 213
233 SOUNDSDIR "/alarm.wav", // 214
234 SOUNDSDIR "/fight bell.wav", // 215
235 NULL, // 216
236 SOUNDSDIR "/attachment.wav", // 217
237 SOUNDSDIR "/ceramic armor insert.wav", // 218
238 SOUNDSDIR "/detonator beep.wav", // 219
239 SOUNDSDIR "/grab roof.wav", // 220
240 SOUNDSDIR "/land on roof.wav", // 221
241 NULL, // 222
242 NULL, // 223
243 NULL, // 224
244 SOUNDSDIR "/fridge door open.wav", // 225
245 SOUNDSDIR "/fridge door close.wav", // 226
246 SOUNDSDIR "/fire 03 loop.wav", // 227
247 SOUNDSDIR "/glass_crack.wav", // 228
248 SOUNDSDIR "/spit ricochet.wav", // 229
249 SOUNDSDIR "/tiger hit.wav", // 230
250 SOUNDSDIR "/bloodcat dying 02.wav", // 231
251 SOUNDSDIR "/slap.wav", // 232
252 SOUNDSDIR "/robot beep.wav", // 233
253 SOUNDSDIR "/electricity.wav", // 234
254 SOUNDSDIR "/swimming 01.wav", // 235
255 SOUNDSDIR "/swimming 02.wav", // 236
256 SOUNDSDIR "/key failure.wav", // 237
257 SOUNDSDIR "/target cursor.wav", // 238
258 SOUNDSDIR "/statue open.wav", // 239
259 SOUNDSDIR "/remote activate.wav", // 240
260 SOUNDSDIR "/wirecutters.wav", // 241
261 SOUNDSDIR "/drink from canteen.wav", // 242
262 SOUNDSDIR "/bloodcat attack.wav", // 243
263 SOUNDSDIR "/bloodcat loud roar.wav", // 244
264 SOUNDSDIR "/robot greeting.wav", // 245
265 SOUNDSDIR "/robot death.wav", // 246
266 SOUNDSDIR "/gas grenade explode.wav", // 247
267 SOUNDSDIR "/air escaping.wav", // 248
268 SOUNDSDIR "/drawer open.wav", // 249
269 SOUNDSDIR "/drawer close.wav", // 250
270 SOUNDSDIR "/locker door open.wav", // 251
271 SOUNDSDIR "/locker door close.wav", // 252
272 SOUNDSDIR "/wooden box open.wav", // 253
273 SOUNDSDIR "/wooden box close.wav", // 254
274 SOUNDSDIR "/robot stop moving.wav", // 255
275 SOUNDSDIR "/water movement 01.wav", // 256
276 SOUNDSDIR "/water movement 02.wav", // 257
277 SOUNDSDIR "/water movement 03.wav", // 258
278 SOUNDSDIR "/water movement 04.wav", // 259
279 SOUNDSDIR "/prone to crouch.wav", // 260
280 SOUNDSDIR "/crouch to prone.wav", // 261
281 SOUNDSDIR "/crouch to stand.wav", // 262
282 SOUNDSDIR "/stand to crouch.wav", // 263
283 SOUNDSDIR "/picking something up.wav", // 264
284 SOUNDSDIR "/cow falling.wav", // 265
285 SOUNDSDIR "/bloodcat_growl_01.wav", // 266
286 SOUNDSDIR "/bloodcat_growl_02.wav", // 267
287 SOUNDSDIR "/bloodcat_growl_03.wav", // 268
288 SOUNDSDIR "/bloodcat_growl_04.wav", // 269
289 SOUNDSDIR "/spit ricochet.wav", // 270
290 SOUNDSDIR "/adult crippled.wav", // 271
291 SOUNDSDIR "/death disintegration.wav", // 272
292 SOUNDSDIR "/queen ambience.wav", // 273
293 SOUNDSDIR "/alien impact.wav", // 274
294 SOUNDSDIR "/crow pecking flesh 01.wav", // 275
295 SOUNDSDIR "/crow fly.wav", // 276
296 SOUNDSDIR "/slap 02.wav", // 277
297 SOUNDSDIR "/setting up mortar.wav", // 278
298 SOUNDSDIR "/mortar whistle.wav", // 279
299 SOUNDSDIR "/load mortar.wav", // 280
300 SOUNDSDIR "/tank turret a.wav", // 281
301 SOUNDSDIR "/tank turret b.wav", // 282
302 SOUNDSDIR "/cow falling b.wav", // 283
303 SOUNDSDIR "/stab into flesh.wav", // 284
304 SOUNDSDIR "/explosion 10.wav", // 285
305 SOUNDSDIR "/explosion 12.wav", // 286
306 SOUNDSDIR "/drink from canteen male.wav", // 287
307 SOUNDSDIR "/x ray activated.wav", // 288
308 SOUNDSDIR "/catch object.wav", // 289
309 SOUNDSDIR "/fence open.wav", // 290
310 };
311
312 static char const* const szAmbientEffects[NUM_AMBIENTS] =
313 {
314 SOUNDSDIR "/storm1.wav",
315 SOUNDSDIR "/storm2.wav",
316 SOUNDSDIR "/rain_loop_22k.wav",
317 SOUNDSDIR "/bird1-22k.wav",
318 SOUNDSDIR "/bird3-22k.wav",
319 SOUNDSDIR "/crickety_loop.wav",
320 SOUNDSDIR "/crickety_loop2.wav",
321 SOUNDSDIR "/cricket1.wav",
322 SOUNDSDIR "/cricket2.wav",
323 SOUNDSDIR "/owl1.wav",
324 SOUNDSDIR "/owl2.wav",
325 SOUNDSDIR "/owl3.wav",
326 SOUNDSDIR "/night_bird1.wav",
327 SOUNDSDIR "/night_bird3.wav"
328 };
329
ShutdownJA2Sound(void)330 void ShutdownJA2Sound(void)
331 {
332 SoundStopAll();
333 }
334
335
getSoundSample(SoundID soundId)336 const char * getSoundSample(SoundID soundId)
337 {
338 if(soundId == -1) {
339 return "";
340 }
341 else
342 {
343 return szSoundEffects[soundId];
344 }
345 }
346
PlayJA2Sample(SoundID const usNum,UINT32 const ubVolume,UINT32 const ubLoops,UINT32 const uiPan)347 UINT32 PlayJA2Sample(SoundID const usNum, UINT32 const ubVolume, UINT32 const ubLoops, UINT32 const uiPan)
348 {
349 UINT32 const vol = CalculateSoundEffectsVolume(ubVolume);
350 return SoundPlay(szSoundEffects[usNum], vol, uiPan, ubLoops, NULL, NULL);
351 }
352
353
PlayJA2Sample(const char * sample,UINT32 const ubVolume,UINT32 const ubLoops,UINT32 const uiPan)354 UINT32 PlayJA2Sample(const char *sample, UINT32 const ubVolume, UINT32 const ubLoops, UINT32 const uiPan)
355 {
356 if((sample != NULL) && strcmp(sample, ""))
357 {
358 UINT32 const vol = CalculateSoundEffectsVolume(ubVolume);
359 return SoundPlay(sample, vol, uiPan, ubLoops, NULL, NULL);
360 }
361 return SOUND_ERROR;
362 }
363
364
PlayJA2StreamingSample(SoundID const usNum,UINT32 const ubVolume,UINT32 const ubLoops,UINT32 const uiPan)365 UINT32 PlayJA2StreamingSample(SoundID const usNum, UINT32 const ubVolume, UINT32 const ubLoops, UINT32 const uiPan)
366 {
367 UINT32 const vol = CalculateSoundEffectsVolume(ubVolume);
368 return SoundPlay(szSoundEffects[usNum], vol, uiPan, ubLoops, NULL, NULL);
369 }
370
371
PlayJA2SampleFromFile(char const * const szFileName,UINT32 const ubVolume,UINT32 const ubLoops,UINT32 const uiPan)372 UINT32 PlayJA2SampleFromFile(char const* const szFileName, UINT32 const ubVolume, UINT32 const ubLoops, UINT32 const uiPan)
373 {
374 // does the same thing as PlayJA2Sound, but one only has to pass the filename, not the index of the sound array
375 UINT32 const vol = CalculateSoundEffectsVolume(ubVolume);
376 return SoundPlay(szFileName, vol, uiPan, ubLoops, NULL, NULL);
377 }
378
379
PlayJA2StreamingSampleFromFile(char const * const szFileName,UINT32 const ubVolume,UINT32 const ubLoops,UINT32 const uiPan,SOUND_STOP_CALLBACK const EndsCallback)380 UINT32 PlayJA2StreamingSampleFromFile(char const* const szFileName, UINT32 const ubVolume, UINT32 const ubLoops, UINT32 const uiPan, SOUND_STOP_CALLBACK const EndsCallback)
381 {
382 // does the same thing as PlayJA2Sound, but one only has to pass the filename, not the index of the sound array
383 UINT32 const vol = CalculateSoundEffectsVolume(ubVolume);
384 return SoundPlay(szFileName, vol, uiPan, ubLoops, EndsCallback, NULL);
385 }
386
387
PlayJA2Ambient(AmbientSoundID const usNum,UINT32 const ubVolume,UINT32 const ubLoops)388 UINT32 PlayJA2Ambient(AmbientSoundID const usNum, UINT32 const ubVolume, UINT32 const ubLoops)
389 {
390 UINT32 const vol = CalculateSoundEffectsVolume(ubVolume);
391 return SoundPlay(szAmbientEffects[usNum], vol, MIDDLEPAN, ubLoops, NULL, NULL);
392 }
393
PlayLocationJA2SampleFromFile(UINT16 const grid_no,char const * const filename,UINT32 const base_vol,UINT32 const loops)394 UINT32 PlayLocationJA2SampleFromFile(UINT16 const grid_no, char const* const filename, UINT32 const base_vol, UINT32 const loops)
395 {
396 UINT32 const vol = SoundVolume(base_vol, grid_no);
397 UINT32 const pan = SoundDir(grid_no);
398 return PlayJA2SampleFromFile(filename, vol, loops, pan);
399 }
400
401
PlayLocationJA2Sample(UINT16 const grid_no,SoundID const idx,UINT32 const base_vol,UINT32 const loops)402 UINT32 PlayLocationJA2Sample(UINT16 const grid_no, SoundID const idx, UINT32 const base_vol, UINT32 const loops)
403 {
404 UINT32 const vol = SoundVolume(base_vol, grid_no);
405 UINT32 const pan = SoundDir(grid_no);
406 return PlayJA2Sample(idx, vol, loops, pan);
407 }
408
409
PlayLocationJA2Sample(UINT16 const grid_no,const ST::string & sample,UINT32 const base_vol,UINT32 const loops)410 UINT32 PlayLocationJA2Sample(UINT16 const grid_no, const ST::string &sample, UINT32 const base_vol, UINT32 const loops)
411 {
412 UINT32 const vol = SoundVolume(base_vol, grid_no);
413 UINT32 const pan = SoundDir(grid_no);
414 return PlayJA2Sample(sample.c_str(), vol, loops, pan);
415 }
416
417
PlayLocationJA2StreamingSample(UINT16 const grid_no,SoundID const idx,UINT32 const base_vol,UINT32 const loops)418 UINT32 PlayLocationJA2StreamingSample(UINT16 const grid_no, SoundID const idx, UINT32 const base_vol, UINT32 const loops)
419 {
420 UINT32 const vol = SoundVolume(base_vol, grid_no);
421 UINT32 const pan = SoundDir(grid_no);
422 return PlayJA2StreamingSample(idx, vol, loops, pan);
423 }
424
425
PlaySoldierJA2Sample(SOLDIERTYPE const * const s,SoundID const usNum,UINT32 const base_vol,UINT32 const ubLoops,BOOLEAN const fCheck)426 UINT32 PlaySoldierJA2Sample(SOLDIERTYPE const* const s, SoundID const usNum, UINT32 const base_vol, UINT32 const ubLoops, BOOLEAN const fCheck)
427 {
428 if( !( gTacticalStatus.uiFlags & LOADING_SAVED_GAME ) )
429 {
430 // CHECK IF GUY IS ON SCREEN BEFORE PLAYING!
431 if (s->bVisible != -1 || !fCheck)
432 {
433 UINT32 const vol = SoundVolume(base_vol, s->sGridNo);
434 UINT32 const pan = SoundDir(s->sGridNo);
435 return PlayJA2Sample(usNum, CalculateSoundEffectsVolume(vol), ubLoops, pan);
436 }
437 }
438
439 return( 0 );
440 }
441
442
SetSpeechVolume(UINT32 uiNewVolume)443 void SetSpeechVolume(UINT32 uiNewVolume)
444 {
445 guiSpeechVolume = __min(uiNewVolume, MAXVOLUME);
446 }
447
448
GetSpeechVolume(void)449 UINT32 GetSpeechVolume(void)
450 {
451 return( guiSpeechVolume );
452 }
453
454
SetSoundEffectsVolume(UINT32 uiNewVolume)455 void SetSoundEffectsVolume(UINT32 uiNewVolume)
456 {
457 guiSoundEffectsVolume = __min(uiNewVolume, MAXVOLUME);
458 }
459
460
GetSoundEffectsVolume(void)461 UINT32 GetSoundEffectsVolume(void)
462 {
463 return( guiSoundEffectsVolume );
464 }
465
466
CalculateSpeechVolume(UINT32 uiVolume)467 UINT32 CalculateSpeechVolume(UINT32 uiVolume)
468 {
469 return (uiVolume * guiSpeechVolume + HIGHVOLUME / 2) / HIGHVOLUME;
470 }
471
472
CalculateSoundEffectsVolume(UINT32 uiVolume)473 UINT32 CalculateSoundEffectsVolume(UINT32 uiVolume)
474 {
475 return (uiVolume * guiSoundEffectsVolume + HIGHVOLUME / 2) / HIGHVOLUME;
476 }
477
478
479 #if 0
480 int x,dif,absDif;
481
482 // This function calculates the general LEFT / RIGHT direction of a gridno
483 // based on the middle of your screen.
484
485 x = Gridx(gridno);
486
487 dif = ScreenMiddleX - x;
488
489 if ( (absDif=abs(dif)) > 32)
490 {
491 // OK, NOT the middle.
492
493 // Is it outside the screen?
494 if (absDif > HalfWindowWidth)
495 {
496 // yes, outside...
497 if (dif > 0)
498 return(25);
499 else
500 return(102);
501 }
502 }
503 else // inside screen
504 {
505 if (dif > 0)
506 return(LEFTSIDE);
507 else
508 return(RIGHTSIDE);
509 }
510 else // hardly any difference, so sound should be played from middle
511 return(MIDDLE);
512
513 }
514 #endif
515
SoundDir(INT16 sGridNo)516 INT8 SoundDir( INT16 sGridNo )
517 {
518 INT16 sScreenX, sScreenY;
519 INT16 sMiddleX;
520 INT16 sDif, sAbsDif;
521
522 if ( sGridNo == NOWHERE )
523 {
524 return( MIDDLEPAN );
525 }
526
527 GetAbsoluteScreenXYFromMapPos(sGridNo, &sScreenX, &sScreenY);
528
529 // Get middle of where we are now....
530 sMiddleX = gsTopLeftWorldX + ( gsBottomRightWorldX - gsTopLeftWorldX ) / 2;
531
532 sDif = sMiddleX - sScreenX;
533
534 if ( ( sAbsDif = ABS( sDif ) ) > 64 )
535 {
536 // OK, NOT the middle.
537
538 // Is it outside the screen?
539 if ( sAbsDif > ( ( gsBottomRightWorldX - gsTopLeftWorldX ) / 2 ) )
540 {
541 // yes, outside...
542 if ( sDif > 0 )
543 {
544 //return( FARLEFT );
545 return( 1 );
546 }
547 else
548 {
549 //return( FARRIGHT );
550 return( 126 );
551 }
552 }
553 else // inside screen
554 {
555 if ( sDif > 0)
556 {
557 return( LEFTSIDE );
558 }
559 else
560 {
561 return( RIGHTSIDE );
562 }
563 }
564 }
565 else // hardly any difference, so sound should be played from middle
566 {
567 return(MIDDLE);
568 }
569 }
570
571
SoundVolume(INT8 bInitialVolume,INT16 sGridNo)572 INT8 SoundVolume( INT8 bInitialVolume, INT16 sGridNo )
573 {
574 INT16 sScreenX, sScreenY;
575 INT16 sMiddleX, sMiddleY;
576 INT16 sDifX, sAbsDifX;
577 INT16 sDifY, sAbsDifY;
578
579 if ( sGridNo == NOWHERE )
580 {
581 return( bInitialVolume );
582 }
583
584 GetAbsoluteScreenXYFromMapPos(sGridNo, &sScreenX, &sScreenY);
585
586 // Get middle of where we are now....
587 sMiddleX = gsTopLeftWorldX + ( gsBottomRightWorldX - gsTopLeftWorldX ) / 2;
588 sMiddleY = gsTopLeftWorldY + ( gsBottomRightWorldY - gsTopLeftWorldY ) / 2;
589
590 sDifX = sMiddleX - sScreenX;
591 sDifY = sMiddleY - sScreenY;
592
593 sAbsDifX = ABS( sDifX );
594 sAbsDifY = ABS( sDifY );
595
596 if ( sAbsDifX > 64 || sAbsDifY > 64 )
597 {
598 // OK, NOT the middle.
599
600 // Is it outside the screen?
601 if ( sAbsDifX > ( ( gsBottomRightWorldX - gsTopLeftWorldX ) / 2 ) ||
602 sAbsDifY > ( ( gsBottomRightWorldY - gsTopLeftWorldY ) / 2 ) )
603 {
604 return( __max( LOWVOLUME, ( bInitialVolume - SOUND_FAR_VOLUME_MOD ) ) );
605 }
606 }
607
608 return( bInitialVolume );
609 }
610
611
612 /////////////////////////////////////////////////////////
613 /////////
614 /////////
615 /////////////////////////////////////////////////////////
616 // Positional Ambients
617 /////////////////////////////////////////////////////////
618 #define NUM_POSITION_SOUND_EFFECT_SLOTS 10
619
620 struct POSITIONSND
621 {
622 INT16 sGridNo;
623 UINT32 uiSoundSampleID;
624 SoundID iSoundToPlay;
625 const SOLDIERTYPE* SoundSource;
626 BOOLEAN fAllocated;
627 BOOLEAN fInActive;
628 };
629
630
631 // GLOBAL FOR SMOKE LISTING
632 static POSITIONSND gPositionSndData[NUM_POSITION_SOUND_EFFECT_SLOTS];
633 static UINT32 guiNumPositionSnds = 0;
634 static BOOLEAN gfPositionSoundsActive = FALSE;
635
636
GetFreePositionSnd(void)637 static INT32 GetFreePositionSnd(void)
638 {
639 for (UINT32 i = 0; i != guiNumPositionSnds; ++i)
640 {
641 if (!gPositionSndData[i].fAllocated) return (INT32)i;
642 }
643
644 if (guiNumPositionSnds < NUM_POSITION_SOUND_EFFECT_SLOTS)
645 return (INT32)guiNumPositionSnds++;
646
647 return -1;
648 }
649
650
RecountPositionSnds(void)651 static void RecountPositionSnds(void)
652 {
653 INT32 uiCount;
654
655 for(uiCount=guiNumPositionSnds-1; (uiCount >=0) ; uiCount--)
656 {
657 if( ( gPositionSndData[uiCount].fAllocated ) )
658 {
659 guiNumPositionSnds=(UINT32)(uiCount+1);
660 break;
661 }
662 }
663 }
664
665
NewPositionSnd(INT16 const sGridNo,SOLDIERTYPE const * const SoundSource,SoundID const iSoundToPlay)666 INT32 NewPositionSnd(INT16 const sGridNo, SOLDIERTYPE const* const SoundSource, SoundID const iSoundToPlay)
667 {
668 INT32 const idx = GetFreePositionSnd();
669 if (idx == -1) return -1;
670
671 POSITIONSND& p = gPositionSndData[idx];
672 p = POSITIONSND{};
673 p.fInActive = !gfPositionSoundsActive;
674 p.sGridNo = sGridNo;
675 p.SoundSource = SoundSource;
676 p.fAllocated = TRUE;
677 p.iSoundToPlay = iSoundToPlay;
678 p.uiSoundSampleID = NO_SAMPLE;
679
680 return idx;
681 }
682
DeletePositionSnd(INT32 iPositionSndIndex)683 void DeletePositionSnd( INT32 iPositionSndIndex )
684 {
685 POSITIONSND *pPositionSnd;
686
687 pPositionSnd = &gPositionSndData[ iPositionSndIndex ];
688
689 if ( pPositionSnd->fAllocated )
690 {
691 // Turn inactive first...
692 pPositionSnd->fInActive = TRUE;
693
694 // End sound...
695 if ( pPositionSnd->uiSoundSampleID != NO_SAMPLE )
696 {
697 SoundStop( pPositionSnd->uiSoundSampleID );
698 }
699
700 pPositionSnd->fAllocated = FALSE;
701
702 RecountPositionSnds( );
703 }
704 }
705
SetPositionSndGridNo(INT32 iPositionSndIndex,INT16 sGridNo)706 void SetPositionSndGridNo( INT32 iPositionSndIndex, INT16 sGridNo )
707 {
708 POSITIONSND *pPositionSnd;
709
710 pPositionSnd = &gPositionSndData[ iPositionSndIndex ];
711
712 if ( pPositionSnd->fAllocated )
713 {
714 pPositionSnd->sGridNo = sGridNo;
715
716 SetPositionSndsVolumeAndPanning( );
717 }
718 }
719
720
SetPositionSndsActive(void)721 void SetPositionSndsActive(void)
722 {
723 gfPositionSoundsActive = TRUE;
724 for (UINT32 i = 0; i != guiNumPositionSnds; ++i)
725 {
726 POSITIONSND& p = gPositionSndData[i];
727 if (!p.fAllocated) continue;
728 if (!p.fInActive) continue;
729
730 p.fInActive = FALSE;
731 // Begin sound effect, Volume 0
732 p.uiSoundSampleID = PlayJA2Sample(p.iSoundToPlay, 0, 0, MIDDLEPAN);
733 }
734 }
735
736
SetPositionSndsInActive(void)737 void SetPositionSndsInActive(void)
738 {
739 gfPositionSoundsActive = FALSE;
740 for (UINT32 i = 0; i != guiNumPositionSnds; ++i)
741 {
742 POSITIONSND& p = gPositionSndData[i];
743 if (!p.fAllocated) continue;
744
745 p.fInActive = TRUE;
746
747 if (p.uiSoundSampleID == NO_SAMPLE) continue;
748
749 // End sound
750 SoundStop(p.uiSoundSampleID);
751 p.uiSoundSampleID = NO_SAMPLE;
752 }
753 }
754
755
PositionSoundDir(INT16 sGridNo)756 static INT8 PositionSoundDir(INT16 sGridNo)
757 {
758 INT16 sScreenX, sScreenY;
759 INT16 sMiddleX;
760 INT16 sDif, sAbsDif;
761
762 if ( sGridNo == NOWHERE )
763 {
764 return( MIDDLEPAN );
765 }
766
767 GetAbsoluteScreenXYFromMapPos(sGridNo, &sScreenX, &sScreenY);
768
769 // Get middle of where we are now....
770 sMiddleX = gsTopLeftWorldX + ( gsBottomRightWorldX - gsTopLeftWorldX ) / 2;
771
772 sDif = sMiddleX - sScreenX;
773
774 if ( ( sAbsDif = ABS( sDif ) ) > 64 )
775 {
776 // OK, NOT the middle.
777
778 // Is it outside the screen?
779 if ( sAbsDif > ( ( gsBottomRightWorldX - gsTopLeftWorldX ) / 2 ) )
780 {
781 // yes, outside...
782 if ( sDif > 0 )
783 {
784 //return( FARLEFT );
785 return( 1 );
786 }
787 else
788 {
789 //return( FARRIGHT );
790 return( 126 );
791 }
792 }
793 else // inside screen
794 {
795 if (sDif > 0)
796 {
797 return( LEFTSIDE );
798 }
799 else
800 {
801 return( RIGHTSIDE );
802 }
803 }
804 }
805 else // hardly any difference, so sound should be played from middle
806 {
807 return(MIDDLE);
808 }
809 }
810
811
PositionSoundVolume(INT8 const initial_volume,GridNo const grid_no)812 static INT8 PositionSoundVolume(INT8 const initial_volume, GridNo const grid_no)
813 {
814 if (grid_no == NOWHERE) return initial_volume;
815
816 INT16 sScreenX;
817 INT16 sScreenY;
818 GetAbsoluteScreenXYFromMapPos(grid_no, &sScreenX, &sScreenY);
819
820 // Get middle of where we are now
821 INT16 const sMiddleX = gsTopLeftWorldX + (gsBottomRightWorldX - gsTopLeftWorldX) / 2;
822 INT16 const sMiddleY = gsTopLeftWorldY + (gsBottomRightWorldY - gsTopLeftWorldY) / 2;
823
824 INT16 const sDifX = sMiddleX - sScreenX;
825 INT16 const sDifY = sMiddleY - sScreenY;
826
827 INT16 const sMaxDistX = (gsBottomRightWorldX - gsTopLeftWorldX) * 3 / 2;
828 INT16 const sMaxDistY = (gsBottomRightWorldY - gsTopLeftWorldY) * 3 / 2;
829
830 double const sMaxSoundDist = sqrt((double)(sMaxDistX * sMaxDistX) + (sMaxDistY * sMaxDistY));
831 double sSoundDist = sqrt((double)(sDifX * sDifX) + (sDifY * sDifY));
832
833 if (sSoundDist == 0) return initial_volume;
834
835 if (sSoundDist > sMaxSoundDist) sSoundDist = sMaxSoundDist;
836
837 // Scale
838 return (INT8)(initial_volume * ((sMaxSoundDist - sSoundDist) / sMaxSoundDist));
839 }
840
841
SetPositionSndsVolumeAndPanning(void)842 void SetPositionSndsVolumeAndPanning(void)
843 {
844 for (UINT32 i = 0; i != guiNumPositionSnds; ++i)
845 {
846 POSITIONSND const& p = gPositionSndData[i];
847 if (!p.fAllocated) continue;
848 if (p.fInActive) continue;
849 if (p.uiSoundSampleID == NO_SAMPLE) continue;
850
851 INT8 volume = PositionSoundVolume(15, p.sGridNo);
852 if (p.SoundSource && p.SoundSource->bVisible == -1)
853 { // Limit volume
854 if (volume > 10) volume = 10;
855 }
856 SoundSetVolume(p.uiSoundSampleID, volume);
857
858 INT8 const pan = PositionSoundDir(p.sGridNo);
859 SoundSetPan(p.uiSoundSampleID, pan);
860 }
861 }
862