title: ALSA: proper way to playback audio - blocking mode and threads
body: <p>I cannot get the correct way to write my loop to play audio and/or I don't understand correctly the meaning of start_threshold, stop_threshold and avail_min parameters for Alsa. I'd like to reach the lowest latency and know the correct parameters to modify in order to make my capture-process-playback chain tolerant to variations in the audio processing time. In this example I'm reading samples from file, to focus on the playback part.</p>
  
  <p>This is my output device configuration, opened in blocking mode (Ubuntu 16.04, PulseAudio present, <code>default</code> device):</p>
  
  <pre><code>ALSA &lt;-&gt; PulseAudio PCM I/O Plugin
  Its setup is:
    stream       : PLAYBACK
    access       : RW_INTERLEAVED
    format       : FLOAT_LE
    subformat    : STD
    channels     : 1
    rate         : 44100
    exact rate   : 44100 (44100/1)
    msbits       : 32
    buffer_size  : 6144
    period_size  : 2048
    period_time  : 46439
    tstamp_mode  : NONE
    tstamp_type  : GETTIMEOFDAY
    period_step  : 1
    avail_min    : 4096
    period_event : 0
    start_threshold  : 2048
    stop_threshold   : 2048
    silence_threshold: 0
    silence_size : 0
    boundary     : 6917529027641081856
  </code></pre>
  
  <p>My playback thread gets audio buffers from another thread which reads samples from file (hence faster than the playback rate). This is the playback function (Cython code):</p>
  
  <pre><code>cdef int play_buffer(self, buffer_t *buf) nogil:
  
      cdef int rc
      cdef long t0, t1
  
      t0 = timestamp_us()
      rc = snd_pcm_writei(self.handle, buf.data, buf.period_size)
      t1 = timestamp_us()
  
      if rc &gt;= 0:
          printf("[%ld / %6ld] snd_pcm_writei: OK %d\n", t0, t1 - t0, rc)
      else:
          printf("[%ld / %6ld] snd_pcm_writei: ERR %d [%s]\n", t0, t1 - t0, rc, snd_strerror(rc))
  
      if rc &lt; 0:
          if rc == -errno.EPIPE:
              rc = snd_pcm_prepare(self.handle)
              printf("snd_pcm_prepare: %d\n", rc)
  
          else:
              printf("play_buffer ERR %d\n", rc)
              return WRITE_ERROR
  
      elif rc != buf.period_size:
          printf('snd_pcm_writei(): short write %d != %d', rc, buf.period_size)
  
      return OK
  </code></pre>
  
  <p>This is the output (<code>timestamp_us()</code> returns the system time in microseconds):</p>
  
  <pre><code>[1525102519583090 /    540] snd_pcm_writei: OK 2048
  [1525102519585406 /     16] snd_pcm_writei: ERR -32 [Broken pipe]
  snd_pcm_prepare: 0
  [1525102519587798 /    393] snd_pcm_writei: OK 2048
  [1525102519590018 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
  snd_pcm_prepare: 0
  [1525102519592303 /    415] snd_pcm_writei: OK 2048
  [1525102519594523 /      3] snd_pcm_writei: ERR -32 [Broken pipe]
  snd_pcm_prepare: 0
  [1525102519596823 /   1905] snd_pcm_writei: OK 2048
  [1525102519599242 /     12] snd_pcm_writei: ERR -32 [Broken pipe]
  snd_pcm_prepare: 0
  [1525102519601707 /   8023] snd_pcm_writei: OK 2048
  [1525102519609754 /     45] snd_pcm_writei: OK 2048
  [1525102519609811 /     27] snd_pcm_writei: OK 2048
  [1525102519609847 /     28] snd_pcm_writei: OK 2048
  [1525102519611328 /     40] snd_pcm_writei: OK 2048
  [1525102519613546 /  48501] snd_pcm_writei: OK 2048
  [1525102519662079 /  50678] snd_pcm_writei: OK 2048
  [1525102519712804 /  49487] snd_pcm_writei: OK 2048
  [1525102519762318 /  50521] snd_pcm_writei: OK 2048
  [1525102519812868 /  49497] snd_pcm_writei: OK 2048
  [1525102519862394 /  49630] snd_pcm_writei: OK 2048
  [1525102519912051 /  49875] snd_pcm_writei: OK 2048
  [1525102519961953 /  50647] snd_pcm_writei: OK 2048
  [1525102520012655 /  49949] snd_pcm_writei: OK 2048
  [1525102520062632 /  49713] snd_pcm_writei: OK 2048
  [1525102520112373 /  49495] snd_pcm_writei: OK 2048
  [1525102520161898 /     62] snd_pcm_writei: OK 2048
  [1525102520161977 /  50485] snd_pcm_writei: OK 2048
  [1525102520212490 /  49514] snd_pcm_writei: OK 2048
  .. continues with no errors ...
  </code></pre>
  
  <p>I don't get the reason of these EPIPE errors at the beginning; What I'm expecting is that <code>snd_pcm_writei</code> either returns immediately or waits (more or less) a period duration time before returning, because I'm in blocking mode and I'm faster to provide samples than the playback sample rate requires.
  When the error sequence ends the playback is fine. Moreover, if I set the realtime priority to my threads (<code>pthread_setschedparam()</code>) I get an endless list of OK 2048 / ERR -32 and I hear only noise. This is really weird to me.</p>
  
  <p>Where's my mistake?</p>
  
  <p>Thanks.</p>