Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Jaroslav Kysela

On Wed, 28 Nov 2001, Jaroslav Kysela wrote:

 On Tue, 27 Nov 2001, Paul Davis wrote:

  enclosed below what happens when using ALSA, mmap mode and poll(2) on my
  trident card at 44100. the value of contiguous is the value returned
  by snd_pcm_mmap_begin() having been passed a value of 2048 as the
  upper limit.  the period size is 2048 frames, the buffer size is 2 *
  period size. the figures shown are for the capture stream; both
  capture and playback are open at the same time and are both in active use.
 
  needless to say, this is basically unworkable as is. any suggestions
  as to why this happening? it happens much, much less frequently at
  48kHz, and almost never on the Hammerfall. i tried it on the
  (admittedly known to be broken) tropez+ and it crashed my machine :)
 
  is this an application design problem, or an alsa low level driver
  implementation problem (i.e. with the hw pointer routines?)

 Can you send me output from 'snd_pcm_dump()', too? It might be caused by
 a wrong sw_params settings.

I looked to this problem. The default sw_params should be ok - they set
avail_min and xfer_align to period_size. The question is, if the direct
access function - snd_pcm_mmap_begin - should take care about these
values. Also, it would be problematic to include the test for
non-continous transfers. The right loop, based on the period_size
transfers, should be like this:

poll();
if ((pfd-revents  POLLIN) {
while (1) {
if (snd_pcm_avail_update(pcm)  period_size)
break;
count = period_size;
// transfer whole period (can be composed from more
// non-continuous parts)
while (avail  0) {
frames = count;
snd_pcm_mmap_begin(pcm, areas, offset, frames);

snd_pcm_mmap_commit(pcm, offset, frames);
count -= frames;
}
}
}

Jaroslav

-
Jaroslav Kysela [EMAIL PROTECTED]
SuSE Linuxhttp://www.suse.com
ALSA Project  http://www.alsa-project.org


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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Paul Davis

 count = (avail / period_size) * period_size;

   count = avail - avail % period_size;

is more efficient (at least on i386 and gcc).

thanks for reminding me. alas, there is still a problem. could it just
be a device-specific issue? its as if the snd_pcm_mmap_commit doesn't
work on the playback stream on the trident ...

source:
---

http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/~checkout~/jackit/jack/alsa_driver.c?rev=1.5content-type=text/plain

params:
---
period_size = 64;
buffer_size = 2 * period_size;

`hw_avail' = values reported by snd_pcm_avail_update() on return from poll(2)
   for each stream

`this_time' = the minimum of the two hw_avail values, processed via
the mod expression above

`contiguous' = smaller of the values returned by snd_pcm_mmap_begin()
  for the two streams, having been passed `this_time'
  as an upper limit

   this is the number passed to snd_pcm_mmap_commit()
   for each stream.

behaviour on a hammerfall (correct):
---
hw avail: c:64 p:64
this time = 64
contiguous = 64
hw avail: c:64 p:64
this time = 64
contiguous = 64
hw avail: c:64 p:64
this time = 64
contiguous = 64
hw avail: c:64 p:64
this time = 64
contiguous = 64
hw avail: c:64 p:64

etc. etc. etc.

behaviour on a trident (problem)
---

hw avail: c:64 p:65
this time = 64
contiguous = 64
hw avail: c:64 p:66
this time = 64
contiguous = 64
hw avail: c:0 p:65
this time = 0
hw avail: c:0 p:65
this time = 0
hw avail: c:65 p:65
this time = 64
contiguous = 64
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0
hw avail: c:1 p:66
this time = 0

[ ... continues like this for quite some time ... then: ]

hw avail: c:64 p:65
this time = 64
contiguous = 64
hw avail: c:64 p:66
this time = 64
contiguous = 64
hw avail: c:64 p:65
this time = 64
contiguous = 64
hw avail: c:0 p:66
this time = 0


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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Jaroslav Kysela

On Wed, 28 Nov 2001, Paul Davis wrote:

 non-continous transfers. The right loop, based on the period_size
 transfers, should be like this:
 
  poll();
  if ((pfd-revents  POLLIN) {
  while (1) {
  if (snd_pcm_avail_update(pcm)  period_size)
  break;
  count = period_size;
  // transfer whole period (can be composed from more
  // non-continuous parts)

 right, i understand that on some hardware, this is true. but there is
 no reason i know of for the trident h/w (perhaps for any hardware) to
 have a whole period composed of 2 non-continuous parts of size 1 and
 (period_size-1) frames. i can't believe that its an honest reflection
 of the state of the hardware.

There can be two reasons:

1) the interrupt acknowledge is a bit delayed
2) the task wakeup is a bit delayed

It makes perfectly sense, that the stream is some frames ahead when
task is woken up.

 the one complication that i can see that might cause this is the
 extent to which capture+playback hw pointers are in sync. what might
 be happening is that there really is a continuous period_size's worth
 of frames available on one stream, but in the other stream, the
 pointer doesn't quite reflect this, so we end up with the silly
 situation of having (period_size-1) + 1 frames. you'll note that in the
 code below, i poll only one descriptor.

Yes, that's right. Some hardware has trouble to pass the same pointers
when the streams are running in sync, but the difference should be only
a few frames.

 do you think this is possible/likely? if it is, do you think that its
 the job of the low level driver(s) to handle this? otherwise, its hard
 for me to see how an application (or library) can handle this
 efficiently in any full-duplex situations.

Yes, I think that only lowlevel driver code knows which streams are broken
and we can have only one interrupt acknowledge source.

 i say this because even if we poll on both stream descriptors, if one
 of them is out-of-step by 1 (or lets just say some very small number
 of frames), we have to go back into poll immediately, which will
 return immediately, and we end up busy waiting, which is not good at all.
 i don't see any other way to handle that situation. do you?

Nope.

 i'm going to add some debugging to check on the pointers-not-in-sync
 theory, and i'll let you know what i find. since very few programs do
 full duplex operation, this may be a rather hidden problem.

  while (avail  0) {

Oops. There should be 'while (count  0) {'.

  frames = count;
  snd_pcm_mmap_begin(pcm, areas, offset, frames
 );
  
  snd_pcm_mmap_commit(pcm, offset, frames);
  count -= frames;
  }
  }
  }

 is there any difference between that and the actual loop (a few
 non-essentials removed to make it clearer):

