  <?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://www.alsa-project.org/main/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sdaau</id>
	<title>AlsaProject - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://www.alsa-project.org/main/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=Sdaau"/>
	<link rel="alternate" type="text/html" href="https://www.alsa-project.org/wiki/Special:Contributions/Sdaau"/>
	<updated>2026-04-09T08:55:12Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.39.0</generator>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=Test_latency.c&amp;diff=6675</id>
		<title>Test latency.c</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=Test_latency.c&amp;diff=6675"/>
		<updated>2013-09-18T05:45:00Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: /* Quick overview */ - added clarification about &amp;quot;Trying latency ...&amp;quot; line&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__FORCETOC__&lt;br /&gt;
== test latency.c ==&lt;br /&gt;
&lt;br /&gt;
Within &amp;lt;code&amp;gt;alsa-lib&amp;lt;/code&amp;gt;, there is a utility, [http://git.alsa-project.org/?p=alsa-lib.git;a=blob;f=test/latency.c; test/latency.c]  ([http://git.alsa-project.org/?p=alsa-lib.git;a=history;f=test/latency.c; history]), which performs a full-duplex test, where recorded (captured) data is played back.&lt;br /&gt;
&lt;br /&gt;
From &amp;lt;code&amp;gt;alsa-lib/test/latency.c&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
 *  Latency test program&lt;br /&gt;
 *&lt;br /&gt;
 *  This small demo program can be used for measuring latency between&lt;br /&gt;
 *  capture and playback. This latency is measured from driver (diff when&lt;br /&gt;
 *  playback and capture was started). Scheduler is set to SCHED_RR.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Building''' ===&lt;br /&gt;
&lt;br /&gt;
The name of the executable has to be passed explicitly to the &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; command - via [http://thread.gmane.org/gmane.linux.alsa.devel/6746/focus=6750 Re: problem ragarding execution of Latency.c (alsa-devel)]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
cd alsa-lib/test&lt;br /&gt;
make latency&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Options''' ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -h&lt;br /&gt;
Usage: latency [OPTION]... [FILE]...&lt;br /&gt;
-h,--help      help&lt;br /&gt;
-P,--pdevice   playback device&lt;br /&gt;
-C,--cdevice   capture device&lt;br /&gt;
-m,--min       minimum latency in frames&lt;br /&gt;
-M,--max       maximum latency in frames&lt;br /&gt;
-F,--frames    frames to transfer&lt;br /&gt;
-f,--format    sample format&lt;br /&gt;
-c,--channels  channels&lt;br /&gt;
-r,--rate      rate&lt;br /&gt;
-B,--buffer    buffer size in frames&lt;br /&gt;
-E,--period    period size in frames&lt;br /&gt;
-s,--seconds   duration of test in seconds&lt;br /&gt;
-b,--block     block mode&lt;br /&gt;
-p,--poll      use poll (wait for event - reduces CPU usage)&lt;br /&gt;
-e,--effect    apply an effect (bandpass filter sweep)&lt;br /&gt;
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE&lt;br /&gt;
&lt;br /&gt;
Tip #1 (usable latency with large periods, non-blocking mode, good CPU usage,&lt;br /&gt;
        superb xrun prevention):&lt;br /&gt;
  latency -m 8192 -M 8192 -t 1 -p&lt;br /&gt;
Tip #2 (superb latency, non-blocking mode, but heavy CPU usage):&lt;br /&gt;
  latency -m 128 -M 128&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The option &amp;lt;code&amp;gt;-F,--frames&amp;lt;/code&amp;gt; seems not to be handled anywhere in the code, and as such has no effect.&lt;br /&gt;
* The &amp;quot;Tip #1&amp;quot; refers to an option &amp;lt;code&amp;gt;-t&amp;lt;/code&amp;gt; which doesn't exist - however, it is likely a typo for the option &amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt; for duration in seconds&lt;br /&gt;
* The option &amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt; for duration in seconds is an integer, and the lowest it can be set is 1 second; default if not specified is 30 seconds&lt;br /&gt;
* Before 2012-08-08, there is a bug where the short options &amp;lt;code&amp;gt;-B&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-E&amp;lt;/code&amp;gt; are not recognized (&amp;quot;invalid option&amp;quot;) - but the long options &amp;lt;code&amp;gt;--buffer&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;--period&amp;lt;/code&amp;gt; still work even then.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Usage''' ===&lt;br /&gt;
&lt;br /&gt;
When called, the &amp;lt;code&amp;gt;test/latency.c&amp;lt;/code&amp;gt; program will attemp to set period/buffer sizes based on the latency entered, starting from &amp;lt;code&amp;gt;-m,--min&amp;lt;/code&amp;gt; option (or the default minimum latency = 64 if not specified). If the run succeeds without errors with that setting, the program exits; otherwise, the latency is increased, and the run repeated - if the run is succesful here, then program exits, else the process continues until the &amp;lt;code&amp;gt;-M,--max&amp;lt;/code&amp;gt; latency is reached.&lt;br /&gt;
&lt;br /&gt;
Example of successful run on Linux kernel 2.6.38 / ALSA 1.0.24.2 with HDA Intel onboard PCI soundcard:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: Intel [HDA Intel], device 0: ALC269 Analog [ALC269 Analog]&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&lt;br /&gt;
$ alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
Success&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 44288 ***&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  trigger_time: 84416.108859821&lt;br /&gt;
  tstamp      : 84417.110319083&lt;br /&gt;
  delay       : 80&lt;br /&gt;
  avail       : 48&lt;br /&gt;
  avail_max   : 120&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 44160 ***&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  trigger_time: 84416.108859821&lt;br /&gt;
  tstamp      : 84417.110439490&lt;br /&gt;
  delay       : 9&lt;br /&gt;
  avail       : 9&lt;br /&gt;
  avail_max   : 65&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
Playback time = 84416.108859, Record time = 84416.108859, diff = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The message &amp;quot;&amp;lt;code&amp;gt;Scheduler set to Round Robin with priority 99 FAILED&amp;lt;/code&amp;gt;&amp;quot; can be avoided by running the program with &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (administrative privileges):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
[sudo] password for user:&lt;br /&gt;
Scheduler set to Round Robin with priority 99...&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The program can also fail, if the streams experience an XRUN; in that case, if &amp;lt;code&amp;gt;-m&amp;lt;/code&amp;gt; is set to be equal to &amp;lt;code&amp;gt;-M&amp;lt;/code&amp;gt;, the program will immediately exit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
Failure&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 38464 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 479.798093354&lt;br /&gt;
  tstamp      : 479.798185056&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 128&lt;br /&gt;
  avail_max   : 128&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 38400 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 479.798093354&lt;br /&gt;
  tstamp      : 479.798361196&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 9&lt;br /&gt;
  avail_max   : 73&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Quick overview''' ===&lt;br /&gt;
&lt;br /&gt;
In brief, the &amp;lt;code&amp;gt;latency.c&amp;lt;/code&amp;gt; program:&lt;br /&gt;
&lt;br /&gt;
* Parses the command line parameters/options, and sets the playback and capture stream properties according to them&lt;br /&gt;
* Starts a loop where (among other things) it:&lt;br /&gt;
** shows the current latency value, using the &amp;lt;code&amp;gt;showlatency()&amp;lt;/code&amp;gt; function - which ultimately prints the &amp;quot;&amp;lt;i&amp;gt;Trying latency %li frames ...&amp;lt;/i&amp;gt;&amp;quot; line&lt;br /&gt;
*** &amp;lt;small&amp;gt;&amp;lt;i&amp;gt;Note:&amp;lt;/i&amp;gt; the &amp;lt;code&amp;gt;showlatency(size_t latency)&amp;lt;/code&amp;gt; function multiplies the &amp;lt;code&amp;gt;latency&amp;lt;/code&amp;gt; input argument by two (&amp;lt;code&amp;gt;latency *= 2;&amp;lt;/code&amp;gt;); so if the printout says &amp;quot;&amp;lt;i&amp;gt;Trying latency 128 frames ...&amp;lt;/i&amp;gt;&amp;quot;, that means that &amp;lt;code&amp;gt;latency&amp;lt;/code&amp;gt; parameter is actually 64&amp;lt;/small&amp;gt;&lt;br /&gt;
** calls [http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gac6c33091b049985baa6466e8fe93917e snd_pcm_link] on the capture and playback stream file descriptors, to have them &amp;quot;&amp;lt;i&amp;gt;start/stop/prepare in sync&amp;lt;/i&amp;gt;&amp;quot;&lt;br /&gt;
** calls &amp;lt;code&amp;gt;snd_pcm_format_set_silence&amp;lt;/code&amp;gt;, and then&lt;br /&gt;
** calls &amp;lt;code&amp;gt;writebuf(phandle, buffer, latency ...)&amp;lt;/code&amp;gt; '''''twice'''''&lt;br /&gt;
*** &amp;lt;small&amp;gt;&amp;lt;i&amp;gt;Note:&amp;lt;/i&amp;gt; since the value of the variable &amp;lt;code&amp;gt;latency&amp;lt;/code&amp;gt; is twice smaller than what the printout &amp;quot;&amp;lt;i&amp;gt;Trying latency %li frames ...&amp;lt;/i&amp;gt;&amp;quot; says - calling &amp;lt;code&amp;gt;writebuf()&amp;lt;/code&amp;gt; twice, means that we ultimately achieve the demanded latency, as shown on the printout.&amp;lt;/small&amp;gt;&lt;br /&gt;
** starts yet another &amp;lt;code&amp;gt;while&amp;lt;/code&amp;gt; loop, where:&lt;br /&gt;
*** [http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gad4d53d58b996a7cd9a5cbf1710b90375 snd_pcm_wait] is called, if polling has been specified in the command line arguments;&lt;br /&gt;
*** &amp;lt;code&amp;gt;r = readbuf(chandle, buffer, latency, ...)&amp;lt;/code&amp;gt; is called on the capture stream&lt;br /&gt;
*** &amp;lt;code&amp;gt;writebuf(phandle, buffer, r, ...)&amp;lt;/code&amp;gt; is called on the playback stream&lt;br /&gt;
&lt;br /&gt;
See the source code for details of the &amp;lt;code&amp;gt;readbuf()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;writebuf()&amp;lt;/code&amp;gt; functions - which may involve loops of their own, but ultimately call &amp;lt;code&amp;gt;[http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#ga4c2c7bd26cf221268d59dc3bbeb9c048 snd_pcm_readi]&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gabc748a500743713eafa960c7d104ca6f snd_pcm_writei]&amp;lt;/code&amp;gt;, respectively.&lt;br /&gt;
&lt;br /&gt;
=== '''Mailing list notes''' ===&lt;br /&gt;
&lt;br /&gt;
[http://thread.gmane.org/gmane.linux.alsa.devel/17014 latency.c: some feature requests (alsa-devel)] (2004-11-28)&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; It looks like the playback runs 64 frames ahead of the capture.  Do you&lt;br /&gt;
&amp;gt; think this would be a problem from the application's perspective?&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's correct - it's the latency.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; I also need the capture device interleaved and the playback device&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; noninterleaved.  latency.c does not support this at all, it just assumes&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; that all hardware supports interleaved format.&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt; Use default device (-D default and -P default) which automatically&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt; uses available parameters.&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; This will not work because I need to use hw:0,3 for playback and hw:0,2&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for capture.&lt;br /&gt;
&amp;gt;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt; -P plughw:0,3 -C plughw:0,2&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; [...] One other thing I noticed is that latency.c doesn't mmap.&lt;br /&gt;
&amp;gt; This would cause higher latencies compared to testing with JACK,&lt;br /&gt;
&amp;gt; correct?&lt;br /&gt;
&lt;br /&gt;
Yes, it's good point. Perhaps, the snd_pcm_mmap_readi/writei functions&lt;br /&gt;
should be used to optimize copying.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://thread.gmane.org/gmane.linux.alsa.devel/37367 latency.c and delay related questions (alsa-devel)] (2006-06-20)&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; The current delay with &amp;quot;latency&amp;quot; is equal to a minimum (that depends&lt;br /&gt;
&amp;gt; on the sound card) plus *two* times the period time.  [...]&lt;br /&gt;
&lt;br /&gt;
Yes, it's correct. Basically, you cannot avoid double buffering, so the&lt;br /&gt;
total latency is:&lt;br /&gt;
&lt;br /&gt;
1) one capture period&lt;br /&gt;
2) one playback period (actually being played)&lt;br /&gt;
3) moved captured period to playback buffer (not counted)&lt;br /&gt;
&lt;br /&gt;
So the latency should be 2 * period plus a hw latency as you noted.&lt;br /&gt;
Everything is correct. Of course, you may get better latencies if you run&lt;br /&gt;
&amp;quot;busy loop&amp;quot; on not-loaded system and immediately put captured data to&lt;br /&gt;
playback stream, but it's not a correct behaviour in *nix.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; * why is snd_pcm_link() mandatory? (no sound otherwise)&lt;br /&gt;
&lt;br /&gt;
It links playback and capture streams so only one start() is called. On&lt;br /&gt;
hardware which supports hardware syncing, the DMA operation is started at&lt;br /&gt;
same time for both stream.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; * why two buffers of silence and not just one?&lt;br /&gt;
&lt;br /&gt;
You must wait one period to get data from the capture direction and then&lt;br /&gt;
you have exactly one period time to put these data to the playback. As I&lt;br /&gt;
said, you can get better results with busy-loop but it's bad&lt;br /&gt;
implementation (but if you have a spare dedicated machine without other&lt;br /&gt;
tasks, it might be an option).&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt; [...] The linking of capture and playback devices&lt;br /&gt;
&amp;gt; explains everything; if I remove linking and use snd_pcm_start() on&lt;br /&gt;
&amp;gt; the playback device I get the expected behaviour.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Here is a little drawing (requires fixed font) to illustrate what you&lt;br /&gt;
&amp;gt; have said and what I have understood (useless for you but some people&lt;br /&gt;
&amp;gt; like me might find it useful).&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; When capture and playback devices are linked, the following happens:&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Capture  | C0 | C1 | C2 | C3 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Playback | -- | -- | C0 | C1 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Capture and playback start simultaneously and so playback device needs&lt;br /&gt;
&amp;gt; something to play. When the first capture is finished, another is&lt;br /&gt;
&amp;gt; started. We would like to play the captured audio, but another&lt;br /&gt;
&amp;gt; playback has already started. Only after the latter is finished can&lt;br /&gt;
&amp;gt; the captured audio be played.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; This explains why the playback device needs two buffers of silence.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; The total delay is hw_delay + 2 * period&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exactly. Well explained.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; When the devices are not linked, we can start the playback device&lt;br /&gt;
&amp;gt; after the first buffer has been captured:&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Capture  | C0 | C1 | C2 | C3 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;                  +-----------------&lt;br /&gt;
&amp;gt; Playback         | C0 | C1 | C2 | .&lt;br /&gt;
&amp;gt;                  +-----------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Starting the playback device and copying data takes some time, so the&lt;br /&gt;
&amp;gt; total delay becomes hw_delay + 1 * period + start_delay + copy_delay.&lt;br /&gt;
&amp;gt; For large periods, with period &amp;gt; start_delay + copy_delay, this can&lt;br /&gt;
&amp;gt; lead to a lower latency, but who would use large periods for low&lt;br /&gt;
&amp;gt; latency?&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes, this buffering schema is also possible, but note that the time window&lt;br /&gt;
for the data copy must satisfy the system scheduler requirements and&lt;br /&gt;
capabilities to get continous playback. In the &amp;quot;stream linked&amp;quot; case this&lt;br /&gt;
time window is exactly one period time.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Meaning of --buffer and --period''' ===&lt;br /&gt;
&lt;br /&gt;
Given the specific operation of the program outlined above, note that:&lt;br /&gt;
&lt;br /&gt;
* The latency parameter, derived from &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt; parameters, ultimately translates to the PCM buffer_size&lt;br /&gt;
* Specifying &amp;lt;code&amp;gt;--buffer&amp;lt;/code&amp;gt; ultimately translates to the PCM period_size, and PCM buffer_size becomes 2x that - so we can consider it as a latency specification alternative to &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt;&lt;br /&gt;
* Specifying &amp;lt;code&amp;gt;--period&amp;lt;/code&amp;gt; does override the PCM period_size, leaving the PCM buffer_size untouched; however, the program will typically exit with an error, if the period_size happens to be not equal to buffer_size/2 and smaller than buffer_size/2 (for values &amp;gt;= buffer_size/2, the engine automatically limits period_size to buffer_size/2)&lt;br /&gt;
&lt;br /&gt;
The easiest way to observe that is to patch/add the following &amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt; statements to the &amp;lt;code&amp;gt;setparams_bufsize&amp;lt;/code&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
int setparams_bufsize(...)&lt;br /&gt;
{&lt;br /&gt;
	int err;&lt;br /&gt;
	snd_pcm_uframes_t periodsize;&lt;br /&gt;
&lt;br /&gt;
	snd_pcm_hw_params_copy(params, tparams);&lt;br /&gt;
	periodsize = bufsize * 2;&lt;br /&gt;
	printf(&amp;quot; spbf: in bufsize:%li ; periodsize %li for %s\n&amp;quot;, bufsize, periodsize, id); //added&lt;br /&gt;
	err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &amp;amp;periodsize);&lt;br /&gt;
	if (err &amp;lt; 0) {&lt;br /&gt;
		printf(&amp;quot;Unable to set buffer size %li for %s: %s\n&amp;quot;, bufsize * 2, id, snd_strerror(err));&lt;br /&gt;
		return err;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     ; set_buffer_size_near: %li for %s\n&amp;quot;, periodsize, id);                //added&lt;br /&gt;
	if (period_size &amp;gt; 0)&lt;br /&gt;
		periodsize = period_size;&lt;br /&gt;
	else&lt;br /&gt;
		periodsize /= 2;&lt;br /&gt;
	printf(&amp;quot;     ; now periodsize %li for %s\n&amp;quot;, periodsize, id);                       //added&lt;br /&gt;
	err = snd_pcm_hw_params_set_period_size_near(handle, params, &amp;amp;periodsize, 0);&lt;br /&gt;
	if (err &amp;lt; 0) {&lt;br /&gt;
		printf(&amp;quot;Unable to set period size %li for %s: %s\n&amp;quot;, periodsize, id, snd_strerror(err));&lt;br /&gt;
		return err;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     ; set_period_size_near: %li for %s\n&amp;quot;, periodsize, id);                //added&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
With this change, we can now observe the buffer/period size calculations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 64 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 64&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 64 frames, 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 32 frames&lt;br /&gt;
Maximum read latency: 725.624us, 0.725624ms (1378.1250Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 64 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 64 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 256 -M 256 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 256, maximum latency = 256&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for playback&lt;br /&gt;
     ; set_buffer_size_near: 256 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 128 for playback&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for capture&lt;br /&gt;
     ; set_buffer_size_near: 256 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 128 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 256 frames, 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 128 frames&lt;br /&gt;
Maximum read latency: 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
&lt;br /&gt;
# so, we have:&lt;br /&gt;
# -m 64 -M 64   -&amp;gt; buffer_size  : 64   -&amp;gt; Trying latency 64 frames&lt;br /&gt;
# -m 128 -M 128 -&amp;gt; buffer_size  : 128  -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# -m 256 -M 256 -&amp;gt; buffer_size  : 256  -&amp;gt; Trying latency 256 frames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 --buffer 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 4096&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for playback&lt;br /&gt;
     ; set_buffer_size_near: 256 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 128 for playback&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for capture&lt;br /&gt;
     ; set_buffer_size_near: 256 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 128 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 256 frames, 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 128 frames&lt;br /&gt;
Maximum read latency: 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 --buffer 256 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 4096&lt;br /&gt;
 spbf: in bufsize:256 ; periodsize 512 for playback&lt;br /&gt;
     ; set_buffer_size_near: 512 for playback&lt;br /&gt;
     ; now periodsize 256 for playback&lt;br /&gt;
     ; set_period_size_near: 256 for playback&lt;br /&gt;
 spbf: in bufsize:256 ; periodsize 512 for capture&lt;br /&gt;
     ; set_buffer_size_near: 512 for capture&lt;br /&gt;
     ; now periodsize 256 for capture&lt;br /&gt;
     ; set_period_size_near: 256 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 512&lt;br /&gt;
  period_size  : 256&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 512&lt;br /&gt;
  period_size  : 256&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 512 frames, 11609.977us, 11.609977ms (86.1328Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 256 frames&lt;br /&gt;
Maximum read latency: 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
&lt;br /&gt;
# so, we have:&lt;br /&gt;
# --buffer 128   -&amp;gt; buffer_size  : 256   -&amp;gt; Trying latency 256 frames&lt;br /&gt;
# --buffer 256   -&amp;gt; buffer_size  : 512   -&amp;gt; Trying latency 512 frames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 64 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 64 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 64 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 32 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
playback device does not support 2 periods per buffer&lt;br /&gt;
&lt;br /&gt;
# so, we have - for buffer_size/latency=128 (spec'd by -m 128 -M 128):&lt;br /&gt;
# --period 64   -&amp;gt; period_size  : 64    -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# --period 128  -&amp;gt; period_size  : 64    -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# --period 32   -&amp;gt; period_size  : 32    -&amp;gt; (error buffer_size != 2*period_size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;device does not support 2 periods per buffer&amp;quot; message comes from a revision to &amp;lt;code&amp;gt;latency.c&amp;lt;/code&amp;gt; from 2011-04-20; earlier versions will exit, but not print a message.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Algorithm locking''' ===&lt;br /&gt;
&lt;br /&gt;
Note that it is also possible to &amp;quot;lock&amp;quot; the program, especially if automatic latency increase is allowed by specifying different  &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt; options, and the very first run fails with an XRUN (which can happen often for small PCM period/buffer sizes).&lt;br /&gt;
&lt;br /&gt;
For instance, under Linux kernel 2.6.38 / ALSA 1.0.24.2, HDA Intel can typically lock with &amp;lt;code&amp;gt;-m 64 -M 128&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;-m 64 -M 128&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 64 frames, 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Failure&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 64 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 7448.736132319&lt;br /&gt;
  tstamp      : 7448.736189100&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 81&lt;br /&gt;
  avail_max   : 81&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 32 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 7448.736132319&lt;br /&gt;
  tstamp      : 7448.736301335&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 1&lt;br /&gt;
  avail_max   : 33&lt;br /&gt;
