All of lore.kernel.org
 help / color / mirror / Atom feed
* Trying to understand alsa
@ 2012-01-12 23:36 Jonathan Andrews
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Andrews @ 2012-01-12 23:36 UTC (permalink / raw)
  To: alsa-devel


> If a packet arrives very late (and one will, eventually), you will
> underrun.  That's unavoidable. You can check for SND_PCM_STATE_XRUN
> from snd_pcm_state().  It's undocumented, but you need to call
> snd_pcm_avail_update() first to get an accurate reading from
> snd_pcm_state(). When an underrun occurs, recover with
> snd_pcm_recover() and then start writing data again.
> 

Ok, this my first attempt at recovery, still haven't solved buffering
problem so it underruns for each and every write.

Does this look roughly correct ?

Thanks,
Jon


#ifdef ALSA
                                // snd_pcm_writen - writes non interleaved (mono) samples
                                // bufs an explicit void* pointer type set to point at real sample buffer "audio"
                                // broken pipe indicates buffer underrun

                                numrecs=sizeof(audio)/2;                // 1k buffer, 512 samples 
                                //printf("%d \n", snd_pcm_wait(playback_handle[activeslot],1));
                                err = snd_pcm_writen (playback_handle[activeslot], &bufs, numrecs);
                                if (err<numrecs)
                                {
                                        fflush(stdout);
                                        if (err>0)
                                        {
                                                fprintf (stderr, "snd_pcm_writen: wrote only %d\n",err);
                                                fflush(stderr);
                                        }
                                        else
                                        {
                                                if (err == EPIPE)      
                                                {
                                                        errb=snd_pcm_recover(playback_handle[activeslot],err,0);                // error passed is resullt of writen
                                                        if (errb<0)
                                                        {
                                                                fprintf(stderr,"Failed to recover from underrun\n");
                                                                fflush(stderr);
                                                                exit(1);
                                                        }
                                                }
                                                else
                                                {
                                                        fprintf (stderr, "snd_pcm_writen:  write to audio interface failed (%s) (%d)\n", snd_strerror (err),err);
                                                        fflush(stdout);
                                                        fflush(stderr);
                                                        exit (1);
                                                }
                                        }
                                }
#endif

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Trying to understand alsa
       [not found]   ` <1326410207.23310.17.camel@jonspc>
@ 2012-01-13 15:10     ` Andrew Eikum
  0 siblings, 0 replies; 8+ messages in thread
From: Andrew Eikum @ 2012-01-13 15:10 UTC (permalink / raw)
  To: Jonathan Andrews; +Cc: alsa-devel

On Thu, Jan 12, 2012 at 11:16:47PM +0000, Jonathan Andrews wrote:
> On Thu, 2012-01-12 at 16:12 -0600, Andrew Eikum wrote:
> > On Thu, Jan 12, 2012 at 09:44:11PM +0000, Jonathan Andrews wrote:
> > > I have an application that works using 512 sample packets of 22050Hz 16
> > > bit mono audio.  The 'receiver' takes many audio streams from a network
> > > via UDP, at the moment it pipes them into pulse.
> > > 
> > > Can alsa buffer audio. At the moment every time I and set an audio
> > > buffer size I get a negative response from
> > > snd_pcm_hw_params_set_buffer_size .  I'm somewhat confused about the
> > > units alsa uses ...
> > > 
> > 
> > You don't want to over-specify your requirements. You require a buffer
> > size of "at least" 3 * 512 frames. So use set_buffer_size_min().
> 
> I cant find any reference to "set_buffer_size_min" in the ALSA API
> documentation I have or the link you provided ?
> snd_pcm_hw_params_set_buffer_time_near() is the closest and that seems
> to take an argument in useconds.  
> ?
> http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html
> 

The doxygen docs are split strangely. The function is documented here:
http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m___h_w___params.html#gb8d160039ffbbb15cb7187aa9ffae462

I find keeping the alsa-lib source on hand for quick grepping is often
helpful.

Andrew

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Trying to understand alsa
  2012-01-12 23:45 Jonathan Andrews
