Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 如何正确设置ALSA设备_C_Linux_Audio_Alsa_Pcm - Fatal编程技术网

C 如何正确设置ALSA设备

C 如何正确设置ALSA设备,c,linux,audio,alsa,pcm,C,Linux,Audio,Alsa,Pcm,编辑:这个问题与建议的重复问题不同,因为我在问如何设置周期/缓冲区大小,以适用于多个目标,每个目标具有不同的声音硬件? 我创建了一些代码,试图在播放OGG文件之前设置ALSA。下面的代码在一个嵌入式Linux平台上工作,但在另一个嵌入式Linux平台上失败,输出如下: Error setting buffersize. Playback open error: Operation not permitted 我只包含了演示该问题的代码设置\u alsa()未完成,无法完全配置alsa设备 #i

编辑:这个问题与建议的重复问题不同,因为我在问
如何设置周期/缓冲区大小,以适用于多个目标,每个目标具有不同的声音硬件?

我创建了一些代码,试图在播放OGG文件之前设置ALSA。下面的代码在一个嵌入式Linux平台上工作,但在另一个嵌入式Linux平台上失败,输出如下:

Error setting buffersize.
Playback open error: Operation not permitted
我只包含了演示该问题的代码<代码>设置\u alsa()未完成,无法完全配置
alsa
设备

#include <alsa/asoundlib.h>

char *buffer;
static char *device = "default";
snd_pcm_uframes_t periodsize = 8192;    /* Periodsize (bytes) */    


int setup_alsa(snd_pcm_t *handle)
{
    int rc; 
    int dir = 0;    
    snd_pcm_uframes_t periods;          /* Number of fragments/periods */
    snd_pcm_hw_params_t *params;
    snd_pcm_sw_params_t *sw_params;
    int rate = 44100;
    int exact_rate;

    int i = 0;

    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_alloca(&params);

    /* Fill it in with default values. */
    if (snd_pcm_hw_params_any(handle, params) < 0)
    {
        fprintf(stderr, "Can not configure this PCM device.\n");
        snd_pcm_close(handle);    
        return(-1);
    }

    /* Set number of periods. Periods used to be called fragments. */ 
    periods = 4;
    if ( snd_pcm_hw_params_set_periods(handle, params, periods, 0) < 0 )
    {
        fprintf(stderr, "Error setting periods.\n");
        snd_pcm_close(handle);    
        return(-1);
    }


    /* Set buffer size (in frames). The resulting latency is given by */
    /* latency = periodsize * periods / (rate * bytes_per_frame)     */
    if (snd_pcm_hw_params_set_buffer_size(handle, params, (periodsize * periods)>>2) < 0)
    {
        fprintf(stderr, "Error setting buffersize.\n");
        snd_pcm_close(handle);    
        return(-1);
    }

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0)
    {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        snd_pcm_close(handle);    
        return -1;
    }

    snd_pcm_hw_params_free(params);
#包括
字符*缓冲区;
静态字符*device=“默认”;
snd_pcm_uframes_t periodsize=8192;/*周期大小(字节)*/
int setup_alsa(snd_pcm_t*手柄)
{
int rc;
int dir=0;
snd_pcm_uframes_t periods;/*片段数/周期数*/
snd_pcm_hw_params_t*params;
snd_pcm_sw_params_t*sw_params;
积分率=44100;
国际精确汇率;
int i=0;
/*分配硬件参数对象*/
snd_pcm_hw_params_alloca(¶ms);
/*用默认值填充它*/
如果(snd_pcm_hw_params_any(句柄,参数)<0)
{
fprintf(stderr,“无法配置此PCM设备。\n”);
snd_pcm_关闭(手柄);
返回(-1);
}
/*设置句点数。句点过去被称为片段。*/
周期=4;
如果(snd_pcm_hw_params_set_periods(句柄、参数、时段,0)<0)
{
fprintf(stderr,“错误设置周期。\n”);
snd_pcm_关闭(手柄);
返回(-1);
}
/*设置缓冲区大小(以帧为单位)*/
/*延迟=周期大小*周期/(速率*每帧字节数)*/
如果(snd_pcm_hw_params_set_buffer_size)(句柄,参数,(周期大小*周期数)>>2)<0)
{
fprintf(stderr,“设置缓冲区大小时出错。\n”);
snd_pcm_关闭(手柄);
返回(-1);
}
/*将参数写入驱动程序*/
rc=snd_pcm_hw_参数(手柄,参数);
if(rc<0)
{
fprintf(stderr,“无法设置硬件参数:%s\n”,snd_strerror(rc));
snd_pcm_关闭(手柄);
返回-1;
}
snd_pcm_hw_params_free(参数);

