Mercurial > ~darius > hgwebdir.cgi > paradise_client
view 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 source
/* * 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); }