Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | RSS feed

  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 <math.h>
  28.  
  29. #include "SDL_audio.h"
  30. #include "SDL_mutex.h"
  31. #include "SDL_byteorder.h"
  32. #include "SDL_version.h"
  33.  
  34. #include "z_zone.h"
  35.  
  36. #include "m_swap.h"
  37. #include "i_system.h"
  38. #include "i_sound.h"
  39. #include "m_argv.h"
  40. #include "m_misc.h"
  41. #include "w_wad.h"
  42.  
  43. #include "doomdef.h"
  44.  
  45.  
  46. // The number of internal mixing channels,
  47. //  the samples calculated for each mixing step,
  48. //  the size of the 16bit, 2 hardware channel (stereo)
  49. //  mixing buffer, and the samplerate of the raw data.
  50.  
  51.  
  52. // Needed for calling the actual sound output.
  53. static int SAMPLECOUNT=         512;
  54. #define NUM_CHANNELS            8
  55.  
  56. #define SAMPLERATE              11025   // Hz
  57.  
  58. // The actual lengths of all sound effects.
  59. int             lengths[NUMSFX];
  60.  
  61. // The actual output device.
  62. int     audio_fd;
  63.  
  64.  
  65. // The channel step amount...
  66. unsigned int    channelstep[NUM_CHANNELS];
  67. // ... and a 0.16 bit remainder of last step.
  68. unsigned int    channelstepremainder[NUM_CHANNELS];
  69.  
  70.  
  71. // The channel data pointers, start and end.
  72. unsigned char*  channels[NUM_CHANNELS];
  73. unsigned char*  channelsend[NUM_CHANNELS];
  74.  
  75.  
  76. // Time/gametic that the channel started playing,
  77. //  used to determine oldest, which automatically
  78. //  has lowest priority.
  79. // In case number of active sounds exceeds
  80. //  available channels.
  81. int             channelstart[NUM_CHANNELS];
  82.  
  83. // The sound in channel handles,
  84. //  determined on registration,
  85. //  might be used to unregister/stop/modify,
  86. //  currently unused.
  87. int             channelhandles[NUM_CHANNELS];
  88.  
  89. // SFX id of the playing sound effect.
  90. // Used to catch duplicates (like chainsaw).
  91. int             channelids[NUM_CHANNELS];                      
  92.  
  93. // Pitch to stepping lookup, unused.
  94. int             steptable[256];
  95.  
  96. // Volume lookups.
  97. int             vol_lookup[128*256];
  98.  
  99. // Hardware left and right channel volume lookup.
  100. int*            channelleftvol_lookup[NUM_CHANNELS];
  101. int*            channelrightvol_lookup[NUM_CHANNELS];
  102.  
  103.  
  104.  
  105. //
  106. // This function loads the sound data from the WAD lump,
  107. //  for single sound.
  108. //
  109. void*
  110. getsfx
  111. ( char*         sfxname,
  112.   int*          len )
  113. {
  114.     unsigned char*      sfx;
  115.     unsigned char*      paddedsfx;
  116.     int                 i;
  117.     int                 size;
  118.     int                 paddedsize;
  119.     char                name[20];
  120.     int                 sfxlump;
  121.  
  122.    
  123.     // Get the sound data from the WAD, allocate lump
  124.     //  in zone memory.
  125.     sprintf(name, "ds%s", sfxname);
  126.  
  127.     // Now, there is a severe problem with the
  128.     //  sound handling, in it is not (yet/anymore)
  129.     //  gamemode aware. That means, sounds from
  130.     //  DOOM II will be requested even with DOOM
  131.     //  shareware.
  132.     // The sound list is wired into sounds.c,
  133.     //  which sets the external variable.
  134.     // I do not do runtime patches to that
  135.     //  variable. Instead, we will use a
  136.     //  default sound for replacement.
  137.     if ( W_CheckNumForName(name) == -1 )
  138.       sfxlump = W_GetNumForName("dspistol");
  139.     else
  140.       sfxlump = W_GetNumForName(name);
  141.    
  142.     size = W_LumpLength( sfxlump );
  143.  
  144.     // Debug.
  145.     // fprintf( stderr, "." );
  146.     //fprintf( stderr, " -loading  %s (lump %d, %d bytes)\n",
  147.     //       sfxname, sfxlump, size );
  148.     //fflush( stderr );
  149.    
  150.     sfx = (unsigned char*)W_CacheLumpNum( sfxlump, PU_STATIC );
  151.  
  152.     // Pads the sound effect out to the mixing buffer size.
  153.     // The original realloc would interfere with zone memory.
  154.     paddedsize = ((size-8 + (SAMPLECOUNT-1)) / SAMPLECOUNT) * SAMPLECOUNT;
  155.  
  156.     // Allocate from zone memory.
  157.     paddedsfx = (unsigned char*)Z_Malloc( paddedsize+8, PU_STATIC, 0 );
  158.     // ddt: (unsigned char *) realloc(sfx, paddedsize+8);
  159.     // This should interfere with zone memory handling,
  160.     //  which does not kick in in the soundserver.
  161.  
  162.     // Now copy and pad.
  163.     memcpy(  paddedsfx, sfx, size );
  164.     for (i=size ; i<paddedsize+8 ; i++)
  165.         paddedsfx[i] = 128;
  166.  
  167.     // Remove the cached lump.
  168.     Z_Free( sfx );
  169.    
  170.     // Preserve padded length.
  171.     *len = paddedsize;
  172.  
  173.     // Return allocated padded data.
  174.     return (void *) (paddedsfx + 8);
  175. }
  176.  
  177.  
  178.  
  179.  
  180.  
  181. //
  182. // This function adds a sound to the
  183. //  list of currently active sounds,
  184. //  which is maintained as a given number
  185. //  (eight, usually) of internal channels.
  186. // Returns a handle.
  187. //
  188. int
  189. addsfx
  190. ( int           sfxid,
  191.   int           volume,
  192.   int           step,
  193.   int           seperation )
  194. {
  195.     static unsigned short       handlenums = 0;
  196.  
  197.     int         i;
  198.     int         rc = -1;
  199.    
  200.     int         oldest = gametic;
  201.     int         oldestnum = 0;
  202.     int         slot;
  203.  
  204.     int         rightvol;
  205.     int         leftvol;
  206.  
  207.     // Chainsaw troubles.
  208.     // Play these sound effects only one at a time.
  209.     if ( sfxid == sfx_sawup
  210.          || sfxid == sfx_sawidl
  211.          || sfxid == sfx_sawful
  212.          || sfxid == sfx_sawhit
  213.          || sfxid == sfx_stnmov
  214.          || sfxid == sfx_pistol  )
  215.     {
  216.         // Loop all channels, check.
  217.         for (i=0 ; i<NUM_CHANNELS ; i++)
  218.         {
  219.             // Active, and using the same SFX?
  220.             if ( (channels[i])
  221.                  && (channelids[i] == sfxid) )
  222.             {
  223.                 // Reset.
  224.                 channels[i] = 0;
  225.                 // We are sure that iff,
  226.                 //  there will only be one.
  227.                 break;
  228.             }
  229.         }
  230.     }
  231.  
  232.     // Loop all channels to find oldest SFX.
  233.     for (i=0; (i<NUM_CHANNELS) && (channels[i]); i++)
  234.     {
  235.         if (channelstart[i] < oldest)
  236.         {
  237.             oldestnum = i;
  238.             oldest = channelstart[i];
  239.         }
  240.     }
  241.  
  242.     // Tales from the cryptic.
  243.     // If we found a channel, fine.
  244.     // If not, we simply overwrite the first one, 0.
  245.     // Probably only happens at startup.
  246.     if (i == NUM_CHANNELS)
  247.         slot = oldestnum;
  248.     else
  249.         slot = i;
  250.  
  251.     // Okay, in the less recent channel,
  252.     //  we will handle the new SFX.
  253.     // Set pointer to raw data.
  254.     channels[slot] = (unsigned char *) S_sfx[sfxid].data;
  255.     // Set pointer to end of raw data.
  256.     channelsend[slot] = channels[slot] + lengths[sfxid];
  257.  
  258.     // Reset current handle number, limited to 0..100.
  259.     if (!handlenums)
  260.         handlenums = 100;
  261.  
  262.     // Assign current handle number.
  263.     // Preserved so sounds could be stopped (unused).
  264.     channelhandles[slot] = rc = handlenums++;
  265.  
  266.     // Set stepping???
  267.     // Kinda getting the impression this is never used.
  268.     channelstep[slot] = step;
  269.     // ???
  270.     channelstepremainder[slot] = 0;
  271.     // Should be gametic, I presume.
  272.     channelstart[slot] = gametic;
  273.  
  274.     // Separation, that is, orientation/stereo.
  275.     //  range is: 1 - 256
  276.     seperation += 1;
  277.  
  278.     // Per left/right channel.
  279.     //  x^2 seperation,
  280.     //  adjust volume properly.
  281.     volume *= 8;
  282.     leftvol =
  283.         volume - ((volume*seperation*seperation) >> 16); ///(256*256);
  284.     seperation = seperation - 257;
  285.     rightvol =
  286.         volume - ((volume*seperation*seperation) >> 16);       
  287.  
  288.     // Sanity check, clamp volume.
  289.     if (rightvol < 0 || rightvol > 127)
  290.         I_Error("rightvol out of bounds");
  291.    
  292.     if (leftvol < 0 || leftvol > 127)
  293.         I_Error("leftvol out of bounds");
  294.    
  295.     // Get the proper lookup table piece
  296.     //  for this volume level???
  297.     channelleftvol_lookup[slot] = &vol_lookup[leftvol*256];
  298.     channelrightvol_lookup[slot] = &vol_lookup[rightvol*256];
  299.  
  300.     // Preserve sound SFX id,
  301.     //  e.g. for avoiding duplicates of chainsaw.
  302.     channelids[slot] = sfxid;
  303.  
  304.     // You tell me.
  305.     return rc;
  306. }
  307.  
  308.  
  309.  
  310.  
  311.  
  312. //
  313. // SFX API
  314. // Note: this was called by S_Init.
  315. // However, whatever they did in the
  316. // old DPMS based DOS version, this
  317. // were simply dummies in the Linux
  318. // version.
  319. // See soundserver initdata().
  320. //
  321. void I_SetChannels()
  322. {
  323.   // Init internal lookups (raw data, mixing buffer, channels).
  324.   // This function sets up internal lookups used during
  325.   //  the mixing process.
  326.   int           i;
  327.   int           j;
  328.    
  329.   int*  steptablemid = steptable + 128;
  330.  
  331.   // Okay, reset internal mixing channels to zero.
  332.   /*for (i=0; i<NUM_CHANNELS; i++)
  333.   {
  334.     channels[i] = 0;
  335.   }*/
  336.  
  337.   // This table provides step widths for pitch parameters.
  338.   // I fail to see that this is currently used.
  339.   for (i=-128 ; i<128 ; i++)
  340.     steptablemid[i] = (int)(pow(2.0, (i/64.0))*65536.0);
  341.  
  342.  
  343.   // Generates volume lookup tables
  344.   //  which also turn the unsigned samples
  345.   //  into signed samples.
  346.   for (i=0 ; i<128 ; i++)
  347.     for (j=0 ; j<256 ; j++) {
  348.       vol_lookup[i*256+j] = (i*(j-128)*256)/127;
  349. //fprintf(stderr, "vol_lookup[%d*256+%d] = %d\n", i, j, vol_lookup[i*256+j]);
  350.     }
  351. }      
  352.  
  353.  
  354. void I_SetSfxVolume(int volume)
  355. {
  356.   // Identical to DOS.
  357.   // Basically, this should propagate
  358.   //  the menu/config file setting
  359.   //  to the state variable used in
  360.   //  the mixing.
  361.   snd_SfxVolume = volume;
  362. }
  363.  
  364. // MUSIC API - dummy. Some code from DOS version.
  365. void I_SetMusicVolume(int volume)
  366. {
  367.   // Internal state variable.
  368.   snd_MusicVolume = volume;
  369.   // Now set volume on output device.
  370.   // Whatever( snd_MusciVolume );
  371. }
  372.  
  373.  
  374. //
  375. // Retrieve the raw data lump index
  376. //  for a given SFX name.
  377. //
  378. int I_GetSfxLumpNum(sfxinfo_t* sfx)
  379. {
  380.     char namebuf[9];
  381.     sprintf(namebuf, "ds%s", sfx->name);
  382.     return W_GetNumForName(namebuf);
  383. }
  384.  
  385. //
  386. // Starting a sound means adding it
  387. //  to the current list of active sounds
  388. //  in the internal channels.
  389. // As the SFX info struct contains
  390. //  e.g. a pointer to the raw data,
  391. //  it is ignored.
  392. // As our sound handling does not handle
  393. //  priority, it is ignored.
  394. // Pitching (that is, increased speed of playback)
  395. //  is set, but currently not used by mixing.
  396. //
  397. int
  398. I_StartSound
  399. ( int           id,
  400.   int           vol,
  401.   int           sep,
  402.   int           pitch,
  403.   int           priority )
  404. {
  405.  
  406.   // UNUSED
  407.   priority = 0;
  408.  
  409.     // Debug.
  410.     //fprintf( stderr, "starting sound %d", id );
  411.    
  412.     // Returns a handle (not used).
  413.     SDL_LockAudio();
  414.     id = addsfx( id, vol, steptable[pitch], sep );
  415.     SDL_UnlockAudio();
  416.  
  417.     // fprintf( stderr, "/handle is %d\n", id );
  418.    
  419.     return id;
  420. }
  421.  
  422.  
  423.  
  424. void I_StopSound (int handle)
  425. {
  426.   // You need the handle returned by StartSound.
  427.   // Would be looping all channels,
  428.   //  tracking down the handle,
  429.   //  an setting the channel to zero.
  430.  
  431.   // UNUSED.
  432.   handle = 0;
  433. }
  434.  
  435.  
  436. int I_SoundIsPlaying(int handle)
  437. {
  438.     // Ouch.
  439.     return gametic < handle;
  440. }
  441.  
  442.  
  443. //
  444. // This function loops all active (internal) sound
  445. //  channels, retrieves a given number of samples
  446. //  from the raw sound data, modifies it according
  447. //  to the current (internal) channel parameters,
  448. //  mixes the per channel samples into the given
  449. //  mixing buffer, and clamping it to the allowed
  450. //  range.
  451. //
  452. // This function currently supports only 16bit.
  453. //
  454. void I_UpdateSound(void *unused, Uint8 *stream, int len)
  455. {
  456.   // Mix current sound data.
  457.   // Data, from raw sound, for right and left.
  458.   register unsigned int sample;
  459.   register int          dl;
  460.   register int          dr;
  461.  
  462.   // Pointers in audio stream, left, right, end.
  463.   signed short*         leftout;
  464.   signed short*         rightout;
  465.   signed short*         leftend;
  466.   // Step in stream, left and right, thus two.
  467.   int                           step;
  468.  
  469.   // Mixing channel index.
  470.   int                           chan;
  471.    
  472.     // Left and right channel
  473.     //  are in audio stream, alternating.
  474.     leftout = (signed short *)stream;
  475.     rightout = ((signed short *)stream)+1;
  476.     step = 2;
  477.  
  478.     // Determine end, for left channel only
  479.     //  (right channel is implicit).
  480.     leftend = leftout + SAMPLECOUNT*step;
  481.  
  482.     // Mix sounds into the mixing buffer.
  483.     // Loop over step*SAMPLECOUNT,
  484.     //  that is 512 values for two channels.
  485.     while (leftout != leftend)
  486.     {
  487.         // Reset left/right value.
  488.         dl = 0;
  489.         dr = 0;
  490.  
  491.         // Love thy L2 chache - made this a loop.
  492.         // Now more channels could be set at compile time
  493.         //  as well. Thus loop those  channels.
  494.         for ( chan = 0; chan < NUM_CHANNELS; chan++ )
  495.         {
  496.             // Check channel, if active.
  497.             if (channels[ chan ])
  498.             {
  499.                 // Get the raw data from the channel.
  500.                 sample = *channels[ chan ];
  501.                 // Add left and right part
  502.                 //  for this channel (sound)
  503.                 //  to the current data.
  504.                 // Adjust volume accordingly.
  505.                 dl += channelleftvol_lookup[ chan ][sample];
  506.                 dr += channelrightvol_lookup[ chan ][sample];
  507.                 // Increment index ???
  508.                 channelstepremainder[ chan ] += channelstep[ chan ];
  509.                 // MSB is next sample???
  510.                 channels[ chan ] += channelstepremainder[ chan ] >> 16;
  511.                 // Limit to LSB???
  512.                 channelstepremainder[ chan ] &= 65536-1;
  513.  
  514.                 // Check whether we are done.
  515.                 if (channels[ chan ] >= channelsend[ chan ])
  516.                     channels[ chan ] = 0;
  517.             }
  518.         }
  519.        
  520.         // Clamp to range. Left hardware channel.
  521.         // Has been char instead of short.
  522.         // if (dl > 127) *leftout = 127;
  523.         // else if (dl < -128) *leftout = -128;
  524.         // else *leftout = dl;
  525.  
  526.         if (dl > 0x7fff)
  527.             *leftout = 0x7fff;
  528.         else if (dl < -0x8000)
  529.             *leftout = -0x8000;
  530.         else
  531.             *leftout = dl;
  532.  
  533.         // Same for right hardware channel.
  534.         if (dr > 0x7fff)
  535.             *rightout = 0x7fff;
  536.         else if (dr < -0x8000)
  537.             *rightout = -0x8000;
  538.         else
  539.             *rightout = dr;
  540.  
  541.         // Increment current pointers in stream
  542.         leftout += step;
  543.         rightout += step;
  544.     }
  545. }
  546.  
  547. void
  548. I_UpdateSoundParams
  549. ( int   handle,
  550.   int   vol,
  551.   int   sep,
  552.   int   pitch)
  553. {
  554.   // I fail too see that this is used.
  555.   // Would be using the handle to identify
  556.   //  on which channel the sound might be active,
  557.   //  and resetting the channel parameters.
  558.  
  559.   // UNUSED.
  560.   handle = vol = sep = pitch = 0;
  561. }
  562.  
  563.  
  564. void I_ShutdownSound(void)
  565. {    
  566.   SDL_CloseAudio();
  567. }
  568.  
  569.  
  570. void
  571. I_InitSound()
  572. {
  573.   SDL_AudioSpec wanted;
  574.   int i;
  575.  
  576.   // Secure and configure sound device first.
  577.   fprintf( stderr, "I_InitSound: ");
  578.  
  579.   // Open the audio device
  580.   wanted.freq = SAMPLERATE;
  581.   if ( SDL_BYTEORDER == SDL_BIG_ENDIAN ) {
  582.     wanted.format = AUDIO_S16MSB;
  583.   } else {
  584.     wanted.format = AUDIO_S16LSB;
  585.   }
  586.   wanted.channels = 2;
  587.   wanted.samples = SAMPLECOUNT;
  588.   wanted.callback = I_UpdateSound;
  589.   if ( SDL_OpenAudio(&wanted, NULL) < 0 ) {
  590.     fprintf(stderr, "couldn't open audio with desired format\n");
  591.     return;
  592.   }
  593.   SAMPLECOUNT = wanted.samples;
  594.   fprintf(stderr, " configured audio device with %d samples/slice\n", SAMPLECOUNT);
  595.  
  596.    
  597.   // Initialize external data (all sounds) at start, keep static.
  598.   fprintf( stderr, "I_InitSound: ");
  599.  
  600.   for (i=1 ; i<NUMSFX ; i++)
  601.   {
  602.     // Alias? Example is the chaingun sound linked to pistol.
  603.     if (!S_sfx[i].link)
  604.     {
  605.       // Load data from WAD file.
  606.       S_sfx[i].data = getsfx( S_sfx[i].name, &lengths[i] );
  607.     }  
  608.     else
  609.     {
  610.       // Previously loaded already?
  611.       S_sfx[i].data = S_sfx[i].link->data;
  612.       lengths[i] = lengths[(S_sfx[i].link - S_sfx)/sizeof(sfxinfo_t)];
  613.     }
  614.   }
  615.  
  616.   fprintf( stderr, " pre-cached all sound data\n");
  617.  
  618.   // Finished initialization.
  619.   fprintf(stderr, "I_InitSound: sound module ready\n");
  620.   SDL_PauseAudio(0);
  621. }
  622.  
  623.  
  624.  
  625.  
  626. //
  627. // MUSIC API.
  628. // Still no music done.
  629. // Remains. Dummies.
  630. //
  631. void I_InitMusic(void)          { }
  632. void I_ShutdownMusic(void)      { }
  633.  
  634. static int      looping=0;
  635. static int      musicdies=-1;
  636.  
  637. void I_PlaySong(int handle, int looping)
  638. {
  639.   // UNUSED.
  640.   handle = looping = 0;
  641.   musicdies = gametic + TICRATE*30;
  642. }
  643.  
  644. void I_PauseSong (int handle)
  645. {
  646.   // UNUSED.
  647.   handle = 0;
  648. }
  649.  
  650. void I_ResumeSong (int handle)
  651. {
  652.   // UNUSED.
  653.   handle = 0;
  654. }
  655.  
  656. void I_StopSong(int handle)
  657. {
  658.   // UNUSED.
  659.   handle = 0;
  660.  
  661.   looping = 0;
  662.   musicdies = 0;
  663. }
  664.  
  665. void I_UnRegisterSong(int handle)
  666. {
  667.   // UNUSED.
  668.   handle = 0;
  669. }
  670.  
  671. int I_RegisterSong(void* data)
  672. {
  673.   // UNUSED.
  674.   data = NULL;
  675.  
  676.   return 1;
  677. }
  678.  
  679. // Is the song playing?
  680. int I_QrySongPlaying(int handle)
  681. {
  682.   // UNUSED.
  683.   handle = 0;
  684.   return looping || musicdies > gametic;
  685. }
  686.  
  687.