1. 程式人生 > >MP3解碼流程(一)-----音訊檔案結構解析

MP3解碼流程(一)-----音訊檔案結構解析

  • 本文多處摘自網際網路,僅供本人學習使用,出處標示於文章尾端。

#一、概述     Layer-3 音訊檔案,MPEG(Moving Picture Experts Group) 在漢語中譯為活動影象專家組,特指活動影音壓縮標準,MPEG音訊檔案是MPEG1 標準中的聲音部分,也叫MPEG 音訊層,它根據壓縮質量和編碼複雜程度劃分為三層,即Layer-1、Layer2、Layer3,且分別對應MP1、MP2、MP3 這三種聲音檔案,並根據不同的用途,使用不同層次的編碼。 MPEG 音訊編碼的層次越高,編碼器越複雜,壓縮率也越高,MP1 和MP2 的壓縮率分別為4:1 和6:1-8:1,而MP3 的壓縮率則高達10:1-12:1,也就是說,一分鐘CD 音質的音樂,未經壓縮需要10MB的儲存空間,而經過MP3 壓縮編碼後只有1MB 左右。不過MP3 對音訊訊號採用的是有失真壓縮方式,為了降低聲音失真度,MP3採取了“感官編碼技術”,即編碼時先對音訊檔案進行頻譜分析,然後用過濾器濾掉噪音電平,接著通過量化的方式將剩下的每一位打散排列,最後形成具有較高壓縮比的MP3 檔案,並使壓縮後的檔案在回放時能夠達到比較接近原音源的聲音效果。

#二、MP3 檔案結構     MP3 檔案大體分為三部分:TAG_V2(ID3V2)音訊資料TAG_V1(ID3V1)

    a). ID3V2 在檔案開始的位置,包含了作者,作曲,專輯等資訊,長度不固定,擴充套件了ID3V1 的資訊量。

    b). 一系列的音訊資料的幀,在檔案的中間位置,個數由檔案大小和幀長決定; 每個幀的長度可能不固定,也可能固定,由位率bitrate決定 每個幀又分為幀頭和資料實體兩部分 幀頭記錄了mp3 的位率,取樣率,版本等資訊,每個幀之間相互獨立 。

    c). ID3V1在檔案結尾的位置,包含了作者,作曲,專輯等資訊,長度為128Byte。

##2.1、ID3V2

    ID3V2 到現在一共有4 個版本,但流行的播放軟體一般只支援第3 版, 既ID3v2.3。

    由於ID3V1 記錄在MP3 檔案的末尾,ID3V2就只好記錄在MP3 檔案的首部了(如果有一天釋出ID3V3,真不知道該記錄在哪裡)。也正是由於這個原因,對ID3V2 的操作比ID3V1 要慢。而且ID3V2 結構比ID3V1 的結構要複雜得多,但比前者全面且可以伸縮和擴充套件。

    下面就介紹一下ID3V2.3: 每個ID3V2.3 的標籤都一個標籤頭和若干個標籤幀或一個擴充套件標籤頭組成。關於曲目的資訊如標題、作者等都存放在不同的標籤幀中,擴充套件標籤頭和標籤幀並不是必要的,但每個標籤至少要有一個標籤幀。標籤頭和標籤幀一起順序存放在MP3 檔案的首部。

###2.1.1、標籤頭     在檔案的首部順序記錄10 個位元組的ID3V2.3 的頭部。資料結構如下:

typedef struct Zs_head_lable
{
    char Header[3]; // 必須為字串"ID3",否則認為標籤不存在 對應16進位制:49 44 33
    char ver;   // 版本號ID3V2.3 就記錄0x03
    char Revision;// 副版本號此版本記錄為0x00
    char Flag;  // 存放標誌的位元組,這個版本只定義了3bit
    char Size[4];   // 標籤幀的大小,不包括標籤頭的10個位元組
}head_lable;

圖2.1.1 這裡寫圖片描述 紅色框部分即為ID3V2.3的頭部:

前3個位元組就是 ID30x03(第3版) 49 44 33

第4個表示版本號 03

第5個位元組:副版本號,為00

第6個位元組是標誌位元組 為00 標誌位元組一般為0,按位定義如下: abc00000 a – 表示是否使用Unsynchronisation(這個單詞不知道是什麼意思,字典裡也沒有找到,一般不設定) b – 表示是否有擴充套件頭部,一般沒有(至少Winamp 沒有記錄),所以一般也不設定 c – 表示是否為測試標籤(99.99%的標籤都不是測試用的啦,所以一般也不設定)

第7-10個位元組表示標籤幀大小 一共四個位元組,但每個位元組只用7位,最高位不使用恆為0。所以格式如下 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx

