天天微速讯:如何将PCM格式的原始音频采样数据编码为MP3格式或AAC格式的音频文件?

2023-06-20 12:23:11 | 来源:博客园

一.打开和关闭输入文件和输出文件以及判断输入文件是否读取完毕


(资料图片仅供参考)

//io_data.cppstatic FILE* input_file= nullptr;static FILE* output_file= nullptr;int32_t open_input_output_files(const char* input_name,const char* output_name){    if(strlen(input_name)==0||strlen(output_name)==0){        cout<<"Error:empty input or output file name."<

二.音频编码器的初始化

//audio_encoder_core.cppstatic const AVCodec* codec= nullptr;static AVCodecContext* codec_ctx= nullptr;static AVFrame* frame= nullptr;static AVPacket* pkt= nullptr;static enum AVCodecID audio_codec_id;int32_t init_audio_encoder(const char* codec_name){    if(strcasecmp(codec_name,"MP3")==0){        audio_codec_id=AV_CODEC_ID_MP3;        cout<<"Select codec id:MP3"<bit_rate=128000;    codec_ctx->sample_fmt=AV_SAMPLE_FMT_FLTP;    codec_ctx->sample_rate=44100;    codec_ctx->channel_layout=AV_CH_LAYOUT_STEREO;    codec_ctx->channels=2;    int32_t result=avcodec_open2(codec_ctx,codec, nullptr);    if(result<0){        cerr<<"Error:could not open codec."<nb_samples=codec_ctx->frame_size;//采样点数量    frame->format=codec_ctx->sample_fmt;    frame->channel_layout=codec_ctx->channel_layout;    result= av_frame_get_buffer(frame,0);    if(result<0){        cerr<<"Error:AVFrame could not get buffer."<

三.编码循环体

1.PCM文件的存储结构

音频采样格式可以分为packed和planar两类。以packed格式保存的采样数据,各声道间按照采样值交替存储;以planar格式保存的采样数据,各个采样值按照不同声道连续存储

下面以8bit为例展示planar和packed格式是如何保存音频采样数据的:

packed:
左声道0右声道0左声道1右声道1左声道2右声道2左声道3右声道3

planar:

左声道0左声道1左声道2左声道3右声道0右声道1右声道2右声道3

2.读取PCM音频采样数据

由于我们代码里设置了采样格式为fltp,即planar格式,而输入的PCM音频采样数据是packed格式的,因此我们需要将packed格式转化为planar格式进行保存:

//io_data.cppint32_t read_pcm_to_frame(AVFrame* frame,AVCodecContext* codec_ctx){    int data_size= av_get_bytes_per_sample(codec_ctx->sample_fmt);    if(data_size<0){        cerr<<"Error:Failed to calculate data size."<channels;ch++){            fread(frame->data[ch]+i*data_size,1,data_size,input_file);        }    }    return 0;}

3.编码音频采样数据

//audio_encoder_core.cppstatic int32_t encode_frame(bool flushing){    int32_t result=0;    if(!flushing){        cout<<"Send frame to encoder with pts:"<<frame->pts<=0){        result= avcodec_receive_packet(codec_ctx,pkt);        if(result==AVERROR(EAGAIN)||result==AVERROR_EOF){//尚未完成对新一帧的编码,要传入后续帧或编码器已完全输出内部缓存的码流            return 1;        }        else if(result<0){            cerr<<"Error:avcodec_receive_packet failed."<dts<<",pts:"<pts<<", "<

4.写出码流数据  

//io_data.cppvoid write_pkt_to_file(AVPacket* pkt){    fwrite(pkt->data,1,pkt->size,output_file);}

5.实现编码循环

//audio_encoder_core.cppint32_t audio_encoding(){    int32_t result=0;    while(!end_of_input_file()){        result= read_pcm_to_frame(frame,codec_ctx);        if(result<0){            cerr<<"Error:read_pcm_to_frame failed."<

6.关闭编码器

