嵌入式设备中经常需要用的音频,音频设备最原始的数据格式就是PCM,也就是大家常见的WAV,在linux中,音频编程使用最多的就是alsa框架,下面就来看一下pcm音频的编程实例吧。
首先需要包含头文件:
#include <alsa/asoundlib.h>
定义产量与结构体
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;
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;
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;
嵌入式设备中经常需要用的音频,音频设备最原始的数据格式就是PCM,也就是大家常见的WAV,在linux中,音频编程使用最多的就是alsa框架,下面就来看一下pcm音频的编程实例吧。 首先需要包含头文件:#include 定义产量与结构体snd_pcm_t *alsaplayhdl;snd_pcm_t *alsacapturehdl;snd_mixer_t
pcm播放的时候,接口snd_pcm_writei 返回 -EPIPE,为underrun
录制音频的时候, 接口snd_pcm_readi 返回 -EPIPE, 为overrun
使用ALSA架构的驱动程序,在实际开发使用过程中,比较常见的错误有-EPIPE,也就是-32?为什么会出现呢?肯定是系统内部不和谐了!EPIPE的错误在播放时出现就是因为驱动buffer没有...
在看音频数据是怎么写的时候,在MixerThread的threadloop函数中,有以下代码完成了往硬件写数据:
int bytesWritten = (int)mOutput->write(mMixBuffer, mixBufferSize);
mOutput来历:
函数AudioFlinger::openOutput中创建了一个MixerThread对象,并将前面调用mAudioH...
[Loong]:之前写过基于ALSA的WAV播放录音程序,见http://blog.csdn.net/sepnic/archive/2011/01/14/6140824.aspx。现在本想好好整理一下ALSA的编程思想,但Google了一下,发现已经有同道做了类似的工作,故将其转载过来,并添加一些本人的疑问以及补充(将会继续补充,原文很多重要的ALSA参数没有提到)。
原文:http://blo
由于历史的原因,在 Linux 环境下有多种API系统可用于声音编程。但没有合适的指引就难以找到合乎自己需要的体系。这里是一个指引,是由Lennart Poettering
所写(参见:Homepage of Lennart),目的就是带你走出这个密林。
最简单的指引莫过于问自己
alsa的音频输出过程
alsa播放音频的原理通过snd_pcm_writei()等函数将音频数据写到alsa的buffer中。alsa启动播放以后,alsa驱动会产生中断,每次中断从buffer中取走period个音频数据帧输出到codec。
音频最后的数据不足一个period
alsa驱动从buffer中是按照一个完整的period个数据帧取走数据的,如果取走的一个period数据中,并不都是音频数据,可能有其他脏数据,那就可能在最后一帧产生噪音。
首先关于buffer和frame的概念还不知道
#include <alsa/asoundlib.h>
3.定义变量
snd_pcm_t *handle; //调用snd_pcm_open打开PCM设备返回的文件句柄,后续的操作都使用是、这个句柄操作这个PCM设备
snd_pcm_hw_para...
http://old.sebug.net/paper/books/scipydoc/wave_pyaudio.html
在虚拟机下不知道为什么就是报错,所以换成的windows下运行,安装教程http://blog.csdn.net/qq_30706581/article/details/56666522
ALSA lib setup.c:548:(add_elem) Cannot o
1. 什么是pcm?
pcm(Pulse-code modulation)脉冲编码调制,是将模拟信号转化为数字信号的一种方法。声音的转化的过程为,先对连续的模拟信号按照固定频率周期性采样,将采样到的数据按照一定的精度进行量化,量化后的信号和采样后的信号差值叫做量化误差,将量化后的数据进行最后的编码存储,最终模拟信号变化为数字信号。
2. pcm的两个重要属性