@ 2012-01-13  1:25 ` Jonathan Andrews
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Andrews @ 2012-01-13  1:25 UTC (permalink / raw)
  To: alsa-devel

On Thu, 2012-01-12 at 23:45 +0000, Jonathan Andrews wrote:
> On Thu, 2012-01-12 at 16:12 -0600, Andrew Eikum wrote:
> > On Thu, Jan 12, 2012 at 09:44:11PM +0000, Jonathan Andrews wrote:
> > > I have an application that works using 512 sample packets of 22050Hz 16
> > > bit mono audio.  The 'receiver' takes many audio streams from a network
> > > via UDP, at the moment it pipes them into pulse.
> > > 
> > > Can alsa buffer audio. At the moment every time I and set an audio
> > > buffer size I get a negative response from
> > > snd_pcm_hw_params_set_buffer_size .  I'm somewhat confused about the
> > > units alsa uses ...
> > > 
> > 
> > You don't want to over-specify your requirements. You require a buffer
> > size of "at least" 3 * 512 frames. So use set_buffer_size_min().
> 
> I cant find any reference to "set_buffer_size_min" in the ALSA API
> documentation I have or the link you provided ?
> snd_pcm_hw_params_set_buffer_time_near() is the closest and that seems
> to take an argument in useconds.  
> ?
> http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html

Scrub that, found it in the end ..... Im over 40, I miss plain old
manuals .....

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Trying to understand alsa
@ 2012-01-12 23:45 Jonathan Andrews
  2012-01-13  1:25 ` Jonathan Andrews
  0 siblings, 1 reply; 8+ messages in thread
From: Jonathan Andrews @ 2012-01-12 23:45 UTC (permalink / raw)
  To: alsa-devel

On Thu, 2012-01-12 at 16:12 -0600, Andrew Eikum wrote:
> On Thu, Jan 12, 2012 at 09:44:11PM +0000, Jonathan Andrews wrote:
> > I have an application that works using 512 sample packets of 22050Hz 16
> > bit mono audio.  The 'receiver' takes many audio streams from a network
> > via UDP, at the moment it pipes them into pulse.
> > 
> > Can alsa buffer audio. At the moment every time I and set an audio
> > buffer size I get a negative response from
> > snd_pcm_hw_params_set_buffer_size .  I'm somewhat confused about the
> > units alsa uses ...
> > 
> 
> You don't want to over-specify your requirements. You require a buffer
> size of "at least" 3 * 512 frames. So use set_buffer_size_min().

I cant find any reference to "set_buffer_size_min" in the ALSA API
documentation I have or the link you provided ?
snd_pcm_hw_params_set_buffer_time_near() is the closest and that seems
to take an argument in useconds.  
?
http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html


> Otherwise ALSA will try to set exactly that buffer size, which can
> fail.
> 
> Check the function signatures for units. Notice that
> set_buffer_size*() all take snd_pcm_uframes_t, that is, the number of
> frames you want to store. In ALSA terms, a "frame" is a set of a
> single sample for every channel. Since you have mono audio, a frame
> and a sample are actually the same unit (for 16 bit stereo audio,
> 1 frame = 2 samples = 32 bits).
> 
> > What I want to do is tell ALSA to hold a buffer of 3 of my packets (3 x
> > 1024Bytes, thats 512 x 16 bit samples) while I feed extra packets (1K
> > Byte, 512 samples per buffer) in for playback.  The packets are arriving
> > at roughly the correct rate, I just need a buffer to  iron out any
> > jitter in network transmit, do I have to do this myself ?
> > 
> > Can somebody help by telling me which numbers I push into which places
> > to make it work ?
> > 
> > At the moment I get i keep getting a broken pipe, if I underrun how can
> > I make it just wait for me ?
> > 
> 
> If a packet arrives very late (and one will, eventually), you will
> underrun.  That's unavoidable. You can check for SND_PCM_STATE_XRUN
> from snd_pcm_state().  It's undocumented, but you need to call
> snd_pcm_avail_update() first to get an accurate reading from
> snd_pcm_state(). When an underrun occurs, recover with
> snd_pcm_recover() and then start writing data again.
Ok, thanks.


