unit ID3Kernel;interfacetype Tid3v1= record Tag: array[0..2] of char; //00..02 , ='TAG' Title:array[0..$1d] of char; //03..20 Artist:array[0..$1d] of char; //21..3e Album:array[0..$1d] of char; //3f..5c Year:array[0..3] of char; //5d..60 Comment:array[0..$1c] of char; //61..7d Track:byte; //7e Genre:byte; //7f end;function ReadID3v1(strFile:string;var pid3v1:Tid3v1):integer; function WriteID3v1(strFile:string;var pid3v1:Tid3v1):integer; function DeleteID3v1(strFile:string):integer;implementationfunction ReadID3v1(strFile:string;var pid3v1:Tid3v1):integer; var f1:file of byte; bytAll: array [0..$7f] of byte; i: integer; begin result:=1; if strFile='' then exit; AssignFile(f1,strFile); FileMode:=0; Reset(f1); if FileSize(f1)<=$80 then exit; Seek(f1, FileSize(f1)-$80); for i:=0 to $7f do Read(f1,bytAll[i]); if (bytAll[0]<>ord('T')) and (bytAll[1]<>ord('A')) and (bytAll[2]<>ord('G')) then exit; // no 'TAG' found Move(bytAll,pid3v1,$80); CloseFile(f1); result:=0; end;function WriteID3v1(strFile:string;var pid3v1:Tid3v1):integer; var f1:file of byte; bytAll: array [0..$7f] of byte; i: integer; begin result:=1; AssignFile(f1,strFile); FileMode:=2; Reset(f1); if FileSize(f1)<=$80 then exit; Seek(f1, FileSize(f1)-$80); for i:=0 to $2 do Read(f1,bytAll[i]); // test if 'TAG' exists if (bytAll[0]=ord('T')) and (bytAll[1]=ord('A')) and (bytAll[2]=ord('G')) then Seek(f1,FileSize(f1)-$80) else Seek(f1,FileSize(f1)); Move(pid3v1,bytAll,$80); for i:=0 to $7f do Write(f1,bytAll[i]); CloseFile(f1); result:=0; end;function DeleteID3v1(strFile:string):integer; var f1:file of byte; bytAll: array [0..$7f] of byte; i: integer; begin Result:=1; AssignFile(f1,strFile); FileMode:=2; Reset(f1); if FileSize(f1)<=$80 then exit; Seek(f1, FileSize(f1)-$80); for i:=0 to $2 do Read(f1,bytAll[i]); // test if 'TAG' exists if (bytAll[0]=ord('T')) and (bytAll[1]=ord('A')) and (bytAll[2]=ord('G')) then begin Seek(f1,FileSize(f1)-$80); Truncate(f1) end; CloseFile(f1); Result:=0; end;end.
这里有个读取信息的,要写入改一下就可以了。
http://community.csdn.net/Expert/topic/4732/4732750.xml?temp=1.647586E-02用FindFirst/FindNext遍历指定文件夹的mp3文件,获取文件名写入就可以了。
Tid3v1= record
Tag: array[0..2] of char; //00..02 , ='TAG'
Title:array[0..$1d] of char; //03..20
Artist:array[0..$1d] of char; //21..3e
Album:array[0..$1d] of char; //3f..5c
Year:array[0..3] of char; //5d..60
Comment:array[0..$1c] of char; //61..7d
Track:byte; //7e
Genre:byte; //7f
end;function ReadID3v1(strFile:string;var pid3v1:Tid3v1):integer;
function WriteID3v1(strFile:string;var pid3v1:Tid3v1):integer;
function DeleteID3v1(strFile:string):integer;implementationfunction ReadID3v1(strFile:string;var pid3v1:Tid3v1):integer;
var
f1:file of byte;
bytAll: array [0..$7f] of byte;
i: integer;
begin
result:=1;
if strFile='' then exit;
AssignFile(f1,strFile);
FileMode:=0;
Reset(f1);
if FileSize(f1)<=$80 then exit;
Seek(f1, FileSize(f1)-$80);
for i:=0 to $7f do Read(f1,bytAll[i]);
if (bytAll[0]<>ord('T')) and (bytAll[1]<>ord('A'))
and (bytAll[2]<>ord('G')) then exit; // no 'TAG' found
Move(bytAll,pid3v1,$80);
CloseFile(f1);
result:=0;
end;function WriteID3v1(strFile:string;var pid3v1:Tid3v1):integer;
var
f1:file of byte;
bytAll: array [0..$7f] of byte;
i: integer;
begin
result:=1;
AssignFile(f1,strFile);
FileMode:=2;
Reset(f1);
if FileSize(f1)<=$80 then exit;
Seek(f1, FileSize(f1)-$80);
for i:=0 to $2 do Read(f1,bytAll[i]); // test if 'TAG' exists
if (bytAll[0]=ord('T')) and (bytAll[1]=ord('A'))
and (bytAll[2]=ord('G'))
then Seek(f1,FileSize(f1)-$80)
else Seek(f1,FileSize(f1));
Move(pid3v1,bytAll,$80);
for i:=0 to $7f do Write(f1,bytAll[i]);
CloseFile(f1);
result:=0;
end;function DeleteID3v1(strFile:string):integer;
var
f1:file of byte;
bytAll: array [0..$7f] of byte;
i: integer;
begin
Result:=1;
AssignFile(f1,strFile);
FileMode:=2;
Reset(f1);
if FileSize(f1)<=$80 then exit;
Seek(f1, FileSize(f1)-$80);
for i:=0 to $2 do Read(f1,bytAll[i]); // test if 'TAG' exists
if (bytAll[0]=ord('T')) and (bytAll[1]=ord('A'))
and (bytAll[2]=ord('G'))
then begin
Seek(f1,FileSize(f1)-$80);
Truncate(f1)
end;
CloseFile(f1);
Result:=0;
end;end.
Classes, SysUtils;const
MAX_MUSIC_GENRES = 148; { Max. number of music genres }
DEFAULT_GENRE = 255; { Index for default genre } { Used with VersionID property }
TAG_VERSION_1_0 = 1; { Index for ID3v1.0 tag }
TAG_VERSION_1_1 = 2; { Index for ID3v1.1 tag }var
MusicGenre: array [0..MAX_MUSIC_GENRES - 1] of string; { Genre names }type
{ Used in TID3v1 class }
String04 = string[4]; { String with max. 4 symbols }
String30 = string[30]; { String with max. 30 symbols } { Class TMPEGID3v1 }
TMPEGID3v1 = class(TObject)
private
{ Private declarations }
FExists: Boolean;
FVersionID: Byte;
FTitle: String30;
FArtist: String30;
FAlbum: String30;
FYear: String04;
FComment: String30;
FTrack: Byte;
FGenreID: Byte;
procedure FSetTitle(const NewTitle: String30);
procedure FSetArtist(const NewArtist: String30);
procedure FSetAlbum(const NewAlbum: String30);
procedure FSetYear(const NewYear: String04);
procedure FSetComment(const NewComment: String30);
procedure FSetTrack(const NewTrack: Byte);
procedure FSetGenreID(const NewGenreID: Byte);
function FGetGenre: string;
public
{ Public declarations }
constructor Create; { Create object }
procedure ResetData; { Reset all data }
function ReadFromFile(const FileName: string): Boolean; { Load tag }
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
function SaveToFile(const FileName: string): Boolean; { Save tag }
property Exists: Boolean read FExists; { True if tag found }
property VersionID: Byte read FVersionID; { Version code }
property Title: String30 read FTitle write FSetTitle; { Song title }
property Artist: String30 read FArtist write FSetArtist; { Artist name }
property Album: String30 read FAlbum write FSetAlbum; { Album name }
property Year: String04 read FYear write FSetYear; { Year }
property Comment: String30 read FComment write FSetComment; { Comment }
property Track: Byte read FTrack write FSetTrack; { Track number }
property GenreID: Byte read FGenreID write FSetGenreID; { Genre code }
property Genre: string read FGetGenre; { Genre name }
end;implementationtype
{ Real structure of ID3v1 tag }
TagRecord = record
Header: array [1..3] of Char; { Tag header - must be "TAG" }
Title: array [1..30] of Char; { Title data }
Artist: array [1..30] of Char; { Artist data }
Album: array [1..30] of Char; { Album data }
Year: array [1..4] of Char; { Year data }
Comment:array [1..30] of Char; { Comment data }
Genre: Byte; { Genre data }
end;{ ********************* Auxiliary functions & procedures ******************** }function ReadTag(const FileName: string; var TagData: TagRecord): Boolean;
var
SourceFile: file;
begin
try
Result := true;
{ Set read-access and open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
{ Read tag }
Seek(SourceFile, FileSize(SourceFile) - 128);
BlockRead(SourceFile, TagData, 128);
CloseFile(SourceFile);
except
{ Error }
Result := false;
end;
end;{ --------------------------------------------------------------------------- }function RemoveTag(const FileName: string): Boolean;
var
SourceFile: file;
begin
try
Result := true;
{ Allow write-access and open file }
FileSetAttr(FileName, 0);
AssignFile(SourceFile, FileName);
FileMode := 2;
Reset(SourceFile, 1);
{ Delete tag }
Seek(SourceFile, FileSize(SourceFile) - 128);
Truncate(SourceFile);
CloseFile(SourceFile);
except
{ Error }
Result := false;
end;
end;{ --------------------------------------------------------------------------- }function SaveTag(const FileName: string; TagData: TagRecord): Boolean;
var
SourceFile: file;
begin
try
Result := true;
{ Allow write-access and open file }
FileSetAttr(FileName, 0);
AssignFile(SourceFile, FileName);
FileMode := 2;
Reset(SourceFile, 1);
{ Write tag }
Seek(SourceFile, FileSize(SourceFile));
BlockWrite(SourceFile, TagData, SizeOf(TagData));
CloseFile(SourceFile);
except
{ Error }
Result := false;
end;
end;{ --------------------------------------------------------------------------- }function GetTagVersion(const TagData: TagRecord): Byte;
begin
Result := TAG_VERSION_1_0;
{ Terms for ID3v1.1 }
if ((TagData.Comment[29] = #0) and (TagData.Comment[30] <> #0)) or
((TagData.Comment[29] = #32) and (TagData.Comment[30] <> #32)) then
Result := TAG_VERSION_1_1;
end;{ ********************** Private functions & procedures ********************* }procedure TMPEGID3v1.FSetTitle(const NewTitle: String30);
begin
FTitle := TrimRight(NewTitle);
end;{ --------------------------------------------------------------------------- }procedure TMPEGID3v1.FSetArtist(const NewArtist: String30);
begin
FArtist := TrimRight(NewArtist);
end;{ --------------------------------------------------------------------------- }procedure TMPEGID3v1.FSetAlbum(const NewAlbum: String30);
begin
FAlbum := TrimRight(NewAlbum);
end;{ --------------------------------------------------------------------------- }procedure TMPEGID3v1.FSetYear(const NewYear: String04);
begin
FYear := TrimRight(NewYear);
end;{ --------------------------------------------------------------------------- }procedure TMPEGID3v1.FSetComment(const NewComment: String30);
begin
FComment := TrimRight(NewComment);
end;{ --------------------------------------------------------------------------- }procedure TMPEGID3v1.FSetTrack(const NewTrack: Byte);
begin
FTrack := NewTrack;
end;{ --------------------------------------------------------------------------- }procedure TMPEGID3v1.FSetGenreID(const NewGenreID: Byte);
begin
FGenreID := NewGenreID;
end;{ --------------------------------------------------------------------------- }function TMPEGID3v1.FGetGenre: string;
begin
Result := '';
{ Return an empty string if the current GenreID is not valid }
if FGenreID in [0..MAX_MUSIC_GENRES - 1] then Result := MusicGenre[FGenreID];
end;
{ ********************** Public functions & procedures ********************** }constructor TMPEGID3v1.Create;
begin
inherited;
ResetData;
end;{ --------------------------------------------------------------------------- }procedure TMPEGID3v1.ResetData;
begin
FExists := false;
FVersionID := TAG_VERSION_1_0;
FTitle := '';
FArtist := '';
FAlbum := '';
FYear := '';
FComment := '';
FTrack := 0;
FGenreID := DEFAULT_GENRE;
end;{ --------------------------------------------------------------------------- }function TMPEGID3v1.ReadFromFile(const FileName: string): Boolean;
var
TagData: TagRecord;
begin
{ Reset and load tag data from file to variable }
ResetData;
Result := ReadTag(FileName, TagData);
{ Process data if loaded and tag header OK }
if (Result) and (TagData.Header = 'TAG') then
begin
FExists := true;
FVersionID := GetTagVersion(TagData);
{ Fill properties with tag data }
FTitle := TrimRight(TagData.Title);
FArtist := TrimRight(TagData.Artist);
FAlbum := TrimRight(TagData.Album);
FYear := TrimRight(TagData.Year);
if FVersionID = TAG_VERSION_1_0 then FComment := TrimRight(TagData.Comment)
else
begin
FComment := TrimRight(Copy(TagData.Comment, 1, 28));
FTrack := Ord(TagData.Comment[30]);
end;
FGenreID := TagData.Genre;
end;
end;{ --------------------------------------------------------------------------- }function TMPEGID3v1.RemoveFromFile(const FileName: string): Boolean;
var
TagData: TagRecord;
begin
{ Find tag }
Result := ReadTag(FileName, TagData);
{ Delete tag if loaded and tag header OK }
if (Result) and (TagData.Header = 'TAG') then Result := RemoveTag(FileName);
end;{ --------------------------------------------------------------------------- }function TMPEGID3v1.SaveToFile(const FileName: string): Boolean;
var
TagData: TagRecord;
begin
{ Prepare tag record }
FillChar(TagData, SizeOf(TagData), 0);
TagData.Header := 'TAG';
Move(FTitle[1], TagData.Title, Length(FTitle));
Move(FArtist[1], TagData.Artist, Length(FArtist));
Move(FAlbum[1], TagData.Album, Length(FAlbum));
Move(FYear[1], TagData.Year, Length(FYear));
Move(FComment[1], TagData.Comment, Length(FComment));
if FTrack > 0 then
begin
TagData.Comment[29] := #0;
TagData.Comment[30] := Chr(FTrack);
end;
TagData.Genre := FGenreID;
{ Delete old tag and write new tag }
Result := (RemoveFromFile(FileName)) and (SaveTag(FileName, TagData));
end;{ ************************** Initialize music genres ************************ }initialization
begin
{ Standard genres }
MusicGenre[0] := 'Blues';
MusicGenre[1] := 'Classic Rock';
MusicGenre[2] := 'Country';
MusicGenre[3] := 'Dance';
MusicGenre[4] := 'Disco';
MusicGenre[5] := 'Funk';
MusicGenre[6] := 'Grunge';
MusicGenre[7] := 'Hip-Hop';
MusicGenre[8] := 'Jazz';
MusicGenre[9] := 'Metal';
MusicGenre[10] := 'New Age';
MusicGenre[11] := 'Oldies';
MusicGenre[12] := 'Other';
MusicGenre[13] := 'Pop';
MusicGenre[14] := 'R&B';
MusicGenre[15] := 'Rap';
MusicGenre[16] := 'Reggae';
MusicGenre[17] := 'Rock';
MusicGenre[18] := 'Techno';
MusicGenre[19] := 'Industrial';
MusicGenre[20] := 'Alternative';
MusicGenre[21] := 'Ska';
MusicGenre[22] := 'Death Metal';
MusicGenre[23] := 'Pranks';
MusicGenre[24] := 'Soundtrack';
MusicGenre[25] := 'Euro-Techno';
MusicGenre[26] := 'Ambient';
MusicGenre[27] := 'Trip-Hop';
MusicGenre[28] := 'Vocal';
MusicGenre[29] := 'Jazz+Funk';
MusicGenre[30] := 'Fusion';
MusicGenre[31] := 'Trance';
MusicGenre[32] := 'Classical';
MusicGenre[33] := 'Instrumental';
MusicGenre[34] := 'Acid';
MusicGenre[35] := 'House';
MusicGenre[36] := 'Game';
MusicGenre[37] := 'Sound Clip';
MusicGenre[38] := 'Gospel';
MusicGenre[39] := 'Noise';
MusicGenre[40] := 'AlternRock';
MusicGenre[41] := 'Bass';
MusicGenre[42] := 'Soul';
MusicGenre[43] := 'Punk';
MusicGenre[44] := 'Space';
MusicGenre[45] := 'Meditative';
MusicGenre[46] := 'Instrumental Pop';
MusicGenre[47] := 'Instrumental Rock';
MusicGenre[48] := 'Ethnic';
MusicGenre[49] := 'Gothic';
MusicGenre[50] := 'Darkwave';
MusicGenre[51] := 'Techno-Industrial';
MusicGenre[52] := 'Electronic';
MusicGenre[53] := 'Pop-Folk';
MusicGenre[54] := 'Eurodance';
MusicGenre[55] := 'Dream';
MusicGenre[56] := 'Southern Rock';
MusicGenre[57] := 'Comedy';
MusicGenre[58] := 'Cult';
MusicGenre[59] := 'Gangsta';
MusicGenre[60] := 'Top 40';
MusicGenre[61] := 'Christian Rap';
MusicGenre[62] := 'Pop/Funk';
MusicGenre[63] := 'Jungle';
MusicGenre[64] := 'Native American';
MusicGenre[65] := 'Cabaret';
MusicGenre[66] := 'New Wave';
MusicGenre[67] := 'Psychadelic';
MusicGenre[68] := 'Rave';
MusicGenre[69] := 'Showtunes';
MusicGenre[70] := 'Trailer';
MusicGenre[71] := 'Lo-Fi';
MusicGenre[72] := 'Tribal';
MusicGenre[73] := 'Acid Punk';
MusicGenre[74] := 'Acid Jazz';
MusicGenre[75] := 'Polka';
MusicGenre[76] := 'Retro';
MusicGenre[77] := 'Musical';
MusicGenre[78] := 'Rock & Roll';
MusicGenre[79] := 'Hard Rock';
{ Extended genres }
MusicGenre[80] := 'Folk';
MusicGenre[81] := 'Folk-Rock';
MusicGenre[82] := 'National Folk';
MusicGenre[83] := 'Swing';
MusicGenre[84] := 'Fast Fusion';
MusicGenre[85] := 'Bebob';
MusicGenre[86] := 'Latin';
MusicGenre[87] := 'Revival';
MusicGenre[88] := 'Celtic';
MusicGenre[89] := 'Bluegrass';
MusicGenre[90] := 'Avantgarde';
MusicGenre[91] := 'Gothic Rock';
MusicGenre[92] := 'Progessive Rock';
MusicGenre[93] := 'Psychedelic Rock';
MusicGenre[94] := 'Symphonic Rock';
MusicGenre[95] := 'Slow Rock';
MusicGenre[96] := 'Big Band';
MusicGenre[97] := 'Chorus';
MusicGenre[98] := 'Easy Listening';
MusicGenre[99] := 'Acoustic';
MusicGenre[100]:= 'Humour';
MusicGenre[101]:= 'Speech';
MusicGenre[102]:= 'Chanson';
MusicGenre[103]:= 'Opera';
MusicGenre[104]:= 'Chamber Music';
MusicGenre[105]:= 'Sonata';
MusicGenre[106]:= 'Symphony';
MusicGenre[107]:= 'Booty Bass';
MusicGenre[108]:= 'Primus';
MusicGenre[109]:= 'Porn Groove';
MusicGenre[110]:= 'Satire';
MusicGenre[111]:= 'Slow Jam';
MusicGenre[112]:= 'Club';
MusicGenre[113]:= 'Tango';
MusicGenre[114]:= 'Samba';
MusicGenre[115]:= 'Folklore';
MusicGenre[116]:= 'Ballad';
MusicGenre[117]:= 'Power Ballad';
MusicGenre[118]:= 'Rhythmic Soul';
MusicGenre[119]:= 'Freestyle';
MusicGenre[120]:= 'Duet';
MusicGenre[121]:= 'Punk Rock';
MusicGenre[122]:= 'Drum Solo';
MusicGenre[123]:= 'A capella';
MusicGenre[124]:= 'Euro-House';
MusicGenre[125]:= 'Dance Hall';
MusicGenre[126]:= 'Goa';
MusicGenre[127]:= 'Drum & Bass';
MusicGenre[128]:= 'Club-House';
MusicGenre[129]:= 'Hardcore';
MusicGenre[130]:= 'Terror';
MusicGenre[131]:= 'Indie';
MusicGenre[132]:= 'BritPop';
MusicGenre[133]:= 'Negerpunk';
MusicGenre[134]:= 'Polsk Punk';
MusicGenre[135]:= 'Beat';
MusicGenre[136]:= 'Christian Gangsta Rap';
MusicGenre[137]:= 'Heavy Metal';
MusicGenre[138]:= 'Black Metal';
MusicGenre[139]:= 'Crossover';
MusicGenre[140]:= 'Contemporary Christian';
MusicGenre[141]:= 'Christian Rock';
MusicGenre[142]:= 'Merengue';
MusicGenre[143]:= 'Salsa';
MusicGenre[144]:= 'Trash Metal';
MusicGenre[145]:= 'Anime';
MusicGenre[146]:= 'JPop';
MusicGenre[147]:= 'Synthpop';
end;end.
Classes, SysUtils;const
TAG_VERSION_2_3 = 3; { Code for ID3v2.3.x tag }type
{ Class TMPEGID3v2 }
TMPEGID3v2 = class(TObject)
private
{ Private declarations }
FExists: Boolean;
FVersionID: Byte;
FSize: Integer;
FTitle: string;
FArtist: string;
FAlbum: string;
FTrack: Byte;
FYear: string;
FGenre: string;
FComment: string;
procedure FSetTitle(const NewTitle: string);
procedure FSetArtist(const NewArtist: string);
procedure FSetAlbum(const NewAlbum: string);
procedure FSetTrack(const NewTrack: Byte);
procedure FSetYear(const NewYear: string);
procedure FSetGenre(const NewGenre: string);
procedure FSetComment(const NewComment: string);
public
{ Public declarations }
constructor Create; { Create object }
procedure ResetData; { Reset all data }
function ReadFromFile(const FileName: string): Boolean; { Load tag }
function RemoveFromFile(const FileName: string): Boolean; { Delete tag }
function SaveToFile(const FileName: string): Boolean; { Save tag }
property Exists: Boolean read FExists; { True if tag found }
property VersionID: Byte read FVersionID; { Version code }
property Size: Integer read FSize; { Total tag size }
property Title: string read FTitle write FSetTitle; { Song title }
property Artist: string read FArtist write FSetArtist; { Artist name }
property Album: string read FAlbum write FSetAlbum; { Album title }
property Track: Byte read FTrack write FSetTrack; { Track number }
property Year: string read FYear write FSetYear; { Release year }
property Genre: string read FGenre write FSetGenre; { Genre name }
property Comment: string read FComment write FSetComment; { Comment }
end;implementationconst
{ ID3v2 tag ID }
ID3V2_ID = 'ID3'; { Max. number of supported tag frames }
ID3V2_FRAME_COUNT = 7; { Names of supported tag frames }
ID3V2_FRAME: array [1..ID3V2_FRAME_COUNT] of string =
('TIT2', 'TPE1', 'TALB', 'TRCK', 'TYER', 'TCON', 'COMM');type
{ ID3v2 frame header }
FrameHeader = record
ID: array [1..4] of Char; { Frame ID }
Size: Integer; { Size excluding header }
Flags: Word; { Flags }
end; { ID3v2 header data - for internal use }
TagInfo = record
{ Real structure of ID3v2 header }
ID: array [1..3] of Char; { Always "ID3" }
Version: Byte; { Version number }
Revision: Byte; { Revision number }
Flags: Byte; { Flags of tag }
Size: array [1..4] of Byte; { Tag size excluding header }
{ Extended data }
FileSize: Integer; { File size (bytes) }
Frame: array [1..ID3V2_FRAME_COUNT] of string; { Information from frames }
end;{ ********************* Auxiliary functions & procedures ******************** }function ReadHeader(const FileName: string; var Tag: TagInfo): Boolean;
var
SourceFile: file;
Transferred: Integer;
begin
try
Result := true;
{ Set read-access and open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
{ Read header and get file size }
BlockRead(SourceFile, Tag, 10, Transferred);
Tag.FileSize := FileSize(SourceFile);
CloseFile(SourceFile);
{ if transfer is not complete }
if Transferred < 10 then Result := false;
except
{ Error }
Result := false;
end;
end;{ --------------------------------------------------------------------------- }function GetVersionID(const Tag: TagInfo): Byte;
begin
{ Get tag version from header }
Result := Tag.Version;
end;{ --------------------------------------------------------------------------- }function GetTagSize(const Tag: TagInfo): Integer;
begin
{ Get total tag size }
Result :=
Tag.Size[1] * $200000 +
Tag.Size[2] * $4000 +
Tag.Size[3] * $80 +
Tag.Size[4] + 10;
if Result > Tag.FileSize then Result := 0;
end;{ --------------------------------------------------------------------------- }procedure SetTagItem(const ID, Data: string; var Tag: TagInfo);
var
Iterator: Byte;
begin
{ Set tag item if supported frame found }
for Iterator := 1 to ID3V2_FRAME_COUNT do
if ID3V2_FRAME[Iterator] = ID then Tag.Frame[Iterator] := Data;
end;{ --------------------------------------------------------------------------- }function Swap32(const Figure: Integer): Integer;
var
ByteArray: array [1..4] of Byte absolute Figure;
begin
{ Swap 4 bytes }
Result :=
ByteArray[1] * $1000000 +
ByteArray[2] * $10000 +
ByteArray[3] * $100 +
ByteArray[4];
end;{ --------------------------------------------------------------------------- }procedure ReadFrames(const FileName: string; var Tag: TagInfo);
var
SourceFile: file;
Frame: FrameHeader;
Data: array [1..250] of Char;
DataPosition: Integer;
begin
try
{ Set read-access, open file }
AssignFile(SourceFile, FileName);
FileMode := 0;
Reset(SourceFile, 1);
Seek(SourceFile, 10);
while (FilePos(SourceFile) < GetTagSize(Tag)) and (not EOF(SourceFile)) do
begin
FillChar(Data, SizeOf(Data), 0);
{ Read frame header and check frame ID }
BlockRead(SourceFile, Frame, 10);
if not (Frame.ID[1] in ['A'..'Z']) then break;
DataPosition := FilePos(SourceFile);
{ Read frame data and set tag item if frame supported }
BlockRead(SourceFile, Data, Swap32(Frame.Size) mod SizeOf(Data));
SetTagItem(Frame.ID, Data, Tag);
Seek(SourceFile, DataPosition + Swap32(Frame.Size));
end;
CloseFile(SourceFile);
except
end;
end;{ --------------------------------------------------------------------------- }function ExtractTrack(const TrackString: string): Byte;
var
Index, Value, Code: Integer;
begin
{ Extract track from string }
Index := Pos('/', Trim(TrackString));
if Index = 0 then Val(Trim(TrackString), Value, Code)
else Val(Copy(Trim(TrackString), 1, Index - 1), Value, Code);
if Code = 0 then Result := Value
else Result := 0;
end;{ --------------------------------------------------------------------------- }function ExtractGenre(const GenreString: string): string;
begin
{ Extract genre from string }
Result := Trim(GenreString);
if Pos(')', Result) > 0 then Delete(Result, 1, LastDelimiter(')', Result));
end;