i_sound.c (11575B)
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <stdarg.h> 4 5 #include <math.h> 6 #include <errno.h> 7 8 #include <sys/time.h> 9 #include <sys/types.h> 10 11 #include <fcntl.h> 12 #include <unistd.h> 13 #include <sys/ioctl.h> 14 15 16 #include <linux/soundcard.h> 17 18 19 #include <time.h> 20 #include <signal.h> 21 22 #include "z_zone.h" 23 24 #include "i_system.h" 25 #include "i_sound.h" 26 #include "m_argv.h" 27 #include "m_misc.h" 28 #include "w_wad.h" 29 30 #include "doomdef.h" 31 32 33 #ifdef SNDSERV 34 35 FILE* sndserver=0; 36 char* sndserver_filename = "./sndserver "; 37 #elif SNDINTR 38 39 40 41 42 #define SOUND_INTERVAL 500 43 44 45 int I_SoundSetTimer( int duration_of_tick ); 46 void I_SoundDelTimer( void ); 47 #else 48 49 #endif 50 51 52 53 54 55 static int flag = 0; 56 57 58 59 60 61 62 63 64 #define SAMPLECOUNT 512 65 #define NUM_CHANNELS 8 66 67 #define BUFMUL 4 68 #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL) 69 70 #define SAMPLERATE 11025 71 #define SAMPLESIZE 2 72 73 74 int lengths[NUMSFX]; 75 76 77 int audio_fd; 78 79 80 81 82 83 signed short mixbuffer[MIXBUFFERSIZE]; 84 85 86 87 unsigned int channelstep[NUM_CHANNELS]; 88 89 unsigned int channelstepremainder[NUM_CHANNELS]; 90 91 92 93 unsigned char* channels[NUM_CHANNELS]; 94 unsigned char* channelsend[NUM_CHANNELS]; 95 96 97 98 99 100 101 102 int channelstart[NUM_CHANNELS]; 103 104 105 106 107 108 int channelhandles[NUM_CHANNELS]; 109 110 111 112 int channelids[NUM_CHANNELS]; 113 114 115 int steptable[256]; 116 117 118 int vol_lookup[128*256]; 119 120 121 int* channelleftvol_lookup[NUM_CHANNELS]; 122 int* channelrightvol_lookup[NUM_CHANNELS]; 123 124 125 126 127 128 129 130 void 131 myioctl 132 ( int fd, 133 int command, 134 int* arg ) 135 { 136 int rc; 137 138 rc = ioctl(fd, command, arg); 139 if (rc < 0) 140 { 141 fprintf(stderr, "ioctl(dsp,%d,arg) failed\n", command); 142 fprintf(stderr, "errno=%d\n", errno); 143 exit(-1); 144 } 145 } 146 147 148 149 150 151 152 153 154 155 void* 156 getsfx 157 ( char* sfxname, 158 int* len ) 159 { 160 unsigned char* sfx; 161 unsigned char* paddedsfx; 162 int i; 163 int size; 164 int paddedsize; 165 char name[20]; 166 int sfxlump; 167 168 169 170 171 sprintf(name, "DS%s", sfxname); 172 173 174 175 176 177 178 179 180 181 182 183 if ( W_CheckNumForName(name) == -1 ) 184 sfxlump = W_GetNumForName("DSPISTOL"); 185 else 186 sfxlump = W_GetNumForName(name); 187 188 size = W_LumpLength( sfxlump ); 189 190 191 192 193 194 195 196 sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC ); 197 198 199 200 paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT; 201 202 203 paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 ); 204 205 206 207 208 209 memcpy( paddedsfx, sfx, size ); 210 for (i=size ; i<paddedsize+8 ; i++) 211 paddedsfx[i] = 128; 212 213 214 Z_Free( sfx ); 215 216 217 *len = paddedsize; 218 219 220 return (void *) (paddedsfx + 8); 221 } 222 223 224 225 226 227 228 229 230 231 232 233 234 int 235 addsfx 236 ( int sfxid, 237 int volume, 238 int step, 239 int seperation ) 240 { 241 static unsigned short handlenums = 0; 242 243 int i; 244 int rc = -1; 245 246 int oldest = gametic; 247 int oldestnum = 0; 248 int slot; 249 250 int rightvol; 251 int leftvol; 252 253 254 255 if ( sfxid == sfx_sawup 256 || sfxid == sfx_sawidl 257 || sfxid == sfx_sawful 258 || sfxid == sfx_sawhit 259 || sfxid == sfx_stnmov 260 || sfxid == sfx_pistol ) 261 { 262 263 for (i=0 ; i<NUM_CHANNELS ; i++) 264 { 265 266 if ( (channels[i]) 267 && (channelids[i] == sfxid) ) 268 { 269 270 channels[i] = 0; 271 272 273 break; 274 } 275 } 276 } 277 278 279 for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++) 280 { 281 if (channelstart[i] < oldest) 282 { 283 oldestnum = i; 284 oldest = channelstart[i]; 285 } 286 } 287 288 289 290 291 292 if (i == NUM_CHANNELS) 293 slot = oldestnum; 294 else 295 slot = i; 296 297 298 299 300 channels[slot] = (unsigned char *) S_sfx[sfxid].data; 301 302 channelsend[slot] = channels[slot] + lengths[sfxid]; 303 304 305 if (!handlenums) 306 handlenums = 100; 307 308 309 310 channelhandles[slot] = rc = handlenums++; 311 312 313 314 channelstep[slot] = step; 315 316 channelstepremainder[slot] = 0; 317 318 channelstart[slot] = gametic; 319 320 321 322 seperation += 1; 323 324 325 326 327 leftvol = 328 volume - ((volume*seperation*seperation) >> 16); 329 seperation = seperation - 257; 330 rightvol = 331 volume - ((volume*seperation*seperation) >> 16); 332 333 334 if (rightvol < 0 || rightvol > 127) 335 I_Error("rightvol out of bounds"); 336 337 if (leftvol < 0 || leftvol > 127) 338 I_Error("leftvol out of bounds"); 339 340 341 342 channelleftvol_lookup[slot] = &vol_lookup[leftvol*256]; 343 channelrightvol_lookup[slot] = &vol_lookup[rightvol*256]; 344 345 346 347 channelids[slot] = sfxid; 348 349 350 return rc; 351 } 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 void I_SetChannels() 367 { 368 369 370 371 int i; 372 int j; 373 374 int* steptablemid = steptable + 128; 375 376 377 /*for (i=0; i<NUM_CHANNELS; i++) 378 { 379 channels[i] = 0; 380 }*/ 381 382 383 384 for (i=-128 ; i<128 ; i++) 385 steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0); 386 387 388 389 390 391 for (i=0 ; i<128 ; i++) 392 for (j=0 ; j<256 ; j++) 393 vol_lookup[i*256+j] = (i*(j-128)*256)/127; 394 } 395 396 397 void I_SetSfxVolume(int volume) 398 { 399 400 401 402 403 404 snd_SfxVolume = volume; 405 } 406 407 408 void I_SetMusicVolume(int volume) 409 { 410 411 snd_MusicVolume = volume; 412 413 414 } 415 416 417 418 419 420 421 int I_GetSfxLumpNum(sfxinfo_t* sfx) 422 { 423 char namebuf[9]; 424 sprintf(namebuf, "DS%s", sfx->name); 425 return W_GetNumForName(namebuf); 426 } 427 428 429 430 431 432 433 434 435 436 437 438 439 440 int 441 I_StartSound 442 ( int id, 443 int vol, 444 int sep, 445 int pitch, 446 int priority ) 447 { 448 449 450 priority = 0; 451 452 #ifdef SNDSERV 453 if (sndserver) 454 { 455 fprintf(sndserver, "p%2.2x%2.2x%2.2x%2.2x\n", id, pitch, vol, sep); 456 fflush(sndserver); 457 } 458 459 return id; 460 #else 461 462 463 464 465 id = addsfx( id, vol, steptable[pitch], sep ); 466 467 468 469 return id; 470 #endif 471 } 472 473 474 475 void I_StopSound (int handle) 476 { 477 478 479 480 481 482 483 handle = 0; 484 } 485 486 487 int I_SoundIsPlaying(int handle) 488 { 489 490 return gametic < handle; 491 } 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 void I_UpdateSound( void ) 510 { 511 #ifdef SNDINTR 512 static int misses = 0; 513 #endif 514 515 516 517 518 register unsigned int sample; 519 register int dl; 520 register int dr; 521 522 523 signed short* leftout; 524 signed short* rightout; 525 signed short* leftend; 526 527 int step; 528 529 530 int chan; 531 532 533 534 leftout = mixbuffer; 535 rightout = mixbuffer+1; 536 step = 2; 537 538 539 540 leftend = mixbuffer + SAMPLECOUNT*step; 541 542 543 544 545 while (leftout != leftend) 546 { 547 548 dl = 0; 549 dr = 0; 550 551 552 553 554 for ( chan = 0; chan < NUM_CHANNELS; chan++ ) 555 { 556 557 if (channels[ chan ]) 558 { 559 560 sample = *channels[ chan ]; 561 562 563 564 565 dl += channelleftvol_lookup[ chan ][sample]; 566 dr += channelrightvol_lookup[ chan ][sample]; 567 568 channelstepremainder[ chan ] += channelstep[ chan ]; 569 570 channels[ chan ] += channelstepremainder[ chan ] >> 16; 571 572 channelstepremainder[ chan ] &= 65536-1; 573 574 575 if (channels[ chan ] >= channelsend[ chan ]) 576 channels[ chan ] = 0; 577 } 578 } 579 580 581 582 583 584 585 586 if (dl > 0x7fff) 587 *leftout = 0x7fff; 588 else if (dl < -0x8000) 589 *leftout = -0x8000; 590 else 591 *leftout = dl; 592 593 594 if (dr > 0x7fff) 595 *rightout = 0x7fff; 596 else if (dr < -0x8000) 597 *rightout = -0x8000; 598 else 599 *rightout = dr; 600 601 602 leftout += step; 603 rightout += step; 604 } 605 606 #ifdef SNDINTR 607 608 if ( flag ) 609 { 610 misses += flag; 611 flag = 0; 612 } 613 614 if ( misses > 10 ) 615 { 616 fprintf( stderr, "I_SoundUpdate: missed 10 buffer writes\n"); 617 misses = 0; 618 } 619 620 621 flag++; 622 #endif 623 } 624 625 626 627 628 629 630 631 632 633 634 void 635 I_SubmitSound(void) 636 { 637 638 write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); 639 } 640 641 642 643 void 644 I_UpdateSoundParams 645 ( int handle, 646 int vol, 647 int sep, 648 int pitch) 649 { 650 651 652 653 654 655 656 handle = vol = sep = pitch = 0; 657 } 658 659 660 661 662 void I_ShutdownSound(void) 663 { 664 #ifdef SNDSERV 665 if (sndserver) 666 { 667 668 fprintf(sndserver, "q\n"); 669 fflush(sndserver); 670 } 671 #else 672 673 int done = 0; 674 int i; 675 676 677 678 fprintf( stderr, "I_ShutdownSound: NOT finishing pending sounds\n"); 679 fflush( stderr ); 680 681 while ( !done ) 682 { 683 for( i=0 ; i<8 && !channels[i] ; i++); 684 685 686 687 done=1; 688 } 689 #ifdef SNDINTR 690 I_SoundDelTimer(); 691 #endif 692 693 694 close ( audio_fd ); 695 #endif 696 697 698 return; 699 } 700 701 702 703 704 705 706 void 707 I_InitSound() 708 { 709 #ifdef SNDSERV 710 char buffer[256]; 711 712 if (getenv("DOOMWADDIR")) 713 sprintf(buffer, "%s/%s", 714 getenv("DOOMWADDIR"), 715 sndserver_filename); 716 else 717 sprintf(buffer, "%s", sndserver_filename); 718 719 720 if ( !access(buffer, X_OK) ) 721 { 722 strcat(buffer, " -quiet"); 723 sndserver = popen(buffer, "w"); 724 } 725 else 726 fprintf(stderr, "Could not start sound server [%s]\n", buffer); 727 #else 728 729 int i; 730 731 #ifdef SNDINTR 732 fprintf( stderr, "I_SoundSetTimer: %d microsecs\n", SOUND_INTERVAL ); 733 I_SoundSetTimer( SOUND_INTERVAL ); 734 #endif 735 736 737 fprintf( stderr, "I_InitSound: "); 738 739 audio_fd = open("/dev/dsp", O_WRONLY); 740 if (audio_fd<0) 741 fprintf(stderr, "Could not open /dev/dsp\n"); 742 743 744 i = 11 | (2<<16); 745 myioctl(audio_fd, SNDCTL_DSP_SETFRAGMENT, &i); 746 myioctl(audio_fd, SNDCTL_DSP_RESET, 0); 747 748 i=SAMPLERATE; 749 750 myioctl(audio_fd, SNDCTL_DSP_SPEED, &i); 751 752 i=1; 753 myioctl(audio_fd, SNDCTL_DSP_STEREO, &i); 754 755 myioctl(audio_fd, SNDCTL_DSP_GETFMTS, &i); 756 757 if (i&=AFMT_S16_LE) 758 myioctl(audio_fd, SNDCTL_DSP_SETFMT, &i); 759 else 760 fprintf(stderr, "Could not play signed 16 data\n"); 761 762 fprintf(stderr, " configured audio device\n" ); 763 764 765 766 fprintf( stderr, "I_InitSound: "); 767 768 for (i=1 ; i<NUMSFX ; i++) 769 { 770 771 if (!S_sfx[i].link) 772 { 773 774 S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] ); 775 } 776 else 777 { 778 779 S_sfx[i].data = S_sfx[i].link->data; 780 lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)]; 781 } 782 } 783 784 fprintf( stderr, " pre-cached all sound data\n"); 785 786 787 for ( i = 0; i< MIXBUFFERSIZE; i++ ) 788 mixbuffer[i] = 0; 789 790 791 fprintf(stderr, "I_InitSound: sound module ready\n"); 792 793 #endif 794 } 795 796 797 798 799 800 801 802 803 804 void I_InitMusic(void) { } 805 void I_ShutdownMusic(void) { } 806 807 static int looping=0; 808 static int musicdies=-1; 809 810 void I_PlaySong(int handle, int looping) 811 { 812 813 handle = looping = 0; 814 musicdies = gametic + TICRATE*30; 815 } 816 817 void I_PauseSong (int handle) 818 { 819 820 handle = 0; 821 } 822 823 void I_ResumeSong (int handle) 824 { 825 826 handle = 0; 827 } 828 829 void I_StopSong(int handle) 830 { 831 832 handle = 0; 833 834 looping = 0; 835 musicdies = 0; 836 } 837 838 void I_UnRegisterSong(int handle) 839 { 840 841 handle = 0; 842 } 843 844 int I_RegisterSong(void* data) 845 { 846 847 data = NULL; 848 849 return 1; 850 } 851 852 853 int I_QrySongPlaying(int handle) 854 { 855 856 handle = 0; 857 return looping || musicdies > gametic; 858 } 859 860 861 862 863 864 865 866 867 868 869 870 #ifdef sun 871 typedef sigset_t tSigSet; 872 #else 873 typedef int tSigSet; 874 #endif 875 876 877 878 879 880 881 static int /*__itimer_which*/ itimer = ITIMER_REAL; 882 883 static int sig = SIGALRM; 884 885 886 void I_HandleSoundTimer( int ignore ) 887 { 888 889 890 891 892 if ( flag ) 893 { 894 895 896 write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL); 897 898 899 flag = 0; 900 } 901 else 902 return; 903 904 905 ignore = 0; 906 return; 907 } 908 909 910 int I_SoundSetTimer( int duration_of_tick ) 911 { 912 913 struct itimerval value; 914 struct itimerval ovalue; 915 struct sigaction act; 916 struct sigaction oact; 917 918 int res; 919 920 921 922 923 924 act.sa_handler = I_HandleSoundTimer; 925 #ifndef sun 926 927 #endif 928 act.sa_flags = SA_RESTART; 929 930 sigaction( sig, &act, &oact ); 931 932 value.it_interval.tv_sec = 0; 933 value.it_interval.tv_usec = duration_of_tick; 934 value.it_value.tv_sec = 0; 935 value.it_value.tv_usec = duration_of_tick; 936 937 938 res = setitimer( itimer, &value, &ovalue ); 939 940 941 if ( res == -1 ) 942 fprintf( stderr, "I_SoundSetTimer: interrupt n.a.\n"); 943 944 return res; 945 } 946 947 948 949 void I_SoundDelTimer() 950 { 951 952 if ( I_SoundSetTimer( 0 ) == -1) 953 fprintf( stderr, "I_SoundDelTimer: failed to remove interrupt. Doh!\n"); 954 }