Delphi判断一个文件是否是MP3

  • 格式:docx
  • 大小:20.03 KB
  • 文档页数:10

Delphi判断一个文件是否是MP3MP3文件是流媒体文件,没有文件头,要判断是不是MP3文件只能分析帧头数据。

MP3文件还可能存在TAG,也可能不存在TAG。

如果存在TAG,其格式可能是ID3V1或者是ID3V2或者是2者都有。

如果是ID3V1,它将存在于MP3文件的末尾,占据128个字节;如果是ID3V2,它在MP3文件的头部,大小不固定,要获取MP3文件的各种信息,不但要判断文件是否含有TAG,还要判断每一帧的数据。

下面将用Delphi实现对上述三种格式的判断。

1.ID3V1:包含128个字节,结构如下:_TTAGV1INFO = record// TAG三个字母,如果有这三个字母则是ID3V1,如果不是则没有Indentify: array [0..2] of Char;// 歌曲名,30个字节Title: array [0..29] of Char;// 歌手名,30个字节Artist: array [0..29] of Char;// 所属唱片,30个字节Album: array [0..29] of Char;// 年,4个字节Year: array [0..3] of Char;// 注释,28个字节Comment: array [0..29] of Char;// 保留位,3个字节Reserved: Char;end;只要判断文件末尾第128个字节开始3个字节是否含有“TAG”标志即可,如含有,则表示有ID3V1,没有则表示没有该TAG。

代码如下:function TForm1.tagV1Check(fileName: string): Boolean;varfsMP3: TFileStream;tagInfo: _TTAGV1INFO;beginresult := False;fsMP3 := TFileStream.Create(fileName, fmOpenRead);tryfsMP3.Position := fsMP3.Size - 128;fsMP3.Read(tagInfo, SizeOf(tagInfo));if tagInfo.Indentify = 'TAG' thenresult := True;finallyFreeAndNil(fsMP3);end;end;2.ID3V2:这个比ID3V1要复杂些,长度并不固定,它的结构大体如下:_TTAGV2INFO = record// ID3v2的标识位,3字节Indentify: array [0..2] of Char;// 版本号,1字节Version: Byte;// 副版本号1字节Sub_Version: Byte;// 存放标志(Flag) 的3位,但只记录1字节Flag: Byte;// 标签大小,4字节(标签头的10个字节不计算在内)Size: array [0..3] of Byte;end;含义:①ID3v2的标识位,3字节,是“ID3”三个字母,如果没有这三个字母,则没有ID3V2信息②版本号,1字节,ID3V2的3版,是“3”③副版本号1字节,此版本记录,是“0”④存放标志(Flag) 的3位,但只记录1字节,标志字节一般为0,格式:abc00000,“a 位”表示不使用同步;“b位”表示否使用展扩头,展扩头一般不用;“c位”表示这个标签是否是个供测试用的标签(一般不是,也不置)。

所以a、b、c三位均设为零。

⑤标签大小,4字节(标签头的10个字节不计算在内) 。

标签大小:一共四个字节,但每个字节只使用7位,最高位不使用恒为0,所以格式如下:0xxxxxxx 0xxxxxxx 0xxxxxxx 0xxxxxxx计算大小时要将0去掉,得到一个28位的二进制数,就是标签的大,计算公式如下ID3大小= 第一个字节 × 0x200000 + 第二个字节 × 0x400 + 第三个字节 × 0x80 + 第四个字节。

