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