home *** CD-ROM | disk | FTP | other *** search
/ Dream 52 / Amiga_Dream_52.iso / Linux / Divers / xgalaga-2_0_tar.gz / xgalaga-2_0_tar / xgalaga-2.0 / xgal.sndsrv.sun.c < prev    next >
C/C++ Source or Header  |  1998-04-12  |  6KB  |  241 lines

  1. /*
  2.  * xgal.sndsrv.c -
  3.  *                 Modified for SunOS/Solaris.
  4.  *                 Reportedly this really sucks, use NAS_SOUND instead
  5.  *                 if you have NAS installed.
  6.  *                     -Joe
  7.  *
  8.  * Copyright 1994-1995 Sujal M. Patel (smpatel@wam.umd.edu)
  9.  * Conditions in "copyright.h"
  10.  */
  11.  
  12. #include <stdio.h>
  13. #include <stdlib.h>
  14. #include <unistd.h>
  15. #include <fcntl.h>
  16. #include <sys/ioctl.h>
  17. #include <sys/time.h>
  18. #include <signal.h>
  19. #include <string.h>
  20.  
  21.  
  22. #ifdef SOLARIS
  23. #define bzero(s,l) memset(s, 0, l)
  24. #define bcopy(s,d,l) memcpy(d,s,l)
  25. #endif
  26.  
  27. char *FILENAME[] = {
  28.                      "/explode.raw",
  29.                      "/firetorp.raw",
  30.                      "/shield.raw",
  31.                      "/torphit.raw",
  32.                      "/explode_big.raw",
  33.              "/ddloo.raw",
  34.              "/warp.raw",
  35.              "/smart.raw",
  36.                    };
  37.  
  38. #define NUM_SOUNDS    (sizeof(FILENAME)/sizeof(char*))
  39.  
  40. signed char *sound_buffer[NUM_SOUNDS];
  41. int sound_size[NUM_SOUNDS];
  42. int fragsize;
  43.  
  44.  
  45. /* Terminate: Signal Handler */
  46. void quit ()
  47. {
  48.   exit (0);
  49. }
  50.  
  51.  
  52.  
  53. void init (int argc, char **argv)
  54. {
  55.   int i;
  56.   char s[1024];
  57.  
  58.   if (argc != 3)
  59.   {
  60.     printf ("This program is only executed by xgal\n");
  61.     exit (1);
  62.   }
  63.  
  64.   for (i=0; i < NUM_SOUNDS; i++)
  65.   {
  66.     s[0] = 0;
  67.     strcat (s, argv[1]);
  68.     if (s[(int)strlen(s) - 1] == '/') FILENAME[i]++;
  69.     strcat (s, FILENAME[i]);
  70.     FILENAME[i] = malloc ((int)strlen (s));
  71.     strcpy (FILENAME[i],s);
  72.     sound_buffer[i]=NULL;
  73.     sound_size[i]=0;
  74.   }
  75.  
  76.   signal(SIGTERM, quit);   /* Setup Terminate Signal Handler */
  77. }
  78.  
  79.  
  80. /*
  81.    Setup DSP: Opens /dev/audio
  82.               Sets fragment size to 512
  83.               Error checking                
  84. */
  85. int setup_dsp (char *dspdev)
  86. {
  87.   int dsp, frag, value;
  88.   int mixer;
  89.  
  90.   dsp = open(dspdev, O_RDWR);
  91.   if (dsp < 1)
  92.   {
  93.     fprintf (stderr, "xgal.sndsrv: Couldn't open DSP %s\n",dspdev);
  94.     return -1;
  95.   }
  96.  
  97.   fragsize = 512;
  98.   
  99.   return dsp;
  100. }
  101.  
  102. /*
  103.    This just keeps the pipe from breaking...
  104.    Eventually I'll look at the xgal signal handlers and
  105.    just trap this.
  106. */
  107. int do_nothing(void)
  108. {
  109.     fprintf(stderr,"xgal.sndsrv: doing nothing, something is broken\n");
  110.     while(1)  sleep (5);
  111. }
  112.  
  113. int read_sound(int k)
  114. {
  115.   int i,fd,size;
  116.  
  117.   /*fprintf(stderr,"loading sound %d, %s\n",k,FILENAME[k]);*/
  118.  
  119.   fd = open(FILENAME[k], O_RDONLY);
  120.   if(fd<=0) 
  121.   {
  122.     fprintf (stderr, "xgal.sndsrv: The sound %s could not be opened\n", FILENAME[k]);
  123.     sound_size[k]=-1;
  124.     return(0);
  125.   };
  126.   size=lseek(fd,0,SEEK_END);
  127.   sound_size[k]=(size/fragsize)+1;   /*size in fragments*/
  128.   sound_buffer[k]=malloc(sound_size[k]*fragsize);
  129.   if(sound_buffer[k]==NULL)
  130.   {
  131.     fprintf(stderr,"xgal.sndsrv: couldn't malloc memory for sound\n");
  132.     sound_size[k]=-1;
  133.     close(fd);
  134.     return(0);
  135.   };
  136.   lseek(fd,0,SEEK_SET);
  137.   read(fd,sound_buffer[k],size);
  138.   close(fd);
  139.   for(i=0;i<size;i++)  sound_buffer[k][i]^=0x80;
  140.   bzero(sound_buffer[k]+size,sound_size[k]*fragsize-size);
  141.   
  142.   /*fprintf(stderr,"sound has been loaded, %d bytes\n",size);*/ /*DEBUG*/
  143.   return(1);
  144. }
  145.  
  146.  
  147. void do_everything (int dsp)
  148. {
  149.   char k;
  150.   int i, j ;
  151.   int terminate = -1;             /* Which Sound to Terminate                              */
  152.   int playing[16];                /* Sound numbers that we are playing                     */
  153.   int position[16];          /* Current position in each sound file */
  154.   int playnum = 0;                /* Number of sounds currently being played               */
  155.   unsigned char final[512];       /* Final Mixing Buffer                                   */
  156.   int premix[512];
  157.   char *sample;
  158.  
  159.   for(;;)  {
  160.     terminate = -1;
  161.     /* Try to open a new sound if we get an integer on the 'in' pipe */
  162.     i=read(STDIN_FILENO,&k,sizeof(k));
  163.     if(i==0)  {   /* EOF on pipe means parent has closed its end */
  164.         /*fprintf(stderr,"xgal.sndsrv: shutting down\n"); */
  165.         kill(getpid(), SIGTERM);
  166.     };
  167.     if(i!=-1)  {  /* there was something in the pipe */
  168.         /*fprintf(stderr,"Just read a %d from pipe\n",(int)k);*/ /*DEBUG*/
  169.         /* Negative means terminate the FIRST sound in the buffer */
  170.         if(k<0)  {
  171.             /*fprintf(stderr,"terminating sound\n");*/ /*DEBUG*/
  172.             terminate = 0;
  173.         } else {
  174.             if(sound_size[(int)k]==0) read_sound(k);
  175.             if(sound_size[(int)k]>0 && playnum<16)  {
  176.             position[playnum]=0;
  177.                 playing[playnum++]=k;
  178.                 /*fprintf(stderr,"sound %d added to play queue\n",playnum-1);*/ /*DEBUG*/
  179.             };
  180.         };
  181.     };
  182.  
  183.     /* terminate a sound if necessary */
  184.     for(i=0;i<playnum;i++)
  185.     {
  186.       if((position[i]==sound_size[playing[i]]) || (terminate==i))
  187.       {
  188.         /*fprintf(stderr,"finished playing sound %d\n",i);*/ /*DEBUG*/
  189.     /*fprintf(stderr,"is was at position %d\n",position[i]);*/ /*DEBUG*/
  190.         bcopy(playing+i+1,playing+i,(playnum-i)*sizeof(int));
  191.         bcopy(position+i+1,position+i,(playnum-i)*sizeof(int));
  192.         playnum--;i--;
  193.       };
  194.     };
  195.  
  196.     if(playnum)  {
  197.         /* Mix each sound into the final buffer */
  198.         bzero(premix,sizeof(premix));
  199.         for(i=0;i<playnum;i++)  {
  200.             sample=sound_buffer[playing[i]]+position[i]*fragsize;
  201.             for(j=0;j<fragsize;j++)  {
  202.                 premix[j]+=*(sample+j);
  203.             };
  204.             position[i]++;
  205.         };
  206.         for(i=0;i<fragsize;i++)
  207.             final[i]=(premix[i]>255)?255:(premix[i]<-256?0:(premix[i]>>1)+128);
  208.     } else {
  209.         /* 
  210.            We have no sounds to play
  211.            Just fill the buffer with silence and maybe play it 
  212.         */
  213.         memset(final,128,sizeof(final));
  214.     };
  215.     write (dsp, final, fragsize);
  216.     /*
  217.        The sound server is in a tight loop, EXCEPT for this
  218.        write which blocks.  Any optimizations in the above
  219.        code would really be helpful.  Right now the server
  220.        takes up to 7% cpu on a 486DX/50.
  221.     */
  222.   }
  223. }
  224.  
  225.  
  226.  
  227. void main (argc, argv)
  228. int argc;
  229. char **argv;
  230. {
  231.   int dsp;
  232.  
  233.   fcntl(STDIN_FILENO,F_SETFL,O_NONBLOCK);
  234.   init (argc, argv);
  235.   dsp = setup_dsp (argv[2]);
  236.  
  237.   if (!dsp) do_nothing();
  238.  
  239.   do_everything (dsp);
  240. }
  241.