title: Continuous recording in PortAudio (from mic or output)
body: <p>I am trying to create a music visualizer application in PortAudio, I did some basic research and found some examples on how to record from a mic to a (temporary) file. But there was no example where the data is not used runtime during the recording.</p>
  
  <p>So how can I start a continuous audio-stream where I can catch the data from the current "frame"?</p>
  
  <p>This is how I tried to do it:</p>
  
  <pre><code>#include &lt;stdio.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;time.h&gt;
  #include &lt;stdlib.h&gt;
  
  #include "portaudio.h"
  
  #define SAMPLE_RATE (44100)
  
  typedef struct{
      int frameIndex;
      int maxFrameIndex;
      char* recordedSamples;
  }
  testData;
  
  PaStream* stream;
  
  static int recordCallback(const void* inputBuffer, void* outputBuffer, unsigned long frameCount, const PaStreamCallbackTimeInfo* timeInfo, PaStreamCallbackFlags statusFlags, void* userData){
      testData* data = (testData*)userData;
      const char* buffer_ptr = (const char*)inputBuffer;
      char* index_ptr = &amp;data-&gt;recordedSamples[data-&gt;frameIndex];
  
      long framesToCalc;
      long i;
      int finished;
      unsigned long framesLeft = data-&gt;maxFrameIndex - data-&gt;frameIndex;
  
      if(framesLeft &lt; frameCount){
          framesToCalc = framesLeft;
          finished = paComplete;
      }else{
          framesToCalc = frameCount;
          finished = paContinue;
      }
  
      if(inputBuffer == NULL){
          for(i = 0; i &lt; framesToCalc; i++){
              *index_ptr++ = 0;
          }
      }else{
          for(i = 0; i &lt; framesToCalc; i++){
              *index_ptr++ = *buffer_ptr++;
          }
      }
  
      data-&gt;frameIndex += framesToCalc;
      return finished;
  }
  
  int setup(testData streamData){
      PaError err;
  
      err = Pa_Initialize();
      if(err != paNoError){
          fprintf(stderr, "Pa_Initialize error: %s\n", Pa_GetErrorText(err));
          return 1;
      }
  
      PaStreamParameters inputParameters;
      inputParameters.device = Pa_GetDefaultInputDevice();
      if (inputParameters.device == paNoDevice) {
          fprintf(stderr, "Error: No default input device.\n");
          return 1;
      }
  
      inputParameters.channelCount = 1;
      inputParameters.sampleFormat = paInt8;
      inputParameters.suggestedLatency = Pa_GetDeviceInfo(inputParameters.device)-&gt;defaultLowInputLatency;
      inputParameters.hostApiSpecificStreamInfo = NULL;
  
      err = Pa_OpenStream(&amp;stream, &amp;inputParameters, NULL, SAMPLE_RATE, 256, paClipOff, recordCallback, &amp;streamData);
      if(err != paNoError){
          fprintf(stderr, "Pa_OpenDefaultStream error: %s\n", Pa_GetErrorText(err));
          return 1;
      }
  
      err = Pa_StartStream(stream);
      if(err != paNoError){
          fprintf(stderr, "Pa_StartStream error: %s\n", Pa_GetErrorText(err));
          return 1;
      }
  
      return 0;
  }
  
  void quit(testData streamData){
      PaError err;
      err = Pa_Terminate();
      if(err != paNoError){
          fprintf(stderr, "Pa_Terminate error: %s\n", Pa_GetErrorText(err));
      }
  
      if(streamData.recordedSamples)
          free(streamData.recordedSamples);
  }
  
  int main(){
      int i;
      PaError err;
      testData streamData = {0};
  
      streamData.frameIndex = 0;
      streamData.maxFrameIndex = SAMPLE_RATE;
      streamData.recordedSamples = (char*)malloc(SAMPLE_RATE * sizeof(char));
      if(streamData.recordedSamples == NULL)
          printf("Could not allocate record array.\n");
  
      for(i=0; i&lt;SAMPLE_RATE; i++) 
          streamData.recordedSamples[i] = 0;
  
      //int totalFrames = SAMPLE_RATE;
  
      if(!setup(streamData)){
          printf("Opened\n");
  
          int i = 0;
  
          while(i++ &lt; 500){
  
              if((err = Pa_GetStreamReadAvailable(stream)) != paNoError)
                  break;
  
              while((err = Pa_IsStreamActive(stream)) == 1){
                  Pa_Sleep(1000);
              }
  
              err = Pa_CloseStream(stream);
              if(err != paNoError)
                  break;
  
              streamData.frameIndex = 0;
              for(i=0; i&lt;SAMPLE_RATE; i++) 
                  streamData.recordedSamples[i] = 0;
          }
  
          if(err != paNoError){
              fprintf(stderr, "Active stream error: %s\n", Pa_GetErrorText(err));
          }
  
          quit(streamData);
      }else{
          puts("Couldn't open\n");
      }
      return 0;
  }
  </code></pre>
  
  <p>But it gives the following output:</p>
  
  <pre><code>ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.rear
  ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.center_lfe
  ALSA lib pcm.c:2217:(snd_pcm_open_noupdate) Unknown PCM cards.pcm.side
  ALSA lib pcm_dmix.c:957:(snd_pcm_dmix_open) The dmix plugin supports only playback stream
  Active stream error: Can't read from a callback stream
  </code></pre>