采集流程:
1.打开PCM(snd_pcm_open)
2.配置PCM硬件配置空间容器(设置采样格式、采样率、声道、周期等等)
3.读取音频数据
#include
#include
int main()
{
snd_pcm_t *handle;//PCM句柄
//打开一个PCM(PCM捕获)
int ret = snd_pcm_open(&handle,"hw:1",SND_PCM_STREAM_CAPTURE,0);
if(ret < 0){
fprintf(stderr,"unable to open pcm device: %s\n",snd_strerror(ret));
exit(1);
}
//配置硬件参数结构体(PCM硬件配置空间容器)
snd_pcm_hw_params_t *params;
//params申请内存(使用标准alloca分配无效的snd_pcm_hw_参数)
snd_pcm_hw_params_alloca(¶ms);
//使用pcm设备初始化hwparams(用PCM的完整配置空间填充参数)
snd_pcm_hw_params_any(handle,params);
//设置多路数据在buffer中的存储方式
//SND_PCM_ACCESS_RW_INTERLEAVED每个周期(period)左右声道的数据交叉存放
snd_pcm_hw_params_set_access(handle,params,SND_PCM_ACCESS_RW_INTERLEAVED);
//设置16位采样格式
snd_pcm_hw_params_set_format(handle,params,SND_PCM_FORMAT_S16_LE);
//设置声道数2
snd_pcm_hw_params_set_channels(handle,params,2);
int dir = 0;
unsigned int sampleRate = 44100;
//设置采样率44100,如果采样率不支持,会用硬件支持最接近的采样率
snd_pcm_hw_params_set_rate_near(handle,params,&sampleRate,&dir);
snd_pcm_uframes_t frames = 32;
//设置周期大小(将配置空间限制为最接近目标的周期大小)
snd_pcm_hw_params_set_period_size_near(handle,params,&frames,&dir);
//让这些参数作用于PCM设备(安装从配置空间和SND_PCM_PREPARE选自配置空间的PCM硬件配置)
ret = snd_pcm_hw_params(handle,params);
if(ret <0){
fprintf(stderr,"unable toset hw params: %s\n",snd_strerror(ret));
exit(1);
}
//从配置空间中提取周期大小。
snd_pcm_hw_params_get_period_size(params,&frames,&dir);
int size = frames *4;
char* pcmBuff = (char*)malloc(size);
//从配置空间中提取周期时间
unsigned int val =0;
snd_pcm_hw_params_get_period_time(params,&val,&dir);
//打开输出文件
FILE* pFile;
pFile = fopen("test.pcm","wb");
int index=0;
while(1)
{
//从PCM读取交错帧
ret = snd_pcm_readi(handle,pcmBuff,frames);
if(ret == -EPIPE){//发生暂停事件(Stream被暂停并等待应用程序恢复)
fprintf(stderr,"overrun.... \n");
snd_pcm_prepare(handle);
}
else if(ret < 0){
fprintf(stderr,"error read: %s\n",snd_strerror(ret));
}
else if(ret != frames ){
fprintf(stderr,"less read: %s\n",ret);
}
ret = fwrite(pcmBuff,sizeof(char),size,pFile);
if(ret != size){
fprintf(stderr,"less write: %s\n",ret);
}
printf("%d\n",index);
index++;
}
snd_pcm_drain(handle);
snd_pcm_close(handle);
free(pcmBuff);
fclose(pFile);
printf("audio capture exit.. \n");
return 0;
}
注意事项:
1.camke需要引入动态链接库
target_link_libraries(文件名
"/usr/lib/libasound.so"
)
2. hw:1表示的card1
snd_pcm_open(&handle,"hw:1",SND_PCM_STREAM_CAPTURE,0);
3.使用ffplay播放pcm(注意ffplay会一直播放,读到文件末尾也不会停)
ffplay -ar 44100 -channels 2 -f s16le -i test.pcm