Subversion Repositories Games.Rick Dangerous

Rev

Rev 2 | Go to most recent revision | Show entire file | Ignore whitespace | Details | Blame | Last modification | View Log | RSS feed

Rev 2 Rev 5
Line 22... Line 22...
22
 
22
 
23
#define ADJVOL(S) (((S) *sndVol) / SDL_MIX_MAXVOLUME)
23
#define ADJVOL(S) (((S) *sndVol) / SDL_MIX_MAXVOLUME)
24
 
24
 
25
 
25
 
26
static U8 isAudioActive = FALSE;
26
static U8 isAudioActive = FALSE;
27
static channel_t channel[SYSSND_MIXCHANNELS];
27
static channel_t channels[SYSSND_MIXCHANNELS];
28
 
28
 
29
static U8 sndVol = SDL_MIX_MAXVOLUME;   /* internal volume */
29
static U8 sndVol = SDL_MIX_MAXVOLUME;   /* internal volume */
30
static U8 sndUVol = SYSSND_MAXVOL;   /* user-selected volume */
30
static U8 sndUVol = SYSSND_MAXVOL;   /* user-selected volume */
31
static U8 sndMute = FALSE;   /* mute flag */
31
static U8 sndMute = FALSE;   /* mute flag */
32
 
-
 
33
static SDL_mutex *sndlock;
-
 
34
 
32
 
35
 
33
 
36
/*
34
/*
37
 * prototypes
35
 * prototypes
38
 */
36
 */
39
static int sdlRWops_open (SDL_RWops *context, char *name);
-
 
40
static int sdlRWops_seek (SDL_RWops *context, int offset, int whence);
-
 
41
static int sdlRWops_read (SDL_RWops *context, void *ptr, int size, int maxnum);
-
 
42
static int sdlRWops_write (SDL_RWops *context, const void *ptr, int size, int num);
-
 
43
static int sdlRWops_close (SDL_RWops *context);
-
 
44
static void end_channel (U8);
37
static void end_channel (channel_t *);
45
 
38
 
46
 
39
 
47
/*
40
/*
48
 * Callback -- this is also where all sound mixing is done
41
 * Callback -- this is also where all sound mixing is done
49
 *
42
 *
Line 51... Line 44...
51
 * may be more efficient to mix samples every frame, or maybe everytime a
44
 * may be more efficient to mix samples every frame, or maybe everytime a
52
 * new sound is sent to be played. I don't know.
45
 * new sound is sent to be played. I don't know.
53
 */
46
 */
54
void syssnd_callback (void *userdata, U8 *stream, int len)
47
void syssnd_callback (void *userdata, U8 *stream, int len)
55
{
48
{
-
 
49
   channel_t *channel;
56
   U8 c;
50
   U8 channel_index;
57
   S16 s;
51
   S16 final_sample;
58
   U32 i;
52
   U32 i;
59
 
53
 
60
   SDL_mutexP(sndlock);
-
 
61
 
54
   // 
62
   for (i = 0; i < (U32)len; i++)
55
   for (i = 0; i < (U32)len; i += 2)
63
   {
56
   {
64
      s = 0;
57
      final_sample = 0;
-
 
58
 
65
      for (c = 0; c < SYSSND_MIXCHANNELS; c++)
59
      for (channel_index = 0; channel_index < SYSSND_MIXCHANNELS; channel_index++)
66
      {
60
      {
-
 
61
         channel = &channels[channel_index]; // quick access to channel
-
 
62
 
67
         if (channel[c].loop != 0)
63
         if (channel->loop == 0)
-
 
64
            continue;
-
 
65
 
-
 
66
         // channel is active
-
 
67
         if (channel->len > 0)
68
         {
68
         {
-
 
69
            // not ending
-
 
70
            final_sample += ADJVOL (*((U16 *) channel->buf));
-
 
71
            channel->buf += 2;
69
            /* channel is active */
72
            channel->len -= 2;
-
 
73
         }
-
 
74
         else
-
 
75
         {
-
 
76
            // ending
70
            if (channel[c].len > 0)
77
            if (channel->loop > 0)
-
 
78
               channel->loop--;
-
 
79
 
-
 
80
            if (channel->loop)
71
            {
81
            {
72
               /* not ending */
82
               // just loop
-
 
83
               channel->buf = channel->snd->buf;
-
 
84
               channel->len = channel->snd->len;
-
 
85
 
73
               s += ADJVOL (*channel[c].buf - 0x80);
86
               final_sample += ADJVOL (*((U16 *) channel->buf));
74
               channel[c].buf++;
87
               channel->buf += 2;
75
               channel[c].len--;
88
               channel->len -= 2;
76
            }
89
            }
77
            else
90
            else
78
            {
-
 
79
               /* ending */
-
 
80
               if (channel[c].loop > 0)
-
 
81
                  channel[c].loop--;
-
 
82
 
-
 
83
               if (channel[c].loop)
-
 
84
               {
-
 
85
                  /* just loop */
-
 
86
                  channel[c].buf = channel[c].snd->buf;
-
 
87
                  channel[c].len = channel[c].snd->len;
-
 
88
                  s += ADJVOL (*channel[c].buf - 0x80);
-
 
89
                  channel[c].buf++;
-
 
90
                  channel[c].len--;
-
 
91
               }
-
 
92
               else
-
 
93
                  end_channel(c); /* end for real */
91
               end_channel (channel); // end for real
94
            }
-
 
95
         }
92
         }
96
      }
93
      }
97
 
94
 
98
      if (sndMute)
-
 
99
         stream[i] = 0x80;
-
 
100
      else
-
 
101
      {
-
 
102
         s += 0x80;
-
 
103
         if (s > 0xff) s = 0xff;
-
 
104
         if (s < 0x00) s = 0x00;
-
 
105
         stream[i] = (U8) s;
95
      *((S16 *) &stream[i]) = (sndMute ? 0 : final_sample);
106
      }
-
 
107
   }
96
   }
108
 
-
 
109
   memcpy (stream, stream, len);
-
 
110
 
-
 
111
   SDL_mutexV (sndlock);
-
 
112
}
97
}
113
 
98
 
114
 
99
 
115
static void end_channel (U8 c)
100
static void end_channel (channel_t *channel)
116
{
101
{
117
   channel[c].loop = 0;
102
   channel->loop = 0;
118
   if (channel[c].snd->dispose)
103
   if (channel->snd->dispose)
119
      syssnd_free (channel[c].snd);
104
      syssnd_free (channel->snd);
120
   channel[c].snd = NULL;
105
   channel->snd = NULL;
121
}
106
}
122
 
107
 
123
 
108
 
124
void syssnd_init (void)
109
void syssnd_init (void)
125
{
110
{
126
   SDL_AudioSpec desired, obtained;
111
   SDL_AudioSpec desired;
127
   U16 c;
112
   U16 c;
128
 
113
 
129
   if (SDL_InitSubSystem (SDL_INIT_AUDIO) < 0)
114
   if (SDL_InitSubSystem (SDL_INIT_AUDIO) < 0)
130
      return;
115
      return;
131
 
116
 
132
   desired.freq = SYSSND_FREQ;
117
   desired.freq = SYSSND_FREQ;
133
   desired.format = AUDIO_U8;
118
   desired.format = AUDIO_S16;
134
   desired.channels = SYSSND_CHANNELS;
119
   desired.channels = SYSSND_CHANNELS;
135
   desired.samples = SYSSND_MIXSAMPLES;
120
   desired.samples = SYSSND_MIXSAMPLES;
136
   desired.callback = syssnd_callback;
121
   desired.callback = syssnd_callback;
137
   desired.userdata = NULL;
122
   desired.userdata = NULL;
138
 
123
 
139
   if (SDL_OpenAudio (&desired, &obtained) < 0)
124
   if (SDL_OpenAudio (&desired, NULL) < 0)
140
      return;
125
      return;
141
 
-
 
142
   sndlock = SDL_CreateMutex ();
-
 
143
   if (sndlock == NULL)
-
 
144
   {
-
 
145
      SDL_CloseAudio ();
-
 
146
      return;
-
 
147
   }
-
 
148
 
126
 
149
   if (sysarg_args_vol != 0)
127
   if (sysarg_args_vol != 0)
150
   {
128
   {
151
      sndUVol = sysarg_args_vol;
129
      sndUVol = sysarg_args_vol;
152
      sndVol = SDL_MIX_MAXVOLUME * sndUVol / SYSSND_MAXVOL;
130
      sndVol = SDL_MIX_MAXVOLUME * sndUVol / SYSSND_MAXVOL;
153
   }
131
   }
154
 
132
 
155
   for (c = 0; c < SYSSND_MIXCHANNELS; c++)
133
   for (c = 0; c < SYSSND_MIXCHANNELS; c++)
156
      channel[c].loop = 0;   /* deactivate */
134
      channels[c].loop = 0;   /* deactivate */
157
 
135
 
158
   isAudioActive = TRUE;
136
   isAudioActive = TRUE;
159
   SDL_PauseAudio (0);
137
   SDL_PauseAudio (0);
160
}
138
}
161
 
139
 
Line 167... Line 145...
167
{
145
{
168
   if (!isAudioActive)
146
   if (!isAudioActive)
169
      return;
147
      return;
170
 
148
 
171
   SDL_CloseAudio ();
149
   SDL_CloseAudio ();
172
   SDL_DestroyMutex (sndlock);
-
 
173
   isAudioActive = FALSE;
150
   isAudioActive = FALSE;
174
}
151
}
175
 
152
 
176
 
153
 
177
/*
154
/*
Line 180... Line 157...
180
 * When muted, sounds are still managed but not sent to the dsp, hence
157
 * When muted, sounds are still managed but not sent to the dsp, hence
181
 * it is possible to un-mute at any time.
158
 * it is possible to un-mute at any time.
182
 */
159
 */
183
void syssnd_toggleMute (void)
160
void syssnd_toggleMute (void)
184
{
161
{
185
   SDL_mutexP (sndlock);
-
 
186
   sndMute = !sndMute;
162
   sndMute = !sndMute;
187
   SDL_mutexV (sndlock);
-
 
188
}
163
}
189
 
164
 
190
 
165
 
191
void syssnd_vol (S8 d)
166
void syssnd_vol (S8 d)
192
{
167
{
193
   if ((d < 0 && sndUVol > 0) || (d > 0 && sndUVol < SYSSND_MAXVOL))
168
   if ((d < 0 && sndUVol > 0) || (d > 0 && sndUVol < SYSSND_MAXVOL))
194
   {
169
   {
195
      sndUVol += d;
170
      sndUVol += d;
196
      SDL_mutexP (sndlock);
-
 
197
      sndVol = SDL_MIX_MAXVOLUME * sndUVol / SYSSND_MAXVOL;
171
      sndVol = SDL_MIX_MAXVOLUME * sndUVol / SYSSND_MAXVOL;
198
      SDL_mutexV (sndlock);
-
 
199
   }
172
   }
200
}
173
}
201
 
174
 
202
 
175
 
203
/*
176
/*
Line 210... Line 183...
210
 * twice the same sound playing -- tends to become noisy when too many
183
 * twice the same sound playing -- tends to become noisy when too many
211
 * bad guys die at the same time).
184
 * bad guys die at the same time).
212
 */
185
 */
213
S8 syssnd_play (sound_t *sound, S8 loop)
186
S8 syssnd_play (sound_t *sound, S8 loop)
214
{
187
{
215
   S8 c;
188
   S8 channel_index;
216
 
189
 
217
   if (!isAudioActive)
190
   if ((sound == NULL) || !isAudioActive)
218
      return -1;
191
      return (-1);
219
   if (sound == NULL)
-
 
220
      return -1;
-
 
221
 
192
 
222
   c = 0;
-
 
223
   SDL_mutexP (sndlock);
193
   for (channel_index = 0; channel_index < SYSSND_MIXCHANNELS; channel_index++)
224
   while ((channel[c].snd != sound || channel[c].loop == 0) && channel[c].loop != 0 && c < SYSSND_MIXCHANNELS)
194
      if ((channels[channel_index].snd == sound) || (channels[channel_index].loop == 0))
225
      c++;
195
         break; // look for a free channel slot
226
   if (c == SYSSND_MIXCHANNELS)
196
   if (channel_index == SYSSND_MIXCHANNELS)
227
      c = -1;
197
      return (-1);
228
 
198
 
229
   if (c >= 0)
-
 
230
   {
-
 
231
      channel[c].loop = loop;
199
   channels[channel_index].loop = loop;
232
      channel[c].snd = sound;
200
   channels[channel_index].snd = sound;
233
      channel[c].buf = sound->buf;
201
   channels[channel_index].buf = sound->buf;
234
      channel[c].len = sound->len;
202
   channels[channel_index].len = sound->len;
235
   }
-
 
236
 
203
 
237
   SDL_mutexV (sndlock);
-
 
238
 
-
 
239
   return c;
204
   return (channel_index);
240
}
205
}
241
 
206
 
242
 
207
 
243
/*
208
/*
244
 * Pause
209
 * Pause
245
 *
210
 *
246
 * pause: TRUE or FALSE
211
 * pause: TRUE or FALSE
247
 * clear: TRUE to cleanup all sounds and make sure we start from scratch
212
 * clear: TRUE to cleanup all sounds and make sure we start from scratch
248
 */
213
 */
