X-Git-Url: https://git.artsoft.org/?a=blobdiff_plain;f=src%2Flibgame%2Fsound.c;h=5f32e98efd131e51cef03f7aeecc6987a2cf7c0b;hb=c4e1a476135ce36417cdd797481feeaaff4301af;hp=a7298a84d811122997367b65cc1bd7637211aec0;hpb=ff56a43aa3799aa3357f4deca4d6482fc25a6a41;p=rocksndiamonds.git diff --git a/src/libgame/sound.c b/src/libgame/sound.c index a7298a84..5f32e98e 100644 --- a/src/libgame/sound.c +++ b/src/libgame/sound.c @@ -11,16 +11,20 @@ * sound.c * ***********************************************************/ +#include #include #include #include +#include +#include "system.h" #include "sound.h" #include "misc.h" -static int num_sounds = 0; +static int num_sounds = 0, num_music = 0, num_mods = 0; static struct SampleInfo *Sound = NULL; +static struct SampleInfo *Mod = NULL; /*** THE STUFF BELOW IS ONLY USED BY THE SOUND SERVER CHILD PROCESS ***/ @@ -81,7 +85,7 @@ int OpenAudioDevice(char *audio_device_name) return audio_fd; } -void UnixOpenAudio(struct AudioSystemInfo *audio) +void UnixOpenAudio(void) { static char *audio_device_name[] = { @@ -104,19 +108,20 @@ void UnixOpenAudio(struct AudioSystemInfo *audio) close(audio_fd); - audio->device_name = audio_device_name[i]; - audio->sound_available = TRUE; - audio->sound_enabled = TRUE; + audio.device_name = audio_device_name[i]; + audio.sound_available = TRUE; + audio.sound_enabled = TRUE; #if defined(AUDIO_STREAMING_DSP) - audio->loops_available = TRUE; + audio.music_available = TRUE; + audio.loops_available = TRUE; #endif } -void UnixCloseAudio(struct AudioSystemInfo *audio) +void UnixCloseAudio(void) { - if (audio->device_fd) - close(audio->device_fd); + if (audio.device_fd) + close(audio.device_fd); } #endif /* PLATFORM_UNIX */ @@ -202,26 +207,34 @@ void SoundServer() byte *sample_ptr; long sample_size; static long max_sample_size = 0; - static long fragment_size = 0; - /* Even if the stereo flag is used as being boolean, it must be - defined as an integer, else 'ioctl()' will fail! */ + static long fragment_size = DEFAULT_AUDIO_FRAGMENT_SIZE; + int sample_rate = DEFAULT_AUDIO_SAMPLE_RATE; int stereo = TRUE; -#if 0 - int sample_rate = 8000; -#else - int sample_rate = 22050; -#endif + /* 'ioctl()' expects pointer to integer value for stereo flag + (boolean is defined as 'char', which will not work here) */ if (playing_sounds || (audio.device_fd = OpenAudioDevice(audio.device_name)) >= 0) { if (!playing_sounds) /* we just opened the audio device */ { - /* 2 buffers / 512 bytes, giving 1/16 second resolution */ - /* (with stereo the effective buffer size will shrink to 256) */ - fragment_size = 0x00020009; + unsigned long fragment_spec = 0; + + /* determine logarithm (log2) of the fragment size */ + for (fragment_spec=0; (1 << fragment_spec) < fragment_size; + fragment_spec++); - if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_size) < 0) + /* use two fragments (play one fragment, prepare the other); + one fragment would result in interrupted audio output, more + than two fragments would raise audio output latency to much */ + fragment_spec |= 0x00020000; + + /* Example for fragment specification: + - 2 buffers / 512 bytes (giving 1/16 second resolution for 8 kHz) + - (with stereo the effective buffer size will shrink to 256) + => fragment_size = 0x00020009 */ + + if (ioctl(audio.device_fd,SNDCTL_DSP_SETFRAGMENT,&fragment_spec) < 0) Error(ERR_EXIT_SOUND_SERVER, "cannot set fragment size of /dev/dsp - no sounds"); @@ -262,7 +275,7 @@ void SoundServer() FD_SET(audio.soundserver_pipe[0], &sound_fdset); /* first clear the last premixing buffer */ - memset(premix_last_buffer,0,fragment_size*sizeof(int)); + memset(premix_last_buffer, 0, fragment_size * sizeof(int)); for(i=0;iname = sound_name; - sprintf(filename, "%s/%s/%s.%s", - options.ro_base_directory, SOUNDS_DIRECTORY, - snd_info->name, sound_ext); + sprintf(filename, "%s/%s/%s", options.ro_base_directory, + (is_music ? MUSIC_DIRECTORY : SOUNDS_DIRECTORY), snd_info->name); #if defined(TARGET_SDL) - snd_info->mix_chunk = Mix_LoadWAV(filename); - if (snd_info->mix_chunk == NULL) + if ((snd_info->mix_chunk = Mix_LoadWAV(filename)) == NULL) { Error(ERR_WARN, "cannot read sound file '%s' - no sounds", filename); return FALSE; } -#else /* !TARGET_SDL */ - -#if !defined(PLATFORM_MSDOS) +#elif defined(PLATFORM_UNIX) - if ((file = fopen(filename, "r")) == NULL) + if ((file = fopen(filename, MODE_READ)) == NULL) { Error(ERR_WARN, "cannot open sound file '%s' - no sounds", filename); return FALSE; @@ -897,12 +901,131 @@ boolean LoadSound(int sound_nr, char *sound_name) return FALSE; } -#endif /* PLATFORM_MSDOS */ -#endif /* !TARGET_SDL */ +#endif return TRUE; } +boolean LoadSound(char *sound_name) +{ + return LoadSoundExt(sound_name, FALSE); +} + +boolean LoadMod(char *mod_name) +{ + struct SampleInfo *mod_info; + char filename[256]; + + num_mods++; + Mod = checked_realloc(Mod, num_mods * sizeof(struct SampleInfo)); + + mod_info = &Mod[num_mods - 1]; + mod_info->name = mod_name; + + sprintf(filename, "%s/%s/%s", options.ro_base_directory, + MUSIC_DIRECTORY, mod_info->name); + +#if defined(TARGET_SDL) + if ((mod_info->mix_music = Mix_LoadMUS(filename)) == NULL) + { + Error(ERR_WARN, "cannot read music file '%s' - no sounds", filename); + return FALSE; + } +#endif + + audio.mods_available = TRUE; + + return TRUE; +} + +int LoadMusic(void) +{ + DIR *dir; + struct dirent *dir_entry; + char *music_directory = getPath2(options.ro_base_directory, MUSIC_DIRECTORY); + + num_music = 0; + + if ((dir = opendir(music_directory)) == NULL) + { + Error(ERR_WARN, "cannot read music directory '%s'", music_directory); + audio.music_available = FALSE; + free(music_directory); + return 0; + } + + while ((dir_entry = readdir(dir)) != NULL) /* loop until last dir entry */ + { + char *filename = dir_entry->d_name; + + if (strlen(filename) > 4 && + strcmp(&filename[strlen(filename) - 4], ".wav") == 0) + { + if (!LoadSoundExt(filename, TRUE)) + { + audio.music_available = FALSE; + free(music_directory); + return num_music; + } + + num_music++; + } + else if (strlen(filename) > 4 && + (strcmp(&filename[strlen(filename) - 4], ".mod") == 0 || + strcmp(&filename[strlen(filename) - 4], ".MOD") == 0 || + strncmp(filename, "mod.", 4) == 0 || + strncmp(filename, "MOD.", 4) == 0)) + { + if (!LoadMod(filename)) + { + audio.music_available = FALSE; + free(music_directory); + return num_music; + } + + num_music++; + } + } + + closedir(dir); + + if (num_music == 0) + Error(ERR_WARN, "cannot find any valid music files in directory '%s'", + music_directory); + + free(music_directory); + + if (num_mods > 0) + num_music = num_mods; + + return num_music; +} + +void PlayMusic(int nr) +{ + if (!audio.music_available) + return; + + if (num_mods == 0) + nr = num_sounds - num_music + nr; + +#if defined(TARGET_SDL) + if (audio.mods_available) + { + Mix_VolumeMusic(SOUND_MAX_VOLUME); + Mix_PlayMusic(Mod[nr].mix_music, -1); + } + else /* play music loop */ + { + Mix_Volume(audio.music_channel, SOUND_MAX_VOLUME); + Mix_PlayChannel(audio.music_channel, Sound[nr].mix_chunk, -1); + } +#else + audio.music_nr = nr; + PlaySoundLoop(nr); +#endif +} + void PlaySound(int nr) { PlaySoundExt(nr, PSND_MAX_VOLUME, PSND_MIDDLE, PSND_NO_LOOP); @@ -944,23 +1067,29 @@ void PlaySoundExt(int nr, int volume, int stereo, boolean loop) snd_ctrl.data_len = Sound[nr].data_len; #if defined(TARGET_SDL) - - Mix_Volume(-1, SDL_MIX_MAXVOLUME / 4); - Mix_VolumeMusic(SDL_MIX_MAXVOLUME / 4); - + Mix_Volume(-1, SOUND_MAX_VOLUME); Mix_PlayChannel(-1, Sound[nr].mix_chunk, (loop ? -1 : 0)); - -#else -#if !defined(PLATFORM_MSDOS) +#elif defined(PLATFORM_UNIX) if (write(audio.soundserver_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; } -#else +#elif defined(PLATFORM_MSDOS) sound_handler(snd_ctrl); #endif +} + +void FadeMusic(void) +{ +#if defined(TARGET_SDL) + if (audio.mods_available) + Mix_FadeOutMusic(SOUND_FADING_INTERVAL); + else + Mix_FadeOutChannel(audio.music_channel, SOUND_FADING_INTERVAL); +#else + FadeSound(audio.music_nr); #endif } @@ -974,6 +1103,18 @@ void FadeSounds() StopSoundExt(-1, SSND_FADE_ALL_SOUNDS); } +void StopMusic(void) +{ +#if defined(TARGET_SDL) + if (audio.mods_available) + Mix_HaltMusic(); + else + Mix_HaltChannel(audio.music_channel); +#else + StopSound(audio.music_nr); +#endif +} + void StopSound(int nr) { StopSoundExt(nr, SSND_STOP_SOUND); @@ -1006,13 +1147,23 @@ void StopSoundExt(int nr, int method) if (SSND_FADING(method)) { - Mix_FadeOutChannel(-1, 1000); - Mix_FadeOutMusic(1000); + int i; + + for (i=0; i