+ 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();
+ }