- {
- premix_left_buffer[j] =
- (left_volume * premix_first_buffer[j])
- >> PSND_MAX_LEFT2RIGHT_BITS;
- premix_right_buffer[j] =
- (right_volume * premix_first_buffer[j])
- >> PSND_MAX_LEFT2RIGHT_BITS;
-
- premix_last_buffer[2 * j + 0] += premix_left_buffer[j];
- premix_last_buffer[2 * j + 1] += premix_right_buffer[j];
- }
- }
- else
- {
- for(j=0; j<sample_size; j++)
- premix_last_buffer[j] += premix_first_buffer[j];
- }
-
- /* delete completed sound entries from the playlist */
- if (playlist[i].playingpos >= playlist[i].data_len)
- {
- if (IS_LOOP(playlist[i]))
- playlist[i].playingpos = 0;
- else
- PlaylistRemoveSound(i);
- }
- else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
- PlaylistRemoveSound(i);
- }
-
- /* prepare final playing buffer according to system audio format */
- for(i=0; i<max_sample_size * (stereo ? 2 : 1); i++)
- {
- /* cut off at 17 bit value */
- if (premix_last_buffer[i] < -65535)
- premix_last_buffer[i] = -65535;
- else if (premix_last_buffer[i] > 65535)
- premix_last_buffer[i] = 65535;
-
- /* shift to 16 bit value */
- premix_last_buffer[i] >>= 1;
-
- if (afmt.format & AUDIO_FORMAT_U8)
- {
- playing_buffer[i] = (premix_last_buffer[i] >> 8) ^ 0x80;
- }
- else if (afmt.format & AUDIO_FORMAT_LE) /* 16 bit */
- {
- playing_buffer[2 * i + 0] = premix_last_buffer[i] & 0xff;
- playing_buffer[2 * i + 1] = premix_last_buffer[i] >> 8;
- }
- else /* big endian */
- {
- playing_buffer[2 * i + 0] = premix_last_buffer[i] >> 8;
- playing_buffer[2 * i + 1] = premix_last_buffer[i] & 0xff;
- }
- }
-
- /* finally play the sound fragment */
- write(audio.device_fd, playing_buffer, fragment_size);
-
- if (!playing_sounds)
- CloseAudioDevice(&audio.device_fd);
-}
-
-#else /* !AUDIO_STREAMING_DSP */
-
-static int SoundServer_SimpleAudio(struct SoundControl snd_ctrl)
-{
- static short premix_first_buffer[SND_BLOCKSIZE];
- static byte playing_buffer[SND_BLOCKSIZE];
- int max_sample_size = SND_BLOCKSIZE;
- void *sample_ptr;
- int sample_len;
- int sample_pos;
- int sample_size;
- int i, j;
-
- i = 1;
-
- /* pointer, lenght and actual playing position of sound sample */
- sample_ptr = playlist[i].data_ptr;
- sample_len = playlist[i].data_len;
- sample_pos = playlist[i].playingpos;
- sample_size = MIN(max_sample_size, sample_len - sample_pos);
- playlist[i].playingpos += sample_size;
-
- /* copy original sample to first mixing buffer */
- CopySampleToMixingBuffer(&playlist[i], sample_pos, sample_size,
- premix_first_buffer);
-
- /* adjust volume of actual sound sample */
- if (playlist[i].volume != PSND_MAX_VOLUME)
- for(j=0; j<sample_size; j++)
- premix_first_buffer[j] =
- (playlist[i].volume * (long)premix_first_buffer[j])
- >> PSND_MAX_VOLUME_BITS;
-
- /* might be needed for u-law /dev/audio */
-#if 0
- for(j=0; j<sample_size; j++)
- playing_buffer[j] =
- linear_to_ulaw(premix_first_buffer[j]);
-#endif
-
- /* delete completed sound entries from the playlist */
- if (playlist[i].playingpos >= playlist[i].data_len)
- PlaylistRemoveSound(i);
-
- for(i=0; i<sample_size; i++)
- playing_buffer[i] = (premix_first_buffer[i] >> 8) ^ 0x80;
-
- /* finally play the sound fragment */
- write(audio.device_fd, playing_buffer, sample_size);
-
- return sample_size;
-}
-#endif /* !AUDIO_STREAMING_DSP */
-
-void SoundServer()
-{
- struct SoundControl snd_ctrl;
- fd_set sound_fdset;
-
- close(audio.soundserver_pipe[1]); /* no writing into pipe needed */
-
- InitPlaylist();
-
-#if defined(PLATFORM_HPUX)
- InitAudioDevice(&afmt);
-#endif
-
- FD_ZERO(&sound_fdset);
- FD_SET(audio.soundserver_pipe[0], &sound_fdset);
-
- while(1) /* wait for sound playing commands from client */
- {
- struct timeval delay = { 0, 0 };
-
- FD_SET(audio.soundserver_pipe[0], &sound_fdset);
- select(audio.soundserver_pipe[0] + 1, &sound_fdset, NULL, NULL, NULL);
- if (!FD_ISSET(audio.soundserver_pipe[0], &sound_fdset))
- continue;
- if (read(audio.soundserver_pipe[0], &snd_ctrl, sizeof(snd_ctrl))
- != sizeof(snd_ctrl))
- Error(ERR_EXIT_SOUND_SERVER, "broken pipe -- no sounds");
-
- HandleSoundRequest(snd_ctrl);
-
-#if defined(AUDIO_STREAMING_DSP)
-
- while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
- &sound_fdset, NULL, NULL, &delay) < 1)
- {
- FD_SET(audio.soundserver_pipe[0], &sound_fdset);
-
- SoundServer_Mixer();
- }
-
-#else /* !AUDIO_STREAMING_DSP */
-
- if (!snd_ctrl.active || IS_LOOP(snd_ctrl) ||
- (audio.device_fd = OpenAudioDevice(audio.device_name)) < 0)
- continue;
-
- InitAudioDevice(&afmt);
-
- delay.tv_sec = 0;
- delay.tv_usec = 0;
-
- while (playing_sounds && select(audio.soundserver_pipe[0] + 1,
- &sound_fdset, NULL, NULL, &delay) < 1)
- {
- int wait_percent = 90; /* wait 90% of the real playing time */
- int sample_size;
-
- FD_SET(audio.soundserver_pipe[0], &sound_fdset);
-
- sample_size = SoundServer_SimpleAudio(snd_ctrl);
-
- delay.tv_sec = 0;
- delay.tv_usec =
- ((sample_size * 10 * wait_percent) / afmt.sample_rate) * 1000;
- }
-
- CloseAudioDevice(&audio.device_fd);
-
- /* delete all sounds from playlist */
- InitPlaylist();
-
-#endif /* !AUDIO_STREAMING_DSP */
- }
-}
-#endif /* PLATFORM_UNIX */
-
-#if defined(PLATFORM_MSDOS)
-static void sound_handler(struct SoundControl snd_ctrl)
-{
- int i;
-
- if (snd_ctrl.fade_sound)
- {
- if (!playing_sounds)
- return;
-
- for (i=0; i<audio.num_channels; i++)
- if ((snd_ctrl.stop_all_sounds ||
- (i != audio.music_channel && playlist[i].nr == snd_ctrl.nr) ||
- (i == audio.music_channel && snd_ctrl.music)) &&
- !playlist[i].fade_sound)
- {
- playlist[i].fade_sound = TRUE;
- if (voice_check(playlist[i].voice))
- voice_ramp_volume(playlist[i].voice, 1000, 0);
- playlist[i].state &= ~SND_CTRL_IS_LOOP;
- }
- }
- else if (snd_ctrl.stop_all_sounds)
- {
- if (!playing_sounds)
- return;
- SoundServer_StopAllSounds();
- }
- else if (snd_ctrl.stop_sound)
- {
- if (!playing_sounds)
- return;
- SoundServer_StopSound(snd_ctrl);
- }
-
- for (i=0; i<audio.num_channels; i++)
- {
- if (!playlist[i].active || playlist[i].loop)
- continue;
-
- playlist[i].playingpos = voice_get_position(playlist[i].voice);
- playlist[i].volume = voice_get_volume(playlist[i].voice);
- if (playlist[i].playingpos == -1 || !playlist[i].volume)
- {
- deallocate_voice(playlist[i].voice);
- PlaylistRemoveSound(i);
- }
- }
-
- if (snd_ctrl.active)
- SoundServer_InsertNewSound(snd_ctrl);
-}
-#endif /* PLATFORM_MSDOS */
-
-#if 0
-#if defined(TARGET_SDL)
-static void sound_handler_SDL(struct SoundControl snd_ctrl)
-{
- /* copy sound_handler() here ... */
-}
-#endif /* TARGET_SDL */
-#endif
-
-#if !defined(PLATFORM_WIN32)
-static void SoundServer_InsertNewSound(struct SoundControl snd_ctrl)
-{
- SoundInfo *snd_info;
- int i, k;
-
-#if 0
- printf("NEW SOUND %d HAS ARRIVED [%d]\n", snd_ctrl.nr, num_sounds);
-#endif
-
- if (IS_MUSIC(snd_ctrl))
- snd_ctrl.nr = snd_ctrl.nr % num_music;
- else if (snd_ctrl.nr >= num_sounds)
- return;
-
- snd_info = (IS_MUSIC(snd_ctrl) ? Music[snd_ctrl.nr] : Sound[snd_ctrl.nr]);
- if (snd_info == NULL)
- {
-#if 0
- printf("sound/music %d undefined\n", snd_ctrl.nr);
-#endif
- return;
- }
-
-#if 0
- printf("-> %d\n", playing_sounds);
-#endif
-
- if (playing_sounds == audio.num_channels)
- {
- for (i=0; i<audio.num_channels; i++)
- {
- if (playlist[i].data_ptr == NULL)
- {
-#if 1
- printf("THIS SHOULD NEVER HAPPEN! [%d]\n", i);
-#endif
-
- PlaylistRemoveSound(i);
- }
- }
- }
-
- /* if playlist is full, remove oldest sound */
- if (playing_sounds == audio.num_channels)
- {
- int longest = 0, longest_nr = 0;
-
- for (i=audio.first_sound_channel; i<audio.num_channels; i++)
- {
-#if !defined(PLATFORM_MSDOS)
- int actual = 100 * playlist[i].playingpos / playlist[i].data_len;
-#else
- int actual = playlist[i].playingpos;
-#endif
-
- if (!IS_LOOP(playlist[i]) && actual > longest)
- {
- longest = actual;
- longest_nr = i;
- }
- }
-#if defined(PLATFORM_MSDOS)
- voice_set_volume(playlist[longest_nr].voice, 0);
- deallocate_voice(playlist[longest_nr].voice);
-#endif
- PlaylistRemoveSound(longest_nr);
- }
-
- /* check if sound is already being played (and how often) */
- for (k=0, i=audio.first_sound_channel; i<audio.num_channels; i++)
- if (playlist[i].nr == snd_ctrl.nr)
- k++;
-
- /* restart loop sounds only if they are just fading out */
- if (k >= 1 && IS_LOOP(snd_ctrl))
- {
- for(i=audio.first_sound_channel; i<audio.num_channels; i++)
- {
- if (playlist[i].nr == snd_ctrl.nr && IS_FADING(playlist[i]))
- {
- playlist[i].state &= ~SND_CTRL_FADE;
- playlist[i].volume = PSND_MAX_VOLUME;
-#if defined(PLATFORM_MSDOS)
- playlist[i].state |= SND_CTRL_LOOP;
- voice_stop_volumeramp(playlist[i].voice);
- voice_ramp_volume(playlist[i].voice, playlist[i].volume, 1000);
-#endif
- }
- }
-
- return;
- }
-
- /* don't play sound more than n times simultaneously (with n == 2 for now) */
- if (k >= 2)
- {
- int longest = 0, longest_nr = 0;
-
- /* look for oldest equal sound */
- for(i=audio.first_sound_channel; i<audio.num_channels; i++)
- {
- int actual;
-
- if (!playlist[i].active || playlist[i].nr != snd_ctrl.nr)
- continue;
-
-#if !defined(PLATFORM_MSDOS)
- actual = 100 * playlist[i].playingpos / playlist[i].data_len;
-#else
- actual = playlist[i].playingpos;
-#endif
- if (actual >= longest)
- {
- longest = actual;
- longest_nr = i;
- }
- }
-
-#if defined(PLATFORM_MSDOS)
- voice_set_volume(playlist[longest_nr].voice, 0);
- deallocate_voice(playlist[longest_nr].voice);
-#endif
- PlaylistRemoveSound(longest_nr);
- }
-
- /* add new sound to playlist */
- for(i=0; i<audio.num_channels; i++)
- {
-#if 0
- printf("CHECKING CHANNEL %d FOR SOUND %d ...\n", i, snd_ctrl.nr);
-#endif
-
- /*
- if (!playlist[i].active ||
- (IS_MUSIC(snd_ctrl) && i == audio.music_channel))
- */
- if ((i == audio.music_channel && IS_MUSIC(snd_ctrl)) ||
- (i != audio.music_channel && !playlist[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 1
- if (snd_info->data_len == 0)
- {
- printf("THIS SHOULD NEVER HAPPEN! [snd_info->data_len == 0]\n");
- }
-#endif
-
-#if 1
- if (IS_MUSIC(snd_ctrl) && i == audio.music_channel && playlist[i].active)
- {
- printf("THIS SHOULD NEVER HAPPEN! [adding music twice]\n");
-
-#if 1
- PlaylistRemoveSound(i);
-#endif