音频播放期间的帧消耗非常快

时间:2016-10-26 11:00:20

标签: linux audio core-audio alsa

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.

问题:快速消除噪音并消耗可用的帧

我正在使用以下api配置ALSA。

//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;
}

//将采样率设置为22050 Hz     if((err = snd_pcm_hw_params_set_rate(rsettings-&gt; ppcm_handle,hw_params,22050,0))&lt; 0)     {             返回-1;     }

//将频道数设置为1
    if((err = snd_pcm_hw_params_set_channels(rsettings-&gt; ppcm_handle,hw_params,1))&lt; 0)     {             返回-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;
}

我有使用POLLING的音频输出API,如下所示

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 );
                            }
                        }
                    }
                }
            }

        }
    }

有人可以告诉我哪里出错了。

1 个答案:

答案 0 :(得分:1)

仅使用所请求的数据量进行轮询以填充音频单元缓冲区将不起作用。您必须使用音频单元回调例程(操作系统使用较低延迟的实时线程调用)来填充音频缓冲区。

您可以轮询以预先填充无锁圆形fifo,其中包含足够数量的音频样本,供音频单元回调复制。