1 /*
2 * SDLRoids - An Astroids clone.
3 *
4 * Copyright (c) 2000 David Hedbor <david@hedbor.org>
5 * based on xhyperoid by Russel Marks.
6 * xhyperoid is based on a Win16 game, Hyperoid by Edward Hutchins
7 *
8 * This program is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 * GNU General Public License for more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program; if not, write to the Free Software
15 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16 *
17 */
18
19 /*
20 * sdlsound.c - Sound playing routines using raw SDL or SDL_mixer.
21 */
22
23 #include "config.h"
24 RCSID("$Id: sdlsound.c,v 1.10 2001/03/24 04:04:06 neotron Exp $");
25
26 #include "SDL_audio.h"
27 #include "sdlsound.h"
28 #include "misc.h"
29 #include "roidsupp.h"
30
31 #ifdef HAVE_LIBSDL_MIXER
32 # ifdef HAVE_SDL_MIXER_H
33 # include "SDL_mixer.h"
34 # define USE_SDL_MIXER
35 # else
36 # ifdef HAVE_SDL_SDL_MIXER_H
37 # include "SDL/SDL_mixer.h"
38 # define USE_SDL_MIXER
39 # endif
40 # endif
41 #endif
42
43 #include <stdlib.h>
44
45 static int use_audio;
46
47 /* sample filenames */
48 static char *samplename[]=
49 {
50 "sounds/pshot.wav",
51 "sounds/thrust.wav",
52 "sounds/explode.wav",
53 "sounds/explode2.wav",
54 "sounds/bshot.wav",
55 "sounds/phit.wav",
56 "sounds/title.wav",
57 "sounds/newbonus.wav",
58 "sounds/newbad.wav",
59 "sounds/bonusgot.wav",
60 "sounds/bwound.wav",
61 "sounds/swarmsplit.wav"
62 };
63
64 #ifndef USE_SDL_MIXER
65
66 struct channel_tag
67 {
68 struct sample_tag *sample; /* pointer to sample struct, NULL if none */
69 int offset; /* position in sample */
70 int loop; /* loop the sound */
71 } channel[NUM_CHANNELS];
72
73
74 /* for in-memory samples */
75 struct sample_tag
76 {
77 SDL_AudioSpec spec; /* Sample format spec */
78 Uint8 *data; /* Data buffer */
79 Uint32 len; /* buffer length */
80 } samples[NUM_SAMPLES];
81
82 #define BYTEFIX(x) (((x)<0)?0:(((x)>255)?255:(x)))
83
84 /* mix and play a chunk of sound to /dev/dsp. */
85
play_audio(void * udata,Uint8 * stream,int len)86 void play_audio(void *udata, Uint8 *stream, int len)
87 {
88 int f,g,v;
89 struct channel_tag *cptr;
90 Uint8 soundbuf[1024];
91 if(udata == NULL) return;
92 for(f = 0; f < len; f++)
93 {
94 v=0;
95 for(g = 0, cptr = &(channel[0]); g < NUM_CHANNELS; g++, cptr++)
96 if(cptr->sample != NULL)
97 {
98 v += (int)cptr->sample->data[ cptr->offset++ ];
99 if(cptr->offset >= cptr->sample->len) {
100 if(cptr->loop == 1) {
101 cptr->offset = 0;
102 } else
103 cptr->sample = NULL;
104 }
105 }
106 else
107 v+=128; /* make sure it doesn't click! */
108
109 /* kludge to up the volume of sound effects - mmm, lovely distortion :-) */
110 v -= 128*NUM_CHANNELS;
111 v = 128 + (v * 3) / (2 * NUM_CHANNELS);
112 v = BYTEFIX(v);
113
114 soundbuf[f] = (unsigned char)v;
115 }
116 SDL_MixAudio(stream, soundbuf, len, SDL_MIX_MAXVOLUME);
117
118 }
119
120 /* Load the specified sample */
load_sample(int num)121 int load_sample(int num) {
122
123 if(SDL_LoadWAV(samplename[num], &samples[num].spec,
124 &samples[num].data, &samples[num].len) ||
125 SDL_LoadWAV(datafilename(NULL, samplename[num]), &samples[num].spec,
126 &samples[num].data, &samples[num].len) ||
127 SDL_LoadWAV(datafilename(DATADIR, samplename[num]), &samples[num].spec,
128 &samples[num].data, &samples[num].len) ||
129 SDL_LoadWAV(datafilename(bindir, samplename[num]), &samples[num].spec,
130 &samples[num].data, &samples[num].len))
131 return 1;
132 return 0;
133 }
134
init_sound(void)135 void init_sound(void)
136 {
137 int f;
138 SDL_AudioSpec wanted;
139 /* Set the audio format */
140 wanted.freq = 8000;
141 wanted.format = AUDIO_U8;
142 wanted.channels = 1; /* 1 = mono, 2 = stereo */
143 wanted.samples = 1024; /* Good low-latency value for callback */
144 wanted.callback = play_audio;
145 wanted.userdata = NULL;
146
147 if( SDL_OpenAudio(&wanted, NULL) < 0) {
148 fprintf(stderr, "Warning: %s\n", SDL_GetError());
149 use_audio=0;
150 return;
151 } else
152 use_audio=1;
153 memset(channel, 0, sizeof(channel));
154 for(f = 0; f < NUM_SAMPLES; f++)
155 {
156 if(!load_sample(f)) {
157 fprintf(stderr, "Fatal: Couldn't load sample %s.\n", samplename[f]);
158 exit(1);
159 }
160 }
161 }
162
163 /* setup a new sample to be played on a given channel. */
queuesam(int chan,int sam)164 void queuesam(int chan,int sam)
165 {
166 if(!use_audio) return;
167 SDL_PauseAudio(1);
168 channel[chan].sample = &samples[sam];
169 channel[chan].offset = 0;
170 channel[chan].loop = 0;
171 SDL_PauseAudio(0);
172 }
173
loopsam(int chan,int sam)174 void loopsam(int chan,int sam)
175 {
176 if(!use_audio) return;
177 SDL_PauseAudio(1);
178 if(sam >=0 ) {
179 channel[chan].sample = &samples[sam];
180 channel[chan].offset = 0;
181 channel[chan].loop = 1;
182 } else {
183 channel[chan].sample = NULL;
184 channel[chan].offset = 0;
185 channel[chan].loop = 0;
186 }
187 SDL_PauseAudio(0);
188 }
189
exit_sound()190 void exit_sound()
191 {
192 int f;
193 if(!use_audio) return;
194
195 for(f = 0; f < NUM_SAMPLES; f++)
196 SDL_FreeWAV(samples[f].data);
197 }
198
199 #else /*USE_SDL_MIXER */
200
201 /* for in-memory samples */
202 static Mix_Chunk *samples[NUM_SAMPLES];
203
204 /* Load the specified sample */
load_sample(int num)205 int load_sample(int num) {
206
207 if((samples[num] = Mix_LoadWAV(samplename[num])) ||
208 Mix_LoadWAV(datafilename(NULL, samplename[num])) ||
209 Mix_LoadWAV(datafilename(DATADIR, samplename[num])) ||
210 Mix_LoadWAV(datafilename(bindir, samplename[num])))
211 return 1;
212 return 0;
213 }
214
init_sound(void)215 void init_sound(void)
216 {
217 int f;
218 int audio_rate, audio_channels;
219 Uint16 audio_format;
220
221 /* Set the audio format */
222 audio_rate = 8000;
223 audio_format = AUDIO_S16;
224 audio_channels = 2; /* 1 = mono, 2 = stereo */
225
226 if (Mix_OpenAudio(audio_rate, audio_format, audio_channels, 256) < 0) {
227 fprintf(stderr, "Warning: %s\n", SDL_GetError());
228 use_audio = 0;
229 return;
230 } else {
231 Mix_QuerySpec(&audio_rate, &audio_format, &audio_channels);
232 use_audio = 1;
233 }
234 for(f = 0; f < NUM_CHANNELS; f++) Mix_Volume(f, 100);
235
236 for(f = 0; f < NUM_SAMPLES; f++)
237 {
238 if(!load_sample(f))
239 {
240 fprintf(stderr, "Fatal: Couldn't load sample %s.\n", samplename[f]);
241 exit(1);
242 }
243 }
244 }
245
exit_sound()246 void exit_sound()
247 {
248 int f;
249 if(!use_audio) return;
250
251 for(f = 0; f < NUM_SAMPLES; f++)
252 Mix_FreeChunk(samples[f]);
253 }
254
255 /* setup a new sample to be played on a given channel. */
queuesam(int chan,int sam)256 void queuesam(int chan,int sam)
257 {
258 if(!use_audio) return;
259 Mix_PlayChannel(chan, samples[sam], 0);
260 }
261
262
263 /* setup a new sample to be played on a given channel. */
loopsam(int chan,int sam)264 void loopsam(int chan,int sam)
265 {
266 if(!use_audio) return;
267 if(sam >=0 )
268 Mix_PlayChannel(chan, samples[sam], -1);
269 else
270 Mix_HaltChannel(chan);
271 }
272
273 #endif
274
275