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(¶ms);
/* 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(¶ms);
/* 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, ¤t_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