> If a packet arrives early, you'll need to check that the ALSA buffer
> isn't full (see snd_pcm_avail_update()), and store it within your
> application to write later if it is full.
> 
> There's some mostly-accurate information here:
> http://0pointer.de/blog/projects/guide-to-sound-apis.html
> As with all ALSA documentation, it is confusing and often incorrect,
> but it's probably the most helpful document I've found.

Many thanks for the help,
Jon

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Trying to understand alsa
@ 2012-01-12 23:36 Jonathan Andrews
  0 siblings, 0 replies; 8+ messages in thread
From: Jonathan Andrews @ 2012-01-12 23:36 UTC (permalink / raw)
  To: alsa-devel

On Thu, 2012-01-12 at 21:50 +0000, Fons Adriaensen wrote:
> On Thu, Jan 12, 2012 at 09:44:11PM +0000, Jonathan Andrews wrote:
>  
> > What I want to do is tell ALSA to hold a buffer of 3 of my packets (3 x
> > 1024Bytes, thats 512 x 16 bit samples) while I feed extra packets (1K
> > Byte, 512 samples per buffer) in for playback.  The packets are arriving
> > at roughly the correct rate, I just need a buffer to  iron out any
> > jitter in network transmit, do I have to do this myself ?
> 
> Unless data is arriving on average at *exactly* the sample
> rate of the ALSA device your buffering will sooner or later
> underrun or overrun. ALSA itself can't handle this use case,
> it requires adaptive resampling and it's not easy.

I'm assuming alsa is holding 3k bytes for me and im writing 1k byte
chunks, so if the audio has not been refreshed by 3 chunks (70ms) then I
should throw it away as its no longer 'real time'

At the moment i would happy just to throw away packets that would cause
an overrun. I just wish i could convince alsa to buffer for me .... ho
hum ...

with pulse I just did this to set up 'some sort of buffer length' with
'some sort of pre buffering before play' interval.  Its a bit hacky at
the moment but seems to work.

    pa_buffer_attr  paattr;
    int buflen=sizeof(audio);
    paattr.tlength = buflen * 4;                                                                // Playback only, target length of the buffer (was *2)
    paattr.minreq = buflen;
    paattr.fragsize = buflen;
    paattr.prebuf = buflen * 6;                                                                 // How much data pulse holds before it starts playing (was *4)
    paattr.maxlength = buflen * 8;                                                              // playback pipeline N samples deep (was *4)

Im looking for alsa equivalent. 

