Mercurial > ~darius > hgwebdir.cgi > paradise_client
diff paradise.sndsrv.hp.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.hp.c Sat Dec 06 05:41:29 1997 +0000 @@ -0,0 +1,293 @@ +/* + * paradise.sndsrv.c - USS-Lite Compatible Sound - July 1996 + * This server is HP/UX 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.hp.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 <sys/audio.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]; +#define fragsize (256) + + +/* 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; + } + + if (-1 == ioctl(dsp, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_LINEAR16BIT)) { + fprintf(stderr,"paradise.sndsrv: parameter setting failed"); + return; + } + + if (-1 == ioctl(dsp, AUDIO_SET_CHANNELS, 1)) { + fprintf(stderr,"paradise.sndsrv: parameter setting failed"); + return; + } + + if (-1 == ioctl(dsp, AUDIO_SET_SAMPLE_RATE, 16000)) { + fprintf(stderr,"paradise.sndsrv: parameter setting failed"); + return -1; + } + + if (-1 == ioctl(dsp, AUDIO_SET_OUTPUT, AUDIO_OUT_INTERNAL)) { + fprintf(stderr,"paradise.sndsrv: parameter setting failed"); + return -1; + } + + + 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; + unsigned char * b; + short * d; + + /* 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]*sizeof(short)*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); + + b = ((unsigned char *)sound_buffer[k])+sound_size[k]*fragsize; + d = sound_buffer[k] + sound_size[k]*fragsize; + /* fprintf(stderr,"size = %d\n",sound_size[k]*fragsize); */ + for (i=0; i < sound_size[k]*fragsize; i++) { + *(--d) = (((short)*(--b))-128) << 8; + } + + close(fd); + bzero(((char *)sound_buffer[k])+size, sound_size[k]*sizeof(short)*fragsize-size); + + /* fprintf(stderr,"buba! 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 */ + short final[fragsize]; /* Final Mixing Buffer */ + short *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--; + }; + }; + + memset(final, 0, sizeof(final)); + if(playnum) { + /* Mix each sound into the final buffer */ + for(i=0;i<playnum;i++) { + short * f = final; + sample=sound_buffer[playing[i]]+position[i]*fragsize; + for(j=0;j<fragsize;j++) { + long s = *f; + s += *sample++; + if (s < -32768) { + s = -32768; + } + if (s > 32767) { + s = 32767; + } + *f++ = (short)s; + }; + position[i]++; + } + } else { + /* + We have no sounds to play + Just fill the buffer with silence and maybe play it + */ + }; + write (dsp, final, fragsize*sizeof(short)); + /* + 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); +}