249
void syssnd_pause (U8 pause, U8 clear)
214
void syssnd_pause (U8 want_pause, U8 want_clear)
250
{
215
{
251
   U8 c;
216
   U8 channel_index;
252
 
217
 
253
   if (!isAudioActive)
218
   if (!isAudioActive)
254
      return;
219
      return;
255
 
220
 
256
   if (clear == TRUE)
221
   if (want_clear)
257
   {
-
 
258
      SDL_mutexP (sndlock);
-
 
259
      for (c = 0; c < SYSSND_MIXCHANNELS; c++)
222
      for (channel_index = 0; channel_index < SYSSND_MIXCHANNELS; channel_index++)
260
         channel[c].loop = 0;
223
         channels[channel_index].loop = 0;
261
      SDL_mutexV (sndlock);
-
 
262
   }
-
 
263
 
224
 
264
   if (pause == TRUE)
-
 
265
      SDL_PauseAudio (1);
-
 
266
   else
-
 
267
      SDL_PauseAudio (0);
225
   SDL_PauseAudio (want_pause ? 1 : 0);
268
}
226
}
269
 
227
 
270
 
228
 
271
/*
229
/*
272
 * Stop a channel
230
 * Stop a channel
Line 274... Line 232...
274
void syssnd_stopchan (S8 chan)
232
void syssnd_stopchan (S8 chan)
275
{
233
{
276
   if (chan < 0 || chan > SYSSND_MIXCHANNELS)
234
   if (chan < 0 || chan > SYSSND_MIXCHANNELS)
277
      return;
235
      return;
278
 
236
 
279
   SDL_mutexP (sndlock);
-
 
280
 
-
 
281
   if (channel[chan].snd)
237
   if (channels[chan].snd)
282
      end_channel (chan);
238
      end_channel (&channels[chan]);
283
 
-
 
284
   SDL_mutexV (sndlock);
-
 
285
}
239
}
286
 
240
 
287
 
241
 
288
/*
242
/*
289
 * Stop a sound
243
 * Stop a sound
Line 292... Line 246...
292
{
246
{
293
   U8 i;
247
   U8 i;
294
 
248
 
295
   if (!sound)
249
   if (!sound)
296
      return;
250
      return;
297
 
-
 
298
   SDL_mutexP (sndlock);
-
 
299
 
251
 
300
   for (i = 0; i < SYSSND_MIXCHANNELS; i++)
252
   for (i = 0; i < SYSSND_MIXCHANNELS; i++)
301
      if (channel[i].snd == sound)
253
      if (channels[i].snd == sound)
302
         end_channel (i);
254
         end_channel (&channels[i]);
303
 
-
 
304
   SDL_mutexV (sndlock);
-
 
305
}
255
}
306
 
256
 
307
 
257
 
308
/*
258
/*
309
 * See if a sound is playing
259
 * See if a sound is playing
310
 */
260
 */
311
int syssnd_isplaying (sound_t *sound)
261
int syssnd_isplaying (sound_t *sound)
312
{
262
{
313
   U8 i, playing;
263
   U8 i;
314
 
-
 
315
   playing = 0;
-
 
316
   SDL_mutexP (sndlock);
-
 
317
 
264
 
318
   for (i = 0; i < SYSSND_MIXCHANNELS; i++)
265
   for (i = 0; i < SYSSND_MIXCHANNELS; i++)
319
      if (channel[i].snd == sound)
266
      if (channels[i].snd == sound)
320
         playing = 1;
267
         return (1);
321
 
268
 
322
   SDL_mutexV (sndlock);
-
 
323
   return playing;
269
   return (0);
324
}
270
}
325
 
271
 
326
 
272
 
327
/*
273
/*
328
 * Stops all channels.
274
 * Stops all channels.
329
 */
275
 */
330
void syssnd_stopall (void)
276
void syssnd_stopall (void)
331
{
277
{
332
   U8 i;
278
   U8 i;
333
 
-
 
334
   SDL_mutexP (sndlock);
-
 
335
 
279
 
336
   for (i = 0; i < SYSSND_MIXCHANNELS; i++)
280
   for (i = 0; i < SYSSND_MIXCHANNELS; i++)
337
      if (channel[i].snd)
281
      if (channels[i].snd)
338
         end_channel (i);
282
         end_channel (&channels[i]);
339
 
-
 
340
   SDL_mutexV (sndlock);
-
 
341
}
283
}
342
 
284
 
343
 
285
 
344
/*
286
/*
345
 * Load a sound.
287
 * Load a sound.
346
 */
288
 */
