简体   繁体   中英

ALSA Capture missing frames

I have inherited a chunk of code that is using ALSA to capture an audio input at 8KHz, 8 bits, 1 channel. The code looks rather simple, it sets channels to 1, rate to 8000, and period size to 8000. The goal of this program to gather audio data in 30+ min chunks at a time.

The main loop looks like

int retval;
snd_pcm_uframes_t numFrames = 8000;

while (!exit)
{
   // Gather data
   while( (unsigned int)(retval = snd_pcm_readi ( handle, buffer, numFrames ) ) != numFrames )
   {
      if( retval == -EPIPE )
      {
         cerr << "overrun " << endl;
         snd_pcm_prepare( handle );
      } 
      else if ( reval < 0 )
      {
         cerr << "Error : " << snd_strerror( retval ) << endl;
         break;
      }
   }

   // buffer processing logic here
}

We have been having behavioral issue (not getting the full 8K samples per second, and weird timing), so I added gettimeofday timestamps around the snd_pcm_readi loop to see how time was being used and I got the following :

loop 1 : 1.017 sec loop 2 : 2.019 sec loop 3 : 0 (less than 1ms) loop 4 : 2.016 sec loop 5 : .001 sec

.. the 2 loop pattern continues (even run 2.01x sec, odd run 0-1 ms) for the rest of the run. This means I am acutally getting on average less that 8000 samples per second (loss appears to be about 3 seconds per 10 minutes of running). This does not sync well with the other gathered data. Also we would have expected to process the data at about 1 second intervals, not have 2 back to back processes every 2 seconds or so. As an additional check, I printed out the buffer values are setting the hardware parameters and I got the following :

Buffer Size : 43690 Periods : 5 Period Size : 8000 Period Time : 1000000 Rate : 8000

So in the end I have 2 questions :

1) Why do I get actual data at less than 8 Khz ? (Possible theory, actual hardware is not quite at 8KHz, even if ALSA thinks it can do it).

2) Why the 2 secs/0 secs cycle on the reads which should be 1 second each ? And what can be done to get it to a real 1 second cycle ?

Thanks for the help. Dale Pennington

snd_pcm_readi() returns as many samples as are available. And it will not wait for more if the device is in non-blocking mode.

You have only retval samples. If you want to handle 8000 samples at once, call snd_pcm_readi() in a loop with the remaining buffer.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM