1 //-------------------------------------------------------------------------
2 /*
3 Copyright (C) 1996, 2003 - 3D Realms Entertainment
4 Copyright (C) 2017-2019 Nuke.YKT
5
6 This file is part of Duke Nukem 3D version 1.5 - Atomic Edition
7
8 Duke Nukem 3D is free software; you can redistribute it and/or
9 modify it under the terms of the GNU General Public License
10 as published by the Free Software Foundation; either version 2
11 of the License, or (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
16
17 See the GNU General Public License for more details.
18
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22
23 Original Source: 1996 - Todd Replogle
24 Prepared for public release: 03/21/2003 - Charlie Wiederhold, 3D Realms
25 */
26 //-------------------------------------------------------------------------
27
28 #include <conio.h>
29 #include <stdio.h>
30 #include <string.h>
31 #include "types.h"
32 #include "sndcards.h"
33 #include "fx_man.h"
34 #include "music.h"
35 #include "util_lib.h"
36 #include "duke3d.h"
37
38
39 #define LOUDESTVOLUME 150
40
41 long backflag,numenvsnds;
42
43 /*
44 ===================
45 =
46 = SoundStartup
47 =
48 ===================
49 */
50
SoundStartup(void)51 void SoundStartup( void )
52 {
53 int32 status;
54
55 // if they chose None lets return
56 if (FXDevice == NumSoundCards) return;
57
58 // Do special Sound Blaster, AWE32 stuff
59 if (
60 ( FXDevice == SoundBlaster ) ||
61 ( FXDevice == Awe32 )
62 )
63 {
64 int MaxVoices;
65 int MaxBits;
66 int MaxChannels;
67
68 status = FX_SetupSoundBlaster
69 (
70 BlasterConfig, (int *)&MaxVoices, (int *)&MaxBits, (int *)&MaxChannels
71 );
72 }
73 else
74 {
75 status = FX_Ok;
76 }
77
78 if ( status == FX_Ok )
79 {
80 if ( eightytwofifty && numplayers > 1)
81 {
82 status = FX_Init( FXDevice, min( NumVoices,4 ), 1, 8, 8000 );
83 }
84 else
85 {
86 status = FX_Init( FXDevice, NumVoices, NumChannels, NumBits, MixRate );
87 }
88 if ( status == FX_Ok )
89 {
90
91 FX_SetVolume( FXVolume );
92 if (ReverseStereo == 1)
93 {
94 FX_SetReverseStereo(!FX_GetReverseStereo());
95 }
96 }
97 }
98 if ( status != FX_Ok )
99 {
100 Error( FX_ErrorString( FX_Error ));
101 }
102
103 status = FX_SetCallBack( testcallback );
104
105 if ( status != FX_Ok )
106 {
107 Error( FX_ErrorString( FX_Error ));
108 }
109 }
110
111 /*
112 ===================
113 =
114 = SoundShutdown
115 =
116 ===================
117 */
118
SoundShutdown(void)119 void SoundShutdown( void )
120 {
121 int32 status;
122
123 // if they chose None lets return
124 if (FXDevice == NumSoundCards)
125 return;
126
127 status = FX_Shutdown();
128 if ( status != FX_Ok )
129 {
130 Error( FX_ErrorString( FX_Error ));
131 }
132 }
133
134 /*
135 ===================
136 =
137 = MusicStartup
138 =
139 ===================
140 */
141
MusicStartup(void)142 void MusicStartup( void )
143 {
144 int32 status;
145
146 // if they chose None lets return
147 if ((MusicDevice == NumSoundCards) || (eightytwofifty && numplayers > 1) )
148 return;
149
150 // satisfy AWE32 and WAVEBLASTER stuff
151 BlasterConfig.Midi = MidiPort;
152
153 // Do special Sound Blaster, AWE32 stuff
154 if (
155 ( FXDevice == SoundBlaster ) ||
156 ( FXDevice == Awe32 )
157 )
158 {
159 int MaxVoices;
160 int MaxBits;
161 int MaxChannels;
162
163 FX_SetupSoundBlaster
164 (
165 BlasterConfig, (int *)&MaxVoices, (int *)&MaxBits, (int *)&MaxChannels
166 );
167 }
168 status = MUSIC_Init( MusicDevice, MidiPort );
169
170 if ( status == MUSIC_Ok )
171 {
172 MUSIC_SetVolume( MusicVolume );
173 }
174 else
175 {
176 Error(MUSIC_ErrorString(MUSIC_ErrorCode));
177 }
178 }
179
180 /*
181 ===================
182 =
183 = MusicShutdown
184 =
185 ===================
186 */
187
MusicShutdown(void)188 void MusicShutdown( void )
189 {
190 int32 status;
191
192 // if they chose None lets return
193 if ((MusicDevice == NumSoundCards) || (eightytwofifty && numplayers > 1) )
194 return;
195
196 status = MUSIC_Shutdown();
197 if ( status != MUSIC_Ok )
198 {
199 Error( MUSIC_ErrorString( MUSIC_ErrorCode ));
200 }
201 }
202
USRHOOKS_GetMem(char ** ptr,unsigned long size)203 int USRHOOKS_GetMem(char **ptr, unsigned long size )
204 {
205 *ptr = SafeMalloc(size);
206
207 if (*ptr == NULL)
208 return(USRHOOKS_Error);
209
210 return( USRHOOKS_Ok);
211
212 }
213
USRHOOKS_FreeMem(char * ptr)214 int USRHOOKS_FreeMem(char *ptr)
215 {
216 SafeFree(ptr);
217 return( USRHOOKS_Ok);
218 }
219
220 char menunum=0;
221
intomenusounds(void)222 void intomenusounds(void)
223 {
224 short i;
225 short menusnds[] =
226 {
227 390,
228 390,
229 390,
230 390,
231 390,
232 390,
233 390,
234 390,
235 390,
236 390,
237 390,
238 390,
239 390,
240 390,
241 390,
242 390,
243 390,
244 };
245 sound(menusnds[menunum++]);
246 menunum %= 17;
247 }
248
playmusic(char * fn)249 void playmusic(char *fn)
250 {
251 short fp;
252 long l;
253 }
254
loadsound(unsigned short num)255 char loadsound(unsigned short num)
256 {
257 long fp, l;
258
259 if(num >= NUM_SOUNDS || SoundToggle == 0) return 0;
260 if (FXDevice == NumSoundCards) return 0;
261
262 fp = kopen4load(sounds[num],loadfromgrouponly);
263 if(fp == -1)
264 {
265 sprintf(&fta_quotes[113][0],"Sound %s(#%ld) not found.",sounds[num],num);
266 FTA(113,&ps[myconnectindex]);
267 return 0;
268 }
269
270 l = kfilelength( fp );
271 soundsiz[num] = l;
272
273 Sound[num].lock = 200;
274
275 allocache((long *)&Sound[num].ptr,l,&Sound[num].lock);
276 kread( fp, Sound[num].ptr , l);
277 kclose( fp );
278 return 1;
279 }
280
xyzsound(short num,short i,long x,long y,long z)281 int xyzsound(short num,short i,long x,long y,long z)
282 {
283 long sndist, cx, cy, cz, j,k;
284 short pitche,pitchs,cs;
285 int voice, sndang, ca, pitch;
286
287 // if(num != 358) return 0;
288
289 if( num >= NUM_SOUNDS ||
290 FXDevice == NumSoundCards ||
291 ( (soundm[num]&8) && ud.lockout ) ||
292 SoundToggle == 0 ||
293 Sound[num].num > 3 ||
294 FX_VoiceAvailable(soundpr[num]) == 0 ||
295 (ps[myconnectindex].timebeforeexit > 0 && ps[myconnectindex].timebeforeexit <= 26*3) ||
296 ps[myconnectindex].gm&MODE_MENU) return -1;
297
298 if( soundm[num]&4 )
299 {
300 if(VoiceToggle==0 || (ud.multimode > 1 && PN == APLAYER && sprite[i].yvel != screenpeek && ud.coop != 1) ) return -1;
301
302 for(j=0;j<NUM_SOUNDS;j++)
303 for(k=0;k<Sound[j].num;k++)
304 if( (Sound[j].num > 0) && (soundm[j]&4) )
305 return -1;
306 }
307
308 cx = ps[screenpeek].oposx;
309 cy = ps[screenpeek].oposy;
310 cz = ps[screenpeek].oposz;
311 cs = ps[screenpeek].cursectnum;
312 ca = ps[screenpeek].ang+ps[screenpeek].look_ang;
313
314 sndist = FindDistance3D((cx-x),(cy-y),(cz-z)>>4);
315
316 if( i >= 0 && (soundm[num]&16) == 0 && PN == MUSICANDSFX && SLT < 999 && (sector[SECT].lotag&0xff) < 9 )
317 sndist = divscale14(sndist,(SHT+1));
318
319 pitchs = soundps[num];
320 pitche = soundpe[num];
321 cx = klabs(pitche-pitchs);
322
323 if(cx)
324 {
325 if( pitchs < pitche )
326 pitch = pitchs + ( rand()%cx );
327 else pitch = pitche + ( rand()%cx );
328 }
329 else pitch = pitchs;
330
331 sndist += soundvo[num];
332 if( sndist && PN != MUSICANDSFX && !cansee(cx,cy,cz-(24<<8),cs,SX,SY,SZ-(24<<8),SECT) )
333 sndist += sndist>>2;
334
335 switch(num)
336 {
337 case PIPEBOMB_EXPLODE:
338 case LASERTRIP_EXPLODE:
339 case RPG_EXPLODE:
340 if(sndist > (6144) )
341 sndist = 6144;
342 if(sector[ps[screenpeek].cursectnum].lotag == 2)
343 pitch -= 1024;
344 break;
345 default:
346 if(sector[ps[screenpeek].cursectnum].lotag == 2 && (soundm[num]&4) == 0)
347 pitch = -768;
348 if( sndist > 31444 && PN != MUSICANDSFX)
349 return -1;
350 break;
351 }
352
353
354 if( Sound[num].num > 0 && PN != MUSICANDSFX )
355 {
356 if( SoundOwner[num][0].i == i ) stopsound(num);
357 else if( Sound[num].num > 1 ) stopsound(num);
358 else if( badguy(&sprite[i]) && sprite[i].extra <= 0 ) stopsound(num);
359 }
360
361 if( PN == APLAYER && sprite[i].yvel == screenpeek )
362 {
363 sndang = 0;
364 sndist = 0;
365 }
366 else
367 {
368 sndang = 2048 + ca - getangle(cx-x,cy-y);
369 sndang &= 2047;
370 }
371
372 if(Sound[num].ptr == 0) { if( loadsound(num) == 0 ) return 0; }
373 else
374 {
375 if (Sound[num].lock < 200)
376 Sound[num].lock = 200;
377 else Sound[num].lock++;
378 }
379
380 if( soundm[num]&16 ) sndist = 0;
381
382 if(sndist < ((255-LOUDESTVOLUME)<<6) )
383 sndist = ((255-LOUDESTVOLUME)<<6);
384
385 if( soundm[num]&1 )
386 {
387 unsigned short start;
388
389 if(Sound[num].num > 0) return -1;
390
391 start = *(unsigned short *)(Sound[num].ptr + 0x14);
392
393 if(*Sound[num].ptr == 'C')
394 voice = FX_PlayLoopedVOC( Sound[num].ptr, start, start + soundsiz[num],
395 pitch,sndist>>6,sndist>>6,0,soundpr[num],num);
396 else
397 voice = FX_PlayLoopedWAV( Sound[num].ptr, start, start + soundsiz[num],
398 pitch,sndist>>6,sndist>>6,0,soundpr[num],num);
399 }
400 else
401 {
402 if( *Sound[num].ptr == 'C')
403 voice = FX_PlayVOC3D( Sound[ num ].ptr,pitch,sndang>>6,sndist>>6, soundpr[num], num );
404 else voice = FX_PlayWAV3D( Sound[ num ].ptr,pitch,sndang>>6,sndist>>6, soundpr[num], num );
405 }
406
407 if ( voice > FX_Ok )
408 {
409 SoundOwner[num][Sound[num].num].i = i;
410 SoundOwner[num][Sound[num].num].voice = voice;
411 Sound[num].num++;
412 }
413 else Sound[num].lock--;
414 return (voice);
415 }
416
sound(short num)417 void sound(short num)
418 {
419 short pitch,pitche,pitchs,cx;
420 int voice;
421 long start;
422
423 if (FXDevice == NumSoundCards) return;
424 if(SoundToggle==0) return;
425 if(VoiceToggle==0 && (soundm[num]&4) ) return;
426 if( (soundm[num]&8) && ud.lockout ) return;
427 if(FX_VoiceAvailable(soundpr[num]) == 0) return;
428
429 pitchs = soundps[num];
430 pitche = soundpe[num];
431 cx = klabs(pitche-pitchs);
432
433 if(cx)
434 {
435 if( pitchs < pitche )
436 pitch = pitchs + ( rand()%cx );
437 else pitch = pitche + ( rand()%cx );
438 }
439 else pitch = pitchs;
440
441 if(Sound[num].ptr == 0) { if( loadsound(num) == 0 ) return; }
442 else
443 {
444 if (Sound[num].lock < 200)
445 Sound[num].lock = 200;
446 else Sound[num].lock++;
447 }
448
449 if( soundm[num]&1 )
450 {
451 if(*Sound[num].ptr == 'C')
452 {
453 start = (long)*(unsigned short *)(Sound[num].ptr + 0x14);
454 voice = FX_PlayLoopedVOC( Sound[num].ptr, start, start + soundsiz[num],
455 pitch,LOUDESTVOLUME,LOUDESTVOLUME,LOUDESTVOLUME,soundpr[num],num);
456 }
457 else
458 {
459 start = (long)*(unsigned short *)(Sound[num].ptr + 0x14);
460 voice = FX_PlayLoopedWAV( Sound[num].ptr, start, start + soundsiz[num],
461 pitch,LOUDESTVOLUME,LOUDESTVOLUME,LOUDESTVOLUME,soundpr[num],num);
462 }
463 }
464 else
465 {
466 if(*Sound[num].ptr == 'C')
467 voice = FX_PlayVOC3D( Sound[ num ].ptr, pitch,0,255-LOUDESTVOLUME,soundpr[num], num );
468 else
469 voice = FX_PlayWAV3D( Sound[ num ].ptr, pitch,0,255-LOUDESTVOLUME,soundpr[num], num );
470 }
471
472 if(voice > FX_Ok) return;
473 Sound[num].lock--;
474 }
475
spritesound(unsigned short num,short i)476 int spritesound(unsigned short num, short i)
477 {
478 if(num >= NUM_SOUNDS) return -1;
479 return xyzsound(num,i,SX,SY,SZ);
480 }
481
stopsound(short num)482 void stopsound(short num)
483 {
484 if(Sound[num].num > 0)
485 {
486 FX_StopSound(SoundOwner[num][Sound[num].num-1].voice);
487 testcallback(num);
488 }
489 }
490
stopenvsound(short num,short i)491 void stopenvsound(short num,short i)
492 {
493 short j, k;
494
495 if(Sound[num].num > 0)
496 {
497 k = Sound[num].num;
498 for(j=0;j<k;j++)
499 if(SoundOwner[num][j].i == i)
500 {
501 FX_StopSound(SoundOwner[num][j].voice);
502 break;
503 }
504 }
505 }
506
pan3dsound(void)507 void pan3dsound(void)
508 {
509 long sndist, sx, sy, sz, cx, cy, cz;
510 short sndang,ca,j,k,i,cs;
511
512 numenvsnds = 0;
513
514 if(ud.camerasprite == -1)
515 {
516 cx = ps[screenpeek].oposx;
517 cy = ps[screenpeek].oposy;
518 cz = ps[screenpeek].oposz;
519 cs = ps[screenpeek].cursectnum;
520 ca = ps[screenpeek].ang+ps[screenpeek].look_ang;
521 }
522 else
523 {
524 cx = sprite[ud.camerasprite].x;
525 cy = sprite[ud.camerasprite].y;
526 cz = sprite[ud.camerasprite].z;
527 cs = sprite[ud.camerasprite].sectnum;
528 ca = sprite[ud.camerasprite].ang;
529 }
530
531 for(j=0;j<NUM_SOUNDS;j++) for(k=0;k<Sound[j].num;k++)
532 {
533 i = SoundOwner[j][k].i;
534
535 sx = sprite[i].x;
536 sy = sprite[i].y;
537 sz = sprite[i].z;
538
539 if( PN == APLAYER && sprite[i].yvel == screenpeek)
540 {
541 sndang = 0;
542 sndist = 0;
543 }
544 else
545 {
546 sndang = 2048 + ca - getangle(cx-sx,cy-sy);
547 sndang &= 2047;
548 sndist = FindDistance3D((cx-sx),(cy-sy),(cz-sz)>>4);
549 if( i >= 0 && (soundm[j]&16) == 0 && PN == MUSICANDSFX && SLT < 999 && (sector[SECT].lotag&0xff) < 9 )
550 sndist = divscale14(sndist,(SHT+1));
551 }
552
553 sndist += soundvo[j];
554
555 if( sndist && PN != MUSICANDSFX && !cansee(cx,cy,cz-(24<<8),cs,sx,sy,sz-(24<<8),SECT) )
556 sndist += sndist>>2;
557
558 if(PN == MUSICANDSFX && SLT < 999)
559 numenvsnds++;
560
561 switch(j)
562 {
563 case PIPEBOMB_EXPLODE:
564 case LASERTRIP_EXPLODE:
565 case RPG_EXPLODE:
566 if(sndist > (6144)) sndist = (6144);
567 break;
568 default:
569 if( sndist > 31444 && PN != MUSICANDSFX)
570 {
571 stopsound(j);
572 continue;
573 }
574 }
575
576 if(Sound[j].ptr == 0 && loadsound(j) == 0 ) continue;
577 if( soundm[j]&16 ) sndist = 0;
578
579 if(sndist < ((255-LOUDESTVOLUME)<<6) )
580 sndist = ((255-LOUDESTVOLUME)<<6);
581
582 FX_Pan3D(SoundOwner[j][k].voice,sndang>>6,sndist>>6);
583 }
584 }
585
testcallback(long num)586 void testcallback(long num)
587 {
588 int tempi,tempj,tempk;
589
590 if(num < 0)
591 {
592 if(lumplockbyte[-num] >= 200)
593 lumplockbyte[-num]--;
594 return;
595 }
596
597 if(Sound[num].num > 0)
598 {
599 tempk = Sound[num].num;
600
601 if( (soundm[num]&16) == 0)
602 for(tempj=0;tempj<tempk;tempj++)
603 {
604 tempi = SoundOwner[num][tempj].i;
605 if(sprite[tempi].picnum == MUSICANDSFX && sector[sprite[tempi].sectnum].lotag < 3 && sprite[tempi].lotag < 999)
606 {
607 hittype[tempi].temp_data[0] = 0;
608 if( (tempj + 1) < tempk )
609 {
610 SoundOwner[num][tempj].voice = SoundOwner[num][tempk-1].voice;
611 SoundOwner[num][tempj].i = SoundOwner[num][tempk-1].i;
612 }
613 break;
614 }
615 }
616
617 Sound[num].num--;
618 SoundOwner[num][tempk-1].i = -1;
619 }
620
621 Sound[num].lock--;
622 }
623
clearsoundlocks(void)624 void clearsoundlocks(void)
625 {
626 long i;
627
628 for(i=0;i<NUM_SOUNDS;i++)
629 if(Sound[i].lock >= 200)
630 Sound[i].lock = 199;
631
632 for(i=0;i<11;i++)
633 if(lumplockbyte[i] >= 200)
634 lumplockbyte[i] = 199;
635 }
636
637