Mp3 - ler e gravar tag de uma musica

Top  Previous  Next

 

How to read infos in MP3 files 

Answer:

 

 

   Description: 

   Component MP3Info extracts/saves any ID3 Tag into/from it's 

   properties from/to MP3 file. 

   Keywords: MP3 ID3 TAG INFO 

 

   Author: Rok Krulec (Rok@fpp.edu) (http://Rok.fpp.edu) 

   Primary site: ftp://ftp.fpp.edu/pub/people/Rok_Krulec/mp3i-v12.zip 

 

If you use this component, I would like to get 1 American dollar to Rok Krulec, Zagrad 6, 3000 Celje, Slovenia, Europe. 

 

Description of Variables, Properties, Methods and Events: 

    Genres: TStrings;                         - List of Genres 

    constructor Create(AOwner: TComponent);   - Creates an instance 

    destructor Destroy; override;             - Destroys an instance 

    method Save;                              - Saves ID3 Tag to file 

    method RemoveID3;                         - Removes ID3 Tag form file 

    property Filename: TFilename;             - Filename of MP3 file, when changed it opens a new MP3 file 

    property Artist: String;                  - Artist   (30 Chars) 

    property Title: String;                   - Title    (30 Chars) 

    property Album: String;                   - Album    (30 Chars) 

    property Year: String;                    - Year     ( 4 chars) 

    property Comment: String;                 - Comment  (30 Chars) 

    property Genre: String;                   - Genre               [Read Only] 

    Property GenreID: Byte;                   - Genre ID 

    property Valid: Boolean;                  - Is ID3 valid        [Read Only] 

    property Saved: Boolean;                  - Save success        [Read Only] 

    property Error: String;                   - Error Message       [Read Only] 

    property onChangeFile:TNotifyEvent;       - Triggers when other file is openned 

    property onChange:TNotifyEvent;           - Triggers when one of propertis is changed (Artist, Title, Album, Year, Comment, GenreID) 

    property onError:TNotifyEvent;            - Triggers when errors ocure (Wrong filename, Frong fileformat) 

} 

 

unit MP3Info; 

 

interface 

 

uses 

  SysUtils, Classes; 

 

const 

TAGLEN = 127

 

type 

  TMP3Info = class(TComponent) 

  private 

    { Private declarations } 

    vFilename: TFilename; 

    vMP3Tag, vArtist, vTitle, vAlbum, vComment, vYear, vGenre, vError: String; 

    vGenreID: Byte; 

    vValid: Boolean; 

    vSaved: Boolean; 

    vChangeFileEvent, vChangeEvent, vErrorEvent: TNotifyEvent; 

    procedure SetFilename(Filename: TFilename); 

    procedure SetArtist(Artist: String); 

    procedure SetTitle(Title: String); 

    procedure SetAlbum(Album: String); 

    procedure SetYear(Year: String); 

    procedure SetComment(Comment: String); 

    procedure SetGenreID(ID: Byte); 

    procedure Open; 

  protected 

    { Protected declarations } 

  public 

    { Public declarations } 

  published 

    { Published declarations } 

    Genres: TStrings; 

    constructor Create(AOwner: TComponent); override; 

    destructor Destroy; override; 

    procedure Save; 

    procedure RemoveID3; 

    property Filename: TFilename read vFilename write SetFilename; 

    property Artist: String read vArtist write SetArtist; 

    property Title: String read vTitle write SetTitle; 

    property Album: String read vAlbum write SetAlbum; 

    property Year: String read vYear write SetYear; 

    property Comment: String read vComment write SetComment; 

    property Genre: String read vGenre; 

    Property GenreID: Byte read vGenreID write SetGenreID; 

    property Valid: Boolean read vValid; 

    property Saved: Boolean read vSaved; 

    property Error: String read vError; 

    property onChangeFile:TNotifyEvent read vChangeFileEvent write vChangeFileEvent; 

    property onChange:TNotifyEvent read vChangeEvent write vChangeEvent; 

    property onError:TNotifyEvent read vErrorEvent write vErrorEvent; 

  end

 

procedure Register; 

 

implementation 

 

constructor TMP3Info.Create(AOwner: TComponent); 

begin 

   inherited Create(AOwner); 

   Genres := TStringList.Create

   vGenreID := 12

   vValid := false; 

   vSaved := false; 

 

{ Fill the Genres String List so one can use it combo boxes e.t.c. Example: ComboBox.Items.Assign(MP3Info.Genres) } 

   Genres.CommaText := 

'"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","Psychedelic","Rave","Showtunes","Trailer","Lo-Fi","Tribal","Acid Punk",' 