Thanks,
Jon

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Trying to understand alsa
  2012-01-12 21:44 Jonathan Andrews
  2012-01-12 21:50 ` Fons Adriaensen
@ 2012-01-12 22:12 ` Andrew Eikum
       [not found]   ` <1326410207.23310.17.camel@jonspc>
  1 sibling, 1 reply; 8+ messages in thread
From: Andrew Eikum @ 2012-01-12 22:12 UTC (permalink / raw)
  To: Jonathan Andrews; +Cc: alsa-devel

On Thu, Jan 12, 2012 at 09:44:11PM +0000, Jonathan Andrews wrote:
> I have an application that works using 512 sample packets of 22050Hz 16
> bit mono audio.  The 'receiver' takes many audio streams from a network
> via UDP, at the moment it pipes them into pulse.
> 
> Can alsa buffer audio. At the moment every time I and set an audio
> buffer size I get a negative response from
> snd_pcm_hw_params_set_buffer_size .  I'm somewhat confused about the
> units alsa uses ...
> 

You don't want to over-specify your requirements. You require a buffer
size of "at least" 3 * 512 frames. So use set_buffer_size_min().
Otherwise ALSA will try to set exactly that buffer size, which can
fail.

Check the function signatures for units. Notice that
set_buffer_size*() all take snd_pcm_uframes_t, that is, the number of
frames you want to store. In ALSA terms, a "frame" is a set of a
single sample for every channel. Since you have mono audio, a frame
and a sample are actually the same unit (for 16 bit stereo audio,
1 frame = 2 samples = 32 bits).

> What I want to do is tell ALSA to hold a buffer of 3 of my packets (3 x
> 1024Bytes, thats 512 x 16 bit samples) while I feed extra packets (1K
> Byte, 512 samples per buffer) in for playback.  The packets are arriving
> at roughly the correct rate, I just need a buffer to  iron out any
> jitter in network transmit, do I have to do this myself ?
> 
> Can somebody help by telling me which numbers I push into which places
> to make it work ?
> 
> At the moment I get i keep getting a broken pipe, if I underrun how can
> I make it just wait for me ?
> 

If a packet arrives very late (and one will, eventually), you will
underrun.  That's unavoidable. You can check for SND_PCM_STATE_XRUN
from snd_pcm_state().  It's undocumented, but you need to call
snd_pcm_avail_update() first to get an accurate reading from
snd_pcm_state(). When an underrun occurs, recover with
snd_pcm_recover() and then start writing data again.

If a packet arrives early, you'll need to check that the ALSA buffer
isn't full (see snd_pcm_avail_update()), and store it within your
application to write later if it is full.

There's some mostly-accurate information here:
http://0pointer.de/blog/projects/guide-to-sound-apis.html
As with all ALSA documentation, it is confusing and often incorrect,
but it's probably the most helpful document I've found.

Good luck!

Andrew

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: Trying to understand alsa
  2012-01-12 21:44 Jonathan Andrews
@ 2012-01-12 21:50 ` Fons Adriaensen
  2012-01-12 22:12 ` Andrew Eikum
  1 sibling, 0 replies; 8+ messages in thread
From: Fons Adriaensen @ 2012-01-12 21:50 UTC (permalink / raw)
  To: alsa-devel

On Thu, Jan 12, 2012 at 09:44:11PM +0000, Jonathan Andrews wrote:
 
> What I want to do is tell ALSA to hold a buffer of 3 of my packets (3 x
> 1024Bytes, thats 512 x 16 bit samples) while I feed extra packets (1K
> Byte, 512 samples per buffer) in for playback.  The packets are arriving
> at roughly the correct rate, I just need a buffer to  iron out any
> jitter in network transmit, do I have to do this myself ?

Unless data is arriving on average at *exactly* the sample
rate of the ALSA device your buffering will sooner or later
underrun or overrun. ALSA itself can't handle this use case,
it requires adaptive resampling and it's not easy.

Ciao,

-- 
FA

Vor uns liegt ein weites Tal, die Sonne scheint - ein Glitzerstrahl.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Trying to understand alsa
@ 2012-01-12 21:44 Jonathan Andrews
  2012-01-12 21:50 ` Fons Adriaensen
  2012-01-12 22:12 ` Andrew Eikum
  0 siblings, 2 replies; 8+ messages in thread
From: Jonathan Andrews @ 2012-01-12 21:44 UTC (permalink / raw)
  To: alsa-devel

Hi people, i'm trying to understand alsa....

I have an application that works using 512 sample packets of 22050Hz 16
bit mono audio.  The 'receiver' takes many audio streams from a network
via UDP, at the moment it pipes them into pulse.

Can alsa buffer audio. At the moment every time I and set an audio
buffer size I get a negative response from
snd_pcm_hw_params_set_buffer_size .  I'm somewhat confused about the
units alsa uses ...

What I want to do is tell ALSA to hold a buffer of 3 of my packets (3 x
1024Bytes, thats 512 x 16 bit samples) while I feed extra packets (1K
Byte, 512 samples per buffer) in for playback.  The packets are arriving
at roughly the correct rate, I just need a buffer to  iron out any
jitter in network transmit, do I have to do this myself ?

Can somebody help by telling me which numbers I push into which places
to make it work ?

At the moment I get i keep getting a broken pipe, if I underrun how can
I make it just wait for me ?

I only code in plain old C at the moment.

Many thanks for any help/advice anyone can offer.

Jon

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2012-01-13 15:11 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2012-01-12 23:36 Trying to understand alsa Jonathan Andrews
  -- strict thread matches above, loose matches on Subject: below --
2012-01-12 23:45 Jonathan Andrews
2012-01-13  1:25 ` Jonathan Andrews
2012-01-12 23:36 Jonathan Andrews
2012-01-12 21:44 Jonathan Andrews
2012-01-12 21:50 ` Fons Adriaensen
2012-01-12 22:12 ` Andrew Eikum
     [not found]   ` <1326410207.23310.17.camel@jonspc>
2012-01-13 15:10     ` Andrew Eikum

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.