X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsound.c;h=d451e6ecf58616a0f5403a815059974bcb917a98;hb=6d37ddaaf9915af0f483f4fc04d07b98e99e091e;hp=00019c6e3e5cc12a1c10e4c3be03ef2c6e692bb2;hpb=1085cba858dc9cccaa5da434ddb990de23fffdfc;p=rocksndiamonds.git diff --git a/src/libgame/sound.c b/src/libgame/sound.c index 00019c6e..d451e6ec 100644 --- a/src/libgame/sound.c +++ b/src/libgame/sound.c @@ -24,6 +24,9 @@ #include "setup.h" +#define IS_PARENT_PROCESS(pid) ((pid) > 0) +#define IS_CHILD_PROCESS(pid) ((pid) == 0) + struct ListNode { char *key; @@ -54,20 +57,13 @@ static struct SoundControl mixer[NUM_MIXER_CHANNELS]; static int mixer_active_channels = 0; /* forward declaration of internal functions */ -static void Mixer_Main(void); -static void Mixer_InsertNewSound(struct SoundControl); static void InitAudioDevice(struct AudioFormatInfo *); +static void Mixer_Main(void); -#if defined(PLATFORM_UNIX) -#if !defined(AUDIO_STREAMING_DSP) +#if defined(PLATFORM_UNIX) && !defined(AUDIO_STREAMING_DSP) static unsigned char linear_to_ulaw(int); static int ulaw_to_linear(unsigned char); #endif -#elif defined(PLATFORM_MSDOS) -static void Mixer_InsertNewSound(struct SoundControl); -static void Mixer_StopSound(struct SoundControl); -static void Mixer_StopAllSounds(); -#endif static void ReloadCustomSounds(); static void ReloadCustomMusic(); @@ -145,15 +141,10 @@ static boolean ForkAudioProcess(void) return FALSE; } - if (audio.mixer_pid == 0) /* we are child process */ - { - Mixer_Main(); - - /* never reached */ - exit(0); - } - else /* we are parent */ - close(audio.mixer_pipe[0]); /* no reading from pipe needed */ + if (IS_CHILD_PROCESS(audio.mixer_pid)) + Mixer_Main(); /* this function never returns */ + else + close(audio.mixer_pipe[0]); /* no reading from pipe needed */ return TRUE; } @@ -182,20 +173,43 @@ void UnixCloseAudio(void) if (audio.device_fd) close(audio.device_fd); - if (audio.mixer_pid > 0) /* we are parent process */ + if (IS_PARENT_PROCESS(audio.mixer_pid)) kill(audio.mixer_pid, SIGTERM); } +static void SendSoundControlToMixerProcess(SoundControl *snd_ctrl) +{ + if (IS_CHILD_PROCESS(audio.mixer_pid)) + return; + + if (write(audio.mixer_pipe[1], snd_ctrl, sizeof(SoundControl)) < 0) + { + Error(ERR_WARN, "cannot pipe to child process -- no sounds"); + audio.sound_available = audio.sound_enabled = FALSE; + return; + } +} + +static void ReadSoundControlFromMainProcess(SoundControl *snd_ctrl) +{ + if (IS_PARENT_PROCESS(audio.mixer_pid)) + return; + + if (read(audio.mixer_pipe[0], snd_ctrl, sizeof(SoundControl)) + != sizeof(SoundControl)) + Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds"); +} + static void WriteReloadInfoToPipe(char *set_name, int type) { - struct SoundControl snd_ctrl; + SoundControl snd_ctrl; TreeInfo *ti = (type == SND_CTRL_RELOAD_SOUNDS ? artwork.snd_current : artwork.mus_current); unsigned long str_size1 = strlen(leveldir_current->fullpath) + 1; unsigned long str_size2 = strlen(ti->basepath) + 1; unsigned long str_size3 = strlen(ti->fullpath) + 1; - if (audio.mixer_pid == 0) /* we are child process */ + if (IS_CHILD_PROCESS(audio.mixer_pid)) return; if (leveldir_current == NULL) /* should never happen */ @@ -232,9 +246,9 @@ static void WriteReloadInfoToPipe(char *set_name, int type) } } -static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl) +static void ReadReloadInfoFromPipe(SoundControl *snd_ctrl) { - TreeInfo **ti_ptr = ((snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) ? + TreeInfo **ti_ptr = ((snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) ? &artwork.snd_current : &artwork.mus_current); TreeInfo *ti = *ti_ptr; unsigned long str_size1, str_size2, str_size3; @@ -243,7 +257,7 @@ static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl) if (set_name) free(set_name); - set_name = checked_malloc(snd_ctrl.data_len); + set_name = checked_malloc(snd_ctrl->data_len); if (leveldir_current == NULL) leveldir_current = checked_calloc(sizeof(TreeInfo)); @@ -257,7 +271,7 @@ static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl) free(ti->fullpath); if (read(audio.mixer_pipe[0], set_name, - snd_ctrl.data_len) != snd_ctrl.data_len || + snd_ctrl->data_len) != snd_ctrl->data_len || read(audio.mixer_pipe[0], leveldir_current, sizeof(TreeInfo)) != sizeof(TreeInfo) || read(audio.mixer_pipe[0], ti, @@ -282,7 +296,7 @@ static void ReadReloadInfoFromPipe(struct SoundControl snd_ctrl) str_size3) != str_size3) Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds"); - if (snd_ctrl.state & SND_CTRL_RELOAD_SOUNDS) + if (snd_ctrl->state & SND_CTRL_RELOAD_SOUNDS) artwork.sounds_set_current = set_name; else artwork.music_set_current = set_name; @@ -298,25 +312,101 @@ void Mixer_InitChannels() mixer_active_channels = 0; } -static void Mixer_FadeSound(int channel) +static void Mixer_PlayChannel(int channel) { - mixer[channel].state |= SND_CTRL_FADE; + /* start with inactive channel in case something goes wrong */ + mixer[channel].active = FALSE; + + if (IS_MUSIC_MODULE(mixer[channel])) + return; + + mixer[channel].playingpos = 0; + mixer[channel].playingtime = 0; + +#if defined(TARGET_SDL) + Mix_Volume(channel, SOUND_MAX_VOLUME); + Mix_PlayChannel(channel, mixer[channel].data_ptr, + IS_LOOP(mixer[channel]) ? -1 : 0); +#elif defined(PLATFORM_MSDOS) + mixer[channel].voice = allocate_voice((SAMPLE *)mixer[channel].data_ptr); + if (mixer[channel].voice < 0) + return; + + if (IS_LOOP(mixer[channel])) + voice_set_playmode(mixer[channel].voice, PLAYMODE_LOOP); + + voice_set_volume(mixer[channel].voice, mixer[channel].volume); + voice_set_pan(mixer[channel].voice, mixer[channel].stereo); + voice_start(mixer[channel].voice); +#endif + + mixer[channel].active = TRUE; + mixer_active_channels++; +} + +static void Mixer_PlayMusicChannel() +{ + Mixer_PlayChannel(audio.music_channel); + +#if defined(TARGET_SDL) + if (IS_MUSIC_MODULE(mixer[audio.music_channel])) + { + /* Mix_VolumeMusic() must be called _after_ Mix_PlayMusic() -- + this looks like a bug in the SDL_mixer library */ + Mix_PlayMusic(mixer[audio.music_channel].data_ptr, -1); + Mix_VolumeMusic(SOUND_MAX_VOLUME); + } +#endif } -static void Mixer_RemoveSound(int channel) +static void Mixer_StopChannel(int channel) { if (!mixer_active_channels || !mixer[channel].active) return; -#if 0 - printf("REMOVING MIXER SOUND %d\n", channel); +#if defined(TARGET_SDL) + Mix_HaltChannel(channel); +#elif defined(PLATFORM_MSDOS) + voice_set_volume(mixer[channel].voice, 0); + deallocate_voice(mixer[channel].voice); #endif mixer[channel].active = FALSE; mixer_active_channels--; } -static void Mixer_InsertSound(struct SoundControl snd_ctrl) +static void Mixer_StopMusicChannel() +{ + Mixer_StopChannel(audio.music_channel); + +#if defined(TARGET_SDL) + Mix_HaltMusic(); +#endif +} + +static void Mixer_FadeChannel(int channel) +{ + mixer[channel].state |= SND_CTRL_FADE; + +#if defined(TARGET_SDL) + Mix_FadeOutChannel(channel, SOUND_FADING_INTERVAL); +#elif defined(PLATFORM_MSDOS) + if (voice_check(mixer[channel].voice)) + voice_ramp_volume(mixer[channel].voice, SOUND_FADING_INTERVAL, 0); + mixer[channel].state &= ~SND_CTRL_IS_LOOP; +#endif +} + +static void Mixer_FadeMusicChannel() +{ + Mixer_FadeChannel(audio.music_channel); + +#if defined(TARGET_SDL) + Mix_FadeOutMusic(SOUND_FADING_INTERVAL); +#endif +} + +static void Mixer_InsertSound(SoundControl snd_ctrl) { SoundInfo *snd_info; int i, k; @@ -332,10 +422,19 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl) snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]); if (snd_info == NULL) + return; + + /* copy sound sample and format information */ + snd_ctrl.data_ptr = snd_info->data_ptr; + snd_ctrl.data_len = snd_info->data_len; + snd_ctrl.format = snd_info->format; + + if (IS_MUSIC(snd_ctrl)) { -#if 0 - printf("sound/music %d undefined\n", snd_ctrl.nr); -#endif + mixer[audio.music_channel] = snd_ctrl; + + Mixer_PlayChannel(audio.music_channel); + return; } @@ -353,7 +452,7 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl) printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i); #endif - Mixer_RemoveSound(i); + Mixer_StopChannel(i); } } } @@ -377,11 +476,8 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl) longest_nr = i; } } -#if defined(PLATFORM_MSDOS) - voice_set_volume(mixer[longest_nr].voice, 0); - deallocate_voice(mixer[longest_nr].voice); -#endif - Mixer_RemoveSound(longest_nr); + + Mixer_StopChannel(longest_nr); } /* check if sound is already being played (and how often) */ @@ -434,11 +530,7 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl) } } -#if defined(PLATFORM_MSDOS) - voice_set_volume(mixer[longest_nr].voice, 0); - deallocate_voice(mixer[longest_nr].voice); -#endif - Mixer_RemoveSound(longest_nr); + Mixer_StopChannel(longest_nr); } /* add new sound to mixer */ @@ -455,12 +547,9 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl) if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) || (i != audio.music_channel && !mixer[i].active)) { - snd_ctrl.data_ptr = snd_info->data_ptr; - snd_ctrl.data_len = snd_info->data_len; - snd_ctrl.format = snd_info->format; - - snd_ctrl.playingpos = 0; - snd_ctrl.playingtime = 0; +#if 0 + printf("ADDING NEW SOUND %d TO MIXER\n", snd_ctrl.nr); +#endif #if 1 if (snd_info->data_len == 0) @@ -475,40 +564,53 @@ static void Mixer_InsertSound(struct SoundControl snd_ctrl) printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n"); #if 1 - Mixer_RemoveSound(i); + Mixer_StopChannel(i); #endif } #endif - mixer[i] = snd_ctrl; - mixer_active_channels++; - #if 0 - printf("NEW SOUND %d ADDED TO MIXER\n", snd_ctrl.nr); + snd_ctrl.data_ptr = snd_info->data_ptr; + snd_ctrl.data_len = snd_info->data_len; + snd_ctrl.format = snd_info->format; #endif -#if defined(PLATFORM_MSDOS) - mixer[i].voice = allocate_voice((SAMPLE *)mixer[i].data_ptr); + mixer[i] = snd_ctrl; - if (snd_ctrl.loop) - voice_set_playmode(mixer[i].voice, PLAYMODE_LOOP); + Mixer_PlayChannel(i); - voice_set_volume(mixer[i].voice, snd_ctrl.volume); - voice_set_pan(mixer[i].voice, snd_ctrl.stereo); - voice_start(mixer[i].voice); -#endif break; } } } -static void HandleSoundRequest(struct SoundControl snd_ctrl) +static void HandleSoundRequest(SoundControl snd_ctrl) { int i; +#if defined(AUDIO_UNIX_NATIVE) + if (IS_PARENT_PROCESS(audio.mixer_pid)) + { + SendSoundControlToMixerProcess(&snd_ctrl); + return; + } +#elif defined(TARGET_ALLEGRO) + for (i=0; i= mixer[i].data_len) - Mixer_RemoveSound(i); + Mixer_StopChannel(i); for(i=0; i> 8) ^ 0x80; @@ -815,7 +917,7 @@ static int Mixer_Main_SimpleAudio(struct SoundControl snd_ctrl) void Mixer_Main() { - struct SoundControl snd_ctrl; + SoundControl snd_ctrl; fd_set mixer_fdset; close(audio.mixer_pipe[1]); /* no writing into pipe needed */ @@ -837,9 +939,8 @@ void Mixer_Main() select(audio.mixer_pipe[0] + 1, &mixer_fdset, NULL, NULL, NULL); if (!FD_ISSET(audio.mixer_pipe[0], &mixer_fdset)) continue; - if (read(audio.mixer_pipe[0], &snd_ctrl, sizeof(snd_ctrl)) - != sizeof(snd_ctrl)) - Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds"); + + ReadSoundControlFromMainProcess(&snd_ctrl); HandleSoundRequest(snd_ctrl); @@ -890,140 +991,6 @@ void Mixer_Main() } #endif /* PLATFORM_UNIX */ -#if defined(PLATFORM_MSDOS) -static void sound_handler(struct SoundControl snd_ctrl) -{ - int i; - - if (snd_ctrl.fade_sound) - { - if (!mixer_active_channels) - return; - - for (i=0; idata_ptr, (state & SND_CTRL_LOOP ? -1 : 0)); - } -#elif defined(PLATFORM_UNIX) - if (audio.mixer_pid == 0) /* we are child process */ - return; - - if (write(audio.mixer_pipe[1], &snd_ctrl, sizeof(snd_ctrl)) < 0) - { - Error(ERR_WARN, "cannot pipe to child process -- no sounds"); - audio.sound_available = audio.sound_enabled = FALSE; - return; - } -#elif defined(PLATFORM_MSDOS) - sound_handler(snd_ctrl); -#endif + HandleSoundRequest(snd_ctrl); } void FadeMusic(void) @@ -1741,7 +1690,7 @@ void StopSounds() void StopSoundExt(int nr, int state) { - struct SoundControl snd_ctrl; + SoundControl snd_ctrl; if (!audio.sound_available) return; @@ -1750,47 +1699,7 @@ void StopSoundExt(int nr, int state) snd_ctrl.nr = nr; snd_ctrl.state = state; -#if defined(TARGET_SDL) - - if (state & SND_CTRL_FADE) - { - int i; - - /* - for (i=audio.first_sound_channel; i