DelphiFAQ Home Search:

How to read/write ID3 tags in MP3 files

 

comments3 comments. Current rating: 2 stars (1 votes). Leave comments and/ or rate it.

The thing that makes MPEG Layer 3 files good (besides their size:) are ID3 tags. Thanks to them you can save information about the song. Here's the ID3 tag structure and information on reading/modifying them. Enjoy!

The ID3 tag is saved in the last 128 bytes of a MPEG Layer 3 file. It starts with a 'TAG' string. If this string is absent that means that ID3 information has been removed. But don't worry - all you have to do is append it to the file. In newer versions of Delphi if you are going to use this code you may want to use the packed keyword with arrays and records.

// The MPEG Layer 3 ID3 tag structure:
type
  ID3Struct = record
    Signature: array [0..2] of Char; { Should be: 'TAG' }
    Title, Artist, Album: array [0..29] of Char;
    Year: array [0..3] of Char;
    Comment: array [0..29] of Char;
    Genre: Byte;
  end;

// Here's the genre (Max. 256 entries).
const
  ID3Genre : array [0..126] of string = ('Blues', 'Classic Rock',
    'Country', 'Dance', 'Disco', 'Funk', 'Grunge', 'Hip-Hop',
    'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B',
    'Rap', 'Reggae', 'Rock', 'Techno', 'Industrial', 'Alternative',
    'Ska', 'Death Metal', 'Pranks', 'Soundtrack', 'Euro-Techno',
    'Ambient', 'Trip-Hop', 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance',
    'Classical', 'Instrumental', 'Acid', 'House', 'Game', 'Sound Clip',
    'Gospel', 'Noise', 'AlternRock', 'Bass', 'Soul', 'Punk',
    'Space', 'Meditative', 'Instrumental Pop', 'Instrumental Rock',
    'Ethnic', 'Gothic', 'Darkwave', 'Techno-Industrial', 'Electronic',
    'Pop-Folk', 'Eurodance', 'Dream', 'Southern Rock', 'Comedy',
    'Cult', 'Gangsta', 'Top 40', 'Christian Rap', 'Pop/Funk',
    'Jungle', 'Native American', 'Cabaret', 'New Wave', 'Psychadelic',
    'Rave', 'Showtunes', 'Trailer', 'Lo-Fi', 'Tribal', 'Acid Punk',
    'Acid Jazz', 'Polka', 'Retro', 'Musical', 'Rock & Roll',
    'Hard Rock', 'Folk', 'Folk-Rock', 'National Folk', 'Swing',
    'Fast Fusion', 'Bebob', 'Latin', 'Revival', 'Celtic', 'Bluegrass',
    'Avantgarde', 'Gothic Rock', 'Progressive Rock', 'Psychedelic Rock',
    'Symphonic Rock', 'Slow Rock', 'Big Band', 'Chorus', 'Easy Listening',
    'Acoustic', 'Humour', 'Speech', 'Chanson', 'Opera', 'Chamber Music',
    'Sonata', 'Symphony', 'Booty Bass', 'Primus', 'Porn Groove',
    'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba', 'Folklore',
    'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle', 'Duet',
    'Punk Rock', 'Drum Solo', 'Acapella', 'Euro-House', 'Dance Hall' );

// This is the ID3 Tag read code:
procedure ReadID3Tag;
var
  fMP3: file of Byte;
  Tag: ID3Struct;
