home *** CD-ROM | disk | FTP | other *** search
/ ST-Computer Leser-CD 2000 January / LCD_01_2000.iso / games / doom / pmdoom / src / i_sound.c < prev    next >
Encoding:
C/C++ Source or Header  |  1999-12-17  |  12.1 KB  |  511 lines

  1. /*  Emacs style mode select   -*- C++ -*-  */
  2. /* ----------------------------------------------------------------------------- */
  3. /*  */
  4. /*  $Id:$ */
  5. /*  */
  6. /*  Copyright (C) 1993-1996 by id Software, Inc. */
  7. /*  */
  8. /*  This source is available for distribution and/or modification */
  9. /*  only under the terms of the DOOM Source Code License as */
  10. /*  published by id Software. All rights reserved. */
  11. /*  */
  12. /*  The source is distributed in the hope that it will be useful, */
  13. /*  but WITHOUT ANY WARRANTY; without even the implied warranty of */
  14. /*  FITNESS FOR A PARTICULAR PURPOSE. See the DOOM Source Code License */
  15. /*  for more details. */
  16. /*  */
  17. /*  $Log:$ */
  18. /*  */
  19. /*  DESCRIPTION: */
  20. /*     System interface for sound. */
  21. /*  */
  22. /* ----------------------------------------------------------------------------- */
  23.  
  24. #include <stdio.h>
  25. #include <stdlib.h>
  26. #include <stdarg.h>
  27.  
  28. #include <math.h>
  29.  
  30. #include <sys/time.h>
  31. #include <sys/types.h>
  32.  
  33. #ifndef LINUX
  34. #ifndef ATARI
  35. #include <sys/filio.h>
  36. #endif
  37. #endif
  38.  
  39. #include <fcntl.h>
  40. #include <unistd.h>
  41. #include <sys/ioctl.h>
  42.  
  43. /*  Linux voxware output. */
  44. #ifdef LINUX
  45. #include <linux/soundcard.h>
  46. #endif
  47.  
  48. /*  Timer stuff. Experimental. */
  49. #include <time.h>
  50. #include <signal.h>
  51.  
  52. #include "z_zone.h"
  53.  
  54. #include "i_system.h"
  55. #include "i_sound.h"
  56. #include "m_argv.h"
  57. #include "m_misc.h"
  58. #include "w_wad.h"
  59.  
  60. #include "doomdef.h"
  61.  
  62. /*  The number of internal mixing channels, */
  63. /*   the samples calculated for each mixing step, */
  64. /*   the size of the 16bit, 2 hardware channel (stereo) */
  65. /*   mixing buffer, and the samplerate of the raw data. */
  66.  
  67.  
  68. /*  Needed for calling the actual sound output. */
  69. #define SAMPLECOUNT        512
  70. #define NUM_CHANNELS        8
  71. /*  It is 2 for 16bit, and 2 for two channels. */
  72. #define BUFMUL                  4
  73. #define MIXBUFFERSIZE        (SAMPLECOUNT*BUFMUL)
  74.  
  75. #define SAMPLERATE        11025    /*  Hz */
  76. #define SAMPLESIZE        2       /*  16bit */
  77.  
  78. /*  The actual lengths of all sound effects. */
  79. int         lengths[NUMSFX];
  80.  
  81. /*  The actual output device. */
  82. int    audio_fd;
  83.  
  84. /*  The global mixing buffer. */
  85. /*  Basically, samples from all active internal channels */
  86. /*   are modifed and added, and stored in the buffer */
  87. /*   that is submitted to the audio device. */
  88. signed short    mixbuffer[MIXBUFFERSIZE];
  89.  
  90.  
  91. /*  The channel step amount... */
  92. unsigned int    channelstep[NUM_CHANNELS];
  93. /*  ... and a 0.16 bit remainder of last step. */
  94. unsigned int    channelstepremainder[NUM_CHANNELS];
  95.  
  96.  
  97. /*  The channel data pointers, start and end. */
  98. unsigned char*    channels[NUM_CHANNELS];
  99. unsigned char*    channelsend[NUM_CHANNELS];
  100.  
  101.  
  102. /*  Time/gametic that the channel started playing, */
  103. /*   used to determine oldest, which automatically */
  104. /*   has lowest priority. */
  105. /*  In case number of active sounds exceeds */
  106. /*   available channels. */
  107. int        channelstart[NUM_CHANNELS];
  108.  
  109. /*  The sound in channel handles, */
  110. /*   determined on registration, */
  111. /*   might be used to unregister/stop/modify, */
  112. /*   currently unused. */
  113. int         channelhandles[NUM_CHANNELS];
  114.  
  115. /*  SFX id of the playing sound effect. */
  116. /*  Used to catch duplicates (like chainsaw). */
  117. int        channelids[NUM_CHANNELS];            
  118.  
  119. /*  Pitch to stepping lookup, unused. */
  120. int        steptable[256];
  121.  
  122. /*  Volume lookups. */
  123. int        vol_lookup[128*256];
  124.  
  125. /*  Hardware left and right channel volume lookup. */
  126. int*        channelleftvol_lookup[NUM_CHANNELS];
  127. int*        channelrightvol_lookup[NUM_CHANNELS];
  128.  
  129.  
  130. /*  */
  131. /*  This function loads the sound data from the WAD lump, */
  132. /*   for single sound. */
  133. /*  */
  134. void*
  135. getsfx
  136. ( char*         sfxname,
  137.   int*          len )
  138. {
  139.     unsigned char*      sfx;
  140.     int                 size;
  141.     int                 paddedsize;
  142.     char                name[20];
  143.     int                 sfxlump;
  144.  
  145.     
  146.     /*  Get the sound data from the WAD, allocate lump */
  147.     /*   in zone memory. */
  148.     sprintf(name, "ds%s", sfxname);
  149.  
  150.     /*  Now, there is a severe problem with the */
  151.     /*   sound handling, in it is not (yet/anymore) */
  152.     /*   gamemode aware. That means, sounds from */
  153.     /*   DOOM II will be requested even with DOOM */
  154.     /*   shareware. */
  155.     /*  The sound list is wired into sounds.c, */
  156.     /*   which sets the external variable. */
  157.     /*  I do not do runtime patches to that */
  158.     /*   variable. Instead, we will use a */
  159.     /*   default sound for replacement. */
  160.     if ( W_CheckNumForName(name) == -1 )
  161.       sfxlump = W_GetNumForName("dspistol");
  162.     else
  163.       sfxlump = W_GetNumForName(name);
  164.     
  165.     size = W_LumpLength( sfxlump );
  166.  
  167.     /*  Pads the sound effect out to the mixing buffer size. */
  168.     /*  The original realloc would interfere with zone memory. */
  169. #ifdef ATARI
  170.     paddedsize = size-8 + SAMPLECOUNT;
  171. #else
  172.     paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
  173. #endif
  174.     /*  Allocate from zone memory. */
  175.     sfx = (unsigned char*)W_CacheLumpNumPadded( sfxlump, PU_STATIC,paddedsize+8 );
  176.     memset(&sfx[size],128,paddedsize+8-size);
  177.     
  178.     /*  Preserve padded length. */
  179. #ifdef ATARI
  180.     *len = size-8;
  181. #else
  182.     *len = paddedsize;
  183. #endif
  184.     /*  Return allocated padded data. */
  185.     return (void *) (sfx + 8);
  186. }
  187.  
  188.  
  189.  
  190.  
  191.  
  192. /*  */
  193. /*  This function adds a sound to the */
  194. /*   list of currently active sounds, */
  195. /*   which is maintained as a given number */
  196. /*   (eight, usually) of internal channels. */
  197. /*  Returns a handle. */
  198. /*  */
  199. int
  200. addsfx
  201. ( int        sfxid,
  202.   int        volume,
  203.   int        step,
  204.   int        seperation )
  205. {
  206.     static unsigned short    handlenums = 0;
  207.  
  208.     int        i;
  209.     int        rc = -1;
  210.     
  211.     int        oldest = gametic;
  212.     int        oldestnum = 0;
  213.     int        slot;
  214.  
  215.     int        rightvol;
  216.     int        leftvol;
  217.  
  218.     /*  Chainsaw troubles. */
  219.     /*  Play these sound effects only one at a time. */
  220.     if ( sfxid == sfx_sawup
  221.      || sfxid == sfx_sawidl
  222.      || sfxid == sfx_sawful
  223.      || sfxid == sfx_sawhit
  224.      || sfxid == sfx_stnmov
  225.      || sfxid == sfx_pistol     )
  226.     {
  227.     /*  Loop all channels, check. */
  228.     for (i=0 ; i<NUM_CHANNELS ; i++)
  229.     {
  230.         /*  Active, and using the same SFX? */
  231.         if ( (channels[i])
  232.          && (channelids[i] == sfxid) )
  233.         {
  234.         /*  Reset. */
  235.         channels[i] = 0;
  236.         /*  We are sure that iff, */
  237.         /*   there will only be one. */
  238.         break;
  239.         }
  240.     }
  241.     }
  242.  
  243.     /*  Loop all channels to find oldest SFX. */
  244.     for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++)
  245.     {
  246.     if (channelstart[i] < oldest)
  247.     {
  248.         oldestnum = i;
  249.         oldest = channelstart[i];
  250.     }
  251.     }
  252.  
  253.     /*  Tales from the cryptic. */
  254.     /*  If we found a channel, fine. */
  255.     /*  If not, we simply overwrite the first one, 0. */
  256.     /*  Probably only happens at startup. */
  257.     if (i == NUM_CHANNELS)
  258.         slot = oldestnum;
  259.     else
  260.         slot = i;
  261.  
  262.     /* Uncache previous sample */
  263.     if (channelids[slot]>=0)
  264.     {
  265.         sfxinfo_t *oldsfx;
  266.  
  267.         oldsfx=&S_sfx[channelids[slot]];
  268.         (oldsfx->nbusing)--;
  269.         if ((oldsfx->nbusing)==0)
  270.         {
  271.             Z_ChangeTag( (oldsfx->data)-8, PU_CACHE);
  272.         }
  273.     }
  274.  
  275.     /*  Okay, in the less recent channel, */
  276.     /*   we will handle the new SFX. */
  277.     /*  Set pointer to raw data. */
  278.     channels[slot] = (unsigned char *) S_sfx[sfxid].data;
  279.     /*  Set pointer to end of raw data. */
  280.     channelsend[slot] = channels[slot] + lengths[sfxid];
  281.  
  282.     /*  Reset current handle number, limited to 0..100. */
  283.     if (!handlenums)
  284.     handlenums = 100;
  285.  
  286.     /*  Assign current handle number. */
  287.     /*  Preserved so sounds could be stopped (unused). */
  288.     channelhandles[slot] = rc = handlenums++;
  289.  
  290.     /*  Set stepping??? */
  291.     /*  Kinda getting the impression this is never used. */
  292. #ifdef ATARI
  293.     channelstep[slot]=0;
  294. #else
  295.     channelstep[slot] = step;
  296. #endif
  297.     /*  ??? */
  298.     channelstepremainder[slot] = 0;
  299.     /*  Should be gametic, I presume. */
  300.     channelstart[slot] = gametic;
  301.  
  302.     /*  Separation, that is, orientation/stereo. */
  303.     /*   range is: 1 - 256 */
  304.     seperation += 1;
  305.  
  306.     /*  Per left/right channel. */
  307.     /*   x^2 seperation, */
  308.     /*   adjust volume properly. */
  309.     leftvol =
  310.     volume - ((volume*seperation*seperation) >> 16); /* /(256*256); */
  311.     seperation = seperation - 257;
  312.     rightvol =
  313.     volume - ((volume*seperation*seperation) >> 16);    
  314.  
  315.     /*  Sanity check, clamp volume. */
  316.     if (rightvol<0) rightvol=0;
  317.     if (rightvol>127) rightvol=127;
  318.     if (leftvol<0) leftvol=0;
  319.     if (leftvol>127) leftvol=127;
  320.     
  321.     /*  Get the proper lookup table piece */
  322.     /*   for this volume level??? */
  323.     channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
  324.     channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
  325.  
  326.     /*  Preserve sound SFX id, */
  327.     /*   e.g. for avoiding duplicates of chainsaw. */
  328.     channelids[slot] = sfxid;
  329.  
  330.     /*  You tell me. */
  331.     return rc;
  332. }
  333.  
  334.  
  335.  
  336.  
  337.  
  338. /*  */
  339. /*  SFX API */
  340. /*  Note: this was called by S_Init. */
  341. /*  However, whatever they did in the */
  342. /*  old DPMS based DOS version, this */
  343. /*  were simply dummies in the Linux */
  344. /*  version. */
  345. /*  See soundserver initdata(). */
  346. /*  */
  347. void I_SetChannels()
  348. {
  349.   /*  Init internal lookups (raw data, mixing buffer, channels). */
  350.   /*  This function sets up internal lookups used during */
  351.   /*   the mixing process.  */
  352.   int        i;
  353.   int        j;
  354.     
  355.   int*    steptablemid = steptable + 128;
  356.   
  357.   /*  Okay, reset internal mixing channels to zero. */
  358.   /*for (i=0; i<NUM_CHANNELS; i++)
  359.   {
  360.     channels[i] = 0;
  361.   }*/
  362.  
  363.   /*  This table provides step widths for pitch parameters. */
  364.   /*  I fail to see that this is currently used. */
  365.   for (i=-128 ; i<128 ; i++)
  366.     steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
  367.   
  368.   /*  Generates volume lookup tables */
  369.   /*   which also turn the unsigned samples */
  370.   /*   into signed samples. */
  371.   for (i=0 ; i<128 ; i++)
  372.     for (j=0 ; j<256 ; j++)
  373.       vol_lookup[i*256+j] = (i*(j-128)*256)/127;
  374. }    
  375.  
  376.  
  377. void I_SetSfxVolume(int volume)
  378. {
  379.   /*  Identical to DOS. */
  380.   /*  Basically, this should propagate */
  381.   /*   the menu/config file setting */
  382.   /*   to the state variable used in */
  383.   /*   the mixing. */
  384.   snd_SfxVolume = volume;
  385. }
  386.  
  387. /*  MUSIC API - dummy. Some code from DOS version. */
  388. void I_SetMusicVolume(int volume)
  389. {
  390.   /*  Internal state variable. */
  391.   snd_MusicVolume = volume;
  392.   /*  Now set volume on output device. */
  393.   /*  Whatever( snd_MusciVolume ); */
  394. }
  395.  
  396.  
  397. /*  */
  398. /*  Retrieve the raw data lump index */
  399. /*   for a given SFX name. */
  400. /*  */
  401. int I_GetSfxLumpNum(sfxinfo_t* sfx)
  402. {
  403.     char namebuf[9];
  404.     sprintf(namebuf, "ds%s", sfx->name);
  405.     return W_GetNumForName(namebuf);
  406. }
  407.  
  408. int
  409. (*I_StartSound)
  410. ( int        id,
  411.   int        vol,
  412.   int        sep,
  413.   int        pitch,
  414.   int        priority );
  415.  
  416. void I_StopSound (int handle)
  417. {
  418.   /*  You need the handle returned by StartSound. */
  419.   /*  Would be looping all channels, */
  420.   /*   tracking down the handle, */
  421.   /*   an setting the channel to zero. */
  422.   
  423.   /*  UNUSED. */
  424.   handle = 0;
  425. }
  426.  
  427.  
  428. int I_SoundIsPlaying(int handle)
  429. {
  430.     /*  Ouch. */
  431.     return gametic < handle;
  432. }
  433.  
  434. void
  435. I_UpdateSoundParams
  436. ( int    handle,
  437.   int    vol,
  438.   int    sep,
  439.   int    pitch)
  440. {
  441.   /*  I fail too see that this is used. */
  442.   /*  Would be using the handle to identify */
  443.   /*   on which channel the sound might be active, */
  444.   /*   and resetting the channel parameters. */
  445.  
  446.   /*  UNUSED. */
  447.   handle = vol = sep = pitch = 0;
  448. }
  449.  
  450.  
  451. /*  */
  452. /*  MUSIC API. */
  453. /*  Still no music done. */
  454. /*  Remains. Dummies. */
  455. /*  */
  456. void I_InitMusic(void)        { }
  457. void I_ShutdownMusic(void)    { }
  458.  
  459. static int    looping=0;
  460. static int    musicdies=-1;
  461.  
  462. void I_PlaySong(int handle, int looping)
  463. {
  464.   /*  UNUSED. */
  465.   handle = looping = 0;
  466.   musicdies = gametic + TICRATE*30;
  467. }
  468.  
  469. void I_PauseSong (int handle)
  470. {
  471.   /*  UNUSED. */
  472.   handle = 0;
  473. }
  474.  
  475. void I_ResumeSong (int handle)
  476. {
  477.   /*  UNUSED. */
  478.   handle = 0;
  479. }
  480.  
  481. void I_StopSong(int handle)
  482. {
  483.   /*  UNUSED. */
  484.   handle = 0;
  485.   
  486.   looping = 0;
  487.   musicdies = 0;
  488. }
  489.  
  490. void I_UnRegisterSong(int handle)
  491. {
  492.   /*  UNUSED. */
  493.   handle = 0;
  494. }
  495.  
  496. int I_RegisterSong(void* data)
  497. {
  498.   /*  UNUSED. */
  499.   data = NULL;
  500.   
  501.   return 1;
  502. }
  503.  
  504. /*  Is the song playing? */
  505. int I_QrySongPlaying(int handle)
  506. {
  507.   /*  UNUSED. */
  508.   handle = 0;
  509.   return looping || musicdies > gametic;
  510. }
  511.