日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

linux编译libmp3lame,使用libmp3lame库编码mp3

發布時間:2023/12/16 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 linux编译libmp3lame,使用libmp3lame库编码mp3 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

使用libmp3lame庫編碼mp3

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)

MPEG1

MPEG2

MPEG2.5

44100

22050

11025

48000

24000

12000

32000

16000

8000

比特率支持(bit/s)

MPEG1

MPEG2

MPEG2.5

32

8

8

40

16

16

48

24

24

56

32

32

64

40

40

80

48

48

96

56

56

112

64

64

128

80

160

96

192

112

224

128

256

144

320

160

編碼

流程

使用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文件。

銷毀編碼器

lame_close銷毀編碼器,釋放資源。

參數的有效性

不規范的參數

對于編碼器的參數設置,所能接受的參數值并不是任意的。上一節的表格中列出了編碼器器能夠支持的參數值,如果我們設置的參數值不在其中,那么編碼器會自動幫我們選擇一個最近的值。

不一致的版本

但是如果仔細看了上面表格中的參數后會發現一個問題,每個版本支持的參數范圍不一致,假如設置了MPEG2的比特率又設置了MPEG1的采樣率那么會發生什么?

這里先給結論,lame庫會優先服從采樣率(這里指的是輸出采樣率)設置,根據采樣率選擇協議版本,然后在這個版本所能支持的比特率中選一個和設置比特率最接近的。

這個結論是我研究了lame的源碼后分析得到的,lame的文檔中并沒有對此有任何描述,網上也沒有任何相關的資料描述這一問題,接下來給出源碼分析,如果不關心的可以跳過這一節。

/*

* 0: MPEG-2 LSF

* 1: MPEG-1

* 2: MPEG-2.5 LSF FhG extention (1995-07-11 shn)

*/

typedef enum {

MPEG_2 = 0,

MPEG_1 = 1,

MPEG_25 = 2

} MPEG_t;

const int bitrate_table[3][16] = {

{0, 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, -1}, /* MPEG 2 */

{0, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, -1}, /* MPEG 1 */

{0, 8, 16, 24, 32, 40, 48, 56, 64, -1, -1, -1, -1, -1, -1, -1}, /* MPEG 2.5 */

};

const int samplerate_table[3][4] = {

{22050, 24000, 16000, -1}, /* MPEG 2 */

{44100, 48000, 32000, -1}, /* MPEG 1 */

{11025, 12000, 8000, -1}, /* MPEG 2.5 */

};

這是lame庫中的參數能力表,lame庫最終會從表中選擇和設置值最接近的值。

下面的代碼是在CBR模式下確定比特率的代碼

if (gfp->VBR == vbr_off && gfp->compression_ratio > 0) {

if (gfp->samplerate_out == 0)

gfp->samplerate_out = map2MP3Frequency((int) (0.97 * gfp->samplerate_in)); /* round up with a margin of 3% */

/* choose a bitrate for the output samplerate which achieves * specified compression ratio */

gfp->brate = gfp->samplerate_out * 16 * cfg->channels_out / (1.e3 * gfp->compression_ratio);

/* we need the version for the bitrate table look up */

cfg->samplerate_index = SmpFrqIndex(gfp->samplerate_out, &cfg->version);

if (!cfg->free_format) /* for non Free Format find the nearest allowed bitrate */

gfp->brate = FindNearestBitrate(gfp->brate, cfg->version, gfp->samplerate_out);

}

int

map2MP3Frequency(int freq)

{

if (freq <= 8000)

return 8000;

if (freq <= 11025)

return 11025;

if (freq <= 12000)

return 12000;

if (freq <= 16000)

return 16000;

if (freq <= 22050)

return 22050;

if (freq <= 24000)

return 24000;

if (freq <= 32000)

return 32000;

if (freq <= 44100)

return 44100;

return 48000;

}

int

BitrateIndex(int bRate, /* legal rates from 32 to 448 kbps */

int version, /* MPEG-1 or MPEG-2/2.5 LSF */

int samplerate)

{ /* convert bitrate in kbps to index */

int i;

if (samplerate < 16000)

version = 2;

for (i = 0; i <= 14; i++) {

if (bitrate_table[version][i] > 0) {

if (bitrate_table[version][i] == bRate) {

return i;

}

}

}

return -1;

}

/* convert samp freq in Hz to index */

int

SmpFrqIndex(int sample_freq, int *const version)

{

switch (sample_freq) {

case 44100:

*version = 1;

return 0;

case 48000:

*version = 1;

return 1;

case 32000:

*version = 1;

return 2;

case 22050:

*version = 0;

return 0;

case 24000:

*version = 0;

return 1;

case 16000:

*version = 0;

return 2;

case 11025:

*version = 0;

return 0;

case 12000:

*version = 0;

return 1;

case 8000:

*version = 0;

return 2;

default:

*version = 0;

return -1;

}

}

可以看到首先如果沒有設置輸出采樣率,調用map2MP3Frequency根據輸入采樣率算出輸出采樣率,默認和輸入采樣率一致的。

然后根據輸出采樣率調用SmpFrqIndex計算出MPEG版本,這里注意將MPEG2和MPEG2.5都視為MPEG2。

根據已經設置的比特率、輸出采樣率、版本調用FindNearestBitrate去尋找合適的比特率。FindNearestBitrate在相應的版本的能力范圍中找一個最接近的值的索引。

接下來分析一下VBR情況下的處理

if (gfp->samplerate_out) {

if (gfp->samplerate_out < 16000) {

gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8);

gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 64);

}

else if (gfp->samplerate_out < 32000) {

gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 8);

gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 160);

}

else {

gfp->VBR_mean_bitrate_kbps = Max(gfp->VBR_mean_bitrate_kbps, 32);

gfp->VBR_mean_bitrate_kbps = Min(gfp->VBR_mean_bitrate_kbps, 320);

}

}

可以看到這里沒有查表,直接是和采樣率對應的版本允許的比特率的范圍比較。這是因為VBR模式下比特率不固定,只要不超出范圍即可。

感想

我在使用lame庫的過程中發現資料很少,大部分博客也是不負責任的直接貼一篇代碼,所以我把自己使用lame庫種總結出的一些心得和體會在此分享出來,希望能幫助其他使用lame庫的人。

總結

以上是生活随笔為你收集整理的linux编译libmp3lame,使用libmp3lame库编码mp3的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。