- struct timeval delay = { 0, 0 };
-
- if (!playing_sounds) /* we just opened the audio device */
- InitAudioDevice_DSP(&afmt);
-
- if (snd_ctrl.active) /* new sound has arrived */
- SoundServer_InsertNewSound(snd_ctrl);
-
- while (playing_sounds &&
- select(audio.soundserver_pipe[0] + 1,
- &sound_fdset, NULL, NULL, &delay) < 1)
- {
- int max_sample_size;
- int fragment_size = afmt.fragment_size;
- int sample_bytes = (afmt.format & AUDIO_FORMAT_U8 ? 1 : 2);
- boolean stereo = afmt.stereo;
-
- FD_SET(audio.soundserver_pipe[0], &sound_fdset);
-
- max_sample_size = fragment_size / ((stereo ? 2 : 1) * sample_bytes);
-
- /* first clear the last premixing buffer */
- memset(premix_last_buffer, 0,
- max_sample_size * (stereo ? 2 : 1) * sizeof(long));
-
- for(i=0; i<MAX_SOUNDS_PLAYING; i++)
- {
- void *sample_ptr;
- int sample_len;
- int sample_pos;
- int sample_size;
- int j;
-
- if (!playlist[i].active)
- continue;
-
- /* 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 */
- if (playlist[i].format == AUDIO_FORMAT_U8)
- for (j=0; j<sample_size; j++)
- premix_first_buffer[j] =
- ((short)(((byte *)sample_ptr)[sample_pos + j] ^ 0x80)) << 8;
- else /* AUDIO_FORMAT_S16 */
- for (j=0; j<sample_size; j++)
- premix_first_buffer[j] =
- ((short *)sample_ptr)[sample_pos + j];
-
- /* are we about to restart a looping sound? */
- if (playlist[i].loop && sample_size < max_sample_size)
- {
- while (sample_size < max_sample_size)
- {
- int restarted_sample_size =
- MIN(max_sample_size - sample_size, sample_len);
-
- if (playlist[i].format == AUDIO_FORMAT_U8)
- for (j=0; j<restarted_sample_size; j++)
- premix_first_buffer[sample_size + j] =
- ((short)(((byte *)sample_ptr)[j] ^ 0x80)) << 8;
- else
- for (j=0; j<restarted_sample_size; j++)
- premix_first_buffer[sample_size + j] =
- ((short *)sample_ptr)[j];
-
- playlist[i].playingpos = restarted_sample_size;
- sample_size += restarted_sample_size;
- }
- }
-
- /* decrease volume if sound is fading out */
- if (playlist[i].fade_sound &&
- playlist[i].volume >= SOUND_FADING_VOLUME_THRESHOLD)
- playlist[i].volume -= SOUND_FADING_VOLUME_STEP;
-
- /* 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;
-
- /* fill the last mixing buffer with stereo or mono sound */
- if (stereo)
- {
- int middle_pos = PSND_MAX_LEFT2RIGHT / 2;
- int left_volume = stereo_volume[middle_pos + playlist[i].stereo];
- int right_volume= stereo_volume[middle_pos - playlist[i].stereo];
-
- for(j=0; j<sample_size; j++)
- {
- 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 (playlist[i].loop)
- playlist[i].playingpos = 0;
- else
- {
- playlist[i] = emptySoundControl;
- playing_sounds--;
- }
- }
- else if (playlist[i].volume <= SOUND_FADING_VOLUME_THRESHOLD)
- {
- playlist[i] = emptySoundControl;
- playing_sounds--;
- }
- }
-
- /* 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 no sounds playing, free device for other sound programs */
- if (!playing_sounds)
- close(audio.device_fd);