设置不需要设置特定缓冲区/缓冲区大小以提供平滑音频播放的ALSA的正常方法是什么?***

事实证明,我可以对我的
ALSA
设置例程进行编程,让
ALSA
通过使用
snd\u pcm\u hw\u params\u set\u buffer\u size\u near()确定最近的工作周期/缓冲区大小
而不是
snd\u pcm\u hw\u params\u set\u buffer\u size()

以下代码现在可以在两种平台上工作:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <vorbis/vorbisfile.h>
#include <alsa/asoundlib.h>

char *buffer;
//static char *device = "default";
static char *device = "plughw:0,0";

snd_pcm_uframes_t periodsize = 4096;    /* Periodsize (bytes) */    

int setup_alsa(snd_pcm_t *handle)
{
    int rc; 
    int dir = 0;    
    snd_pcm_uframes_t periods;          /* Number of fragments/periods */
    snd_pcm_hw_params_t *params;
    snd_pcm_sw_params_t *sw_params;
    int rate = 44100;
    int exact_rate;
    int i = 0;

    /* Allocate a hardware parameters object. */
    snd_pcm_hw_params_malloc(&params);

    /* Fill it in with default values. */
    if (snd_pcm_hw_params_any(handle, params) < 0)
    {
        fprintf(stderr, "Can not configure this PCM device.\n");
        snd_pcm_close(handle);    
        return(-1);
    }

    /* Set the desired hardware parameters. */
    /* Non-Interleaved mode */
    snd_pcm_hw_params_set_access(handle, params, SND_PCM_ACCESS_RW_NONINTERLEAVED);
    snd_pcm_hw_params_set_format(handle, params, SND_PCM_FORMAT_S16_LE);

    /* 44100 bits/second sampling rate (CD quality) */
    /* Set sample rate. If the exact rate is not supported */
    /* by the hardware, use nearest possible rate.         */ 
    exact_rate = rate;
    if (snd_pcm_hw_params_set_rate_near(handle, params, &exact_rate, 0) < 0)
    {
        fprintf(stderr, "Error setting rate.\n");
        snd_pcm_close(handle);    
        return(-1);
    }

    if (rate != exact_rate)
    {
        fprintf(stderr, "The rate %d Hz is not supported by your hardware.\n==> Using %d Hz instead.\n", rate, exact_rate);
    }

    /* Set number of channels to 1 */
    if( snd_pcm_hw_params_set_channels(handle, params, 1 ) < 0 )
    {
        fprintf(stderr, "Error setting channels.\n");
        snd_pcm_close(handle);    
        return(-1);
    }

    /* Set number of periods. Periods used to be called fragments. */ 
    periods = 4;
    if ( snd_pcm_hw_params_set_periods(handle, params, periods, 0) < 0 )
    {
        fprintf(stderr, "Error setting periods.\n");
        snd_pcm_close(handle);    
        return(-1);
    }

    snd_pcm_uframes_t size = (periodsize * periods) >> 2;
    if( (rc = snd_pcm_hw_params_set_buffer_size_near( handle, params, &size )) < 0)
    {
        fprintf(stderr, "Error setting buffersize: [%s]\n", snd_strerror(rc) );
        snd_pcm_close(handle);    
        return(-1);
    }
    else
    {
        printf("Buffer size = %lu\n", (unsigned long)size);
    }

    /* Write the parameters to the driver */
    rc = snd_pcm_hw_params(handle, params);
    if (rc < 0)
    {
        fprintf(stderr, "unable to set hw parameters: %s\n", snd_strerror(rc));
        snd_pcm_close(handle);    
        return -1;
    }

    snd_pcm_hw_params_free(params);

    /* Allocate a software parameters object. */
    rc = snd_pcm_sw_params_malloc(&sw_params);
    if( rc < 0 )
    {
        fprintf (stderr, "cannot allocate software parameters structure (%s)\n", snd_strerror(rc) );
        return(-1);
    }

    rc = snd_pcm_sw_params_current(handle, sw_params);
    if( rc < 0 )
    {
        fprintf (stderr, "cannot initialize software parameters structure (%s)\n", snd_strerror(rc) );
        return(-1);
    }

    if((rc = snd_pcm_sw_params_set_avail_min(handle, sw_params, 1024)) < 0)
    {
        fprintf (stderr, "cannot set minimum available count (%s)\n", snd_strerror (rc));
        return(-1);
    }

    rc = snd_pcm_sw_params_set_start_threshold(handle, sw_params, 1);
    if( rc < 0 )
    {
        fprintf(stderr, "Error setting start threshold\n");
        snd_pcm_close(handle);    
        return -1;
    }

    if((rc = snd_pcm_sw_params(handle, sw_params)) < 0)
    {
        fprintf (stderr, "cannot set software parameters (%s)\n", snd_strerror (rc));
        return(-1);
    }

    snd_pcm_sw_params_free(sw_params);

    return 0;
}