347
sound_t *syssnd_load (char *name)
289
sound_t *syssnd_load (char *name)
348
{
290
{
349
   char *soundfile_fullpathname;
291
   char *soundfile_fullpathname;
350
   sound_t *s;
292
   sound_t *s;
351
   SDL_RWops *context;
-
 
352
   SDL_AudioSpec audiospec;
293
   SDL_AudioSpec audiospec;
353
 
294
 
354
   /* alloc space for sound file's full pathname and build it */
295
   /* alloc space for sound file's full pathname and build it */
355
   soundfile_fullpathname = (char *) malloc (1024);
296
   soundfile_fullpathname = (char *) malloc (1024);
356
   sprintf_s (soundfile_fullpathname, 1024, "%s/%s", sys_getbasepath (), name);
297
   sprintf_s (soundfile_fullpathname, 1024, "%s/%s", sys_getbasepath (), name);
357
 
-
 
358
   /* alloc context */
-
 
359
   context = malloc (sizeof (SDL_RWops));
-
 
360
   context->seek = sdlRWops_seek;
-
 
361
   context->read = sdlRWops_read;
-
 
362
   context->write = sdlRWops_write;
-
 
363
   context->close = sdlRWops_close;
-
 
364
 
-
 
365
   /* open */
-
 
366
   if (sdlRWops_open (context, soundfile_fullpathname) == -1)
-
 
367
   {
-
 
368
      free (soundfile_fullpathname);
-
 
369
      return NULL;
-
 
370
   }
-
 
371
   free (soundfile_fullpathname);
-
 
372
 
298
 
373
   /* alloc sound */
299
   /* alloc sound */
374
   s = malloc (sizeof (sound_t));
300
   s = malloc (sizeof (sound_t));
375
 
301
 
376
   /* read */
302
   /* read */
377
   /* second param == 1 -> close source once read */
303
   /* second param == 1 -> close source once read */
378
   if (!SDL_LoadWAV_RW (context, 1, &audiospec, &(s->buf), &(s->len)))
304
   if (!SDL_LoadWAV_RW (SDL_RWFromFile (soundfile_fullpathname, "rb"), 1, &audiospec, &(s->buf), &(s->len)))
379
   {
305
   {
380
      free (s);
306
      free (s);
381
      return NULL;
307
      return NULL;
382
   }
308
   }
-
 
309
   free (soundfile_fullpathname);
383
 
310
 
384
   s->dispose = FALSE;
311
   s->dispose = FALSE;
385
 
312
 
386
   return s;
313
   return s;
387
}
314
}
Line 398... Line 325...
398
   if (s->buf)
325
   if (s->buf)
399
      SDL_FreeWAV (s->buf);
326
      SDL_FreeWAV (s->buf);
400
 
327
 
401
   s->buf = NULL;
328
   s->buf = NULL;
402
   s->len = 0;
329
   s->len = 0;
403
}
-
 
404
 
-
 
405
 
-
 
406
/*
-
 
407
 *
-
 
408
 */
-
 
409
static int sdlRWops_open (SDL_RWops *context, char *name)
-
 
410
{
-
 
411
   FILE *fp;
-
 
412
 
-
 
413
   fopen_s (&fp, name, "rb");
-
 
414
 
-
 
415
   if (!fp)
-
 
416
      return -1;
-
 
417
 
-
 
418
   context->hidden.unknown.data1 = (void *) fp;
-
 
419
 
-
 
420
   return 0;
-
 
421
}
-
 
422
 
-
 
423
 
-
 
424
static int sdlRWops_seek (SDL_RWops *context, int offset, int whence)
-
 
425
{
-
 
426
   return (fseek ((FILE *) context->hidden.unknown.data1, offset, whence));
-
 
427
}
-
 
428
 
-
 
429
 
-
 
430
static int sdlRWops_read (SDL_RWops *context, void *ptr, int size, int maxnum)
-
 
431
{
-
 
432
   return (fread (ptr, size, maxnum, (FILE *) context->hidden.unknown.data1));
-
 
433
}
-
 
434
 
-
 
435
 
-
 
436
static int sdlRWops_write (SDL_RWops *context, const void *ptr, int size, int num)
-
 
437
{
-
 
438
   return -1; /* not implemented */
-
 
439
}
-
 
440
 
-
 
441
 
-
 
442
static int sdlRWops_close (SDL_RWops *context)
-
 
443
{
-
 
444
   if (context)
-
 
445
   {
-
 
446
      fclose ((FILE *) context->hidden.unknown.data1);
-
 
447
      free (context);
-
 
448
   }
-
 
449
 
-
 
450
   return 0;
-
 
451
}
330
}