+'"Acid Jazz","Polka","Retro","Musical","Rock & Roll","Hard Rock","Folk","Folk/Rock","National Folk","Swing","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"' 

 

end

 

destructor TMP3Info.Destroy; 

begin 

   inherited Destroy; 

end

 

{ Procedure to run when Filename property is changed } 

procedure TMP3Info.SetFilename(Filename: TFilename); 

begin 

   vFilename:=Filename; 

   Open; 

end

 

procedure TMP3Info.SetArtist(Artist: String); 

begin 

   vArtist:=Copy(Artist,030); 

   if Assigned(onChange) then onChange(Self); 

end

 

procedure TMP3Info.SetTitle(Title: String); 

begin 

   vTitle:=Copy(Title, 030); 

   if Assigned(onChange) then onChange(Self); 

end

 

procedure TMP3Info.SetAlbum(Album: String); 

begin 

   vAlbum:=Copy(Album, 030); 

   if Assigned(onChange) then onChange(Self); 

end

 

procedure TMP3Info.SetYear(Year: String); 

begin 

   vYear:=Copy(Year, 04); 

   if Assigned(onChange) then onChange(Self); 

end

 

procedure TMP3Info.SetComment(Comment: String); 

begin 

   vComment:=Copy(Comment, 030); 

   if Assigned(onChange) then onChange(Self); 

end

 

procedure TMP3Info.SetGenreID(ID: Byte); 

