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