1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 2010-2019 EDuke32 developers and contributors
4 Copyright (C) 2019 Nuke.YKT
5
6 This file is part of NBlood.
7
8 NBlood is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License version 2
10 as published by the Free Software Foundation.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
15
16 See the GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22 //-------------------------------------------------------------------------
23 #include <string.h>
24 #include "build.h"
25 #include "compat.h"
26 #include "common_game.h"
27 #include "fx_man.h"
28
29 #include "config.h"
30 #include "gameutil.h"
31 #include "player.h"
32 #include "resource.h"
33 #include "sfx.h"
34 #include "sound.h"
35 #include "trig.h"
36
37 POINT2D earL, earR, earL0, earR0; // Ear position
38 VECTOR2D earVL, earVR; // Ear velocity ?
39 int lPhase, rPhase, lVol, rVol, lPitch, rPitch;
40
41 BONKLE Bonkle[256];
42 BONKLE *BonkleCache[256];
43
44 int nBonkles;
45
sfxInit(void)46 void sfxInit(void)
47 {
48 for (int i = 0; i < 256; i++)
49 BonkleCache[i] = &Bonkle[i];
50 nBonkles = 0;
51 }
52
sfxTerm()53 void sfxTerm()
54 {
55 }
56
Vol3d(int angle,int dist)57 int Vol3d(int angle, int dist)
58 {
59 return dist - mulscale16(dist, 0x2000 - mulscale30(0x2000, Cos(angle)));
60 }
61
Calc3DValues(BONKLE * pBonkle)62 void Calc3DValues(BONKLE *pBonkle)
63 {
64 int dx = pBonkle->at20.x - gMe->pSprite->x;
65 int dy = pBonkle->at20.y - gMe->pSprite->y;
66 int dz = pBonkle->at20.z - gMe->pSprite->z;
67 int angle = getangle(dx, dy);
68 dx >>= 4;
69 dy >>= 4;
70 dz >>= 8;
71 int distance = ksqrt(dx*dx + dy * dy + dz * dz);
72 distance = ClipLow((distance >> 2) + (distance >> 3), 64);
73 int v14, v18;
74 v14 = v18 = scale(pBonkle->at1c, 80, distance);
75 int sinVal = Sin(angle);
76 int cosVal = Cos(angle);
77 int v8 = dmulscale30r(cosVal, pBonkle->at20.x - pBonkle->at2c.x, sinVal, pBonkle->at20.y - pBonkle->at2c.y);
78
79 int distanceL = approxDist(pBonkle->at20.x - earL.x, pBonkle->at20.y - earL.y);
80 lVol = Vol3d(angle - (gMe->pSprite->ang - 85), v18);
81 int phaseLeft = mulscale16r(distanceL, pBonkle->at3c == 1 ? 4114 : 8228);
82 lPitch = scale(pBonkle->at18, dmulscale30r(cosVal, earVL.dx, sinVal, earVL.dy) + 5853, v8 + 5853);
83 if (lPitch < 0 || lPitch > pBonkle->at18 * 4)
84 lPitch = pBonkle->at18;
85
86 int distanceR = approxDist(pBonkle->at20.x - earR.x, pBonkle->at20.y - earR.y);
87 rVol = Vol3d(angle - (gMe->pSprite->ang + 85), v14);
88 int phaseRight = mulscale16r(distanceR, pBonkle->at3c == 1 ? 4114 : 8228);
89 rPitch = scale(pBonkle->at18, dmulscale30r(cosVal, earVR.dx, sinVal, earVR.dy) + 5853, v8 + 5853);
90 if (rPitch < 0 || rPitch > pBonkle->at18 * 4)
91 rPitch = pBonkle->at18;
92
93 int phaseMin = ClipHigh(phaseLeft, phaseRight);
94 lPhase = phaseRight - phaseMin;
95 rPhase = phaseLeft - phaseMin;
96 }
97
sfxPlay3DSound(int x,int y,int z,int soundId,int nSector)98 void sfxPlay3DSound(int x, int y, int z, int soundId, int nSector)
99 {
100 if (!SoundToggle || soundId < 0) return;
101
102 DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX");
103 if (!hRes)return;
104
105 SFX *pEffect = (SFX*)gSoundRes.Load(hRes);
106 hRes = gSoundRes.Lookup(pEffect->rawName, "RAW");
107 if (!hRes) return;
108
109 int v1c, v18;
110 v1c = v18 = mulscale16(pEffect->pitch, sndGetRate(pEffect->format));
111 if (nBonkles >= 256)
112 return;
113 BONKLE *pBonkle = BonkleCache[nBonkles++];
114 pBonkle->at10 = NULL;
115 pBonkle->at20.x = x;
116 pBonkle->at20.y = y;
117 pBonkle->at20.z = z;
118 pBonkle->at38 = nSector;
119 FindSector(x, y, z, &pBonkle->at38);
120 pBonkle->at2c = pBonkle->at20;
121 pBonkle->atc = soundId;
122 pBonkle->at8 = hRes;
123 pBonkle->at1c = pEffect->relVol;
124 pBonkle->at18 = v18;
125 pBonkle->at3c = pEffect->format;
126 int size = hRes->size;
127 char *pData = (char*)gSoundRes.Lock(hRes);
128 Calc3DValues(pBonkle);
129 int priority = 1;
130 if (priority < lVol)
131 priority = lVol;
132 if (priority < rVol)
133 priority = rVol;
134 if (gDoppler)
135 {
136 MV_Lock();
137 pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, fix16_one, (intptr_t)&pBonkle->at0);
138 pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, fix16_one, (intptr_t)&pBonkle->at4);
139 MV_Unlock();
140 }
141 else
142 {
143 pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v1c, 0, lVol, lVol, rVol, priority, fix16_one, (intptr_t)&pBonkle->at0);
144 pBonkle->at4 = 0;
145 }
146 }
147
sfxPlay3DSound(spritetype * pSprite,int soundId,int a3,int a4)148 void sfxPlay3DSound(spritetype *pSprite, int soundId, int a3, int a4)
149 {
150 if (!SoundToggle)
151 return;
152 if (!pSprite)
153 return;
154 if (soundId < 0)
155 return;
156 DICTNODE *hRes = gSoundRes.Lookup(soundId, "SFX");
157 if (!hRes)
158 return;
159
160 SFX *pEffect = (SFX*)gSoundRes.Load(hRes);
161 hRes = gSoundRes.Lookup(pEffect->rawName, "RAW");
162 if (!hRes)
163 return;
164 int size = hRes->size;
165 if (size <= 0)
166 return;
167 int v14;
168 v14 = mulscale16(pEffect->pitch, sndGetRate(pEffect->format));
169 BONKLE *pBonkle = NULL;
170 if (a3 >= 0)
171 {
172 int i;
173 for (i = 0; i < nBonkles; i++)
174 {
175 pBonkle = BonkleCache[i];
176 if (pBonkle->at14 == a3 && (pBonkle->at10 == pSprite || (a4 & 1) != 0))
177 {
178 if ((a4 & 4) != 0 && pBonkle->at14 == a3)
179 return;
180 if ((a4 & 2) != 0 && pBonkle->atc == soundId)
181 return;
182 if (pBonkle->at0 > 0)
183 FX_StopSound(pBonkle->at0);
184 if (pBonkle->at4 > 0)
185 FX_StopSound(pBonkle->at4);
186 if (pBonkle->at8)
187 {
188 gSoundRes.Unlock(pBonkle->at8);
189 pBonkle->at8 = NULL;
190 }
191 break;
192 }
193 }
194 if (i == nBonkles)
195 {
196 if (nBonkles >= 256)
197 return;
198 pBonkle = BonkleCache[nBonkles++];
199 }
200 pBonkle->at10 = pSprite;
201 pBonkle->at14 = a3;
202 }
203 else
204 {
205 if (nBonkles >= 256)
206 return;
207 pBonkle = BonkleCache[nBonkles++];
208 pBonkle->at10 = NULL;
209 }
210 pBonkle->at20.x = pSprite->x;
211 pBonkle->at20.y = pSprite->y;
212 pBonkle->at20.z = pSprite->z;
213 pBonkle->at38 = pSprite->sectnum;
214 pBonkle->at2c = pBonkle->at20;
215 pBonkle->atc = soundId;
216 pBonkle->at8 = hRes;
217 pBonkle->at1c = pEffect->relVol;
218 pBonkle->at18 = v14;
219 Calc3DValues(pBonkle);
220 int priority = 1;
221 if (priority < lVol)
222 priority = lVol;
223 if (priority < rVol)
224 priority = rVol;
225 int loopStart = pEffect->loopStart;
226 int loopEnd = ClipLow(size - 1, 0);
227 if (a3 < 0)
228 loopStart = -1;
229 MV_Lock();
230 char *pData = (char*)gSoundRes.Lock(hRes);
231 if (loopStart >= 0)
232 {
233 if (gDoppler)
234 {
235 pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, lPitch, 0, lVol, lVol, 0, priority, fix16_one, (intptr_t)&pBonkle->at0);
236 pBonkle->at4 = FX_PlayLoopedRaw(pData + rPhase, size - rPhase, pData + loopStart, pData + loopEnd, rPitch, 0, rVol, 0, rVol, priority, fix16_one, (intptr_t)&pBonkle->at4);
237 }
238 else
239 {
240 pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, v14, 0, lVol, lVol, rVol, priority, fix16_one, (intptr_t)&pBonkle->at0);
241 pBonkle->at4 = 0;
242 }
243 }
244 else
245 {
246 pData = (char*)gSoundRes.Lock(pBonkle->at8);
247 if (gDoppler)
248 {
249 pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, fix16_one, (intptr_t)&pBonkle->at0);
250 pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, fix16_one, (intptr_t)&pBonkle->at4);
251 }
252 else
253 {
254 pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v14, 0, lVol, lVol, rVol, priority, fix16_one, (intptr_t)&pBonkle->at0);
255 pBonkle->at4 = 0;
256 }
257 }
258 MV_Unlock();
259 }
260
261 // by NoOne: same as previous, but allows to set custom pitch for sound AND volume.
sfxPlay3DSoundCP(spritetype * pSprite,int soundId,int a3,int a4,int pitch,int volume)262 void sfxPlay3DSoundCP(spritetype* pSprite, int soundId, int a3, int a4, int pitch, int volume)
263 {
264 if (!SoundToggle || !pSprite || soundId < 0) return;
265 DICTNODE* hRes = gSoundRes.Lookup(soundId, "SFX");
266 if (!hRes) return;
267
268 SFX* pEffect = (SFX*)gSoundRes.Load(hRes);
269 hRes = gSoundRes.Lookup(pEffect->rawName, "RAW");
270 if (!hRes) return;
271 int size = hRes->size;
272 if (size <= 0) return;
273
274 if (pitch <= 0) pitch = pEffect->pitch;
275 else pitch -= Random(pEffect->pitchRange);
276
277 int v14;
278 v14 = mulscale16(pitch, sndGetRate(pEffect->format));
279
280 BONKLE * pBonkle = NULL;
281 if (a3 >= 0)
282 {
283 int i;
284 for (i = 0; i < nBonkles; i++)
285 {
286 pBonkle = BonkleCache[i];
287 if (pBonkle->at14 == a3 && (pBonkle->at10 == pSprite || (a4 & 1) != 0))
288 {
289 if ((a4 & 4) != 0 && pBonkle->at14 == a3)
290 return;
291 if ((a4 & 2) != 0 && pBonkle->atc == soundId)
292 return;
293 if (pBonkle->at0 > 0)
294 FX_StopSound(pBonkle->at0);
295 if (pBonkle->at4 > 0)
296 FX_StopSound(pBonkle->at4);
297 if (pBonkle->at8)
298 {
299 gSoundRes.Unlock(pBonkle->at8);
300 pBonkle->at8 = NULL;
301 }
302 break;
303 }
304 }
305 if (i == nBonkles)
306 {
307 if (nBonkles >= 256)
308 return;
309 pBonkle = BonkleCache[nBonkles++];
310 }
311 pBonkle->at10 = pSprite;
312 pBonkle->at14 = a3;
313 }
314 else
315 {
316 if (nBonkles >= 256)
317 return;
318 pBonkle = BonkleCache[nBonkles++];
319 pBonkle->at10 = NULL;
320 }
321 pBonkle->at20.x = pSprite->x;
322 pBonkle->at20.y = pSprite->y;
323 pBonkle->at20.z = pSprite->z;
324 pBonkle->at38 = pSprite->sectnum;
325 pBonkle->at2c = pBonkle->at20;
326 pBonkle->atc = soundId;
327 pBonkle->at8 = hRes;
328 pBonkle->at1c = ((volume == 0) ? pEffect->relVol : ((volume == -1) ? 0 : ((volume > 255) ? 255 : volume)));
329 pBonkle->at18 = v14;
330 Calc3DValues(pBonkle);
331 int priority = 1;
332 if (priority < lVol)
333 priority = lVol;
334 if (priority < rVol)
335 priority = rVol;
336 int loopStart = pEffect->loopStart;
337 int loopEnd = ClipLow(size - 1, 0);
338 if (a3 < 0)
339 loopStart = -1;
340 MV_Lock();
341 char* pData = (char*)gSoundRes.Lock(hRes);
342 if (loopStart >= 0)
343 {
344 if (gDoppler)
345 {
346 pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, lPitch, 0, lVol, lVol, 0, priority, fix16_one, (intptr_t)& pBonkle->at0);
347 pBonkle->at4 = FX_PlayLoopedRaw(pData + rPhase, size - rPhase, pData + loopStart, pData + loopEnd, rPitch, 0, rVol, 0, rVol, priority, fix16_one, (intptr_t)& pBonkle->at4);
348 }
349 else
350 {
351 pBonkle->at0 = FX_PlayLoopedRaw(pData + lPhase, size - lPhase, pData + loopStart, pData + loopEnd, v14, 0, lVol, lVol, rVol, priority, fix16_one, (intptr_t)& pBonkle->at0);
352 pBonkle->at4 = 0;
353 }
354 }
355 else
356 {
357 pData = (char*)gSoundRes.Lock(pBonkle->at8);
358 if (gDoppler)
359 {
360 pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, lPitch, 0, lVol, lVol, 0, priority, fix16_one, (intptr_t)& pBonkle->at0);
361 pBonkle->at4 = FX_PlayRaw(pData + rPhase, size - rPhase, rPitch, 0, rVol, 0, rVol, priority, fix16_one, (intptr_t)& pBonkle->at4);
362 }
363 else
364 {
365 pBonkle->at0 = FX_PlayRaw(pData + lPhase, size - lPhase, v14, 0, lVol, lVol, rVol, priority, fix16_one, (intptr_t)& pBonkle->at0);
366 pBonkle->at4 = 0;
367 }
368 }
369 MV_Unlock();
370 }
371
sfxKillSoundInternal(int i)372 EXTERN_INLINE void sfxKillSoundInternal(int i)
373 {
374 BONKLE *pBonkle = BonkleCache[i];
375 if (pBonkle->at0 > 0)
376 {
377 FX_EndLooping(pBonkle->at0);
378 FX_StopSound(pBonkle->at0);
379 }
380 if (pBonkle->at4 > 0)
381 {
382 FX_EndLooping(pBonkle->at4);
383 FX_StopSound(pBonkle->at4);
384 }
385 if (pBonkle->at8)
386 {
387 gSoundRes.Unlock(pBonkle->at8);
388 pBonkle->at8 = NULL;
389 }
390 BonkleCache[i] = BonkleCache[--nBonkles];
391 BonkleCache[nBonkles] = pBonkle;
392 }
393
sfxKill3DSound(spritetype * pSprite,int a2,int a3)394 void sfxKill3DSound(spritetype *pSprite, int a2, int a3)
395 {
396 if (!pSprite)
397 return;
398 for (int i = nBonkles - 1; i >= 0; i--)
399 {
400 BONKLE *pBonkle = BonkleCache[i];
401 if (pBonkle->at10 == pSprite && (a2 < 0 || a2 == pBonkle->at14) && (a3 < 0 || a3 == pBonkle->atc))
402 {
403 sfxKillSoundInternal(i);
404 break;
405 }
406 }
407 }
408
sfxKillAllSounds(void)409 void sfxKillAllSounds(void)
410 {
411 for (int i = nBonkles - 1; i >= 0; i--)
412 {
413 sfxKillSoundInternal(i);
414 }
415 }
416
sfxKillSpriteSounds(spritetype * pSprite)417 void sfxKillSpriteSounds(spritetype *pSprite)
418 {
419 if (!pSprite)
420 return;
421 for (int i = nBonkles - 1; i >= 0; i--)
422 {
423 BONKLE *pBonkle = BonkleCache[i];
424 if (pBonkle->at10 == pSprite)
425 {
426 sfxKillSoundInternal(i);
427 }
428 }
429 }
430
sfxUpdate3DSounds(void)431 void sfxUpdate3DSounds(void)
432 {
433 int dx = mulscale30(Cos(gMe->pSprite->ang + 512), 43);
434 earL0 = earL;
435 int dy = mulscale30(Sin(gMe->pSprite->ang + 512), 43);
436 earR0 = earR;
437 earL.x = gMe->pSprite->x - dx;
438 earL.y = gMe->pSprite->y - dy;
439 earR.x = gMe->pSprite->x + dx;
440 earR.y = gMe->pSprite->y + dy;
441 earVL.dx = earL.x - earL0.x;
442 earVL.dy = earL.y - earL0.y;
443 earVR.dx = earR.x - earR0.x;
444 earVR.dy = earR.y - earR0.y;
445 for (int i = nBonkles - 1; i >= 0; i--)
446 {
447 BONKLE *pBonkle = BonkleCache[i];
448 if (pBonkle->at0 > 0 || pBonkle->at4 > 0)
449 {
450 if (!pBonkle->at8)
451 continue;
452 if (pBonkle->at10)
453 {
454 pBonkle->at2c = pBonkle->at20;
455 pBonkle->at20.x = pBonkle->at10->x;
456 pBonkle->at20.y = pBonkle->at10->y;
457 pBonkle->at20.z = pBonkle->at10->z;
458 pBonkle->at38 = pBonkle->at10->sectnum;
459 }
460 Calc3DValues(pBonkle);
461 MV_Lock();
462 if (pBonkle->at0 > 0)
463 {
464 if (pBonkle->at4 > 0)
465 {
466 FX_SetPan(pBonkle->at0, lVol, lVol, 0);
467 FX_SetFrequency(pBonkle->at0, lPitch);
468 }
469 else
470 FX_SetPan(pBonkle->at0, lVol, lVol, rVol);
471 }
472 if (pBonkle->at4 > 0)
473 {
474 FX_SetPan(pBonkle->at4, rVol, 0, rVol);
475 FX_SetFrequency(pBonkle->at4, rPitch);
476 }
477 MV_Unlock();
478 }
479 else
480 {
481 gSoundRes.Unlock(pBonkle->at8);
482 pBonkle->at8 = NULL;
483 BonkleCache[i] = BonkleCache[--nBonkles];
484 BonkleCache[nBonkles] = pBonkle;
485 }
486 }
487 }
488
sfxSetReverb(bool toggle)489 void sfxSetReverb(bool toggle)
490 {
491 if (toggle)
492 {
493 FX_SetReverb(128);
494 FX_SetReverbDelay(10);
495 }
496 else
497 FX_SetReverb(0);
498 }
499
sfxSetReverb2(bool toggle)500 void sfxSetReverb2(bool toggle)
501 {
502 if (toggle)
503 {
504 FX_SetReverb(128);
505 FX_SetReverbDelay(20);
506 }
507 else
508 FX_SetReverb(0);
509 }
510