begin 

   if ((ID>255or (ID>Genres.Count-1)) then ID:=12

   vGenreID:=ID; 

   vGenre:=Genres[vGenreID]; //this line is important because after changing 

                              //vGenreID whitout it vGenre will be the same like before !!! 

   if Assigned(onChange) then onChange(Self); 

end

 

{ Opens file with Filename property, reads ID3 Tag and sets properties } 

procedure TMP3Info.Open; 

 

   { Strips empty spaces at the end of word } 

   function Strip(WordToStrip:String; CharToStripAway: Char):String; 

   var i: Integer; 

   begin 

      for i:=length(WordToStrip) downto 1 do begin 

         if WordToStrip[i]<>' ' then begin 

            Strip:=Copy(WordToStrip, 0, i); 

            exit

         end

      end

      Strip:=''

   end

 

var dat:file of char; 

    id3:array [0..TAGLEN] of char; 

begin 

   vSaved:=false; 

   vValid:=True; 

   if FileExists(vFilename) then begin 

      assignfile(dat,vFilename); 

      reset(dat); 

      seek(dat,FileSize(dat)-128); 

      blockread(dat,id3,128); 

      closefile(dat); 

      vMP3tag:=copy(id3, 13); 

      if vMP3Tag='TAG' then begin 

         vTitle:=strip(copy(id3, 430),' '); 

         vArtist:=strip(copy(id3, 3430), ' '); 

         vAlbum:=strip(copy(id3, 6430), ' '); 

         vComment:=strip(copy(id3, 9830), ' '); 

         vYear:=strip(copy(id3, 944), ' '); 

         vGenreID:=ord(id3[127]); 

         if vGenreID>Genres.Count then vGenreID:=12

         vGenre:=Genres[vGenreID]; 

         { Trigger OnChange Event } 

         if Assigned(onChangeFile) then onChangeFile(Self); 

      end else begin 

         vValid:=False; 

         vTitle:=''

         vArtist:=''

         vAlbum:=''

         vComment:=''

         vYear:=''

         vGenreID:=12

         vError:='Wrong file format or no ID3 Tag !'

         if Assigned(onError) then onError(Self); 

      end

   end else begin 

      vValid:=False; 

      vError:='File doesn`t exist !'

      if Assigned(onError) then onError(Self); 

   end

end

 

{ Removes the ID3-tag from currently open file } 

procedure TMP3Info.RemoveID3; 

var dat : file of char; 

begin 

  // does the file exist ? 

  if Not FileExists(vFilename) then 

     begin 

       vError:='File doesn`t exist !'

       if Assigned(onError) then onError(Self); 

       exit

     end

  // is the file already untagged ? 

  if (vValid=false) then 

     begin 

       vError:='File is already untagged !'

       if Assigned(onError) then onError(Self); 

       exit

     end

  // remove readonly-attribute 

  If (FileGetAttr(vFilename) and faReadOnly >0) then 

     FileSetAttr(vFileName,FileGetAttr(vFilename)-faReadOnly); 

  // if readonly attr. already exists it cannot be removed to cut ID3 Tag 

  If (FileGetAttr(vFilename) and faReadOnly >0) then 

     begin 

       vError:='Can´t write ID3 tag information !'

       if Assigned(onError) then onError(Self); 

       exit

     end

  // open current mp3 file if ID3 tag exists 

  If (vValid=true) then 

     begin 

       {I-} 

         assignfile(dat,vFilename); 

         reset(dat); 

       {I+} 

       If IOResult<>0 then 

          begin 

            vError:='Could not open file !'

            if Assigned(onError) then onError(Self); 

            exit

          end

       seek(dat,FileSize(dat)-128); 

       truncate(dat);  // cut all 128 bytes of file 

       closefile(dat); 

       vValid:=false;  // set vValid to false because the tag has been removed 

     end

end

 

{ Saves ID3 Tag to currently opened file } 

procedure TMP3Info.Save; 

 

   { Empties 128 character array } { Don't tell me that there is a function for this in Pascal } 

   procedure EmptyArray(var Destination: array of char); 

   var i: Integer; 

   begin 

      for i:=0 to TAGLEN do begin 

         Destination[i]:=' '

      end

   end

 

   { Insert a substring into character array at index position of array } 

   procedure InsertToArray(Source: String; var Destination: array of char; Index: Integer); 

   var i: Integer; 

   begin 

      for i:=0 to length(Source)-1 do begin 

         Destination[Index+i]:=Source[i+1]; 

      end

   end

 

var dat:file of char; 

    id3:array [0..TAGLEN] of char; 

begin 

   vSaved:=true; 

   // does the filename exist ? 

   if FileExists(vFilename) then begin 

      // fill 128 bytes long array with ID3 Tag information 

      EmptyArray(id3); 

      InsertToArray('TAG', id3, 0); 

      InsertToArray(vTitle, id3, 3); 

      InsertToArray(vArtist, id3, 33); 

      InsertToArray(vAlbum, id3, 63); 

      InsertToArray(vComment, id3, 97); 

      InsertToArray(vYear, id3, 93); 

      id3[127]:=chr(vGenreID); 

      // remove readonly-attribute 

      If (FileGetAttr(vFilename) and faReadOnly >0) then 

         FileSetAttr(vFileName,FileGetAttr(vFilename)-faReadOnly); 

      // if readonly attr. already exists it cannot be removed to write ID3 

      If (FileGetAttr(vFilename) and faReadOnly >0) then 

         begin 

           vSaved:=False; 

           vError:='Can´t write ID3 tag information !'

           if Assigned(onError) then onError(Self); 

           exit

         end

      // if valid then overwrite existing ID3 Tag, else append to file 

      if (vValid=True) then begin 

         {I-} 

           assignfile(dat,vFilename); 

           reset(dat); 

           seek(dat,FileSize(dat)-128); 

           blockwrite(dat,id3,128); 

           closefile(dat); 

         {I+} 

         If IOResult<>0 then vSaved:=false; 

      end else begin 

         {I-} 

           assignfile(dat,vFilename); 

           reset(dat); 

           seek(dat,FileSize(dat)); 

           blockwrite(dat,id3,128); 

           closefile(dat); 

         {I+} 

         If IOResult<>0 then vSaved:=false; 

      end 

   end else begin 

      vValid:=False; 

      vSaved:=False; 

      vError:='File doesn`t exist or is not valid !'

      if Assigned(onError) then onError(Self); 

   end

end

 

procedure Register; 

begin 

  RegisterComponents('Samples', [TMP3Info]); 

end

 

end

 

   The ID3 Information is stored in the last 128 bytes of an MP3 file. 

   The ID3 has the following fields, and the offsets given here, are from 0-127 

 

   Field       Length            offsets 

   ------------------------------------- 

   Tag           3                0-2 

   Songname     30                3-32 

   Artist       30                33-62 

   Album        30                63-92 

   Year          4                93-96 

   Comment      30                97-126 

   Genre         1                127 

} 

 

 

---------------------- another way

 

// Ler a TAG da música:

 

procedure ReadID3Tag(path_arquivo: String);

var

  FS: TFileStream;

  Buffer: array [1..128of char;

  ID: string[3];

  Titulo: string[30];

  Artista: string[30];

  Album: string[30];

  Ano: string[4];

  Comentario: string[30];

  Genero: byte;

begin

  FS := TFileStream.Create(path_arquivo, fmOpenRead or fmShareDenyWrite);

  try

    FS.Seek(-128, soFromEnd);

    FS.Read(Buffer, 128);

     ID:=copy(Buffer,1,3);

     Titulo:=copy(Buffer,4,30);

     Artista:=copy(Buffer,34,30);

     Album:=copy(Buffer,64,30);

     Ano:=copy(Buffer,94,4);

     Comentario:=copy(Buffer,98,30);

     Genero:=ord(Buffer[128]);

  finally

    FS.Free;

  end;

end;