Yes, there are differences:

   if (poll (driver-pfd, 1, 1000)  0) {
    error ...
   }

   if (driver-pfd.revents  POLLERR) {
    error 
   }

   if (driver-pfd.revents == 0) {
   ... timeout 
   }

   if ((capture_avail = snd_pcm_avail_update (driver-capture_handle))  0) {
 ... detect xruns ...
   }

   if ((playback_avail = snd_pcm_avail_update (driver-playback_handle))  0) {
  ... detect xruns ...
   }

   ... handle xruns ...

   avail = capture_avail  playback_avail ?
  capture_avail : playback_avail;

   while (avail) {

You are trying to process all available frames. It's not bad, but you can
assume (if poll returned a bit later) that there will be extra frames
available in the ring buffer. It's your problem with the sigle extra
frame, which started this discussion.

   /* driver-frames_per_cycle === period_size */

   capture_avail = (avail  driver-frames_per_cycle) ?
 driver-frames_per_cycle : avail;
   playback_avail = (avail  driver-frames_per_cycle) ?
 driver-frames_per_cycle : avail;

Note that my algorithm has two loops: One handles that only frames for the
whole period will be processed, the second is for non-contiguous frames
in one period. The second loop can be called maximally twice.

   /* THIS CALLS snd_pcm_mmap_begin() FOR BOTH STREAMS */

   if (alsa_driver_get_channel_addresses
(driver,
(snd_pcm_uframes_t *) capture_avail,
  (snd_pcm_uframes_t *) playback_avail,
capture_offset, playback_offset)  0) {
   return -1;
   }

   contiguous = capture_avail  playback_avail ?

Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Paul Davis

 true, except that we enforce this requirement at a different
 level. you can't get a synchronous engine to run correctly if the
 capture and playback streams are not usable in the same basic way.

 or can you?

Yes, you can find the nearest transfer count for both streams.

Sure, that would work but its not of much interest to me right
now. Thats really just telling a user you asked for N frames per
cycle, but we can only do 3*N, just to let you know. That may be
completely wrong. The model in a synchronous system is that you
specify the number of frames per cycle, and that number is
honored. choosing a value thats not supported by both streams is
obviously a mistake. if a user asks for N, but one of the streams
can't support it, its arguably better to tell what will work, and let
them try again.

 a similar issue arises with devices like the sbawe, which also
 cannot be used because the code requires that both streams be
 configurable with the same data format (the sbawe can't do this)

But the alsa-lib can.

well, JACK could too. it would be a small detail to add this to the
code, probably no more than half and hour. its just not of much
interest to anyone involved in it right now. its a hack to support
broken h/w, and you all know how i feel about that :)

--p



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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Abramo Bagnara


I think that you can easily solve the problem of missing frames from
capture or playback simply calling poll a first time with both stream
and a second time with the missing one.

In this way you solve the problem without the busy loop.

-- 
Abramo Bagnara   mailto:[EMAIL PROTECTED]

Opera Unica  Phone: +39.546.656023
Via Emilia Interna, 140
48014 Castel Bolognese (RA) - Italy

ALSA project   http://www.alsa-project.org
It sounds good!

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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Paul Davis

I think that you can easily solve the problem of missing frames from
capture or playback simply calling poll a first time with both stream
and a second time with the missing one.

In this way you solve the problem without the busy loop.

thats true.

however, as we've seen, that wasn't the nature of the problem, which
was instead my code trying to process all frames rather than
N*period_size frames. when this is fixed, that particular issue goes
away. 

well, it does if other things are working as expected :)

