[Etoys] Patch to fix sound delay issue
Takashi Yamamiya
tak at metatoys.org
Sun Dec 3 09:30:45 EST 2006
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
-------------- next part --------------
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)
-------------- next part --------------
A non-text attachment was scrubbed...
Name: vm-sound-ALSA.gz
Type: application/gzip
Size: 8041 bytes
Desc: not available
Url : http://mailman.laptop.org/pipermail/etoys/attachments/20061203/b19b1393/vm-sound-ALSA.bin
More information about the Etoys
mailing list