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