Einzelnen Beitrag anzeigen

Benutzerbild von negaH
negaH

Registriert seit: 25. Jun 2003
Ort: Thüringen
2.950 Beiträge
 
#8

Re: ID3Tag einer String-Variable zuweisen

  Alt 1. Feb 2004, 13:01
Wenn ich deinen Code richtig vestanden habe, dann sind die ID3 Tag felder alle mit fester Länge codiert ?

Dann müsste die hier funktionieren:

Delphi-Quellcode:
type
  PID3Tag = ^TID3Tag;
  TID3Tag = record
    ID: String;
    Title: String;
    Artist: String;
    Album: String;
    Year: String;
    Comment: String;
    Genre: Byte;
  end;


function ReadID3Tag(const FileName: String): TID3Tag;

  function StrLPas(Value: PChar; Len: Integer): String;
    
    function Min(A,B: Integer): Integer;
    begin
      if A <= B then Result := A
        else Result := B;
    end;

  begin
    SetString(Result, Value, Min(Len, StrLen(Value)));
    Result := Trim(Result);
  end;
  
type
  TID3Struct = packed record
    ID: array[0..2] of Char; // 3
    Title: array[0..29] of Char; // 33
    Artist: array[0..29] of Char; // 63
    Album: array[0..29] of Char; // 93
    Year: array[0..3] of Char; // 97
    Comment: array[0..29] of Char; // 127
    Genre: Byte; // 128
  end;

var
  Tag: TID3Struct;
begin
  with TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone) do
  try
    Position := Size - SizeOf(Tag);
    Read(Tag, SizeOf(Tag));
  finally
    Free;
  end;
  with Tag do
  begin
    Result.ID := StrLPas(ID, SizeOf(ID));
    Result.Title := StrLPas(Title, SizeOf(Title));
    Result.Artist := StrLPas(Artist, SizeOf(Artist));
    Result.Album := StrLPas(Album, SizeOf(Album));
    Result.Year := StrLPas(Year, SizeOf(Year));
    Result.Comment := StrLPas(Comment, SizeOf(Comment));
    Result.Genre := Genre;
  end;
end;
Leider ist der MP3 ID3 Tag so ziemlich die schlechteste Struktur die ein Programmierer sich einfallen lassen kann. Sie benutzt keine Variable Length Felder, keine Null Terminierten Chars oder eben keine PASCAL typischen Längenbasierten Strings. D.h. egal ob man in C/C++ oder PASCAL oder sonstwas programmiert, man muß IMMER eine Konvertierung der gelesenen Daten vorsehen. Dabei ist es zusätzlich noch wichtig Leerzeichen oder eventuelle Nullterminatoren zu berücksichtigen. Der ID3 ist eben eine ziemlich unprofessionelle Sache, dies merkt man auch daran das am ID3 "Standard" so viele Änderungen vorgenommen wurden.

Hier eine Version die eher C Typisch ist:

Delphi-Quellcode:
type
  TID3Tag = record
   // diese Struktur erweitert die Char arrays um ein Zeichen für Nullterminator,
   // somit muß sie Feld für Feld gelesen und geschrieben werden, da ID3 eben diese Terminatoren NICHT speichert.
    ID: array[0..3] of Char;
    Title: array[0..30] of Char;
    Artist: array[0..30] of Char;
    Album: array[0..30] of Char;
    Year: array[0..4] of Char;
    Comment: array[0..30] of Char;
    Genre: Byte;
  end;

function ReadID3Tag(const FileName: String): TID3Tag;
begin
  FillChar(Result, SizeOf(Result), 0);
  with TFileStream.Create(FileName, fmOpenRead or fmShareDenyNone) do
  try
    Position := Size - 128;
    Read(Result.ID, 3);
    Read(Result.Title, 30);
    Read(Result.Artist, 30);
    Read(Result.Album, 30);
    Read(Result.Year, 4);
    Read(Result.Comment, 30);
    Read(Result.Genre, 1);
  finally
    Free;
  end;
end;
Gruß Hagen
  Mit Zitat antworten Zitat