begin { ReadID3Tag }
  try
    (* sFileName - (string) The full file name with path. *)
    AssignFile(fMP3, sFileName);
    Reset(fMP3);
    try
      Seek(fMP3, FileSize(fMP3) - 128);
      BlockRead(fMP3, Tag, SizeOf(Tag))
    finally

    end; { try }

  finally
    CloseFile(fMP3)
  end; { try }
  if fMP3.Signature<>'TAG' then
  begin

    { Doesn't have an ID3 tag }
  end { fMP3.Signature<>'TAG' }
  else
  begin

    { do something with the tag }
  end; { not (fMP3.Signature<>'TAG') }
end; { ReadID3Tag }


(* WriteID3Tag() function
  **
  ** Copyright (c) 2000 Jacob Dybala (m3Rlin)
  ** Freeware.
  **
  ** Created : January 7 2000
  ** Modified: January 7 2000
  ** Please leave this copyright notice.
  *)
procedure WriteID3Tag(id3NewTag: ID3Struct; sFileName: string);
var
  fMP3: file of Byte;
  Tag: ID3Struct;
begin { WriteID3Tag }
  try
    AssignFile(fMP3, sFileName);
    Reset(fMP3);
    try
      Seek(fMP3, FileSize(fMP3) - ID3OffsetFromEnd);
      BlockRead(fMP3, Tag, SizeOf(Tag));
      if fMP3.Signature='TAG' then
        { Replace old tag }
        Seek(fMP3, FileSize(fMP3) - ID3OffsetFromEnd)
      else
        { Append tag to file because it doesn't exist.
          Cannot use Append() function. It's only for text files. }
        Seek(fMP3, FileSize(fMP3));
      BlockWrite(fMP3, id3NewTag, SizeOf(id3NewTag))
    finally

    end; { try }

  finally
    CloseFile(fMP3)
  end; { try }
end; { WriteID3Tag }
You don't like the formatting? Check out SourceCoder then!

Comments:

2006-01-15, 15:55:56
anonymous from France  
rating
Lots of errors ...
This code works :
procedure WriteID3Tag(NewTag: ID3Struct; sFileName: string);
var
fMP3 : file;
Tag : ID3Struct;
begin { WriteID3Tag }
try
FileSetAttr(sFileName, 0);
AssignFile(fMP3, sFileName);
FileMode := 2;
Reset(fMP3, 1);
try
Seek(fMP3, FileSize(fMP3) - 128);
BlockRead(fMP3, Tag, SizeOf(Tag));

if Tag.Signature='TAG' then
{ Replace old tag }
Seek(fMP3, FileSize(fMP3) - 128)
else
{ Append tag to file because it doesn't exist.
Cannot use Append() function. It's only for text files. }
Seek(fMP3, FileSize(fMP3));

BlockWrite(fMP3, NewTag, SizeOf(NewTag))
finally

end; { try }

finally
CloseFile(fMP3)
end; { try }
end; { WriteID3Tag }

2006-06-09, 02:12:25
anonymous from China  
2006-12-23, 06:22:15
anonymous from Italy  
//----------------------------------------------
//error fixed, and put everything inounit:
//----------------------------------------------

un
unit ulfmp3;

interface

// The MPEG Layer 3 ID3 tag structure:
type
ID3Struct = record
Signature: array [0..2] of Char; { Should be: 'TAG' }
Title, Artist, Album: array [0..29] of Char;
Year: array [0..3] of Char;
Comment: array [0..29] of Char;
Genre: Byte;
end;

// Here's the genre (Max. 256 entries).
const
ID3Genre : array [0..125] of string = ('Blues', 'Classic Rock',
'Country', 'Dance', 'Disco', 'Funk', 'Grunge', 'Hip-Hop',
'Jazz', 'Metal', 'New Age', 'Oldies', 'Other', 'Pop', 'R&B',
'Rap', 'Reggae', 'Rock', 'Techno', 'Industrial', 'Alternative',
'Ska', 'Death Metal', 'Pranks', 'Soundtrack', 'Euro-Techno',
'Ambient', 'Trip-Hop', 'Vocal', 'Jazz+Funk', 'Fusion', 'Trance',
'Classical', 'Instrumental', 'Acid', 'House', 'Game', 'Sound Clip',
'Gospel', 'Noise', 'AlternRock', 'Bass', 'Soul', 'Punk',
'Space', 'Meditative', 'Instrumental Pop', 'Instrumental Rock',
'Ethnic', 'Gothic', 'Darkwave', 'Techno-Industrial', 'Electronic',
'Pop-Folk', 'Eurodance', 'Dream', 'Southern Rock', 'Comedy',
'Cult', 'Gangsta', 'Top 40', 'Christian Rap', 'Pop/Funk',
'Jungle', 'Native American', 'Cabaret', 'New Wave', 'Psychadelic',
'Rave', 'Showtunes', 'Trailer', 'Lo-Fi', 'Tribal', 'Acid Punk',
'Acid Jazz', 'Polka', 'Retro', 'Musical', 'Rock & Roll',
'Hard Rock', 'Folk', 'Folk-Rock', 'National Folk', 'Swing',
'Fast Fusion', 'Bebob', 'Latin', 'Revival', 'Celtic', 'Bluegrass',
'Avantgarde', 'Gothic Rock', 'Progressive Rock', 'Psychedelic Rock',
'Symphonic Rock', 'Slow Rock', 'Big Band', 'Chorus', 'Easy Listening',
'Acoustic', 'Humour', 'Speech', 'Chanson', 'Opera', 'Chamber Music',
'Sonata', 'Symphony', 'Booty Bass', 'Primus', 'Porn Groove',
'Satire', 'Slow Jam', 'Club', 'Tango', 'Samba', 'Folklore',
'Ballad', 'Power Ballad', 'Rhythmic Soul', 'Freestyle', 'Duet',
'Punk Rock', 'Drum Solo', 'Acapella', 'Euro-House', 'Dance Hall' );

function ReadID3Tag(sFileName:String):ID3Struct;
procedure WriteID3Tag(NewTag: ID3Struct; sFileName: string);

implementation


// This is the ID3 Tag read code:
function ReadID3Tag(sFileName:String):ID3Struct;
var
fMP3: file of Byte;
Tag: ID3Struct;
begin { ReadID3Tag }
try
(* sFileName - (string) The full file name with path. *)
AssignFile(fMP3, sFileName);
Reset(fMP3);
try
Seek(fMP3, FileSize(fMP3) - 128);
BlockRead(fMP3, Tag, SizeOf(Tag))
finally

end; { try }

finally
CloseFile(fMP3)
end; { try }

if tag.Signature<>'TAG' then
begin

{ Doesn't have an ID3 tag }
end { fMP3.Signature<>'TAG' }
else
begin

{ do something with the tag }
end; { not (fMP3.Signature<>'TAG') }
result:=tag;
end; { ReadID3Tag }


(* WriteID3Tag() function
**
** Copyright (c) 2000 Jacob Dybala (m3Rlin)
** Freeware.
**
** Created : January 7 2000
** Modified: January 7 2000
** Please leave this copyright notice.
*)

procedure WriteID3Tag(NewTag: ID3Struct; sFileName: string);
var
fMP3 : file;
Tag : ID3Struct;
begin { WriteID3Tag }
try
//FileSetAttr(sFileName, 0);
AssignFile(fMP3, sFileName);
FileMode := 2;
Reset(fMP3, 1);
try
Seek(fMP3, FileSize(fMP3) - 128);
BlockRead(fMP3, Tag, SizeOf(Tag));

if Tag.Signature='TAG' then
{ Replace old tag }
Seek(fMP3, FileSize(fMP3) - 128)
else
{ Append tag to file because it doesn't exist.
Cannot use Append() function. It's only for text files. }
Seek(fMP3, FileSize(fMP3));

BlockWrite(fMP3, NewTag, SizeOf(NewTag))
finally

end; { try }

finally
CloseFile(fMP3)
end; { try }
end; { WriteID3Tag }


end.

 

 

Email address (not necessary):

Rate as
Hide my email when showing my comment.
Please notify me once a day about new comments on this topic.
Please provide a valid email address if you select this option.
 
It seems that you are
from Los Angeles, US .

Info/ Feedback on this

Show city and country
Show country only
Hide my location
You can mark text as 'quoted' by putting [quote] .. [/quote] around it.
Please type in the code:
photo Add a picture:

Please do not post inappropriate pictures. Inappropriate pictures include pictures of minors and nudity. The owner of this web site reserves the right to delete such material.