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