zoukankan      html  css  js  c++  java
  • MP3文件结构及解码概述

    MP3文件结构概述

    Layer-3音频文件。MPEG(MovingPicture Experts Group)在汉语中译为活动图像专家组,特指活动影音压缩标准,MPEG音频文件是MPEG1标准中的声音部分。也叫MPEG音频层,它依据压缩质量和编码复杂程度划分为三层,即Layer-1Layer2Layer3。且分别相应MP1MP2MP3这三种声音文件,并依据不同的用途,使用不同层次的编码。MPEG音频编码的层次越高,编码器越复杂,压缩率也越高。MP1MP2的压缩率分别为4161-81,而MP3的压缩率则高达101-121

    MP3文件大体分为三部分:TAG_V2(ID3V2),音频数据。TAG_V1(ID3V1),当中ID3V2ID3V1的补充,并非全部的MP3都有ID3V2补充。即是不是全部的MP3文件都有ID3V2

    ID3V2

            假设MP3文件存在ID3V2。则一定在文件的头部,ID3V2结构分为头部(header)和若干标签帧。当中头部长度为10字节。10个字节的结构如表1

    0

    1

    2

    3

    4

    5

    6

    7

    8

    9

    内容为”ID3”

    版本

    副版本

    存放标志的字节

    ID3V2总大小(帧头和之后的若干标签帧总和)

    1

    由于345字节所代表的意义并非MP3解码的重点,故此仅仅讲解前三字节和后四字节:

    1.  从表1可看出推断MP3文件是否存在ID3V2。仅仅须要推断文件前三个字节是否是”ID3”

    2. ID3V2数据大小计算公司:

    total_size = (Size[0]&0x7F)*0x200000+ (Size[1]&0x7F)*0x400 + (Size[2]&0x7F)*0x80 +(Size[3]&0x7F)

    当中。size[0~3]。各自是表1中的6~9字节。

    须要注意的是。这个公司计算的长度并不包含ID3V210个字节的头部。

    ID3V2头部之后的若干标签帧每一帧结构分为标签ID4字节)、帧内容大小(4字节。不包含标签帧帧头)、存放标志位(2字节)、内容。

    当中标签ID的含义例如以下:

    TEXT: 歌词作者    TENC: 编码        WXXX URL链接(URL)        TCOP: 版权(Copyright)   TOPE: 原艺术家

    TCOM: 作曲家      TDAT: 日期        TPE3: 指挥者              TPE2: 乐队               TPE1: 艺术家相当于ID3v1Artist

    TPE4: 翻译(记录员、改动员)          TYER: 即ID3v1Year      USLT: 歌词               TSIZ: 大小

    TALB: 专辑相当于ID3v1Album         TIT1: 内容组描写叙述          

    TIT2: 标题相当于ID3v1Title       TIT3: 副标题

    TCON: 流派(风格)相当于ID3v1Genre AENC: 音频加密技术        

    TBPM: 每分钟节拍数COMM: 凝视相当于ID3v1Comment   

    TDLY: 播放列表返录                  TRCK: 音轨(曲号)相当于ID3v1Track

    TFLT: 文件类型                      TIME: 时间       

    TKEY: 最初keyword                    TLAN: 语言                

    TLEN: 长度                         TMED: 媒体类型    

    TOAL: 原唱片集                      TOFN: 原文件名称            

    TOLY: 原歌词作者                    TORY: 最初发行年份

    TOWM: 文件全部者(许可证者)          TPOS: 作品集部分          

    TPUB: 发行人                        TRDA: 录制日期

    TRSN Intenet电台名称                 TRSO Intenet电台全部者   UFID: 唯一的文件标识符  

    TSRC ISRC(国际的标准记录代码)     TSSE: 编码使用的软件(硬件设置)

    读取MP3文件ID3V2信息的函数可例如以下:

    //定义头部和标签帧

    typedefstruct ID3v2Header{

       char Identify[3];         // ID3v2固定标志:ID3

       char Ver;              //主版本,ID3v2就是3

       char Rever;            //副版本。一般都为0

       char Flag;             //标志位,一般为0。字义为abc00000

       char Size[4];             // 标签大小,一共四个字节,但每一个字节仅仅使用7位,最高位不使用恒为0,所以格式: 0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx

    }ID3v2Header;

     

    typedefstruct ID3v2Frame//标签帧,10个字节

    {

       char FrameID[4];          // 标志对比符。如TEXTTOPETDAT....

       char Size[4];             // 帧体的大小。依照正常的8位存储的,FSize = Size[0]*0x100000000 + Size[1]*0x10000 + Size[2]*0x100 + Size[3];

       char Flag[2];             // 存放标志

    }ID3v2Frame;

     

    //输出信息并返回ID3V2大小

    int ReadID3v2(FILE *pf)

    {

       ID3v2Headermp3header;

       ID3v2Frame mp3Frame;

       int FSize      = 0;

       char str[4096] = {0};

       char str2[5]   = {0};

       int ID3size;

       inthead_size = 0;

       inti;

       if(!pf)

           return -1;

       fseek(pf,0,SEEK_SET);

       fread(&mp3header,sizeof(mp3header),1,pf);

       if (mp3header.Identify[0]!='I' || mp3header.Identify[1]!='D' || mp3header.Identify[2]!='3' ){

           printf("此歌曲不支持ID3v2标准! ");

           //文件复位

           rewind(pf);

           return -2;

       }

       printf("ID3v2标志:%.3s ",mp3header.Identify);

       printf("ID3v2版本号:%d ",  mp3header.Ver);

       ID3size= (mp3header.Size[0]& 0x7F)<< 21|(mp3header.Size[1]& 0x7F)<< 14|(mp3header.Size[2] & 0x7F) << 7|(mp3header.Size[3] & 0x7F);

       printf("标签大小:%d *********** ",ID3size);

       for (i=0;i<ID3size;i=i+11+FSize){

           memset(&mp3Frame,0,sizeof(mp3Frame));

           memset(&str,0,sizeof(str));

           fseek(pf,10+i,SEEK_SET);               //移动到标签帧头

           fread(&mp3Frame,sizeof(mp3Frame),1,pf);

           //原则上是不用-1的,可是实际发现,总有一个字节的差距,为了计算方便-1。所以出现-1时标明此区块无内容

           FSize  = (int)(mp3Frame.Size[0]*0x100000000 + mp3Frame.Size[1]*0x10000+ mp3Frame.Size[2]*0x100 + mp3Frame.Size[3]-1);

           if (FSize>0)   {

               fseek(pf,10+11+i,SEEK_SET);//移动到内容区           

               fread(str,FSize,1,pf);

               GetStr(mp3Frame.FrameID,str2);

               printf("%s-%s: %s ",str2,mp3Frame.FrameID,str);

               head_size+=11;

           }else{

               return ID3size+10;

           }

       }

       return ID3size+10;

    }

     

    //通过FrameID获取相应的中文名

    void GetStr(char* oldstr,char* str)

    {

       if (0==memcmp((LPCTSTR)"TIT2",oldstr,4))

       {

           memcpy(str,"标题",4);

       }elseif(0==memcmp((LPCTSTR)"TPE1",oldstr,4)){

           memcpy(str,"作者",4);

       }elseif(0==memcmp((LPCTSTR)"TALB",oldstr,4)){

           memcpy(str,"专辑",4);

       }elseif(0==memcmp((LPCTSTR)"TRCK",oldstr,4)){

           memcpy(str,"音轨",4);

       }elseif(0==memcmp((LPCTSTR)"TYER",oldstr,4)){

           memcpy(str,"年代",4);

       }elseif(0==memcmp((LPCTSTR)"COMM",oldstr,4)){

           memcpy(str,"备注",4);

       }elseif(0==memcmp((LPCTSTR)"TCON",oldstr,4)){

           memcpy(str,"类型",4);

       }else{

           memcpy(str,"未知",4);  //其它的不是非常重要,所以省略了

       }

    }

    MP3文件数据结构及处理流程

    MP3数据解码流程借用图1描写叙述。

    1

    MP3文件的音频数据部分。是分为非常多数据帧存放。每一帧数据播放的时间长度计算公式:

       每帧持续时间(毫秒) =每帧採样数 /採样频率 * 1000

    如果每帧採样数为1152,採样频率为44.1K,则每帧数据播放的时间约为26ms

       没帧数据的结构包含帧头(header)、帧边信息(side)、主数据(main data)。

    帧头(header

            数据帧帧头长度为4字节,结构如图2所看到的。

    2

            由图可知。同步信息(synchronizationword11位皆为1,其它位信息如表

    版本号(ID

    2bit

    00-MPEG 2.5  01-没有定义    10-MPEG 2    11-MPEG 1

    层(layer

    2bit

    00-没有定义     01-Layer 3    10-Layer 2     11-Layer 1

    CRC校验

    1bit

    0-校验       1-不校验

    位率索引

    4bit

    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

    56

    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" 表示不同意值

    採样频率

    2bit

    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-没有定义

    是否填充

    1bit

    0-无需调整,1-调整

    保留(reserved

    1bit

     

    声道模式

    2bit

    00-立体声Stereo   01-Joint Stereo   10-双声道       11-单声道

    保留(reserved

    2bit

     

    版权标志

    1bit

    0-不合法  1-合法

    原版标志

    1bit

    0-非原版  1-原版

    强调方式

    2bit

    00-没有定义    01-50/15ms    10-保留      11-CCITT J.17

    2

    数据帧大小计算公式:

    Size=((採样个数 * (1 / 採样率))*帧的比特率)/8 +帧的填充大小

    对于Mp3格式:

       Size=((1152 * (1 /採样率))*帧的比特率)/8 +帧的填充大小= 144*帧的比特率/採样率+帧的填充大小

    当中:帧的填充大小便是23bit,不是0则为1

    帧边信息(side

    帧边信息解码的主要目的在于找出解这帧的各个參数。包含主数据開始位置,尺度因子长度等。

    帧边信息如图3所看到的。

    3

    当中main_data_begin(主数据開始)是一个偏移值。指出主数据是在同步字之前多少个字节開始。

    须要注意的是。1.帧头不一定是一帧的開始,帧头CRC校验字和帧边信息在帧数据中是滑动的。

    2.这个数值忽略帧头和帧边信息的存在,假设main_data_begin = 0, 则主数据从帧边信息的下一个字节開始,示意图如图4.

    4

            块类型(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个数据独立加窗后在经过连接计算得到的。

    主数据(main_data

            main_data中有两粒度组。没个粒度组分为两个声道,取数据存储结构如图5

    5

    当中,每一个通道(chN_data)的结构图6.

    6

    
  • 相关阅读:
    机会主义和理想主义
    从 http://snowolf.iteye.com/blog/735294 收藏 Java加密技术(十二)——*.PFX(*.p12)&个人信息交换文件
    Demystifying ‘Sys is undefined’
    server.mappath
    C# 发送http请求的几类方法
    几款用于防破解的软件
    机器学习之嵌套交叉验证
    机器学习之生成多项式和交互特征
    机器学习之调参
    dataframe列联表等操作
  • 原文地址:https://www.cnblogs.com/blfshiye/p/5177892.html
Copyright © 2011-2022 走看看