使用libmp3lame库编码mp3

原文链接https://blog.csdn.net/bjrxyz/article/details/73435407?locationNum=15&fps=1

LAME

lame是一个有名的开源mp3编码库,但是目前网上使用lame库的教程基本都是直接贴一篇代码,没有任何的解释,而每个使用者需要编码的需求都不一样,这些所谓的教程基本没什么作用。

这篇文章将会介绍如何调用lame库的接口编码出mp3。不同于目前网上的大多数lame教程,本文不会干巴巴的贴一屏幕代码,而是尽量对lame库提供的各种参数设置的接口做讲解。让读者能够举一反三,根据自己的需求编码出各种格式的mp3。

lame库编译

lame对linux的编译支持比较好,但是对于vc的支持基本停留在10年以前。所幸编码库的代码只有几个文件(下载的代码还包括命令行程序代码和gui程序代码,我们在此只需要编码库的代码,在libmp3lame目录中),自己新建个项目包含进来编译就行。

MP3

mp3(MPEG Layer III)这种格式在生活中很常见,但是mp3有很多种参数,这里讨论一下mp3编码所必须知道的一些参数。

采样率(sampleRate):采样率越高声音的还原度越好。

比特率(bitrate):每秒钟的数据量,越高音质越好。

声道数(channels):声道的数量,通常只有单声道和双声道,双声道即所谓的立体声。

比特率控制模式:ABR、VBR、CBR,这3中模式含义很容易查询到,不在赘述。

MPEG Layer III

MPEG有几个版本的协议,不同版本的协议能够支持的参数能力是不同的。编码库的使用者必须清楚不同版本的区别才能正确的设置参数。

有以下3个版本的协议,MPEG1、MPEG2、MPEG2.5。其中MPEG2.5是非官方的标准,但是流传广泛,所以基本也都支持。他们的区别主要集中在支持的比特率和采样率不同。

采样率支持(Hz)

MPEG1MPEG2MPEG2.5

441002205011025

480002400012000

32000160008000

比特率支持(bit/s)

MPEG1MPEG2MPEG2.5

3288

401616

482424

563232

644040

804848

965656

1126464

12880

16096

192112

224128

256144

320160

编码

流程

使用lame库只需要包含lame.h头文件,编码mp3基本上遵循以下的流程,

初始化编码参数

lame_init:初始化一个编码参数的数据结构,给使用者用来设置参数。

设置编码参数

lame_set_in_samplerate:设置被输入编码器的原始数据的采样率。

lame_set_out_samplerate:设置最终mp3编码输出的声音的采样率,如果不设置则和输入采样率一样。

lame_set_num_channels:设置被输入编码器的原始数据的声道数。

lame_set_mode:设置最终mp3编码输出的声道模式,如果不设置则和输入声道数一样。参数是枚举,STEREO代表双声道,MONO代表单声道。

lame_set_VBR:设置比特率控制模式,默认是CBR,但是通常我们都会设置VBR。参数是枚举,vbr_off代表CBR,vbr_abr代表ABR(因为ABR不常见,所以本文不对ABR做讲解)vbr_mtrh代表VBR。

lame_set_brate:设置CBR的比特率,只有在CBR模式下才生效。

lame_set_VBR_mean_bitrate_kbps:设置VBR的比特率,只有在VBR模式下才生效。

其中每个参数都有默认的配置,如非必要可以不设置。这里只介绍了几个关键的设置接口,还有其他的设置接口可以参考lame.h(lame的文档里只有命令行程序的用法,没有库接口的用法)。

初始化编码器器

lame_init_params:根据上面设置好的参数建立编码器

编码PCM数据

lame_encode_buffer或lame_encode_buffer_interleaved:将PCM数据送入编码器,获取编码出的mp3数据。这些数据写入文件就是mp3文件。

其中lame_encode_buffer输入的参数中是双声道的数据分别输入的,lame_encode_buffer_interleaved输入的参数中双声道数据是交错在一起输入的。具体使用哪个需要看采集到的数据是哪种格式的,不过现在的设备采集到的数据大部分都是双声道数据是交错在一起。

单声道输入只能使用lame_encode_buffer,把单声道数据当成左声道数据传入,右声道传NULL即可。

调用这两个函数时需要传入一块内存来获取编码器出的数据,这块内存的大小lame给出了一种建议的计算方式:采样率/20+7200。

结束编码

lame_encode_flush:刷新编码器缓冲,获取残留在编码器缓冲里的数据。这部分数据也需要写入mp3文件

写入VBRTAG

lame_mp3_tags_fid:向一个文件指针中写入XING规范的VBRTAG。

VBRTAG的作用是记录整个mp3的一些信息,通常用于VBR模式下的编码,因为VBR模式下比特率不固定,无法直接计算出播放的时长和跳跃点,所以在mp3的开头部分插入一个VBRTAG。

VBRTAG有几种规范,但是lame支持的是最通用的XING规范。

注意lame_mp3_tags_fid函数的参数需要一个FILE *类型代表要写入的文件,这个文件一定是之前编码时写入了mp3数据的文件,VBRTAG是需要卸载mp3的开头的,之前的编码过程中会自动空出写入VBRTAG所需要的空间,这个函数内会自动寻找合适的文件偏移然后覆盖,所以当前的文件偏移是无关紧要的,但是打开文件的时候一定要以读写模式打开。

注意我提到了之前的编码过程中会自动空出写入VBRTAG所需要的空间,所以如果结束编码后不调用lame_mp3_tags_fid写入VBRTAG就会导致这部分内容为空,虽然不影响播放,但是会影响很多播放器对于时长和跳跃点的计算。

那么对于非VBR模式也需要写入VBRTAG吗?是的,lame对于非VBR模式也会预留出VBRTAG的空间,所以非VBR模式的编码最后也需要写入VBRTAG。

销毁编码器

lame_close销毁编码器,释放资源。

参数的有效性

不规范的参数

对于编码器的参数设置,所能接受的参数值并不是任意的。上一节的表格中列出了编码器器能够支持的参数值,如果我们设置的参数值不在其中,那么编码器会自动帮我们选择一个最近的值。

不一致的版本

但是如果仔细看了上面表格中的参数后会发现一个问题,每个版本支持的参数范围不一致,假如设置了MPEG2的比特率又设置了MPEG1的采样率那么会发生什么?

这里先给结论,lame库会优先服从采样率(这里指的是输出采样率)设置,根据采样率选择协议版本,然后在这个版本所能支持的比特率中选一个和设置比特率最接近的。

这个结论是我研究了lame的源码后分析得到的,lame的文档中并没有对此有任何描述,网上也没有任何相关的资料描述这一问题,接下来给出源码分析,如果不关心的可以跳过这一节。


首先如果没有设置输出采样率,调用map2MP3Frequency根据输入采样率算出输出采样率,默认和输入采样率一致的。

然后根据输出采样率调用SmpFrqIndex计算出MPEG版本,这里注意将MPEG2和MPEG2.5都视为MPEG2。

根据已经设置的比特率、输出采样率、版本调用FindNearestBitrate去寻找合适的比特率。FindNearestBitrate在相应的版本的能力范围中找一个最接近的值的索引。



原文链接https://blog.csdn.net/bjrxyz/article/details/73435407?locationNum=15&fps=1

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,922评论 6 497
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,591评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,546评论 0 350
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,467评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,553评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,580评论 1 293
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,588评论 3 414
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,334评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,780评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,092评论 2 330
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,270评论 1 344
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,925评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,573评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,194评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,437评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,154评论 2 366
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,127评论 2 352

推荐阅读更多精彩内容