title: C++ recording PCM stream in Linux
body: <p>I'm playing a .Wav file on Ubuntu's default PCM device and I can hear the PCM sound in headphone, now I need to record the PCM stream(write the PCM data played in that default PCM device into a local file) with C++. I tried ALSA <code>snd_pcm_readi(capture_handle, buffer, buffer_frames)</code> method as below, the program works fine but the values in buffer are all 0. I think there're several possibilities:</p>
  <ul>
  <li>I didn't select the right PCM device (but I double checked the Wav file was played in default PCM device and the <code>snd_pcm_open ()</code> device argument was indeed &quot;default&quot;)</li>
  <li>the ALSA 'capture' method didn't support 'record' from playing PCM stream as <a href="http://equalarea.com/paul/alsa-audio.html" rel="nofollow noreferrer">this</a> mentioned</li>
  </ul>
  <p>any help? thanks</p>
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;stdlib.h&gt;
  #include &lt;alsa/asoundlib.h&gt;
            
  int main (int argc, char *argv[])
  {
    int i;
    int err;
    char *buffer;
    int buffer_frames = 128;
    unsigned int rate = 44100;
    snd_pcm_t *capture_handle;
    snd_pcm_hw_params_t *hw_params;
      snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
  
    if ((err = snd_pcm_open (&amp;capture_handle, &quot;default&quot;, SND_PCM_STREAM_CAPTURE, 0)) &lt; 0) {
      fprintf (stderr, &quot;cannot open audio device %s (%s)\n&quot;, 
               argv[1],
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;audio interface opened\n&quot;);
             
    if ((err = snd_pcm_hw_params_malloc (&amp;hw_params)) &lt; 0) {
      fprintf (stderr, &quot;cannot allocate hardware parameter structure (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;hw_params allocated\n&quot;);
                   
    if ((err = snd_pcm_hw_params_any (capture_handle, hw_params)) &lt; 0) {
      fprintf (stderr, &quot;cannot initialize hardware parameter structure (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;hw_params initialized\n&quot;);
      
    if ((err = snd_pcm_hw_params_set_access (capture_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) &lt; 0) {
      fprintf (stderr, &quot;cannot set access type (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;hw_params access setted\n&quot;);
      
    if ((err = snd_pcm_hw_params_set_format (capture_handle, hw_params, format)) &lt; 0) {
      fprintf (stderr, &quot;cannot set sample format (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;hw_params format setted\n&quot;);
      
    if ((err = snd_pcm_hw_params_set_rate_near (capture_handle, hw_params, &amp;rate, 0)) &lt; 0) {
      fprintf (stderr, &quot;cannot set sample rate (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
      
    fprintf(stdout, &quot;hw_params rate setted\n&quot;);
  
    if ((err = snd_pcm_hw_params_set_channels (capture_handle, hw_params, 2)) &lt; 0) {
      fprintf (stderr, &quot;cannot set channel count (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;hw_params channels setted\n&quot;);
      
    if ((err = snd_pcm_hw_params (capture_handle, hw_params)) &lt; 0) {
      fprintf (stderr, &quot;cannot set parameters (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;hw_params setted\n&quot;);
      
    snd_pcm_hw_params_free (hw_params);
  
    fprintf(stdout, &quot;hw_params freed\n&quot;);
      
    if ((err = snd_pcm_prepare (capture_handle)) &lt; 0) {
      fprintf (stderr, &quot;cannot prepare audio interface for use (%s)\n&quot;,
               snd_strerror (err));
      exit (1);
    }
  
    fprintf(stdout, &quot;audio interface prepared\n&quot;);
  
    buffer = malloc(128 * snd_pcm_format_width(format) / 8 * 2);
  
    fprintf(stdout, &quot;buffer allocated\n&quot;);
  
    for (i = 0; i &lt; 10; ++i) {
      if ((err = snd_pcm_readi (capture_handle, buffer, buffer_frames)) != buffer_frames) {
        fprintf (stderr, &quot;read from audio interface failed %d (%s)\n&quot;,
                 err, snd_strerror (err));
        exit (1);
      }
      fprintf(stdout, &quot;read %d done\n&quot;, i);
    }
  
    free(buffer);
  
    fprintf(stdout, &quot;buffer freed\n&quot;);
      
    snd_pcm_close (capture_handle);
    fprintf(stdout, &quot;audio interface closed\n&quot;);
  
    exit (0);
  }
  </code></pre>