diff paradise.sndsrv.sun.c @ 3:5a977ccbc7a9 default tip

Empty changelog
author darius
date Sat, 06 Dec 1997 05:41:29 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/paradise.sndsrv.sun.c	Sat Dec 06 05:41:29 1997 +0000
@@ -0,0 +1,283 @@
+/*
+ * paradise.sndsrv.c - VoxWare(tm) Compatible Sound - July 1996
+ *                   This server is SunOS Specific.
+ * Sujal M. Patel (smpatel@umiacs.umd.edu)
+ *
+ * Copyright (c) 1994-1996, Sujal M. Patel
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *      $Id: paradise.sndsrv.sun.c,v 1.1.1.1 1997/12/06 05:41:29 darius Exp $
+ */
+
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <signal.h>
+#include <string.h>
+
+char *FILENAME[] = {
+                     "/explode.raw",
+                     "/cloak.raw",
+                     "/firetorp.raw",
+                     "/phaser.raw",
+                     "/plasma.raw",
+                     "/shield.raw",
+                     "/torphit.raw",
+                     "/explode_big.raw",
+                     "/paradise.raw",
+                     "/thermal.raw",
+                     "/redalert.raw"
+                   };
+
+#define NUM_SOUNDS      (sizeof(FILENAME)/sizeof(char*))
+
+signed char *sound_buffer[NUM_SOUNDS];
+int sound_size[NUM_SOUNDS];
+int fragsize;
+
+
+/* Terminate: Signal Handler */
+void
+quit ()
+{
+  exit (0);
+}
+
+
+
+void
+init (int argc, char **argv)
+{
+  int             i;
+  char            s[1024];
+
+  if (argc != 3)
+    {
+      printf ("This program is only executed by Paradise\n");
+      exit (1);
+    }
+
+  for (i = 0; i < NUM_SOUNDS; i++)
+    {
+      s[0] = 0;
+      strcat (s, argv[1]);
+      if (s[(int) strlen (s) - 1] == '/')
+	FILENAME[i]++;
+      strcat (s, FILENAME[i]);
+      FILENAME[i] = malloc ((int) strlen (s) + 1);
+      strcpy (FILENAME[i], s);
+      sound_buffer[i] = NULL;
+      sound_size[i] = 0;
+    }
+
+  signal (SIGTERM, quit);	/* Setup Terminate Signal Handler */
+}
+
+
+/*
+   Setup DSP: Opens /dev/audio
+   Sets fragment size to 512
+   Error checking                
+ */
+int
+setup_dsp (char *dspdev)
+{
+  int             dsp, frag, value;
+  int             mixer;
+
+  dsp = open (dspdev, O_RDWR);
+  if (dsp < 1)
+    {
+      fprintf (stderr, "paradise.sndsrv: Couldn't open device %s\n", dspdev);
+      return -1;
+    }
+
+  fragsize = 512;
+
+  return dsp;
+}
+
+/*
+   This just keeps the pipe from breaking...
+   Eventually I'll look at the paradise signal handlers and
+   just trap this.
+ */
+int
+do_nothing (void)
+{
+  while (1)
+    sleep (5);
+}
+
+int
+read_sound (int k)
+{
+  int             i, fd, size;
+
+  /*fprintf(stderr,"loading sound %d, %s\n",k,FILENAME[k]); */
+
+  fd = open (FILENAME[k], O_RDONLY);
+  if (fd <= 0)
+    {
+      fprintf (stderr, "paradise.sndsrv: The sound %s could not be opened\n", FILENAME[k]);
+      sound_size[k] = -1;
+      return (0);
+    };
+  size = lseek (fd, 0, SEEK_END);
+  sound_size[k] = (size / fragsize) + 1;	/*size in fragments */
+  sound_buffer[k] = malloc (sound_size[k] * fragsize);
+  if (sound_buffer[k] == NULL)
+    {
+      fprintf (stderr, "paradise.sndsrv: couldn't malloc memory for sound\n");
+      sound_size[k] = -1;
+      close (fd);
+      return (0);
+    };
+  lseek (fd, 0, SEEK_SET);
+  read (fd, sound_buffer[k], size);
+  close (fd);
+  for (i = 0; i < size; i++)
+    sound_buffer[k][i] ^= 0x80;
+  bzero (sound_buffer[k] + size, sound_size[k] * fragsize - size);
+
+  /*fprintf(stderr,"sound has been loaded, %d bytes\n",size); *//*DEBUG */
+  return (1);
+}
+
+
+void
+do_everything (int dsp)
+{
+  char            k;
+  int             i, j;
+  int             terminate = -1;	/* Which Sound to Terminate                              */
+  int             playing[16];	/* Sound numbers that we are playing                     */
+  int             position[16];	/* Current position in each sound file */
+  int             playnum = 0;	/* Number of sounds currently being played               */
+  unsigned char   final[512];	/* Final Mixing Buffer                                   */
+  int             premix[512];
+  char           *sample;
+
+  for (;;)
+    {
+      terminate = -1;
+      /* Try to open a new sound if we get an integer on the 'in' pipe */
+      i = read (STDIN_FILENO, &k, sizeof (k));
+      if (i == 0)
+	{			/* EOF on pipe means parent has closed its end */
+	  /*fprintf(stderr,"paradise.sndsrv: shutting down\n"); */
+	  kill (getpid (), SIGTERM);
+	};
+      if (i != -1)
+	{			/* there was something in the pipe */
+	  /*fprintf(stderr,"Just read a %d from pipe\n",(int)k); *//*DEBUG */
+	  /* Negative means terminate the FIRST sound in the buffer */
+	  if (k < 0)
+	    {
+	      /*fprintf(stderr,"terminating sound\n"); *//*DEBUG */
+	      terminate = 0;
+	    }
+	  else
+	    {
+	      if (sound_size[(int) k] == 0)
+		read_sound (k);
+	      if (sound_size[(int) k] > 0 && playnum < 16)
+		{
+		  position[playnum] = 0;
+		  playing[playnum++] = k;
+		  /*fprintf(stderr,"sound %d added to play queue\n",playnum-1); *//*DEBUG */
+		};
+	    };
+	};
+
+      /* terminate a sound if necessary */
+      for (i = 0; i < playnum; i++)
+	{
+	  if ((position[i] == sound_size[playing[i]]) || (terminate == i))
+	    {
+	      /*fprintf(stderr,"finished playing sound %d\n",i); *//*DEBUG */
+	      /*fprintf(stderr,"is was at position %d\n",position[i]); *//*DEBUG */
+	      bcopy (playing + i + 1, playing + i, (playnum - i) * sizeof (int));
+	      bcopy (position + i + 1, position + i, (playnum - i) * sizeof (int));
+	      playnum--;
+	      i--;
+	    };
+	};
+
+      if (playnum)
+	{
+	  /* Mix each sound into the final buffer */
+	  bzero (premix, sizeof (premix));
+	  for (i = 0; i < playnum; i++)
+	    {
+	      sample = sound_buffer[playing[i]] + position[i] * fragsize;
+	      for (j = 0; j < fragsize; j++)
+		{
+		  premix[j] += *(sample + j);
+		};
+	      position[i]++;
+	    };
+	  for (i = 0; i < fragsize; i++)
+	    final[i] = (premix[i] > 255) ? 255 : (premix[i] < -256 ? 0 : (premix[i] >> 1) + 128);
+	}
+      else
+	{
+	  /* 
+	     We have no sounds to play
+	     Just fill the buffer with silence and maybe play it 
+	   */
+	  memset (final, 128, sizeof (final));
+	};
+      write (dsp, final, fragsize);
+      /*
+         The sound server is in a tight loop, EXCEPT for this
+         write which blocks.  Any optimizations in the above
+         code would really be helpful.  Right now the server
+         takes up to 7% cpu on a 486DX/50.
+       */
+    }
+}
+
+
+
+void
+main (argc, argv)
+     int             argc;
+     char          **argv;
+{
+  int             dsp;
+
+  fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK);
+  init (argc, argv);
+  dsp = setup_dsp (argv[2]);
+
+  if (dsp < 1)
+    do_nothing ();
+
+  do_everything (dsp);
+}