* latency.c and delay related questions
@ 2006-06-20 10:10 Christophe Osuna
2006-06-20 16:15 ` Lee Revell
2006-06-20 17:38 ` Jaroslav Kysela
0 siblings, 2 replies; 5+ messages in thread
From: Christophe Osuna @ 2006-06-20 10:10 UTC (permalink / raw)
To: alsa-devel
[-- Attachment #1.1: Type: text/plain, Size: 4488 bytes --]
Hi,
I am trying to get small delays with my application and I have been
playing with "latency" from alsa-lib/test.
The current delay with "latency" is equal to a minimum (that depends
on the sound card) plus *two* times the period time. If I disable
manual change of sound card state as described in the patch below the
delay becomes equal to a minimum *higher than the previous* plus *one*
time the period time.
The delay has been measured with an external box plugged on the sound
card.
I would like to mix both settings to get a delay of the lowest minimum
plus one time the period time. But for this I need to understand what
is happening, and more precisely:
* why is snd_pcm_link() mandatory? (no sound otherwise)
* why two buffers of silence and not just one?
* why is there no snd_pcm_start() for the playback device?
* why is the minimum delay lower with manual handling of the sound
card state?
Help is welcome :-)
Thanxs in advance.
--- latency.c.orig 2006-06-20 10:21:57.000000000 +0200
+++ latency.c 2006-06-20 11:06:10.000000000 +0200
@@ -148,11 +148,11 @@
printf("Unable to determine current swparams for %s: %s\n",
id, snd_strerror(err
));
return err;
}
- err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
0x7fffffff);
- if (err < 0) {
- printf("Unable to set start threshold mode for %s: %s\n",
id, snd_strerror(err))
;
- return err;
- }
+/* err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
0x7fffffff); */
+/* if (err < 0) { */
+/* printf("Unable to set start threshold mode for %s: %s\n",
id, snd_strerror(err))
; */
+/* return err; */
+/* } */
tick_time_ok = 0;
if (tick_time > 0) {
unsigned int time, ttime;
@@ -273,10 +273,10 @@
exit(0);
}
- if ((err = snd_pcm_prepare(phandle)) < 0) {
- printf("Prepare error: %s\n", snd_strerror(err));
- exit(0);
- }
+/* if ((err = snd_pcm_prepare(phandle)) < 0) { */
+/* printf("Prepare error: %s\n", snd_strerror(err)); */
+/* exit(0); */
+/* } */
snd_pcm_dump(phandle, output);
snd_pcm_dump(chandle, output);
@@ -646,27 +646,27 @@
showlatency(latency);
if (tick_time_ok)
printf("Using tick time %ius\n", tick_time_ok);
- if ((err = snd_pcm_link(chandle, phandle)) < 0) {
- printf("Streams link error: %s\n",
snd_strerror(err));
- exit(0);
- }
- if (snd_pcm_format_set_silence(format, buffer,
latency*channels) < 0) {
- fprintf(stderr, "silence error\n");
- break;
- }
- if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
- fprintf(stderr, "write error\n");
- break;
- }
- if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
- fprintf(stderr, "write error\n");
- break;
- }
-
- if ((err = snd_pcm_start(chandle)) < 0) {
- printf("Go error: %s\n", snd_strerror(err));
- exit(0);
- }
+/* if ((err = snd_pcm_link(chandle, phandle)) < 0) { */
+/* printf("Streams link error: %s\n",
snd_strerror(err)); */
+/* exit(0); */
+/* } */
+/* if (snd_pcm_format_set_silence(format, buffer,
latency*channels) < 0) { */
+/* fprintf(stderr, "silence error\n"); */
+/* break; */
+/* } */
+/* if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
*/
+/* fprintf(stderr, "write error\n"); */
+/* break; */
+/* } */
+/* if (writebuf(phandle, buffer, latency, &frames_out) < 0) {
*/
+/* fprintf(stderr, "write error\n"); */
+/* break; */
+/* } */
+
+/* if ((err = snd_pcm_start(chandle)) < 0) { */
+/* printf("Go error: %s\n", snd_strerror(err)); */
+/* exit(0); */
+/* } */
gettimestamp(phandle, &p_tstamp);
gettimestamp(chandle, &c_tstamp);
#if 0
[-- Attachment #1.2: Type: text/html, Size: 10347 bytes --]
[-- Attachment #2: Type: text/plain, Size: 0 bytes --]
[-- Attachment #3: Type: text/plain, Size: 161 bytes --]
_______________________________________________
Alsa-devel mailing list
Alsa-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/alsa-devel
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: latency.c and delay related questions
2006-06-20 10:10 latency.c and delay related questions Christophe Osuna
@ 2006-06-20 16:15 ` Lee Revell
2006-06-20 17:38 ` Jaroslav Kysela
1 sibling, 0 replies; 5+ messages in thread
From: Lee Revell @ 2006-06-20 16:15 UTC (permalink / raw)
To: Christophe Osuna; +Cc: alsa-devel
On Tue, 2006-06-20 at 12:10 +0200, Christophe Osuna wrote:
> Hi,
>
> I am trying to get small delays with my application and I have been
> playing with "latency" from alsa-lib/test.
>
Can you please not post HTML to this list?
Lee
> The current delay with "latency" is equal to a minimum (that depends
> on the sound card) plus *two* times the period time. If I disable
> manual change of sound card state as described in the patch below the
> delay becomes equal to a minimum *higher than the previous* plus *one*
> time the period time.
>
> The delay has been measured with an external box plugged on the sound
> card.
>
> I would like to mix both settings to get a delay of the lowest minimum
> plus one time the period time. But for this I need to understand what
> is happening, and more precisely:
>
> * why is snd_pcm_link() mandatory? (no sound otherwise)
> * why two buffers of silence and not just one?
> * why is there no snd_pcm_start() for the playback device?
> * why is the minimum delay lower with manual handling of the sound
> card state?
>
> Help is welcome :-)
>
> Thanxs in advance.
>
>
>
> --- latency.c.orig 2006-06-20 10:21:57.000000000 +0200
> +++ latency.c 2006-06-20 11:06:10.000000000 +0200
> @@ -148,11 +148,11 @@
> printf("Unable to determine current swparams for %s: %
> s\n", id, snd_strerror(err
> ));
> return err;
> }
> - err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
> 0x7fffffff);
> - if (err < 0) {
> - printf("Unable to set start threshold mode for %s: %s
> \n", id, snd_strerror(err))
> ;
> - return err;
> - }
> +/* err = snd_pcm_sw_params_set_start_threshold(handle, swparams,
> 0x7fffffff); */
> +/* if (err < 0) { */
> +/* printf("Unable to set start threshold mode for %s: %s
> \n", id, snd_strerror(err))
> ; */
> +/* return err; */
> +/* } */
> tick_time_ok = 0;
> if (tick_time > 0) {
> unsigned int time, ttime;
> @@ -273,10 +273,10 @@
> exit(0);
> }
>
> - if ((err = snd_pcm_prepare(phandle)) < 0) {
> - printf("Prepare error: %s\n", snd_strerror(err));
> - exit(0);
> - }
> +/* if ((err = snd_pcm_prepare(phandle)) < 0) { */
> +/* printf("Prepare error: %s\n", snd_strerror(err)); */
> +/* exit(0); */
> +/* } */
>
> snd_pcm_dump(phandle, output);
> snd_pcm_dump(chandle, output);
> @@ -646,27 +646,27 @@
> showlatency(latency);
> if (tick_time_ok)
> printf("Using tick time %ius\n",
> tick_time_ok);
> - if ((err = snd_pcm_link(chandle, phandle)) < 0) {
> - printf("Streams link error: %s\n",
> snd_strerror(err));
> - exit(0);
> - }
> - if (snd_pcm_format_set_silence(format, buffer,
> latency*channels) < 0) {
> - fprintf(stderr, "silence error\n");
> - break;
> - }
> - if (writebuf(phandle, buffer, latency, &frames_out) <
> 0) {
> - fprintf(stderr, "write error\n");
> - break;
> - }
> - if (writebuf(phandle, buffer, latency, &frames_out) <
> 0) {
> - fprintf(stderr, "write error\n");
> - break;
> - }
> -
> - if ((err = snd_pcm_start(chandle)) < 0) {
> - printf("Go error: %s\n", snd_strerror(err));
> - exit(0);
> - }
> +/* if ((err = snd_pcm_link(chandle, phandle)) < 0) { */
> +/* printf("Streams link error: %s\n",
> snd_strerror(err)); */
> +/* exit(0); */
> +/* } */
> +/* if (snd_pcm_format_set_silence(format, buffer,
> latency*channels) < 0) { */
> +/* fprintf(stderr, "silence error\n"); */
> +/* break; */
> +/* } */
> +/* if (writebuf(phandle, buffer, latency, &frames_out) <
> 0) { */
> +/* fprintf(stderr, "write error\n"); */
> +/* break; */
> +/* } */
> +/* if (writebuf(phandle, buffer, latency, &frames_out) <
> 0) { */
> +/* fprintf(stderr, "write error\n"); */
> +/* break; */
> +/* } */
> +
> +/* if ((err = snd_pcm_start(chandle)) < 0) { */
> +/* printf("Go error: %s\n", snd_strerror(err));
> */
> +/* exit(0); */
> +/* } */
> gettimestamp(phandle, &p_tstamp);
> gettimestamp(chandle, &c_tstamp);
> #if 0
>
> _______________________________________________
> Alsa-devel mailing list
> Alsa-devel@lists.sourceforge.net
> https://lists.sourceforge.net/lists/listinfo/alsa-devel
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: latency.c and delay related questions
2006-06-20 10:10 latency.c and delay related questions Christophe Osuna
2006-06-20 16:15 ` Lee Revell
@ 2006-06-20 17:38 ` Jaroslav Kysela
2006-06-21 10:16 ` Christophe Osuna
1 sibling, 1 reply; 5+ messages in thread
From: Jaroslav Kysela @ 2006-06-20 17:38 UTC (permalink / raw)
To: Christophe Osuna; +Cc: alsa-devel
On Tue, 20 Jun 2006, Christophe Osuna wrote:
> The current delay with "latency" is equal to a minimum (that depends
> on the sound card) plus *two* times the period time. If I disable
Yes, it's correct. Basically, you cannot avoid double buffering, so the
total latency is:
1) one capture period
2) one playback period (actually being played)
3) moved captured period to playback buffer (not counted)
So the latency should be 2 * period plus a hw latency as you noted.
Everything is correct. Of course, you may get better latencies if you run
"busy loop" on not-loaded system and immediately put captured data to
playback stream, but it's not a correct behaviour in *nix.
> * why is snd_pcm_link() mandatory? (no sound otherwise)
It links playback and capture streams so only one start() is called. On
hardware which supports hardware syncing, the DMA operation is started at
same time for both stream.
> * why two buffers of silence and not just one?
You must wait one period to get data from the capture direction and then
you have exactly one period time to put these data to the playback. As I
said, you can get better results with busy-loop but it's bad
implementation (but if you have a spare dedicated machine without other
tasks, it might be an option).
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: latency.c and delay related questions
2006-06-20 17:38 ` Jaroslav Kysela
@ 2006-06-21 10:16 ` Christophe Osuna
2006-06-21 18:35 ` Jaroslav Kysela
0 siblings, 1 reply; 5+ messages in thread
From: Christophe Osuna @ 2006-06-21 10:16 UTC (permalink / raw)
To: alsa-devel
(I apologize for the previous message with HTML - I am a new gmail
user and was expecting it not to send HTML for a basic text message. I
have disabled text formatting - hope it works now.)
Thanks for your help. The linking of capture and playback devices
explains everything; if I remove linking and use snd_pcm_start() on
the playback device I get the expected behaviour.
Here is a little drawing (requires fixed font) to illustrate what you
have said and what I have understood (useless for you but some people
like me might find it useful).
When capture and playback devices are linked, the following happens:
+-------------------------
Capture | C0 | C1 | C2 | C3 | ...
+-------------------------
+-------------------------
Playback | -- | -- | C0 | C1 | ...
+-------------------------
Capture and playback start simultaneously and so playback device needs
something to play. When the first capture is finished, another is
started. We would like to play the captured audio, but another
playback has already started. Only after the latter is finished can
the captured audio be played.
This explains why the playback device needs two buffers of silence.
The total delay is hw_delay + 2 * period
When the devices are not linked, we can start the playback device
after the first buffer has been captured:
+-------------------------
Capture | C0 | C1 | C2 | C3 | ...
+-------------------------
+-----------------
Playback | C0 | C1 | C2 | .
+-----------------
Starting the playback device and copying data takes some time, so the
total delay becomes hw_delay + 1 * period + start_delay + copy_delay.
For large periods, with period > start_delay + copy_delay, this can
lead to a lower latency, but who would use large periods for low
latency?
Thanks again for your help.
^ permalink raw reply [flat|nested] 5+ messages in thread* Re: latency.c and delay related questions
2006-06-21 10:16 ` Christophe Osuna
@ 2006-06-21 18:35 ` Jaroslav Kysela
0 siblings, 0 replies; 5+ messages in thread
From: Jaroslav Kysela @ 2006-06-21 18:35 UTC (permalink / raw)
To: Christophe Osuna; +Cc: alsa-devel
On Wed, 21 Jun 2006, Christophe Osuna wrote:
> (I apologize for the previous message with HTML - I am a new gmail
> user and was expecting it not to send HTML for a basic text message. I
> have disabled text formatting - hope it works now.)
>
> Thanks for your help. The linking of capture and playback devices
> explains everything; if I remove linking and use snd_pcm_start() on
> the playback device I get the expected behaviour.
>
> Here is a little drawing (requires fixed font) to illustrate what you
> have said and what I have understood (useless for you but some people
> like me might find it useful).
>
> When capture and playback devices are linked, the following happens:
>
> +-------------------------
> Capture | C0 | C1 | C2 | C3 | ...
> +-------------------------
>
> +-------------------------
> Playback | -- | -- | C0 | C1 | ...
> +-------------------------
>
> Capture and playback start simultaneously and so playback device needs
> something to play. When the first capture is finished, another is
> started. We would like to play the captured audio, but another
> playback has already started. Only after the latter is finished can
> the captured audio be played.
>
> This explains why the playback device needs two buffers of silence.
>
> The total delay is hw_delay + 2 * period
Exactly. Well explained.
> When the devices are not linked, we can start the playback device
> after the first buffer has been captured:
>
> +-------------------------
> Capture | C0 | C1 | C2 | C3 | ...
> +-------------------------
>
> +-----------------
> Playback | C0 | C1 | C2 | .
> +-----------------
>
> Starting the playback device and copying data takes some time, so the
> total delay becomes hw_delay + 1 * period + start_delay + copy_delay.
> For large periods, with period > start_delay + copy_delay, this can
> lead to a lower latency, but who would use large periods for low
> latency?
Yes, this buffering schema is also possible, but note that the time window
for the data copy must satisfy the system scheduler requirements and
capabilities to get continous playback. In the "stream linked" case this
time window is exactly one period time.
Jaroslav
-----
Jaroslav Kysela <perex@suse.cz>
Linux Kernel Sound Maintainer
ALSA Project, SUSE Labs
All the advantages of Linux Managed Hosting--Without the Cost and Risk!
Fully trained technicians. The highest number of Red Hat certifications in
the hosting industry. Fanatical Support. Click to learn more
http://sel.as-us.falkag.net/sel?cmd=lnk&kid=107521&bid=248729&dat=121642
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2006-06-21 18:35 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2006-06-20 10:10 latency.c and delay related questions Christophe Osuna
2006-06-20 16:15 ` Lee Revell
2006-06-20 17:38 ` Jaroslav Kysela
2006-06-21 10:16 ` Christophe Osuna
2006-06-21 18:35 ` Jaroslav Kysela
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.