Mercurial > ~darius > hgwebdir.cgi > paradise_client
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); +}