1 /*
2 * koules.sndsrv.sgi.c - SGI Indigo/Indigo^2/Indy Sound Driver
3 *
4 * Copyright (c) 1996 Rick Sayre (whorfin@pixar.com)
5 * Based on the various existing PC sound drivers.
6 *
7 * Permission to use, copy, modify, and distribute this
8 * software and its documentation for any purpose and without
9 * fee is hereby granted, provided that the above copyright
10 * notice appear in all copies and that both that copyright
11 * notice and this permission notice appear in supporting
12 * documentation. No representations are made about the
13 * suitability of this software for any purpose. It is
14 * provided "as is" without express or implied warranty.
15 */
16
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <unistd.h>
20 #include <fcntl.h>
21 #include <signal.h>
22 #include <audio.h>
23
24 #define FREQUENCY 8000
25 #define FRAGSIZE 510 /* 1/16 second: XXX 500 causes 6.2 crash! */
26
27 char *FILENAME[] = {
28 "/start.raw",
29 "/end.raw",
30 "/colize.raw",
31 "/destroy1.raw",
32 "/destroy2.raw",
33 "/creator1.raw",
34 "/creator2.raw",
35 };
36
37 #define NUM_SOUNDS (sizeof(FILENAME)/sizeof(char*))
38
39 signed char *sound_buffer[NUM_SOUNDS];
40
41 int sound_size[NUM_SOUNDS];
42
43
44 /* Terminate: Signal Handler */
45 static void
quit()46 quit()
47 {
48 exit(0);
49 }
50
51
52
53 static void
init(int argc,char ** argv)54 init(int argc, char **argv)
55 {
56 int i;
57 char s[1024];
58
59 if (argc != 3) {
60 printf("This program is only executed by koules\n");
61 exit(1);
62 }
63 for (i = 0; i < NUM_SOUNDS; i++) {
64 s[0] = 0;
65 strcat(s, argv[1]);
66 if (s[(int) strlen(s) - 1] == '/')
67 FILENAME[i]++;
68 strcat(s, FILENAME[i]);
69 FILENAME[i] = malloc((int) strlen(s));
70 strcpy(FILENAME[i], s);
71 sound_buffer[i] = NULL;
72 sound_size[i] = 0;
73 }
74
75 signal(SIGTERM, quit); /* Setup Terminate Signal Handler */
76 }
77
78
79
80 static ALport
setup_dsp(char * dspdev)81 setup_dsp(char *dspdev)
82 {
83 ALport writePort;
84 ALconfig writeConfig;
85
86 static long audioParams[2] = {
87 AL_OUTPUT_RATE, FREQUENCY
88 };
89
90 writeConfig = ALnewconfig();
91 ALsetqueuesize(writeConfig, FRAGSIZE);
92 ALsetchannels(writeConfig, AL_MONO);
93 ALsetparams(AL_DEFAULT_DEVICE, audioParams, 2);
94 ALsetwidth(writeConfig, AL_SAMPLE_8);
95
96 if (!(writePort = ALopenport("koules.sndsrv", "w", writeConfig))) {
97 fprintf(stderr, "koules.sndsrv.sgi: Couldn't open audio port\n");
98 return(NULL);
99 }
100
101 return writePort;
102 }
103
104 /*
105 This just keeps the pipe from breaking...
106 Eventually I'll look at the koules signal handlers and
107 just trap this.
108 */
109 static void
do_nothing(void)110 do_nothing(void)
111 {
112 fprintf(stderr, "koules.sndsrv: doing nothing, something is broken\n");
113 while (1)
114 sleep(5);
115 }
116
117 static int
read_sound(int k)118 read_sound(int k)
119 {
120 int i, fd, size;
121
122 #ifdef DEBUG
123 fprintf(stderr, "loading sound %d, %s\n", k, FILENAME[k]);
124 #endif
125
126 fd = open(FILENAME[k], O_RDONLY);
127 if (fd <= 0) {
128 fprintf(stderr, "koules.sndsrv: The sound %s could not be opened\n", FILENAME[k]);
129 sound_size[k] = -1;
130 return (0);
131 }
132 size = lseek(fd, 0, SEEK_END);
133 sound_size[k] = (size / FRAGSIZE) + 1; /* size in fragments */
134 sound_buffer[k] = malloc(sound_size[k] * FRAGSIZE);
135 if (sound_buffer[k] == NULL) {
136 fprintf(stderr, "koules.sndsrv: couldn't malloc memory for sound\n");
137 sound_size[k] = -1;
138 close(fd);
139 return (0);
140 }
141 lseek(fd, 0, SEEK_SET);
142 read(fd, sound_buffer[k], size);
143 close(fd);
144
145 /* data is unsigned; convert to signed */
146 for (i = 0; i < size; i++)
147 sound_buffer[k][i] ^= 0x80;
148 bzero(sound_buffer[k] + size, sound_size[k] * FRAGSIZE - size);
149
150 #ifdef DEBUG
151 fprintf(stderr, "sound has been loaded, %d bytes\n", size);
152 #endif
153 return (1);
154 }
155
156
157 static void
do_everything(ALport writePort)158 do_everything(ALport writePort)
159 {
160 signed char k;
161 int i, j;
162 int terminate = -1; /* Which Sound to Terminate */
163 int playing[16];/* Sound numbers that we are playing */
164 int position[16]; /* Current position in each sound
165 * file */
166 int playnum = 0;/* Number of sounds currently being played */
167 signed char final[512]; /* Final Mixing Buffer */
168 int premix[512];
169 signed char *sample;
170
171 for (;;) {
172 terminate = -1;
173
174 /* Try to open a new sound if we get an integer on the 'in' pipe */
175 i = read(STDIN_FILENO, &k, sizeof(k));
176 if (i == 0) { /* EOF on pipe means parent has closed its end*/
177 #ifdef DEBUG
178 fprintf(stderr,"koules.sndsrv: shutting down\n");
179 #endif
180 kill(getpid(), SIGTERM);
181 }
182 if (i != -1) { /* there was something in the pipe */
183 #ifdef DEBUG
184 fprintf(stderr,"Just read a %d from pipe\n",(int)k);
185 #endif
186 /* Negative means terminate the FIRST sound in the buffer */
187 if (k < 0) {
188 #ifdef DEBUG
189 fprintf(stderr,"terminating sound\n");
190 #endif
191 terminate = 0;
192 } else {
193 if (sound_size[(int) k] == 0)
194 read_sound(k);
195 if (sound_size[(int) k] > 0 && playnum < 16) {
196 position[playnum] = 0;
197 playing[playnum++] = k;
198 #ifdef DEBUG
199 fprintf(stderr,"sound %d added to play queue\n",playnum-1);
200 #endif
201 }
202 }
203 }
204
205 /* terminate a sound if necessary */
206 for (i = 0; i < playnum; i++) {
207 if ((position[i] == sound_size[playing[i]]) || (terminate == i)) {
208 #ifdef DEBUG
209 fprintf(stderr,"finished playing sound %d\n",i);
210 fprintf(stderr,"is was at position %d\n",position[i]);
211 #endif
212 bcopy(playing + i + 1, playing + i, (playnum - i) * sizeof(int));
213 bcopy(position + i + 1, position + i, (playnum - i) * sizeof(int));
214 playnum--;
215 i--;
216 }
217 }
218
219 if (playnum) {
220 /* Mix each sound into the final buffer */
221 bzero(premix, sizeof(premix));
222 for (i = 0; i < playnum; i++) {
223 sample = sound_buffer[playing[i]] + position[i] * FRAGSIZE;
224 for (j = 0; j < FRAGSIZE; j++) {
225 premix[j] += *(sample + j);
226 }
227 position[i]++;
228 }
229 /* clamp premix */
230 for (i = 0; i < FRAGSIZE; i++)
231 final[i] = (premix[i] > 127) ? 127 : (premix[i] < -128 ? -128 : premix[i]);
232 } else {
233 /*
234 * We have no sounds to play Just fill the buffer with silence
235 * and maybe play it
236 */
237 bzero(final, sizeof(final));
238 }
239 ALwritesamps(writePort, final, FRAGSIZE);
240
241 }
242 }
243
244
245
246 void
main(int argc,char ** argv)247 main(int argc, char **argv)
248 {
249 ALport writePort;
250
251 fcntl(STDIN_FILENO, F_SETFL, O_NONBLOCK);
252 init(argc, argv);
253
254 if (!(writePort = setup_dsp(argv[2])))
255 do_nothing();
256
257 do_everything(writePort);
258 }
259