为了计算MP3文件的播放时间,要将MP3文件除去TAG的大小计算出来,所以在判断ID3V2时,将其所占字节数返回,以便计算MP3帧的大小,代码如下:function TForm1.tagV2Check(fileName: string): Cardinal;varfsMP3: TFileStream;tagInfo: _TTAGV2INFO;tagSize: Integer;bTagNoExist: Boolean;beginresult := 0;bTagNoExist := False;fsMP3 := TFileStream.Create(fileName, fmOpenRead);tryfsMP3.Position := 0;repeatfsMP3.Read(tagInfo, SizeOf(tagInfo));if tagInfo.Indentify = 'ID3' thenbegintagSize := (tagInfo.Size[0] and $7F) * $200000 + (tagInfo.Size[1] and $7F) * $400 + (tagInfo.Size[2] and $7F) * $80 + (tagInfo.Size[3] and $7F);result := tagSize + 10;fsMP3.Position := tagSize + 10;endelsebTagNoExist := True;until bTagNoExist;finallyFreeAndNil(fsMP3);end;end;3.MP3帧头:mp3帧头的格式如下:=======================================帧头格式=======================================12 sync 0xFFF1 version 1=mpeg1.0, 0=mpeg2.02 lay 4-lay = layerI, II or III1 error protection 0=yes, 1=no4 bitrate_index see table below2 sampling_freq see table below1 padding1 extension see table below2 mode see table below2 mode_ext used with "joint stereo" mode1 copyright 0=no 1=yes1 original 0=no 1=yes2 emphasis see table below=======================================含义:- bitrate_index. mpeg1.01 2 3 4 5 6 7 8 9 10 11 12 13 14layer1 32 64 96 128 160 192 224 256 288 320 352 384 416 448 layer2 32 48 56 64 80 96 112 128 160 192 224 256 320 384 layer3 32 40 48 56 64 80 96 112 128 160 192 224 256 320 . mpeg2.01 2 3 4 5 6 7 8 9 10 11 12 13 14layer1 32 48 56 64 80 96 112 128 144 160 176 192 224 256layer2 8 16 24 32 40 48 56 64 80 96 112 128 144 160layer3 8 16 24 32 40 48 56 64 80 96 112 128 144 160- sampling_freq. mpeg1.00 1 244100 48000 32000. mpeg2.00 1 222050 24000 16000- mode:0 "stereo"1 "joint stereo"2 "dual channel"3 "single channel"- mode extension:0 MPG_MD_LR_LR1 MPG_MD_LR_I2 MPG_MD_MS_LR3 MPG_MD_MS_Ijsbound :mode_ext 0 1 2 3layer1 4 8 12 162 4 8 12 163 04 8 16- emphasis:0 "none"1 "50/15 microsecs"2 "reserved" must not be used !3 "CCITT J 17"播放时间计算公式:MP3文件一帧的播放时间为26ms。

