1. 程式人生 > >QT 讀取mp3ID3V2 獲取mp3專輯圖片、專輯名稱、標題、作者(一)

QT 讀取mp3ID3V2 獲取mp3專輯圖片、專輯名稱、標題、作者(一)

ID3V2是目前主流的mp3標籤格式,特別是做為車載音樂播放器等一些無法連線到網際網路的應用場景上,我們無法通過網路獲得歌曲的資訊,因此,讀取ID3V2或者ID3V1標籤就是一個很好的解決方案,這裡主要記錄的是在qt上通過程式碼實現這些資訊的讀取,借鑑了網上主流的方案,這裡只是簡單的介紹了下程式碼會用到的地方

一、ID3V2標籤格式說明

1.1 標籤頭

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

char Header[3]; /*必須為"ID3"否則認為標籤不存在*/

char Ver; /*版本號;ID3V2.3就記錄03,ID3V2.4就記錄04*/

char Revision; /*副版本號;此

版本記錄為00*/

char Flag; /*存放標誌的位元組,這個版本只定義了三位,稍後詳細解說*/

char Size[4]; /*標籤大小,包括標籤幀和標籤頭。(不包括擴充套件標籤頭的10個位元組)*/

我們可以利用Binary Viewer開啟任意一個mp3檔案:

觀察前10個位元組:

其中,49,44,33 對應的ascii碼就是ID3,03代表ID3V2.3,說明這個音樂檔案的標籤是ID3V2.3格式;

後4個位元組00,17,2B,1A記錄的是整個標籤的大小(位元組),但每個位元組只用7位,最高位不使用恆為0。所以格式如下:

0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx

計算時要做適當的轉換,通過移位操作實現:

    mp3_TagSize = 	((Header_size[0] & 0xff) << 21) |
                                ((Header_size[1] & 0xff) << 14) |
                                ((Header_size[2] & 0xff) << 7) |
                                (Header_size[3] & 0xff);

其中Header_size[0]對應的是00位元組,Header_size[3]對應的是最後一個位元組(1A),以此類推;

1.2標籤幀

每個標籤幀都有一個10個位元組的幀頭和至少一個位元組的不固定長度的內容組成,如圖所示:

灰色框為幀頭,藍色框為幀內容

幀頭的定義如下:

char FrameID[4]; /*用四個字元標識一個幀,說明其內容,稍後有常用的標識對照表*/

char Size[4]; /*幀內容的大小,不包括幀頭,不得小於1*/

char Flags[2]; /*存放標誌,只定義了6位,稍後詳細解說*/

幀內容每個位元組的8位全用,格式如下:

xxxxxxxx xxxxxxxx xxxxxxxx xxxxxxxx

framecount = frameSize[0]*0x1000000+frameSize[1]*0x10000+frameSize[2]*0x100+frameSize[3];

1.3 幀標識

用四個字元標識一個幀,說明一個幀的內容含義,常用的對照如下:

TIT2=標題 表示內容為這首歌的標題,下同

TPE1=作者

TALB=專集

TRCK=音軌 格式:N/M 其中N為專集中的第N首,M為專集中共M首,N和M為ASCII碼錶示的數字

TYER=年代 是用ASCII碼錶示的數字

TCON=型別 直接用字串表示

COMM=備註 格式:"eng\0備註內容",其中eng表示備註所使用的自然語言

APIC = 專輯圖片

二、圖片讀取

在網易雲音樂和qq音樂下載的歌曲,一般都是以png和jfif(jpeg的一種衍生格式)儲存在歌曲檔案中的,我們要把圖片提取並且存放,就必須知道圖片的儲存格式,這樣才能生成指定的圖片檔案格式

jpeg格式解析可以參考博文:

png格式解析可以參考博文:

我這裡只做簡單的判斷:

png檔案標誌的前兩個位元組為89 50;

jpeg檔案標誌的前兩個位元組為FF,D8;

根據這兩個特點可以判斷出圖片的型別

圖中紅色部分的14個位元組是固定的,我們在讀取圖片的資料幀時直接跳過,接著到綠色部分,判斷綠色部分的資料,根據資料可以得出圖片型別,圖中顯然是jpeg格式圖片,接著就可以讀取圖片內容了(綠色部分也要包含在圖片內容的讀取部分,紅色不用)

總結:在程式碼中,只要在標籤頭的10個位元組中判斷檔案開頭是否為ID3V2,讀取標籤的總大小;

然後依次讀取每個標籤幀;

每個標籤幀中又分為:讀取標籤頭,獲得標籤型別,獲得幀內容大小,讀取幀內容;

下一篇將通過程式碼實現讀取