[Etoys] Patch to fix sound delay issue
Yoshiki Ohshima
yoshiki at squeakland.org
Mon Dec 4 15:45:44 EST 2006
Takashi,
The attached vm-sound-ALSA does shorten the delay when I play sound
from PianoKeyboard, but for a longer sound, it doesn't work as
expected. The buffer underrun seems to be happening a lot, and also I
might guess that the index to fill the buffer may be wrong.
Now you have one, try
SampledSound stereoBachFugue play
and see (hear) how it sounds.
-- Yoshiki
Takashi Yamamiya wrote:
>
> [1 <text/plain; ISO-2022-JP (7bit)>]
> Hi Ian, and folks,
>
> I fixed the issue of sound latency in ALSA. I tried minimize the delay
> as well as possible. I have tested it on my Fedora Core with VMWare,
> and A-board.
>
> - Minimum delay size depends on the sound buffer size (periods
> frames in ALSA term).
> - If underrun error happens, the delay is extended longer.
> - If nothing wrong, the delay becomes shorter.
> - sound_AvailableSpace() (#primSoundAvailableBytes) answers always the
> buffer size (periods frames) if the delay is short enough.
>
> Yoshiki, could you test it on B-Board?
>
> Thank you,
> - Takashi
> [2 alsa-fixDelay-tak.diff <text/plain (base64)>]
> Index: platforms/unix/vm-sound-ALSA/sqUnixSoundALSA.c
> ===================================================================
> --- platforms/unix/vm-sound-ALSA/sqUnixSoundALSA.c (revision 1592)
> +++ platforms/unix/vm-sound-ALSA/sqUnixSoundALSA.c (working copy)
> @@ -69,6 +69,7 @@
> static int output_channels= 0;
> static int output_buffer_frames_size= 0;
> static int output_buffer_frames_available= 0;
> +static double max_delay_frames = 0;
>
> static void output_callback(snd_async_handler_t *handler)
> {
> @@ -120,8 +121,9 @@
> snd(pcm_sw_params_set_xfer_align(output_handle, swparams, 1), "sound_Start: snd_pcm_sw_params_set_xfer_align");
> snd(pcm_sw_params(output_handle, swparams), "sound_Start: snd_pcm_sw_params");
>
> - output_buffer_frames_size= frameCount;
> + output_buffer_frames_size= frames;
> output_buffer_frames_available= 1;
> + max_delay_frames = frames * 1.5; /* set initial delay frames */
>
> snd(pcm_nonblock(output_handle, 1), "sound_Start: snd_pcm_nonblock");
> snd(async_add_pcm_handler(&output_handler, output_handle, output_callback, 0), "soundStart: snd_add_pcm_handler");
> @@ -152,17 +154,35 @@
> return 1;
> }
>
> +/* Answers periods frame size, or zero if the delay is over. */
> +
> static sqInt sound_AvailableSpace(void)
> {
> - if (output_handle)
> - {
> - int count = snd_pcm_avail_update(output_handle);
> - if (count >= 0)
> - return count;
> - fprintf(stderr, "sound_AvailableSpace: snd_pcm_avail_update: %s\n", snd_strerror(count));
> - snd_pcm_prepare(output_handle);
> - }
> - return 0;
> + snd_pcm_sframes_t delay; /* distance to playback point (in frames) */
> + snd_pcm_state_t state;
> + sqInt avail = 0;
> +
> + if (!output_handle) return 0;
> +
> + snd_pcm_delay(output_handle, &delay);
> + state = snd_pcm_state (output_handle);
> +
> + /* if underrun causes, max delay is loosened */
> + if (state == SND_PCM_STATE_XRUN) {
> + max_delay_frames = max_delay_frames * 1.5;
> + }
> +
> + /* if the state is not running, new sound is needed bacause nobody can
> + signal the semaphore. */
> + if (delay < max_delay_frames || state != SND_PCM_STATE_RUNNING) {
> + avail = output_buffer_frames_size;
> + double new_delay = max_delay_frames * 0.9995;
> + max_delay_frames = new_delay > output_buffer_frames_size ?
> + new_delay : output_buffer_frames_size;
> + }
> + // fprintf(stderr, "delay=%i, avail=%i, state=%i, delay=%.1fms\n",
> + // (int) delay, avail, state, 1000 * max_delay_frames / 22050);
> + return avail * output_channels * 2; /* bytes */
> }
>
> static sqInt sound_InsertSamplesFromLeadTime(sqInt frameCount, sqInt srcBufPtr, sqInt samplesOfLeadTime) FAIL(frameCount)
> [3 vm-sound-ALSA.gz <application/gzip (base64)>]
>
> [4 <text/plain; us-ascii (7bit)>]
> _______________________________________________
> Etoys mailing list
> Etoys at laptop.org
> http://mailman.laptop.org/mailman/listinfo/etoys
More information about the Etoys
mailing list