播放时间(ms)= 帧数× 26帧数= 帧文件大小/ 帧长度帧长度:. mpeg1.0layer1:(48000 × bitrate) / sampling_freq + paddinglayer2 & 3:(144000 × bitrate) / sampling_freq + padding. mpeg2.0layer1:(24000 × bitrate) / sampling_freq + paddinglayer2 & 3:(72000 × bitrate) / sampling_freq + paddingMP3为mpeg1.0 layer3,所以以上的取值都取mpeg1.0 layer3 Delphi定义的帧结构:_MP3Header = recordsync: string;version: string;lay: string;error_protection: string;bitrate_index: Word;sampling_freq: Word;padding: Byte;extension: string;mode: string;mode_ext: string;copyright: string;original: string;emphasis: string;end;_MPEG1_LAY_3 = (// 32kbps 1MPEG1_LAY_3_BITRATE_32 = 1,// 40kbps 2MPEG1_LAY_3_BITRATE_40,// 48kbps 3MPEG1_LAY_3_BITRATE_48,// 56kbps 4MPEG1_LAY_3_BITRATE_56,// 64kbps 5MPEG1_LAY_3_BITRATE_64,// 80kbps 6MPEG1_LAY_3_BITRATE_80,// 96kbps 7MPEG1_LAY_3_BITRATE_96,// 112kbps 8MPEG1_LAY_3_BITRATE_112,// 128kbps 9MPEG1_LAY_3_BITRATE_128,// 160kbps 10MPEG1_LAY_3_BITRATE_160,// 192kbps 11MPEG1_LAY_3_BITRATE_192,// 224kbps 12MPEG1_LAY_3_BITRATE_224,// 256kbps 13MPEG1_LAY_3_BITRATE_256,// 320kbps 14MPEG1_LAY_3_BITRATE_320);实现代码:function TActiveFormX.headCheck(fileName: string; bTagV1Exist: Boolean;cTagV2Length, cBitRate, cPlayTime: Cardinal): Boolean;varfsMP3: TFileStream;header_Info: _MP3Header;strHeader: array [0..3] of Byte;fileSize, frameLength, frameNum, fileTime: Cardinal;beginresult := False;fsMP3 := TFileStream.Create(fileName, fmOpenRead);tryfsMP3.Seek(cTagV2Length, soBeginning);fsMP3.Read(strHeader, SizeOf(strHeader));// (同步信号)sync,version,lay,error protection检查if ((strHeader[0] and $FF) <> $FF) or ((strHeader[1] and $FB) <> $FB) thenbeginShowMessage('sync,version,lay,error protection is error! sync,version,lay,error protection: ' + IntToStr(strHeader[0]) + IntToStr(strHeader[1]));Exit;end;// bitrate检查if ((strHeader[2] and $F0) = $00) or ((strHeader[2] and $F0) = $F0) thenbeginShowMessage('bitrate检查error! bitrate:' + IntToStr((strHeader[2] and $F0)));end;// sampling_freq检查if ((strHeader[2] shr 2) and $03) = $03 thenbeginShowMessage('sampling_freq检查error! sampling_freq:' + IntToStr((strHeader[2] shr 2) and $03));Exit;end;// 取bitrate_indexcase _MPEG1_LAY_3((strHeader[2] shr 4) and $0F) of// 32kbps 1MPEG1_LAY_3_BITRATE_32: header_Info.bitrate_index := 32;// 40kbps 2MPEG1_LAY_3_BITRATE_40: header_Info.bitrate_index := 40;// 48kbps 3MPEG1_LAY_3_BITRATE_48: header_Info.bitrate_index := 48;// 56kbps 4MPEG1_LAY_3_BITRATE_56: header_Info.bitrate_index := 56;// 64kbps 5MPEG1_LAY_3_BITRATE_64: header_Info.bitrate_index := 64;// 80kbps 6MPEG1_LAY_3_BITRATE_80: header_Info.bitrate_index := 80;// 96kbps 7MPEG1_LAY_3_BITRATE_96: header_Info.bitrate_index := 96;// 112kbps 8MPEG1_LAY_3_BITRATE_112: header_Info.bitrate_index := 112;// 128kbps 9MPEG1_LAY_3_BITRATE_128: header_Info.bitrate_index := 128;// 160kbps 10MPEG1_LAY_3_BITRATE_160: header_Info.bitrate_index := 160;// 192kbps 11MPEG1_LAY_3_BITRATE_192: header_Info.bitrate_index := 192;// 224kbps 12MPEG1_LAY_3_BITRATE_224: header_Info.bitrate_index := 224;// 256kbps 13MPEG1_LAY_3_BITRATE_256: header_Info.bitrate_index := 256;// 320kbps 14MPEG1_LAY_3_BITRATE_320: header_Info.bitrate_index := 320;elsebeginShowMessage('取bitrate_index error! bitrate_index:' + IntToStr((strHeader[2] shr 4) and $0F));Exit;end;// 判断此mp3文件是否为cBitRate kbps以上文件if header_Info.bitrate_index < cBitRate thenbeginShowMessage('判断此mp3文件是否为' + IntToStr(cBitRate) + 'kbps以上文件error! bitrate_index:' + IntToStr(header_Info.bitrate_index));Exit;end;// 取sampling_freqif ((strHeader[2] shr 2) and $03) = $00 thenheader_Info.sampling_freq := 44100else if ((strHeader[2] shr 2) and $03) = $01 thenheader_Info.sampling_freq := 48000else if ((strHeader[2] shr 2) and $03) = $02 thenheader_Info.sampling_freq := 32000elsebeginShowMessage('取sampling_freq error! sampling_freq:' + IntToStr((strHeader[2] shr 2) and $03));Exit;end;// 获取paddingif ((strHeader[2] shr 1) and $01) = $00 thenheader_Info.padding := 0elseheader_Info.padding := 1;// 获得MP3播放时间fileSize := fsMP3.Size - cTagV2Length;if bTagV1Exist thenfileSize := fileSize - 128;frameLength := (144000 * header_Info.bitrate_index) div header_Info.sampling_freq + header_Info.padding;frameNum := fileSize div frameLength;fileTime := frameNum * 26 div 1000;// 判断此mp3音频的播放时间是否为cPlayTime分以上文件if fileTime < cPlayTime thenbeginShowMessage('判断此mp3音频的播放时间是否为' + IntToStr(cPlayTime) + '秒以上文件error! 音频的播放时间:' + IntToStr(fileTime));Exit;end;// 判断mp3音频采样率是否在44KHZ以上if header_Info.sampling_freq < 44000 thenShowMessage('判断mp3音频采样率是否在44KHZ以上error! 音频采样率:' + IntToStr(header_Info.sampling_freq));Exit;end;result := True;finallyFreeAndNil(fsMP3);end;end;。