Shrinock
Shrinock

Reputation: 65

Frames during Audio playback are consumed very fast

My requirement is to play 16 bit, 22KHz linear PCM data to audioout using alsa API. I have added 2 section of code which i have written to configure ALSA and audioout wrapper which writes 2048 frames using write API.

Issue : Getting distorted noise and consuming available frames very quickly

I am configuring ALSA using below api's.

//opening audio handle 

    if ((err = snd_pcm_open (&rsettings->ppcm_handle, name, SND_PCM_STREAM_PLAYBACK, 0)) < 0)
{
      return -1;
}


if ((err = snd_pcm_hw_params_malloc (&hw_params)) < 0)
{
         return -1;
}

if ((err = snd_pcm_hw_params_any (rsettings->ppcm_handle, hw_params)) < 0)
{
        return -1;
}

//setting interleaved mode
if ((err = snd_pcm_hw_params_set_access (rsettings->ppcm_handle, hw_params, SND_PCM_ACCESS_RW_INTERLEAVED)) < 0)
{
        return -1;
}
//setting bit depth to 2 byte
if ((err = snd_pcm_hw_params_set_format (rsettings->ppcm_handle, hw_params, SND_PCM_FORMAT_S16_LE) ) < 0)
{
        return -1;
}

//Setting sample rate to 22050 Hz if ((err = snd_pcm_hw_params_set_rate(rsettings->ppcm_handle, hw_params, 22050, 0 ) ) < 0 ) { return -1; }

//setting number of channels to 1
if ((err = snd_pcm_hw_params_set_channels (rsettings->ppcm_handle, hw_params, 1 ) ) < 0) { return -1; }

snd_pcm_uframes_t frame_size = 1024;

    if(( err = snd_pcm_hw_params_set_period_size_near(rsettings->ppcm_handle, hw_params, &frame_size, 0 ) ) < 0 )
{
            printf("\n cannot set size");
            return -1;
}


// setting number of period to 1
if ((err = snd_pcm_hw_params_set_periods(rsettings->ppcm_handle, hw_params, 1, 1 ) ) < 0)
{
       return -1;
}


frame_size = 2048;
//setting buffer size to 2048
if ((err = snd_pcm_hw_params_set_buffer_size_near(rsettings->ppcm_handle, hw_params, &frame_size) ) < 0)
{
        return -1;
}

if ((err = snd_pcm_nonblock (rsettings->ppcm_handle, 0 ) ) < 0)
{
        return -1;
}

if ( (err = snd_pcm_hw_params (rsettings->ppcm_handle, hw_params)) < 0)
{
      return -1;
}

snd_pcm_hw_params_free (hw_params);

if ((err = snd_pcm_prepare (rsettings->ppcm_handle)) < 0)
{
       return -1;
}

I have audioout API using POLLING as below

noOfFrames = 2024

    while( noOfFrames > 0 )
    {    
        if( 0 > ( poll( descriptors, pollDescriptorCount, 500 ) ) )
        {
            printf("error polling for data");

        }
        else
        {
            printf("\nPoll Unblocked");

            if( 0 > ( retVal = snd_pcm_poll_descriptors_revents( rsettings->ppcm_handle, descriptors, pollDescriptorCount, &pollEvent ) ) )
            {
                printf("\nError getting poll events, return value : %d", retVal);
                break;
            }
            else
            {
                frames = snd_pcm_avail_update( rsettings->ppcm_handle );
                printf("\nAvailable channel frames = %d",frames );
                if( frames < 0 )
                {
                    if( frames == -EPIPE )
                    {
                        snd_pcm_prepare( rsettings->ppcm_handle );
                    }
                    else if( frames == -ESTRPIPE )
                    {
                        while (-EAGAIN == snd_pcm_resume( rsettings->ppcm_handle ) )
                            usleep(2000);
                    }
                    else
                    {
                        snd_pcm_prepare( rsettings->ppcm_handle); 
                    }
                }
                else
                {
                    if( frames >= noOfFrames )
                    {
                        if ((framesWritten = snd_pcm_writei(rsettings->ppcm_handle, &pBuffer, noOfFrames)) > 0 )
                        {
                            printf("\nNo of frames written : %d",framesWritten);
                            noOfFrames = noOfFrames - framesWritten;
                            free(descriptors);

                        }

                        else if( framesWritten < 0 )
                        {
                            if( framesWritten == -EPIPE )
                            {
                                snd_pcm_prepare( rsettings->ppcm_handle );
                            }
                            else if( framesWritten == -ESTRPIPE )
                            {
                                while (-EAGAIN == snd_pcm_resume( rsettings->ppcm_handle ))
                                    usleep(2000);
                            }
                            else
                            {
                                snd_pcm_prepare( rsettings->ppcm_handle );
                            }
                        }
                    }
                    else 
                    {
                        if ( ( framesWritten = snd_pcm_writei(rsettings->ppcm_handle, &pBuffer, frames ) ) > 0 )
                        {
                            printf("\nNo of frames written : %d",framesWritten);
                            noOfFrames = noOfFrames - framesWritten;
                            free(descriptors);


                        }

                        else if( framesWritten < 0 )
                        {
                            if( framesWritten == -EPIPE )
                            {
                                snd_pcm_prepare( rsettings->ppcm_handle );
                            }
                            else if( framesWritten == -ESTRPIPE )
                            {
                                while (-EAGAIN == snd_pcm_resume( rsettings->ppcm_handle ))
                                    usleep(2000);
                            }
                            else
                            {
                                snd_pcm_prepare( rsettings->ppcm_handle );
                            }
                        }
                    }
                }
            }

        }
    }

Can some tell where i am going wrong.

Upvotes: 1

Views: 355

Answers (1)

hotpaw2
hotpaw2

Reputation: 70733

Polling to fill Audio Unit buffers with just the requested amount of data will not work. You have to use the Audio Unit callback routines (which the OS calls using a lower latency real-time thread) to fill the audio buffers.

You can poll to pre-fill a lock-free circular fifo with a sufficient amount of audio samples for the Audio Unit callbacks to copy from.

Upvotes: 1

Related Questions