Maximum read: 32 frames&lt;br /&gt;
Maximum read latency: 725.624us, 0.725624ms (1378.1250Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
 spbf: in bufsize:36 ; periodsize 72 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:36 ; periodsize 72 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 72 frames, 1632.653us, 1.632653ms (612.5000Hz)&lt;br /&gt;
^C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, first the application is &amp;quot;Trying latency 64 frames&amp;quot;, experiences an XRUN there, and then repeats the process, this time &amp;quot;Trying latency 72 frames&amp;quot;. At this point, the application locks, and Ctrl-C needs to issued in the terminal to stop the application. Note that - in both cases - the engine decides on PCM buffer_size: 64, and period_size: 32 frames; regardless of what is specified as input latency.&lt;br /&gt;
&lt;br /&gt;
Note that if we piped the output to &amp;lt;code&amp;gt;grep&amp;lt;/code&amp;gt; also in the above example, similarly to previous examples - it is very likely that we would not observe the &amp;quot;Trying latency 72 frames ...&amp;quot; line.&lt;br /&gt;
&lt;br /&gt;
A quick debug would be to first run the program through &amp;lt;code&amp;gt;strace&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ strace ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
...&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
^C--- SIGINT (Interrupt) @ 0 (0) ---&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... which tells us that the program gets stuck on an &amp;lt;code&amp;gt;ioctl&amp;lt;/code&amp;gt; system call, repeatedly trying to complete it (and again, Ctrl-C needs to issued in the terminal to stop the application).&lt;br /&gt;
&lt;br /&gt;
To see more precisely where this problem occurs, we can run the program in the &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt; debugger; wait for it to lock - and when it does, we can issue Ctrl-C to break into the program, and then issue &amp;lt;code&amp;gt;bt&amp;lt;/code&amp;gt; to obtain a backtrace.&lt;br /&gt;
&lt;br /&gt;
It should be noted here that &amp;lt;code&amp;gt;alsa-lib/test/latency&amp;lt;/code&amp;gt; is actually a shell script, which loads the libraries built from the specific &amp;lt;code&amp;gt;alsa-lib/&amp;lt;/code&amp;gt; source folder; however, for &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt;, we need the actual executable, which is typically in &amp;lt;code&amp;gt;alsa-lib/test/.libs/lt-latency&amp;lt;/code&amp;gt; &amp;lt;i&amp;gt;or&amp;lt;/i&amp;gt; &amp;lt;code&amp;gt;alsa-lib/test/.libs/latency&amp;lt;/code&amp;gt; (not sure why this name can vary; the &amp;lt;code&amp;gt;lt-&amp;lt;/code&amp;gt; prefix is likely due to &amp;lt;code&amp;gt;ltmain.sh (GNU libtool)&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
So, the &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt; session would look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ gdb --args alsa-lib/test/.libs/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
GNU gdb (GDB) 7.3.50.20110806-cvs&lt;br /&gt;
...&lt;br /&gt;
Reading symbols from /path/to/alsa-lib/test/.libs/latency...done.&lt;br /&gt;
(gdb) r&lt;br /&gt;
...&lt;br /&gt;
...&lt;br /&gt;
Trying latency 72 frames, 1632.653us, 1.632653ms (612.5000Hz)&lt;br /&gt;
^C&lt;br /&gt;
Program received signal SIGINT, Interrupt.&lt;br /&gt;
0x0012e416 in __kernel_vsyscall ()&lt;br /&gt;
(gdb) bt&lt;br /&gt;
#0  0x0012e416 in __kernel_vsyscall ()&lt;br /&gt;
#1  0x002c97c9 in ioctl () from /lib/i386-linux-gnu/libc.so.6&lt;br /&gt;
#2  0x00182890 in ?? () from /usr/lib/libasound.so.2&lt;br /&gt;
#3  0x00171ac4 in snd_pcm_writei () from /usr/lib/libasound.so.2&lt;br /&gt;
#4  0x0804a23b in writebuf (handle=0x8056ed8, buf=0x804e0b8 &amp;quot;&amp;quot;, len=8, frames=0xbffff1bc) at latency.c:383&lt;br /&gt;
#5  0x0804ab8d in main (argc=14, argv=0xbffff294) at latency.c:639&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... which confirms that the failing &amp;lt;code&amp;gt;ioctl&amp;lt;/code&amp;gt; is due to a &amp;lt;code&amp;gt;snd_pcm_writei&amp;lt;/code&amp;gt; call.&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=Test_latency.c&amp;diff=6674</id>
		<title>Test latency.c</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=Test_latency.c&amp;diff=6674"/>
		<updated>2013-09-12T20:02:02Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: added quick overview section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__FORCETOC__&lt;br /&gt;
== test latency.c ==&lt;br /&gt;
&lt;br /&gt;
Within &amp;lt;code&amp;gt;alsa-lib&amp;lt;/code&amp;gt;, there is a utility, [http://git.alsa-project.org/?p=alsa-lib.git;a=blob;f=test/latency.c; test/latency.c]  ([http://git.alsa-project.org/?p=alsa-lib.git;a=history;f=test/latency.c; history]), which performs a full-duplex test, where recorded (captured) data is played back.&lt;br /&gt;
&lt;br /&gt;
From &amp;lt;code&amp;gt;alsa-lib/test/latency.c&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
 *  Latency test program&lt;br /&gt;
 *&lt;br /&gt;
 *  This small demo program can be used for measuring latency between&lt;br /&gt;
 *  capture and playback. This latency is measured from driver (diff when&lt;br /&gt;
 *  playback and capture was started). Scheduler is set to SCHED_RR.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Building''' ===&lt;br /&gt;
&lt;br /&gt;
The name of the executable has to be passed explicitly to the &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; command - via [http://thread.gmane.org/gmane.linux.alsa.devel/6746/focus=6750 Re: problem ragarding execution of Latency.c (alsa-devel)]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
cd alsa-lib/test&lt;br /&gt;
make latency&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Options''' ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -h&lt;br /&gt;
Usage: latency [OPTION]... [FILE]...&lt;br /&gt;
-h,--help      help&lt;br /&gt;
-P,--pdevice   playback device&lt;br /&gt;
-C,--cdevice   capture device&lt;br /&gt;
-m,--min       minimum latency in frames&lt;br /&gt;
-M,--max       maximum latency in frames&lt;br /&gt;
-F,--frames    frames to transfer&lt;br /&gt;
-f,--format    sample format&lt;br /&gt;
-c,--channels  channels&lt;br /&gt;
-r,--rate      rate&lt;br /&gt;
-B,--buffer    buffer size in frames&lt;br /&gt;
-E,--period    period size in frames&lt;br /&gt;
-s,--seconds   duration of test in seconds&lt;br /&gt;
-b,--block     block mode&lt;br /&gt;
-p,--poll      use poll (wait for event - reduces CPU usage)&lt;br /&gt;
-e,--effect    apply an effect (bandpass filter sweep)&lt;br /&gt;
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE&lt;br /&gt;
&lt;br /&gt;
Tip #1 (usable latency with large periods, non-blocking mode, good CPU usage,&lt;br /&gt;
        superb xrun prevention):&lt;br /&gt;
  latency -m 8192 -M 8192 -t 1 -p&lt;br /&gt;
Tip #2 (superb latency, non-blocking mode, but heavy CPU usage):&lt;br /&gt;
  latency -m 128 -M 128&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The option &amp;lt;code&amp;gt;-F,--frames&amp;lt;/code&amp;gt; seems not to be handled anywhere in the code, and as such has no effect.&lt;br /&gt;
* The &amp;quot;Tip #1&amp;quot; refers to an option &amp;lt;code&amp;gt;-t&amp;lt;/code&amp;gt; which doesn't exist - however, it is likely a typo for the option &amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt; for duration in seconds&lt;br /&gt;
* The option &amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt; for duration in seconds is an integer, and the lowest it can be set is 1 second; default if not specified is 30 seconds&lt;br /&gt;
* Before 2012-08-08, there is a bug where the short options &amp;lt;code&amp;gt;-B&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-E&amp;lt;/code&amp;gt; are not recognized (&amp;quot;invalid option&amp;quot;) - but the long options &amp;lt;code&amp;gt;--buffer&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;--period&amp;lt;/code&amp;gt; still work even then.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Usage''' ===&lt;br /&gt;
&lt;br /&gt;
When called, the &amp;lt;code&amp;gt;test/latency.c&amp;lt;/code&amp;gt; program will attemp to set period/buffer sizes based on the latency entered, starting from &amp;lt;code&amp;gt;-m,--min&amp;lt;/code&amp;gt; option (or the default minimum latency = 64 if not specified). If the run succeeds without errors with that setting, the program exits; otherwise, the latency is increased, and the run repeated - if the run is succesful here, then program exits, else the process continues until the &amp;lt;code&amp;gt;-M,--max&amp;lt;/code&amp;gt; latency is reached.&lt;br /&gt;
&lt;br /&gt;
Example of successful run on Linux kernel 2.6.38 / ALSA 1.0.24.2 with HDA Intel onboard PCI soundcard:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: Intel [HDA Intel], device 0: ALC269 Analog [ALC269 Analog]&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&lt;br /&gt;
$ alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
Success&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 44288 ***&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  trigger_time: 84416.108859821&lt;br /&gt;
  tstamp      : 84417.110319083&lt;br /&gt;
  delay       : 80&lt;br /&gt;
  avail       : 48&lt;br /&gt;
  avail_max   : 120&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 44160 ***&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  trigger_time: 84416.108859821&lt;br /&gt;
  tstamp      : 84417.110439490&lt;br /&gt;
  delay       : 9&lt;br /&gt;
  avail       : 9&lt;br /&gt;
  avail_max   : 65&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
Playback time = 84416.108859, Record time = 84416.108859, diff = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The message &amp;quot;&amp;lt;code&amp;gt;Scheduler set to Round Robin with priority 99 FAILED&amp;lt;/code&amp;gt;&amp;quot; can be avoided by running the program with &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (administrative privileges):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
[sudo] password for user:&lt;br /&gt;
Scheduler set to Round Robin with priority 99...&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The program can also fail, if the streams experience an XRUN; in that case, if &amp;lt;code&amp;gt;-m&amp;lt;/code&amp;gt; is set to be equal to &amp;lt;code&amp;gt;-M&amp;lt;/code&amp;gt;, the program will immediately exit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
Failure&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 38464 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 479.798093354&lt;br /&gt;
  tstamp      : 479.798185056&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 128&lt;br /&gt;
  avail_max   : 128&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 38400 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 479.798093354&lt;br /&gt;
  tstamp      : 479.798361196&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 9&lt;br /&gt;
  avail_max   : 73&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Quick overview''' ===&lt;br /&gt;
&lt;br /&gt;
In brief, the &amp;lt;code&amp;gt;latency.c&amp;lt;/code&amp;gt; program:&lt;br /&gt;
&lt;br /&gt;
* Parses the command line parameters/options, and sets the playback and capture stream properties according to them&lt;br /&gt;
* Starts a loop where (among other things) it:&lt;br /&gt;
** shows the current latency value, using the &amp;lt;code&amp;gt;showlatency()&amp;lt;/code&amp;gt; function - which ultimately prints the &amp;quot;&amp;lt;i&amp;gt;Trying latency %li frames ...&amp;lt;/i&amp;gt;&amp;quot; line&lt;br /&gt;
** calls [http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gac6c33091b049985baa6466e8fe93917e snd_pcm_link] on the capture and playback stream file descriptors, to have them &amp;quot;&amp;lt;i&amp;gt;start/stop/prepare in sync&amp;lt;/i&amp;gt;&amp;quot;&lt;br /&gt;
** calls &amp;lt;code&amp;gt;snd_pcm_format_set_silence&amp;lt;/code&amp;gt;, and then&lt;br /&gt;
** calls &amp;lt;code&amp;gt;writebuf(phandle, buffer, latency ...)&amp;lt;/code&amp;gt; '''''twice'''''&lt;br /&gt;
** starts yet another &amp;lt;code&amp;gt;while&amp;lt;/code&amp;gt; loop, where:&lt;br /&gt;
*** [http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gad4d53d58b996a7cd9a5cbf1710b90375 snd_pcm_wait] is called, if polling has been specified in the command line arguments;&lt;br /&gt;
*** &amp;lt;code&amp;gt;r = readbuf(chandle, buffer, latency, ...)&amp;lt;/code&amp;gt; is called on the capture stream&lt;br /&gt;
*** &amp;lt;code&amp;gt;writebuf(phandle, buffer, r, ...)&amp;lt;/code&amp;gt; is called on the playback stream&lt;br /&gt;
&lt;br /&gt;
See the source code for details of the &amp;lt;code&amp;gt;readbuf()&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;writebuf()&amp;lt;/code&amp;gt; functions - which may involve loops of their own, but ultimately call &amp;lt;code&amp;gt;[http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#ga4c2c7bd26cf221268d59dc3bbeb9c048 snd_pcm_readi]&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;[http://www.alsa-project.org/alsa-doc/alsa-lib/group___p_c_m.html#gabc748a500743713eafa960c7d104ca6f snd_pcm_writei]&amp;lt;/code&amp;gt;, respectively.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Mailing list notes''' ===&lt;br /&gt;
&lt;br /&gt;
[http://thread.gmane.org/gmane.linux.alsa.devel/17014 latency.c: some feature requests (alsa-devel)] (2004-11-28)&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; It looks like the playback runs 64 frames ahead of the capture.  Do you&lt;br /&gt;
&amp;gt; think this would be a problem from the application's perspective?&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's correct - it's the latency.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; I also need the capture device interleaved and the playback device&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; noninterleaved.  latency.c does not support this at all, it just assumes&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; that all hardware supports interleaved format.&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt; Use default device (-D default and -P default) which automatically&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt; uses available parameters.&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; This will not work because I need to use hw:0,3 for playback and hw:0,2&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for capture.&lt;br /&gt;
&amp;gt;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt; -P plughw:0,3 -C plughw:0,2&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; [...] One other thing I noticed is that latency.c doesn't mmap.&lt;br /&gt;
&amp;gt; This would cause higher latencies compared to testing with JACK,&lt;br /&gt;
&amp;gt; correct?&lt;br /&gt;
&lt;br /&gt;
Yes, it's good point. Perhaps, the snd_pcm_mmap_readi/writei functions&lt;br /&gt;
should be used to optimize copying.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://thread.gmane.org/gmane.linux.alsa.devel/37367 latency.c and delay related questions (alsa-devel)] (2006-06-20)&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; The current delay with &amp;quot;latency&amp;quot; is equal to a minimum (that depends&lt;br /&gt;
&amp;gt; on the sound card) plus *two* times the period time.  [...]&lt;br /&gt;
&lt;br /&gt;
Yes, it's correct. Basically, you cannot avoid double buffering, so the&lt;br /&gt;
total latency is:&lt;br /&gt;
&lt;br /&gt;
1) one capture period&lt;br /&gt;
2) one playback period (actually being played)&lt;br /&gt;
3) moved captured period to playback buffer (not counted)&lt;br /&gt;
&lt;br /&gt;
So the latency should be 2 * period plus a hw latency as you noted.&lt;br /&gt;
Everything is correct. Of course, you may get better latencies if you run&lt;br /&gt;
&amp;quot;busy loop&amp;quot; on not-loaded system and immediately put captured data to&lt;br /&gt;
playback stream, but it's not a correct behaviour in *nix.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; * why is snd_pcm_link() mandatory? (no sound otherwise)&lt;br /&gt;
&lt;br /&gt;
It links playback and capture streams so only one start() is called. On&lt;br /&gt;
hardware which supports hardware syncing, the DMA operation is started at&lt;br /&gt;
same time for both stream.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; * why two buffers of silence and not just one?&lt;br /&gt;
&lt;br /&gt;
You must wait one period to get data from the capture direction and then&lt;br /&gt;
you have exactly one period time to put these data to the playback. As I&lt;br /&gt;
said, you can get better results with busy-loop but it's bad&lt;br /&gt;
implementation (but if you have a spare dedicated machine without other&lt;br /&gt;
tasks, it might be an option).&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt; [...] The linking of capture and playback devices&lt;br /&gt;
&amp;gt; explains everything; if I remove linking and use snd_pcm_start() on&lt;br /&gt;
&amp;gt; the playback device I get the expected behaviour.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Here is a little drawing (requires fixed font) to illustrate what you&lt;br /&gt;
&amp;gt; have said and what I have understood (useless for you but some people&lt;br /&gt;
&amp;gt; like me might find it useful).&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; When capture and playback devices are linked, the following happens:&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Capture  | C0 | C1 | C2 | C3 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Playback | -- | -- | C0 | C1 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Capture and playback start simultaneously and so playback device needs&lt;br /&gt;
&amp;gt; something to play. When the first capture is finished, another is&lt;br /&gt;
&amp;gt; started. We would like to play the captured audio, but another&lt;br /&gt;
&amp;gt; playback has already started. Only after the latter is finished can&lt;br /&gt;
&amp;gt; the captured audio be played.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; This explains why the playback device needs two buffers of silence.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; The total delay is hw_delay + 2 * period&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exactly. Well explained.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; When the devices are not linked, we can start the playback device&lt;br /&gt;
&amp;gt; after the first buffer has been captured:&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Capture  | C0 | C1 | C2 | C3 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;                  +-----------------&lt;br /&gt;
&amp;gt; Playback         | C0 | C1 | C2 | .&lt;br /&gt;
&amp;gt;                  +-----------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Starting the playback device and copying data takes some time, so the&lt;br /&gt;
&amp;gt; total delay becomes hw_delay + 1 * period + start_delay + copy_delay.&lt;br /&gt;
&amp;gt; For large periods, with period &amp;gt; start_delay + copy_delay, this can&lt;br /&gt;
&amp;gt; lead to a lower latency, but who would use large periods for low&lt;br /&gt;
&amp;gt; latency?&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes, this buffering schema is also possible, but note that the time window&lt;br /&gt;
for the data copy must satisfy the system scheduler requirements and&lt;br /&gt;
capabilities to get continous playback. In the &amp;quot;stream linked&amp;quot; case this&lt;br /&gt;
time window is exactly one period time.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Meaning of --buffer and --period''' ===&lt;br /&gt;
&lt;br /&gt;
Given the specific operation of the program outlined above, note that:&lt;br /&gt;
&lt;br /&gt;
* The latency parameter, derived from &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt; parameters, ultimately translates to the PCM buffer_size&lt;br /&gt;
* Specifying &amp;lt;code&amp;gt;--buffer&amp;lt;/code&amp;gt; ultimately translates to the PCM period_size, and PCM buffer_size becomes 2x that - so we can consider it as a latency specification alternative to &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt;&lt;br /&gt;
* Specifying &amp;lt;code&amp;gt;--period&amp;lt;/code&amp;gt; does override the PCM period_size, leaving the PCM buffer_size untouched; however, the program will typically exit with an error, if the period_size happens to be not equal to buffer_size/2 and smaller than buffer_size/2 (for values &amp;gt;= buffer_size/2, the engine automatically limits period_size to buffer_size/2)&lt;br /&gt;
&lt;br /&gt;
The easiest way to observe that is to patch/add the following &amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt; statements to the &amp;lt;code&amp;gt;setparams_bufsize&amp;lt;/code&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
int setparams_bufsize(...)&lt;br /&gt;
{&lt;br /&gt;
	int err;&lt;br /&gt;
	snd_pcm_uframes_t periodsize;&lt;br /&gt;
&lt;br /&gt;
	snd_pcm_hw_params_copy(params, tparams);&lt;br /&gt;
	periodsize = bufsize * 2;&lt;br /&gt;
	printf(&amp;quot; spbf: in bufsize:%li ; periodsize %li for %s\n&amp;quot;, bufsize, periodsize, id); //added&lt;br /&gt;
	err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &amp;amp;periodsize);&lt;br /&gt;
	if (err &amp;lt; 0) {&lt;br /&gt;
		printf(&amp;quot;Unable to set buffer size %li for %s: %s\n&amp;quot;, bufsize * 2, id, snd_strerror(err));&lt;br /&gt;
		return err;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     ; set_buffer_size_near: %li for %s\n&amp;quot;, periodsize, id);                //added&lt;br /&gt;
	if (period_size &amp;gt; 0)&lt;br /&gt;
		periodsize = period_size;&lt;br /&gt;
	else&lt;br /&gt;
		periodsize /= 2;&lt;br /&gt;
	printf(&amp;quot;     ; now periodsize %li for %s\n&amp;quot;, periodsize, id);                       //added&lt;br /&gt;
	err = snd_pcm_hw_params_set_period_size_near(handle, params, &amp;amp;periodsize, 0);&lt;br /&gt;
	if (err &amp;lt; 0) {&lt;br /&gt;
		printf(&amp;quot;Unable to set period size %li for %s: %s\n&amp;quot;, periodsize, id, snd_strerror(err));&lt;br /&gt;
		return err;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     ; set_period_size_near: %li for %s\n&amp;quot;, periodsize, id);                //added&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
With this change, we can now observe the buffer/period size calculations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 64 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 64&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 64 frames, 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 32 frames&lt;br /&gt;
Maximum read latency: 725.624us, 0.725624ms (1378.1250Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 64 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 64 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 256 -M 256 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 256, maximum latency = 256&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for playback&lt;br /&gt;
     ; set_buffer_size_near: 256 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 128 for playback&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for capture&lt;br /&gt;
     ; set_buffer_size_near: 256 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 128 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 256 frames, 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 128 frames&lt;br /&gt;
Maximum read latency: 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
&lt;br /&gt;
# so, we have:&lt;br /&gt;
# -m 64 -M 64   -&amp;gt; buffer_size  : 64   -&amp;gt; Trying latency 64 frames&lt;br /&gt;
# -m 128 -M 128 -&amp;gt; buffer_size  : 128  -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# -m 256 -M 256 -&amp;gt; buffer_size  : 256  -&amp;gt; Trying latency 256 frames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 --buffer 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 4096&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for playback&lt;br /&gt;
     ; set_buffer_size_near: 256 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 128 for playback&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for capture&lt;br /&gt;
     ; set_buffer_size_near: 256 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 128 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 256 frames, 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 128 frames&lt;br /&gt;
Maximum read latency: 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 --buffer 256 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 4096&lt;br /&gt;
 spbf: in bufsize:256 ; periodsize 512 for playback&lt;br /&gt;
     ; set_buffer_size_near: 512 for playback&lt;br /&gt;
     ; now periodsize 256 for playback&lt;br /&gt;
     ; set_period_size_near: 256 for playback&lt;br /&gt;
 spbf: in bufsize:256 ; periodsize 512 for capture&lt;br /&gt;
     ; set_buffer_size_near: 512 for capture&lt;br /&gt;
     ; now periodsize 256 for capture&lt;br /&gt;
     ; set_period_size_near: 256 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 512&lt;br /&gt;
  period_size  : 256&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 512&lt;br /&gt;
  period_size  : 256&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 512 frames, 11609.977us, 11.609977ms (86.1328Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 256 frames&lt;br /&gt;
Maximum read latency: 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
&lt;br /&gt;
# so, we have:&lt;br /&gt;
# --buffer 128   -&amp;gt; buffer_size  : 256   -&amp;gt; Trying latency 256 frames&lt;br /&gt;
# --buffer 256   -&amp;gt; buffer_size  : 512   -&amp;gt; Trying latency 512 frames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 64 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 64 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 64 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 32 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
playback device does not support 2 periods per buffer&lt;br /&gt;
&lt;br /&gt;
# so, we have - for buffer_size/latency=128 (spec'd by -m 128 -M 128):&lt;br /&gt;
# --period 64   -&amp;gt; period_size  : 64    -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# --period 128  -&amp;gt; period_size  : 64    -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# --period 32   -&amp;gt; period_size  : 32    -&amp;gt; (error buffer_size != 2*period_size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;device does not support 2 periods per buffer&amp;quot; message comes from a revision to &amp;lt;code&amp;gt;latency.c&amp;lt;/code&amp;gt; from 2011-04-20; earlier versions will exit, but not print a message.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Algorithm locking''' ===&lt;br /&gt;
&lt;br /&gt;
Note that it is also possible to &amp;quot;lock&amp;quot; the program, especially if automatic latency increase is allowed by specifying different  &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt; options, and the very first run fails with an XRUN (which can happen often for small PCM period/buffer sizes).&lt;br /&gt;
&lt;br /&gt;
For instance, under Linux kernel 2.6.38 / ALSA 1.0.24.2, HDA Intel can typically lock with &amp;lt;code&amp;gt;-m 64 -M 128&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;-m 64 -M 128&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 64 frames, 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Failure&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 64 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 7448.736132319&lt;br /&gt;
  tstamp      : 7448.736189100&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 81&lt;br /&gt;
  avail_max   : 81&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 32 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 7448.736132319&lt;br /&gt;
  tstamp      : 7448.736301335&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 1&lt;br /&gt;
  avail_max   : 33&lt;br /&gt;
Maximum read: 32 frames&lt;br /&gt;
Maximum read latency: 725.624us, 0.725624ms (1378.1250Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
 spbf: in bufsize:36 ; periodsize 72 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:36 ; periodsize 72 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 72 frames, 1632.653us, 1.632653ms (612.5000Hz)&lt;br /&gt;
^C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, first the application is &amp;quot;Trying latency 64 frames&amp;quot;, experiences an XRUN there, and then repeats the process, this time &amp;quot;Trying latency 72 frames&amp;quot;. At this point, the application locks, and Ctrl-C needs to issued in the terminal to stop the application. Note that - in both cases - the engine decides on PCM buffer_size: 64, and period_size: 32 frames; regardless of what is specified as input latency.&lt;br /&gt;
&lt;br /&gt;
Note that if we piped the output to &amp;lt;code&amp;gt;grep&amp;lt;/code&amp;gt; also in the above example, similarly to previous examples - it is very likely that we would not observe the &amp;quot;Trying latency 72 frames ...&amp;quot; line.&lt;br /&gt;
&lt;br /&gt;
A quick debug would be to first run the program through &amp;lt;code&amp;gt;strace&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ strace ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
...&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
^C--- SIGINT (Interrupt) @ 0 (0) ---&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... which tells us that the program gets stuck on an &amp;lt;code&amp;gt;ioctl&amp;lt;/code&amp;gt; system call, repeatedly trying to complete it (and again, Ctrl-C needs to issued in the terminal to stop the application).&lt;br /&gt;
&lt;br /&gt;
To see more precisely where this problem occurs, we can run the program in the &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt; debugger; wait for it to lock - and when it does, we can issue Ctrl-C to break into the program, and then issue &amp;lt;code&amp;gt;bt&amp;lt;/code&amp;gt; to obtain a backtrace.&lt;br /&gt;
&lt;br /&gt;
It should be noted here that &amp;lt;code&amp;gt;alsa-lib/test/latency&amp;lt;/code&amp;gt; is actually a shell script, which loads the libraries built from the specific &amp;lt;code&amp;gt;alsa-lib/&amp;lt;/code&amp;gt; source folder; however, for &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt;, we need the actual executable, which is typically in &amp;lt;code&amp;gt;alsa-lib/test/.libs/lt-latency&amp;lt;/code&amp;gt; &amp;lt;i&amp;gt;or&amp;lt;/i&amp;gt; &amp;lt;code&amp;gt;alsa-lib/test/.libs/latency&amp;lt;/code&amp;gt; (not sure why this name can vary; the &amp;lt;code&amp;gt;lt-&amp;lt;/code&amp;gt; prefix is likely due to &amp;lt;code&amp;gt;ltmain.sh (GNU libtool)&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
So, the &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt; session would look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ gdb --args alsa-lib/test/.libs/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
GNU gdb (GDB) 7.3.50.20110806-cvs&lt;br /&gt;
...&lt;br /&gt;
Reading symbols from /path/to/alsa-lib/test/.libs/latency...done.&lt;br /&gt;
(gdb) r&lt;br /&gt;
...&lt;br /&gt;
...&lt;br /&gt;
Trying latency 72 frames, 1632.653us, 1.632653ms (612.5000Hz)&lt;br /&gt;
^C&lt;br /&gt;
Program received signal SIGINT, Interrupt.&lt;br /&gt;
0x0012e416 in __kernel_vsyscall ()&lt;br /&gt;
(gdb) bt&lt;br /&gt;
#0  0x0012e416 in __kernel_vsyscall ()&lt;br /&gt;
#1  0x002c97c9 in ioctl () from /lib/i386-linux-gnu/libc.so.6&lt;br /&gt;
#2  0x00182890 in ?? () from /usr/lib/libasound.so.2&lt;br /&gt;
#3  0x00171ac4 in snd_pcm_writei () from /usr/lib/libasound.so.2&lt;br /&gt;
#4  0x0804a23b in writebuf (handle=0x8056ed8, buf=0x804e0b8 &amp;quot;&amp;quot;, len=8, frames=0xbffff1bc) at latency.c:383&lt;br /&gt;
#5  0x0804ab8d in main (argc=14, argv=0xbffff294) at latency.c:639&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... which confirms that the failing &amp;lt;code&amp;gt;ioctl&amp;lt;/code&amp;gt; is due to a &amp;lt;code&amp;gt;snd_pcm_writei&amp;lt;/code&amp;gt; call.&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=Test_latency.c&amp;diff=6671</id>
		<title>Test latency.c</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=Test_latency.c&amp;diff=6671"/>
		<updated>2013-08-18T11:06:52Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: inited page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;__FORCETOC__&lt;br /&gt;
== test latency.c ==&lt;br /&gt;
&lt;br /&gt;
Within &amp;lt;code&amp;gt;alsa-lib&amp;lt;/code&amp;gt;, there is a utility, [http://git.alsa-project.org/?p=alsa-lib.git;a=blob;f=test/latency.c; test/latency.c]  ([http://git.alsa-project.org/?p=alsa-lib.git;a=history;f=test/latency.c; history]), which performs a full-duplex test, where recorded (captured) data is played back.&lt;br /&gt;
&lt;br /&gt;
From &amp;lt;code&amp;gt;alsa-lib/test/latency.c&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
 *  Latency test program&lt;br /&gt;
 *&lt;br /&gt;
 *  This small demo program can be used for measuring latency between&lt;br /&gt;
 *  capture and playback. This latency is measured from driver (diff when&lt;br /&gt;
 *  playback and capture was started). Scheduler is set to SCHED_RR.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Building''' ===&lt;br /&gt;
&lt;br /&gt;
The name of the executable has to be passed explicitly to the &amp;lt;code&amp;gt;make&amp;lt;/code&amp;gt; command - via [http://thread.gmane.org/gmane.linux.alsa.devel/6746/focus=6750 Re: problem ragarding execution of Latency.c (alsa-devel)]:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
cd alsa-lib/test&lt;br /&gt;
make latency&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Options''' ===&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -h&lt;br /&gt;
Usage: latency [OPTION]... [FILE]...&lt;br /&gt;
-h,--help      help&lt;br /&gt;
-P,--pdevice   playback device&lt;br /&gt;
-C,--cdevice   capture device&lt;br /&gt;
-m,--min       minimum latency in frames&lt;br /&gt;
-M,--max       maximum latency in frames&lt;br /&gt;
-F,--frames    frames to transfer&lt;br /&gt;
-f,--format    sample format&lt;br /&gt;
-c,--channels  channels&lt;br /&gt;
-r,--rate      rate&lt;br /&gt;
-B,--buffer    buffer size in frames&lt;br /&gt;
-E,--period    period size in frames&lt;br /&gt;
-s,--seconds   duration of test in seconds&lt;br /&gt;
-b,--block     block mode&lt;br /&gt;
-p,--poll      use poll (wait for event - reduces CPU usage)&lt;br /&gt;
-e,--effect    apply an effect (bandpass filter sweep)&lt;br /&gt;
Recognized sample formats are: S8 U8 S16_LE S16_BE U16_LE U16_BE S24_LE S24_BE U24_LE U24_BE S32_LE S32_BE U32_LE U32_BE FLOAT_LE FLOAT_BE FLOAT64_LE FLOAT64_BE IEC958_SUBFRAME_LE IEC958_SUBFRAME_BE MU_LAW A_LAW IMA_ADPCM MPEG GSM SPECIAL S24_3LE S24_3BE U24_3LE U24_3BE S20_3LE S20_3BE U20_3LE U20_3BE S18_3LE S18_3BE U18_3LE&lt;br /&gt;
&lt;br /&gt;
Tip #1 (usable latency with large periods, non-blocking mode, good CPU usage,&lt;br /&gt;
        superb xrun prevention):&lt;br /&gt;
  latency -m 8192 -M 8192 -t 1 -p&lt;br /&gt;
Tip #2 (superb latency, non-blocking mode, but heavy CPU usage):&lt;br /&gt;
  latency -m 128 -M 128&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Notes:&lt;br /&gt;
* The option &amp;lt;code&amp;gt;-F,--frames&amp;lt;/code&amp;gt; seems not to be handled anywhere in the code, and as such has no effect.&lt;br /&gt;
* The &amp;quot;Tip #1&amp;quot; refers to an option &amp;lt;code&amp;gt;-t&amp;lt;/code&amp;gt; which doesn't exist - however, it is likely a typo for the option &amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt; for duration in seconds&lt;br /&gt;
* The option &amp;lt;code&amp;gt;-s&amp;lt;/code&amp;gt; for duration in seconds is an integer, and the lowest it can be set is 1 second; default if not specified is 30 seconds&lt;br /&gt;
* Before 2012-08-08, there is a bug where the short options &amp;lt;code&amp;gt;-B&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-E&amp;lt;/code&amp;gt; are not recognized (&amp;quot;invalid option&amp;quot;) - but the long options &amp;lt;code&amp;gt;--buffer&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;--period&amp;lt;/code&amp;gt; still work even then.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Usage''' ===&lt;br /&gt;
&lt;br /&gt;
When called, the &amp;lt;code&amp;gt;test/latency.c&amp;lt;/code&amp;gt; program will attemp to set period/buffer sizes based on the latency entered, starting from &amp;lt;code&amp;gt;-m,--min&amp;lt;/code&amp;gt; option (or the default minimum latency = 64 if not specified). If the run succeeds without errors with that setting, the program exits; otherwise, the latency is increased, and the run repeated - if the run is succesful here, then program exits, else the process continues until the &amp;lt;code&amp;gt;-M,--max&amp;lt;/code&amp;gt; latency is reached.&lt;br /&gt;
&lt;br /&gt;
Example of successful run on Linux kernel 2.6.38 / ALSA 1.0.24.2 with HDA Intel onboard PCI soundcard:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ aplay -l&lt;br /&gt;
**** List of PLAYBACK Hardware Devices ****&lt;br /&gt;
card 0: Intel [HDA Intel], device 0: ALC269 Analog [ALC269 Analog]&lt;br /&gt;
  Subdevices: 1/1&lt;br /&gt;
  Subdevice #0: subdevice #0&lt;br /&gt;
&lt;br /&gt;
$ alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
Success&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 44288 ***&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  trigger_time: 84416.108859821&lt;br /&gt;
  tstamp      : 84417.110319083&lt;br /&gt;
  delay       : 80&lt;br /&gt;
  avail       : 48&lt;br /&gt;
  avail_max   : 120&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 44160 ***&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  trigger_time: 84416.108859821&lt;br /&gt;
  tstamp      : 84417.110439490&lt;br /&gt;
  delay       : 9&lt;br /&gt;
  avail       : 9&lt;br /&gt;
  avail_max   : 65&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
Playback time = 84416.108859, Record time = 84416.108859, diff = 0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The message &amp;quot;&amp;lt;code&amp;gt;Scheduler set to Round Robin with priority 99 FAILED&amp;lt;/code&amp;gt;&amp;quot; can be avoided by running the program with &amp;lt;code&amp;gt;sudo&amp;lt;/code&amp;gt; (administrative privileges):&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ sudo alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
[sudo] password for user:&lt;br /&gt;
Scheduler set to Round Robin with priority 99...&lt;br /&gt;
...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
The program can also fail, if the streams experience an XRUN; in that case, if &amp;lt;code&amp;gt;-m&amp;lt;/code&amp;gt; is set to be equal to &amp;lt;code&amp;gt;-M&amp;lt;/code&amp;gt;, the program will immediately exit:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ alsa-lib/test/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  period_time  : 1451&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 64&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 128&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
Failure&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 38464 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 479.798093354&lt;br /&gt;
  tstamp      : 479.798185056&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 128&lt;br /&gt;
  avail_max   : 128&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 38400 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 479.798093354&lt;br /&gt;
  tstamp      : 479.798361196&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 9&lt;br /&gt;
  avail_max   : 73&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Mailing list notes''' ===&lt;br /&gt;
&lt;br /&gt;
[http://thread.gmane.org/gmane.linux.alsa.devel/17014 latency.c: some feature requests (alsa-devel)] (2004-11-28)&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; It looks like the playback runs 64 frames ahead of the capture.  Do you&lt;br /&gt;
&amp;gt; think this would be a problem from the application's perspective?&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
That's correct - it's the latency.&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; I also need the capture device interleaved and the playback device&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; noninterleaved.  latency.c does not support this at all, it just assumes&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt;&amp;gt; that all hardware supports interleaved format.&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt; Use default device (-D default and -P default) which automatically&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&amp;gt; uses available parameters.&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; This will not work because I need to use hw:0,3 for playback and hw:0,2&lt;br /&gt;
&amp;gt;&amp;gt;&amp;gt; for capture.&lt;br /&gt;
&amp;gt;&amp;gt;&lt;br /&gt;
&amp;gt;&amp;gt; -P plughw:0,3 -C plughw:0,2&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; [...] One other thing I noticed is that latency.c doesn't mmap.&lt;br /&gt;
&amp;gt; This would cause higher latencies compared to testing with JACK,&lt;br /&gt;
&amp;gt; correct?&lt;br /&gt;
&lt;br /&gt;
Yes, it's good point. Perhaps, the snd_pcm_mmap_readi/writei functions&lt;br /&gt;
should be used to optimize copying.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
[http://thread.gmane.org/gmane.linux.alsa.devel/37367 latency.c and delay related questions (alsa-devel)] (2006-06-20)&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; The current delay with &amp;quot;latency&amp;quot; is equal to a minimum (that depends&lt;br /&gt;
&amp;gt; on the sound card) plus *two* times the period time.  [...]&lt;br /&gt;
&lt;br /&gt;
Yes, it's correct. Basically, you cannot avoid double buffering, so the&lt;br /&gt;
total latency is:&lt;br /&gt;
&lt;br /&gt;
1) one capture period&lt;br /&gt;
2) one playback period (actually being played)&lt;br /&gt;
3) moved captured period to playback buffer (not counted)&lt;br /&gt;
&lt;br /&gt;
So the latency should be 2 * period plus a hw latency as you noted.&lt;br /&gt;
Everything is correct. Of course, you may get better latencies if you run&lt;br /&gt;
&amp;quot;busy loop&amp;quot; on not-loaded system and immediately put captured data to&lt;br /&gt;
playback stream, but it's not a correct behaviour in *nix.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; * why is snd_pcm_link() mandatory? (no sound otherwise)&lt;br /&gt;
&lt;br /&gt;
It links playback and capture streams so only one start() is called. On&lt;br /&gt;
hardware which supports hardware syncing, the DMA operation is started at&lt;br /&gt;
same time for both stream.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; * why two buffers of silence and not just one?&lt;br /&gt;
&lt;br /&gt;
You must wait one period to get data from the capture direction and then&lt;br /&gt;
you have exactly one period time to put these data to the playback. As I&lt;br /&gt;
said, you can get better results with busy-loop but it's bad&lt;br /&gt;
implementation (but if you have a spare dedicated machine without other&lt;br /&gt;
tasks, it might be an option).&lt;br /&gt;
&lt;br /&gt;
-----&lt;br /&gt;
&lt;br /&gt;
&amp;gt; [...] The linking of capture and playback devices&lt;br /&gt;
&amp;gt; explains everything; if I remove linking and use snd_pcm_start() on&lt;br /&gt;
&amp;gt; the playback device I get the expected behaviour.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Here is a little drawing (requires fixed font) to illustrate what you&lt;br /&gt;
&amp;gt; have said and what I have understood (useless for you but some people&lt;br /&gt;
&amp;gt; like me might find it useful).&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; When capture and playback devices are linked, the following happens:&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Capture  | C0 | C1 | C2 | C3 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Playback | -- | -- | C0 | C1 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Capture and playback start simultaneously and so playback device needs&lt;br /&gt;
&amp;gt; something to play. When the first capture is finished, another is&lt;br /&gt;
&amp;gt; started. We would like to play the captured audio, but another&lt;br /&gt;
&amp;gt; playback has already started. Only after the latter is finished can&lt;br /&gt;
&amp;gt; the captured audio be played.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; This explains why the playback device needs two buffers of silence.&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; The total delay is hw_delay + 2 * period&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Exactly. Well explained.&lt;br /&gt;
&lt;br /&gt;
&amp;gt; When the devices are not linked, we can start the playback device&lt;br /&gt;
&amp;gt; after the first buffer has been captured:&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt; Capture  | C0 | C1 | C2 | C3 | ...&lt;br /&gt;
&amp;gt;          +-------------------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt;                  +-----------------&lt;br /&gt;
&amp;gt; Playback         | C0 | C1 | C2 | .&lt;br /&gt;
&amp;gt;                  +-----------------&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&amp;gt; Starting the playback device and copying data takes some time, so the&lt;br /&gt;
&amp;gt; total delay becomes hw_delay + 1 * period + start_delay + copy_delay.&lt;br /&gt;
&amp;gt; For large periods, with period &amp;gt; start_delay + copy_delay, this can&lt;br /&gt;
&amp;gt; lead to a lower latency, but who would use large periods for low&lt;br /&gt;
&amp;gt; latency?&lt;br /&gt;
&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Yes, this buffering schema is also possible, but note that the time window&lt;br /&gt;
for the data copy must satisfy the system scheduler requirements and&lt;br /&gt;
capabilities to get continous playback. In the &amp;quot;stream linked&amp;quot; case this&lt;br /&gt;
time window is exactly one period time.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Meaning of --buffer and --period''' ===&lt;br /&gt;
&lt;br /&gt;
Given the specific operation of the program outlined above, note that:&lt;br /&gt;
&lt;br /&gt;
* The latency parameter, derived from &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt; parameters, ultimately translates to the PCM buffer_size&lt;br /&gt;
* Specifying &amp;lt;code&amp;gt;--buffer&amp;lt;/code&amp;gt; ultimately translates to the PCM period_size, and PCM buffer_size becomes 2x that - so we can consider it as a latency specification alternative to &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt;&lt;br /&gt;
* Specifying &amp;lt;code&amp;gt;--period&amp;lt;/code&amp;gt; does override the PCM period_size, leaving the PCM buffer_size untouched; however, the program will typically exit with an error, if the period_size happens to be not equal to buffer_size/2 and smaller than buffer_size/2 (for values &amp;gt;= buffer_size/2, the engine automatically limits period_size to buffer_size/2)&lt;br /&gt;
&lt;br /&gt;
The easiest way to observe that is to patch/add the following &amp;lt;code&amp;gt;printf&amp;lt;/code&amp;gt; statements to the &amp;lt;code&amp;gt;setparams_bufsize&amp;lt;/code&amp;gt; function:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
int setparams_bufsize(...)&lt;br /&gt;
{&lt;br /&gt;
	int err;&lt;br /&gt;
	snd_pcm_uframes_t periodsize;&lt;br /&gt;
&lt;br /&gt;
	snd_pcm_hw_params_copy(params, tparams);&lt;br /&gt;
	periodsize = bufsize * 2;&lt;br /&gt;
	printf(&amp;quot; spbf: in bufsize:%li ; periodsize %li for %s\n&amp;quot;, bufsize, periodsize, id); //added&lt;br /&gt;
	err = snd_pcm_hw_params_set_buffer_size_near(handle, params, &amp;amp;periodsize);&lt;br /&gt;
	if (err &amp;lt; 0) {&lt;br /&gt;
		printf(&amp;quot;Unable to set buffer size %li for %s: %s\n&amp;quot;, bufsize * 2, id, snd_strerror(err));&lt;br /&gt;
		return err;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     ; set_buffer_size_near: %li for %s\n&amp;quot;, periodsize, id);                //added&lt;br /&gt;
	if (period_size &amp;gt; 0)&lt;br /&gt;
		periodsize = period_size;&lt;br /&gt;
	else&lt;br /&gt;
		periodsize /= 2;&lt;br /&gt;
	printf(&amp;quot;     ; now periodsize %li for %s\n&amp;quot;, periodsize, id);                       //added&lt;br /&gt;
	err = snd_pcm_hw_params_set_period_size_near(handle, params, &amp;amp;periodsize, 0);&lt;br /&gt;
	if (err &amp;lt; 0) {&lt;br /&gt;
		printf(&amp;quot;Unable to set period size %li for %s: %s\n&amp;quot;, periodsize, id, snd_strerror(err));&lt;br /&gt;
		return err;&lt;br /&gt;
	}&lt;br /&gt;
	printf(&amp;quot;     ; set_period_size_near: %li for %s\n&amp;quot;, periodsize, id);                //added&lt;br /&gt;
	return 0;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
With this change, we can now observe the buffer/period size calculations:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 64 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 64&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 64 frames, 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 32 frames&lt;br /&gt;
Maximum read latency: 725.624us, 0.725624ms (1378.1250Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 64 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 64 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 256 -M 256 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 256, maximum latency = 256&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for playback&lt;br /&gt;
     ; set_buffer_size_near: 256 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 128 for playback&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for capture&lt;br /&gt;
     ; set_buffer_size_near: 256 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 128 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 256 frames, 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 128 frames&lt;br /&gt;
Maximum read latency: 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
&lt;br /&gt;
# so, we have:&lt;br /&gt;
# -m 64 -M 64   -&amp;gt; buffer_size  : 64   -&amp;gt; Trying latency 64 frames&lt;br /&gt;
# -m 128 -M 128 -&amp;gt; buffer_size  : 128  -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# -m 256 -M 256 -&amp;gt; buffer_size  : 256  -&amp;gt; Trying latency 256 frames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 --buffer 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 4096&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for playback&lt;br /&gt;
     ; set_buffer_size_near: 256 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 128 for playback&lt;br /&gt;
 spbf: in bufsize:128 ; periodsize 256 for capture&lt;br /&gt;
     ; set_buffer_size_near: 256 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 128 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 256&lt;br /&gt;
  period_size  : 128&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 256 frames, 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 128 frames&lt;br /&gt;
Maximum read latency: 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 --buffer 256 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 4096&lt;br /&gt;
 spbf: in bufsize:256 ; periodsize 512 for playback&lt;br /&gt;
     ; set_buffer_size_near: 512 for playback&lt;br /&gt;
     ; now periodsize 256 for playback&lt;br /&gt;
     ; set_period_size_near: 256 for playback&lt;br /&gt;
 spbf: in bufsize:256 ; periodsize 512 for capture&lt;br /&gt;
     ; set_buffer_size_near: 512 for capture&lt;br /&gt;
     ; now periodsize 256 for capture&lt;br /&gt;
     ; set_period_size_near: 256 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 512&lt;br /&gt;
  period_size  : 256&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 512&lt;br /&gt;
  period_size  : 256&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 512 frames, 11609.977us, 11.609977ms (86.1328Hz)&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
  state       : RUNNING&lt;br /&gt;
Maximum read: 256 frames&lt;br /&gt;
Maximum read latency: 5804.989us, 5.804989ms (172.2656Hz)&lt;br /&gt;
&lt;br /&gt;
# so, we have:&lt;br /&gt;
# --buffer 128   -&amp;gt; buffer_size  : 256   -&amp;gt; Trying latency 256 frames&lt;br /&gt;
# --buffer 256   -&amp;gt; buffer_size  : 512   -&amp;gt; Trying latency 512 frames&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 64 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 64 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 64 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 128 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 128 for playback&lt;br /&gt;
     ; set_period_size_near: 64 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 128 for capture&lt;br /&gt;
     ; set_period_size_near: 64 for capture&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  buffer_size  : 128&lt;br /&gt;
  period_size  : 64&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
Trying latency 128 frames, 2902.494us, 2.902494ms (344.5312Hz)&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
Maximum read: 64 frames&lt;br /&gt;
Maximum read latency: 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 128 -M 128 --period 32 -p -s 1 | grep 'size\|Trying\|limit\|state\|stream\|Max\|support'&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 128, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for playback&lt;br /&gt;
     ; set_buffer_size_near: 128 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:64 ; periodsize 128 for capture&lt;br /&gt;
     ; set_buffer_size_near: 128 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
playback device does not support 2 periods per buffer&lt;br /&gt;
&lt;br /&gt;
# so, we have - for buffer_size/latency=128 (spec'd by -m 128 -M 128):&lt;br /&gt;
# --period 64   -&amp;gt; period_size  : 64    -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# --period 128  -&amp;gt; period_size  : 64    -&amp;gt; Trying latency 128 frames&lt;br /&gt;
# --period 32   -&amp;gt; period_size  : 32    -&amp;gt; (error buffer_size != 2*period_size)&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that the &amp;quot;device does not support 2 periods per buffer&amp;quot; message comes from a revision to &amp;lt;code&amp;gt;latency.c&amp;lt;/code&amp;gt; from 2011-04-20; earlier versions will exit, but not print a message.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
=== '''Algorithm locking''' ===&lt;br /&gt;
&lt;br /&gt;
Note that it is also possible to &amp;quot;lock&amp;quot; the program, especially if automatic latency increase is allowed by specifying different  &amp;lt;code&amp;gt;-m/--min&amp;lt;/code&amp;gt; and &amp;lt;code&amp;gt;-M/--max&amp;lt;/code&amp;gt; options, and the very first run fails with an XRUN (which can happen often for small PCM period/buffer sizes).&lt;br /&gt;
&lt;br /&gt;
For instance, under Linux kernel 2.6.38 / ALSA 1.0.24.2, HDA Intel can typically lock with &amp;lt;code&amp;gt;-m 64 -M 128&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;-m 64 -M 128&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
!!!Scheduler set to Round Robin with priority 99 FAILED!!!&lt;br /&gt;
Playback device is hw:0,0&lt;br /&gt;
Capture device is hw:0,0&lt;br /&gt;
Parameters are 44100Hz, S16_LE, 2 channels, non-blocking mode&lt;br /&gt;
Poll mode: yes&lt;br /&gt;
Loop limit is 44100 frames, minimum latency = 64, maximum latency = 128&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:32 ; periodsize 64 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 64 frames, 1451.247us, 1.451247ms (689.0625Hz)&lt;br /&gt;
Failure&lt;br /&gt;
Playback:&lt;br /&gt;
*** frames = 64 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 7448.736132319&lt;br /&gt;
  tstamp      : 7448.736189100&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 81&lt;br /&gt;
  avail_max   : 81&lt;br /&gt;
Capture:&lt;br /&gt;
*** frames = 32 ***&lt;br /&gt;
  state       : XRUN&lt;br /&gt;
  trigger_time: 7448.736132319&lt;br /&gt;
  tstamp      : 7448.736301335&lt;br /&gt;
  delay       : 0&lt;br /&gt;
  avail       : 1&lt;br /&gt;
  avail_max   : 33&lt;br /&gt;
Maximum read: 32 frames&lt;br /&gt;
Maximum read latency: 725.624us, 0.725624ms (1378.1250Hz)&lt;br /&gt;
Hardware sync&lt;br /&gt;
 spbf: in bufsize:36 ; periodsize 72 for playback&lt;br /&gt;
     ; set_buffer_size_near: 64 for playback&lt;br /&gt;
     ; now periodsize 32 for playback&lt;br /&gt;
     ; set_period_size_near: 32 for playback&lt;br /&gt;
 spbf: in bufsize:36 ; periodsize 72 for capture&lt;br /&gt;
     ; set_buffer_size_near: 64 for capture&lt;br /&gt;
     ; now periodsize 32 for capture&lt;br /&gt;
     ; set_period_size_near: 32 for capture&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : PLAYBACK&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Hardware PCM card 0 'HDA Intel' device 0 subdevice 0&lt;br /&gt;
Its setup is:&lt;br /&gt;
  stream       : CAPTURE&lt;br /&gt;
  access       : RW_INTERLEAVED&lt;br /&gt;
  format       : S16_LE&lt;br /&gt;
  subformat    : STD&lt;br /&gt;
  channels     : 2&lt;br /&gt;
  rate         : 44100&lt;br /&gt;
  exact rate   : 44100 (44100/1)&lt;br /&gt;
  msbits       : 16&lt;br /&gt;
  buffer_size  : 64&lt;br /&gt;
  period_size  : 32&lt;br /&gt;
  period_time  : 725&lt;br /&gt;
  tstamp_mode  : NONE&lt;br /&gt;
  period_step  : 1&lt;br /&gt;
  avail_min    : 32&lt;br /&gt;
  period_event : 0&lt;br /&gt;
  start_threshold  : 2147483647&lt;br /&gt;
  stop_threshold   : 64&lt;br /&gt;
  silence_threshold: 0&lt;br /&gt;
  silence_size : 0&lt;br /&gt;
  boundary     : 1073741824&lt;br /&gt;
  appl_ptr     : 0&lt;br /&gt;
  hw_ptr       : 0&lt;br /&gt;
Trying latency 72 frames, 1632.653us, 1.632653ms (612.5000Hz)&lt;br /&gt;
^C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
So, first the application is &amp;quot;Trying latency 64 frames&amp;quot;, experiences an XRUN there, and then repeats the process, this time &amp;quot;Trying latency 72 frames&amp;quot;. At this point, the application locks, and Ctrl-C needs to issued in the terminal to stop the application. Note that - in both cases - the engine decides on PCM buffer_size: 64, and period_size: 32 frames; regardless of what is specified as input latency.&lt;br /&gt;
&lt;br /&gt;
Note that if we piped the output to &amp;lt;code&amp;gt;grep&amp;lt;/code&amp;gt; also in the above example, similarly to previous examples - it is very likely that we would not observe the &amp;quot;Trying latency 72 frames ...&amp;quot; line.&lt;br /&gt;
&lt;br /&gt;
A quick debug would be to first run the program through &amp;lt;code&amp;gt;strace&amp;lt;/code&amp;gt;:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ strace ./latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
...&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
ioctl(4, 0x400c4150, 0xbfc7f6c8)        = -1 EAGAIN (Resource temporarily unavailable)&lt;br /&gt;
^C--- SIGINT (Interrupt) @ 0 (0) ---&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... which tells us that the program gets stuck on an &amp;lt;code&amp;gt;ioctl&amp;lt;/code&amp;gt; system call, repeatedly trying to complete it (and again, Ctrl-C needs to issued in the terminal to stop the application).&lt;br /&gt;
&lt;br /&gt;
To see more precisely where this problem occurs, we can run the program in the &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt; debugger; wait for it to lock - and when it does, we can issue Ctrl-C to break into the program, and then issue &amp;lt;code&amp;gt;bt&amp;lt;/code&amp;gt; to obtain a backtrace.&lt;br /&gt;
&lt;br /&gt;
It should be noted here that &amp;lt;code&amp;gt;alsa-lib/test/latency&amp;lt;/code&amp;gt; is actually a shell script, which loads the libraries built from the specific &amp;lt;code&amp;gt;alsa-lib/&amp;lt;/code&amp;gt; source folder; however, for &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt;, we need the actual executable, which is typically in &amp;lt;code&amp;gt;alsa-lib/test/.libs/lt-latency&amp;lt;/code&amp;gt; &amp;lt;i&amp;gt;or&amp;lt;/i&amp;gt; &amp;lt;code&amp;gt;alsa-lib/test/.libs/latency&amp;lt;/code&amp;gt; (not sure why this name can vary; the &amp;lt;code&amp;gt;lt-&amp;lt;/code&amp;gt; prefix is likely due to &amp;lt;code&amp;gt;ltmain.sh (GNU libtool)&amp;lt;/code&amp;gt;).&lt;br /&gt;
&lt;br /&gt;
So, the &amp;lt;code&amp;gt;gdb&amp;lt;/code&amp;gt; session would look like this:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;small&amp;gt;&amp;lt;pre&amp;gt;&lt;br /&gt;
$ gdb --args alsa-lib/test/.libs/latency -P hw:0,0 -C hw:0,0 -r 44100 -m 64 -M 128 -p -s 1&lt;br /&gt;
GNU gdb (GDB) 7.3.50.20110806-cvs&lt;br /&gt;
...&lt;br /&gt;
Reading symbols from /path/to/alsa-lib/test/.libs/latency...done.&lt;br /&gt;
(gdb) r&lt;br /&gt;
...&lt;br /&gt;
...&lt;br /&gt;
Trying latency 72 frames, 1632.653us, 1.632653ms (612.5000Hz)&lt;br /&gt;
^C&lt;br /&gt;
Program received signal SIGINT, Interrupt.&lt;br /&gt;
0x0012e416 in __kernel_vsyscall ()&lt;br /&gt;
(gdb) bt&lt;br /&gt;
#0  0x0012e416 in __kernel_vsyscall ()&lt;br /&gt;
#1  0x002c97c9 in ioctl () from /lib/i386-linux-gnu/libc.so.6&lt;br /&gt;
#2  0x00182890 in ?? () from /usr/lib/libasound.so.2&lt;br /&gt;
#3  0x00171ac4 in snd_pcm_writei () from /usr/lib/libasound.so.2&lt;br /&gt;
#4  0x0804a23b in writebuf (handle=0x8056ed8, buf=0x804e0b8 &amp;quot;&amp;quot;, len=8, frames=0xbffff1bc) at latency.c:383&lt;br /&gt;
#5  0x0804ab8d in main (argc=14, argv=0xbffff294) at latency.c:639&lt;br /&gt;
&amp;lt;/pre&amp;gt;&amp;lt;/small&amp;gt;&lt;br /&gt;
&lt;br /&gt;
... which confirms that the failing &amp;lt;code&amp;gt;ioctl&amp;lt;/code&amp;gt; is due to a &amp;lt;code&amp;gt;snd_pcm_writei&amp;lt;/code&amp;gt; call.&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc-pavucontrol.png&amp;diff=6337</id>
		<title>File:Minivosc-pavucontrol.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc-pavucontrol.png&amp;diff=6337"/>
		<updated>2012-04-23T07:54:13Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: Minivosc with `pavucontrol` volume applet from `pulseaudio`; ( image processed with: pngquant 256 minivosc-pavucontrol_orig.png ; pngcrush -rem gAMA -rem cHRM -rem iCCP -force -bkgd 255 255 255 minivosc-pavucontrol_orig-fs8.png minivosc-pavucontrol.png )&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Minivosc with `pavucontrol` volume applet from `pulseaudio`; ( image processed with: pngquant 256 minivosc-pavucontrol_orig.png ; pngcrush -rem gAMA -rem cHRM -rem iCCP -force -bkgd 255 255 255 minivosc-pavucontrol_orig-fs8.png minivosc-pavucontrol.png )&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc-gnome-volume.png&amp;diff=6336</id>
		<title>File:Minivosc-gnome-volume.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc-gnome-volume.png&amp;diff=6336"/>
		<updated>2012-04-23T07:45:03Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: gnome-volume-control in Ubuntu 11.04 with minivosc - with and without pulseaudio&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;gnome-volume-control in Ubuntu 11.04 with minivosc - with and without pulseaudio&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=User:Sdaau/Monobook.js&amp;diff=2240</id>
		<title>User:Sdaau/Monobook.js</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=User:Sdaau/Monobook.js&amp;diff=2240"/>
		<updated>2010-11-05T02:21:12Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: New page: // Install InstaView document.write('&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://www.alsa-project.org/main/index.php/User:Sdaau/instaview.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&amp;amp;dontcountme=s&amp;quot;&amp;gt;...&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// Install InstaView&lt;br /&gt;
document.write('&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://www.alsa-project.org/main/index.php/User:Sdaau/instaview.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&amp;amp;dontcountme=s&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
InstaView.conf.user.name = 'Sdaau';&lt;br /&gt;
&lt;br /&gt;
/* This is to keep track of who is using InstaView: [[User:Pilaf/instaview.js]] */&lt;br /&gt;
&lt;br /&gt;
/************ OLD STUFF *************&lt;br /&gt;
&lt;br /&gt;
// Live Preview customization,&lt;br /&gt;
// edit this to your own liking.&lt;br /&gt;
&lt;br /&gt;
wpUserName   = 'Pilaf';   // User name to display in signatures&lt;br /&gt;
wpShowImages = true;      // Enable downloading and displaying of images&lt;br /&gt;
&lt;br /&gt;
// Include Live Preview...&lt;br /&gt;
document.write('&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://en.wikipedia.org/w/index.php?title=User:Pilaf/livepreview.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&amp;amp;dontcountme=s&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
// Now set everything up&lt;br /&gt;
window.onload = Main;&lt;br /&gt;
&lt;br /&gt;
function Main()&lt;br /&gt;
{&lt;br /&gt;
 LivePreviewInstall();&lt;br /&gt;
 // You may include here other &amp;quot;extensions&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
*/&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=User:Sdaau/monobook.js&amp;diff=2239</id>
		<title>User:Sdaau/monobook.js</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=User:Sdaau/monobook.js&amp;diff=2239"/>
		<updated>2010-11-05T02:11:46Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// Install InstaView&lt;br /&gt;
document.write('&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://www.alsa-project.org/main/index.php/User:Sdaau/instaview.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&amp;amp;dontcountme=s&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
InstaView.conf.user.name = 'Sdaau';&lt;br /&gt;
&lt;br /&gt;
/* This is to keep track of who is using InstaView: [[User:Pilaf/instaview.js]] */&lt;br /&gt;
&lt;br /&gt;
/************ OLD STUFF *************&lt;br /&gt;
&lt;br /&gt;
// Live Preview customization,&lt;br /&gt;
// edit this to your own liking.&lt;br /&gt;
&lt;br /&gt;
wpUserName   = 'Pilaf';   // User name to display in signatures&lt;br /&gt;
wpShowImages = true;      // Enable downloading and displaying of images&lt;br /&gt;
&lt;br /&gt;
// Include Live Preview...&lt;br /&gt;
document.write('&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://en.wikipedia.org/w/index.php?title=User:Pilaf/livepreview.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&amp;amp;dontcountme=s&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
// Now set everything up&lt;br /&gt;
window.onload = Main;&lt;br /&gt;
&lt;br /&gt;
function Main()&lt;br /&gt;
{&lt;br /&gt;
 LivePreviewInstall();&lt;br /&gt;
 // You may include here other &amp;quot;extensions&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
*/&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=User:Sdaau/monobook.css&amp;diff=2238</id>
		<title>User:Sdaau/monobook.css</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=User:Sdaau/monobook.css&amp;diff=2238"/>
		<updated>2010-11-05T02:10:30Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: New page: #content { background: red !important; }&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;#content { background: red !important; }&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=User:Sdaau/instaview.js&amp;diff=2237</id>
		<title>User:Sdaau/instaview.js</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=User:Sdaau/instaview.js&amp;diff=2237"/>
		<updated>2010-11-05T02:07:24Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: added instaview.js&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// Last update: Cacycle 22:26, 22 November 2008 (UTC)&lt;br /&gt;
// &amp;lt;nowiki&amp;gt;&lt;br /&gt;
&lt;br /&gt;
// Script to embed InstaView in MediaWiki's edit page&lt;br /&gt;
addOnloadHook(function(){&lt;br /&gt;
  if (document.getElementById('editpage-copywarn')) {&lt;br /&gt;
    var oldPreview = document.getElementById('wpPreview');&lt;br /&gt;
    var newPreview = document.createElement('input');&lt;br /&gt;
    newPreview.setAttribute('type', 'button');&lt;br /&gt;
    newPreview.setAttribute('style', 'font-style: italic');&lt;br /&gt;
    newPreview.setAttribute('value', 'InstaView');&lt;br /&gt;
    newPreview.setAttribute('id', 'InstaView');&lt;br /&gt;
    newPreview.setAttribute('name', 'InstaView');&lt;br /&gt;
    newPreview.setAttribute('onclick', &amp;quot;InstaView.dump('wpTextbox1', 'InstaViewDump')&amp;quot;);&lt;br /&gt;
    oldPreview.parentNode.insertBefore(newPreview, oldPreview);&lt;br /&gt;
    oldPreview.parentNode.innerHTML += '&amp;lt;div style=&amp;quot;margin: 5px 0 5px 0; padding: 5px; border: 2px solid orange;&amp;quot; id=&amp;quot;InstaViewDump&amp;quot;&amp;gt;&amp;lt;/div&amp;gt;';&lt;br /&gt;
    oldPreview.value = 'Classic Preview';&lt;br /&gt;
    }&lt;br /&gt;
});&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * InstaView - a Mediawiki to HTML converter in JavaScript&lt;br /&gt;
 * Version 0.6.1&lt;br /&gt;
 * Copyright (C) Pedro Fayolle 2005-2006&lt;br /&gt;
 * http://en.wikipedia.org/wiki/User:Pilaf&lt;br /&gt;
 * Distributed under the BSD license&lt;br /&gt;
 *&lt;br /&gt;
 * Changelog:&lt;br /&gt;
 *&lt;br /&gt;
 * 0.6.1&lt;br /&gt;
 * - Fixed problem caused by \r characters&lt;br /&gt;
 * - Improved inline formatting parser&lt;br /&gt;
 *&lt;br /&gt;
 * 0.6&lt;br /&gt;
 * - Changed name to InstaView&lt;br /&gt;
 * - Some major code reorganizations and factored out some common functions&lt;br /&gt;
 * - Handled conversion of relative links (i.e. [[/foo]])&lt;br /&gt;
 * - Fixed misrendering of adjacent definition list items&lt;br /&gt;
 * - Fixed bug in table headings handling&lt;br /&gt;
 * - Changed date format in signatures to reflect Mediawiki's&lt;br /&gt;
 * - Fixed handling of [[:Image:...]]&lt;br /&gt;
 * - Updated MD5 function (hopefully it will work with UTF-8)&lt;br /&gt;
 * - Fixed bug in handling of links inside images&lt;br /&gt;
 *&lt;br /&gt;
 * To do:&lt;br /&gt;
 * - Better support for &amp;lt;math&amp;gt;&lt;br /&gt;
 * - Full support for &amp;lt;nowiki&amp;gt;&lt;br /&gt;
 * - Parser-based (as opposed to RegExp-based) inline wikicode handling (make it one-pass and bullet-proof)&lt;br /&gt;
 * - Support for templates (through AJAX)&lt;br /&gt;
 * - Support for coloured links (AJAX)&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
var InstaView = {}&lt;br /&gt;
&lt;br /&gt;
// options&lt;br /&gt;
InstaView.conf =&lt;br /&gt;
{&lt;br /&gt;
	user: {},&lt;br /&gt;
	&lt;br /&gt;
	wiki: {&lt;br /&gt;
		lang: 'en',&lt;br /&gt;
		interwiki: 'ab|aa|af|ak|sq|als|am|ang|ar|an|arc|hy|roa-rup|as|ast|av|ay|az|bm|ba|eu|be|bn|bh|bi|bs|br|bg|my|ca|ch|ce|chr|chy|ny|zh|zh-tw|zh-cn|cho|cv|kw|co|cr|hr|cs|da|dv|nl|dz|en|eo|et|ee|fo|fj|fi|fr|fy|ff|gl|ka|de|got|el|kl|gn|gu|ht|ha|haw|he|hz|hi|ho|hu|is|io|ig|id|ia|ie|iu|ik|ga|it|ja|jv|kn|kr|csb|ks|kk|km|ki|rw|rn|tlh|kv|kg|ko|kj|ku|ky|lo|la|lv|li|ln|lt|jbo|nds|lg|lb|mk|mg|ms|ml|mt|gv|mi|minnan|mr|mh|zh-min-nan|mo|mn|mus|nah|na|nv|ne|se|no|nn|oc|or|om|pi|fa|pl|pt|pa|ps|qu|ro|rm|ru|sm|sg|sa|sc|gd|sr|sh|st|tn|sn|scn|simple|sd|si|sk|sl|so|st|es|su|sw|ss|sv|tl|ty|tg|ta|tt|te|th|bo|ti|tpi|to|tokipona|ts|tum|tr|tk|tw|uk|ur|ug|uz|ve|vi|vo|wa|cy|wo|xh|ii|yi|yo|za|zu',&lt;br /&gt;
		default_thumb_width: 180&lt;br /&gt;
	},&lt;br /&gt;
	&lt;br /&gt;
	paths: {&lt;br /&gt;
		articles: '/wiki/',&lt;br /&gt;
		math: '/math/',&lt;br /&gt;
		images: '',&lt;br /&gt;
		images_fallback: 'http://upload.wikimedia.org/wikipedia/commons/',&lt;br /&gt;
		magnify_icon: 'skins/common/images/magnify-clip.png'&lt;br /&gt;
	},&lt;br /&gt;
	&lt;br /&gt;
	locale: {&lt;br /&gt;
		user: 'User',&lt;br /&gt;
		image: 'Image',&lt;br /&gt;
		category: 'Category',&lt;br /&gt;
		months: ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec']&lt;br /&gt;
	}&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// options with default values or backreferences&lt;br /&gt;
with (InstaView.conf) {&lt;br /&gt;
	user.name = user.name || 'Wikipedian'&lt;br /&gt;
	user.signature = '[['+locale.user+':'+user.name+'|'+user.name+']]'&lt;br /&gt;
	paths.images = 'http://upload.wikimedia.org/wikipedia/' + wiki.lang + '/'&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// define constants&lt;br /&gt;
InstaView.BLOCK_IMAGE = new RegExp('^\\[\\['+InstaView.conf.locale.image+':.*?\\|.*?(?:frame|thumbnail|thumb|none|right|left|center)', 'i');&lt;br /&gt;
&lt;br /&gt;
InstaView.dump = function(from, to)&lt;br /&gt;
{&lt;br /&gt;
	if (typeof from == 'string') from = document.getElementById(from)&lt;br /&gt;
	if (typeof to == 'string') to = document.getElementById(to)&lt;br /&gt;
	to.innerHTML = this.convert(from.value)&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
InstaView.convert = function(wiki)&lt;br /&gt;
{&lt;br /&gt;
	var 	ll = (typeof wiki == 'string')? wiki.replace(/\r/g,'').split(/\n/): wiki, // lines of wikicode&lt;br /&gt;
		o='',	// output&lt;br /&gt;
		p=0,	// para flag&lt;br /&gt;
		$r	// result of passing a regexp to $()&lt;br /&gt;
	&lt;br /&gt;
	// some shorthands&lt;br /&gt;
	function remain() { return ll.length }&lt;br /&gt;
	function sh() { return ll.shift() } // shift&lt;br /&gt;
	function ps(s) { o+=s } // push&lt;br /&gt;
	&lt;br /&gt;
	function f() // similar to C's printf, uses ? as placeholders, ?? to escape question marks&lt;br /&gt;
	{&lt;br /&gt;
		var i=1,a=arguments,f=a[0],o='',c,p&lt;br /&gt;
		for (;i&amp;lt;a.length; i++) if ((p=f.indexOf('?'))+1) {&lt;br /&gt;
			// allow character escaping&lt;br /&gt;
			i -= c=f.charAt(p+1)=='?'?1:0&lt;br /&gt;
			o += f.substring(0,p)+(c?'?':a[i])&lt;br /&gt;
			f=f.substr(p+1+c)&lt;br /&gt;
		} else break;&lt;br /&gt;
		return o+f&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function html_entities(s) { return s.replace(/&amp;amp;/g,&amp;quot;&amp;amp;amp;&amp;quot;).replace(/&amp;lt;/g,&amp;quot;&amp;amp;lt;&amp;quot;).replace(/&amp;gt;/g,&amp;quot;&amp;amp;gt;&amp;quot;) }&lt;br /&gt;
	&lt;br /&gt;
	function max(a,b) { return (a&amp;gt;b)?a:b }&lt;br /&gt;
	function min(a,b) { return (a&amp;lt;b)?a:b }&lt;br /&gt;
	&lt;br /&gt;
	// return the first non matching character position between two strings&lt;br /&gt;
	function str_imatch(a, b)&lt;br /&gt;
	{&lt;br /&gt;
		for (var i=0, l=min(a.length, b.length); i&amp;lt;l; i++) if (a.charAt(i)!=b.charAt(i)) break&lt;br /&gt;
		return i&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// compare current line against a string or regexp&lt;br /&gt;
	// if passed a string it will compare only the first string.length characters&lt;br /&gt;
	// if passed a regexp the result is stored in $r&lt;br /&gt;
	function $(c) { return (typeof c == 'string') ? (ll[0].substr(0,c.length)==c) : ($r = ll[0].match(c)) }&lt;br /&gt;
	&lt;br /&gt;
	function $$(c) { return ll[0]==c } // compare current line against a string&lt;br /&gt;
	function _(p) { return ll[0].charAt(p) } // return char at pos p&lt;br /&gt;
	&lt;br /&gt;
	function endl(s) { ps(s); sh() }&lt;br /&gt;
	&lt;br /&gt;
	function parse_list()&lt;br /&gt;
	{&lt;br /&gt;
		var prev='';&lt;br /&gt;
		&lt;br /&gt;
		while (remain() &amp;amp;&amp;amp; $(/^([*#:;]+)(.*)$/)) {&lt;br /&gt;
			&lt;br /&gt;
			var l_match = $r&lt;br /&gt;
			&lt;br /&gt;
			sh()&lt;br /&gt;
			&lt;br /&gt;
			var ipos = str_imatch(prev, l_match[1])&lt;br /&gt;
			&lt;br /&gt;
			// close uncontinued lists&lt;br /&gt;
			for (var i=prev.length-1; i &amp;gt;= ipos; i--) {&lt;br /&gt;
				&lt;br /&gt;
				var pi = prev.charAt(i)&lt;br /&gt;
				&lt;br /&gt;
				if (pi=='*') ps('&amp;lt;/ul&amp;gt;')&lt;br /&gt;
				else if (pi=='#') ps('&amp;lt;/ol&amp;gt;')&lt;br /&gt;
				// close a dl only if the new item is not a dl item (:, ; or empty)&lt;br /&gt;
				else switch (l_match[1].charAt(i)) { case'':case'*':case'#': ps('&amp;lt;/dl&amp;gt;') }&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			// open new lists&lt;br /&gt;
			for (var i=ipos; i&amp;lt;l_match[1].length; i++) {&lt;br /&gt;
				&lt;br /&gt;
				var li = l_match[1].charAt(i)&lt;br /&gt;
				&lt;br /&gt;
				if (li=='*') ps('&amp;lt;ul&amp;gt;')&lt;br /&gt;
				else if (li=='#') ps('&amp;lt;ol&amp;gt;')&lt;br /&gt;
				// open a new dl only if the prev item is not a dl item (:, ; or empty)&lt;br /&gt;
				else switch(prev.charAt(i)) { case'':case'*':case'#': ps('&amp;lt;dl&amp;gt;') }&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			switch (l_match[1].charAt(l_match[1].length-1)) {&lt;br /&gt;
			&lt;br /&gt;
				case '*': case '#':&lt;br /&gt;
					ps('&amp;lt;li&amp;gt;' + parse_inline_nowiki(l_match[2])); break&lt;br /&gt;
					&lt;br /&gt;
				case ';':&lt;br /&gt;
					ps('&amp;lt;dt&amp;gt;')&lt;br /&gt;
					&lt;br /&gt;
					var dt_match&lt;br /&gt;
					&lt;br /&gt;
					// handle ;dt :dd format&lt;br /&gt;
					if (dt_match = l_match[2].match(/(.*?) (:.*?)$/)) {&lt;br /&gt;
						&lt;br /&gt;
						ps(parse_inline_nowiki(dt_match[1]))&lt;br /&gt;
						ll.unshift(dt_match[2])&lt;br /&gt;
						&lt;br /&gt;
					} else ps(parse_inline_nowiki(l_match[2]))&lt;br /&gt;
					&lt;br /&gt;
					break&lt;br /&gt;
					&lt;br /&gt;
				case ':':&lt;br /&gt;
					ps('&amp;lt;dd&amp;gt;' + parse_inline_nowiki(l_match[2]))&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			prev=l_match[1]&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		// close remaining lists&lt;br /&gt;
		for (var i=prev.length-1; i&amp;gt;=0; i--)&lt;br /&gt;
			ps(f('&amp;lt;/?&amp;gt;', (prev.charAt(i)=='*')? 'ul': ((prev.charAt(i)=='#')? 'ol': 'dl')))&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function parse_table()&lt;br /&gt;
	{&lt;br /&gt;
		endl(f('&amp;lt;table?&amp;gt;', $(/^\{\|( .*)$/)? $r[1]: ''))&lt;br /&gt;
		&lt;br /&gt;
		for (;remain();) if ($('|')) switch (_(1)) {&lt;br /&gt;
			case '}': endl('&amp;lt;/table&amp;gt;'); return&lt;br /&gt;
			case '-': endl(f('&amp;lt;tr ?&amp;gt;', $(/\|-*(.*)/)[1])); break&lt;br /&gt;
			default: parse_table_data()&lt;br /&gt;
		}&lt;br /&gt;
		else if ($('!')) parse_table_data()&lt;br /&gt;
		else sh()&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function parse_table_data()&lt;br /&gt;
	{&lt;br /&gt;
		var td_line, match_i&lt;br /&gt;
		&lt;br /&gt;
		// 1: &amp;quot;|+&amp;quot;, '|' or '+'&lt;br /&gt;
		// 2: ??&lt;br /&gt;
		// 3: attributes ??&lt;br /&gt;
		// TODO: finish commenting this regexp&lt;br /&gt;
		var td_match = sh().match(/^(\|\+|\||!)((?:([^[|]*?)\|(?!\|))?(.*))$/)&lt;br /&gt;
		&lt;br /&gt;
		if (td_match[1] == '|+') ps('&amp;lt;caption');&lt;br /&gt;
		else ps('&amp;lt;t' + ((td_match[1]=='|')?'d':'h'))&lt;br /&gt;
		&lt;br /&gt;
		if (typeof td_match[3] != 'undefined') {&lt;br /&gt;
			&lt;br /&gt;
			ps(' ' + td_match[3])&lt;br /&gt;
			match_i = 4&lt;br /&gt;
			&lt;br /&gt;
		} else match_i = 2&lt;br /&gt;
		&lt;br /&gt;
		ps('&amp;gt;')&lt;br /&gt;
		&lt;br /&gt;
		if (td_match[1] != '|+') {&lt;br /&gt;
			&lt;br /&gt;
			// use || or !! as a cell separator depending on context&lt;br /&gt;
			// NOTE: when split() is passed a regexp make sure to use non-capturing brackets&lt;br /&gt;
			td_line = td_match[match_i].split((td_match[1] == '|')? '||': /(?:\|\||!!)/)&lt;br /&gt;
			&lt;br /&gt;
			ps(parse_inline_nowiki(td_line.shift()))&lt;br /&gt;
			&lt;br /&gt;
			while (td_line.length) ll.unshift(td_match[1] + td_line.pop())&lt;br /&gt;
			&lt;br /&gt;
		} else ps(td_match[match_i])&lt;br /&gt;
		&lt;br /&gt;
		var tc = 0, td = []&lt;br /&gt;
		&lt;br /&gt;
		for (;remain(); td.push(sh()))&lt;br /&gt;
		if ($('|')) {&lt;br /&gt;
			if (!tc) break // we're at the outer-most level (no nested tables), skip to td parse&lt;br /&gt;
			else if (_(1)=='}') tc--&lt;br /&gt;
		}&lt;br /&gt;
		else if (!tc &amp;amp;&amp;amp; $('!')) break&lt;br /&gt;
		else if ($('{|')) tc++&lt;br /&gt;
		&lt;br /&gt;
		if (td.length) ps(InstaView.convert(td))&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function parse_pre()&lt;br /&gt;
	{&lt;br /&gt;
		ps('&amp;lt;pre&amp;gt;')&lt;br /&gt;
		do endl(parse_inline_nowiki(ll[0].substring(1)) + &amp;quot;\n&amp;quot;); while (remain() &amp;amp;&amp;amp; $(' '))&lt;br /&gt;
		ps('&amp;lt;/pre&amp;gt;')&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function parse_block_image()&lt;br /&gt;
	{&lt;br /&gt;
		ps(parse_image(sh()))&lt;br /&gt;
	}&lt;br /&gt;
&lt;br /&gt;
	function parse_image(str)&lt;br /&gt;
	{&lt;br /&gt;
		// get what's in between &amp;quot;[[Image:&amp;quot; and &amp;quot;]]&amp;quot;&lt;br /&gt;
		var tag = str.substring(InstaView.conf.locale.image.length + 3, str.length - 2);&lt;br /&gt;
		&lt;br /&gt;
		var width;&lt;br /&gt;
		var attr = [], filename, caption = '';&lt;br /&gt;
		var thumb=0, frame=0, center=0;&lt;br /&gt;
		var align='';&lt;br /&gt;
		&lt;br /&gt;
		if (tag.match(/\|/)) {&lt;br /&gt;
			// manage nested links&lt;br /&gt;
			var nesting = 0;&lt;br /&gt;
			var last_attr;&lt;br /&gt;
			for (var i = tag.length-1; i &amp;gt; 0; i--) {&lt;br /&gt;
				if (tag.charAt(i) == '|' &amp;amp;&amp;amp; !nesting) {&lt;br /&gt;
					last_attr = tag.substr(i+1);&lt;br /&gt;
					tag = tag.substring(0, i);&lt;br /&gt;
					break;&lt;br /&gt;
				} else switch (tag.substr(i-1, 2)) {&lt;br /&gt;
					case ']]':&lt;br /&gt;
						nesting++;&lt;br /&gt;
						i--;&lt;br /&gt;
						break;&lt;br /&gt;
					case '[[':&lt;br /&gt;
						nesting--;&lt;br /&gt;
						i--;&lt;br /&gt;
				}&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			attr = tag.split(/\s*\|\s*/);&lt;br /&gt;
			attr.push(last_attr);&lt;br /&gt;
			filename = attr.shift();&lt;br /&gt;
			&lt;br /&gt;
			var w_match;&lt;br /&gt;
			&lt;br /&gt;
			for (;attr.length; attr.shift())&lt;br /&gt;
			if (w_match = attr[0].match(/^(\d*)px$/)) width = w_match[1]&lt;br /&gt;
			else switch(attr[0]) {&lt;br /&gt;
				case 'thumb':&lt;br /&gt;
				case 'thumbnail':&lt;br /&gt;
					thumb=true;&lt;br /&gt;
				case 'frame':&lt;br /&gt;
					frame=true;&lt;br /&gt;
					break;&lt;br /&gt;
				case 'none':&lt;br /&gt;
				case 'right':&lt;br /&gt;
				case 'left':&lt;br /&gt;
					center=false;&lt;br /&gt;
					align=attr[0];&lt;br /&gt;
					break;&lt;br /&gt;
				case 'center':&lt;br /&gt;
					center=true;&lt;br /&gt;
					align='none';&lt;br /&gt;
					break;&lt;br /&gt;
				default:&lt;br /&gt;
					if (attr.length == 1) caption = attr[0];&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
		} else filename = tag;&lt;br /&gt;
		&lt;br /&gt;
		&lt;br /&gt;
		var o='';&lt;br /&gt;
		&lt;br /&gt;
		if (frame) {&lt;br /&gt;
		&lt;br /&gt;
			if (align=='') align = 'right';&lt;br /&gt;
			&lt;br /&gt;
			o += f(&amp;quot;&amp;lt;div class='thumb t?'&amp;gt;&amp;quot;, align);&lt;br /&gt;
			&lt;br /&gt;
			if (thumb) {&lt;br /&gt;
				if (!width) width = InstaView.conf.wiki.default_thumb_width;&lt;br /&gt;
				&lt;br /&gt;
				o += f(&amp;quot;&amp;lt;div style='width:?px;'&amp;gt;?&amp;quot;, 2+width*1, make_image(filename, caption, width)) +&lt;br /&gt;
					f(&amp;quot;&amp;lt;div class='thumbcaption'&amp;gt;&amp;lt;div class='magnify' style='float:right'&amp;gt;&amp;lt;a href='?' class='internal' title='Enlarge'&amp;gt;&amp;lt;img src='?'&amp;gt;&amp;lt;/a&amp;gt;&amp;lt;/div&amp;gt;?&amp;lt;/div&amp;gt;&amp;quot;,&lt;br /&gt;
						InstaView.conf.paths.articles + InstaView.conf.locale.image + ':' + filename,&lt;br /&gt;
						InstaView.conf.paths.magnify_icon,&lt;br /&gt;
						parse_inline_nowiki(caption)&lt;br /&gt;
					)&lt;br /&gt;
			} else {&lt;br /&gt;
				o += '&amp;lt;div&amp;gt;' + make_image(filename, caption) + f(&amp;quot;&amp;lt;div class='thumbcaption'&amp;gt;?&amp;lt;/div&amp;gt;&amp;quot;, parse_inline_nowiki(caption))&lt;br /&gt;
			}&lt;br /&gt;
			&lt;br /&gt;
			o += '&amp;lt;/div&amp;gt;&amp;lt;/div&amp;gt;';&lt;br /&gt;
			&lt;br /&gt;
		} else if (align != '') {&lt;br /&gt;
			o += f(&amp;quot;&amp;lt;div class='float?'&amp;gt;&amp;lt;span&amp;gt;?&amp;lt;/span&amp;gt;&amp;lt;/div&amp;gt;&amp;quot;, align, make_image(filename, caption, width));&lt;br /&gt;
		} else {&lt;br /&gt;
			return make_image(filename, caption, width);&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return center? f(&amp;quot;&amp;lt;div class='center'&amp;gt;?&amp;lt;/div&amp;gt;&amp;quot;, o): o;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function parse_inline_nowiki(str)&lt;br /&gt;
	{&lt;br /&gt;
		var start, lastend=0&lt;br /&gt;
		var substart=0, nestlev=0, open, close, subloop;&lt;br /&gt;
		var html='';&lt;br /&gt;
		&lt;br /&gt;
		while (-1 != (start = str.indexOf('&amp;lt;nowiki&amp;gt;', substart))) {&lt;br /&gt;
			html += parse_inline_wiki(str.substring(lastend, start));&lt;br /&gt;
			start += 8;&lt;br /&gt;
			substart = start;&lt;br /&gt;
			subloop = true;&lt;br /&gt;
			do {&lt;br /&gt;
				open = str.indexOf('&amp;lt;nowiki&amp;gt;', substart);&lt;br /&gt;
				close = str.indexOf('&amp;lt;/nowiki&amp;gt;', substart);&lt;br /&gt;
				if (close&amp;lt;=open || open==-1) {&lt;br /&gt;
					if (close==-1) {&lt;br /&gt;
						return html + html_entities(str.substr(start));&lt;br /&gt;
					}&lt;br /&gt;
					substart = close+9;&lt;br /&gt;
					if (nestlev) {&lt;br /&gt;
						nestlev--;&lt;br /&gt;
					} else {&lt;br /&gt;
						lastend = substart;&lt;br /&gt;
						html += html_entities(str.substring(start, lastend-9));&lt;br /&gt;
						subloop = false;&lt;br /&gt;
					}&lt;br /&gt;
				} else {&lt;br /&gt;
					substart = open+8;&lt;br /&gt;
					nestlev++;&lt;br /&gt;
				}&lt;br /&gt;
			} while (subloop)&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return html + parse_inline_wiki(str.substr(lastend));&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function make_image(filename, caption, width)&lt;br /&gt;
	{&lt;br /&gt;
		// uppercase first letter in file name&lt;br /&gt;
		filename = filename.charAt(0).toUpperCase() + filename.substr(1);&lt;br /&gt;
		// replace spaces with underscores&lt;br /&gt;
		filename = filename.replace(/ /g, '_');&lt;br /&gt;
		&lt;br /&gt;
		caption = strip_inline_wiki(caption);&lt;br /&gt;
		&lt;br /&gt;
		var md5 = hex_md5(filename);&lt;br /&gt;
		&lt;br /&gt;
		var source = md5.charAt(0) + '/' + md5.substr(0,2) + '/' + filename;&lt;br /&gt;
		&lt;br /&gt;
		if (width) width = &amp;quot;width='&amp;quot; + width + &amp;quot;px'&amp;quot;;&lt;br /&gt;
		&lt;br /&gt;
		var img = f(&amp;quot;&amp;lt;img onerror=\&amp;quot;this.onerror=null;this.src='?'\&amp;quot; src='?' ? ?&amp;gt;&amp;quot;, InstaView.conf.paths.images_fallback + source, InstaView.conf.paths.images + source, (caption!='')? &amp;quot;alt='&amp;quot; + caption + &amp;quot;'&amp;quot; : '', width);&lt;br /&gt;
		&lt;br /&gt;
		return f(&amp;quot;&amp;lt;a class='image' ? href='?'&amp;gt;?&amp;lt;/a&amp;gt;&amp;quot;, (caption!='')? &amp;quot;title='&amp;quot; + caption + &amp;quot;'&amp;quot; : '', InstaView.conf.paths.articles + InstaView.conf.locale.image + ':' + filename, img);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function parse_inline_images(str)&lt;br /&gt;
	{&lt;br /&gt;
		var start, substart=0, nestlev=0;&lt;br /&gt;
		var loop, close, open, wiki, html;&lt;br /&gt;
		&lt;br /&gt;
		while (-1 != (start=str.indexOf('[[', substart))) {&lt;br /&gt;
			if(str.substr(start+2).match(RegExp('^' + InstaView.conf.locale.image + ':','i'))) {&lt;br /&gt;
				loop=true;&lt;br /&gt;
				substart=start;&lt;br /&gt;
				do {&lt;br /&gt;
					substart+=2;&lt;br /&gt;
					close=str.indexOf(']]',substart);&lt;br /&gt;
					open=str.indexOf('[[',substart);&lt;br /&gt;
					if (close&amp;lt;=open||open==-1) {&lt;br /&gt;
						if (close==-1) return str;&lt;br /&gt;
						substart=close;&lt;br /&gt;
						if (nestlev) {&lt;br /&gt;
							nestlev--;&lt;br /&gt;
						} else {&lt;br /&gt;
							wiki=str.substring(start,close+2);&lt;br /&gt;
							html=parse_image(wiki);&lt;br /&gt;
							str=str.replace(wiki,html);&lt;br /&gt;
							substart=start+html.length;&lt;br /&gt;
							loop=false;&lt;br /&gt;
						}&lt;br /&gt;
					} else {&lt;br /&gt;
						substart=open;&lt;br /&gt;
						nestlev++;&lt;br /&gt;
					}&lt;br /&gt;
				} while (loop)&lt;br /&gt;
				&lt;br /&gt;
			} else break;&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		return str;&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// the output of this function doesn't respect the FILO structure of HTML&lt;br /&gt;
	// but since most browsers can handle it I'll save myself the hassle&lt;br /&gt;
	function parse_inline_formatting(str)&lt;br /&gt;
	{&lt;br /&gt;
		var em,st,i,li,o='';&lt;br /&gt;
		while ((i=str.indexOf(&amp;quot;''&amp;quot;,li))+1) {&lt;br /&gt;
			o += str.substring(li,i);&lt;br /&gt;
			li=i+2;&lt;br /&gt;
			if (str.charAt(i+2)==&amp;quot;'&amp;quot;) {&lt;br /&gt;
				li++;&lt;br /&gt;
				st=!st;&lt;br /&gt;
				o+=st?'&amp;lt;strong&amp;gt;':'&amp;lt;/strong&amp;gt;';&lt;br /&gt;
			} else {&lt;br /&gt;
				em=!em;&lt;br /&gt;
				o+=em?'&amp;lt;em&amp;gt;':'&amp;lt;/em&amp;gt;';&lt;br /&gt;
			}&lt;br /&gt;
		}&lt;br /&gt;
		return o+str.substr(li);&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function parse_inline_wiki(str)&lt;br /&gt;
	{&lt;br /&gt;
		var aux_match;&lt;br /&gt;
		&lt;br /&gt;
		str = parse_inline_images(str);&lt;br /&gt;
		str = parse_inline_formatting(str);&lt;br /&gt;
		&lt;br /&gt;
		// math&lt;br /&gt;
		while (aux_match = str.match(/&amp;lt;(?:)math&amp;gt;(.*?)&amp;lt;\/math&amp;gt;/i)) {&lt;br /&gt;
			var math_md5 = hex_md5(aux_match[1]);&lt;br /&gt;
			str = str.replace(aux_match[0], f(&amp;quot;&amp;lt;img src='?.png'&amp;gt;&amp;quot;, InstaView.conf.paths.math+math_md5));&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		// Build a Mediawiki-formatted date string&lt;br /&gt;
		var date = new Date;&lt;br /&gt;
		var minutes = date.getUTCMinutes();&lt;br /&gt;
		if (minutes &amp;lt; 10) minutes = '0' + minutes;&lt;br /&gt;
		var date = f(&amp;quot;?:?, ? ? ? (UTC)&amp;quot;, date.getUTCHours(), minutes, date.getUTCDate(), InstaView.conf.locale.months[date.getUTCMonth()], date.getUTCFullYear());&lt;br /&gt;
		&lt;br /&gt;
		// text formatting&lt;br /&gt;
		return str.&lt;br /&gt;
			// signatures&lt;br /&gt;
			replace(/~{5}(?!~)/g, date).&lt;br /&gt;
			replace(/~{4}(?!~)/g, InstaView.conf.user.name+' '+date).&lt;br /&gt;
			replace(/~{3}(?!~)/g, InstaView.conf.user.name).&lt;br /&gt;
			&lt;br /&gt;
			// [[:Category:...]], [[:Image:...]], etc...&lt;br /&gt;
			replace(RegExp('\\[\\[:((?:'+InstaView.conf.locale.category+'|'+InstaView.conf.locale.image+'|'+InstaView.conf.wiki.interwiki+'):.*?)\\]\\]','gi'), &amp;quot;&amp;lt;a href='&amp;quot;+InstaView.conf.paths.articles+&amp;quot;$1'&amp;gt;$1&amp;lt;/a&amp;gt;&amp;quot;).&lt;br /&gt;
			replace(RegExp('\\[\\[(?:'+InstaView.conf.locale.category+'|'+InstaView.conf.wiki.interwiki+'):.*?\\]\\]','gi'),'').&lt;br /&gt;
			&lt;br /&gt;
			// [[/Relative links]]&lt;br /&gt;
			replace(/\[\[(\/[^|]*?)\]\]/g, f(&amp;quot;&amp;lt;a href='?$1'&amp;gt;$1&amp;lt;/a&amp;gt;&amp;quot;, location)).&lt;br /&gt;
			&lt;br /&gt;
			// [[/Replaced|Relative links]]&lt;br /&gt;
			replace(/\[\[(\/.*?)\|(.+?)\]\]/g, f(&amp;quot;&amp;lt;a href='?$1'&amp;gt;$2&amp;lt;/a&amp;gt;&amp;quot;, location)).&lt;br /&gt;
			&lt;br /&gt;
			// [[Common links]]&lt;br /&gt;
			replace(/\[\[([^|]*?)\]\](\w*)/g, f(&amp;quot;&amp;lt;a href='?$1'&amp;gt;$1$2&amp;lt;/a&amp;gt;&amp;quot;, InstaView.conf.paths.articles)).&lt;br /&gt;
			&lt;br /&gt;
			// [[Replaced|Links]]&lt;br /&gt;
			replace(/\[\[(.*?)\|([^\]]+?)\]\](\w*)/g, f(&amp;quot;&amp;lt;a href='?$1'&amp;gt;$2$3&amp;lt;/a&amp;gt;&amp;quot;, InstaView.conf.paths.articles)).&lt;br /&gt;
			&lt;br /&gt;
			// [[Stripped:Namespace|Namespace]]&lt;br /&gt;
			replace(/\[\[([^\]]*?:)?(.*?)( *\(.*?\))?\|\]\]/g, f(&amp;quot;&amp;lt;a href='?$1$2$3'&amp;gt;$2&amp;lt;/a&amp;gt;&amp;quot;, InstaView.conf.paths.articles)).&lt;br /&gt;
			&lt;br /&gt;
			// External links&lt;br /&gt;
			replace(/\[(https?|news|ftp|mailto|gopher|irc):(\/*)([^\]]*?) (.*?)\]/g, &amp;quot;&amp;lt;a href='$1:$2$3'&amp;gt;$4&amp;lt;/a&amp;gt;&amp;quot;).&lt;br /&gt;
			replace(/\[http:\/\/(.*?)\]/g, &amp;quot;&amp;lt;a href='http://$1'&amp;gt;[#]&amp;lt;/a&amp;gt;&amp;quot;).&lt;br /&gt;
			replace(/\[(news|ftp|mailto|gopher|irc):(\/*)(.*?)\]/g, &amp;quot;&amp;lt;a href='$1:$2$3'&amp;gt;$1:$2$3&amp;lt;/a&amp;gt;&amp;quot;).&lt;br /&gt;
			replace(/(^| )(https?|news|ftp|mailto|gopher|irc):(\/*)([^ $]*)/g, &amp;quot;$1&amp;lt;a href='$2:$3$4'&amp;gt;$2:$3$4&amp;lt;/a&amp;gt;&amp;quot;).&lt;br /&gt;
			&lt;br /&gt;
			replace('__NOTOC__','').&lt;br /&gt;
			replace('__NOEDITSECTION__','');&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	function strip_inline_wiki(str)&lt;br /&gt;
	{&lt;br /&gt;
		return str&lt;br /&gt;
			.replace(/\[\[[^\]]*\|(.*?)\]\]/g,'$1')&lt;br /&gt;
			.replace(/\[\[(.*?)\]\]/g,'$1')&lt;br /&gt;
			.replace(/''(.*?)''/g,'$1');&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	// begin parsing&lt;br /&gt;
	for (;remain();) if ($(/^(={1,6})(.*)\1(.*)$/)) {&lt;br /&gt;
		p=0&lt;br /&gt;
		endl(f('&amp;lt;h?&amp;gt;?&amp;lt;/h?&amp;gt;?', $r[1].length, parse_inline_nowiki($r[2]), $r[1].length, $r[3]))&lt;br /&gt;
		&lt;br /&gt;
	} else if ($(/^[*#:;]/)) {&lt;br /&gt;
		p=0&lt;br /&gt;
		parse_list()&lt;br /&gt;
		&lt;br /&gt;
	} else if ($(' ')) {&lt;br /&gt;
		p=0&lt;br /&gt;
		parse_pre()&lt;br /&gt;
		&lt;br /&gt;
	} else if ($('{|')) {&lt;br /&gt;
		p=0&lt;br /&gt;
		parse_table()&lt;br /&gt;
		&lt;br /&gt;
	} else if ($(/^----+$/)) {&lt;br /&gt;
		p=0&lt;br /&gt;
		endl('&amp;lt;hr&amp;gt;')&lt;br /&gt;
		&lt;br /&gt;
	} else if ($(InstaView.BLOCK_IMAGE)) {&lt;br /&gt;
		p=0&lt;br /&gt;
		parse_block_image()&lt;br /&gt;
		&lt;br /&gt;
	} else {&lt;br /&gt;
		&lt;br /&gt;
		// handle paragraphs&lt;br /&gt;
		if ($$('')) {&lt;br /&gt;
			if (p = (remain()&amp;gt;1 &amp;amp;&amp;amp; ll[1]==(''))) endl('&amp;lt;p&amp;gt;&amp;lt;br&amp;gt;')&lt;br /&gt;
		} else {&lt;br /&gt;
			if(!p) {&lt;br /&gt;
				ps('&amp;lt;p&amp;gt;')&lt;br /&gt;
				p=1&lt;br /&gt;
			}&lt;br /&gt;
			ps(parse_inline_nowiki(ll[0]) + ' ')&lt;br /&gt;
		}&lt;br /&gt;
		&lt;br /&gt;
		sh();&lt;br /&gt;
	}&lt;br /&gt;
	&lt;br /&gt;
	return o&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * A JavaScript implementation of the RSA Data Security, Inc. MD5 Message&lt;br /&gt;
 * Digest Algorithm, as defined in RFC 1321.&lt;br /&gt;
 * Version 2.2-alpha Copyright (C) Paul Johnston 1999 - 2005&lt;br /&gt;
 * Other contributors: Greg Holt, Andrew Kepert, Ydnar, Lostinet&lt;br /&gt;
 * Distributed under the BSD License&lt;br /&gt;
 * See http://pajhome.org.uk/crypt/md5 for more info.&lt;br /&gt;
 */&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Configurable variables. You may need to tweak these to be compatible with&lt;br /&gt;
 * the server-side, but the defaults work in most cases.&lt;br /&gt;
 */&lt;br /&gt;
var hexcase = 0;   /* hex output format. 0 - lowercase; 1 - uppercase        */&lt;br /&gt;
var b64pad  = &amp;quot;&amp;quot;; /* base-64 pad character. &amp;quot;=&amp;quot; for strict RFC compliance   */&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * These are the functions you'll usually want to call&lt;br /&gt;
 * They take string arguments and return either hex or base-64 encoded strings&lt;br /&gt;
 */&lt;br /&gt;
function hex_md5(s)    { return rstr2hex(rstr_md5(str2rstr_utf8(s))); }&lt;br /&gt;
function b64_md5(s)    { return rstr2b64(rstr_md5(str2rstr_utf8(s))); }&lt;br /&gt;
function any_md5(s, e) { return rstr2any(rstr_md5(str2rstr_utf8(s)), e); }&lt;br /&gt;
function hex_hmac_md5(k, d)&lt;br /&gt;
  { return rstr2hex(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }&lt;br /&gt;
function b64_hmac_md5(k, d)&lt;br /&gt;
  { return rstr2b64(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d))); }&lt;br /&gt;
function any_hmac_md5(k, d, e)&lt;br /&gt;
  { return rstr2any(rstr_hmac_md5(str2rstr_utf8(k), str2rstr_utf8(d)), e); }&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Calculate the MD5 of a raw string&lt;br /&gt;
 */&lt;br /&gt;
function rstr_md5(s)&lt;br /&gt;
{&lt;br /&gt;
  return binl2rstr(binl_md5(rstr2binl(s), s.length * 8));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Calculate the HMAC-MD5, of a key and some data (raw strings)&lt;br /&gt;
 */&lt;br /&gt;
function rstr_hmac_md5(key, data)&lt;br /&gt;
{&lt;br /&gt;
  var bkey = rstr2binl(key);&lt;br /&gt;
  if(bkey.length &amp;gt; 16) bkey = binl_md5(bkey, key.length * 8);&lt;br /&gt;
&lt;br /&gt;
  var ipad = Array(16), opad = Array(16);&lt;br /&gt;
  for(var i = 0; i &amp;lt; 16; i++)&lt;br /&gt;
  {&lt;br /&gt;
    ipad[i] = bkey[i] ^ 0x36363636;&lt;br /&gt;
    opad[i] = bkey[i] ^ 0x5C5C5C5C;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  var hash = binl_md5(ipad.concat(rstr2binl(data)), 512 + data.length * 8);&lt;br /&gt;
  return binl2rstr(binl_md5(opad.concat(hash), 512 + 128));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Convert a raw string to a hex string&lt;br /&gt;
 */&lt;br /&gt;
function rstr2hex(input)&lt;br /&gt;
{&lt;br /&gt;
  var hex_tab = hexcase ? &amp;quot;0123456789ABCDEF&amp;quot; : &amp;quot;0123456789abcdef&amp;quot;;&lt;br /&gt;
  var output = &amp;quot;&amp;quot;;&lt;br /&gt;
  var x;&lt;br /&gt;
  for(var i = 0; i &amp;lt; input.length; i++)&lt;br /&gt;
  {&lt;br /&gt;
    x = input.charCodeAt(i);&lt;br /&gt;
    output += hex_tab.charAt((x &amp;gt;&amp;gt;&amp;gt; 4) &amp;amp; 0x0F)&lt;br /&gt;
           +  hex_tab.charAt( x        &amp;amp; 0x0F);&lt;br /&gt;
  }&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Convert a raw string to a base-64 string&lt;br /&gt;
 */&lt;br /&gt;
function rstr2b64(input)&lt;br /&gt;
{&lt;br /&gt;
  var tab = &amp;quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&amp;quot;;&lt;br /&gt;
  var output = &amp;quot;&amp;quot;;&lt;br /&gt;
  var len = input.length;&lt;br /&gt;
  for(var i = 0; i &amp;lt; len; i += 3)&lt;br /&gt;
  {&lt;br /&gt;
    var triplet = (input.charCodeAt(i) &amp;lt;&amp;lt; 16)&lt;br /&gt;
                | (i + 1 &amp;lt; len ? input.charCodeAt(i+1) &amp;lt;&amp;lt; 8 : 0)&lt;br /&gt;
                | (i + 2 &amp;lt; len ? input.charCodeAt(i+2)      : 0);&lt;br /&gt;
    for(var j = 0; j &amp;lt; 4; j++)&lt;br /&gt;
    {&lt;br /&gt;
      if(i * 8 + j * 6 &amp;gt; input.length * 8) output += b64pad;&lt;br /&gt;
      else output += tab.charAt((triplet &amp;gt;&amp;gt;&amp;gt; 6*(3-j)) &amp;amp; 0x3F);&lt;br /&gt;
    }&lt;br /&gt;
  }&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Convert a raw string to an arbitrary string encoding&lt;br /&gt;
 */&lt;br /&gt;
function rstr2any(input, encoding)&lt;br /&gt;
{&lt;br /&gt;
  var divisor = encoding.length;&lt;br /&gt;
  var remainders = Array();&lt;br /&gt;
  var i, q, x, quotient;&lt;br /&gt;
&lt;br /&gt;
  /* Convert to an array of 16-bit big-endian values, forming the dividend */&lt;br /&gt;
  var dividend = Array(input.length / 2);&lt;br /&gt;
  for(i = 0; i &amp;lt; dividend.length; i++)&lt;br /&gt;
  {&lt;br /&gt;
    dividend[i] = (input.charCodeAt(i * 2) &amp;lt;&amp;lt; 8) | input.charCodeAt(i * 2 + 1);&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /*&lt;br /&gt;
   * Repeatedly perform a long division. The binary array forms the dividend,&lt;br /&gt;
   * the length of the encoding is the divisor. Once computed, the quotient&lt;br /&gt;
   * forms the dividend for the next step. We stop when the dividend is zero.&lt;br /&gt;
   * All remainders are stored for later use.&lt;br /&gt;
   */&lt;br /&gt;
  while(dividend.length &amp;gt; 0)&lt;br /&gt;
  {&lt;br /&gt;
    quotient = Array();&lt;br /&gt;
    x = 0;&lt;br /&gt;
    for(i = 0; i &amp;lt; dividend.length; i++)&lt;br /&gt;
    {&lt;br /&gt;
      x = (x &amp;lt;&amp;lt; 16) + dividend[i];&lt;br /&gt;
      q = Math.floor(x / divisor);&lt;br /&gt;
      x -= q * divisor;&lt;br /&gt;
      if(quotient.length &amp;gt; 0 || q &amp;gt; 0)&lt;br /&gt;
        quotient[quotient.length] = q;&lt;br /&gt;
    }&lt;br /&gt;
    remainders[remainders.length] = x;&lt;br /&gt;
    dividend = quotient;&lt;br /&gt;
  }&lt;br /&gt;
&lt;br /&gt;
  /* Convert the remainders to the output string */&lt;br /&gt;
  var output = &amp;quot;&amp;quot;;&lt;br /&gt;
  for(i = remainders.length - 1; i &amp;gt;= 0; i--)&lt;br /&gt;
    output += encoding.charAt(remainders[i]);&lt;br /&gt;
&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Encode a string as utf-8.&lt;br /&gt;
 * For efficiency, this assumes the input is valid utf-16.&lt;br /&gt;
 */&lt;br /&gt;
function str2rstr_utf8(input)&lt;br /&gt;
{&lt;br /&gt;
  var output = &amp;quot;&amp;quot;;&lt;br /&gt;
  var i = -1;&lt;br /&gt;
  var x, y;&lt;br /&gt;
&lt;br /&gt;
  while(++i &amp;lt; input.length)&lt;br /&gt;
  {&lt;br /&gt;
    /* Decode utf-16 surrogate pairs */&lt;br /&gt;
    x = input.charCodeAt(i);&lt;br /&gt;
    y = i + 1 &amp;lt; input.length ? input.charCodeAt(i + 1) : 0;&lt;br /&gt;
    if(0xD800 &amp;lt;= x &amp;amp;&amp;amp; x &amp;lt;= 0xDBFF &amp;amp;&amp;amp; 0xDC00 &amp;lt;= y &amp;amp;&amp;amp; y &amp;lt;= 0xDFFF)&lt;br /&gt;
    {&lt;br /&gt;
      x = 0x10000 + ((x &amp;amp; 0x03FF) &amp;lt;&amp;lt; 10) + (y &amp;amp; 0x03FF);&lt;br /&gt;
      i++;&lt;br /&gt;
    }&lt;br /&gt;
&lt;br /&gt;
    /* Encode output as utf-8 */&lt;br /&gt;
    if(x &amp;lt;= 0x7F)&lt;br /&gt;
      output += String.fromCharCode(x);&lt;br /&gt;
    else if(x &amp;lt;= 0x7FF)&lt;br /&gt;
      output += String.fromCharCode(0xC0 | ((x &amp;gt;&amp;gt;&amp;gt; 6 ) &amp;amp; 0x1F),&lt;br /&gt;
                                    0x80 | ( x         &amp;amp; 0x3F));&lt;br /&gt;
    else if(x &amp;lt;= 0xFFFF)&lt;br /&gt;
      output += String.fromCharCode(0xE0 | ((x &amp;gt;&amp;gt;&amp;gt; 12) &amp;amp; 0x0F),&lt;br /&gt;
                                    0x80 | ((x &amp;gt;&amp;gt;&amp;gt; 6 ) &amp;amp; 0x3F),&lt;br /&gt;
                                    0x80 | ( x         &amp;amp; 0x3F));&lt;br /&gt;
    else if(x &amp;lt;= 0x1FFFFF)&lt;br /&gt;
      output += String.fromCharCode(0xF0 | ((x &amp;gt;&amp;gt;&amp;gt; 18) &amp;amp; 0x07),&lt;br /&gt;
                                    0x80 | ((x &amp;gt;&amp;gt;&amp;gt; 12) &amp;amp; 0x3F),&lt;br /&gt;
                                    0x80 | ((x &amp;gt;&amp;gt;&amp;gt; 6 ) &amp;amp; 0x3F),&lt;br /&gt;
                                    0x80 | ( x         &amp;amp; 0x3F));&lt;br /&gt;
  }&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Encode a string as utf-16&lt;br /&gt;
 */&lt;br /&gt;
function str2rstr_utf16le(input)&lt;br /&gt;
{&lt;br /&gt;
  var output = &amp;quot;&amp;quot;;&lt;br /&gt;
  for(var i = 0; i &amp;lt; input.length; i++)&lt;br /&gt;
    output += String.fromCharCode( input.charCodeAt(i)        &amp;amp; 0xFF,&lt;br /&gt;
                                  (input.charCodeAt(i) &amp;gt;&amp;gt;&amp;gt; 8) &amp;amp; 0xFF);&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
function str2rstr_utf16be(input)&lt;br /&gt;
{&lt;br /&gt;
  var output = &amp;quot;&amp;quot;;&lt;br /&gt;
  for(var i = 0; i &amp;lt; input.length; i++)&lt;br /&gt;
    output += String.fromCharCode((input.charCodeAt(i) &amp;gt;&amp;gt;&amp;gt; 8) &amp;amp; 0xFF,&lt;br /&gt;
                                   input.charCodeAt(i)        &amp;amp; 0xFF);&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Convert a raw string to an array of little-endian words&lt;br /&gt;
 * Characters &amp;gt;255 have their high-byte silently ignored.&lt;br /&gt;
 */&lt;br /&gt;
function rstr2binl(input)&lt;br /&gt;
{&lt;br /&gt;
  var output = Array(input.length &amp;gt;&amp;gt; 2);&lt;br /&gt;
  for(var i = 0; i &amp;lt; output.length; i++)&lt;br /&gt;
    output[i] = 0;&lt;br /&gt;
  for(var i = 0; i &amp;lt; input.length * 8; i += 8)&lt;br /&gt;
    output[i&amp;gt;&amp;gt;5] |= (input.charCodeAt(i / 8) &amp;amp; 0xFF) &amp;lt;&amp;lt; (i%32);&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Convert an array of little-endian words to a string&lt;br /&gt;
 */&lt;br /&gt;
function binl2rstr(input)&lt;br /&gt;
{&lt;br /&gt;
  var output = &amp;quot;&amp;quot;;&lt;br /&gt;
  for(var i = 0; i &amp;lt; input.length * 32; i += 8)&lt;br /&gt;
    output += String.fromCharCode((input[i&amp;gt;&amp;gt;5] &amp;gt;&amp;gt;&amp;gt; (i % 32)) &amp;amp; 0xFF);&lt;br /&gt;
  return output;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Calculate the MD5 of an array of little-endian words, and a bit length.&lt;br /&gt;
 */&lt;br /&gt;
function binl_md5(x, len)&lt;br /&gt;
{&lt;br /&gt;
  /* append padding */&lt;br /&gt;
  x[len &amp;gt;&amp;gt; 5] |= 0x80 &amp;lt;&amp;lt; ((len) % 32);&lt;br /&gt;
  x[(((len + 64) &amp;gt;&amp;gt;&amp;gt; 9) &amp;lt;&amp;lt; 4) + 14] = len;&lt;br /&gt;
&lt;br /&gt;
  var a =  1732584193;&lt;br /&gt;
  var b = -271733879;&lt;br /&gt;
  var c = -1732584194;&lt;br /&gt;
  var d =  271733878;&lt;br /&gt;
&lt;br /&gt;
  for(var i = 0; i &amp;lt; x.length; i += 16)&lt;br /&gt;
  {&lt;br /&gt;
    var olda = a;&lt;br /&gt;
    var oldb = b;&lt;br /&gt;
    var oldc = c;&lt;br /&gt;
    var oldd = d;&lt;br /&gt;
&lt;br /&gt;
    a = md5_ff(a, b, c, d, x[i+ 0], 7 , -680876936);&lt;br /&gt;
    d = md5_ff(d, a, b, c, x[i+ 1], 12, -389564586);&lt;br /&gt;
    c = md5_ff(c, d, a, b, x[i+ 2], 17,  606105819);&lt;br /&gt;
    b = md5_ff(b, c, d, a, x[i+ 3], 22, -1044525330);&lt;br /&gt;
    a = md5_ff(a, b, c, d, x[i+ 4], 7 , -176418897);&lt;br /&gt;
    d = md5_ff(d, a, b, c, x[i+ 5], 12,  1200080426);&lt;br /&gt;
    c = md5_ff(c, d, a, b, x[i+ 6], 17, -1473231341);&lt;br /&gt;
    b = md5_ff(b, c, d, a, x[i+ 7], 22, -45705983);&lt;br /&gt;
    a = md5_ff(a, b, c, d, x[i+ 8], 7 ,  1770035416);&lt;br /&gt;
    d = md5_ff(d, a, b, c, x[i+ 9], 12, -1958414417);&lt;br /&gt;
    c = md5_ff(c, d, a, b, x[i+10], 17, -42063);&lt;br /&gt;
    b = md5_ff(b, c, d, a, x[i+11], 22, -1990404162);&lt;br /&gt;
    a = md5_ff(a, b, c, d, x[i+12], 7 ,  1804603682);&lt;br /&gt;
    d = md5_ff(d, a, b, c, x[i+13], 12, -40341101);&lt;br /&gt;
    c = md5_ff(c, d, a, b, x[i+14], 17, -1502002290);&lt;br /&gt;
    b = md5_ff(b, c, d, a, x[i+15], 22,  1236535329);&lt;br /&gt;
&lt;br /&gt;
    a = md5_gg(a, b, c, d, x[i+ 1], 5 , -165796510);&lt;br /&gt;
    d = md5_gg(d, a, b, c, x[i+ 6], 9 , -1069501632);&lt;br /&gt;
    c = md5_gg(c, d, a, b, x[i+11], 14,  643717713);&lt;br /&gt;
    b = md5_gg(b, c, d, a, x[i+ 0], 20, -373897302);&lt;br /&gt;
    a = md5_gg(a, b, c, d, x[i+ 5], 5 , -701558691);&lt;br /&gt;
    d = md5_gg(d, a, b, c, x[i+10], 9 ,  38016083);&lt;br /&gt;
    c = md5_gg(c, d, a, b, x[i+15], 14, -660478335);&lt;br /&gt;
    b = md5_gg(b, c, d, a, x[i+ 4], 20, -405537848);&lt;br /&gt;
    a = md5_gg(a, b, c, d, x[i+ 9], 5 ,  568446438);&lt;br /&gt;
    d = md5_gg(d, a, b, c, x[i+14], 9 , -1019803690);&lt;br /&gt;
    c = md5_gg(c, d, a, b, x[i+ 3], 14, -187363961);&lt;br /&gt;
    b = md5_gg(b, c, d, a, x[i+ 8], 20,  1163531501);&lt;br /&gt;
    a = md5_gg(a, b, c, d, x[i+13], 5 , -1444681467);&lt;br /&gt;
    d = md5_gg(d, a, b, c, x[i+ 2], 9 , -51403784);&lt;br /&gt;
    c = md5_gg(c, d, a, b, x[i+ 7], 14,  1735328473);&lt;br /&gt;
    b = md5_gg(b, c, d, a, x[i+12], 20, -1926607734);&lt;br /&gt;
&lt;br /&gt;
    a = md5_hh(a, b, c, d, x[i+ 5], 4 , -378558);&lt;br /&gt;
    d = md5_hh(d, a, b, c, x[i+ 8], 11, -2022574463);&lt;br /&gt;
    c = md5_hh(c, d, a, b, x[i+11], 16,  1839030562);&lt;br /&gt;
    b = md5_hh(b, c, d, a, x[i+14], 23, -35309556);&lt;br /&gt;
    a = md5_hh(a, b, c, d, x[i+ 1], 4 , -1530992060);&lt;br /&gt;
    d = md5_hh(d, a, b, c, x[i+ 4], 11,  1272893353);&lt;br /&gt;
    c = md5_hh(c, d, a, b, x[i+ 7], 16, -155497632);&lt;br /&gt;
    b = md5_hh(b, c, d, a, x[i+10], 23, -1094730640);&lt;br /&gt;
    a = md5_hh(a, b, c, d, x[i+13], 4 ,  681279174);&lt;br /&gt;
    d = md5_hh(d, a, b, c, x[i+ 0], 11, -358537222);&lt;br /&gt;
    c = md5_hh(c, d, a, b, x[i+ 3], 16, -722521979);&lt;br /&gt;
    b = md5_hh(b, c, d, a, x[i+ 6], 23,  76029189);&lt;br /&gt;
    a = md5_hh(a, b, c, d, x[i+ 9], 4 , -640364487);&lt;br /&gt;
    d = md5_hh(d, a, b, c, x[i+12], 11, -421815835);&lt;br /&gt;
    c = md5_hh(c, d, a, b, x[i+15], 16,  530742520);&lt;br /&gt;
    b = md5_hh(b, c, d, a, x[i+ 2], 23, -995338651);&lt;br /&gt;
&lt;br /&gt;
    a = md5_ii(a, b, c, d, x[i+ 0], 6 , -198630844);&lt;br /&gt;
    d = md5_ii(d, a, b, c, x[i+ 7], 10,  1126891415);&lt;br /&gt;
    c = md5_ii(c, d, a, b, x[i+14], 15, -1416354905);&lt;br /&gt;
    b = md5_ii(b, c, d, a, x[i+ 5], 21, -57434055);&lt;br /&gt;
    a = md5_ii(a, b, c, d, x[i+12], 6 ,  1700485571);&lt;br /&gt;
    d = md5_ii(d, a, b, c, x[i+ 3], 10, -1894986606);&lt;br /&gt;
    c = md5_ii(c, d, a, b, x[i+10], 15, -1051523);&lt;br /&gt;
    b = md5_ii(b, c, d, a, x[i+ 1], 21, -2054922799);&lt;br /&gt;
    a = md5_ii(a, b, c, d, x[i+ 8], 6 ,  1873313359);&lt;br /&gt;
    d = md5_ii(d, a, b, c, x[i+15], 10, -30611744);&lt;br /&gt;
    c = md5_ii(c, d, a, b, x[i+ 6], 15, -1560198380);&lt;br /&gt;
    b = md5_ii(b, c, d, a, x[i+13], 21,  1309151649);&lt;br /&gt;
    a = md5_ii(a, b, c, d, x[i+ 4], 6 , -145523070);&lt;br /&gt;
    d = md5_ii(d, a, b, c, x[i+11], 10, -1120210379);&lt;br /&gt;
    c = md5_ii(c, d, a, b, x[i+ 2], 15,  718787259);&lt;br /&gt;
    b = md5_ii(b, c, d, a, x[i+ 9], 21, -343485551);&lt;br /&gt;
&lt;br /&gt;
    a = safe_add(a, olda);&lt;br /&gt;
    b = safe_add(b, oldb);&lt;br /&gt;
    c = safe_add(c, oldc);&lt;br /&gt;
    d = safe_add(d, oldd);&lt;br /&gt;
  }&lt;br /&gt;
  return Array(a, b, c, d);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * These functions implement the four basic operations the algorithm uses.&lt;br /&gt;
 */&lt;br /&gt;
function md5_cmn(q, a, b, x, s, t)&lt;br /&gt;
{&lt;br /&gt;
  return safe_add(bit_rol(safe_add(safe_add(a, q), safe_add(x, t)), s),b);&lt;br /&gt;
}&lt;br /&gt;
function md5_ff(a, b, c, d, x, s, t)&lt;br /&gt;
{&lt;br /&gt;
  return md5_cmn((b &amp;amp; c) | ((~b) &amp;amp; d), a, b, x, s, t);&lt;br /&gt;
}&lt;br /&gt;
function md5_gg(a, b, c, d, x, s, t)&lt;br /&gt;
{&lt;br /&gt;
  return md5_cmn((b &amp;amp; d) | (c &amp;amp; (~d)), a, b, x, s, t);&lt;br /&gt;
}&lt;br /&gt;
function md5_hh(a, b, c, d, x, s, t)&lt;br /&gt;
{&lt;br /&gt;
  return md5_cmn(b ^ c ^ d, a, b, x, s, t);&lt;br /&gt;
}&lt;br /&gt;
function md5_ii(a, b, c, d, x, s, t)&lt;br /&gt;
{&lt;br /&gt;
  return md5_cmn(c ^ (b | (~d)), a, b, x, s, t);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Add integers, wrapping at 2^32. This uses 16-bit operations internally&lt;br /&gt;
 * to work around bugs in some JS interpreters.&lt;br /&gt;
 */&lt;br /&gt;
function safe_add(x, y)&lt;br /&gt;
{&lt;br /&gt;
  var lsw = (x &amp;amp; 0xFFFF) + (y &amp;amp; 0xFFFF);&lt;br /&gt;
  var msw = (x &amp;gt;&amp;gt; 16) + (y &amp;gt;&amp;gt; 16) + (lsw &amp;gt;&amp;gt; 16);&lt;br /&gt;
  return (msw &amp;lt;&amp;lt; 16) | (lsw &amp;amp; 0xFFFF);&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
/*&lt;br /&gt;
 * Bitwise rotate a 32-bit number to the left.&lt;br /&gt;
 */&lt;br /&gt;
function bit_rol(num, cnt)&lt;br /&gt;
{&lt;br /&gt;
  return (num &amp;lt;&amp;lt; cnt) | (num &amp;gt;&amp;gt;&amp;gt; (32 - cnt));&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
// &amp;lt;/nowiki&amp;gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=User:Sdaau/monobook.js&amp;diff=2236</id>
		<title>User:Sdaau/monobook.js</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=User:Sdaau/monobook.js&amp;diff=2236"/>
		<updated>2010-11-05T01:57:40Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: tried adding LivePreview - instaview&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;// Install InstaView&lt;br /&gt;
document.write('&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://en.wikipedia.org/w/index.php?title=User:Pilaf/instaview.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&amp;amp;dontcountme=s&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
InstaView.conf.user.name = 'Sdaau';&lt;br /&gt;
&lt;br /&gt;
/* This is to keep track of who is using InstaView: [[User:Pilaf/instaview.js]] */&lt;br /&gt;
&lt;br /&gt;
/************ OLD STUFF *************&lt;br /&gt;
&lt;br /&gt;
// Live Preview customization,&lt;br /&gt;
// edit this to your own liking.&lt;br /&gt;
&lt;br /&gt;
wpUserName   = 'Pilaf';   // User name to display in signatures&lt;br /&gt;
wpShowImages = true;      // Enable downloading and displaying of images&lt;br /&gt;
&lt;br /&gt;
// Include Live Preview...&lt;br /&gt;
document.write('&amp;lt;script type=&amp;quot;text/javascript&amp;quot; src=&amp;quot;http://en.wikipedia.org/w/index.php?title=User:Pilaf/livepreview.js&amp;amp;action=raw&amp;amp;ctype=text/javascript&amp;amp;dontcountme=s&amp;quot;&amp;gt;&amp;lt;/script&amp;gt;');&lt;br /&gt;
&lt;br /&gt;
// Now set everything up&lt;br /&gt;
window.onload = Main;&lt;br /&gt;
&lt;br /&gt;
function Main()&lt;br /&gt;
{&lt;br /&gt;
 LivePreviewInstall();&lt;br /&gt;
 // You may include here other &amp;quot;extensions&amp;quot;&lt;br /&gt;
}&lt;br /&gt;
&lt;br /&gt;
*/&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=FramesPeriods&amp;diff=2235</id>
		<title>FramesPeriods</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=FramesPeriods&amp;diff=2235"/>
		<updated>2010-11-04T23:27:20Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: /* Additional example */ - added mailing list quote&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A frame is equivalent of one sample being played, irrespective of the number of channels or the number of bits. e.g.&lt;br /&gt;
* 1 frame of a Stereo 48khz 16bit PCM stream is 4 bytes.&lt;br /&gt;
* 1 frame of a 5.1 48khz 16bit PCM stream is 12 bytes.&lt;br /&gt;
&lt;br /&gt;
A period is the number of frames in between each hardware interrupt. The poll() will return once a period.&lt;br /&gt;
&lt;br /&gt;
The buffer is a ring buffer. The buffer size always has to be greater than one period size. Commonly this is 2*period size, but some hardware can do 8 periods per buffer. It is also possible for the buffer size to not be an integer multiple of the period size.&lt;br /&gt;
&lt;br /&gt;
Now, if the hardware has been set to 48000Hz , 2 periods, of 1024 frames each, making a buffer size of 2048 frames. The hardware will interrupt 2 times per buffer. ALSA will endeavor to keep the buffer as full as possible. Once the first period of samples has been played, the third period of samples is transfered into the space the first one occupied while the second period of samples is being played. (normal ring buffer behaviour).&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Additional example ==&lt;br /&gt;
&lt;br /&gt;
Here is an alternative example for the above discussion. &lt;br /&gt;
&lt;br /&gt;
Say we want to work with a stereo, 16-bit, 44.1 KHz stream, ''one-way'' (meaning, ''either'' in playback ''or'' in capture direction). Then we have:&lt;br /&gt;
* 'stereo' = '''number of channels''': 2&lt;br /&gt;
* 1 '''analog sample''' is represented with 16 bits = 2 bytes&lt;br /&gt;
* 1 '''frame''' represents 1 analog sample from all channels; here we have 2 channels, and so:&lt;br /&gt;
** 1 frame = (num_channels) * (1 sample in bytes) = (2 channels) * (2 bytes (16 bits) per sample) = 4 bytes (32 bits)&lt;br /&gt;
* To sustain 2x 44.1 KHz '''analog rate''' - the system must be capable of '''data transfer rate''', in Bytes/sec: &lt;br /&gt;
** Bps_rate = (num_channels) * (1 sample in bytes) * (analog_rate) = (1 frame) * (analog_rate) = ( 2 channels ) * (2 bytes/sample) * (44100 samples/sec) = 2*2*44100 = 176400 Bytes/sec ([http://latex.codecogs.com/png.latex?\begin{array}{ccc}&amp;amp;space;Bps\_rate&amp;amp;space;&amp;amp;=&amp;amp;space;(analog\_rate)&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(num\_channels)&amp;amp;space;\cdot&amp;amp;space;(1\&amp;amp;space;\text{sample&amp;amp;space;(as&amp;amp;space;bytes)})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;(analog\_rate)&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(1\&amp;amp;space;\text{frame})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;(44100\&amp;amp;space;\frac{\text{samples}}{\text{sec}})&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(&amp;amp;space;2\&amp;amp;space;\text{channels}&amp;amp;space;)&amp;amp;space;\cdot&amp;amp;space;(2\&amp;amp;space;\frac{\text{bytes}}{\text{sample}})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;(44100\&amp;amp;space;\frac{\text{frames}}{\text{sec}})&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(4\&amp;amp;space;\frac{\text{bytes}}{\text{frame}})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;176400\&amp;amp;space;\frac{\text{bytes}}{\text{sec}}&amp;amp;space;\end{array} link to formula img])&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
[[Image:alsa_bps_formula.png|frame|center|Alsa Bps formula]] &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
Now, if ALSA would interrupt each second, asking for bytes - we'd need to have 176400 bytes ready for it (at end of each second), in order to sustain analog 16-bit stereo @ 44.1Khz. &lt;br /&gt;
* If it would interrupt each half a second, correspondingly for the same stream we'd need 176400/2 = 88200 bytes ready, at each interrupt; &lt;br /&gt;
* if the interrupt hits each 100 ms, we'd need to have 176400*(0.1/1) = 17640 bytes ready, at each interrupt. &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
We can control when this PCM interrupt is generated, by setting a ''period size'', which is set in ''frames''. &lt;br /&gt;
* Thus, if we set 16-bit stereo @ 44.1Khz, and the period_size to 4410 frames =&amp;gt; (&amp;lt;small&amp;gt;for 16-bit stereo @ 44.1Khz, 1 frame equals 4 bytes - so 4410 frames equal 4410*4 = 17640 bytes&amp;lt;/small&amp;gt;) =&amp;gt; an interrupt will be generated each 17640 bytes - that is, each 100 ms. &lt;br /&gt;
* Correspondingly, buffer_size should be at least 2*period_size = 2*4410 = 8820 frames (or 8820*4 = 35280 bytes). &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
It seems ([http://mirror.leaseweb.com/kernel/people/tiwai/docs/writing-an-alsa-driver.pdf writing-an-alsa-driver.pdf]), however, that it is the ALSA runtime that decides on the actual ''buffer_size'' and ''period_size'', depending on: the requested number of channels, and their respective properties (rate and sampling resolution) - as well as the parameters set in the ''snd_pcm_hardware'' structure (in the driver). &lt;br /&gt;
 &lt;br /&gt;
Also, the following quote may be relevant, from &amp;quot;[http://mailman.alsa-project.org/pipermail/alsa-devel/2007-April/000474.html (alsa-devel) Questions about writing a new ALSA driver for a very limitted device]&amp;quot;: &lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;gt; &amp;gt; The &amp;quot;frame&amp;quot; represents the unit, 1 frame = # channels x sample_bytes.&lt;br /&gt;
&amp;gt; &amp;gt; In your case, 1 frame corresponds to 2 channels x 16 bits = 4 bytes.&lt;br /&gt;
&amp;gt; &amp;gt; &lt;br /&gt;
&amp;gt; &amp;gt; The periods is the number of periods in a ring-buffer.  In OSS, called&lt;br /&gt;
&amp;gt; &amp;gt; as &amp;quot;fragments&amp;quot;.&lt;br /&gt;
&amp;gt; &amp;gt; &lt;br /&gt;
&amp;gt; &amp;gt; So,&lt;br /&gt;
&amp;gt; &amp;gt;  - buffer_size = period_size * periods&lt;br /&gt;
&amp;gt; &amp;gt;  - period_bytes = period_size * bytes_per_frame&lt;br /&gt;
&amp;gt; &amp;gt;  - bytes_per_frame = channels * bytes_per_sample &lt;br /&gt;
&amp;gt; &amp;gt;&lt;br /&gt;
&amp;gt; &lt;br /&gt;
&amp;gt; I still don't understand what 'period_size' and a 'period' is?&lt;br /&gt;
&lt;br /&gt;
The &amp;quot;period&amp;quot; defines the frequency to update the status, usually via&lt;br /&gt;
the invokation of interrupts.  The &amp;quot;period_size&amp;quot; defines the frame&lt;br /&gt;
sizes corresponding to the &amp;quot;period time&amp;quot;.  This term corresponds to&lt;br /&gt;
the &amp;quot;fragment size&amp;quot; on OSS.  On major sound hardwares, a ring-buffer&lt;br /&gt;
is divided to several parts and an irq is issued on each boundary.&lt;br /&gt;
The period_size defines the size of this chunk.&lt;br /&gt;
&lt;br /&gt;
On some hardwares, the irq is controlled on the basis of a timer.  In&lt;br /&gt;
this case, the period is defined as the timer frequency to invoke an&lt;br /&gt;
irq.&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[https://bugtrack.alsa-project.org/wiki/wikka.php?wakka=FramesPeriods original] created 2006-09-24 by [[User:JamesCourtierDutton]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]] [[Category:MigratedFromDev]]&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=FramesPeriods&amp;diff=2233</id>
		<title>FramesPeriods</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=FramesPeriods&amp;diff=2233"/>
		<updated>2010-11-04T22:29:48Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: added additional example section&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;A frame is equivalent of one sample being played, irrespective of the number of channels or the number of bits. e.g.&lt;br /&gt;
* 1 frame of a Stereo 48khz 16bit PCM stream is 4 bytes.&lt;br /&gt;
* 1 frame of a 5.1 48khz 16bit PCM stream is 12 bytes.&lt;br /&gt;
&lt;br /&gt;
A period is the number of frames in between each hardware interrupt. The poll() will return once a period.&lt;br /&gt;
&lt;br /&gt;
The buffer is a ring buffer. The buffer size always has to be greater than one period size. Commonly this is 2*period size, but some hardware can do 8 periods per buffer. It is also possible for the buffer size to not be an integer multiple of the period size.&lt;br /&gt;
&lt;br /&gt;
Now, if the hardware has been set to 48000Hz , 2 periods, of 1024 frames each, making a buffer size of 2048 frames. The hardware will interrupt 2 times per buffer. ALSA will endeavor to keep the buffer as full as possible. Once the first period of samples has been played, the third period of samples is transfered into the space the first one occupied while the second period of samples is being played. (normal ring buffer behaviour).&lt;br /&gt;
&lt;br /&gt;
&amp;amp;nbsp;&lt;br /&gt;
&lt;br /&gt;
== Additional example ==&lt;br /&gt;
&lt;br /&gt;
Here is an alternative example for the above discussion. &lt;br /&gt;
&lt;br /&gt;
Say we want to work with a stereo, 16-bit, 44.1 KHz stream, ''one-way'' (meaning, ''either'' in playback ''or'' in capture direction). Then we have:&lt;br /&gt;
* 'stereo' = '''number of channels''': 2&lt;br /&gt;
* 1 '''analog sample''' is represented with 16 bits = 2 bytes&lt;br /&gt;
* 1 '''frame''' represents 1 analog sample from all channels; here we have 2 channels, and so:&lt;br /&gt;
** 1 frame = (num_channels) * (1 sample in bytes) = (2 channels) * (2 bytes (16 bits) per sample) = 4 bytes (32 bits)&lt;br /&gt;
* To sustain 2x 44.1 KHz '''analog rate''' - the system must be capable of '''data transfer rate''', in Bytes/sec: &lt;br /&gt;
** Bps_rate = (num_channels) * (1 sample in bytes) * (analog_rate) = (1 frame) * (analog_rate) = ( 2 channels ) * (2 bytes/sample) * (44100 samples/sec) = 2*2*44100 = 176400 Bytes/sec ([http://latex.codecogs.com/png.latex?\begin{array}{ccc}&amp;amp;space;Bps\_rate&amp;amp;space;&amp;amp;=&amp;amp;space;(analog\_rate)&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(num\_channels)&amp;amp;space;\cdot&amp;amp;space;(1\&amp;amp;space;\text{sample&amp;amp;space;(as&amp;amp;space;bytes)})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;(analog\_rate)&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(1\&amp;amp;space;\text{frame})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;(44100\&amp;amp;space;\frac{\text{samples}}{\text{sec}})&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(&amp;amp;space;2\&amp;amp;space;\text{channels}&amp;amp;space;)&amp;amp;space;\cdot&amp;amp;space;(2\&amp;amp;space;\frac{\text{bytes}}{\text{sample}})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;(44100\&amp;amp;space;\frac{\text{frames}}{\text{sec}})&amp;amp;space;&amp;amp;\cdot&amp;amp;space;(4\&amp;amp;space;\frac{\text{bytes}}{\text{frame}})&amp;amp;space;\\&amp;amp;space;&amp;amp;=&amp;amp;space;176400\&amp;amp;space;\frac{\text{bytes}}{\text{sec}}&amp;amp;space;\end{array} link to formula img])&lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
[[Image:alsa_bps_formula.png|frame|center|Alsa Bps formula]] &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
Now, if ALSA would interrupt each second, asking for bytes - we'd need to have 176400 bytes ready for it (at end of each second), in order to sustain analog 16-bit stereo @ 44.1Khz. &lt;br /&gt;
* If it would interrupt each half a second, correspondingly for the same stream we'd need 176400/2 = 88200 bytes ready, at each interrupt; &lt;br /&gt;
* if the interrupt hits each 100 ms, we'd need to have 176400*(0.1/1) = 17640 bytes ready, at each interrupt. &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
We can control when this PCM interrupt is generated, by setting a ''period size'', which is set in ''frames''. &lt;br /&gt;
* Thus, if we set 16-bit stereo @ 44.1Khz, and the period_size to 4410 frames =&amp;gt; (&amp;lt;small&amp;gt;for 16-bit stereo @ 44.1Khz, 1 frame equals 4 bytes - so 4410 frames equal 4410*4 = 17640 bytes&amp;lt;/small&amp;gt;) =&amp;gt; an interrupt will be generated each 17640 bytes - that is, each 100 ms. &lt;br /&gt;
* Correspondingly, buffer_size should be at least 2*period_size = 2*4410 = 8820 frames (or 8820*4 = 35280 bytes). &lt;br /&gt;
  &lt;br /&gt;
  &lt;br /&gt;
It seems ([http://mirror.leaseweb.com/kernel/people/tiwai/docs/writing-an-alsa-driver.pdf writing-an-alsa-driver.pdf]), however, that it is the ALSA runtime that decides on the actual ''buffer_size'' and ''period_size'', depending on: the requested number of channels, and their respective properties (rate and sampling resolution) - as well as the parameters set in the ''snd_pcm_hardware'' structure (in the driver). &lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
[https://bugtrack.alsa-project.org/wiki/wikka.php?wakka=FramesPeriods original] created 2006-09-24 by [[User:JamesCourtierDutton]]&lt;br /&gt;
&lt;br /&gt;
[[Category:Development]] [[Category:MigratedFromDev]]&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Alsa_bps_formula.png&amp;diff=2232</id>
		<title>File:Alsa bps formula.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Alsa_bps_formula.png&amp;diff=2232"/>
		<updated>2010-11-04T22:16:19Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: Alsa bps formula&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Alsa bps formula&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=Tutorials_and_Presentations&amp;diff=2193</id>
		<title>Tutorials and Presentations</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=Tutorials_and_Presentations&amp;diff=2193"/>
		<updated>2010-09-10T07:10:55Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: /* Developer tutorials */ - added a link to MInivosc page&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;== Developer tutorials ==&lt;br /&gt;
&lt;br /&gt;
*[http://www.suse.de/~mana/alsa090_howto.html ALSA 0.9.0 HOWTO] - Dr Matthias Nagorni has writen a comprehensive tutorial for audio application developers.&lt;br /&gt;
*[http://equalarea.com/paul/alsa-audio.html Howto use the ALSA API] - Paul Davis has also written a brief explanation.&lt;br /&gt;
*[http://www.alsa-project.org/~frank/alsa-sequencer/ ALSA Sequencer (draft)] - Frank van de Pol's draft on programming the alsa sequencer.&lt;br /&gt;
*[http://www.alsa-project.org/~iwai/OSS-Emulation.html Kernel OSS-Emulation] - Takashi Iwai has written some notes on how ALSA handles OSS applications.&lt;br /&gt;
*[http://www.salleurl.edu/~is04069/Modders/Docs/alsadoc.html Programming ALSA (Espanol)] - David Garcia Garzon has written Spanish docs and tutorials&lt;br /&gt;
*[http://ben-collins.blogspot.com/2010/04/writing-alsa-driver.html Basic Alsa Driver Tutorial] - Ben Collins has written a very basic tutorial on the minimum alsa kernel driver&lt;br /&gt;
*[[Minivosc]] - Smilen Dimitrov has written a driver tutorial for a '''mini'''mal '''v'''irtual '''osc'''illator driver (based on some of the resources above)&lt;br /&gt;
&lt;br /&gt;
=== Presentations: ===&lt;br /&gt;
&lt;br /&gt;
*The [http://lad.linuxaudio.org/events/2003_zkm/index.html LAD Meeting @ZKM 2003] in Karlsruhe, April 2003 provided two presentations (among many) from the core ALSA developers Jaroslav and Takashi. You can view slides and listen to .ogg recordings of the presentations.&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp07-ant.png&amp;diff=2176</id>
		<title>File:Minivosc-comp07-ant.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp07-ant.png&amp;diff=2176"/>
		<updated>2010-08-10T09:58:14Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp03-ant.png&amp;diff=2175</id>
		<title>File:Minivosc-comp03-ant.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp03-ant.png&amp;diff=2175"/>
		<updated>2010-08-10T09:57:06Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp03.png&amp;diff=2174</id>
		<title>File:Minivosc-comp03.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp03.png&amp;diff=2174"/>
		<updated>2010-08-10T09:55:37Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp02.png&amp;diff=2173</id>
		<title>File:Minivosc-comp02.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp02.png&amp;diff=2173"/>
		<updated>2010-08-10T09:54:58Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp01.png&amp;diff=2172</id>
		<title>File:Minivosc-comp01.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc-comp01.png&amp;diff=2172"/>
		<updated>2010-08-10T09:54:16Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Minivosc_buffer_viz.png&amp;diff=2171</id>
		<title>File:Minivosc buffer viz.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Minivosc_buffer_viz.png&amp;diff=2171"/>
		<updated>2010-08-10T09:52:59Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
	<entry>
		<id>https://www.alsa-project.org/main/index.php?title=File:Snd-driver-context.png&amp;diff=2170</id>
		<title>File:Snd-driver-context.png</title>
		<link rel="alternate" type="text/html" href="https://www.alsa-project.org/main/index.php?title=File:Snd-driver-context.png&amp;diff=2170"/>
		<updated>2010-08-10T09:52:08Z</updated>

		<summary type="html">&lt;p&gt;Sdaau: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;&lt;/div&gt;</summary>
		<author><name>Sdaau</name></author>
	</entry>
</feed>