計算大小時要將0 去掉,得到一個28 位的二進位制數,就是標籤大小,計算公式如下:

int label_frame_size;
label_frame_size=((Size[0]&0x7F)<<21)
                        + ((Size[1]&0x7F)<<14))
                        + ((Size[2]&0x7F)<<7)
                        + (Size[3]&0x7F);

第7到10位元組:表示ID3標籤的大小,這裡為

label_frame_size=((0x00&0x7F)<<21)+((0x00&0x7F)<<14)+((0x07&0x7F)<<7) +(0x76 &0x7F) = 0x3F6=1014;

這裡的 0x3F6幀大小,並不包含標籤頭的10個位元組,只表示標籤幀內容的大小 加上標籤頭是10個位元組,音訊資料就是從1024後面的位元組開始算。

###2.1.2、標籤幀     接上面的例子,接下里4086個位元組都是標籤幀的內容。 每個標籤幀都有一個10 個位元組的幀頭和至少一個位元組的不固定長度的內容組成。它們也是順序存放在檔案中,和標籤頭和其他的標籤幀也沒有特殊的字元分隔。得到一個完整的幀的內容只有從幀頭中的到內容大小後才能讀出,讀取時要注意大小,不要將其他幀的內容或幀頭讀入。

幀頭的定義如下:

typedef struct Zs_lable_frame_head
{
	char ID[4]; //用四個字元標識一個幀,說明其內容,稍後有常用的標識對照表
	char Size[4]; //幀內容的大小,不包括幀頭,不得小於1
	char Flags[2]; //存放標誌,只定義了6 位
}lable_frame_head,*plable_frame_head;

圖2.1.2 這裡寫圖片描述 藍色部分是一個歌曲的標籤幀的有效內容

####1)幀標識 用四個字元標識一個幀,說明一個幀的內容含義,常用的對照如下: TIT2=標題表示內容為這首歌的標題,下同 TPE1=作者 TALB=專集 TRCK=音軌格式:N/M 其中N 為專集中的第N 首,M為專集中共M 首,N和M 為ASCII 碼錶示的數字 TYER=年代是用ASCII 碼錶示的數字 TCON=型別直接用字串表示 COMM=備註格式:”eng\0備註內容”,其中eng 表示備註所使用的自然語言 注:更多的幀標識說明見附錄一。

前4個位元組為幀標識,這裡是54 59 45 52 (TYER) 是年代

####2)大小 這個可沒有標籤頭的演算法那麼麻煩,每個位元組的8 位全用,格式如下 xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx 演算法如下:

int FrameSize;
FrameSize= (Size[0]<<24) 
			+(Size[1]<<16)
			+ (Size[2]<<8)
			+ Size[3];

這裡為

FrameSize =(0x00<<24) +( 0x00<<16) + (0x00<<8) + 0x05 = 5;

注意:這裡的幀大小,並不包含幀頭的10個位元組,只表示幀內容的大小

####3)標誌 只定義了6 位,另外的10 位為0,但大部分的情況下16 位都為0 就可以了。格式如下: abc00000ijk00000

a – 標籤保護標誌,設定時認為此幀作廢

b – 檔案保護標誌,設定時認為此幀作廢

c – 只讀標誌,設定時認為此幀不能修改(但我沒有找到一個軟體理會這個標誌)

i – 壓縮標誌,設定時一個位元組存放兩個BCD 碼錶示數字

j – 加密標誌(沒有見過哪個MP3 檔案的標籤用了加密)

k – 組標誌,設定時說明此幀和其他的某幀是一組

值得一提的是winamp 在儲存和讀取幀內容的時候會在內容前面加個”\0”,並把這個位元組計算在幀內容的大小中。 第9到10位元組為標籤幀的標記,如上所述,這裡為00

第一個幀內容是歌曲年代,標題的5個位元組的內容為: 0x00 0x32 0x30 0x31 0x35 ‘\0’ ‘2’ ‘0’ ‘1’ ‘5’ 上圖中的內容依次讀出為: TYER:2015 TALB:Purpose COMM:eng TIT2:LoveYourself TPE1:JustinBieber

##2.2、音訊資料幀

一個MP3資料幀分為5個部分:幀頭、CRC校驗值、通道資訊、主資料、附加資料。

###2.2.1、MP3幀頭位元組說明 每個幀都有一個幀頭Header,長度是4Byte(32bit),幀頭後面可能有兩個位元組的CRC 校驗值,這兩個位元組的是否存在決定於Header 資訊的第16bit,為0 則幀頭後面無校驗,為1 則有校驗,校驗值長度為2 個位元組,緊跟在Header 後面,接著就是幀的實體資料了. 圖2.2.1 這裡寫圖片描述 紅色部分的4個位元組即是幀頭

**表2.1.1 MP3幀頭位元組說明**表
名稱 位長
說明
同步資訊 11 所有位均為1,第1位元組恆為FF>
版本 2 00-MPEG 2.5 01-未定義 10-MPEG 2 11-MPEG 1
2 00-未定義 01-Layer 3 10-Layer 2 11-Layer 1
CRC校驗 1 0-校驗 1-不校驗
位元率 4 單位是kbps,例如採用MPEG-1 Layer 3,128kbps是,值為1001 具體引數對應位元率表
取樣率 2 取樣頻率,對於MPEG-1: 00-44.1kHz 01-48kHz 10-32kHz 11-未定義 對於MPEG-2: 00-22.05kHz 01-24kHz 10-16kHz 11-未定義 對於MPEG-2.5: 00-11.025kHz 01-12kHz 10-8kHz 11-未定義
幀長調節 1 用來調整檔案頭長度,0-無需調整,1-調整,具體調整計算方法見下文
保留字 1 沒有使用
聲道模式 2 表示聲道, 00-立體聲Stereo 01-Joint Stereo 10-雙聲道 11-單聲道
擴充模式 2 當聲道模式為01是才使用 Value   強度立體聲    MS立體聲 00             off             off 01             on              off 10             off              on 11              on             on
版權 1 檔案是否合法,0-不合法 1-合法
原版標誌 1 是否原版, 0-非原版 1-原版
強調方式 2 用於聲音經降噪壓縮後再補償的分類,很少用到,今後也可能不會用。 00-未定義 01-50/15ms 10-保留 11-CCITT J.17
**表2.1.2 MP3資料幀位元率表**
bits
V1,L1
V1,L2
V1,L3
V2,L1
V2,L2
V2,L3
0000
free
free
free
free
free
free
0001
32
32
32
32(32)
32(8)
8(8)
0010
64
48
40
64(48)
48(16)
16(16)
0011
96
54
48
96(56)
56(24)
24(24)
0100
128
64
56
128(64)
64(32)
32 (32)
0101
160
80
64
160(80)
80(40)
64 (40)
0110
192
96
80
192(96)
96(48)
80 (48)
0111
224
112
96
224(112)
112(56)
56 (56)
1000
256
128
112
256(128)
128(64)
64 (64)
1001
288
160
128
288(144)
160(80)
128 (80)
1010
320
192
160
320(160)
192(96)
160 (96)
1011
352
224
192
352(176)
224(112)
112 (112
1100
384
256
224
384(192)
256(128)
128 (128)
1101
416
320
256
416(224)
320(144)
256 (144)
1110
448
384
320
448(256)
384(160)
320 (160)
1111
bad
bad
bad
bad
bad
bad
V1 - MPEG 1 V2 - MPEG 2 and MPEG 2.5 L1 - Layer 1 L2 - Layer 2 L3 - Layer 3 "free" 表示位率可變 "bad" 表示不允許值 規律說明:根據上表的分析,所有的Mp3檔案的資料幀開始的兩個位元組必需是“FF FA”或者 “FF FB”。

####a) 例子資料分析 第1幀資料:幀頭為 FF FA 91 6C 1111 1111 111 11 01 0 1001 00 0 1 01 10 1 1 00

前11位:同步資訊

第12到13位:版本,其值為11 ->MPEG 1

第14到15位:層,其值為01->Layer 3

第16位:CRC檢驗標識,其值為0 ->校驗

第17到20位:位率,其值為1001,從前面可知本幀為V1,L3型別, ->128K

第21到22位:取樣率,其值為00,從前面知本幀為 MPEG 1-> 44.1K

第23位:幀長調節,其值為0 ->無需調整

第24位:保留字,未使用

第25到26位:聲道模式,其值為01->-Joint Stereo

第27到28位:擴充模式,當聲道模式為01(聯合立體聲)時才使用,此處是10, 使用MS立體聲

第29位:版權,其值為1->有版權

第30位:原版標誌,其值為1->是原版檔案

第31到32位:強調方式,其值為00->未定義

####b)、 幀頭資訊儲存結構體 自定義以下結構體,用來儲存幀頭資料:

typedef struct frameHeader
{
    unsigned int sync1:11;                      //同步資訊1
    unsigned int version:2;                    //版本
    unsigned int layer:2;                      //層
    unsigned int crc_check:1;                  //CRC校驗
    
    unsigned int bit_rate_index:4;             //位元率索引
	unsigned int sample_rate_index:2;          //取樣率索引
    unsigned int padding:1;                    //幀長調節位
    unsigned int reserved:1;                   //保留字
    
    unsigned int channel_mode:2;               //聲道模式
    unsigned int mode_extension:2;             //擴充套件模式,僅用於聯合立體聲
    unsigned int copyright:1;                  //版權標誌
    unsigned int original:1;                   //原版標誌
    unsigned int emphasis:2;                   //強調方式
}FHEADER, *LPHEADER;

發現直接讀取4個位元組的資料到這個結構體內,發現數據不對, 讀的過程是按8位元組對齊的,比如sync1會先讀取8個位元組到低位,剩下的3個bit成了其他資料的低位。 還是進行資料分析,然後填充到結構體內。 ###2.2.2、CRC校驗     如果幀頭的校驗位為0,則幀頭後就有一個16位的CRC值,這個值是big-endian的值,把這個值和該幀通過計算得出的CRC值進行比較就可以得知該幀是否有效。 例子中是校驗值為0,需要進行校驗。CRC校驗值即是 幀頭的後2個位元組:06 9B CRC校驗本文不做詳細介紹。

###2.2.3、 MP3幀長的計算 MP3幀長取決於位率和頻率,計算公式為:

Size=((取樣個數 * (1 / 取樣率))* 幀的位元率)/8 + 幀的填充大小

a),幀的填充大小就是第23位的幀長調節,不是0就是1。

