i'm doing full-duplex mmapped io on emu8k. the good news is the streams
stay in sync, the bad news is how the processing occurs is not optimal if
one follows the 'schoolbook approach'.

remember the alsa schoolbook:

while (running)
{
  poll();
  available = min (streams->update_available());

  while (available > 0)
  {
    frames = min (streams->mmap_begin (available));
    process (frames);
    streams->mmap_commit (frames);
    available -= frames;
  }
}

but with the emu8k it's better to do:

  ...
  while (available > threshold_frames)
    ...

here's why I think this is necessary. every time poll() returns, 
before process() i print 

    for (int i = 0; i < streams; i++)
      fprintf (_msg::file, "%c %4d / %4d", (i > 0 ? ',' : ' '),
               streams[i]->frames, streams[i]->available);
    fprintf (_msg::file, " dt = %.5f\n", dt);

where 
 'streams[i]->frames' is what mmap_begin returned as the number of 
   contiguous frames, or our period_size if that is smaller,
 'streams[i]->available' is what update_avail returned earlier, and 
 'dt' is the time in seconds since the last return from poll().

with period_size = 512 and the schoolbook code we get:

   512 /  515,  512 /  515 dt = 0.00000 /* first cycle */
     3 /  515,    3 /  515 dt = 0.00000 /* still first cycle, better
                                           ignore ... */

   509 /  512,  509 /  512 dt = 0.01400 /* ... and process() 512 now. */
     3 /  512,    3 /  512 dt = 0.01400

   512 /  512,  512 /  512 dt = 0.01343 

   509 /  512,  509 /  511 dt = 0.00743 
     2 /  512,    2 /  511 dt = 0.00743 

   512 /  513,  512 /  513 dt = 0.01153
     1 /  513,    1 /  513 dt = 0.01153

   509 /  512,  509 /  512 dt = 0.01164
     3 /  512,    3 /  512 dt = 0.01164

   512 /  512,  512 /  512 dt = 0.01161

   509 /  512,  509 /  512 dt = 0.01158
     3 /  512,    3 /  512 dt = 0.01158
etc.

processing a small number of frames can turn out to eat a lot of cpu,
depending on what process() is doing, and how it is doing it. anyway i do
not think it will reduce the chance of xruns.

when i modify the code to break the loop if there are < 5 frames available
the outer loop runs smoothly with 512 frames for every process() call. 

i don't really like putting in an arbitrary number for the threshold
value, or making this a configuration option that most users will
rightly regard as esoteric, but i suspect there is little to do about 
this when you're dealing with junk hardware like the emu8k.

i must add that the same code runs steady as a train with the ice1712,
where period_size == available == frames at every poll() return, so this
hw does not need a threshold_frames != 0 (it doesn't do harm, either). 

tim



_______________________________________________
Alsa-devel mailing list
[EMAIL PROTECTED]
https://lists.sourceforge.net/lists/listinfo/alsa-devel

Reply via email to