//audio_encoder_core.cppvoid destroy_audio_encoder(){    av_frame_free(&frame);    av_packet_free(&pkt);    avcodec_free_context(&codec_ctx);}

7.最终main函数的实现如下:

int main(){    const char* input_file_name="../input.pcm";    const char* output_file_name="../output.mp3";    const char* codec_name="MP3";    int32_t result= open_input_output_files(input_file_name,output_file_name);    if(result<0){        return result;    }    result=init_audio_encoder(codec_name);    if(result<0){        return result;    }    result=audio_encoding();    if(result<0){        return result;    }    destroy_audio_encoder();    close_input_output_files();    return 0;}

与视频文件类似,可以使用ffplay播放输出的.mp3文件来测试效果。

上一篇 下一篇

相关新闻

天天微速讯:如何将PCM格式的原始音频采样数据编码为MP3格式或AAC格式的音频文件?

快速背英语单词的方法和技巧_快速背英语单词的方法-每日视讯

Vision Pro入门版本:苹果基于iPhone的VR头显专利出炉

“白色黄金”锂的绿色化难题 新消息

别克SUV ELECTRA E4上市 售价18.99万-25.99万元 消息

大脚lol盒子官方下载 lol大脚最新版本|全球观点

看余杭618狂欢大派“兑”,超多福利来咯!限时折扣、5折兑换!

房子产权到了70年后怎么办 每日热闻

航班取消如何赔偿乘客

今日热门!小鹏,站在悬崖边上?

世界最资讯丨伊力特(600197)6月19日主力资金净卖出1962.65万元

实时焦点:湖南软件和信息技术服务业营收突破2000亿元

6月19日基金净值:华商新兴活力混合最新净值2.713,涨2.8% 热点

烤箱烤红薯能直接烤吗怎么烤

令我感动的一件事开头结尾 即时看

最新新闻

天天微速讯:如何将PCM格式的原始音频采样数据编码为MP3格式或AAC格式的音频文件?

快速背英语单词的方法和技巧_快速背英语单词的方法-每日视讯

Vision Pro入门版本:苹果基于iPhone的VR头显专利出炉

“白色黄金”锂的绿色化难题 新消息

别克SUV ELECTRA E4上市 售价18.99万-25.99万元 消息

大脚lol盒子官方下载 lol大脚最新版本|全球观点

看余杭618狂欢大派“兑”,超多福利来咯!限时折扣、5折兑换!

房子产权到了70年后怎么办 每日热闻

航班取消如何赔偿乘客

今日热门!小鹏,站在悬崖边上?

世界最资讯丨伊力特(600197)6月19日主力资金净卖出1962.65万元

实时焦点:湖南软件和信息技术服务业营收突破2000亿元

6月19日基金净值:华商新兴活力混合最新净值2.713,涨2.8% 热点

烤箱烤红薯能直接烤吗怎么烤

令我感动的一件事开头结尾 即时看

岳阳首批政务服务效能监督员“上岗”

1n立方米n是什么意思(n立方米是什么单位) 世界热门

焦点速看:抖音怎么卖东西 抖音怎么卖自己的产品

中楚物业被行政处罚,因违反生活垃圾管理条例

海南:开展基础教育质量提升三年攻坚行动|天天快资讯

洛阳洛宁:“五星”支部强引领 乡村运营促振兴 世界今热点

世界热资讯!厦门方特端午水上乐园有什么游玩项目

全球热消息:中辉期货油籽油料日报20230619:美豆种植炒作,期价上行

“中国兰花第一县”逾160个兰花品种指导价发布|重点聚焦

养老舒适,旅居更美好,贵州景美人少的小地方,离贵阳特别近_观速讯

焦点消息!云南通报5起违规配备和使用公务用车典型问题

五粮液旗下公司投资光伏科技企业

“水韵江苏”文旅公众推广活动在日本东京举行

世界观天下!信用卡还不了款怎么办?信用卡分期怎么申请?-全球动态

床单200*230长是多少,宽是多少