**b),**取樣個數:MPEG的不同規範(MPEG-1/2/3),以及同一規範中不同的 Layer(Layer I/II/III),每一幀所對應的取樣數,都是固定的,其具體的值參見下表:

表 2.2.2 MPEG幀的取樣數索引表(單位:個/幀)
MPEG 1
MPEG 2(LSF)
MPEG 2.5(LSF)
Layer 1
384
384
384
Layer 2
1152
1152
1152
Layer 3
1152
576
576

對於Mp3格式,MPEG 1 Layer3 取樣個數是固定的1152, Size = ((1152 * (1 / 取樣率))* 幀的位元率)/8 + 幀的填充大小 = 144*幀的位元率/取樣率 + 幀的填充大小 例: 如2.2.1中的資料,位元率為128K,取樣率為44.1K,填充0,則其幀長度為: (144 * 128K)/44.1K +0= 417 (位元組) 回去看 圖2.2.1 從當前資料的 “FF FA” 到下一個資料幀開始的"FF FA"之間,剛好是417個數據 包含了幀頭的4個位元組和2個CRC校驗位元組

###2.2.4、Side Info(通道資訊)     在幀頭後邊是Side Info(姑且稱之為通道資訊)。對標準的立體聲MP3檔案來說其長度為32位元組。通道資訊後面是Scale factor(增益因子)資訊。當解碼器在讀到上述資訊後,就可以進行解碼了。 圖2.2.1中是緊接著校驗位的後32位元組的資料。 幀邊資訊解碼的主要目的在於找出解這幀的各個引數,包括主資料開始位置,尺度因子長度等。幀邊資訊如圖2.2.4-1所示。

