All of lore.kernel.org
 help / color / mirror / Atom feed
From: Benno Senoner <sbenno@gardena.net>
To: Paolo Losi <p.losi@hypersonic.it>
Cc: alsa-devel@lists.sf.net
Subject: Re: Event Based time synchronization with ALSA
Date: Mon, 17 Jan 2005 17:45:03 +0100	[thread overview]
Message-ID: <41EBEB8F.9030009@gardena.net> (raw)
In-Reply-To: <41EB9874.4060407@hypersonic.it>

I suggest you to do the following:

have a thread that does audio I/O and write/read the
audio data to 2 ringbuffers using eg frame size of about 10msec.
10msec = 441 samples, thus I'd choose 512 samples (alsa period sizes 
must be power of 2).

for example for the RTP sending (capturing audio from the alsa device 
and send a RTP packet).

you could for example do:

short audiobu[512];

while(1) {

 capture_audio_from_alsa(audiobuf) // (blocking read,  512 samples)

 write_to_ringbuffer(audiobuf, 512); // write the 512 samples to the 
ringbuffer

 space = get_ringbuffer_read_space(); // now we get how many samples are 
accumulated in the ringbuffer

 if(space >= 882)  {   // ( 882 = 20msec of samples at 44100Hz).
    ringbufferdata = read_from_ringbuffer(882);
    send_rtp_packet(ringbufferdata);
  }


}

The above routine has the advantage that you can use any kind of 
periodsize (fragment size) in ALSA
and the send_rtp packet() always gets 20msec worth of data.
But you must ensure that the ALSA period size must be <20msec , 
otherwise too much jitter is introduced.
eg if I have a periodsize of 100msec , the ALSA blocking read() will 
block until 100msec worth of audio are available

and then the send_rtp_packet() would only fetch 20msec of audio from the 
ringbuffer and the thread would sleep
for 100msec again and the ringbuffer would eventually fill up leading to 
garbled RTP audio (you hear only
every 5th packet).
You could wrap  space = ...  ; if(space >= 882) in a while(space >= 882) 
loop but that would cause to send
out fast bursts of 20msec packets each 100msec probably overrunning or 
putting strain on the jitter buffer
on the receiving side of the other SIP phone.

So far for the sending side of your SIP phone.

The receiving side is more complex since RTP packets (which are based on 
UDP) could come out of order
so you need a jitter buffer (sliding window) which reorders the packets, 
discards late packets etc.
Or if you assume that out of order packets are very rare you could 
ignore the case and discard the packet.
and simply insert the RTP audio data to the end of a receiving 
ringbuffer (in an analogous way like the the code
above) and have the audio thread writing an audio frames to the ALSA 
device as soon as enough packets are here.
The problem of the internet is that it is not easy to estimate the 
latency in advance (eg when you do a oversea
SIP call) so you have to use an adaptive algorithm which measures jitter 
between packets
(eg instead of each 20msec, some packets could arrive after 100msec but 
then 5 packets in a burst etc), and thus
adapting the size of the ringbufffer dynamically based on the latency 
measurements.
This will give you the lowest possible latency with the best call quality.
Perhaps if you look at the code of some of the opensource soft phones 
you can get an idea what's the best method
to implement this.

ciao,
Benno









Paolo Losi wrote:

> Hi all,
>     I'd like to develop a sip phone using alsa...
>
> All the app is going to be event based (no_blocking io, poll).
>
> One of the issues is how to read 20ms sample periods
> to build an rtp packet
>
> What I'd like to understand is if I can rely on interrupts (poll
> read data available event) by HW in order to get accurate 50HZ
> poll frequency or I must rely on poll timeout instead...
>
> My goal is (as always :-) ) to reduce as much as I can latency...
>
> In the case poll events would be enough what would be the
> relevant sw_params api's?
>
>     Thank you very much
>
>     PL
>
>
> -------------------------------------------------------
> The SF.Net email is sponsored by: Beat the post-holiday blues
> Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
> It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/alsa-devel
>



-------------------------------------------------------
The SF.Net email is sponsored by: Beat the post-holiday blues
Get a FREE limited edition SourceForge.net t-shirt from ThinkGeek.
It's fun and FREE -- well, almost....http://www.thinkgeek.com/sfshirt

  reply	other threads:[~2005-01-17 16:45 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2005-01-17 10:50 Event Based time synchronization with ALSA Paolo Losi
2005-01-17 16:45 ` Benno Senoner [this message]
2005-01-17 19:46   ` Jaroslav Kysela
2005-01-18  9:40     ` Takashi Iwai
2005-01-18 11:47   ` Paolo Losi
2005-01-18 13:46     ` Benno Senoner

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=41EBEB8F.9030009@gardena.net \
    --to=sbenno@gardena.net \
    --cc=alsa-devel@lists.sf.net \
    --cc=p.losi@hypersonic.it \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.