Mercurial > ~darius > hgwebdir.cgi > paradise_client
comparison paradise.sndsrv.sun.c @ 3:5a977ccbc7a9 default tip
Empty changelog
author | darius |
---|---|
date | Sat, 06 Dec 1997 05:41:29 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
2:fba0b6e6cdc7 | 3:5a977ccbc7a9 |
---|---|
1 /* | |
2 * paradise.sndsrv.c - VoxWare(tm) Compatible Sound - July 1996 | |
3 * This server is SunOS Specific. | |
4 * Sujal M. Patel (smpatel@umiacs.umd.edu) | |
5 * | |
6 * Copyright (c) 1994-1996, Sujal M. Patel | |
7 * All rights reserved. | |
8 * | |
9 * Redistribution and use in source and binary forms, with or without | |
10 * modification, are permitted provided that the following conditions | |
11 * are met: | |
12 * 1. Redistributions of source code must retain the above copyright | |
13 * notice, this list of conditions and the following disclaimer. | |
14 * 2. Redistributions in binary form must reproduce the above copyright | |
15 * notice, this list of conditions and the following disclaimer in the | |
16 * documentation and/or other materials provided with the distribution. | |
17 * | |
18 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND | |
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | |
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE | |
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE | |
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | |
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | |
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | |
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT | |
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY | |
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF | |
28 * SUCH DAMAGE. | |
29 * | |
30 * $Id: paradise.sndsrv.sun.c,v 1.1.1.1 1997/12/06 05:41:29 darius Exp $ | |
31 */ | |
32 | |
33 | |
34 #include <stdio.h> | |
35 #include <stdlib.h> | |
36 #include <unistd.h> | |
37 #include <fcntl.h> | |
38 #include <sys/ioctl.h> | |
39 #include <sys/time.h> | |
40 #include <signal.h> | |
41 #include <string.h> | |
42 | |
43 char *FILENAME[] = { | |
44 "/explode.raw", | |
45 "/cloak.raw", | |
46 "/firetorp.raw", | |
47 "/phaser.raw", | |
48 "/plasma.raw", | |
49 "/shield.raw", | |
50 "/torphit.raw", | |
51 "/explode_big.raw", | |
52 "/paradise.raw", | |
53 "/thermal.raw", | |
54 "/redalert.raw" | |
55 }; | |
56 | |
57 #define NUM_SOUNDS (sizeof(FILENAME)/sizeof(char*)) | |
58 | |
59 signed char *sound_buffer[NUM_SOUNDS]; | |
60 int sound_size[NUM_SOUNDS]; | |
61 int fragsize; | |
62 | |
63 | |
64 /* Terminate: Signal Handler */ | |
65 void | |
66 quit () | |
67 { | |
68 exit (0); | |
69 } | |
70 | |
71 | |
72 | |
73 void | |
74 init (int argc, char **argv) | |
75 { | |
76 int i; | |
77 char s[1024]; | |
78 | |
79 if (argc != 3) | |
80 { | |
81 printf ("This program is only executed by Paradise\n"); | |
82 exit (1); | |
83 } | |
84 | |
85 for (i = 0; i < NUM_SOUNDS; i++) | |
86 { | |
87 s[0] = 0; | |
88 strcat (s, argv[1]); | |
89 if (s[(int) strlen (s) - 1] == '/') | |
90 FILENAME[i]++; | |
91 strcat (s, FILENAME[i]); | |
92 FILENAME[i] = malloc ((int) strlen (s) + 1); | |
93 strcpy (FILENAME[i], s); | |
94 sound_buffer[i] = NULL; | |
95 sound_size[i] = 0; | |
96 } | |
97 | |
98 signal (SIGTERM, quit); /* Setup Terminate Signal Handler */ | |
99 } | |
100 | |
101 | |
102 /* | |
103 Setup DSP: Opens /dev/audio | |
104 Sets fragment size to 512 | |
105 Error checking | |
106 */ | |
107 int | |
108 setup_dsp (char *dspdev) | |
109 { | |
110 int dsp, frag, value; | |
111 int mixer; | |
112 | |
113 dsp = open (dspdev, O_RDWR); | |
114 if (dsp < 1) | |
115 { | |
116 fprintf (stderr, "paradise.sndsrv: Couldn't open device %s\n", dspdev); | |
117 return -1; | |
118 } | |
119 | |
120 fragsize = 512; | |
121 | |
122 return dsp; | |
123 } | |
124 | |
125 /* | |
126 This just keeps the pipe from breaking... | |
127 Eventually I'll look at the paradise signal handlers and | |
128 just trap this. | |
129 */ | |
130 int | |
131 do_nothing (void) | |
132 { | |
133 while (1) | |
134 sleep (5); | |
135 } | |
136 | |
137 int | |
138 read_sound (int k) | |
139 { | |
140 int i, fd, size; | |
141 | |
142 /*fprintf(stderr,"loading sound %d, %s\n",k,FILENAME[k]); */ | |
143 | |
144 fd = open (FILENAME[k], O_RDONLY); | |
145 if (fd <= 0) | |
146 { | |
147 fprintf (stderr, "paradise.sndsrv: The sound %s could not be opened\n", FILENAME[k]); | |
148 sound_size[k] = -1; | |
149 return (0); | |
150 }; | |
151 size = lseek (fd, 0, SEEK_END); | |
152 sound_size[k] = (size / fragsize) + 1; /*size in fragments */ | |
153 sound_buffer[k] = malloc (sound_size[k] * fragsize); | |
154 if (sound_buffer[k] == NULL) | |
155 { | |
156 fprintf (stderr, "paradise.sndsrv: couldn't malloc memory for sound\n"); | |
157 sound_size[k] = -1; | |
158 close (fd); | |
159 return (0); | |
160 }; | |
161 lseek (fd, 0, SEEK_SET); | |
162 read (fd, sound_buffer[k], size); | |
163 close (fd); | |
164 for (i = 0; i < size; i++) | |
165 sound_buffer[k][i] ^= 0x80; | |
166 bzero (sound_buffer[k] + size, sound_size[k] * fragsize - size); | |
167 | |
168 /*fprintf(stderr,"sound has been loaded, %d bytes\n",size); *//*DEBUG */ | |
169 return (1); | |
170 } | |
171 | |
172 | |
173 void | |
174 do_everything (int dsp) | |
175 { | |
176 char k; | |
177 int i, j; | |
178 int terminate = -1; /* Which Sound to Terminate */ | |
179 int playing[16]; /* Sound numbers that we are playing */ | |
180 int position[16]; /* Current position in each sound file */ | |
181 int playnum = 0; /* Number of sounds currently being played */ | |
182 unsigned char final[512]; /* Final Mixing Buffer */ | |
183 int premix[512]; | |
184 char *sample; | |
185 | |
186 for (;;) | |
187 { | |
188 terminate = -1; | |
189 /* Try to open a new sound if we get an integer on the 'in' pipe */ | |
190 i = read (STDIN_FILENO, &k, sizeof (k)); | |
191 if (i == 0) | |
192 { /* EOF on pipe means parent has closed its end */ | |
193 /*fprintf(stderr,"paradise.sndsrv: shutting down\n"); */ | |
194 kill (getpid (), SIGTERM); | |
195 }; | |
196 if (i != -1) | |
197 { /* there was something in the pipe */ | |
198 /*fprintf(stderr,"Just read a %d from pipe\n",(int)k); *//*DEBUG */ | |
199 /* Negative means terminate the FIRST sound in the buffer */ | |
200 if (k < 0) | |
201 { | |
202 /*fprintf(stderr,"terminating sound\n"); *//*DEBUG */ | |
203 terminate = 0; | |
204 } | |
205 else | |
206 { | |
207 if (sound_size[(int) k] == 0) | |
208 read_sound (k); | |
209 if (sound_size[(int) k] > 0 && playnum < 16) | |
210 { | |
211 position[playnum] = 0; | |
212 playing[playnum++] = k; | |
213 /*fprintf(stderr,"sound %d added to play queue\n",playnum-1); *//*DEBUG */ | |
214 }; | |
215 }; | |
216 }; | |
217 | |
218 /* terminate a sound if necessary */ | |
219 for (i = 0; i < playnum; i++) | |
220 { | |
221 if ((position[i] == sound_size[playing[i]]) || (terminate == i)) | |
222 { | |
223 /*fprintf(stderr,"finished playing sound %d\n",i); *//*DEBUG */ | |
224 /*fprintf(stderr,"is was at position %d\n",position[i]); *//*DEBUG */ | |
225 bcopy (playing + i + 1, playing + i, (playnum - i) * sizeof (int)); | |
226 bcopy (position + i + 1, position + i, (playnum - i) * sizeof (int)); | |
227 playnum--; | |
228 i--; | |
229 }; | |
230 }; | |
231 | |
232 if (playnum) | |
233 { | |
234 /* Mix each sound into the final buffer */ | |
235 bzero (premix, sizeof (premix)); | |
236 for (i = 0; i < playnum; i++) | |
237 { | |
238 sample = sound_buffer[playing[i]] + position[i] * fragsize; | |
239 for (j = 0; j < fragsize; j++) | |
240 { | |
241 premix[j] += *(sample + j); | |
242 }; | |
243 position[i]++; | |
244 }; | |
245 for (i = 0; i < fragsize; i++) | |
246 final[i] = (premix[i] > 255) ? 255 : (premix[i] < -256 ? 0 : (premix[i] >> 1) + 128); | |
247 } | |
248 else | |
249 { | |
250 /* | |
251 We have no sounds to play | |
252 Just fill the buffer with silence and maybe play it | |
253 */ | |
254 memset (final, 128, sizeof (final)); | |
255 }; | |
256 write (dsp, final, fragsize); | |
257 /* | |
258 The sound server is in a tight loop, EXCEPT for this | |
259 write which blocks. Any optimizations in the above | |
260 code would really be helpful. Right now the server | |
261 takes up to 7% cpu on a 486DX/50. | |
262 */ | |
263 } | |
264 } | |
265 | |
266 | |
267 | |
268 void | |
269 main (argc, argv) | |
270 int argc; | |
271 char **argv; | |
272 { | |
273 int dsp; | |
274 | |
275 fcntl (STDIN_FILENO, F_SETFL, O_NONBLOCK); | |
276 init (argc, argv); | |
277 dsp = setup_dsp (argv[2]); | |
278 | |
279 if (dsp < 1) | |
280 do_nothing (); | |
281 | |
282 do_everything (dsp); | |
283 } |