1 #ifdef SOUND_SUPPORT
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <fcntl.h>
6 #include <unistd.h>
7 #include <sys/soundcard.h>
8 #include "sound.h"
9 
10 int sound=1;
11 int soundfd=-1;
12 int sndpipe[2];
13 int sound_bufsiz;
14 
15 /* use 256 byte frags */
16 #define BASE_SOUND_FRAG_PWR	8
17 #define BASE_SOUND_BUFSIZ	(1<<BASE_SOUND_FRAG_PWR)
18 
19 
20 struct channel_tag {
21   struct sample_tag *sample;	/* pointer to sample struct, NULL if none */
22   int offset;			/* position in sample */
23   } channel[NUM_CHANNELS];
24 
25 
26 /* sample filenames */
27 char samplename[][16]={
28   "launch.raw",
29   "explode.raw",
30   "levelst.raw",
31   "levelend.raw",
32   "gameover.raw",
33   "citybang.raw"
34   };
35 
36 /* for in-memory samples */
37 struct sample_tag {
38   unsigned char *data;		/* pointer to sample, NULL if none */
39   int length;			/* length of sample */
40   } sample[NUM_SAMPLES];
41 
42 
43 
44 /* setup a new sample to be played on a given channel. */
queuesam(int chan,int sam)45 void queuesam(int chan,int sam)
46 {
47 unsigned char buf[2];
48 
49 buf[0]=chan;
50 buf[1]=sam;
51 write(sndpipe[1],buf,2);
52 }
53 
54 
55 #define BYTEFIX(x)	(((x)<0)?0:(((x)>255)?255:(x)))
56 
57 /* mix and play a chunk of sound to /dev/dsp. */
snd_playchunk()58 void snd_playchunk()
59 {
60 int f,g,v;
61 struct channel_tag *cptr;
62 static unsigned char soundbuf[1024];
63 
64 if(soundfd==-1 || sound==0)
65   {
66   usleep(50000);
67   return;
68   }
69 
70 for(f=0;f<sound_bufsiz;f++)
71   {
72   v=0;
73   for(g=0,cptr=&(channel[0]);g<NUM_CHANNELS;g++,cptr++)
74     if(cptr->sample!=NULL)
75       {
76       v+=(int)cptr->sample->data[cptr->offset++];
77       if(cptr->offset>=cptr->sample->length)
78         cptr->sample=NULL;
79       }
80     else
81       v+=128;	/* make sure it doesn't click! */
82 
83   v/=NUM_CHANNELS;
84 
85   /* make it louder, as we can get away with it */
86   v-=128; v*=2; v+=128;
87 
88   soundbuf[f]=BYTEFIX(v);
89   }
90 
91 write(soundfd,soundbuf,sound_bufsiz);
92 }
93 
94 
snd_main()95 void snd_main()
96 {
97 unsigned char buf[2];
98 int live=1;
99 
100 while(live)
101   {
102   while(read(sndpipe[0],buf,2)!=-1)
103     {
104     switch(*buf)
105       {
106       case KILL_SNDSERV:
107         live=0;
108         break;
109 
110       default:
111         channel[buf[0]].sample=&(sample[buf[1]]);
112         channel[buf[0]].offset=0;
113       }
114     }
115 
116   snd_playchunk();
117   }
118 
119 exit(0);
120 }
121 
122 
start_sndserv()123 void start_sndserv()
124 {
125 int f;
126 
127 for(f=0;f<NUM_SAMPLES;f++) sample[f].data=NULL;
128 
129 pipe(sndpipe);
130 fcntl(sndpipe[0],F_SETFL,O_NONBLOCK);
131 fcntl(sndpipe[1],F_SETFL,O_NONBLOCK);
132 
133 if(fork())
134   /* parent - game */
135   return;
136 
137 /* child - sound player */
138 
139 sound_bufsiz=BASE_SOUND_BUFSIZ;
140 #ifndef SNDCTL_DSP_SETFRAGMENT		/* voxware 3 only */
141 sound=0;
142 soundfd=-1;
143 #else
144 if(sound)
145   {
146   if((soundfd=open("/dev/dsp",O_WRONLY))<0)
147     {
148     sound=0;
149     soundfd=-1;
150     }
151   else
152     {
153     int frag;
154     FILE *in;
155     char buf[256];
156 
157 #ifdef MORE_SOUNDBUF
158     frag=(0x40000|BASE_SOUND_FRAG_PWR);
159 #else
160     frag=(0x20000|BASE_SOUND_FRAG_PWR);
161 #endif
162     ioctl(soundfd,SNDCTL_DSP_SETFRAGMENT,&frag);
163 
164     /* load in the samples */
165     for(f=0;f<NUM_SAMPLES;f++)
166       {
167       sprintf(buf,"%s/%s",SOUNDSDIR,samplename[f]);
168       if((in=fopen(buf,"rb"))!=NULL)
169         {
170         fseek(in,0,SEEK_END);
171         sample[f].length=ftell(in);
172         if((sample[f].data=(unsigned char *)malloc(sample[f].length))==NULL)
173           break;
174         rewind(in);
175         fread(sample[f].data,1,sample[f].length,in);
176         fclose(in);
177         }
178       }
179     }
180   }
181 #endif
182 
183 snd_main();
184 }
185 
186 
187 #else	/* !SOUND_SUPPORT */
188 
189 /* need dummy queuesam/start_sndserv */
190 
queuesam(int chan,int sam)191 void queuesam(int chan,int sam)
192 {
193 }
194 
start_sndserv()195 void start_sndserv()
196 {
197 }
198 
199 #endif	/* !SOUND_SUPPORT */
200