/* copied from libvorbis source */
int ov_fopen(const char *path, OggVorbis_File *vf)
{
    int ret = 0;
    FILE *f = fopen(path, "rb");

    if( f )
    {
        ret = ov_open(f, vf, NULL, 0);
        if( ret ) 
        {
            fclose(f);
        }
    }
    else
    {
        ret = -1;
    }
    return( ret );
}


int main(int argc, char *argv[])
{
    // sample rate * bytes per sample * channel count * seconds
    //int bufferSize = 44100 * 2 * 1 * 2;

    int err;
    snd_pcm_t *handle;
    snd_pcm_sframes_t frames;


    buffer = (char *) malloc( periodsize );
    if( buffer )
    {
        if((err = snd_pcm_open(&handle, "default", SND_PCM_STREAM_PLAYBACK, 0)) < 0)
        {
            printf("Playback open error #1: %s\n", snd_strerror(err));
            exit(EXIT_FAILURE);
        }

        if(err = setup_alsa(handle))
        {
            printf("Playback open error #2: %s\n", snd_strerror(err));
            exit(EXIT_FAILURE);
        }

        OggVorbis_File vf;
        int eof = 0;
        int current_section;

        err = ov_fopen(argv[1], &vf);

        if(err != 0)
        {
            perror("Error opening file");
        }
        else
        {
            vorbis_info *vi = ov_info(&vf, -1);
            fprintf(stderr, "Bitstream is %d channel, %ldHz\n", vi->channels, vi->rate);
            fprintf(stderr, "Encoded by: %s\n\n", ov_comment(&vf, -1)->vendor);

            while(!eof)
            {
                long ret = ov_read(&vf, buffer, periodsize, 0, 2, 1, &current_section);
                if(ret == 0)
                {
                    /* EOF */
                    eof = 1;
                }
                else if(ret < 0)
                {
                    /* error in the stream. */
                    fprintf( stderr, "ov_read error %l", ret );
                }
                else
                {
                    frames = snd_pcm_writen(handle, (void *)&buffer, ret/2);
                    if(frames < 0)
                    {
                        printf("snd_pcm_writen failed: %s\n", snd_strerror(frames));
                        if( frames == -EPIPE )
                        {
                            snd_pcm_prepare(handle);
                            //frames = snd_pcm_writen(handle, (void *)&buffer, ret/2);
                        }
                        else
                        {       
                            break;
                        }
                    }
                }
            }
            ov_clear(&vf);
        }
        free( buffer );
        snd_pcm_drain(handle);
        snd_pcm_close(handle);
    }
    return 0;
}
#包括
#包括
#包括
#包括
#包括
字符*缓冲区;
//静态字符*device=“默认”;
静态字符*device=“plughw:0,0”;
snd_pcm_uframes_t periodsize=4096;/*periodsize(字节)*/
int setup_alsa(snd_pcm_t*手柄)
{
int rc;
int dir=0;
snd_pcm_uframes_t periods;/*片段数/周期数*/
snd_pcm_hw_params_t*params;
snd_pcm_sw_params_t*sw_params;
积分率=44100;
国际精确汇率;
int i=0;
/*分配硬件参数对象*/
snd_pcm_hw_params_malloc(¶ms);
/*用默认值填充它*/
如果(snd_pcm_hw_params_any(句柄,参数)<0)
{
fprintf(stderr,“无法配置此PCM设备。\n”);
snd_pcm_关闭(手柄);
返回(-1);
}
/*设置所需的硬件参数*/
/*非交织模式*/
snd_pcm_hw_params_set_access(句柄、参数、snd_pcm_access_RW_非交互);
snd_pcm_hw_params_set_format(句柄、参数、snd_pcm_format_S16_LE);
/*44100位/秒采样率(CD质量)*/
/*设置采样率。如果不支持精确的采样率*/
/*根据硬件,使用最接近的速率。*/
准确率=比率;
如果(snd_pcm_hw_params_set_rate_near(句柄、参数和精确速率,0)<0)
{
fprintf(标准“错误设置率”。\n”);
snd_pcm_关闭(手柄);
返回(-1);
}
if(费率!=准确费率)
{
fprintf(stderr,“速率%d Hz不受硬件支持。\n==>改用%d Hz。\n”,速率,精确速率);
}
/*将通道数设置为1*/
如果(snd_pcm_hw_params_set_地震道(句柄,参数,1)<0)
{
fprintf(stderr,“设置通道时出错。\n”);
snd_pcm_关闭(手柄);
返回(-1);
}
/*设置句点数。句点过去被称为片段。*/
周期=4;
如果(snd_pcm_hw_params_set_periods(句柄、参数、时段,0)<0)
{
fprintf(stderr,“错误设置周期。\n”);
snd_pcm_关闭(手柄);
返回(-1);
}
snd_pcm_uframes_t size=(periodsize*periods)>>2;
如果((rc=snd_pcm_hw_params_set_buffer_size_near(handle、params和size))<0)
{
fprintf(stderr,“错误设置缓冲区大小:[%s]\n”,snd_strerror(rc));
snd_pcm_关闭(手柄);
返回(-1);
}
其他的
{
printf(“缓冲区大小=%lu\n”,(无符号长)大小);
}
/*将参数写入驱动程序*/
rc=snd_pcm_hw_参数(手柄,参数);
if(rc<0)
{
fprintf(stderr,“无法设置硬件参数:%s\n”,snd_strerror(rc));
snd_pcm_关闭(手柄);
返回-1;
}
snd_pcm_hw_params_free(参数);
/*分配软件参数对象*/
rc=snd_pcm_sw_参数_malloc(&sw_参数);
if(rc<0)
{
fprintf(stderr,“无法分配软件参数结构(%s)\n”,snd_strerror(rc));
返回(-1);
}
rc=snd_pcm_sw_参数_电流(手柄,sw_参数);
if(rc<0)
{
fprintf(stderr,“无法初始化软件参数结构(%s)\n)”,snd_strerror(rc));
返回(-1);
}
如果((rc=snd_pcm_sw_params_set_avail_min)(手柄,sw_params