--p

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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Paul Davis

Jaroslav, you wrote:

avail = capture_avail  playback_avail ?
capture_avail : playback_avail;

/* here is very bad assumption, that all drivers are able */
/* todo full duplex with same period sizes, it would be better *
/
/* to choose smaller value from playback-frames_per_cycle */
/* and capture-frames_per_cycle */


true, except that we enforce this requirement at a different
level. you can't get a synchronous engine to run correctly if the
capture and playback streams are not usable in the same basic way. 

or can you?

a similar issue arises with devices like the sbawe, which also
cannot be used because the code requires that both streams be
configurable with the same data format (the sbawe can't do this)

--p

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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Jaroslav Kysela

On Wed, 28 Nov 2001, Paul Davis wrote:

 Jaroslav, you wrote:

 avail = capture_avail  playback_avail ?
 capture_avail : playback_avail;

 /* here is very bad assumption, that all drivers are able */
 /* todo full duplex with same period sizes, it would be better *
 /
 /* to choose smaller value from playback-frames_per_cycle */
 /* and capture-frames_per_cycle */


 true, except that we enforce this requirement at a different
 level. you can't get a synchronous engine to run correctly if the
 capture and playback streams are not usable in the same basic way.

 or can you?

Yes, you can find the nearest transfer count for both streams.

 a similar issue arises with devices like the sbawe, which also
 cannot be used because the code requires that both streams be
 configurable with the same data format (the sbawe can't do this)

But the alsa-lib can.
Jaroslav

-
Jaroslav Kysela [EMAIL PROTECTED]
SuSE Linuxhttp://www.suse.com
ALSA Project  http://www.alsa-project.org


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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Jaroslav Kysela

On Wed, 28 Nov 2001, Abramo Bagnara wrote:

 I think that you can easily solve the problem of missing frames from
 capture or playback simply calling poll a first time with both stream
 and a second time with the missing one.

 In this way you solve the problem without the busy loop.

That's right. I was writting exactly same answer.

Jaroslav

-
Jaroslav Kysela [EMAIL PROTECTED]
SuSE Linuxhttp://www.suse.com
ALSA Project  http://www.alsa-project.org


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



RE: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread James Courtier-Dutton

I don't know all about mmap, but why does one need to poll.
I would have thought that a callback with info on how many samples it wants
would be a better way.
Cheers
James


 -Original Message-
 From: [EMAIL PROTECTED]
 [mailto:[EMAIL PROTECTED]]On Behalf Of Paul Davis
 Sent: 28 November 2001 13:47
 To: Jaroslav Kysela
 Cc: [EMAIL PROTECTED]
 Subject: Re: [Alsa-devel] more on that return from poll(2) issue


 non-continous transfers. The right loop, based on the period_size
 transfers, should be like this:
 
  poll();
  if ((pfd-revents  POLLIN) {
  while (1) {
  if (snd_pcm_avail_update(pcm)  period_size)
  break;
  count = period_size;
  // transfer whole period (can be composed from more
  // non-continuous parts)

 right, i understand that on some hardware, this is true. but there is
 no reason i know of for the trident h/w (perhaps for any hardware) to
 have a whole period composed of 2 non-continuous parts of size 1 and
 (period_size-1) frames. i can't believe that its an honest reflection
 of the state of the hardware.

 the one complication that i can see that might cause this is the
 extent to which capture+playback hw pointers are in sync. what might
 be happening is that there really is a continuous period_size's worth
 of frames available on one stream, but in the other stream, the
 pointer doesn't quite reflect this, so we end up with the silly
 situation of having (period_size-1) + 1 frames. you'll note that in the
 code below, i poll only one descriptor.

 do you think this is possible/likely? if it is, do you think that its
 the job of the low level driver(s) to handle this? otherwise, its hard
 for me to see how an application (or library) can handle this
 efficiently in any full-duplex situations.

 i say this because even if we poll on both stream descriptors, if one
 of them is out-of-step by 1 (or lets just say some very small number
 of frames), we have to go back into poll immediately, which will
 return immediately, and we end up busy waiting, which is not good at all.
 i don't see any other way to handle that situation. do you?

 i'm going to add some debugging to check on the pointers-not-in-sync
 theory, and i'll let you know what i find. since very few programs do
 full duplex operation, this may be a rather hidden problem.

  while (avail  0) {
  frames = count;
  snd_pcm_mmap_begin(pcm, areas,
 offset, frames
 );
  
  snd_pcm_mmap_commit(pcm, offset, frames);
  count -= frames;
  }
  }
  }

 is there any difference between that and the actual loop (a few
 non-essentials removed to make it clearer):

   if (poll (driver-pfd, 1, 1000)  0) {
    error ...
   }

   if (driver-pfd.revents  POLLERR) {
    error 
   }

   if (driver-pfd.revents == 0) {
   ... timeout 
   }

   if ((capture_avail = snd_pcm_avail_update
 (driver-capture_handle))  0) {
 ... detect xruns ...
   }

   if ((playback_avail = snd_pcm_avail_update
 (driver-playback_handle))  0) {
  ... detect xruns ...
   }

   ... handle xruns ...

   avail = capture_avail  playback_avail ?
  capture_avail : playback_avail;

   while (avail) {

   /* driver-frames_per_cycle === period_size */

   capture_avail = (avail  driver-frames_per_cycle) ?
 driver-frames_per_cycle : avail;
   playback_avail = (avail  driver-frames_per_cycle) ?
 driver-frames_per_cycle : avail;

   /* THIS CALLS snd_pcm_mmap_begin() FOR BOTH STREAMS */

   if (alsa_driver_get_channel_addresses
(driver,
(snd_pcm_uframes_t *) capture_avail,
  (snd_pcm_uframes_t *) playback_avail,
capture_offset, playback_offset)  0) {
   return -1;
   }

   contiguous = capture_avail  playback_avail ?
 capture_avail : playback_avail;

    do interesting stuff with `contiguous' frames ...

   snd_pcm_mmap_commit (driver-capture_handle,
capture_offset, contiguous);
   snd_pcm_mmap_commit (driver-playback_handle,
playback_offset, contiguous);

   avail -= contiguous;
   }





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


___
Alsa-devel

Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Paul Davis

after hacking both the kernel driver and alsa-lib, this is the view
from user-space. each block between  is single return from
poll(2). i added code to print the values of the hw_ptr and appl_ptr
from within alsa-lib. 

---
hwptr = 65 apptr = 0
hwptr = 128 apptr = 64
hw avail: c:64 p:66
this time = 64
hwptr = 128 apptr = 64
contiguous = 64
---
hwptr = 128 apptr = 64
hwptr = 193 apptr = 128
hw avail: c:65 p:65
this time = 64
hwptr = 193 apptr = 128
contiguous = 64
---
hwptr = 193 apptr = 128
hwptr = 193 apptr = 192=== THIS
hw avail: c:1 p:66
this time = 0

the line marked THIS seems impossible to me. we've returned from
poll(2), but only one hwptr has changed since the last time. i just
don't understand how this can happen. unless its an xrun, but that
seems unlikely given that the code run here takes about 2usec
to execute, is mlocked and SCHED_FIFO'ed. any suggestions of how to
study this some more?

the appl_ptr is being updated correctly by snd_pcm_mmap_commit() (it
moves forward 64 frames each time).

i have a kernel space trace too, but it seems too hard to sync up the
output from there with the userspace dump.

needless to say, i don't see this on the hammerfall (not suprising
since there is only one hw_ptr for both playback and capture).

--p



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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Jaroslav Kysela

On Wed, 28 Nov 2001, Paul Davis wrote:

 after hacking both the kernel driver and alsa-lib, this is the view
 from user-space. each block between  is single return from
 poll(2). i added code to print the values of the hw_ptr and appl_ptr
 from within alsa-lib.

 ---
 hwptr = 65 apptr = 0
 hwptr = 128 apptr = 64
 hw avail: c:64 p:66
 this time = 64
 hwptr = 128 apptr = 64
 contiguous = 64
 ---
 hwptr = 128 apptr = 64
 hwptr = 193 apptr = 128
 hw avail: c:65 p:65
 this time = 64
 hwptr = 193 apptr = 128
 contiguous = 64
 ---
 hwptr = 193 apptr = 128
 hwptr = 193 apptr = 192=== THIS
 hw avail: c:1 p:66
 this time = 0

 the line marked THIS seems impossible to me. we've returned from
 poll(2), but only one hwptr has changed since the last time. i just
 don't understand how this can happen. unless its an xrun, but that

Note that IRQ acknowledge differs for playback and capture streams for the
Trident hardware. So it is possible, that one stream is acknowledged
before other and the hw pointer is updated only inside IRQ routine.

Jaroslav

-
Jaroslav Kysela [EMAIL PROTECTED]
SuSE Linuxhttp://www.suse.com
ALSA Project  http://www.alsa-project.org


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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Wolfgang Hoffmann

From a recent thread I learned that my RME DIGI96 only
allows period sizes of 2048 or 8192 bytes. No other choices,
due to hardware design. So what if the applications asks for
256 bytes? If the applications insists on that, it won't run. If
it asks for near, it'll get not what it expects, but at least
something that works.

I tried to run the ardour-package that Takashi Iwai provides on
ftp://ftp.suse.com/pub/people/tiwai/alsa9-packages/7.3-src/
but it seems that exactly due to this it won't run. Too bad, ardour
look very very promising on the web-pages!

It should be possible to run applications with periods of 2048
bytes, shouldn't it? Well, latency would be bad, but for plain
recording it should be ok, right?

Wolfgang

- Original Message -
From: Paul Davis [EMAIL PROTECTED]
To: Jaroslav Kysela [EMAIL PROTECTED]
Cc: Abramo Bagnara [EMAIL PROTECTED];
[EMAIL PROTECTED]
Sent: Wednesday, November 28, 2001 6:08 PM
Subject: Re: [Alsa-devel] more on that return from poll(2) issue


 Yes, you can find the nearest transfer count for both streams.

 Sure, that would work but its not of much interest to me right
 now. Thats really just telling a user you asked for N frames per
 cycle, but we can only do 3*N, just to let you know. That may be
 completely wrong. The model in a synchronous system is that you
 specify the number of frames per cycle, and that number is
 honored. choosing a value thats not supported by both streams is
 obviously a mistake. if a user asks for N, but one of the streams
 can't support it, its arguably better to tell what will work, and let
 them try again.


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


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



Re: [Alsa-devel] more on that return from poll(2) issue

2001-11-28 Thread Paul Davis

I tried to run the ardour-package that Takashi Iwai provides on
ftp://ftp.suse.com/pub/people/tiwai/alsa9-packages/7.3-src/
but it seems that exactly due to this it won't run. Too bad, ardour
look very very promising on the web-pages!

I respectfull request, with great vigor, that Takashi remove this
package. It is not acceptable to distribute binary copies of ardour
at this time. Absolutely not acceptable, and I am quite annoyed that
this was done. Its the second report I've had on this package. 

It should be possible to run applications with periods of 2048
bytes, shouldn't it? Well, latency would be bad, but for plain
recording it should be ok, right?

ardour -f 2048 will ask the h/w for a period of size 2048.
ardour --help will show all options.

--p

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