圖2.2.4-1 side info ![這裡寫圖片描述](https://img-blog.csdn.net/20171205190010497?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdsaWUxMTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) 其中,main_data_begin(主資料開始)是一個偏移值,指出主資料是在同步字之前多少個位元組開始。需要注意的是,1.幀頭不一定是一幀的開始,幀頭CRC校驗字和幀邊資訊在幀資料中是滑動的。2.這個數值忽略幀頭和幀邊資訊的存在,如果main_data_begin = 0, 則主資料從幀邊資訊的下一個位元組開始,示意圖如圖2.2.4-2.
圖2.2.4-2 MP3位流資料組織圖 ![這裡寫圖片描述](https://img-blog.csdn.net/20171206104103255?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdsaWUxMTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)

塊型別(block_type)分為三種類型:

block_type = 0長塊

block_type = 1開始塊

block_type = 3結束塊

block_type = 2短塊

在編碼過程中進行IMDCT變換時,針對不同訊號為同時得到較好的時域和頻域解析度定義了兩種不同的塊長:長塊的塊長為18個樣本,短塊的塊長為6個樣本。這使得長塊對於平穩的聲音訊號可以得到更高的頻率解析度,而短塊對跳變訊號可以得到更高的時域解析度。由於在短塊模式下,3個短塊代替1個長塊,而短塊的大小恰好是一個長塊的1/3,所以IMDCT的樣本數不受塊長的影響。對於給定的一幀聲音訊號,IMDCT可以全部使用長塊或全部使用短塊,也可以長短塊混合使用。因為低頻區的頻域解析度對音質有重大影響,所以在混合塊模式下,IMDCT對最低頻的2個子帶使用長塊,而對其餘的30個子帶使用短塊。這樣,既能保證低頻區的頻域解析度,又不會犧牲高頻區的時域解析度。長塊和短塊之間的切換有一個過程,一般用一個帶特殊長轉短(即,起始塊block_type = 1)或短轉長(即終止塊,block_type = 3)資料視窗的長塊來完成這個長短塊之間的切換。因此長塊也就是包括正常窗,起始塊和終止塊資料視窗的資料塊;短塊也包含18個數據,但是是由6個數據獨立加窗後在經過連線計算得到的。

libmad 使用以下結構體來儲存side info

struct sideinfo {
  unsigned int main_data_begin;
  unsigned int private_bits;
  unsigned char scfsi[2];

  struct granule {
    struct channel {
      /* from side info */
      unsigned short part2_3_length;
      unsigned short big_values;
      unsigned short global_gain;
      unsigned short scalefac_compress;

	   unsigned char flags;
	   unsigned char block_type;
	   unsigned char table_select[3];
	   unsigned char subblock_gain[3];
	   unsigned char region0_count;
	   unsigned char region1_count;

	   /* from main_data */
	    unsigned char scalefac[39];	/* scalefac_l and/or scalefac_s */
  } ch[2];
  } gr[2];
};

###2.2.5、主資料(main data) main_data中有兩粒度組,沒個粒度組分為兩個聲道,取資料儲存結構如圖2.2.5。

圖2.2.5 ![這裡寫圖片描述](https://img-blog.csdn.net/20171205164031847?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhlbmdsaWUxMTA=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast) **b)**對於mp3來說,現在有兩種編碼方式:

        一種是CBR,也就是固定位率,固定位率的幀的大小在整個檔案中都是是固定的,只要知道檔案總長度,和從第一幀幀頭讀出的資訊,就都可以通過計算得出這個mp3檔案的資訊,比如總的幀數,總的播放時間等等,要定位到某一幀或某個時間點也很方便,這種編碼方式不需要檔案頭,第一幀開始就是音訊資料。

        另一種是VBR,就是可變位率,VBR是XING公司推出的演算法,所以在MP3的FRAME裡有“Xing”這個關鍵字(也有用”Info”來標識的,現在很多流行的小軟體也可以進行VBR壓縮,它們是否遵守這個約定,那就不得而知了),它存放在MP3檔案中的第一個有效幀的資料區裡,它標識了這個MP3檔案是VBR的。同時第一個幀裡存放了MP3檔案的幀的總個數,這就很容易獲得了播放總時間,同時還有100個位元組存放了播放總時間的100個時間分段的幀索引,假設4分鐘的MP3歌曲,240S,分成100段,每兩個相鄰INDEX的時間差就是2.4S,所以通過這個INDEX,只要前後處理少數的FRAME,就能快速找出我們需要快進的幀頭。其實這第一幀就相當於檔案頭了。不過現在有些編碼器在編碼CBR檔案時也像VBR那樣將資訊記入第一幀,比如著名的lame,它使用”Info”來做CBR的標記。         第三種是 Info 幀         info幀,結構和Xing幀是相同的,從一些網上的資料顯示:這種型別的幀有點怪,在CBR檔案中的第一個資料幀可以是Info幀,在VBR檔案中的第一個資料幀也有可能是Info幀,但是我個人更傾向於認為第一個資料幀為Info幀的檔案是CBR檔案,比如Kugoo軟體製作的鈴聲的第一幀都是Info幀,而且是CBR檔案。

這裡列出VBR的第一幀儲存檔案資訊的頭的格式。有兩種格式,一種是常見的XINGHeader(頭部包含字元‘Xing’),另一種是VBRIHeader(頭部包含字元‘VBRI’)鑑於VBRIHeader不常見,下面只說XINGHeader:

表2.2.4 VBR Xing檔案第一幀結構
位元組
說明
1-4
標準聲音幀頭(Mp3時,為“FF FA xx xx”或者“FF FB xx xx”)
xx
校驗位,如果有校驗位,後面的資料後移兩位
5-40
存放VBR檔案標識“Xing”(58 69 6E 67),此標識具體位置視採用的MPEG標準和聲道模式而定。標識的前後位元組沒有使用。
37-40
MPEG-1和非單聲道(常見)注意:Mp3的就是這種情況,第5至36的資料儲存的是前面提到過的32位元組的邊資訊,無效邊資訊時是32位元組的“00”
22-25
MPEG-1和單聲道
22-25
MPEG-2和非單聲道
14-17
MPEG-2和單聲道
41-44
標誌,說明是否儲存了幀數、檔案長度、目錄表和VBR規模資訊,如果儲存了,則01 02 04 08。注意:如果四種資訊都儲存了則這4個位元組為“00 00 00 0F”,即F的二進位制是“1111”,相應地,如果儲存了幀數、檔案長度、目錄表,則這4個位元組為“00 00 00 0E”
45-48
幀數(包括第一幀)
49-52
檔案長度
53-152
目錄表,用來按時間進行位元組定位
153-156
VBR規模,用於位率變動音訊質量指示,最差 0,最好 100,大端[可選]

在VBR格式的第一幀中,XING Header包括幀頭一共最多隻需要156個位元組就夠了,當然也可以在XING Header後面儲存編碼器的資訊,比如lame在其後就是儲存其版本,這需要給第一幀留足夠的空間才行。 本文中的例子不是VBR,因此不做分析。

c)如何區分CBR和VBR 這裡寫圖片描述

###2.2.6、播放時間計算          區分了檔案型別就可以計算Mp3檔案的播放時長了。

####a) .CBR檔案的時長計算(duration)         每幀的持續時間         每幀的持續時間可以通過計算獲得,下面給出計算公式         每幀持續時間(毫秒) = 每幀取樣數 / 取樣頻率 * 1000         標準的MP3其每幀時間為: 1152 / 44.1K * 1000 = 26.12 (約等於26ms)

        對於計算CBR 的MP3的播放時間,其是Constant Bitrate,固定的位元率,每一幀的位元率也都是固定的同樣的大小,所以,相對來說,很容易想得到,用檔案大小,直接除於位元率,就可以得到檔案的播放時間了,即就用如下公式可以計算MP3的播放時間: CBR Duration = File Size(Byte) × 8 bit/Byte ÷ (Bitrate(K bit/s)× 1000 bit/Kbit ) CBR播放時間 = 檔案大小(位元組)× 8位元/位元組 ÷(位元率 千位元/秒 ×1000 位元/千位元) 【公式1】 其中: 檔案大小:嚴格地說,應該是 MP3的檔案總大小,減去 MP3的 Tag 的大小,即:檔案大小 = 總的MP3檔案大小 – MP3的 Tag 大小;其中,MP3的 Tag,往往和 MP3檔案總大小相比,幾乎可以忽略不計,所以,一般也可以直接用總的MP3為檔案大小,直接來計算:檔案大小 = 總的MP3檔案大小。 位元率:可以通過解析MP3檔案的第一幀的MPEG的幀頭,得到位元率的索引值,然後查位元率索引表,即可得到位元率是多少。 所以,可以看出,對於 CBR的檔案,可以用上面的公式,獲得MP3檔案大小後,再去解析第一幀的MPEG幀頭,得到位元率索引值,查表得到位元率的值,然後就算出整個CBR MP3檔案的播放時間。

####b).VBR檔案的時長計算(duration)

#####1 平均位元率法 這個方法,就是和CBR 同樣的思路,對於 VBR 的MP3來說,假如也像 CBR 的MP3一樣,也有個類似的每一幀都是固定的某個值的位元率,那麼計算整個 VBR的播放時間,也就可以用上面CBR 一樣的公式去計算了。 由此,就有了平均位元率的概念,即,將所有幀的位元率的值相加,得到一個總的位元率的值,然後除於總的幀數,就得到了一個平均位元率,這樣,使得理論上,此 VBR 相當於一個位元率為該平均位元率的CBR 了。 不過,可以看出,需要計算平均位元率之前,要先得到每一幀的位元率的值,以及總的幀的數目,然後才可以計算平均位元率的值。而為了得到每一幀的位元率的值,就要將整個 VBR MP3檔案都遍歷一遍,以此找到所有的幀,並解析每一個幀的幀頭,得到位元率索引值,然後查表得到位元率的值。如此做的話,效率顯然很低。因為此處只是為了計算整個 VBR MP3的播放時間,卻要遍歷整個檔案,還要解析每一幀的幀頭。

#####2 .總幀數法

    總幀數法,即利用總的幀的數目,來計算 VBR 的播放時間。 此方法的前提,也是MP3檔案的規範(以下兩點非常重要): (1)MP3,即 MPEG-1,Layer III,不論是 CBR,還是 VBR,每一幀的取樣個數都是固定的 1152個。即每一幀,都是固定的 1152個取樣。 (2)CBR和 VBR中的固定和可變,都是指的是位元率 Bitrate,而不是取樣率 Sample Rate。對於同一 MP3檔案,不論 CBR還是 VBR,取樣率都是固定的。

瞭解了這兩個前提後,就可以看出,對於 VBR 來說,雖然每一幀的位元率不同,但是每一幀的時間都是固定的,因為:

每一幀的時間= 該幀的取樣個數 * 該幀的取樣率 = 1152 * 取樣率

其中: 取樣個數:MPEG-1,Layer III,即MP3,不論是CBR 還是VBR,都是固定的 1152 取樣率:對於單個的 VBR 檔案,都是統一的,固定的,常見的是 44100Hz。取樣率可 以通過解析第一幀的幀頭得出取樣率索引,然後查表得到取樣率。 既然知道了每一幀的時間都是固定的,那麼很容易就想到,如果知道 VBR MP3有一共多少幀,那麼就可以用 總的幀數 × 每一幀的時間 = 總的時間長度了。公式如下:

VBR Duration = Total_Frame_Number * Time_Per_Frame = Total_Frame_Number * (Sample_Number * Time_Per_Sample) = Total_Frame_Number * (Sample_Number * (1 / Frame_Sample_Rate)) ------------------因為是Mp3,所以Sample_Number=1152

所以,剩下的事情,就是去得到 VBR MP3的總的幀數和採用率。 獲取第一個資料幀,解析幀的幀頭,別忘了,在VBR檔案的“Xing”標誌或“VBRi”標誌的頭中,會記錄幀的總個數,這樣就可以輕易地得到總的幀數和取樣率了。不過如果幀頭沒有記錄總幀數資訊的話,還得遍歷整個檔案計算總幀數。 ##2.3、ID3v1     ID3V1標準並不周全,存放的資訊少,無法存放歌詞,無法錄入專輯封面、圖片等。ID3V2是一個相當完備的標準,但給編寫軟體帶來困難,雖然贊成此格式的人很多,在軟體中絕大多數MP3仍在使用ID3V1標準。ID3v1標籤包含藝術家,標題,唱片集,釋出年代和流派。另外還有額外的註釋空間。位於音訊檔案的最後固定為128位元組。可以讀取該檔案的最後這128位元組獲得標籤。

ID3V1結構如下:

AAABBBBB BBBBBBBB BBBBBBBB BBBBBBBB BCCCCCCC CCCCCCCC CCCCCCCC CCCCCCCD DDDDDDDD DDDDDDDD DDDDDDDD DDDDDEEE EFFFFFFF FFFFFFFF FFFFFFFF FFFFFGHI

**表3.1 ID3 V1.0檔案尾說明**
位元組
長度 (位元組)
說 明
1-3(A)
3
存放“TAG”字元,表示ID3 V1.0標準,緊接其後的是歌曲資訊。
4-33(B)
30
歌名
34-63(C)
30
作者
64-93(D)
30
專輯名
94-97(E)
4
年份
98-125(F)
28
附註
126(G)
1
保留位
127(H)
1
音軌號
127(I)
1
MP3音樂類別,共147種
ID3V1 的各項資訊都是順序存放,沒有任何標識將其分開,比如標題資訊不足30 個位元組,則使用”\0”填充,資料結構定義如下:
typedef struct tagID3V1
{
	char Header[3];     //標籤頭必須是”TAG”否則認為沒有標籤
	char Title[30];     //標題
	char Artist[30];    //作者
	char Album[30];     //專集
	char Year[4];       //出品年代
	char Comment[28];   //備註
	char reserve;       //保留
	char track;         //音軌
	char Genre;         //型別
}ID3V1, *pID3V1;
##**注:流派使用原碼錶示說明見附錄二**

##附錄一:幀標識的含義 4). Declared ID3v2 frames

Thefollowing frames are declared in this draft.

AENCAudio encryption

APICAttached picture

COMMComments

COMRCommercial

ENCREncryption method registration

EQUAEqualization

ETCOEvent timing codes

GEOBGeneral encapsulated object

GRIDGroup identification registration

IPLSInvolved people list

LINKLinked information

MCDIMusic CD identifier

MLLT MPEGlocation lookup table

OWNEOwnership

PRIVPrivate

PCNT Playcounter

POPMPopularimeter

POSSPosition synchronisation

RBUFRecommended buffer size

RVADRelative volume adjustment

RVRBReverb

SYLTSynchronized lyric/text

SYTCSynchronized tempo codes

TALBAlbum/Movie/Show title

TBPM BPM(beats per minute)

TCOMComposer

TCONContent type

TCOPCopyright message

TDAT Date

TDLYPlaylist delay

TENCEncoded by

TEXTLyricist/Text writer

TFLT Filetype

TIME Time

TIT1Content group deion

TIT2Title/songname/content deion

TIT3Subtitle/Deion refinement

TKEYInitial key

TLANLanguage(s)

TLENLength

TMEDMedia type

TOALOriginal album/movie/show title

TOFNOriginal filename

TOLYOriginal lyricist(s)/text writer(s)

TOPEOriginal artist(s)/performer(s)

TORYOriginal release year

TOWN Fileowner/licensee

TPE1 Leadperformer(s)/Soloist(s)

TPE2Band/orchestra/accompaniment

TPE3Conductor/performer refinement

TPE4Interpreted, remixed, or otherwise modified by

TPOS Partof a set

TPUBPublisher

TRCKTrack number/Position in set

TRDARecording dates

TRSNInternet radio station name

TRSOInternet radio station owner

TSIZ Size

TSRC ISRC(international standard recording code)

TSSESoftware/Hardware and settings used for encoding

TYER Year

TXXX Userdefined text information

UFIDUnique file identifier

USERTerms of use

USLTUnsychronized lyric/text tranion

WCOMCommercial information

WCOPCopyright/Legal information

WOAFOfficial audio file webpage

WOAROfficial artist/performer webpage

WOASOfficial audio source webpage

WORSOfficial internet radio station homepage

WPAYPayment

WPUBPublishers official webpage

WXXX Userdefined URL link

##附錄二:流派使用原碼錶 /* Standard genres */ 0=”Blues”; 1=”ClassicRock”; 2=”Country”; 3=”Dance”; 4=”Disco”; 5=”Funk”; 6=”Grunge”; 7=”Hip-Hop”; 8=”Jazz”; 9=”Metal”; 10=”NewAge”; 11=”Oldies”; 12=”Other”; 13=”Pop”; 14=”R&B”; 15=”Rap”; 16=”Reggae”; 17=”Rock”; 18=”Techno”; 19=”Industrial”; 20=”Alternative”; 21=”Ska”; 22=”Deathl”; 23=”Pranks”; 24=”Soundtrack”; 25=”Euro-Techno”; 26=”Ambient”; 27=”Trip-Hop”; 28=”Vocal”; 29=”Jazz+Funk”; 30=”Fusion”; 31=”Trance”; 32=”Classical”; 33=”Instrumental”; 34=”Acid”; 35=”House”; 36=”Game”; 37=”SoundClip”; 38=”Gospel”; 39=”Noise”; 40=”AlternRock”; 41=”Bass”; 42=”Soul”; 43=”Punk”; 44=”Space”; 45=”Meditative”; 46=”InstrumentalPop”; 47=”InstrumentalRock”; 48=”Ethnic”; 49=”Gothic”; 50=”Darkwave”; 51=”Techno-Industrial”; 52=”Electronic”; 53=”Pop-Folk”; 54=”Eurodance”; 55=”Dream”; 56=”SouthernRock”; 57=”Comedy”; 58=”Cult”; 59=”Gangsta”; 60=”Top40”; 61=”ChristianRap”; 62=”Pop/Funk”; 63=”Jungle”; 64=”NativeAmerican”; 65=”Cabaret”; 66=”NewWave”; 67=”Psychadelic”; 68=”Rave”; 69=”Showtunes”; 70=”Trailer”; 71=”Lo-Fi”; 72=”Tribal”; 73=”AcidPunk”; 74=”AcidJazz”; 75=”Polka”; 76=”Retro”; 77=”Musical”; 78=”Rock&Roll”; 79=”HardRock”;

Winamp擴充了這個表

80=”Folk”; 81=”Folk-Rock”; 82=”NationalFolk”; 83=”Swing”; 84=”FastFusion”; 85=”Bebob”; 86=”Latin”; 87=”Revival”; 88=”Celtic”; 89=”Bluegrass”; 90=”Avantgarde”; 91=”GothicRock”; 92=”ProgessiveRock”; 93=”PsychedelicRock”; 94=”SymphonicRock”; 95=”SlowRock”; 96=”BigBand”; 97=”Chorus”; 98=”EasyListening”; 99=”Acoustic”; 100=”Humour”; 101=”Speech”; 102=”Chanson”; 103=”Opera”; 104=”ChamberMusic”; 105=”Sonata”; 106=”Symphony”; 107=”BootyBass”; 108=”Primus”; 109=”PornGroove”; 110=”Satire”; 111=”SlowJam”; 112=”Club”; 113=”Tango”; 114=”Samba”; 115=”Folklore”; 116=”Ballad”; 117=”PowerBallad”; 118=”RhythmicSoul”; 119=”Freestyle”; 120=”Duet”; 121=”PunkRock”; 122=”DrumSolo”; 123=”Acapella”; 124=”Euro-House”; 125=”DanceHall”;

其他擴充

126=”Goa”; 127=”Drum&Bass”; 128=”Club-House”; 129=”Hardcore”; 130=”Terror”; 131=”Indie”; 132=”BritPop”; 133=”Negerpunk”; 134=”PolskPunk”; 135=”Beat”; 136=”ChristianGangstaRap”; 137=”Heavyl”; 138=”Blackl”; 139=”Crossover”; 140=”ContemporaryChristian”; 141=”ChristianRock”; 142=”Merengue”; 143=”Salsa”; 144=”Trashl”; 145=”Anime”; 146=”JPop”; 147=”Synthpop”;

其他任何的數值都認為是“unknown”