[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://lists.squeakland.org/pipermail/etoys-dev/attachments/20061203/b19b1393/vm-sound-ALSA.bin


More information about the etoys-dev mailing list