Linux应用程序--ALSA编程
文章摘要:
本文主要描述了采用alsa接口播放wav格式声音方法,稍后抄一些关于alsa的介绍补充。
运行环境:debian8
安装alsa应用程序接口库:
编译选项: -lasound
打开并初始化设备:
#include <alsa/asoundlib.h>
snd_pcm_t *snd_pcm;
snd_pcm_hw_params_t *params;
unsigned int sample = 44100; // 采样率(重要)
unsigned int channels = 1; // 通道数量
snd_pcm_format_t format = SND_PCM_FORMAT_S16_LE;
/*
* 初始化ALSA设备
*/
int alsa_init(void)
{
int ret;
snd_pcm_uframes_t frames = 1024;
// 打开音频设备
ret = snd_pcm_open(&snd_pcm, "default",SND_PCM_STREAM_PLAYBACK, 0);
if (ret)
{
printf("can not open pcm device: %s\r\n", snd_strerror(ret));
return -1;
}
// 分配参数内存(将指针地址传入)
snd_pcm_hw_params_alloca(¶ms);
// 填充默认参数
snd_pcm_hw_params_any(snd_pcm, params);
// 初始化访问权限
ret = snd_pcm_hw_params_set_access(snd_pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED);
if (ret < 0)
{
printf("set_access error: %s\r\n", snd_strerror(ret));
return -2;
}
// 设置数据格式: SND_PCM_FORMAT_S16_LE/S24_LE/U8
snd_pcm_hw_params_set_format(snd_pcm, params, format);
// 设置通道数量(重要)
snd_pcm_hw_params_set_channels(snd_pcm, params, channels);
// 设置采样率(重要)
snd_pcm_hw_params_set_rate_near(snd_pcm, params, &sample, 0);
#if 0
// 设置每个周期有多少帧(可采用默认值)
ret = snd_pcm_hw_params_set_period_size_near(snd_pcm, params,&frames, 0);
if(ret < 0)
{
printf("set_period_size error: %s\r\n", snd_strerror(ret));
}
printf("frames = %d\r\n", frames);
#endif
// 将参数写入设备
ret = snd_pcm_hw_params(snd_pcm, params);
if(ret < 0)
{
printf("write params failed: %s\r\n", snd_strerror(ret));
return -3;
}
// 读取每周期帧数
snd_pcm_hw_params_get_period_size(params, &frames, 0);
return 0;
}
播放WAV格式:
int main(int argc, char** argv)
{
int fd;
int ret;
int count;
char *pdata; // 数据指针
char buff[2048];
snd_pcm_uframes_t frames;
// 打开声音文件
fd = open(argv[1], O_RDONLY);
if (fd < 0)
{
perror("can not open snd file ");
}
// 读取文件头并解析相关参数,此处先跳过文件头,再WAV章节再做解析
ret = read(fd, buff, 44);
// 初始化声卡
alsa_init();
// 获取每周期的帧数
snd_pcm_hw_params_get_period_size(params, &frames, 0);
// 计算单次数据长度 = 每周期帧数*通道号*样本数据位数/8
count = frames * channels * 2;
printf("size = %d\r\n", count);
pdata = malloc(count);
if(pdata == NULL)
{
printf("malloc failed\r\n");
}
while (1)
{
// 从文件读入声音数据
ret = read(fd, pdata, count);
if (ret <= 0)
{
break;
}
// 将数据写入alsa播放(写入的帧数是前边读出来的值)
ret = snd_pcm_writei(snd_pcm, pdata, frames);
if (ret == -EPIPE)
{
snd_pcm_prepare(snd_pcm);
}
}
// 等待缓冲区数据播放结束
while(snd_pcm_avail_update(snd_pcm) > 0)
{
usleep(20 * 1000);
}
snd_pcm_drop(snd_pcm);
snd_pcm_drain(snd_pcm);
snd_pcm_close(snd_pcm); // 关闭ALSA
close(fd); // 关闭文件
}
移植alsa库至ARM平台:
下载地址:https://www.alsa-project.org/files/pub/lib/
软件版本:alsa-lib-1.2.1.tar.bz2
# ./configure --host=arm-linux --prefix=/opt/rootfs CC=arm-linux-gnueabihf-gcc
# make
# make install
注意事项:
V1.2.2版本有问题,交叉编译报错。