Subversion Repositories Kolibri OS

Rev

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