嵌入式设备中经常需要用的音频,音频设备最原始的数据格式就是 PCM,也就是大家常见的 WAV,在 linux 中,音频编程使用最多的就是 alsa 框架,下面就来看一下 pcm 音频的编程实例吧.
首先需要包含头文件:
定义产量与结构体
snd_pcm_t * alsaplayhdl;
snd_pcm_t * alsacapturehdl;
snd_mixer_t * mixerfd;
snd_mixer_elem_t * elem;
pthread_mutex_t alsa_play_mutex;
pthread_mutex_t alsa_cap_mutex;
snd_pcm_hw_params_t * dispalsa_hwparams;
snd_pcm_sw_params_t * dispalsa_swparams;
snd_pcm_hw_params_t * capturehwparams;
snd_pcm_sw_params_t * captureswparams;
定义设备号:
#define ALSADEVNAME "default"
打开设备:
void open_dev(void) {
int ret = -1;
ret = snd_pcm_open( & alsaplayhdl, ALSADEVNAME, SND_PCM_STREAM_PLAYBACK, 0);
if (ret < 0) {
printf("open alsa display failture\n");
}
}关闭设备:
void close_dev(void) {
int ret = -1;
pthread_t tid;
if (alsaplayhdl != NULL) {
snd_pcm_drop(alsaplayhdl);
ret = snd_pcm_close(alsaplayhdl);
if (ret < 0) {
printf("alsa close dev failture\n");
}
alsaplayhdl = NULL;
}
}
写入音频数据
int alsa_write(char * buf, int length) {
int frames;
int ret = 0;
int write = 0,
size;
long int audiodisplay[2];
audiodisplay[0]++; //正常情况下,alsa_write_audiobuf()调用一次,sysglobaldata_status.audiodisplay[0]的值增加1.如果该值长久没有变化时表明声音播放异常
frames = snd_pcm_writei(alsaplayhdl, buf, length / 2);
if (frames == -EPIPE) {
printf("apps write buff too Slow!-EPIPE\n");
snd_pcm_prepare(alsaplayhdl);
frames = snd_pcm_writei(alsaplayhdl, buf, length / 2);
} else if (frames < 0) {
printf("snd_pcm_writei call failure:%s\n", snd_strerror(ret));
frames = snd_pcm_recover(alsaplayhdl, frames, 0);
}
ret = frames * 2;
err: return ret;
}
读取设备音频数据
int alsa_read(char * buf, int length) {
int frames;
int ret = -1;
int read;
pthread_mutex_lock( & alsa_cap_mutex);
frames = snd_pcm_avail(alsacapturehdl);
if (frames <= 0) {
goto err;
}
read = frames * 2 > length ? length: frames * 2;
frames = snd_pcm_readi(alsacapturehdl, buf, read / 2);
if (frames < 0) {
goto err;
}
ret = frames * 2;
err: pthread_mutex_unlock( & alsa_cap_mutex);
return ret;
}
打开混音器
int open_mixer(void) {
int ret;
unsigned char mixercount;
if (mixercount <= 0) {
ret = snd_mixer_open( & mixerfd, 0); // 打开混音器
if (ret < 0) {
printf("alsa mixer open failture\n");
return - 1;
}
ret = snd_mixer_attach(mixerfd, "default"); // 先设定为默认
if (ret < 0) {
printf("alsa mixer attach failture\n");
return - 2;
}
ret = snd_mixer_selem_register(mixerfd, NULL, NULL); // 注册混音器
if (ret < 0) {
printf("alsa mixer register failture\n");
return - 3;
}
ret = snd_mixer_load(mixerfd);
if (ret < 0) {
printf("alsa mixer load failture\n");
return - 4;
}
mixercount = 0;
}
mixercount++;
return mixercount;
}
设置设备音量
int set_volume(int volume) {
int err;
int orig_volume = 0;
static snd_ctl_t * handle = NULL;
snd_ctl_elem_info_t * info;
snd_ctl_elem_id_t * id;
snd_ctl_elem_value_t * control;
unsigned int count;
snd_ctl_elem_type_t type;
snd_ctl_elem_info_alloca( & info);
snd_ctl_elem_id_alloca( & id);
snd_ctl_elem_value_alloca( & control);
snd_ctl_elem_id_set_interface(id, SND_CTL_ELEM_IFACE_MIXER);
snd_ctl_elem_id_set_name(id, "Mic Capture Volume");
if ((err = snd_ctl_open( & handle, "default", 0)) < 0) {
printf("open ctl device failed\n");
return - 1;
}
snd_ctl_elem_info_set_id(info, id);
if ((err = snd_ctl_elem_info(handle, info)) < 0) {
printf("snd_ctl_elem_info failed\n");
snd_ctl_close(handle);
handle = NULL;
return - 1;
}
type = snd_ctl_elem_info_get_type(info);
count = snd_ctl_elem_info_get_count(info);
snd_ctl_elem_value_set_id(control, id);
if (!snd_ctl_elem_read(handle, control)) {
orig_volume = snd_ctl_elem_value_get_integer(control, 0);
}
if (volume != orig_volume) {
//snd_ctl_elem_value_set_integer(control, 0, static_cast<long>(volume));
snd_ctl_elem_value_set_integer(control, 0, volume);
snd_ctl_elem_value_set_integer(control, 1, volume);
if ((err = snd_ctl_elem_write(handle, control)) < 0) {
printf("snd_ctl_elem_write failed\n");
snd_ctl_close(handle);
handle = NULL;
return - 1;
}
}
snd_ctl_close(handle);
handle = NULL;
return 1;
}
来源: http://lib.csdn.net/article/embeddeddevelopment/34823