1. 利用alsa库录制PCM音频,并保存为音频文件。

(该部分代码摘自网络,原链接不记得了,侵删。但是代码亲测可用,在此做个demo备用)

/*** @file record_pcm.c* @brief 进行音频采集,采集pcm数据并直接保存pcm数据到文件* 音频参数: * 声道数:     2* 采样位数: 16bit、LE格式* 采样频率:    44100Hz* @author  fangye (fangye945@qq.com)* @version 1.0* @date 2021-01-20* @copyright Copyright (c) 2021 xxxx有限公司*/#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
#include "alsa/asoundlib.h"/*PCM的采样格式在pcm.h文件里有定义*/
snd_pcm_format_t format=SND_PCM_FORMAT_S16_LE; // 采样位数:16bit、LE格式
snd_pcm_t *capture_handle;// 一个指向PCM设备的句柄
snd_pcm_hw_params_t *hw_params; //此结构包含有关硬件的信息,可用于指定PCM流的配置static int run_flag=0;
static FILE *pcm_data_file=NULL;
static pthread_t pcm_record_thread_id;static void *pcm_record_task(void *arg)
{int err = 0;int buffer_frames = 128;/*配置一个数据缓冲区用来缓冲数据*/char *buffer = (char *)malloc( buffer_frames * snd_pcm_format_width(format)/8*2 );printf("缓冲区分配成功.\n");/*开始采集音频pcm数据*/printf("开始采集数据...\n");while(1) {/*从声卡设备读取一帧音频数据*/if((err = snd_pcm_readi(capture_handle,buffer,buffer_frames))!=buffer_frames) {printf("从音频接口读取失败(%s)\n",snd_strerror(err));exit(1);}/*写数据到文件*/fwrite(buffer,(buffer_frames*2), sizeof(short), pcm_data_file);if(run_flag){printf("停止采集.\n");break;}}/*释放数据缓冲区*/free(buffer);return NULL;
}/*** @brief 开始pcm音频录制* @param  savepath[in]  pcm音频文件保存路径* @return int  成功返回0,失败返回-1      */
int start_pcm_record(const char *savepath)
{   int i = 0;int err = 0;unsigned int rate = 48000;// 常用的采样频率: 44100Hz 、16000HZ、8000HZ、48000HZ、22050HZ/*打开音频采集卡硬件,并判断硬件是否打开成功,若打开失败则打印出错误提示*/if ((err = snd_pcm_open (&capture_handle, "default", SND_PCM_STREAM_CAPTURE,0))<0) {printf("无法打开音频设备: (%s)\n", snd_strerror (err));return -1;}printf("音频接口打开成功.\n");/*创建一个保存PCM数据的文件*/if((pcm_data_file = fopen(savepath, "wb")) == NULL){printf("无法创建%s音频文件.\n", savepath);return -1;} printf("用于录制的音频文件已打开.\n");/*分配硬件参数结构对象,并判断是否分配成功*/if((err = snd_pcm_hw_params_malloc(&hw_params)) < 0) {printf("无法分配硬件参数结构 (%s)\n",snd_strerror(err));return -1;}printf("硬件参数结构已分配成功.\n");/*按照默认设置对硬件对象进行设置,并判断是否设置成功*/if((err=snd_pcm_hw_params_any(capture_handle,hw_params)) < 0) {printf("无法初始化硬件参数结构 (%s)\n", snd_strerror(err));return -1;}printf("硬件参数结构初始化成功.\n");/*设置数据为交叉模式,并判断是否设置成功interleaved/non interleaved:交叉/非交叉模式。表示在多声道数据传输的过程中是采样交叉的模式还是非交叉的模式。对多声道数据,如果采样交叉模式,使用一块buffer即可,其中各声道的数据交叉传输;如果使用非交叉模式,需要为各声道分别分配一个buffer,各声道数据分别传输。*/if((err = snd_pcm_hw_params_set_access (capture_handle,hw_params,SND_PCM_ACCESS_RW_INTERLEAVED)) < 0) {printf("无法设置访问类型(%s)\n",snd_strerror(err));return -1;}printf("访问类型设置成功.\n");/*设置数据编码格式,并判断是否设置成功*/if ((err=snd_pcm_hw_params_set_format(capture_handle, hw_params,format)) < 0) {printf("无法设置格式 (%s)\n",snd_strerror(err));return -1;}fprintf(stdout, "PCM数据格式设置成功.\n");/*设置采样频率,并判断是否设置成功*/if((err=snd_pcm_hw_params_set_rate_near (capture_handle,hw_params,&rate,0))<0) {printf("无法设置采样率(%s)\n",snd_strerror(err));return -1;}printf("采样率设置成功\n");/*设置声道,并判断是否设置成功*/if((err = snd_pcm_hw_params_set_channels(capture_handle, hw_params, 2)) < 0) {printf("无法设置声道数(%s)\n",snd_strerror(err));return -1;}printf("声道数设置成功.\n");/*将配置写入驱动程序中,并判断是否配置成功*/if ((err=snd_pcm_hw_params (capture_handle,hw_params))<0) {printf("无法向驱动程序设置参数(%s)\n",snd_strerror(err));return -1;}printf("参数设置成功.\n");/*使采集卡处于空闲状态*/snd_pcm_hw_params_free(hw_params);/*准备音频接口,并判断是否准备好*/if((err=snd_pcm_prepare(capture_handle))<0) {printf("无法使用音频接口 (%s)\n",snd_strerror(err));return -1;}printf("音频接口准备好.\n");err = pthread_create(&pcm_record_thread_id, NULL, pcm_record_task, NULL);if(err != 0){printf("创建音频录制线程失败: %s\n",strerror(err));return -1;}printf("创建音频录制线程成功.\n");return 0;
}/*** @brief 停止PCM音频录制*/
void stop_pcm_record()
{run_flag = 1; //结束音频录制pthread_join(pcm_record_thread_id, NULL);   //等待线程退出, 回收线程资源/*关闭音频采集卡硬件*/snd_pcm_close(capture_handle);/*关闭文件流*/fclose(pcm_data_file);
}

