i_sound.c
上传用户:xuyinpeng
上传日期:2021-05-12
资源大小:455k
文件大小:29k
源码类别:

射击游戏

开发平台:

Visual C++

  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. static const char
  24. rcsid[] = "$Id: i_unix.c,v 1.5 1997/02/03 22:45:10 b1 Exp $";
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <stdarg.h>
  28. #include <math.h>
  29. #include <time.h>
  30. #include <sys/types.h>
  31. //#ifndef LINUX
  32. //#include <sys/filio.h>
  33. //#endif
  34. #include <fcntl.h>
  35. #include <io.h>
  36. //#include <unistd.h>
  37. //#include <sys/ioctl.h>
  38. // Linux voxware output.
  39. //#include <linux/soundcard.h>
  40. // Timer stuff. Experimental.
  41. #include <time.h>
  42. #include <signal.h>
  43. #include "z_zone.h"
  44. #include "i_system.h"
  45. #include "i_sound.h"
  46. #include "m_argv.h"
  47. #include "m_misc.h"
  48. #include "w_wad.h"
  49. #include "doomdef.h"
  50. ////////////////////////////////////////////////////////////////////////////
  51. // WinDoom - DirectSound
  52. ////////////////////////////////////////////////////////////////////////////
  53. #include <dsound.h>
  54. char MsgText[256];
  55. void WriteDebug(char *);
  56. #define NUM_SOUND_FX 128
  57. #define SB_SIZE      20480
  58. void CreateSoundBuffer(int Channel, int length, unsigned char *data);
  59. void I_PlaySoundEffect(int sfxid, int Channel, int volume, int pan);
  60. void DS_Error( HRESULT hresult, char *msg );
  61. #define NUM_DSBUFFERS 256
  62. typedef enum { dsb_perm, dsb_temp } dsb_type;
  63. extern LPDIRECTSOUND        lpDS;
  64. extern LPDIRECTSOUNDBUFFER  lpDSBuffer[NUM_DSBUFFERS];
  65. typedef struct
  66.    {
  67.     void   *origin;
  68.     int     dsb_type;
  69.     int     sfxid;
  70.    }DSBControl_t;
  71. DSBControl_t DSBControl[NUM_DSBUFFERS];
  72. extern int swap_stereo;
  73. ////////////////////////////////////////////////////////////////////////////
  74. // UNIX hack, to be removed.
  75. #ifdef SNDSERV
  76. // Separate sound server process.
  77. FILE* sndserver=0;
  78. char* sndserver_filename = "./sndserver ";
  79. #elif SNDINTR
  80. // Update all 30 millisecs, approx. 30fps synchronized.
  81. // Linux resolution is allegedly 10 millisecs,
  82. //  scale is microseconds.
  83. #define SOUND_INTERVAL     500
  84. // Get the interrupt. Set duration in millisecs.
  85. int I_SoundSetTimer( int duration_of_tick );
  86. void I_SoundDelTimer( void );
  87. #else
  88. // None?
  89. #endif
  90. // A quick hack to establish a protocol between
  91. // synchronous mix buffer updates and asynchronous
  92. // audio writes. Probably redundant with gametic.
  93. static int flag = 0;
  94. // The number of internal mixing channels,
  95. //  the samples calculated for each mixing step,
  96. //  the size of the 16bit, 2 hardware channel (stereo)
  97. //  mixing buffer, and the samplerate of the raw data.
  98. // Needed for calling the actual sound output.
  99. #define SAMPLECOUNT 512
  100. #define NUM_CHANNELS 16
  101. // It is 2 for 16bit, and 2 for two channels.
  102. #define BUFMUL                  4
  103. #define MIXBUFFERSIZE (SAMPLECOUNT*BUFMUL)
  104. #define SAMPLERATE 11025 // Hz
  105. #define SAMPLESIZE 2    // 16bit
  106. // The actual lengths of all sound effects.
  107. int  lengths[NUMSFX];
  108. // The actual output device.
  109. int audio_fd;
  110. // The global mixing buffer.
  111. // Basically, samples from all active internal channels
  112. //  are modifed and added, and stored in the buffer
  113. //  that is submitted to the audio device.
  114. signed short mixbuffer[MIXBUFFERSIZE];
  115. // The channel step amount...
  116. unsigned int channelstep[NUM_CHANNELS];
  117. // ... and a 0.16 bit remainder of last step.
  118. unsigned int channelstepremainder[NUM_CHANNELS];
  119. // The channel data pointers, start and end.
  120. unsigned char* channels[NUM_CHANNELS];
  121. unsigned char* channelsend[NUM_CHANNELS];
  122. // Time/gametic that the channel started playing,
  123. //  used to determine oldest, which automatically
  124. //  has lowest priority.
  125. // In case number of active sounds exceeds
  126. //  available channels.
  127. int channelstart[NUM_CHANNELS];
  128. // The sound in channel handles,
  129. //  determined on registration,
  130. //  might be used to unregister/stop/modify,
  131. //  currently unused.
  132. int  channelhandles[NUM_CHANNELS];
  133. // SFX id of the playing sound effect.
  134. // Used to catch duplicates (like chainsaw).
  135. int channelids[NUM_DSBUFFERS];
  136. // Pitch to stepping lookup, unused.
  137. int steptable[256];
  138. // Volume lookups.
  139. int vol_lookup[128*256];
  140. // Hardware left and right channel volume lookup.
  141. int* channelleftvol_lookup[NUM_CHANNELS];
  142. int* channelrightvol_lookup[NUM_CHANNELS];
  143. //
  144. // Safe ioctl, convenience.
  145. //
  146. void
  147. myioctl
  148. ( int fd,
  149.   int command,
  150.   int* arg )
  151. {   
  152. // FIXME
  153. /*
  154.     int rc;
  155.     extern int errno;
  156.     
  157.     rc = ioctl(fd, command, arg);  
  158.     if (rc < 0)
  159.     {
  160. fprintf(stderr, "ioctl(dsp,%d,arg) failedn", command);
  161. fprintf(stderr, "errno=%dn", errno);
  162. exit(-1);
  163.     }
  164. */
  165. }
  166. //
  167. // This function loads the sound data from the WAD lump,
  168. //  for single sound.
  169. //
  170. void *getsfx( char *sfxname, int *len )
  171.    {
  172.     unsigned char*      sfx;
  173.     unsigned char*      paddedsfx;
  174.     int                 i;
  175.     int                 size;
  176.     int                 paddedsize;
  177.     char                name[20];
  178.     int                 sfxlump;
  179.    
  180.     sprintf(name, "ds%s", sfxname);
  181.     // Get the sound data from the WAD, allocate lump
  182.     //  in zone memory.
  183.     // Now, there is a severe problem with the
  184.     //  sound handling, in it is not (yet/anymore)
  185.     //  gamemode aware. That means, sounds from
  186.     //  DOOM II will be requested even with DOOM
  187.     //  shareware.
  188.     // The sound list is wired into sounds.c,
  189.     //  which sets the external variable.
  190.     // I do not do runtime patches to that
  191.     //  variable. Instead, we will use a
  192.     //  default sound for replacement.
  193.     if ( W_CheckNumForName(name) == -1 )
  194.       sfxlump = W_GetNumForName("dspistol");
  195.     else
  196.       sfxlump = W_GetNumForName(name);
  197.     
  198.     size = W_LumpLength( sfxlump );
  199. //    sprintf(MsgText, "Getting sound effect : %s - %dn", name, size);
  200. //    WriteDebug(MsgText);
  201.     // Debug.
  202.     // fprintf( stderr, "." );
  203.     //fprintf( stderr, " -loading  %s (lump %d, %d bytes)n",
  204.     //      sfxname, sfxlump, size );
  205.     //fflush( stderr );
  206.     
  207.     sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC );
  208.     // Pads the sound effect out to the mixing buffer size.
  209.     // The original realloc would interfere with zone memory.
  210.     paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
  211.     // Allocate from zone memory.
  212.     paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );
  213.     // ddt: (unsigned char *) realloc(sfx, paddedsize+8);
  214.     // This should interfere with zone memory handling,
  215.     //  which does not kick in in the soundserver.
  216.     // Now copy and pad.
  217.     memcpy(  paddedsfx, sfx, size );
  218.     for (i = size; i < paddedsize+8; i++)
  219.         paddedsfx[i] = 128;
  220.     // Remove the cached lump.
  221.     Z_Free( sfx );
  222.     
  223.     // Preserve padded length.
  224.     *len = paddedsize;
  225.     // Return allocated padded data.
  226.     return (void *) (paddedsfx + 8);
  227.    }
  228. /*
  229. //
  230. // This function adds a sound to the
  231. //  list of currently active sounds,
  232. //  which is maintained as a given number
  233. //  (eight, usually) of internal channels.
  234. // Returns a handle.
  235. //
  236. int addsfx( int sfxid, int volume, int step, int seperation )
  237.    {
  238.     static unsigned short handlenums = 0;
  239.  
  240.     int i;
  241.     int rc = -1;
  242.     
  243.     int oldest = gametic;
  244.     int oldestnum = 0;
  245.     int slot;
  246.     int rightvol;
  247.     int leftvol;
  248.     int     iVolume, iPan;
  249.     // Chainsaw troubles.
  250.     // Play these sound effects only one at a time.
  251.     if ( sfxid == sfx_sawup || sfxid == sfx_sawidl || sfxid == sfx_sawful ||
  252.          sfxid == sfx_sawhit || sfxid == sfx_stnmov || sfxid == sfx_pistol )
  253.        {
  254.         // Loop all channels, check.
  255.         for (i = 0; i < NUM_CHANNELS; i++)
  256.            {
  257.             // Active, and using the same SFX?
  258.             if ( (channels[i]) && (channelids[i] == sfxid) )
  259.                {
  260.                 // Reset.
  261.                 channels[i] = 0;
  262.                 // We are sure that iff, there will only be one.
  263.                 break;
  264.                }
  265.            }
  266.        }
  267.     // Loop all channels to find oldest SFX.
  268.     for (i = 0; (i<NUM_CHANNELS) && (channels[i]); i++)
  269.         {
  270.          if (channelstart[i] < oldest)
  271.             {
  272.              oldestnum = i;
  273.              oldest = channelstart[i];
  274.             }
  275.         }
  276.     // Tales from the cryptic.
  277.     // If we found a channel, fine.
  278.     // If not, we simply overwrite the first one, 0.
  279.     // Probably only happens at startup.
  280.     if (i == NUM_CHANNELS)
  281.         slot = oldestnum;
  282.     else
  283.         slot = i;
  284.     // Okay, in the less recent channel,
  285.     //  we will handle the new SFX.
  286.     // Set pointer to raw data.
  287.     channels[slot] = (unsigned char *) S_sfx[sfxid].data;
  288.     // Set pointer to end of raw data.
  289.     channelsend[slot] = channels[slot] + lengths[sfxid];
  290.     // Reset current handle number, limited to 0..100.
  291.     if (!handlenums)
  292.         handlenums = 100;
  293.     // Assign current handle number.
  294.     // Preserved so sounds could be stopped (unused).
  295.     channelhandles[slot] = rc = handlenums++;
  296.     // Set stepping???
  297.     // Kinda getting the impression this is never used.
  298.     channelstep[slot] = step;
  299.     // ???
  300.     channelstepremainder[slot] = 0;
  301.     // Should be gametic, I presume.
  302.     channelstart[slot] = gametic;
  303.     iVolume = 0-(128*(15-volume));
  304.     if (iVolume < -10000)
  305.        iVolume == -10000;
  306.     iPan = (seperation-128)*20;
  307.     if (iPan < -10000)
  308.        iPan = -10000;
  309.     if (iPan > 10000)
  310.        iPan = 10000;
  311.     if (swap_stereo == TRUE)
  312.        iPan *= -1;
  313.     // Separation, that is, orientation/stereo.
  314.     //  range is: 1 - 256
  315.     seperation += 1;
  316.     // Per left/right channel.
  317.     //  x^2 seperation,
  318.     //  adjust volume properly.
  319.     leftvol = volume - ((volume*seperation*seperation) >> 16); //(256*256);
  320.     seperation = seperation - 257;
  321.     rightvol = volume - ((volume*seperation*seperation) >> 16);
  322.     // Sanity check, clamp volume.
  323.     if (rightvol < 0 || rightvol > 127)
  324.         I_Error("rightvol out of bounds");
  325.     
  326.     if (leftvol < 0 || leftvol > 127)
  327.         I_Error("leftvol out of bounds");
  328.     
  329.     // Get the proper lookup table piece
  330.     //  for this volume level???
  331.     channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
  332.     channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
  333.     // Preserve sound SFX id,
  334.     //  e.g. for avoiding duplicates of chainsaw.
  335.     channelids[slot] = sfxid;
  336.     I_PlaySoundEffect(sfxid, iVolume, iPan);
  337.     // You tell me.
  338.     //return rc;
  339.     return sfxid;
  340.    }
  341. */
  342. //
  343. // This function adds a sound to the
  344. //  list of currently active sounds,
  345. //  which is maintained as a given number
  346. //  (eight, usually) of internal channels.
  347. // Returns a handle.
  348. //
  349. int addsfx( int sfxid, int volume, int step, int seperation, void *origin )
  350.    {
  351.     static unsigned short handlenums = 0;
  352.  
  353.     int i;
  354.     int rc = -1;
  355.     
  356.     int oldest = gametic;
  357.     int oldestnum = 0;
  358.     int slot;
  359.     int rightvol;
  360.     int leftvol;
  361.     int     iVolume, iPan;
  362.     DWORD   dwDSBStatus;
  363.     int     dsbchannel;
  364.     // Chainsaw troubles.
  365.     // Play these sound effects only one at a time.
  366.     if ( sfxid == sfx_sawup  || sfxid == sfx_sawidl || sfxid == sfx_sawful ||
  367.          sfxid == sfx_sawhit || sfxid == sfx_stnmov )
  368.         dsbchannel = sfxid;
  369.     else
  370.        {
  371.         dsbchannel = sfxid;
  372.         if (lpDSBuffer[0] != 0)
  373.             lpDSBuffer[sfxid]->lpVtbl->GetStatus(lpDSBuffer[sfxid], &dwDSBStatus);
  374.         else
  375.             dwDSBStatus = DS_OK;
  376.         if (dwDSBStatus == DSBSTATUS_PLAYING)
  377.            {
  378.             for (i = NUMSFX; i < NUM_DSBUFFERS; i++)
  379.                {
  380.                 if ((DSBControl[i].origin == origin) && (DSBControl[i].sfxid == sfxid))
  381.                    {
  382.                     dsbchannel = i;
  383.                     break;
  384.                    }
  385.                 if (DSBControl[i].sfxid == -1)
  386.                    {
  387.                     dsbchannel = i;
  388.                     DSBControl[i].origin = origin;
  389.                     break;
  390.                    }
  391.                 if (DSBControl[i].sfxid >= 0)
  392.                    {
  393.                     lpDSBuffer[i]->lpVtbl->GetStatus(lpDSBuffer[i], &dwDSBStatus);
  394.                     if (dwDSBStatus != DSBSTATUS_PLAYING)
  395.                        {
  396.                         dsbchannel = i;
  397.                         DSBControl[i].origin = origin;
  398.                         break;
  399.                        }
  400.                    }
  401.                 if (DSBControl[i].origin == origin)
  402.                    {
  403.                     dsbchannel = i;
  404.                     break;
  405.                    }
  406.                }
  407.            }
  408.        }
  409.     iVolume = 0-(128*(15-volume));
  410.     if (iVolume < -10000)
  411.        iVolume == -10000;
  412.     iPan = (seperation-128)*20;
  413.     if (iPan < -10000)
  414.        iPan = -10000;
  415.     if (iPan > 10000)
  416.        iPan = 10000;
  417.     if (swap_stereo == TRUE)
  418.        iPan *= -1;
  419.     // Preserve sound SFX id,
  420.     //  e.g. for avoiding duplicates of chainsaw.
  421.     channelids[dsbchannel] = sfxid;
  422.     I_PlaySoundEffect(sfxid, dsbchannel, iVolume, iPan);
  423.     // You tell me.
  424.     //return rc;
  425.     return dsbchannel;
  426.    }
  427. // This function call starts a sound playing in a DirectSound buffer...
  428. void I_PlaySoundEffect(int sfxid, int Channel, int iVolume, int iPan)
  429.    {
  430.     HRESULT hresult;
  431.     DWORD   dwDSBStatus;
  432.     if (Channel > NUM_SOUND_FX)
  433.        {
  434.         //WriteDebug("Invalid sound channel...n");
  435.         return;
  436.        }
  437.     if (lpDSBuffer[Channel] == 0)
  438.        {
  439.         //WriteDebug("Trying to play sound without DirectSound working...n");
  440.         return;
  441.        }
  442.     if ((DSBControl[Channel].dsb_type == dsb_temp) && (DSBControl[Channel].sfxid != sfxid))
  443.        {
  444.         if (DSBControl[Channel].sfxid > 0)
  445.            {
  446. /*
  447.             lpDSBuffer[Channel]->lpVtbl->GetStatus(lpDSBuffer[Channel], &dwDSBStatus);
  448.             if (dwDSBStatus == DSBSTATUS_PLAYING)
  449.                {
  450.                 hresult = lpDSBuffer[Channel]->lpVtbl->Stop(lpDSBuffer[Channel]);
  451.                 if (hresult != DS_OK)
  452.                     DS_Error(hresult, "lpDSBuffer.Stop");
  453.                }
  454. */
  455.             lpDSBuffer[Channel]->lpVtbl->Release(lpDSBuffer[Channel]);
  456.             DSBControl[Channel].sfxid = -1;
  457.            }
  458.         if (DSBControl[Channel].sfxid < 0)
  459.            {
  460.             // clone temp buffer here...
  461.             lpDS->lpVtbl->DuplicateSoundBuffer(lpDS, lpDSBuffer[sfxid], &lpDSBuffer[Channel]);
  462.             DSBControl[Channel].sfxid = sfxid;
  463.            }
  464.        }
  465. /*
  466.     else
  467.        {
  468.         lpDSBuffer[Channel]->lpVtbl->GetStatus(lpDSBuffer[Channel], &dwDSBStatus);
  469.         if (dwDSBStatus == DSBSTATUS_PLAYING)
  470.            {
  471.             hresult = lpDSBuffer[Channel]->lpVtbl->Stop(lpDSBuffer[Channel]);
  472.             if (hresult != DS_OK)
  473.                 DS_Error(hresult, "lpDSBuffer.Stop");
  474.            }
  475.        }
  476. */
  477.     hresult = lpDSBuffer[Channel]->lpVtbl->SetCurrentPosition(lpDSBuffer[Channel], 0);
  478.     if (hresult != DS_OK)
  479.         DS_Error(hresult, "lpDSBuffer.SetCurrentPosition");
  480.     hresult = lpDSBuffer[Channel]->lpVtbl->SetVolume(lpDSBuffer[Channel], iVolume );
  481.     if (hresult != DS_OK)
  482.         DS_Error(hresult, "lpDSBuffer.SetVolume");
  483.     hresult = lpDSBuffer[Channel]->lpVtbl->SetPan(lpDSBuffer[Channel], iPan);
  484.     if (hresult != DS_OK)
  485.         DS_Error(hresult, "lpDSBuffer.SetPan");
  486.     hresult = lpDSBuffer[Channel]->lpVtbl->Play(lpDSBuffer[Channel], 0, 0, 0);
  487.     if (hresult != DS_OK)
  488.         DS_Error(hresult, "lpDSBuffer.Play");
  489.    }
  490. //
  491. // SFX API
  492. // Note: this was called by S_Init.
  493. // However, whatever they did in the
  494. // old DPMS based DOS version, this
  495. // were simply dummies in the Linux
  496. // version.
  497. // See soundserver initdata().
  498. //
  499. void I_SetChannels()
  500. {
  501.   // Init internal lookups (raw data, mixing buffer, channels).
  502.   // This function sets up internal lookups used during
  503.   //  the mixing process. 
  504.   int i;
  505.   int j;
  506.     
  507.   int* steptablemid = steptable + 128;
  508.   
  509.   // Okay, reset internal mixing channels to zero.
  510.   for (i=0; i<NUM_CHANNELS; i++)
  511.   {
  512.     channels[i] = 0;
  513.   }
  514.   // This table provides step widths for pitch parameters.
  515.   // I fail to see that this is currently used.
  516.   for (i=-128 ; i<128 ; i++)
  517.     steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
  518.   
  519.   
  520.   // Generates volume lookup tables
  521.   //  which also turn the unsigned samples
  522.   //  into signed samples.
  523.   for (i=0 ; i<128 ; i++)
  524.     for (j=0 ; j<256 ; j++)
  525.       vol_lookup[i*256+j] = (i*(j-128)*256)/127;
  526. }
  527.  
  528. void I_SetSfxVolume(int volume)
  529. {
  530.   // Identical to DOS.
  531.   // Basically, this should propagate
  532.   //  the menu/config file setting
  533.   //  to the state variable used in
  534.   //  the mixing.
  535.   snd_SfxVolume = volume;
  536. }
  537. // MUSIC API - dummy. Some code from DOS version.
  538. void I_SetMusicVolume(int volume)
  539. {
  540.   // Internal state variable.
  541.   snd_MusicVolume = volume;
  542.   // Now set volume on output device.
  543.   // Whatever( snd_MusciVolume );
  544. }
  545. //
  546. // Retrieve the raw data lump index
  547. //  for a given SFX name.
  548. //
  549. int I_GetSfxLumpNum(sfxinfo_t* sfx)
  550. {
  551.     char namebuf[9];
  552.     sprintf(namebuf, "ds%s", sfx->name);
  553.     return W_GetNumForName(namebuf);
  554. }
  555. //
  556. // Starting a sound means adding it
  557. //  to the current list of active sounds
  558. //  in the internal channels.
  559. // As the SFX info struct contains
  560. //  e.g. a pointer to the raw data,
  561. //  it is ignored.
  562. // As our sound handling does not handle
  563. //  priority, it is ignored.
  564. // Pitching (that is, increased speed of playback)
  565. //  is set, but currently not used by mixing.
  566. //
  567. int I_StartSound( int id, int vol, int sep, int pitch, int priority, void *origin )
  568.    {
  569.     // UNUSED
  570.     priority = 0;
  571.   
  572.     // Debug.
  573. //    sprintf(MsgText, "starting sound %d", id );
  574. //    WriteDebug(MsgText);
  575.     
  576.     // Returns a handle (not used).
  577.     id = addsfx( id, vol, steptable[pitch], sep, origin );
  578. //    sprintf(MsgText, "/handle is %dn", id );
  579. //    WriteDebug(MsgText);
  580.     return id;
  581.    }
  582. void I_StopSound (int handle)
  583.    {
  584.     HRESULT hresult;
  585.   // You need the handle returned by StartSound.
  586.   // Would be looping all channels,
  587.   //  tracking down the handle,
  588.   //  an setting the channel to zero.
  589.   
  590.   // UNUSED.
  591. //    handle = 0;
  592.     if (handle > NUM_DSBUFFERS)
  593.        {
  594.         WriteDebug("Invalid sound channel...n");
  595.         return;
  596.        }
  597.     if (lpDSBuffer[handle] == 0)
  598.        {
  599.         WriteDebug("Trying to stop sound without DirectSound working...n");
  600.         return;
  601.        }
  602.     hresult = lpDSBuffer[handle]->lpVtbl->Stop(lpDSBuffer[handle]);
  603.     if (hresult != DS_OK)
  604.         DS_Error(hresult, "lpDSBuffer.Stop");
  605. /*
  606.     else
  607.     if (DSBControl[handle].dsb_type == dsb_temp)
  608.        {
  609.         lpDSBuffer[handle]->lpVtbl->Release(lpDSBuffer[handle]);
  610.         DSBControl[handle].origin = NULL;
  611.         DSBControl[handle].sfxid = -1;
  612.        }
  613. */
  614.    }
  615. int I_SoundIsPlaying(int handle)
  616.    {
  617.     DWORD dwStatus;
  618.     HRESULT hresult;
  619.     if (lpDSBuffer[handle] == 0)
  620.        {
  621.         //WriteDebug("Trying to get status of a sound without DirectSound working...n");
  622.         return FALSE;
  623.        }
  624.     hresult = lpDSBuffer[handle]->lpVtbl->GetStatus(lpDSBuffer[handle], &dwStatus);
  625.     if (hresult != DS_OK)
  626.         DS_Error(hresult, "lpDSBuffer.GetStatus");
  627.     return (dwStatus == DSBSTATUS_PLAYING);
  628.     // Ouch.
  629. //    return gametic < handle;
  630.    }
  631. //
  632. // This function loops all active (internal) sound
  633. //  channels, retrieves a given number of samples
  634. //  from the raw sound data, modifies it according
  635. //  to the current (internal) channel parameters,
  636. //  mixes the per channel samples into the global
  637. //  mixbuffer, clamping it to the allowed range,
  638. //  and sets up everything for transferring the
  639. //  contents of the mixbuffer to the (two)
  640. //  hardware channels (left and right, that is).
  641. //
  642. // This function currently supports only 16bit.
  643. //
  644. void I_UpdateSound( void )
  645.    {
  646. #ifdef SNDINTR
  647.   // Debug. Count buffer misses with interrupt.
  648.   static int misses = 0;
  649. #endif
  650.   
  651.     // Mix current sound data.
  652.     // Data, from raw sound, for right and left.
  653.     register unsigned int sample;
  654.     register int dl;
  655.     register int dr;
  656.   
  657.     // Pointers in global mixbuffer, left, right, end.
  658.     signed short* leftout;
  659.     signed short* rightout;
  660.     signed short* leftend;
  661.     // Step in mixbuffer, left and right, thus two.
  662.     int step;
  663.     // Mixing channel index.
  664.     int chan;
  665.     
  666.     // Left and right channel
  667.     //  are in global mixbuffer, alternating.
  668.     leftout = mixbuffer;
  669.     rightout = mixbuffer+1;
  670.     step = 2;
  671.     // Determine end, for left channel only
  672.     //  (right channel is implicit).
  673.     leftend = mixbuffer + SAMPLECOUNT*step;
  674.     // Mix sounds into the mixing buffer.
  675.     // Loop over step*SAMPLECOUNT,
  676.     //  that is 512 values for two channels.
  677.     while (leftout != leftend)
  678.     {
  679. // Reset left/right value. 
  680. dl = 0;
  681. dr = 0;
  682. // Love thy L2 chache - made this a loop.
  683. // Now more channels could be set at compile time
  684. //  as well. Thus loop those  channels.
  685. for ( chan = 0; chan < NUM_CHANNELS; chan++ )
  686. {
  687.     // Check channel, if active.
  688.     if (channels[ chan ])
  689.     {
  690. // Get the raw data from the channel. 
  691. sample = *channels[ chan ];
  692. // Add left and right part
  693. //  for this channel (sound)
  694. //  to the current data.
  695. // Adjust volume accordingly.
  696. dl += channelleftvol_lookup[ chan ][sample];
  697. dr += channelrightvol_lookup[ chan ][sample];
  698. // Increment index ???
  699. channelstepremainder[ chan ] += channelstep[ chan ];
  700. // MSB is next sample???
  701. channels[ chan ] += channelstepremainder[ chan ] >> 16;
  702. // Limit to LSB???
  703. channelstepremainder[ chan ] &= 65536-1;
  704. // Check whether we are done.
  705. if (channels[ chan ] >= channelsend[ chan ])
  706.     channels[ chan ] = 0;
  707.     }
  708. }
  709. // Clamp to range. Left hardware channel.
  710. // Has been char instead of short.
  711. // if (dl > 127) *leftout = 127;
  712. // else if (dl < -128) *leftout = -128;
  713. // else *leftout = dl;
  714. if (dl > 0x7fff)
  715.     *leftout = 0x7fff;
  716. else if (dl < -0x8000)
  717.     *leftout = -0x8000;
  718. else
  719.     *leftout = dl;
  720. // Same for right hardware channel.
  721. if (dr > 0x7fff)
  722.     *rightout = 0x7fff;
  723. else if (dr < -0x8000)
  724.     *rightout = -0x8000;
  725. else
  726.     *rightout = dr;
  727. // Increment current pointers in mixbuffer.
  728. leftout += step;
  729. rightout += step;
  730.     }
  731. #ifdef SNDINTR
  732.     // Debug check.
  733.     if ( flag )
  734.     {
  735.       misses += flag;
  736.       flag = 0;
  737.     }
  738.     
  739.     if ( misses > 10 )
  740.     {
  741.       fprintf( stderr, "I_SoundUpdate: missed 10 buffer writesn");
  742.       misses = 0;
  743.     }
  744.     
  745.     // Increment flag for update.
  746.     flag++;
  747. #endif
  748. }
  749. // 
  750. // This would be used to write out the mixbuffer
  751. //  during each game loop update.
  752. // Updates sound buffer and audio device at runtime. 
  753. // It is called during Timer interrupt with SNDINTR.
  754. // Mixing now done synchronous, and
  755. //  only output be done asynchronous?
  756. //
  757. void
  758. I_SubmitSound(void)
  759. {
  760.   // Write it to DSP device.
  761.   write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
  762. }
  763. void
  764. I_UpdateSoundParams
  765. ( int handle,
  766.   int vol,
  767.   int sep,
  768.   int pitch)
  769. {
  770.   // I fail too see that this is used.
  771.   // Would be using the handle to identify
  772.   //  on which channel the sound might be active,
  773.   //  and resetting the channel parameters.
  774.  int iVolume, iPan;
  775.  HRESULT hresult;
  776.  if (lpDSBuffer[handle] == 0)
  777.     return;
  778.     iVolume = 0-(128*(15-vol));
  779.     if (iVolume < -10000)
  780.        iVolume == -10000;
  781.     iPan = (sep-128)*20;
  782.     if (iPan < -10000)
  783.        iPan = -10000;
  784.     if (iPan > 10000)
  785.        iPan = 10000;
  786.     if (swap_stereo == TRUE)
  787.        iPan *= -1;
  788.     hresult = lpDSBuffer[handle]->lpVtbl->SetVolume(lpDSBuffer[handle], iVolume );
  789.     if (hresult != DS_OK)
  790.         DS_Error(hresult, "lpDSBuffer.SetVolume");
  791.     hresult = lpDSBuffer[handle]->lpVtbl->SetPan(lpDSBuffer[handle], iPan);
  792.     if (hresult != DS_OK)
  793.         DS_Error(hresult, "lpDSBuffer.SetPan");
  794.   // UNUSED.
  795.   //handle = vol = sep = pitch = 0;
  796. }
  797. void I_ShutdownSound(void)
  798. {    
  799. #ifdef SNDSERV
  800.   if (sndserver)
  801.   {
  802.     // Send a "quit" command.
  803.     fprintf(sndserver, "qn");
  804.     fflush(sndserver);
  805.   }
  806. #else
  807.   // Wait till all pending sounds are finished.
  808.   int done = 0;
  809.   int i;
  810.   
  811.   // FIXME (below).
  812.   fprintf( stderr, "I_ShutdownSound: NOT finishing pending soundsn");
  813.   fflush( stderr );
  814.   
  815.   while ( !done )
  816.   {
  817.     for( i=0 ; i<8 && !channels[i] ; i++);
  818.     
  819.     // FIXME. No proper channel output.
  820.     //if (i==8)
  821.     done=1;
  822.   }
  823. #ifdef SNDINTR
  824.   I_SoundDelTimer();
  825. #endif
  826.   
  827.   // Cleaning up -releasing the DSP device.
  828.   close ( audio_fd );
  829. #endif
  830.   // Done.
  831.   return;
  832. }
  833. void
  834. I_InitSound()
  835.   int i;
  836.   for (i = 1; i < NUMSFX; i++)
  837.      { 
  838.       // Alias? Example is the chaingun sound linked to pistol.
  839.       if (!S_sfx[i].link)
  840.          {
  841.           // Load data from WAD file.
  842.           S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
  843.          }
  844.       else
  845.          {
  846.           // Previously loaded already?
  847.           S_sfx[i].data = S_sfx[i].link->data;
  848.           lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
  849.          }
  850.       CreateSoundBuffer(i, lengths[i], S_sfx[i].data);
  851.       DSBControl[i].origin = NULL;
  852.       DSBControl[i].sfxid = i;
  853.       DSBControl[i].dsb_type = dsb_perm;
  854.      }
  855.   for (; i < NUM_DSBUFFERS; i++)
  856.      {
  857.       DSBControl[i].origin = NULL;
  858.       DSBControl[i].sfxid = -1;
  859.       DSBControl[i].dsb_type = dsb_temp;
  860.      }
  861. }
  862. //
  863. // MUSIC API.
  864. // Still no music done.
  865. // Remains. Dummies.
  866. //
  867. void I_InitMusic(void) { }
  868. void I_ShutdownMusic(void) { }
  869. static int looping=0;
  870. static int musicdies=-1;
  871. void I_PlaySong(int handle, int looping)
  872. {
  873.   // UNUSED.
  874.   handle = looping = 0;
  875.   musicdies = gametic + TICRATE*30;
  876. }
  877. void I_PauseSong (int handle)
  878. {
  879.   // UNUSED.
  880.   handle = 0;
  881. }
  882. void I_ResumeSong (int handle)
  883. {
  884.   // UNUSED.
  885.   handle = 0;
  886. }
  887. void I_StopSong(int handle)
  888. {
  889.   // UNUSED.
  890.   handle = 0;
  891.   
  892.   looping = 0;
  893.   musicdies = 0;
  894. }
  895. void I_UnRegisterSong(int handle)
  896. {
  897.   // UNUSED.
  898.   handle = 0;
  899. }
  900. int I_RegisterSong(void* data)
  901. {
  902.   // UNUSED.
  903.   data = NULL;
  904.   
  905.   return 1;
  906. }
  907. // Is the song playing?
  908. int I_QrySongPlaying(int handle)
  909. {
  910.   // UNUSED.
  911.   handle = 0;
  912.   return looping || musicdies > gametic;
  913. }
  914. //
  915. // Experimental stuff.
  916. // A Linux timer interrupt, for asynchronous
  917. //  sound output.
  918. // I ripped this out of the Timer class in
  919. //  our Difference Engine, including a few
  920. //  SUN remains...
  921. //  
  922. #ifdef sun
  923.     typedef     sigset_t        tSigSet;
  924. #else    
  925.     typedef     int             tSigSet;
  926. #endif
  927. // We might use SIGVTALRM and ITIMER_VIRTUAL, if the process
  928. //  time independend timer happens to get lost due to heavy load.
  929. // SIGALRM and ITIMER_REAL doesn't really work well.
  930. // There are issues with profiling as well.
  931. // FIXME
  932. #define ITIMER_REAL 0
  933. static int /*__itimer_which*/  itimer = ITIMER_REAL;
  934. // FIXME
  935. #define SIGALRM 0
  936. static int sig = SIGALRM;
  937. // Interrupt handler.
  938. void I_HandleSoundTimer( int ignore )
  939. {
  940.   // Debug.
  941.   //fprintf( stderr, "%c", '+' ); fflush( stderr );
  942.   
  943.   // Feed sound device if necesary.
  944.   if ( flag )
  945.   {
  946.     // See I_SubmitSound().
  947.     // Write it to DSP device.
  948.     write(audio_fd, mixbuffer, SAMPLECOUNT*BUFMUL);
  949.     // Reset flag counter.
  950.     flag = 0;
  951.   }
  952.   else
  953.     return;
  954.   
  955.   // UNUSED, but required.
  956.   ignore = 0;
  957.   return;
  958. }
  959. // Get the interrupt. Set duration in millisecs.
  960. int I_SoundSetTimer( int duration_of_tick )
  961. {
  962. /*
  963.   // Needed for gametick clockwork.
  964.   struct itimerval    value;
  965.   struct itimerval    ovalue;
  966.   struct sigaction    act;
  967.   struct sigaction    oact;
  968.   int res;
  969.   
  970.   // This sets to SA_ONESHOT and SA_NOMASK, thus we can not use it.
  971.   //     signal( _sig, handle_SIG_TICK );
  972.   
  973.   // Now we have to change this attribute for repeated calls.
  974.   act.sa_handler = I_HandleSoundTimer;
  975. #ifndef sun    
  976.   //ac t.sa_mask = _sig;
  977. #endif
  978.   act.sa_flags = SA_RESTART;
  979.   
  980.   sigaction( sig, &act, &oact );
  981.   value.it_interval.tv_sec    = 0;
  982.   value.it_interval.tv_usec   = duration_of_tick;
  983.   value.it_value.tv_sec       = 0;
  984.   value.it_value.tv_usec      = duration_of_tick;
  985.   // Error is -1.
  986.   res = setitimer( itimer, &value, &ovalue );
  987.   // Debug.
  988.   if ( res == -1 )
  989.     fprintf( stderr, "I_SoundSetTimer: interrupt n.a.n");
  990.   
  991.   return res;
  992. */
  993.  return 0;
  994. }
  995. // Remove the interrupt. Set duration to zero.
  996. void I_SoundDelTimer()
  997. {
  998.   // Debug.
  999.   if ( I_SoundSetTimer( 0 ) == -1)
  1000.     fprintf( stderr, "I_SoundDelTimer: failed to remove interrupt. Doh!n");
  1001. }