1 /***********************************************************
2 * Artsoft Retro-Game Library *
3 *----------------------------------------------------------*
4 * (c) 1994-2006 Artsoft Entertainment *
5 * Holger Schemel *
6 * Detmolder Strasse 189 *
7 * 33604 Bielefeld *
8 * Germany *
9 * e-mail: info@artsoft.org *
10 *----------------------------------------------------------*
11 * sound.c *
12 ***********************************************************/
13
14 #include <sys/types.h>
15 #include <sys/time.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <fcntl.h>
19 #include <dirent.h>
20 #include <signal.h>
21 #include <math.h>
22
23 #include "platform.h"
24
25 #if defined(PLATFORM_LINUX)
26 #include <sys/ioctl.h>
27 #include <linux/soundcard.h>
28 #elif defined(PLATFORM_FREEBSD)
29 #include <sys/soundcard.h>
30 #elif defined(PLATFORM_NETBSD)
31 #include <sys/ioctl.h>
32 #include <sys/audioio.h>
33 #elif defined(PLATFORM_HPUX)
34 #include <sys/audio.h>
35 #endif
36
37 #include "system.h"
38 #include "sound.h"
39 #include "misc.h"
40 #include "setup.h"
41 #include "text.h"
42
43
44 /* expiration time (in milliseconds) for sound loops */
45 #define SOUND_LOOP_EXPIRATION_TIME 200
46
47 /* one second fading interval == 1000 ticks (milliseconds) */
48 #define SOUND_FADING_INTERVAL 1000
49
50 #if defined(AUDIO_STREAMING_DSP)
51 #define SOUND_FADING_VOLUME_STEP (SOUND_MAX_VOLUME / 40)
52 #define SOUND_FADING_VOLUME_THRESHOLD (SOUND_FADING_VOLUME_STEP * 2)
53 #endif
54
55 #define SND_TYPE_NONE 0
56 #define SND_TYPE_WAV 1
57
58 #define MUS_TYPE_NONE 0
59 #define MUS_TYPE_WAV 1
60 #define MUS_TYPE_MOD 2
61
62 #define DEVICENAME_DSP "/dev/dsp"
63 #define DEVICENAME_SOUND_DSP "/dev/sound/dsp"
64 #define DEVICENAME_AUDIO "/dev/audio"
65 #define DEVICENAME_AUDIOCTL "/dev/audioCtl"
66
67 #define SOUND_VOLUME_LEFT(x) (stereo_volume[x])
68 #define SOUND_VOLUME_RIGHT(x) (stereo_volume[SOUND_MAX_LEFT2RIGHT-x])
69
70 #define SAME_SOUND_NR(x,y) ((x).nr == (y).nr)
71 #define SAME_SOUND_DATA(x,y) ((x).data_ptr == (y).data_ptr)
72
73 #if defined(AUDIO_UNIX_NATIVE)
74 struct SoundHeader_WAV
75 {
76 unsigned short compression_code;
77 unsigned short num_channels;
78 unsigned long sample_rate;
79 unsigned long bytes_per_second;
80 unsigned short block_align;
81 unsigned short bits_per_sample;
82 };
83 #endif
84
85 struct AudioFormatInfo
86 {
87 boolean stereo; /* availability of stereo sound */
88 int format; /* size and endianess of sample data */
89 int sample_rate; /* sample frequency */
90 int fragment_size; /* audio device fragment size in bytes */
91 };
92
93 struct SampleInfo
94 {
95 char *source_filename;
96 int num_references;
97
98 int type;
99 int format;
100 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
101 long data_len; /* number of samples, NOT number of bytes */
102 int num_channels; /* mono: 1 channel, stereo: 2 channels */
103 };
104 typedef struct SampleInfo SoundInfo;
105 typedef struct SampleInfo MusicInfo;
106
107 struct SoundControl
108 {
109 boolean active;
110
111 int nr;
112 int volume;
113 int stereo_position;
114
115 int state;
116
117 unsigned long playing_starttime;
118 unsigned long playing_pos;
119
120 int type;
121 int format;
122 void *data_ptr; /* pointer to first sample (8 or 16 bit) */
123 long data_len; /* number of samples, NOT number of bytes */
124 int num_channels; /* mono: 1 channel, stereo: 2 channels */
125
126 #if defined(TARGET_ALLEGRO)
127 int voice;
128 #endif
129 };
130 typedef struct SoundControl SoundControl;
131
132 static struct ArtworkListInfo *sound_info = NULL;
133 static struct ArtworkListInfo *music_info = NULL;
134
135 static MusicInfo **Music_NoConf = NULL;
136
137 static int num_music_noconf = 0;
138 static int stereo_volume[SOUND_MAX_LEFT2RIGHT + 1];
139
140
141 /* ========================================================================= */
142 /* THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
143
144 static struct SoundControl mixer[NUM_MIXER_CHANNELS];
145 static int mixer_active_channels = 0;
146
147 #if defined(AUDIO_UNIX_NATIVE)
148 static struct AudioFormatInfo afmt;
149
150 static void Mixer_Main(void);
151 #if !defined(AUDIO_STREAMING_DSP)
152 static unsigned char linear_to_ulaw(int);
153 static int ulaw_to_linear(unsigned char);
154 #endif
155 #endif
156
157 static void ReloadCustomSounds();
158 static void ReloadCustomMusic();
159 static void FreeSound(void *);
160 static void FreeMusic(void *);
161 static void FreeAllMusic_NoConf();
162
163 static SoundInfo *getSoundInfoEntryFromSoundID(int);
164 static MusicInfo *getMusicInfoEntryFromMusicID(int);
165
166
167 /* ------------------------------------------------------------------------- */
168 /* functions for native (non-SDL) Unix audio/mixer support */
169 /* ------------------------------------------------------------------------- */
170
171 #if defined(AUDIO_UNIX_NATIVE)
172
OpenAudioDevice(char * audio_device_name)173 static int OpenAudioDevice(char *audio_device_name)
174 {
175 int audio_device_fd;
176
177 /* check if desired audio device is accessible */
178 if (access(audio_device_name, W_OK) != 0)
179 return -1;
180
181 /* try to open audio device in non-blocking mode */
182 if ((audio_device_fd = open(audio_device_name, O_WRONLY | O_NONBLOCK)) < 0)
183 return audio_device_fd;
184
185 /* re-open audio device in blocking mode */
186 close(audio_device_fd);
187 audio_device_fd = open(audio_device_name, O_WRONLY);
188
189 return audio_device_fd;
190 }
191
CloseAudioDevice(int * audio_device_fd)192 static void CloseAudioDevice(int *audio_device_fd)
193 {
194 if (*audio_device_fd == 0)
195 return;
196
197 close(*audio_device_fd);
198 *audio_device_fd = -1;
199 }
200
TestAudioDevices(void)201 static boolean TestAudioDevices(void)
202 {
203 static char *audio_device_name[] =
204 {
205 DEVICENAME_DSP,
206 DEVICENAME_SOUND_DSP,
207 DEVICENAME_AUDIO
208 };
209 int audio_device_fd = -1;
210 int i;
211
212 /* look for available audio devices, starting with preferred ones */
213 for (i = 0; i < sizeof(audio_device_name)/sizeof(char *); i++)
214 if ((audio_device_fd = OpenAudioDevice(audio_device_name[i])) >= 0)
215 break;
216
217 if (audio_device_fd < 0)
218 {
219 Error(ERR_WARN, "cannot open audio device -- no sound");
220 return FALSE;
221 }
222
223 close(audio_device_fd);
224
225 audio.device_name = audio_device_name[i];
226
227 return TRUE;
228 }
229
ForkAudioProcess(void)230 static boolean ForkAudioProcess(void)
231 {
232 if (pipe(audio.mixer_pipe) < 0)
233 {
234 Error(ERR_WARN, "cannot create pipe -- no sounds");
235 return FALSE;
236 }
237
238 if ((audio.mixer_pid = fork()) < 0)
239 {
240 Error(ERR_WARN, "cannot create sound server process -- no sounds");
241 return FALSE;
242 }
243
244 if (audio.mixer_pid == 0) /* we are the child process */
245 audio.mixer_pid = getpid();
246
247 if (IS_CHILD_PROCESS())
248 Mixer_Main(); /* this function never returns */
249 else
250 close(audio.mixer_pipe[0]); /* no reading from pipe needed */
251
252 return TRUE;
253 }
254
UnixOpenAudio(void)255 void UnixOpenAudio(void)
256 {
257 if (!TestAudioDevices())
258 return;
259
260 audio.sound_available = TRUE;
261 audio.sound_enabled = TRUE;
262
263 #if defined(AUDIO_STREAMING_DSP)
264 audio.music_available = TRUE;
265 audio.loops_available = TRUE;
266 #endif
267
268 audio.num_channels = NUM_MIXER_CHANNELS;
269 audio.music_channel = MUSIC_CHANNEL;
270 audio.first_sound_channel = FIRST_SOUND_CHANNEL;
271 }
272
UnixCloseAudio(void)273 void UnixCloseAudio(void)
274 {
275 if (audio.device_fd)
276 close(audio.device_fd);
277
278 if (IS_PARENT_PROCESS() && HAS_CHILD_PROCESS())
279 kill(audio.mixer_pid, SIGTERM);
280 }
281
282
283 /* ------------------------------------------------------------------------- */
284 /* functions for platform specific audio device initialization */
285 /* ------------------------------------------------------------------------- */
286
287 #if defined(AUDIO_LINUX_IOCTL)
InitAudioDevice_Linux(struct AudioFormatInfo * afmt)288 static void InitAudioDevice_Linux(struct AudioFormatInfo *afmt)
289 {
290 /* "ioctl()" expects pointer to 'int' value for stereo flag
291 (boolean is defined as 'char', which will not work here) */
292 unsigned int fragment_spec = 0;
293 int fragment_size_query = -1;
294 int stereo = TRUE;
295 struct
296 {
297 int format_ioctl;
298 int format_result;
299 }
300 formats[] =
301 {
302 /* supported audio format in preferred order */
303 { AFMT_S16_LE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_LE },
304 { AFMT_S16_BE, AUDIO_FORMAT_S16 | AUDIO_FORMAT_BE },
305 { AFMT_U8, AUDIO_FORMAT_U8 },
306 { -1, -1 }
307 };
308 int i;
309
310 /* determine logarithm (log2) of the fragment size */
311 while ((1 << fragment_spec) < afmt->fragment_size)
312 fragment_spec++;
313
314 /* use two fragments (play one fragment, prepare the other);
315 one fragment would result in interrupted audio output, more
316 than two fragments would raise audio output latency to much */
317 fragment_spec |= 0x00020000;
318
319 /* Example for fragment specification:
320 - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz)
321 - (with stereo the effective buffer size will shrink to 256)
322 => fragment_size = 0x00020009 */
323
324 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFRAGMENT, &fragment_spec) < 0)
325 Error(ERR_EXIT_SOUND_SERVER,
326 "cannot set fragment size of audio device -- no sounds");
327
328 i = 0;
329 afmt->format = 0;
330 while (formats[i].format_result != -1)
331 {
332 unsigned int audio_format = formats[i].format_ioctl;
333 if (ioctl(audio.device_fd, SNDCTL_DSP_SETFMT, &audio_format) == 0)
334 {
335 afmt->format = formats[i].format_result;
336 break;
337 }
338 }
339
340 if (afmt->format == 0) /* no supported audio format found */
341 Error(ERR_EXIT_SOUND_SERVER,
342 "cannot set audio format of audio device -- no sounds");
343
344 /* try if we can use stereo sound */
345 afmt->stereo = TRUE;
346 if (ioctl(audio.device_fd, SNDCTL_DSP_STEREO, &stereo) < 0)
347 afmt->stereo = FALSE;
348
349 if (ioctl(audio.device_fd, SNDCTL_DSP_SPEED, &afmt->sample_rate) < 0)
350 Error(ERR_EXIT_SOUND_SERVER,
351 "cannot set sample rate of audio device -- no sounds");
352
353 /* get the real fragmentation size; this should return 512 */
354 if (ioctl(audio.device_fd, SNDCTL_DSP_GETBLKSIZE, &fragment_size_query) < 0)
355 Error(ERR_EXIT_SOUND_SERVER,
356 "cannot get fragment size of audio device -- no sounds");
357 if (fragment_size_query != afmt->fragment_size)
358 Error(ERR_EXIT_SOUND_SERVER,
359 "cannot set fragment size of audio device -- no sounds");
360 }
361 #endif /* AUDIO_LINUX_IOCTL */
362
363 #if defined(PLATFORM_NETBSD)
InitAudioDevice_NetBSD(struct AudioFormatInfo * afmt)364 static void InitAudioDevice_NetBSD(struct AudioFormatInfo *afmt)
365 {
366 audio_info_t a_info;
367 boolean stereo = TRUE;
368
369 AUDIO_INITINFO(&a_info);
370 a_info.play.encoding = AUDIO_ENCODING_LINEAR8;
371 a_info.play.precision = 8;
372 a_info.play.channels = 2;
373 a_info.play.sample_rate = afmt->sample_rate;
374 a_info.blocksize = afmt->fragment_size;
375
376 afmt->format = AUDIO_FORMAT_U8;
377 afmt->stereo = TRUE;
378
379 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
380 {
381 /* try to disable stereo */
382 a_info.play.channels = 1;
383
384 afmt->stereo = FALSE;
385
386 if (ioctl(audio.device_fd, AUDIO_SETINFO, &a_info) < 0)
387 Error(ERR_EXIT_SOUND_SERVER,
388 "cannot set sample rate of audio device -- no sounds");
389 }
390 }
391 #endif /* PLATFORM_NETBSD */
392
393 #if defined(PLATFORM_HPUX)
InitAudioDevice_HPUX(struct AudioFormatInfo * afmt)394 static void InitAudioDevice_HPUX(struct AudioFormatInfo *afmt)
395 {
396 struct audio_describe ainfo;
397 int audio_ctl;
398
399 audio_ctl = open("/dev/audioCtl", O_WRONLY | O_NDELAY);
400 if (audio_ctl == -1)
401 Error(ERR_EXIT_SOUND_SERVER, "cannot open audio device -- no sounds");
402
403 if (ioctl(audio_ctl, AUDIO_DESCRIBE, &ainfo) == -1)
404 Error(ERR_EXIT_SOUND_SERVER, "no audio info -- no sounds");
405
406 if (ioctl(audio_ctl, AUDIO_SET_DATA_FORMAT, AUDIO_FORMAT_ULAW) == -1)
407 Error(ERR_EXIT_SOUND_SERVER, "ulaw audio not available -- no sounds");
408
409 ioctl(audio_ctl, AUDIO_SET_CHANNELS, 1);
410 ioctl(audio_ctl, AUDIO_SET_SAMPLE_RATE, 8000);
411
412 afmt->format = AUDIO_FORMAT_U8;
413 afmt->stereo = FALSE;
414 afmt->sample_rate = 8000;
415
416 close(audio_ctl);
417 }
418 #endif /* PLATFORM_HPUX */
419
InitAudioDevice(struct AudioFormatInfo * afmt)420 static void InitAudioDevice(struct AudioFormatInfo *afmt)
421 {
422 afmt->stereo = TRUE;
423 afmt->format = AUDIO_FORMAT_UNKNOWN;
424 afmt->sample_rate = DEFAULT_AUDIO_SAMPLE_RATE;
425 afmt->fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
426
427 #if defined(AUDIO_LINUX_IOCTL)
428 InitAudioDevice_Linux(afmt);
429 #elif defined(PLATFORM_NETBSD)
430 InitAudioDevice_NetBSD(afmt);
431 #elif defined(PLATFORM_HPUX)
432 InitAudioDevice_HPUX(afmt);
433 #else
434 /* generic /dev/audio stuff might be placed here */
435 #endif
436 }
437
438
439 /* ------------------------------------------------------------------------- */
440 /* functions for communication between main process and sound mixer process */
441 /* ------------------------------------------------------------------------- */
442
SendSoundControlToMixerProcess(SoundControl * snd_ctrl)443 static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl)
444 {
445 if (IS_CHILD_PROCESS())
446 return;
447
448 if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0)
449 {
450 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
451 audio.sound_available = audio.sound_enabled = FALSE;
452 return;
453 }
454 }
455
ReadSoundControlFromMainProcess(SoundControl * snd_ctrl)456 static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl)
457 {
458 if (IS_PARENT_PROCESS())
459 return;
460
461 if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl))
462 != sizeof(SoundControl))
463 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
464 }
465
WriteReloadInfoToPipe(char * set_identifier,int type)466 static void WriteReloadInfoToPipe(char *set_identifier, int type)
467 {
468 SoundControl snd_ctrl;
469 TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current :
470 artwork.mus_current);
471 unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1;
472 unsigned long str_size2 = strlen(leveldir_current->sounds_path) + 1;
473 unsigned long str_size3 = strlen(leveldir_current->music_path) + 1;
474 unsigned long str_size4 = strlen(ti->basepath) + 1;
475 unsigned long str_size5 = strlen(ti->fullpath) + 1;
476 boolean override_level_artwork = (type == SND_CTRL_RELOAD_SOUNDS ?
477 gfx.override_level_sounds :
478 gfx.override_level_music);
479
480 if (IS_CHILD_PROCESS())
481 return;
482
483 if (leveldir_current == NULL) /* should never happen */
484 Error(ERR_EXIT, "leveldir_current == NULL");
485
486 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
487
488 snd_ctrl.active = FALSE;
489 snd_ctrl.state = type;
490 snd_ctrl.data_len = strlen(set_identifier) + 1;
491
492 if (write(audio.mixer_pipe[1], &snd_ctrl,
493 sizeof(snd_ctrl)) < 0 ||
494 write(audio.mixer_pipe[1], set_identifier,
495 snd_ctrl.data_len) < 0 ||
496 write(audio.mixer_pipe[1], &override_level_artwork,
497 sizeof(boolean)) < 0 ||
498 write(audio.mixer_pipe[1], leveldir_current,
499 sizeof(TreeInfo)) < 0 ||
500 write(audio.mixer_pipe[1], ti,
501 sizeof(TreeInfo)) < 0 ||
502 write(audio.mixer_pipe[1], &str_size1,
503 sizeof(unsigned long)) < 0 ||
504 write(audio.mixer_pipe[1], &str_size2,
505 sizeof(unsigned long)) < 0 ||
506 write(audio.mixer_pipe[1], &str_size3,
507 sizeof(unsigned long)) < 0 ||
508 write(audio.mixer_pipe[1], &str_size4,
509 sizeof(unsigned long)) < 0 ||
510 write(audio.mixer_pipe[1], &str_size5,
511 sizeof(unsigned long)) < 0 ||
512 write(audio.mixer_pipe[1], leveldir_current->fullpath,
513 str_size1) < 0 ||
514 write(audio.mixer_pipe[1], leveldir_current->sounds_path,
515 str_size2) < 0 ||
516 write(audio.mixer_pipe[1], leveldir_current->music_path,
517 str_size3) < 0 ||
518 write(audio.mixer_pipe[1], ti->basepath,
519 str_size4) < 0 ||
520 write(audio.mixer_pipe[1], ti->fullpath,
521 str_size5) < 0)
522 {
523 Error(ERR_WARN, "cannot pipe to child process -- no sounds");
524 audio.sound_available = audio.sound_enabled = FALSE;
525 return;
526 }
527 }
528
ReadReloadInfoFromPipe(SoundControl * snd_ctrl)529 static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl)
530 {
531 TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ?
532 &artwork.snd_current : &artwork.mus_current);
533 TreeInfo *ti = *ti_ptr;
534 unsigned long str_size1, str_size2, str_size3, str_size4, str_size5;
535 static char *set_identifier = NULL;
536 boolean *override_level_artwork = (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS ?
537 &gfx.override_level_sounds :
538 &gfx.override_level_music);
539
540 checked_free(set_identifier);
541
542 set_identifier = checked_malloc(snd_ctrl->data_len);
543
544 if (leveldir_current == NULL)
545 leveldir_current = checked_calloc(sizeof(TreeInfo));
546
547 if (ti == NULL)
548 ti = *ti_ptr = checked_calloc(sizeof(TreeInfo));
549
550 checked_free(leveldir_current->fullpath);
551 checked_free(leveldir_current->sounds_path);
552 checked_free(leveldir_current->music_path);
553 checked_free(ti->basepath);
554 checked_free(ti->fullpath);
555
556 if (read(audio.mixer_pipe[0], set_identifier,
557 snd_ctrl->data_len) != snd_ctrl->data_len ||
558 read(audio.mixer_pipe[0], override_level_artwork,
559 sizeof(boolean)) != sizeof(boolean) ||
560 read(audio.mixer_pipe[0], leveldir_current,
561 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
562 read(audio.mixer_pipe[0], ti,
563 sizeof(TreeInfo)) != sizeof(TreeInfo) ||
564 read(audio.mixer_pipe[0], &str_size1,
565 sizeof(unsigned long)) != sizeof(unsigned long) ||
566 read(audio.mixer_pipe[0], &str_size2,
567 sizeof(unsigned long)) != sizeof(unsigned long) ||
568 read(audio.mixer_pipe[0], &str_size3,
569 sizeof(unsigned long)) != sizeof(unsigned long) ||
570 read(audio.mixer_pipe[0], &str_size4,
571 sizeof(unsigned long)) != sizeof(unsigned long) ||
572 read(audio.mixer_pipe[0], &str_size5,
573 sizeof(unsigned long)) != sizeof(unsigned long))
574 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
575
576 leveldir_current->fullpath = checked_calloc(str_size1);
577 leveldir_current->sounds_path = checked_calloc(str_size2);
578 leveldir_current->music_path = checked_calloc(str_size3);
579 ti->basepath = checked_calloc(str_size4);
580 ti->fullpath = checked_calloc(str_size5);
581
582 if (read(audio.mixer_pipe[0], leveldir_current->fullpath,
583 str_size1) != str_size1 ||
584 read(audio.mixer_pipe[0], leveldir_current->sounds_path,
585 str_size2) != str_size2 ||
586 read(audio.mixer_pipe[0], leveldir_current->music_path,
587 str_size3) != str_size3 ||
588 read(audio.mixer_pipe[0], ti->basepath,
589 str_size4) != str_size4 ||
590 read(audio.mixer_pipe[0], ti->fullpath,
591 str_size5) != str_size5)
592 Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
593
594 if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS)
595 artwork.snd_current_identifier = set_identifier;
596 else
597 artwork.mus_current_identifier = set_identifier;
598 }
599
600 #endif /* AUDIO_UNIX_NATIVE */
601
602
603 /* ------------------------------------------------------------------------- */
604 /* mixer functions */
605 /* ------------------------------------------------------------------------- */
606
Mixer_InitChannels()607 void Mixer_InitChannels()
608 {
609 int i;
610
611 for (i = 0; i < audio.num_channels; i++)
612 mixer[i].active = FALSE;
613 mixer_active_channels = 0;
614 }
615
Mixer_ResetChannelExpiration(int channel)616 static void Mixer_ResetChannelExpiration(int channel)
617 {
618 mixer[channel].playing_starttime = Counter();
619
620 #if defined(TARGET_SDL)
621 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]))
622 Mix_ExpireChannel(channel, SOUND_LOOP_EXPIRATION_TIME);
623 #endif
624 }
625
Mixer_ChannelExpired(int channel)626 static boolean Mixer_ChannelExpired(int channel)
627 {
628 if (!mixer[channel].active)
629 return TRUE;
630
631 if (IS_LOOP(mixer[channel]) && !IS_MUSIC(mixer[channel]) &&
632 DelayReached(&mixer[channel].playing_starttime,
633 SOUND_LOOP_EXPIRATION_TIME))
634 return TRUE;
635
636 #if defined(TARGET_SDL)
637
638 if (!Mix_Playing(channel))
639 return TRUE;
640
641 #elif defined(TARGET_ALLEGRO)
642
643 mixer[channel].playing_pos = voice_get_position(mixer[channel].voice);
644 mixer[channel].volume = voice_get_volume(mixer[channel].voice);
645
646 /* sound sample has completed playing or was completely faded out */
647 if (mixer[channel].playing_pos == -1 || mixer[channel].volume == 0)
648 return TRUE;
649
650 #endif /* TARGET_ALLEGRO */
651
652 return FALSE;
653 }
654
Mixer_AllocateChannel(int channel)655 static boolean Mixer_AllocateChannel(int channel)
656 {
657 #if defined(TARGET_ALLEGRO)
658 mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr);
659 if (mixer[channel].voice < 0)
660 return FALSE;
661 #endif
662
663 return TRUE;
664 }
665
Mixer_SetChannelProperties(int channel)666 static void Mixer_SetChannelProperties(int channel)
667 {
668 #if defined(TARGET_SDL)
669 Mix_Volume(channel, mixer[channel].volume);
670 Mix_SetPanning(channel,
671 SOUND_VOLUME_LEFT(mixer[channel].stereo_position),
672 SOUND_VOLUME_RIGHT(mixer[channel].stereo_position));
673 #elif defined(TARGET_ALLEGRO)
674 voice_set_volume(mixer[channel].voice, mixer[channel].volume);
675 voice_set_pan(mixer[channel].voice, mixer[channel].stereo_position);
676 #endif
677 }
678
Mixer_StartChannel(int channel)679 static void Mixer_StartChannel(int channel)
680 {
681 #if defined(TARGET_SDL)
682 Mix_PlayChannel(channel, mixer[channel].data_ptr,
683 IS_LOOP(mixer[channel]) ? -1 : 0);
684 #elif defined(TARGET_ALLEGRO)
685 if (IS_LOOP(mixer[channel]))
686 voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP);
687
688 voice_start(mixer[channel].voice);
689 #endif
690 }
691
Mixer_PlayChannel(int channel)692 static void Mixer_PlayChannel(int channel)
693 {
694 /* start with inactive channel in case something goes wrong */
695 mixer[channel].active = FALSE;
696
697 if (mixer[channel].type != MUS_TYPE_WAV)
698 return;
699
700 if (!Mixer_AllocateChannel(channel))
701 return;
702
703 Mixer_SetChannelProperties(channel);
704 Mixer_StartChannel(channel);
705
706 Mixer_ResetChannelExpiration(channel);
707
708 mixer[channel].playing_pos = 0;
709 mixer[channel].active = TRUE;
710 mixer_active_channels++;
711 }
712
Mixer_PlayMusicChannel()713 static void Mixer_PlayMusicChannel()
714 {
715 Mixer_PlayChannel(audio.music_channel);
716
717 #if defined(TARGET_SDL)
718 if (mixer[audio.music_channel].type != MUS_TYPE_WAV)
719 {
720 /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() --
721 this looks like a bug in the SDL_mixer library */
722 Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1);
723 Mix_VolumeMusic(SOUND_MAX_VOLUME);
724 }
725 #endif
726 }
727
Mixer_StopChannel(int channel)728 static void Mixer_StopChannel(int channel)
729 {
730 if (!mixer[channel].active)
731 return;
732
733 #if defined(TARGET_SDL)
734 Mix_HaltChannel(channel);
735 #elif defined(TARGET_ALLEGRO)
736 voice_set_volume(mixer[channel].voice, 0);
737 deallocate_voice(mixer[channel].voice);
738 #endif
739
740 mixer[channel].active = FALSE;
741 mixer_active_channels--;
742 }
743
Mixer_StopMusicChannel()744 static void Mixer_StopMusicChannel()
745 {
746 Mixer_StopChannel(audio.music_channel);
747
748 #if defined(TARGET_SDL)
749 Mix_HaltMusic();
750 #endif
751 }
752
Mixer_FadeChannel(int channel)753 static void Mixer_FadeChannel(int channel)
754 {
755 if (!mixer[channel].active)
756 return;
757
758 mixer[channel].state |= SND_CTRL_FADE;
759
760 #if defined(TARGET_SDL)
761 Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL);
762 #elif defined(TARGET_ALLEGRO)
763 if (voice_check(mixer[channel].voice))
764 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0);
765 #endif
766 }
767
Mixer_FadeMusicChannel()768 static void Mixer_FadeMusicChannel()
769 {
770 Mixer_FadeChannel(audio.music_channel);
771
772 #if defined(TARGET_SDL)
773 Mix_FadeOutMusic(SOUND_FADING_INTERVAL);
774 #endif
775 }
776
Mixer_UnFadeChannel(int channel)777 static void Mixer_UnFadeChannel(int channel)
778 {
779 if (!mixer[channel].active || !IS_FADING(mixer[channel]))
780 return;
781
782 mixer[channel].state &= ~SND_CTRL_FADE;
783 mixer[channel].volume = SOUND_MAX_VOLUME;
784
785 #if defined(TARGET_SDL)
786 Mix_ExpireChannel(channel, -1);
787 Mix_Volume(channel, mixer[channel].volume);
788 #elif defined(TARGET_ALLEGRO)
789 voice_stop_volumeramp(mixer[channel].voice);
790 voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL,
791 mixer[channel].volume);
792 #endif
793 }
794
Mixer_InsertSound(SoundControl snd_ctrl)795 static void Mixer_InsertSound(SoundControl snd_ctrl)
796 {
797 SoundInfo *snd_info;
798 int i, k;
799 int num_sounds = getSoundListSize();
800 int num_music = getMusicListSize();
801
802 if (IS_MUSIC(snd_ctrl))
803 {
804 if (snd_ctrl.nr >= num_music) /* invalid music */
805 return;
806
807 if (snd_ctrl.nr < 0) /* undefined music */
808 {
809 if (num_music_noconf == 0) /* no fallback music available */
810 return;
811
812 snd_ctrl.nr = UNMAP_NOCONF_MUSIC(snd_ctrl.nr) % num_music_noconf;
813 snd_info = Music_NoConf[snd_ctrl.nr];
814 }
815 else
816 snd_info = getMusicInfoEntryFromMusicID(snd_ctrl.nr);
817 }
818 else
819 {
820 if (snd_ctrl.nr < 0 || snd_ctrl.nr >= num_sounds)
821 return;
822
823 snd_info = getSoundInfoEntryFromSoundID(snd_ctrl.nr);
824 }
825
826 if (snd_info == NULL)
827 return;
828
829 /* copy sound sample and format information */
830 snd_ctrl.type = snd_info->type;
831 snd_ctrl.format = snd_info->format;
832 snd_ctrl.data_ptr = snd_info->data_ptr;
833 snd_ctrl.data_len = snd_info->data_len;
834 snd_ctrl.num_channels = snd_info->num_channels;
835
836 /* play music samples on a dedicated music channel */
837 if (IS_MUSIC(snd_ctrl))
838 {
839 Mixer_StopMusicChannel();
840
841 mixer[audio.music_channel] = snd_ctrl;
842 Mixer_PlayMusicChannel();
843
844 return;
845 }
846
847 /* check if (and how often) this sound sample is already playing */
848 for (k = 0, i = audio.first_sound_channel; i < audio.num_channels; i++)
849 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
850 k++;
851
852 /* reset expiration delay for already playing loop sounds */
853 if (k > 0 && IS_LOOP(snd_ctrl))
854 {
855 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
856 {
857 if (mixer[i].active && SAME_SOUND_DATA(mixer[i], snd_ctrl))
858 {
859 if (IS_FADING(mixer[i]))
860 Mixer_UnFadeChannel(i);
861
862 /* restore settings like volume and stereo position */
863 mixer[i].volume = snd_ctrl.volume;
864 mixer[i].stereo_position = snd_ctrl.stereo_position;
865
866 Mixer_SetChannelProperties(i);
867 Mixer_ResetChannelExpiration(i);
868 }
869 }
870
871 return;
872 }
873
874 /* don't play sound more than n times simultaneously (with n == 2 for now) */
875 if (k >= 2)
876 {
877 unsigned long playing_current = Counter();
878 int longest = 0, longest_nr = audio.first_sound_channel;
879
880 /* look for oldest equal sound */
881 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
882 {
883 int playing_time = playing_current - mixer[i].playing_starttime;
884 int actual;
885
886 if (!mixer[i].active || !SAME_SOUND_NR(mixer[i], snd_ctrl))
887 continue;
888
889 actual = 1000 * playing_time / mixer[i].data_len;
890
891 if (actual >= longest)
892 {
893 longest = actual;
894 longest_nr = i;
895 }
896 }
897
898 Mixer_StopChannel(longest_nr);
899 }
900
901 /* If all (non-music) channels are active, stop the channel that has
902 played its sound sample most completely (in percent of the sample
903 length). As we cannot currently get the actual playing position
904 of the channel's sound sample when compiling with the SDL mixer
905 library, we use the current playing time (in milliseconds) instead. */
906
907 #if DEBUG
908 /* channel allocation sanity check -- should not be needed */
909 if (mixer_active_channels ==
910 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
911 {
912 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
913 {
914 if (!mixer[i].active)
915 {
916 Error(ERR_INFO, "Mixer_InsertSound: Channel %d inactive", i);
917 Error(ERR_INFO, "Mixer_InsertSound: This should never happen!");
918
919 mixer_active_channels--;
920 }
921 }
922 }
923 #endif
924
925 if (mixer_active_channels ==
926 audio.num_channels - (mixer[audio.music_channel].active ? 0 : 1))
927 {
928 unsigned long playing_current = Counter();
929 int longest = 0, longest_nr = audio.first_sound_channel;
930
931 #if 0
932 #if DEBUG
933 /* print some debugging information about audio channel usage */
934 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
935 {
936 Error(ERR_INFO, "Mixer_InsertSound: %d [%d]: %ld (%ld)",
937 i, mixer[i].active, mixer[i].data_len, (long)mixer[i].data_ptr);
938 }
939 #endif
940 #endif
941
942 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
943 {
944 int playing_time = playing_current - mixer[i].playing_starttime;
945 int actual = 1000 * playing_time / mixer[i].data_len;
946
947 if (!IS_LOOP(mixer[i]) && actual > longest)
948 {
949 longest = actual;
950 longest_nr = i;
951 }
952 }
953
954 Mixer_StopChannel(longest_nr);
955 }
956
957 /* add the new sound to the mixer */
958 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
959 {
960 if (!mixer[i].active)
961 {
962 #if defined(AUDIO_UNIX_NATIVE)
963 if (snd_info->data_len == 0)
964 {
965 printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
966 }
967 #endif
968
969 mixer[i] = snd_ctrl;
970 Mixer_PlayChannel(i);
971
972 break;
973 }
974 }
975 }
976
HandleSoundRequest(SoundControl snd_ctrl)977 static void HandleSoundRequest(SoundControl snd_ctrl)
978 {
979 int i;
980
981 #if defined(AUDIO_UNIX_NATIVE)
982 if (IS_PARENT_PROCESS())
983 {
984 SendSoundControlToMixerProcess(&snd_ctrl);
985 return;
986 }
987 #endif
988
989 /* deactivate channels that have expired since the last request */
990 for (i = 0; i < audio.num_channels; i++)
991 if (mixer[i].active && Mixer_ChannelExpired(i))
992 Mixer_StopChannel(i);
993
994 if (IS_RELOADING(snd_ctrl)) /* load new sound or music files */
995 {
996 Mixer_StopMusicChannel();
997 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
998 Mixer_StopChannel(i);
999
1000 #if defined(AUDIO_UNIX_NATIVE)
1001 CloseAudioDevice(&audio.device_fd);
1002 ReadReloadInfoFromPipe(&snd_ctrl);
1003 #endif
1004
1005 if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS)
1006 ReloadCustomSounds();
1007 else
1008 ReloadCustomMusic();
1009 }
1010 else if (IS_FADING(snd_ctrl)) /* fade out existing sound or music */
1011 {
1012 if (IS_MUSIC(snd_ctrl))
1013 {
1014 Mixer_FadeMusicChannel();
1015 return;
1016 }
1017
1018 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
1019 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1020 Mixer_FadeChannel(i);
1021 }
1022 else if (IS_STOPPING(snd_ctrl)) /* stop existing sound or music */
1023 {
1024 if (IS_MUSIC(snd_ctrl))
1025 {
1026 Mixer_StopMusicChannel();
1027 return;
1028 }
1029
1030 for (i = audio.first_sound_channel; i < audio.num_channels; i++)
1031 if (SAME_SOUND_NR(mixer[i], snd_ctrl) || ALL_SOUNDS(snd_ctrl))
1032 Mixer_StopChannel(i);
1033
1034 #if defined(AUDIO_UNIX_NATIVE)
1035 if (!mixer_active_channels)
1036 CloseAudioDevice(&audio.device_fd);
1037 #endif
1038 }
1039 else if (snd_ctrl.active) /* add new sound to mixer */
1040 {
1041 Mixer_InsertSound(snd_ctrl);
1042 }
1043 }
1044
StartMixer(void)1045 void StartMixer(void)
1046 {
1047 int i;
1048
1049 #if 0
1050 SDL_version compile_version;
1051 const SDL_version *link_version;
1052 MIX_VERSION(&compile_version);
1053 printf("compiled with SDL_mixer version: %d.%d.%d\n",
1054 compile_version.major,
1055 compile_version.minor,
1056 compile_version.patch);
1057 link_version = Mix_Linked_Version();
1058 printf("running with SDL_mixer version: %d.%d.%d\n",
1059 link_version->major,
1060 link_version->minor,
1061 link_version->patch);
1062 #endif
1063
1064 if (!audio.sound_available)
1065 return;
1066
1067 /* initialize stereo position conversion information */
1068 for (i = 0; i <= SOUND_MAX_LEFT2RIGHT; i++)
1069 stereo_volume[i] =
1070 (int)sqrt((float)(SOUND_MAX_LEFT2RIGHT * SOUND_MAX_LEFT2RIGHT - i * i));
1071
1072 #if defined(AUDIO_UNIX_NATIVE)
1073 if (!ForkAudioProcess())
1074 audio.sound_available = FALSE;
1075 #endif
1076 }
1077
1078 #if defined(AUDIO_UNIX_NATIVE)
1079
CopySampleToMixingBuffer(SoundControl * snd_ctrl,int sample_pos,int sample_size,short * buffer_base_ptr,int buffer_pos,int num_output_channels)1080 static void CopySampleToMixingBuffer(SoundControl *snd_ctrl,
1081 int sample_pos, int sample_size,
1082 short *buffer_base_ptr, int buffer_pos,
1083 int num_output_channels)
1084 {
1085 short *buffer_ptr = buffer_base_ptr + num_output_channels * buffer_pos;
1086 int num_channels = snd_ctrl->num_channels;
1087 int stepsize = num_channels;
1088 int output_stepsize = num_output_channels;
1089 int i, j;
1090
1091 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1092 {
1093 byte *sample_ptr = (byte *)snd_ctrl->data_ptr + num_channels * sample_pos;
1094
1095 for (i = 0; i < num_output_channels; i++)
1096 {
1097 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1098
1099 for (j = 0; j < sample_size; j++)
1100 buffer_ptr[output_stepsize * j + i] =
1101 ((short)(sample_ptr[stepsize * j + offset] ^ 0x80)) << 8;
1102 }
1103 }
1104 else /* AUDIO_FORMAT_S16 */
1105 {
1106 short *sample_ptr= (short *)snd_ctrl->data_ptr + num_channels * sample_pos;
1107
1108 for (i = 0; i < num_output_channels; i++)
1109 {
1110 int offset = (snd_ctrl->num_channels == 1 ? 0 : i);
1111
1112 for (j = 0; j < sample_size; j++)
1113 buffer_ptr[output_stepsize * j + i] =
1114 sample_ptr[stepsize * j + offset];
1115 }
1116 }
1117 }
1118
1119 #if defined(AUDIO_STREAMING_DSP)
Mixer_Main_DSP()1120 static void Mixer_Main_DSP()
1121 {
1122 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1123 static long premix_last_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1124 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1125 boolean stereo;
1126 int fragment_size;
1127 int sample_bytes;
1128 int max_sample_size;
1129 int num_output_channels;
1130 int i, j;
1131
1132 if (!mixer_active_channels)
1133 return;
1134
1135 if (audio.device_fd < 0)
1136 {
1137 if ((audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1138 return;
1139
1140 InitAudioDevice(&afmt);
1141 }
1142
1143 stereo = afmt.stereo;
1144 fragment_size = afmt.fragment_size;
1145 sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
1146 num_output_channels = (stereo ? 2 : 1);
1147 max_sample_size = fragment_size / (num_output_channels * sample_bytes);
1148
1149 /* first clear the last premixing buffer */
1150 clear_mem(premix_last_buffer,
1151 max_sample_size * num_output_channels * sizeof(long));
1152
1153 for (i = 0; i < audio.num_channels; i++)
1154 {
1155 void *sample_ptr;
1156 int sample_len;
1157 int sample_pos;
1158 int sample_size;
1159
1160 if (!mixer[i].active)
1161 continue;
1162
1163 if (Mixer_ChannelExpired(i))
1164 {
1165 Mixer_StopChannel(i);
1166 continue;
1167 }
1168
1169 /* pointer, lenght and actual playing position of sound sample */
1170 sample_ptr = mixer[i].data_ptr;
1171 sample_len = mixer[i].data_len;
1172 sample_pos = mixer[i].playing_pos;
1173 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1174 mixer[i].playing_pos += sample_size;
1175
1176 /* copy original sample to first mixing buffer */
1177 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1178 premix_first_buffer, 0, num_output_channels);
1179
1180 /* are we about to restart a looping sound? */
1181 if (IS_LOOP(mixer[i]) && sample_size < max_sample_size)
1182 {
1183 while (sample_size < max_sample_size)
1184 {
1185 int restarted_sample_size =
1186 MIN(max_sample_size - sample_size, sample_len);
1187
1188 CopySampleToMixingBuffer(&mixer[i], 0, restarted_sample_size,
1189 premix_first_buffer, sample_size,
1190 num_output_channels);
1191
1192 mixer[i].playing_pos = restarted_sample_size;
1193 sample_size += restarted_sample_size;
1194 }
1195 }
1196
1197 /* decrease volume if sound is fading out */
1198 if (IS_FADING(mixer[i]) &&
1199 mixer[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
1200 mixer[i].volume -= SOUND_FADING_VOLUME_STEP;
1201
1202 /* adjust volume of actual sound sample */
1203 if (mixer[i].volume != SOUND_MAX_VOLUME)
1204 for (j = 0; j < sample_size * num_output_channels; j++)
1205 premix_first_buffer[j] =
1206 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1207
1208 /* adjust left and right channel volume due to stereo sound position */
1209 if (stereo)
1210 {
1211 int left_volume = SOUND_VOLUME_LEFT(mixer[i].stereo_position);
1212 int right_volume = SOUND_VOLUME_RIGHT(mixer[i].stereo_position);
1213
1214 for (j = 0; j < sample_size; j++)
1215 {
1216 premix_first_buffer[2 * j + 0] =
1217 left_volume * premix_first_buffer[2 * j + 0] / SOUND_MAX_LEFT2RIGHT;
1218 premix_first_buffer[2 * j + 1] =
1219 right_volume * premix_first_buffer[2 * j + 1] / SOUND_MAX_LEFT2RIGHT;
1220 }
1221 }
1222
1223 /* fill the last mixing buffer with stereo or mono sound */
1224 for (j = 0; j < sample_size * num_output_channels; j++)
1225 premix_last_buffer[j] += premix_first_buffer[j];
1226
1227 /* delete completed sound entries from the mixer */
1228 if (mixer[i].playing_pos >= mixer[i].data_len)
1229 {
1230 if (IS_LOOP(mixer[i]))
1231 mixer[i].playing_pos = 0;
1232 else
1233 Mixer_StopChannel(i);
1234 }
1235 else if (mixer[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
1236 Mixer_StopChannel(i);
1237 }
1238
1239 /* prepare final playing buffer according to system audio format */
1240 for (i = 0; i < max_sample_size * num_output_channels; i++)
1241 {
1242 /* cut off at 17 bit value */
1243 if (premix_last_buffer[i] < -65535)
1244 premix_last_buffer[i] = -65535;
1245 else if (premix_last_buffer[i] > 65535)
1246 premix_last_buffer[i] = 65535;
1247
1248 /* shift to 16 bit value */
1249 premix_last_buffer[i] >>= 1;
1250
1251 if (afmt.format & AUDIO_FORMAT_U8)
1252 {
1253 playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
1254 }
1255 else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
1256 {
1257 playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
1258 playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
1259 }
1260 else /* big endian */
1261 {
1262 playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
1263 playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
1264 }
1265 }
1266
1267 /* finally play the sound fragment */
1268 write(audio.device_fd, playing_buffer, fragment_size);
1269
1270 if (!mixer_active_channels)
1271 CloseAudioDevice(&audio.device_fd);
1272 }
1273
1274 #else /* !AUDIO_STREAMING_DSP */
1275
Mixer_Main_SimpleAudio(SoundControl snd_ctrl)1276 static int Mixer_Main_SimpleAudio(SoundControl snd_ctrl)
1277 {
1278 static short premix_first_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1279 static byte playing_buffer[DEFAULT_AUDIO_FRAGMENT_SIZE];
1280 int max_sample_size = DEFAULT_AUDIO_FRAGMENT_SIZE;
1281 int num_output_channels = 1;
1282 void *sample_ptr;
1283 int sample_len;
1284 int sample_pos;
1285 int sample_size;
1286 int i, j;
1287
1288 i = 1;
1289
1290 /* pointer, lenght and actual playing position of sound sample */
1291 sample_ptr = mixer[i].data_ptr;
1292 sample_len = mixer[i].data_len;
1293 sample_pos = mixer[i].playing_pos;
1294 sample_size = MIN(max_sample_size, sample_len - sample_pos);
1295 mixer[i].playing_pos += sample_size;
1296
1297 /* copy original sample to first mixing buffer */
1298 CopySampleToMixingBuffer(&mixer[i], sample_pos, sample_size,
1299 premix_first_buffer, 0, num_output_channels);
1300
1301 /* adjust volume of actual sound sample */
1302 if (mixer[i].volume != SOUND_MAX_VOLUME)
1303 for (j = 0; j < sample_size; j++)
1304 premix_first_buffer[j] =
1305 mixer[i].volume * (long)premix_first_buffer[j] / SOUND_MAX_VOLUME;
1306
1307 /* might be needed for u-law /dev/audio */
1308 for (j = 0; j < sample_size; j++)
1309 playing_buffer[j] =
1310 linear_to_ulaw(premix_first_buffer[j]);
1311
1312 /* delete completed sound entries from the mixer */
1313 if (mixer[i].playing_pos >= mixer[i].data_len)
1314 Mixer_StopChannel(i);
1315
1316 for (i = 0; i < sample_size; i++)
1317 playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
1318
1319 /* finally play the sound fragment */
1320 write(audio.device_fd, playing_buffer, sample_size);
1321
1322 return sample_size;
1323 }
1324 #endif /* !AUDIO_STREAMING_DSP */
1325
Mixer_Main()1326 void Mixer_Main()
1327 {
1328 SoundControl snd_ctrl;
1329 fd_set mixer_fdset;
1330
1331 close(audio.mixer_pipe[1]); /* no writing into pipe needed */
1332
1333 Mixer_InitChannels();
1334
1335 #if defined(PLATFORM_HPUX)
1336 InitAudioDevice(&afmt);
1337 #endif
1338
1339 FD_ZERO(&mixer_fdset);
1340 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1341
1342 while (1) /* wait for sound playing commands from client */
1343 {
1344 struct timeval delay = { 0, 0 };
1345
1346 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1347 select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL);
1348 if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset))
1349 continue;
1350
1351 ReadSoundControlFromMainProcess(&snd_ctrl);
1352
1353 HandleSoundRequest(snd_ctrl);
1354
1355 #if defined(AUDIO_STREAMING_DSP)
1356
1357 while (mixer_active_channels &&
1358 select(audio.mixer_pipe[0] + 1,
1359 &mixer_fdset, NULL, NULL, &delay) < 1)
1360 {
1361 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1362
1363 Mixer_Main_DSP();
1364 }
1365
1366 #else /* !AUDIO_STREAMING_DSP */
1367
1368 if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
1369 (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
1370 continue;
1371
1372 InitAudioDevice(&afmt);
1373
1374 delay.tv_sec = 0;
1375 delay.tv_usec = 0;
1376
1377 while (mixer_active_channels &&
1378 select(audio.mixer_pipe[0] + 1,
1379 &mixer_fdset, NULL, NULL, &delay) < 1)
1380 {
1381 int wait_percent = 90; /* wait 90% of the real playing time */
1382 int sample_size;
1383
1384 FD_SET(audio.mixer_pipe[0], &mixer_fdset);
1385
1386 sample_size = Mixer_Main_SimpleAudio(snd_ctrl);
1387
1388 delay.tv_sec = 0;
1389 delay.tv_usec =
1390 ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
1391 }
1392
1393 CloseAudioDevice(&audio.device_fd);
1394
1395 Mixer_InitChannels(); /* remove all sounds from mixer */
1396
1397 #endif /* !AUDIO_STREAMING_DSP */
1398 }
1399 }
1400 #endif /* AUDIO_UNIX_NATIVE */
1401
1402
1403 #if defined(AUDIO_UNIX_NATIVE) && !defined(AUDIO_STREAMING_DSP)
1404
1405 /* these two are stolen from "sox"... :) */
1406
1407 /*
1408 ** This routine converts from linear to ulaw.
1409 **
1410 ** Craig Reese: IDA/Supercomputing Research Center
1411 ** Joe Campbell: Department of Defense
1412 ** 29 September 1989
1413 **
1414 ** References:
1415 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1416 ** 2) "A New Digital Technique for Implementation of Any
1417 ** Continuous PCM Companding Law," Villeret, Michel,
1418 ** et al. 1973 IEEE Int. Conf. on Communications, Vol 1,
1419 ** 1973, pg. 11.12-11.17
1420 ** 3) MIL-STD-188-113,"Interoperability and Performance Standards
1421 ** for Analog-to_Digital Conversion Techniques,"
1422 ** 17 February 1987
1423 **
1424 ** Input: Signed 16 bit linear sample
1425 ** Output: 8 bit ulaw sample
1426 */
1427
1428 #define ZEROTRAP /* turn on the trap as per the MIL-STD */
1429 #define BIAS 0x84 /* define the add-in bias for 16 bit samples */
1430 #define CLIP 32635
1431
linear_to_ulaw(int sample)1432 static unsigned char linear_to_ulaw(int sample)
1433 {
1434 static int exp_lut[256] =
1435 {
1436 0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
1437 4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
1438 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1439 5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
1440 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1441 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1442 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1443 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
1444 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1445 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1446 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1447 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1448 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1449 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1450 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
1451 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7
1452 };
1453
1454 int sign, exponent, mantissa;
1455 unsigned char ulawbyte;
1456
1457 /* Get the sample into sign-magnitude. */
1458 sign = (sample >> 8) & 0x80; /* set aside the sign */
1459 if (sign != 0)
1460 sample = -sample; /* get magnitude */
1461 if (sample > CLIP)
1462 sample = CLIP; /* clip the magnitude */
1463
1464 /* Convert from 16 bit linear to ulaw. */
1465 sample = sample + BIAS;
1466 exponent = exp_lut[( sample >> 7 ) & 0xFF];
1467 mantissa = ( sample >> ( exponent + 3 ) ) & 0x0F;
1468 ulawbyte = ~ ( sign | ( exponent << 4 ) | mantissa );
1469 #ifdef ZEROTRAP
1470 if (ulawbyte == 0)
1471 ulawbyte = 0x02; /* optional CCITT trap */
1472 #endif
1473
1474 return(ulawbyte);
1475 }
1476
1477 /*
1478 ** This routine converts from ulaw to 16 bit linear.
1479 **
1480 ** Craig Reese: IDA/Supercomputing Research Center
1481 ** 29 September 1989
1482 **
1483 ** References:
1484 ** 1) CCITT Recommendation G.711 (very difficult to follow)
1485 ** 2) MIL-STD-188-113,"Interoperability and Performance Standards
1486 ** for Analog-to_Digital Conversion Techniques,"
1487 ** 17 February 1987
1488 **
1489 ** Input: 8 bit ulaw sample
1490 ** Output: signed 16 bit linear sample
1491 */
1492
ulaw_to_linear(unsigned char ulawbyte)1493 static int ulaw_to_linear(unsigned char ulawbyte)
1494 {
1495 static int exp_lut[8] = { 0, 132, 396, 924, 1980, 4092, 8316, 16764 };
1496 int sign, exponent, mantissa, sample;
1497
1498 ulawbyte = ~ ulawbyte;
1499 sign = ( ulawbyte & 0x80 );
1500 exponent = ( ulawbyte >> 4 ) & 0x07;
1501 mantissa = ulawbyte & 0x0F;
1502 sample = exp_lut[exponent] + ( mantissa << ( exponent + 3 ) );
1503 if (sign != 0)
1504 sample = -sample;
1505
1506 return(sample);
1507 }
1508 #endif /* AUDIO_UNIX_NATIVE && !AUDIO_STREAMING_DSP */
1509
1510
1511 /* THE STUFF ABOVE IS ONLY USED BY THE SOUND SERVER CHILD PROCESS */
1512 /* ========================================================================= */
1513 /* THE STUFF BELOW IS ONLY USED BY THE MAIN PROCESS */
1514
1515 #define CHUNK_ID_LEN 4 /* IFF style chunk id length */
1516 #define WAV_HEADER_SIZE 16 /* size of WAV file header */
1517
Load_WAV(char * filename)1518 static void *Load_WAV(char *filename)
1519 {
1520 SoundInfo *snd_info;
1521 #if defined(AUDIO_UNIX_NATIVE)
1522 struct SoundHeader_WAV header;
1523 #if 0
1524 byte sound_header_buffer[WAV_HEADER_SIZE];
1525 int i;
1526 #endif
1527 char chunk_name[CHUNK_ID_LEN + 1];
1528 int chunk_size;
1529 int data_byte_len;
1530 FILE *file;
1531 #endif
1532
1533 if (!audio.sound_available)
1534 return NULL;
1535
1536 snd_info = checked_calloc(sizeof(SoundInfo));
1537
1538 #if defined(TARGET_SDL)
1539
1540 if ((snd_info->data_ptr = Mix_LoadWAV(filename)) == NULL)
1541 {
1542 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1543 free(snd_info);
1544 return NULL;
1545 }
1546
1547 snd_info->data_len = ((Mix_Chunk *)snd_info->data_ptr)->alen;
1548
1549 #elif defined(TARGET_ALLEGRO)
1550
1551 if ((snd_info->data_ptr = load_sample(filename)) == NULL)
1552 {
1553 Error(ERR_WARN, "cannot read sound file '%s'", filename);
1554 free(snd_info);
1555 return NULL;
1556 }
1557
1558 snd_info->data_len = ((SAMPLE *)snd_info->data_ptr)->len;
1559
1560 #else /* AUDIO_UNIX_NATIVE */
1561
1562 clear_mem(&header, sizeof(struct SoundHeader_WAV)); /* to make gcc happy */
1563
1564 if ((file = fopen(filename, MODE_READ)) == NULL)
1565 {
1566 Error(ERR_WARN, "cannot open sound file '%s'", filename);
1567 free(snd_info);
1568 return NULL;
1569 }
1570
1571 /* read chunk id "RIFF" */
1572 getFileChunkLE(file, chunk_name, &chunk_size);
1573 if (!strEqual(chunk_name, "RIFF"))
1574 {
1575 Error(ERR_WARN, "missing 'RIFF' chunk of sound file '%s'", filename);
1576 fclose(file);
1577 free(snd_info);
1578 return NULL;
1579 }
1580
1581 /* read "RIFF" type id "WAVE" */
1582 getFileChunkLE(file, chunk_name, NULL);
1583 if (!strEqual(chunk_name, "WAVE"))
1584 {
1585 Error(ERR_WARN, "missing 'WAVE' type ID of sound file '%s'", filename);
1586 fclose(file);
1587 free(snd_info);
1588 return NULL;
1589 }
1590
1591 while (getFileChunkLE(file, chunk_name, &chunk_size))
1592 {
1593 if (strEqual(chunk_name, "fmt "))
1594 {
1595 if (chunk_size < WAV_HEADER_SIZE)
1596 {
1597 Error(ERR_WARN, "sound file '%s': chunk 'fmt ' too short", filename);
1598 fclose(file);
1599 free(snd_info);
1600 return NULL;
1601 }
1602
1603 header.compression_code = getFile16BitLE(file);
1604 header.num_channels = getFile16BitLE(file);
1605 header.sample_rate = getFile32BitLE(file);
1606 header.bytes_per_second = getFile32BitLE(file);
1607 header.block_align = getFile16BitLE(file);
1608 header.bits_per_sample = getFile16BitLE(file);
1609
1610 if (chunk_size > WAV_HEADER_SIZE)
1611 ReadUnusedBytesFromFile(file, chunk_size - WAV_HEADER_SIZE);
1612
1613 if (header.compression_code != 1)
1614 {
1615 Error(ERR_WARN, "sound file '%s': compression code %d not supported",
1616 filename, header.compression_code);
1617 fclose(file);
1618 free(snd_info);
1619 return NULL;
1620 }
1621
1622 if (header.num_channels != 1 &&
1623 header.num_channels != 2)
1624 {
1625 Error(ERR_WARN, "sound file '%s': number of %d channels not supported",
1626 filename, header.num_channels);
1627 fclose(file);
1628 free(snd_info);
1629 return NULL;
1630 }
1631
1632 if (header.bits_per_sample != 8 &&
1633 header.bits_per_sample != 16)
1634 {
1635 Error(ERR_WARN, "sound file '%s': %d bits per sample not supported",
1636 filename, header.bits_per_sample);
1637 fclose(file);
1638 free(snd_info);
1639 return NULL;
1640 }
1641
1642 /* warn, but accept wrong sample rate (may be only slightly different) */
1643 if (header.sample_rate != DEFAULT_AUDIO_SAMPLE_RATE)
1644 Error(ERR_WARN, "sound file '%s': wrong sample rate %d instead of %d",
1645 filename, header.sample_rate, DEFAULT_AUDIO_SAMPLE_RATE);
1646
1647 #if 0
1648 printf("WAV file: '%s'\n", filename);
1649 printf(" Compression code: %d'\n", header.compression_code);
1650 printf(" Number of channels: %d'\n", header.num_channels);
1651 printf(" Sample rate: %ld'\n", header.sample_rate);
1652 printf(" Average bytes per second: %ld'\n", header.bytes_per_second);
1653 printf(" Block align: %d'\n", header.block_align);
1654 printf(" Significant bits per sample: %d'\n", header.bits_per_sample);
1655 #endif
1656 }
1657 else if (strEqual(chunk_name, "data"))
1658 {
1659 data_byte_len = chunk_size;
1660
1661 snd_info->data_len = data_byte_len;
1662 snd_info->data_ptr = checked_malloc(snd_info->data_len);
1663
1664 /* read sound data */
1665 if (fread(snd_info->data_ptr, 1, snd_info->data_len, file) !=
1666 snd_info->data_len)
1667 {
1668 Error(ERR_WARN,"cannot read 'data' chunk of sound file '%s'",filename);
1669 fclose(file);
1670 free(snd_info->data_ptr);
1671 free(snd_info);
1672 return NULL;
1673 }
1674
1675 /* check for odd number of data bytes (data chunk is word aligned) */
1676 if ((data_byte_len % 2) == 1)
1677 ReadUnusedBytesFromFile(file, 1);
1678 }
1679 else /* unknown chunk -- ignore */
1680 ReadUnusedBytesFromFile(file, chunk_size);
1681 }
1682
1683 fclose(file);
1684
1685 if (snd_info->data_ptr == NULL)
1686 {
1687 Error(ERR_WARN, "missing 'data' chunk of sound file '%s'", filename);
1688 free(snd_info);
1689 return NULL;
1690 }
1691
1692 if (header.bits_per_sample == 8)
1693 snd_info->format = AUDIO_FORMAT_U8;
1694 else /* header.bits_per_sample == 16 */
1695 {
1696 snd_info->format = AUDIO_FORMAT_S16;
1697 snd_info->data_len /= 2; /* correct number of samples */
1698 }
1699
1700 snd_info->num_channels = header.num_channels;
1701 if (header.num_channels == 2)
1702 snd_info->data_len /= 2; /* correct number of samples */
1703
1704 #if 0
1705 if (header.num_channels == 1) /* convert mono sound to stereo */
1706 {
1707 void *buffer_ptr = checked_malloc(data_byte_len * 2);
1708 void *sample_ptr = snd_info->data_ptr;
1709 int sample_size = snd_info->data_len;
1710 int i;
1711
1712 if (snd_ctrl->format == AUDIO_FORMAT_U8)
1713 for (i = 0; i < sample_size; i++)
1714 *buffer_ptr++ =
1715 ((short)(((byte *)sample_ptr)[i] ^ 0x80)) << 8;
1716 else /* AUDIO_FORMAT_S16 */
1717 for (i = 0; i < sample_size; i++)
1718 *buffer_ptr++ =
1719 ((short *)sample_ptr)[i];
1720 }
1721 #endif
1722
1723 #endif /* AUDIO_UNIX_NATIVE */
1724
1725 snd_info->type = SND_TYPE_WAV;
1726 snd_info->source_filename = getStringCopy(filename);
1727
1728 return snd_info;
1729 }
1730
Load_MOD(char * filename)1731 static void *Load_MOD(char *filename)
1732 {
1733 #if defined(TARGET_SDL)
1734 MusicInfo *mod_info;
1735
1736 if (!audio.sound_available)
1737 return NULL;
1738
1739 mod_info = checked_calloc(sizeof(MusicInfo));
1740
1741 if ((mod_info->data_ptr = Mix_LoadMUS(filename)) == NULL)
1742 {
1743 Error(ERR_WARN, "cannot read music file '%s'", filename);
1744 free(mod_info);
1745 return NULL;
1746 }
1747
1748 mod_info->type = MUS_TYPE_MOD;
1749 mod_info->source_filename = getStringCopy(filename);
1750
1751 return mod_info;
1752 #else
1753 return NULL;
1754 #endif
1755 }
1756
Load_WAV_or_MOD(char * filename)1757 static void *Load_WAV_or_MOD(char *filename)
1758 {
1759 if (FileIsSound(filename))
1760 return Load_WAV(filename);
1761 else if (FileIsMusic(filename))
1762 return Load_MOD(filename);
1763 else
1764 return NULL;
1765 }
1766
LoadCustomMusic_NoConf(void)1767 void LoadCustomMusic_NoConf(void)
1768 {
1769 static boolean draw_init_text = TRUE; /* only draw at startup */
1770 static char *last_music_directory = NULL;
1771 char *music_directory = getCustomMusicDirectory();
1772 DIR *dir;
1773 struct dirent *dir_entry;
1774 int num_music = getMusicListSize();
1775
1776 if (!audio.sound_available)
1777 return;
1778
1779 if (last_music_directory != NULL &&
1780 strEqual(last_music_directory, music_directory))
1781 return; /* old and new music directory are the same */
1782
1783 if (last_music_directory != NULL)
1784 free(last_music_directory);
1785 last_music_directory = getStringCopy(music_directory);
1786
1787 FreeAllMusic_NoConf();
1788
1789 if ((dir = opendir(music_directory)) == NULL)
1790 {
1791 Error(ERR_WARN, "cannot read music directory '%s'", music_directory);
1792 audio.music_available = FALSE;
1793 return;
1794 }
1795
1796 if (draw_init_text)
1797 DrawInitText("Loading music", 120, FC_GREEN);
1798
1799 while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */
1800 {
1801 char *basename = dir_entry->d_name;
1802 char *filename = NULL;
1803 MusicInfo *mus_info = NULL;
1804 boolean music_already_used = FALSE;
1805 int i;
1806
1807 /* skip all music files that are configured in music config file */
1808 for (i = 0; i < num_music; i++)
1809 {
1810 struct FileInfo *music = getMusicListEntry(i);
1811
1812 if (strEqual(basename, music->filename))
1813 {
1814 music_already_used = TRUE;
1815 break;
1816 }
1817 }
1818
1819 if (music_already_used)
1820 continue;
1821
1822 if (draw_init_text)
1823 DrawInitText(basename, 150, FC_YELLOW);
1824
1825 filename = getPath2(music_directory, basename);
1826
1827 if (FileIsMusic(basename))
1828 mus_info = Load_WAV_or_MOD(filename);
1829
1830 free(filename);
1831
1832 if (mus_info)
1833 {
1834 num_music_noconf++;
1835 Music_NoConf = checked_realloc(Music_NoConf,
1836 num_music_noconf * sizeof(MusicInfo *));
1837 Music_NoConf[num_music_noconf - 1] = mus_info;
1838 }
1839 }
1840
1841 closedir(dir);
1842
1843 draw_init_text = FALSE;
1844 }
1845
getSoundListSize()1846 int getSoundListSize()
1847 {
1848 return (sound_info->num_file_list_entries +
1849 sound_info->num_dynamic_file_list_entries);
1850 }
1851
getMusicListSize()1852 int getMusicListSize()
1853 {
1854 return (music_info->num_file_list_entries +
1855 music_info->num_dynamic_file_list_entries);
1856 }
1857
getSoundListEntry(int pos)1858 struct FileInfo *getSoundListEntry(int pos)
1859 {
1860 int num_list_entries = sound_info->num_file_list_entries;
1861 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1862
1863 return (pos < num_list_entries ? &sound_info->file_list[list_pos] :
1864 &sound_info->dynamic_file_list[list_pos]);
1865 }
1866
getMusicListEntry(int pos)1867 struct FileInfo *getMusicListEntry(int pos)
1868 {
1869 int num_list_entries = music_info->num_file_list_entries;
1870 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1871
1872 return (pos < num_list_entries ? &music_info->file_list[list_pos] :
1873 &music_info->dynamic_file_list[list_pos]);
1874 }
1875
getSoundInfoEntryFromSoundID(int pos)1876 static SoundInfo *getSoundInfoEntryFromSoundID(int pos)
1877 {
1878 int num_list_entries = sound_info->num_file_list_entries;
1879 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1880 SoundInfo **snd_info =
1881 (SoundInfo **)(pos < num_list_entries ? sound_info->artwork_list :
1882 sound_info->dynamic_artwork_list);
1883
1884 return snd_info[list_pos];
1885 }
1886
getMusicInfoEntryFromMusicID(int pos)1887 static MusicInfo *getMusicInfoEntryFromMusicID(int pos)
1888 {
1889 int num_list_entries = music_info->num_file_list_entries;
1890 int list_pos = (pos < num_list_entries ? pos : pos - num_list_entries);
1891 MusicInfo **mus_info =
1892 (MusicInfo **)(pos < num_list_entries ? music_info->artwork_list :
1893 music_info->dynamic_artwork_list);
1894
1895 return mus_info[list_pos];
1896 }
1897
getSoundListPropertyMappingSize()1898 int getSoundListPropertyMappingSize()
1899 {
1900 return sound_info->num_property_mapping_entries;
1901 }
1902
getMusicListPropertyMappingSize()1903 int getMusicListPropertyMappingSize()
1904 {
1905 return music_info->num_property_mapping_entries;
1906 }
1907
getSoundListPropertyMapping()1908 struct PropertyMapping *getSoundListPropertyMapping()
1909 {
1910 return sound_info->property_mapping;
1911 }
1912
getMusicListPropertyMapping()1913 struct PropertyMapping *getMusicListPropertyMapping()
1914 {
1915 return music_info->property_mapping;
1916 }
1917
InitSoundList(struct ConfigInfo * config_list,int num_file_list_entries,struct ConfigTypeInfo * config_suffix_list,char ** base_prefixes,char ** ext1_suffixes,char ** ext2_suffixes,char ** ext3_suffixes,char ** ignore_tokens)1918 void InitSoundList(struct ConfigInfo *config_list, int num_file_list_entries,
1919 struct ConfigTypeInfo *config_suffix_list,
1920 char **base_prefixes, char **ext1_suffixes,
1921 char **ext2_suffixes, char **ext3_suffixes,
1922 char **ignore_tokens)
1923 {
1924 int i;
1925
1926 sound_info = checked_calloc(sizeof(struct ArtworkListInfo));
1927 sound_info->type = ARTWORK_TYPE_SOUNDS;
1928
1929 /* ---------- initialize file list and suffix lists ---------- */
1930
1931 sound_info->num_file_list_entries = num_file_list_entries;
1932 sound_info->num_dynamic_file_list_entries = 0;
1933
1934 sound_info->file_list =
1935 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
1936 num_file_list_entries);
1937 sound_info->dynamic_file_list = NULL;
1938
1939 sound_info->num_suffix_list_entries = 0;
1940 for (i = 0; config_suffix_list[i].token != NULL; i++)
1941 sound_info->num_suffix_list_entries++;
1942
1943 sound_info->suffix_list = config_suffix_list;
1944
1945 /* ---------- initialize base prefix and suffixes lists ---------- */
1946
1947 sound_info->num_base_prefixes = 0;
1948 for (i = 0; base_prefixes[i] != NULL; i++)
1949 sound_info->num_base_prefixes++;
1950
1951 sound_info->num_ext1_suffixes = 0;
1952 for (i = 0; ext1_suffixes[i] != NULL; i++)
1953 sound_info->num_ext1_suffixes++;
1954
1955 sound_info->num_ext2_suffixes = 0;
1956 for (i = 0; ext2_suffixes[i] != NULL; i++)
1957 sound_info->num_ext2_suffixes++;
1958
1959 sound_info->num_ext3_suffixes = 0;
1960 for (i = 0; ext3_suffixes[i] != NULL; i++)
1961 sound_info->num_ext3_suffixes++;
1962
1963 sound_info->num_ignore_tokens = 0;
1964 for (i = 0; ignore_tokens[i] != NULL; i++)
1965 sound_info->num_ignore_tokens++;
1966
1967 sound_info->base_prefixes = base_prefixes;
1968 sound_info->ext1_suffixes = ext1_suffixes;
1969 sound_info->ext2_suffixes = ext2_suffixes;
1970 sound_info->ext3_suffixes = ext3_suffixes;
1971 sound_info->ignore_tokens = ignore_tokens;
1972
1973 sound_info->num_property_mapping_entries = 0;
1974
1975 sound_info->property_mapping = NULL;
1976
1977 /* ---------- initialize artwork reference and content lists ---------- */
1978
1979 sound_info->sizeof_artwork_list_entry = sizeof(SoundInfo *);
1980
1981 sound_info->artwork_list =
1982 checked_calloc(num_file_list_entries * sizeof(SoundInfo *));
1983 sound_info->dynamic_artwork_list = NULL;
1984
1985 sound_info->content_list = NULL;
1986
1987 /* ---------- initialize artwork loading/freeing functions ---------- */
1988
1989 sound_info->load_artwork = Load_WAV;
1990 sound_info->free_artwork = FreeSound;
1991 }
1992
InitMusicList(struct ConfigInfo * config_list,int num_file_list_entries,struct ConfigTypeInfo * config_suffix_list,char ** base_prefixes,char ** ext1_suffixes,char ** ext2_suffixes,char ** ext3_suffixes,char ** ignore_tokens)1993 void InitMusicList(struct ConfigInfo *config_list, int num_file_list_entries,
1994 struct ConfigTypeInfo *config_suffix_list,
1995 char **base_prefixes, char **ext1_suffixes,
1996 char **ext2_suffixes, char **ext3_suffixes,
1997 char **ignore_tokens)
1998 {
1999 int i;
2000
2001 music_info = checked_calloc(sizeof(struct ArtworkListInfo));
2002 music_info->type = ARTWORK_TYPE_MUSIC;
2003
2004 /* ---------- initialize file list and suffix lists ---------- */
2005
2006 music_info->num_file_list_entries = num_file_list_entries;
2007 music_info->num_dynamic_file_list_entries = 0;
2008
2009 music_info->file_list =
2010 getFileListFromConfigList(config_list, config_suffix_list, ignore_tokens,
2011 num_file_list_entries);
2012 music_info->dynamic_file_list = NULL;
2013
2014 music_info->num_suffix_list_entries = 0;
2015 for (i = 0; config_suffix_list[i].token != NULL; i++)
2016 music_info->num_suffix_list_entries++;
2017
2018 music_info->suffix_list = config_suffix_list;
2019
2020 /* ---------- initialize base prefix and suffixes lists ---------- */
2021
2022 music_info->num_base_prefixes = 0;
2023 for (i = 0; base_prefixes[i] != NULL; i++)
2024 music_info->num_base_prefixes++;
2025
2026 music_info->num_ext1_suffixes = 0;
2027 for (i = 0; ext1_suffixes[i] != NULL; i++)
2028 music_info->num_ext1_suffixes++;
2029
2030 music_info->num_ext2_suffixes = 0;
2031 for (i = 0; ext2_suffixes[i] != NULL; i++)
2032 music_info->num_ext2_suffixes++;
2033
2034 music_info->num_ext3_suffixes = 0;
2035 for (i = 0; ext3_suffixes[i] != NULL; i++)
2036 music_info->num_ext3_suffixes++;
2037
2038 music_info->num_ignore_tokens = 0;
2039 for (i = 0; ignore_tokens[i] != NULL; i++)
2040 music_info->num_ignore_tokens++;
2041
2042 music_info->base_prefixes = base_prefixes;
2043 music_info->ext1_suffixes = ext1_suffixes;
2044 music_info->ext2_suffixes = ext2_suffixes;
2045 music_info->ext3_suffixes = ext3_suffixes;
2046 music_info->ignore_tokens = ignore_tokens;
2047
2048 music_info->num_property_mapping_entries = 0;
2049
2050 music_info->property_mapping = NULL;
2051
2052 /* ---------- initialize artwork reference and content lists ---------- */
2053
2054 music_info->sizeof_artwork_list_entry = sizeof(MusicInfo *);
2055
2056 music_info->artwork_list =
2057 checked_calloc(num_file_list_entries * sizeof(MusicInfo *));
2058 music_info->dynamic_artwork_list = NULL;
2059
2060 music_info->content_list = NULL;
2061
2062 /* ---------- initialize artwork loading/freeing functions ---------- */
2063
2064 music_info->load_artwork = Load_WAV_or_MOD;
2065 music_info->free_artwork = FreeMusic;
2066 }
2067
PlayMusic(int nr)2068 void PlayMusic(int nr)
2069 {
2070 if (!audio.music_available)
2071 return;
2072
2073 PlaySoundMusic(nr);
2074 }
2075
PlaySound(int nr)2076 void PlaySound(int nr)
2077 {
2078 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_SOUND);
2079 }
2080
PlaySoundStereo(int nr,int stereo_position)2081 void PlaySoundStereo(int nr, int stereo_position)
2082 {
2083 PlaySoundExt(nr, SOUND_MAX_VOLUME, stereo_position, SND_CTRL_PLAY_SOUND);
2084 }
2085
PlaySoundLoop(int nr)2086 void PlaySoundLoop(int nr)
2087 {
2088 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_LOOP);
2089 }
2090
PlaySoundMusic(int nr)2091 void PlaySoundMusic(int nr)
2092 {
2093 PlaySoundExt(nr, SOUND_MAX_VOLUME, SOUND_MIDDLE, SND_CTRL_PLAY_MUSIC);
2094 }
2095
PlaySoundExt(int nr,int volume,int stereo_position,int state)2096 void PlaySoundExt(int nr, int volume, int stereo_position, int state)
2097 {
2098 SoundControl snd_ctrl;
2099
2100 if (!audio.sound_available ||
2101 !audio.sound_enabled ||
2102 audio.sound_deactivated)
2103 return;
2104
2105 if (volume < SOUND_MIN_VOLUME)
2106 volume = SOUND_MIN_VOLUME;
2107 else if (volume > SOUND_MAX_VOLUME)
2108 volume = SOUND_MAX_VOLUME;
2109
2110 if (stereo_position < SOUND_MAX_LEFT)
2111 stereo_position = SOUND_MAX_LEFT;
2112 else if (stereo_position > SOUND_MAX_RIGHT)
2113 stereo_position = SOUND_MAX_RIGHT;
2114
2115 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
2116
2117 snd_ctrl.active = TRUE;
2118 snd_ctrl.nr = nr;
2119 snd_ctrl.volume = volume;
2120 snd_ctrl.stereo_position = stereo_position;
2121 snd_ctrl.state = state;
2122
2123 HandleSoundRequest(snd_ctrl);
2124 }
2125
FadeMusic(void)2126 void FadeMusic(void)
2127 {
2128 if (!audio.music_available)
2129 return;
2130
2131 StopSoundExt(-1, SND_CTRL_FADE_MUSIC);
2132 }
2133
FadeSound(int nr)2134 void FadeSound(int nr)
2135 {
2136 StopSoundExt(nr, SND_CTRL_FADE_SOUND);
2137 }
2138
FadeSounds()2139 void FadeSounds()
2140 {
2141 StopSoundExt(-1, SND_CTRL_FADE_ALL);
2142 }
2143
FadeSoundsAndMusic()2144 void FadeSoundsAndMusic()
2145 {
2146 FadeSounds();
2147 FadeMusic();
2148 }
2149
StopMusic(void)2150 void StopMusic(void)
2151 {
2152 if (!audio.music_available)
2153 return;
2154
2155 StopSoundExt(-1, SND_CTRL_STOP_MUSIC);
2156 }
2157
StopSound(int nr)2158 void StopSound(int nr)
2159 {
2160 StopSoundExt(nr, SND_CTRL_STOP_SOUND);
2161 }
2162
StopSounds()2163 void StopSounds()
2164 {
2165 StopMusic();
2166 StopSoundExt(-1, SND_CTRL_STOP_ALL);
2167 }
2168
StopSoundExt(int nr,int state)2169 void StopSoundExt(int nr, int state)
2170 {
2171 SoundControl snd_ctrl;
2172
2173 if (!audio.sound_available)
2174 return;
2175
2176 clear_mem(&snd_ctrl, sizeof(SoundControl)); /* to make valgrind happy */
2177
2178 snd_ctrl.active = FALSE;
2179 snd_ctrl.nr = nr;
2180 snd_ctrl.state = state;
2181
2182 HandleSoundRequest(snd_ctrl);
2183 }
2184
ReloadCustomSounds()2185 static void ReloadCustomSounds()
2186 {
2187 #if 0
2188 printf("::: reloading sounds '%s' ...\n", artwork.snd_current_identifier);
2189 #endif
2190
2191 LoadArtworkConfig(sound_info);
2192 ReloadCustomArtworkList(sound_info);
2193 }
2194
ReloadCustomMusic()2195 static void ReloadCustomMusic()
2196 {
2197 #if 0
2198 printf("::: reloading music '%s' ...\n", artwork.mus_current_identifier);
2199 #endif
2200
2201 LoadArtworkConfig(music_info);
2202 ReloadCustomArtworkList(music_info);
2203
2204 /* load all music files from directory not defined in "musicinfo.conf" */
2205 LoadCustomMusic_NoConf();
2206 }
2207
InitReloadCustomSounds(char * set_identifier)2208 void InitReloadCustomSounds(char *set_identifier)
2209 {
2210 if (!audio.sound_available)
2211 return;
2212
2213 #if defined(AUDIO_UNIX_NATIVE)
2214 LoadArtworkConfig(sound_info); /* also load config on sound client */
2215 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_SOUNDS);
2216 #else
2217 ReloadCustomSounds();
2218 #endif
2219 }
2220
InitReloadCustomMusic(char * set_identifier)2221 void InitReloadCustomMusic(char *set_identifier)
2222 {
2223 if (!audio.music_available)
2224 return;
2225
2226 #if defined(AUDIO_UNIX_NATIVE)
2227 LoadArtworkConfig(music_info); /* also load config on sound client */
2228 WriteReloadInfoToPipe(set_identifier, SND_CTRL_RELOAD_MUSIC);
2229 #else
2230 ReloadCustomMusic();
2231 #endif
2232 }
2233
FreeSound(void * ptr)2234 void FreeSound(void *ptr)
2235 {
2236 SoundInfo *sound = (SoundInfo *)ptr;
2237
2238 if (sound == NULL)
2239 return;
2240
2241 if (sound->data_ptr)
2242 {
2243 #if defined(TARGET_SDL)
2244 Mix_FreeChunk(sound->data_ptr);
2245 #elif defined(TARGET_ALLEGRO)
2246 destroy_sample(sound->data_ptr);
2247 #else /* AUDIO_UNIX_NATIVE */
2248 free(sound->data_ptr);
2249 #endif
2250 }
2251
2252 checked_free(sound->source_filename);
2253
2254 free(sound);
2255 }
2256
FreeMusic(void * ptr)2257 void FreeMusic(void *ptr)
2258 {
2259 MusicInfo *music = (MusicInfo *)ptr;
2260
2261 if (music == NULL)
2262 return;
2263
2264 if (music->data_ptr)
2265 {
2266 #if defined(TARGET_SDL)
2267 if (music->type == MUS_TYPE_MOD)
2268 Mix_FreeMusic(music->data_ptr);
2269 else
2270 Mix_FreeChunk(music->data_ptr);
2271 #elif defined(TARGET_ALLEGRO)
2272 destroy_sample(music->data_ptr);
2273 #else /* AUDIO_UNIX_NATIVE */
2274 free(music->data_ptr);
2275 #endif
2276 }
2277
2278 free(music);
2279 }
2280
FreeAllMusic_NoConf()2281 static void FreeAllMusic_NoConf()
2282 {
2283 int i;
2284
2285 if (Music_NoConf == NULL)
2286 return;
2287
2288 for (i = 0; i < num_music_noconf; i++)
2289 FreeMusic(Music_NoConf[i]);
2290
2291 free(Music_NoConf);
2292
2293 Music_NoConf = NULL;
2294 num_music_noconf = 0;
2295 }
2296
FreeAllSounds()2297 void FreeAllSounds()
2298 {
2299 FreeCustomArtworkLists(sound_info);
2300 }
2301
FreeAllMusic()2302 void FreeAllMusic()
2303 {
2304 FreeCustomArtworkLists(music_info);
2305 FreeAllMusic_NoConf();
2306 }
2307
2308 /* THE STUFF ABOVE IS ONLY USED BY THE MAIN PROCESS */
2309 /* ========================================================================= */
2310