2. 利用fdk-aac库将录制的PCM音频文件编码为aac音频文件。

fdk_aac_encode.c 文件:

/*** @file fdk_aac_encode.c* @brief 利用libfdk-aac库将pcm文件编码为aac音频文件* @author  fangye (fangye945@qq.com)* @version 1.0* @date 2021-01-20* @copyright Copyright (c) 2021  XXXX有限公司*/
#include <stdio.h>
#include "fdk_aac_encode.h"#define FRAME_LEN (2*2*1024)static int aac_encode_init(AACContext *paac_context)
{AACENC_InfoStruct info = { 0 };if(!paac_context)return -1;printf("fdk-aac encode param:\n");printf("input channel: %d\n", paac_context->input_ch);printf("encode type: %d\n", paac_context->aacenc_type);printf("sample Rate: %d\n", paac_context->sampleRate);printf("encode channel: %d\n", paac_context->enc_ch);printf("bit_rate: %d\n", paac_context->bit_rate);printf("aac_format: %d\n", paac_context->aac_format);if (aacEncOpen(&paac_context->handle, 0, paac_context->input_ch) != AACENC_OK) {printf("Unable to open fdkaac encoder\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_AOT, paac_context->aacenc_type) != AACENC_OK) {  //aac lc MPEG-4 AAC Low Complexity.printf("Unable to set the AOT\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_SBR_MODE, paac_context->sbr_enable) != AACENC_OK) { printf("Unable to set the SBR MODE enable\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_SAMPLERATE, paac_context->sampleRate) != AACENC_OK) {printf("Unable to set the AOT\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_CHANNELMODE, paac_context->enc_ch) != AACENC_OK) {  // 2 channleprintf("Unable to set the channel mode\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_CHANNELORDER, paac_context->input_ch_order) != AACENC_OK) {  // 2 channleprintf("Unable to set the channel order\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_BITRATEMODE, paac_context->bit_rate_mode) != AACENC_OK) {  // 2 channleprintf("Unable to set the bit_rate_mode\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_BITRATE, paac_context->bit_rate) != AACENC_OK) {printf("Unable to set the bitrate\n");goto error;}if (aacEncoder_SetParam(paac_context->handle, AACENC_TRANSMUX, paac_context->aac_format) != AACENC_OK) { //0-raw 2-adtsprintf("Unable to set the ADTS transmux\n");goto error;}if (aacEncEncode(paac_context->handle, NULL, NULL, NULL, NULL) != AACENC_OK) {printf("Unable to initialize the encoder\n");goto error;}if (aacEncInfo(paac_context->handle, &info) != AACENC_OK) {printf("Unable to get the encoder info\n");goto error;}return 0;error:aacEncClose(&paac_context->handle);return -1;
}static int aac_encode_frame(FILE * outstream, void *pData, unsigned int insize, AACContext *paac_context)
{if(!outstream||!pData||!paac_context)return -1;unsigned char m_aacOutbuf[FRAME_LEN];AACENC_BufDesc in_buf = { 0 }, out_buf = { 0 };AACENC_InArgs in_args = { 0 };AACENC_OutArgs out_args = { 0 };int in_identifier = IN_AUDIO_DATA;int in_elem_size = 2;  in_args.numInSamples = insize/2;                  //size为pcm字节数in_buf.numBufs = 1;in_buf.bufs = &pData;                             //pData为pcm数据指针in_buf.bufferIdentifiers = &in_identifier;in_buf.bufSizes = (INT *)&insize;in_buf.bufElSizes = &in_elem_size;int out_identifier = OUT_BITSTREAM_DATA;void *out_ptr = m_aacOutbuf;unsigned int out_size = sizeof(m_aacOutbuf);int out_elem_size = 1;out_buf.numBufs = 1;out_buf.bufs = &out_ptr;out_buf.bufferIdentifiers = &out_identifier;out_buf.bufSizes = (INT *)&out_size;out_buf.bufElSizes = &out_elem_size;if ((aacEncEncode(paac_context->handle, &in_buf, &out_buf, &in_args, &out_args)) != AACENC_OK) {printf("Encoding aac failed\n");return -2;}if (out_args.numOutBytes == 0){printf("Encoding aac out size is 0\n");return -3;}fwrite(m_aacOutbuf, 1, out_args.numOutBytes, outstream);    //编码后的aac数据存在outbuf中,大小为out_args.numOutBytesreturn 0;
}/*** @brief 将原始PCM音频文件编码为acc音频文件* @param  pcm_file_path[in]    pcm文件* @param  acc_file_path[in]    acc文件* @return int            */
int pcm2aac(const char *pcm_file_path, const char *acc_file_path)
{FILE * out_stream, *in_stream;unsigned char m_aacInbuf[FRAME_LEN];unsigned int m_aacInsize;AACContext aac_context;unsigned int i = 0;//init encoder paramaac_context.input_ch         = 2;aac_context.sbr_enable     = 0;aac_context.aacenc_type    = 2;aac_context.sampleRate         = 48000;aac_context.enc_ch             = MODE_2;aac_context.input_ch_order    = 1;aac_context.bit_rate_mode  = 0;aac_context.bit_rate       = 128*1024;    aac_context.aac_format      = 2;   out_stream = fopen(acc_file_path,"w");in_stream  = fopen(pcm_file_path,"r");if((!out_stream)||(!in_stream))return -1;if(aac_encode_init(&aac_context)<0)goto closefile;while(1){m_aacInsize = fread(m_aacInbuf,1, FRAME_LEN, in_stream);if(m_aacInsize == 0)break;aac_encode_frame(out_stream, (void *)m_aacInbuf, m_aacInsize, &aac_context);//printf("frame%d  size:%d\t", i++, m_aacInsize);}closefile:fclose(in_stream);fclose(out_stream);return 0;
}

fdk_aac_encode.h 文件:

/*** @file fdk_aac_encode.h* @brief aac音频编码头文件* @author  fangye (fangye945@qq.com)* @version 1.0* @date 2021-01-20* @copyright Copyright (c) 2021  XXXX有限公司*/
#ifndef __FDK_ACC_ENCODE_H__
#define __FDK_ACC_ENCODE_H__#include "fdk-aac/aacenc_lib.h"#ifdef __cplusplus
extern "C"{
#endif /* __cplusplus */typedef struct _AACContext {int input_ch;int aacenc_type;   //HE-AACint sbr_enable;     //- -1: Use ELD SBR auto configurator (default). 0: Disable Spectral Band Replication. 1: Enable Spectral Band Replication.int sampleRate;      /*!< Audio input data sampling rate.8000, 11025, 12000, 16000, 22050, 24000, 32000, 44100, 48000, 64000, 88200, 96000 */int enc_ch;          //Channel mode must match with number of input channels.int input_ch_order; /*!< Input audio data channel ordering scheme:- 0: MPEG channel ordering (e. g. 5.1: C, L, R, SL, SR, LFE). (default)- 1: WAVE file format channel ordering (e. g. 5.1: L, R, C, LFE, SL, SR). */int bit_rate_mode;  /*!< Bitrate mode. Configuration can be different kind of bitrate configurations:- 0: Constant bitrate, use bitrate according to ::AACENC_BITRATE. (default)Within none LD/ELD ::AUDIO_OBJECT_TYPE, the CBR mode makes use of full allowed bitreservoir.In contrast, at Low-Delay ::AUDIO_OBJECT_TYPE the bitreservoir is kept very small.- 8: LD/ELD full bitreservoir for packet based transmission. */int bit_rate;       int aac_format;     //0-raw 2-adtsHANDLE_AACENCODER     handle;
} AACContext;extern int pcm2aac(const char *pcm_file_path, const char *acc_file_path);#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* __FDK_ACC_ENCODE`_H__ */

alsa录制pcm音频及fdk-aac编码相关推荐

  1. 在Linux环境下使用ffmpeg将PCM音频数据编码成aac数据

    在Linux环境下使用ffmpeg将PCM音频数据编码成aac数据 程序框图 代码演示 程序框图 将pcm数据经过aac编码器编码成aac数据,我是将从设备上采集的数据经过重采样送入aac编码器进行编 ...

  2. Android使用AudioRecord录制PCM音频、PCM转AAC、使用MediaRecorder直接录制AAC编码音频

    Android为我们提供了两个音频处理的API:AudioRecord和MediaRecorder AudioRecord:偏底层的api MediaRecorder:对AudioRecord进行包装 ...

  3. Android OpenSL ES 开发:Android OpenSL 录制 PCM 音频数据

    一.实现说明 OpenSL ES的录音要比播放简单一些,在创建好引擎后,再创建好录音接口基本就可以录音了.在这里我们做的是流式录音,所以需要用至少2个buffer来缓存录制好的PCM数据,这里我们可以 ...

  4. Qt录制音频为pcm并进行ffmpeg aac编码

      Qt提供了音频采集功能,主要涉及到3个类,QAudioFormat,QAudioInput,QIODevice.   在进行音频采集时先用QAudioFormat设置采集参数,然后创建音频输入对象 ...

  5. 音视频开发系列(27)AudioRecord录制PCM音频

    目录 音频采集API AudioRecord和MediaRecorder介绍 PCM的介绍 AudioRecord的使用(构造.开始录制.停止录制.其他细节点) ffplay播放pcm pcm转为wa ...

  6. 音视频开发之旅(二)AudioRecord录制PCM音频

    目录 音频采集API AudioRecord和MediaRecorder介绍 PCM的介绍 AudioRecord的使用(构造.开始录制.停止录制.其他细节点) ffplay播放pcm pcm转为wa ...

  7. 音视频开发(二):AudioRecord录制PCM音频

    目录 音频采集API AudioRecord和MediaRecorder介绍 PCM的介绍 AudioRecord的使用(构造.开始录制.停止录制.其他细节点) ffplay播放pcm pcm转为wa ...

  8. 【开源项目】基于QT录制PCM音频实例详细

    #include "QtAudio_input.h" #include <QtWidgets/QApplication> #include<QAudioInput ...

  9. Android使用AudioRecord录制pcm音频原始数据以及使用AudioTrack播放

    https://github.com/z13538657403/Android_PCM_Record_Play

最新文章

  1. 如何在调试页面的时候清除页面的缓存?
  2. MVC应用程序实现上传文件(续)
  3. Java Web编程的主要组件技术——Hibernate入门
  4. subscribe error不执行_你不知道的redis:第三方jar无封装命令我们该怎么执行?
  5. Selenium自动化测试-5.脚本录制神器Katalon Recorder
  6. 空军预警学院计算机与网络,空军预警学院学报
  7. android自定义ViewPager之——处理与ScrollView的事件冲突
  8. Eclipse 可视化插件Windows Builder在线更新地址
  9. 微信小程序wx.getUserInfo授权获取用户信息(头像、昵称)的实现
  10. IE浏览器http请求缓存问题
  11. 中文语音软件再次升级,即将发布百度语音助手
  12. The harder I work, the luckier I get. - Samuel Goldwyn
  13. 如何用安装启动盘启动计算机,如何使用U盘启动进入PE安装系统,小编教你如何安装...
  14. Matlab统计图片中不同颜色小球个数
  15. html5大全,常用html5标签大全 - 小俊学习网
  16. envi反演水质参数_遥感干旱反演方法汇总
  17. Docker推送一个自制镜像到dockerhub
  18. 超声波测距仪编程_Micropython教程之TPYBoard DIY超声波测距仪实例演示
  19. linux 文件 图标 覆盖,在Deepin下处理Microsoft Edge替换图标及替换文件
  20. 华为云CDN加速,真正的六边形战士

热门文章

  1. Unity检测网络连接状态
  2. idea下将scala编写的项目打成jar包
  3. 【论文阅读】Learning with Hypergraphs: Clustering, Classification, and Embedding
  4. [分享]NOAA磁偏角计算器
  5. 缩放比例 页面缩放 自适应布局(布局不变)vue
  6. Unity地形材质贴图随高度变化
  7. EasyCVR视频广场可以播放WebRTC,设备中却无法播放是什么原因?
  8. 网络中数据的封装与解封装
  9. 计算机及应用(独立本科段)B080702|学习考试顺序梳理 (专业名现更改为计算机科学与技术)
  10. 软考高级系统架构设计师:论面向服务的架构及其应用