Delphi-PRAXiS
Seite 1 von 3  1 23   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen (https://www.delphipraxis.net/54063-id3v1-tag-id3v2-tag-und-mpeg-header-einer-mp3-auslesen.html)

Alex_ITA01 27. Sep 2005 11:10


ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Liste der Anhänge anzeigen (Anzahl: 1)
Hallo erstmal,
ich schon wieder :-)
Naja, wie gestern versprochen, hier der Source für mein Programm ID3Tag-Verwalter.
Nur mal kurz zu meinem Beweggründen, warum ich den Source hier rein stelle. Ihr (DP) habt mir schon ziemlich oft geholfen und ich hoffe natürlich das ihr das weiter so macht :-)
Daher will ich anderen genauso die Chance geben etwas zu lernen bzw. zu verbessern. Schließlich muss man sich in einem solchen Forum helfen und helfen lassen (Nobody is perfect...)

Ich habe den Source ein wenig abgespeckt, weil dort meine Kompos und ein ziemlich großer Standard von mir drinne war aber in dem nachfolgenden Beispiel ist alles gezeigt.
Lesen und Schreiben des ID3v1 + ID3v2-Tag's und lesen des MPEG-Headers.
Ihr werdet sicher damit etwas anfangen können (nachdem so viele gestern schon nach den Source gefragt haben :-) )

Wenn ihr Verbesserungen oder Änderungen am Source vornehmt, könnt ihr mir ja Bescheid sagen.Vielleicht hat es ja auch Nutzen für mich.

MFG
Alex

ID3v1.pas
Delphi-Quellcode:
unit ID3v1;

interface

uses
  Classes, SysUtils;

const
  MAX_MUSIC_GENRES = 148;
  DEFAULT_GENRE = 255;

  TAG_VERSION_1_0 = 1;
  TAG_VERSION_1_1 = 2;

var
  MusicGenre: array [0..MAX_MUSIC_GENRES - 1] of string;

type
  String04 = String[4];
  String30 = String[30];

  TID3v1 = 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;
      procedure ResetData;
      function ReadFromFile (const FileName: string): Boolean;
      function RemoveFromFile(const FileName: string): Boolean;
      function SaveToFile   (const FileName: string): Boolean;
      property Exists   : Boolean read FExists;
      property VersionID : Byte    read FVersionID;
      property Title    : String30 read FTitle  write FSetTitle;
      property Artist   : String30 read FArtist write FSetArtist;
      property Album    : String30 read FAlbum  write FSetAlbum;
      property Year     : String04 read FYear   write FSetYear;
      property Comment  : String30 read FComment write FSetComment;
      property Track    : Byte    read FTrack  write FSetTrack;
      property GenreID  : Byte    read FGenreID write FSetGenreID;
      property Genre    : String  read FGetGenre;
  end;
{ --------------------------------------------------------------------------- }
implementation
{ --------------------------------------------------------------------------- }
type
  TagRecord = record
    Header : array [1..3] of Char;
    Title  : array [1..30] of Char;
    Artist : array [1..30] of Char;
    Album  : array [1..30] of Char;
    Year   : array [1..4] of Char;
    Comment : array [1..30] of Char;
    Genre  : Byte;
  end;
{ --------------------------------------------------------------------------- }
function ReadTag(const FileName: string; var TagData: TagRecord): Boolean;
var
  SourceFile : File;
begin
  try
    Result := true;
    AssignFile(SourceFile, FileName);
    FileMode := 0;
    Reset(SourceFile, 1);
    Seek(SourceFile, FileSize(SourceFile) - 128);
    BlockRead(SourceFile, TagData, 128);
    CloseFile(SourceFile);
  except
    Result := false;
  end;
end;
{ --------------------------------------------------------------------------- }
function RemoveTag(const FileName: string): Boolean;
var
  SourceFile : File;
begin
  {$IFDEF MSWINDOWS}
  try
    Result := true;
    FileSetAttr(FileName, 0);
    AssignFile(SourceFile, FileName);
    FileMode := 2;
    Reset(SourceFile, 1);
    Seek(SourceFile, FileSize(SourceFile) - 128);
    Truncate(SourceFile);
    CloseFile(SourceFile);
  except
    Result := false;
  end;
  {$ENDIF}
end;
{ --------------------------------------------------------------------------- }
function SaveTag(const FileName: String; TagData: TagRecord): Boolean;
var
  SourceFile : File;
begin
  try
    Result := true;
    FileSetAttr(FileName, 0);
    AssignFile(SourceFile, FileName);
    FileMode := 2;
    Reset(SourceFile, 1);
    Seek(SourceFile, FileSize(SourceFile));
    BlockWrite(SourceFile, TagData, SizeOf(TagData));
    CloseFile(SourceFile);
  except
    Result := false;
  end;
end;
{ --------------------------------------------------------------------------- }
function GetTagVersion(const TagData: TagRecord): Byte;
begin
  Result := TAG_VERSION_1_0;
  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;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetTitle(const NewTitle: String30);
begin
  FTitle := TrimRight(NewTitle);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetArtist(const NewArtist: String30);
begin
  FArtist := TrimRight(NewArtist);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetAlbum(const NewAlbum: String30);
begin
  FAlbum := TrimRight(NewAlbum);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetYear(const NewYear: String04);
begin
  FYear := TrimRight(NewYear);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetComment(const NewComment: String30);
begin
  FComment := TrimRight(NewComment);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetTrack(const NewTrack: Byte);
begin
  FTrack := NewTrack;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.FSetGenreID(const NewGenreID: Byte);
begin
  FGenreID := NewGenreID;
end;
{ --------------------------------------------------------------------------- }
function TID3v1.FGetGenre : String;
begin
  Result := '';
  if FGenreID in [0..MAX_MUSIC_GENRES - 1] then Result := MusicGenre[FGenreID];
end;
{ --------------------------------------------------------------------------- }
constructor TID3v1.Create;
begin
  inherited;
  ResetData;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v1.ResetData;
begin
  FExists   := false;
  FVersionID := TAG_VERSION_1_0;
  FTitle    := '';
  FArtist   := '';
  FAlbum    := '';
  FYear     := '';
  FComment  := '';
  FTrack    := 0;
  FGenreID  := DEFAULT_GENRE;
end;
{ --------------------------------------------------------------------------- }
function TID3v1.ReadFromFile(const FileName: String): Boolean;
var
  TagData : TagRecord;
begin
  ResetData;
  Result := ReadTag(FileName, TagData);
  if (Result) and (TagData.Header = 'TAG') then
  begin
    FExists := true;
    FVersionID := GetTagVersion(TagData);
    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 TID3v1.RemoveFromFile(const FileName: String): Boolean;
var
  TagData : TagRecord;
begin
  Result := ReadTag(FileName, TagData);
  if (Result) and (TagData.Header = 'TAG') then Result := RemoveTag(FileName);
end;
{ --------------------------------------------------------------------------- }
function TID3v1.SaveToFile(const FileName: String): Boolean;
var
  TagData : TagRecord;
begin
  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;
  Result := (RemoveFromFile(FileName)) and (SaveTag(FileName, TagData));
end;
{ --------------------------------------------------------------------------- }
initialization
begin
  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';
  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.
ID3v2.pas
Delphi-Quellcode:
unit ID3v2;

interface

uses
  Classes, SysUtils;

const
  TAG_VERSION_2_2 = 2;
  TAG_VERSION_2_3 = 3;
  TAG_VERSION_2_4 = 4;

type
  TID3v2 = class(TObject)
  private
    { Private declarations }
    FExists: Boolean;
    FVersionID: Byte;
    FSize: Integer;
    FTitle: string;
    FArtist: string;
    FAlbum: string;
    FTrack: Word;
    FTrackString: string;
    FYear: string;
    FGenre: string;
    FComment: string;
    FComposer: string;
    FEncoder: string;
    FCopyright: string;
    FLanguage: string;
    FLink: string;
    procedure FSetTitle(const NewTitle: string);
    procedure FSetArtist(const NewArtist: string);
    procedure FSetAlbum(const NewAlbum: string);
    procedure FSetTrack(const NewTrack: Word);
    procedure FSetYear(const NewYear: string);
    procedure FSetGenre(const NewGenre: string);
    procedure FSetComment(const NewComment: string);
    procedure FSetComposer(const NewComposer: string);
    procedure FSetEncoder(const NewEncoder: string);
    procedure FSetCopyright(const NewCopyright: string);
    procedure FSetLanguage(const NewLanguage: string);
    procedure FSetLink(const NewLink: string);
  public
    { Public declarations }
    constructor Create;
    procedure ResetData;
    function ReadFromFile (const FileName: string): Boolean;
    function SaveToFile   (const FileName: string): Boolean;
    function RemoveFromFile(const FileName: string): Boolean;
    property Exists     : Boolean read FExists;
    property VersionID  : Byte   read FVersionID;
    property Size       : Integer read FSize;
    property Title      : String read FTitle    write FSetTitle;
    property Artist     : String read FArtist   write FSetArtist;
    property Album      : String read FAlbum    write FSetAlbum;
    property Track      : Word   read FTrack    write FSetTrack;
    property TrackString : String read FTrackString;
    property Year       : String read FYear     write FSetYear;
    property Genre      : String read FGenre    write FSetGenre;
    property Comment    : String read FComment  write FSetComment;
    property Composer   : String read FComposer write FSetComposer;
    property Encoder    : String read FEncoder  write FSetEncoder;
    property Copyright  : String read FCopyright write FSetCopyright;
    property Language   : String read FLanguage write FSetLanguage;
    property Link       : String read FLink     write FSetLink;
  end;
{ --------------------------------------------------------------------------- }
implementation
{ --------------------------------------------------------------------------- }
const
  ID3V2_ID = 'ID3';
  ID3V2_FRAME_COUNT = 16;
  ID3V2_FRAME_NEW: array [1..ID3V2_FRAME_COUNT] of string =
    ('TIT2', 'TPE1', 'TALB', 'TRCK', 'TYER', 'TCON', 'COMM', 'TCOM', 'TENC',
     'TCOP', 'TLAN', 'WXXX', 'TDRC', 'TOPE', 'TIT1', 'TOAL');
  ID3V2_FRAME_OLD: array [1..ID3V2_FRAME_COUNT] of string =
    ('TT2', 'TP1', 'TAL', 'TRK', 'TYE', 'TCO', 'COM', 'TCM', 'TEN',
     'TCR', 'TLA', 'WXX', 'TOR', 'TOA', 'TT1', 'TOT');
  ID3V2_MAX_SIZE = 4096;
  UNICODE_ID = #1;
{ --------------------------------------------------------------------------- }
type
  FrameHeaderNew = record
    ID   : array [1..4] of Char;
    Size : Integer;
    Flags : Word;
  end;

  FrameHeaderOld = record
    ID  : array [1..3] of Char;
    Size : array [1..3] of Byte;
  end;

  TagInfo = record
    ID         : array [1..3] of Char;
    Version    : Byte;
    Revision   : Byte;
    Flags      : Byte;
    Size       : array [1..4] of Byte;
    FileSize   : Integer;
    Frame      : array [1..ID3V2_FRAME_COUNT] of string;
    NeedRewrite : Boolean;
    PaddingSize : Integer;
  end;
{ --------------------------------------------------------------------------- }
function ReadHeader(const FileName: string; var Tag: TagInfo): Boolean;
var
  SourceFile: file;
  Transferred: Integer;
begin
  try
    Result := true;
    AssignFile(SourceFile, FileName);
    FileMode := 0;
    Reset(SourceFile, 1);
    BlockRead(SourceFile, Tag, 10, Transferred);
    Tag.FileSize := FileSize(SourceFile);
    CloseFile(SourceFile);
    if Transferred < 10 then Result := false;
  except
    Result := false;
  end;
end;
{ --------------------------------------------------------------------------- }
function GetTagSize(const Tag: TagInfo): Integer;
begin
  Result :=
    Tag.Size[1] * $200000 +
    Tag.Size[2] * $4000 +
    Tag.Size[3] * $80 +
    Tag.Size[4] + 10;
  if Tag.Flags and $10 = $10 then Inc(Result, 10);
  if Result > Tag.FileSize then Result := 0;
end;
{ --------------------------------------------------------------------------- }
procedure SetTagItem(const ID, Data: string; var Tag: TagInfo);
var
  Iterator: Byte;
  FrameID: string;
begin
  for Iterator := 1 to ID3V2_FRAME_COUNT do
  begin
    if Tag.Version > TAG_VERSION_2_2 then
      FrameID := ID3V2_FRAME_NEW[Iterator]
    else
      FrameID := ID3V2_FRAME_OLD[Iterator];
    if (FrameID = ID) and (Data[1] <= UNICODE_ID) then
      Tag.Frame[Iterator] := Data;
  end;
end;
{ --------------------------------------------------------------------------- }
function Swap32(const Figure: Integer): Integer;
var
  ByteArray: array [1..4] of Byte absolute Figure;
begin
  Result :=
    ByteArray[1] * $1000000 +
    ByteArray[2] * $10000 +
    ByteArray[3] * $100 +
    ByteArray[4];
end;
{ --------------------------------------------------------------------------- }
procedure ReadFramesNew(const FileName: string; var Tag: TagInfo);
var
  SourceFile: file;
  Frame: FrameHeaderNew;
  Data: array [1..500] of Char;
  DataPosition, DataSize: Integer;
begin
  try
    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);
      BlockRead(SourceFile, Frame, 10);
      if not (Frame.ID[1] in ['A'..'Z']) then break;
      DataPosition := FilePos(SourceFile);
      if Swap32(Frame.Size) > SizeOf(Data) then DataSize := SizeOf(Data)
      else DataSize := Swap32(Frame.Size);
      BlockRead(SourceFile, Data, DataSize);
      if Frame.Flags and $8000 <> $8000 then SetTagItem(Frame.ID, Data, Tag);
      Seek(SourceFile, DataPosition + Swap32(Frame.Size));
    end;
    CloseFile(SourceFile);
  except
  end;
end;
{ --------------------------------------------------------------------------- }
procedure ReadFramesOld(const FileName: string; var Tag: TagInfo);
var
  SourceFile: file;
  Frame: FrameHeaderOld;
  Data: array [1..500] of Char;
  DataPosition, FrameSize, DataSize: Integer;
begin
  try
    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);
      BlockRead(SourceFile, Frame, 6);
      if not (Frame.ID[1] in ['A'..'Z']) then break;
      DataPosition := FilePos(SourceFile);
      FrameSize := Frame.Size[1] shl 16 + Frame.Size[2] shl 8 + Frame.Size[3];
      if FrameSize > SizeOf(Data) then DataSize := SizeOf(Data)
      else DataSize := FrameSize;
      BlockRead(SourceFile, Data, DataSize);
      SetTagItem(Frame.ID, Data, Tag);
      Seek(SourceFile, DataPosition + FrameSize);
    end;
    CloseFile(SourceFile);
  except
  end;
end;
{ --------------------------------------------------------------------------- }
function GetANSI(const Source: string): string;
var
  Index: Integer;
  FirstByte, SecondByte: Byte;
  UnicodeChar: WideChar;
begin
  if (Length(Source) > 0) and (Source[1] = UNICODE_ID) then
  begin
    Result := '';
    for Index := 1 to ((Length(Source) - 1) div 2) do
    begin
      FirstByte := Ord(Source[Index * 2]);
      SecondByte := Ord(Source[Index * 2 + 1]);
      UnicodeChar := WideChar(FirstByte or (SecondByte shl 8));
      if UnicodeChar = #0 then break;
      if FirstByte < $FF then Result := Result + UnicodeChar;
    end;
    Result := Trim(Result);
  end
  else
    Result := Trim(Source);
end;
{ --------------------------------------------------------------------------- }
function GetContent(const Content1, Content2: string): string;
begin
  Result := GetANSI(Content1);
  if Result = '' then Result := GetANSI(Content2);
end;
{ --------------------------------------------------------------------------- }
function ExtractTrack(const TrackString: string): Word;
var
  Track: string;
  Index, Value, Code: Integer;
begin
  Track := GetANSI(TrackString);
  Index := Pos('/', Track);
  if Index = 0 then Val(Track, Value, Code)
  else Val(Copy(Track, 1, Index - 1), Value, Code);
  if Code = 0 then Result := Value
  else Result := 0;
end;
{ --------------------------------------------------------------------------- }
function ExtractYear(const YearString, DateString: string): string;
begin
  Result := GetANSI(YearString);
  if Result = '' then Result := Copy(GetANSI(DateString), 1, 4);
end;
{ --------------------------------------------------------------------------- }
function ExtractGenre(const GenreString: string): string;
begin
  Result := GetANSI(GenreString);
  if Pos(')', Result) > 0 then Delete(Result, 1, LastDelimiter(')', Result));
end;
{ --------------------------------------------------------------------------- }
function ExtractText(const SourceString: string; LanguageID: Boolean): string;
var
  Source, Separator: string;
  EncodingID: Char;
begin
  Source := SourceString;
  Result := '';
  if Length(Source) > 0 then
  begin
    EncodingID := Source[1];
    if EncodingID = UNICODE_ID then Separator := #0#0
    else Separator := #0;
    if LanguageID then Delete(Source, 1, 4)
    else Delete(Source, 1, 1);
    Delete(Source, 1, Pos(Separator, Source) + Length(Separator) - 1);
    Result := GetANSI(EncodingID + Source);
  end;
end;
{ --------------------------------------------------------------------------- }
procedure BuildHeader(var Tag: TagInfo);
var
  Iterator, TagSize: Integer;
begin
  TagSize := 10;
  for Iterator := 1 to ID3V2_FRAME_COUNT do
    if Tag.Frame[Iterator] <> '' then
      Inc(TagSize, Length(Tag.Frame[Iterator]) + 11);
  Tag.NeedRewrite :=
    (Tag.ID <> ID3V2_ID) or
    (GetTagSize(Tag) < TagSize) or
    (GetTagSize(Tag) > ID3V2_MAX_SIZE);
  if Tag.NeedRewrite then Tag.PaddingSize := ID3V2_MAX_SIZE - TagSize
  else Tag.PaddingSize := GetTagSize(Tag) - TagSize;
  if Tag.PaddingSize > 0 then Inc(TagSize, Tag.PaddingSize);
  Tag.ID := ID3V2_ID;
  Tag.Version := TAG_VERSION_2_3;
  Tag.Revision := 0;
  Tag.Flags := 0;
  for Iterator := 1 to 4 do
    Tag.Size[Iterator] := ((TagSize - 10) shr ((4 - Iterator) * 7)) and $7F;
end;
{ --------------------------------------------------------------------------- }
function ReplaceTag(const FileName: string; TagData: TStream): Boolean;
var
  Destination: TFileStream;
begin
  Result := false;
  if (not FileExists(FileName)) or (FileSetAttr(FileName, 0) <> 0) then exit;
  try
    TagData.Position := 0;
    Destination := TFileStream.Create(FileName, fmOpenReadWrite);
    Destination.CopyFrom(TagData, TagData.Size);
    Destination.Free;
    Result := true;
  except
  end;
end;
{ --------------------------------------------------------------------------- }
function RebuildFile(const FileName: string; TagData: TStream): Boolean;
var
  Tag: TagInfo;
  Source, Destination: TFileStream;
  BufferName: string;
begin
  Result := false;
  if (not FileExists(FileName)) or (FileSetAttr(FileName, 0) <> 0) then exit;
  if not ReadHeader(FileName, Tag) then exit;
  if (TagData = nil) and (Tag.ID <> ID3V2_ID) then exit;
  try
    BufferName := FileName + '~';
    Source := TFileStream.Create(FileName, fmOpenRead);
    Destination := TFileStream.Create(BufferName, fmCreate);
    if Tag.ID = ID3V2_ID then Source.Seek(GetTagSize(Tag), soFromBeginning);
    if TagData <> nil then Destination.CopyFrom(TagData, 0);
    Destination.CopyFrom(Source, Source.Size - Source.Position);
    Source.Free;
    Destination.Free;
    if (DeleteFile(FileName)) and (RenameFile(BufferName, FileName)) then
      Result := true
    else
      raise Exception.Create('');
  except
    if FileExists(BufferName) then DeleteFile(BufferName);
  end;
end;
{ --------------------------------------------------------------------------- }
function SaveTag(const FileName: string; Tag: TagInfo): Boolean;
var
  TagData: TStringStream;
  Iterator, FrameSize: Integer;
  Padding: array [1..ID3V2_MAX_SIZE] of Byte;
begin
  TagData := TStringStream.Create('');
  BuildHeader(Tag);
  TagData.Write(Tag, 10);
  for Iterator := 1 to ID3V2_FRAME_COUNT do
    if Tag.Frame[Iterator] <> '' then
    begin
      TagData.WriteString(ID3V2_FRAME_NEW[Iterator]);
      FrameSize := Swap32(Length(Tag.Frame[Iterator]) + 1);
      TagData.Write(FrameSize, SizeOf(FrameSize));
      TagData.WriteString(#0#0#0 + Tag.Frame[Iterator]);
    end;
  FillChar(Padding, SizeOf(Padding), 0);
  if Tag.PaddingSize > 0 then TagData.Write(Padding, Tag.PaddingSize);
  if Tag.NeedRewrite then Result := RebuildFile(FileName, TagData)
  else Result := ReplaceTag(FileName, TagData);
  TagData.Free;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetTitle(const NewTitle: string);
begin
  FTitle := Trim(NewTitle);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetArtist(const NewArtist: string);
begin
  FArtist := Trim(NewArtist);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetAlbum(const NewAlbum: string);
begin
  FAlbum := Trim(NewAlbum);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetTrack(const NewTrack: Word);
begin
  FTrack := NewTrack;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetYear(const NewYear: string);
begin
  FYear := Trim(NewYear);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetGenre(const NewGenre: string);
begin
  FGenre := Trim(NewGenre);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetComment(const NewComment: string);
begin
  FComment := Trim(NewComment);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetComposer(const NewComposer: string);
begin
  FComposer := Trim(NewComposer);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetEncoder(const NewEncoder: string);
begin
  FEncoder := Trim(NewEncoder);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetCopyright(const NewCopyright: string);
begin
  FCopyright := Trim(NewCopyright);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetLanguage(const NewLanguage: string);
begin
  FLanguage := Trim(NewLanguage);
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.FSetLink(const NewLink: string);
begin
  FLink := Trim(NewLink);
end;
{ --------------------------------------------------------------------------- }
constructor TID3v2.Create;
begin
  inherited;
  ResetData;
end;
{ --------------------------------------------------------------------------- }
procedure TID3v2.ResetData;
begin
  FExists     := false;
  FVersionID  := 0;
  FSize       := 0;
  FTitle      := '';
  FArtist     := '';
  FAlbum      := '';
  FTrack      := 0;
  FTrackString := '';
  FYear       := '';
  FGenre      := '';
  FComment    := '';
  FComposer   := '';
  FEncoder    := '';
  FCopyright  := '';
  FLanguage   := '';
  FLink       := '';
end;
{ --------------------------------------------------------------------------- }
function TID3v2.ReadFromFile(const FileName: string): Boolean;
var
  Tag: TagInfo;
begin
  ResetData;
  Result := ReadHeader(FileName, Tag);
  if (Result) and (Tag.ID = ID3V2_ID) then
  begin
    FExists := true;
    FVersionID := Tag.Version;
    FSize := GetTagSize(Tag);
    if (FVersionID in [TAG_VERSION_2_2..TAG_VERSION_2_4]) and (FSize > 0) then
    begin
      if FVersionID > TAG_VERSION_2_2 then ReadFramesNew(FileName, Tag)
      else ReadFramesOld(FileName, Tag);
      FTitle := GetContent(Tag.Frame[1], Tag.Frame[15]);
      FArtist := GetContent(Tag.Frame[2], Tag.Frame[14]);
      FAlbum := GetContent(Tag.Frame[3], Tag.Frame[16]);
      FTrack := ExtractTrack(Tag.Frame[4]);
      FTrackString := GetANSI(Tag.Frame[4]);
      FYear := ExtractYear(Tag.Frame[5], Tag.Frame[13]);
      FGenre := ExtractGenre(Tag.Frame[6]);
      FComment := ExtractText(Tag.Frame[7], true);
      FComposer := GetANSI(Tag.Frame[8]);
      FEncoder := GetANSI(Tag.Frame[9]);
      FCopyright := GetANSI(Tag.Frame[10]);
      FLanguage := GetANSI(Tag.Frame[11]);
      FLink := ExtractText(Tag.Frame[12], false);
    end;
  end;
end;
{ --------------------------------------------------------------------------- }
function TID3v2.SaveToFile(const FileName: string): Boolean;
var
  Tag: TagInfo;
begin
  FillChar(Tag, SizeOf(Tag), 0);
  ReadHeader(FileName, Tag);
  Tag.Frame[1] := FTitle;
  Tag.Frame[2] := FArtist;
  Tag.Frame[3] := FAlbum;
  if FTrack > 0 then Tag.Frame[4] := IntToStr(FTrack);
  Tag.Frame[5] := FYear;
  Tag.Frame[6] := FGenre;
  if FComment <> '' then Tag.Frame[7] := 'eng' + #0 + FComment;
  Tag.Frame[8] := FComposer;
  Tag.Frame[9] := FEncoder;
  Tag.Frame[10] := FCopyright;
  Tag.Frame[11] := FLanguage;
  if FLink <> '' then Tag.Frame[12] := #0 + FLink;
  Result := SaveTag(FileName, Tag);
end;
{ --------------------------------------------------------------------------- }
function TID3v2.RemoveFromFile(const FileName: string): Boolean;
begin
  Result := RebuildFile(FileName, nil);
end;
{ --------------------------------------------------------------------------- }
end.
MPEG-Header.pas
Delphi-Quellcode:
unit MPEGHeader;

interface
{ ---------------------------------------------------------------------------- }
type
  TMPEGInfo = record
    Position: integer;
    Version: integer;
    Layer: integer;
    Protection: boolean;
    Bitrate: integer;
    Samplerate: integer;
    ChannelMode: byte;
    Extension: byte;
    Copyright: boolean;
    Original: boolean;
    Emphasis: byte;
    Frames: longint;
    Dauer: longint;
    VBR: boolean;
  end;
{ ---------------------------------------------------------------------------- }
const
  MPEG_BIT_RATES: array[1..3] of array[1..3] of array[0..15] of word = ((
      { Version 1, Layer I }
      (0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0),
      { Version 1, Layer II }
      (0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0),
      { Version 1, Layer III }
      (0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0)),
      { Version 2, Layer I }
      ((0,32,48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0),
      { Version 2, Layer II }
      (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0),
      { Version 2, Layer III }
      (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0)),
      { Version 2.5, Layer I }
      ((0,32,48, 56, 64, 80, 96,112,128,144,160,176,192,224,256,0),
      { Version 2.5, Layer II }
      (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0),
      { Version 2.5, Layer III }
      (0, 8,16,24, 32, 40, 48, 56, 64, 80, 96, 112,128,144,160,0)
    ));

  MPEG_SAMPLE_RATES: array[1..3] of array [0..3] of word = (
      (44100, 48000, 32000, 0),
      (22050, 24000, 16000, 0),
      (11025, 12000, 8000, 0)
    );
{ ---------------------------------------------------------------------------- }
type
  TMPEGHeader = class(TObject)
    private
      { Private declarations }
      F                         : File;
      id3v1_tag                 : array[1..128] of char;
      mp3_header                : array[1..4] of char;
      buffer                    : array of char;
      fsize                     : longint;
      id3v1_size                : integer;
      xing_header_size          : integer;
      id3_size                  : longint;

      bitrateindex, versionindex : byte;
      valid                     : boolean;
      position                  : integer;
      padding,samplerateindex   : byte;
      framelength               : longint;
      Xing_Offset               : integer;
      Xing_Flags                : byte;
    public
      { Public declarations }
      MPEGInfo : TMpeginfo;
      constructor Create;
      procedure MPEG_Header(FileName : String);  { liest alle Informationen einer MP3 aus }
  end;
{ ---------------------------------------------------------------------------- }
implementation
{ ---------------------------------------------------------------------------- }
{ TMPEGHeader }
{ ---------------------------------------------------------------------------- }
constructor TMPEGHeader.Create;
begin
  inherited Create;
end;
{ ---------------------------------------------------------------------------- }
procedure TMPEGHeader.MPEG_Header(FileName: String);
begin
  xing_header_size := 0;
  id3_size        := 0;
  id3v1_size      := 0;
  AssignFile(F, filename);
  FileMode := 0;
  Reset(F,1);
  fsize := filesize(f);

  if fsize>=6000 then setlength(buffer,6000) else
      setlength(buffer,fsize);

  blockread(f,buffer[0],length(buffer));
  Seek(F,FileSize(F)-128);
  BlockRead(F, id3v1_tag, 128);
  CloseFile(F);
  //*******************Start des MPEG-Headers***********************
  valid := false;
  mpeginfo.position := - 1;
  position := id3_size - 1;
  while NOT ((valid) or (position>length(buffer)+4)) do
  begin
    inc(position);
    if (ord(buffer[position]) = $FF) AND (ord(buffer[position + 1]) >= $E0)
    then
    begin
      valid := true;
      Versionindex := ((ord(buffer[position+1]) shr 3) and 3);
      case versionindex of
        0: mpeginfo.version := 3;
        1: mpeginfo.version := 0;
        2: mpeginfo.version := 2;
        3: mpeginfo.version := 1;
      end;
      mpeginfo.Layer := 4 - ((ord(buffer[position + 1]) shr 1) and 3);
      mpeginfo.protection := ((ord(buffer[position + 1]) AND 1) =0);

      bitrateindex := ((ord(buffer[position + 2]) shr 4) AND $F);
      mpeginfo.bitrate := MPEG_BIT_RATES[mpeginfo.version][mpeginfo.layer][bitrateindex];
      if bitrateindex = $F then
        valid := false;
      samplerateindex := ((ord(buffer[position + 2]) shr 2) AND 3);
      mpeginfo.samplerate := MPEG_SAMPLE_RATES[mpeginfo.version][samplerateindex];
      padding := ((ord(buffer[position + 2]) shr 1) AND 1);

      mpeginfo.channelmode :=((ord(buffer[position + 3]) shr 6) AND 3);
      mpeginfo.extension  :=((ord(buffer[position + 3]) shr 4) AND 3);
      mpeginfo.copyright  :=((ord(buffer[position + 3]) shr 3) AND 1) = 1;
      mpeginfo.original   :=((ord(buffer[position + 3]) shr 2) AND 1) = 1;
      mpeginfo.emphasis   :=(ord(buffer[position + 3]) AND 3);

      if mpeginfo.layer = 2 then
      begin
        if (mpeginfo.bitrate = 32) AND (mpeginfo.channelmode <> 3) then valid := false;
        if (mpeginfo.bitrate = 48) AND (mpeginfo.channelmode <> 3) then valid := false;
        if (mpeginfo.bitrate = 56) AND (mpeginfo.channelmode <> 3) then valid := false;
        if (mpeginfo.bitrate = 80) AND (mpeginfo.channelmode <> 3) then valid := false;
        if (mpeginfo.bitrate = 224) AND (mpeginfo.channelmode = 3) then valid := false;
        if (mpeginfo.bitrate = 256) AND (mpeginfo.channelmode = 3) then valid := false;
        if (mpeginfo.bitrate = 320) AND (mpeginfo.channelmode = 3) then valid := false;
        if (mpeginfo.bitrate = 384) AND (mpeginfo.channelmode = 3) then valid := false;
      end;
//***************damit ist der MPEG Header komplett eingelesen***********************************

//**************Einlesen des XING-Headers***************************
      if mpeginfo.version = 1 then
        if mpeginfo.channelmode <> 3 then
          xing_offset := 32 + 4
        else
          xing_offset := 17 + 4
      else
        if mpeginfo.channelmode <> 3 then
          xing_offset := 17 + 4
        else
          xing_offset := 9 + 4;
      if (buffer[position + xing_offset] = 'X')
      AND (buffer[position + xing_offset + 1] = 'i')
      AND (buffer[position + xing_offset + 2] = 'n')
      AND (buffer[position + xing_offset + 3] = 'g') then
      begin
        Xing_flags := ord(buffer[position + xing_offset + 7]);
        if (Xing_flags AND 1) = 1 then
        begin
          mpeginfo.frames := 16777216 * ord(buffer[position + xing_offset + 8])
              + 65536 * ord(buffer[position + xing_offset + 9])
              + 256 * ord(buffer[position + xing_offset + 10])
              + ord(buffer[position + xing_offset + 11]);
        end;
        if mpeginfo.layer = 1 then
          xing_header_size := trunc(((12 * MPEG_BIT_RATES[mpeginfo.version][mpeginfo.layer][bitrateindex] * 1000 / mpeginfo.samplerate) + padding) * 4)
        else
          xing_header_size := trunc(144 * (MPEG_BIT_RATES[mpeginfo.version][mpeginfo.layer][bitrateindex]* 1000 / mpeginfo.samplerate) + padding);
        framelength := xing_header_size;
        mpeginfo.bitrate := trunc((mpeginfo.samplerate / 1000 * (fsize - id3_size - id3v1_size - xing_header_size)) / (mpeginfo.frames * 144));
        mpeginfo.vbr := true;
      end
      else
      begin
        if mpeginfo.layer = 1 then
          framelength := trunc(((12 * MPEG_BIT_RATES[mpeginfo.version][mpeginfo.layer][bitrateindex] * 1000 / mpeginfo.samplerate) + padding) * 4)
        else
          framelength := trunc(144 * (MPEG_BIT_RATES[mpeginfo.version][mpeginfo.layer][bitrateindex] * 1000 / mpeginfo.samplerate) + padding);
        mpeginfo.frames := trunc((fsize - id3_size - id3v1_size - xing_header_size) / framelength);
        mpeginfo.vbr := false;
        xing_header_size := 0;
      end;
//**************XING-Header Ende***************************

      if (position + framelength > length(buffer) - 2) AND (position + framelength + 4 < fsize) then
      begin
        Reset(F,1);
        Seek(F,position + framelength);
        blockread(f,mp3_header,4);
        CloseFile(F);
      end
      else
      begin
        try
          mp3_header[1] := buffer[position + framelength];
          mp3_header[2] := buffer[position + framelength + 1];
        except
          mp3_header[1] := '0';
          mp3_header[2] := '0';
        end;
      end;
      if (ord(mp3_header[1]) <> $FF) or (ord(mp3_header[2]) < $E0) then valid := false;

      if valid then begin
          mpeginfo.dauer := ((fsize - id3_size - id3v1_size - xing_header_size) * 8) div ((mpeginfo.bitrate) * 1000);
          mpeginfo.position := position;
      end;
    end;
  end;
end;
{ ---------------------------------------------------------------------------- }
end.
Beispielprogramm zum laden und speichern füge ich an.
Grüße an alle.

MFG Alex

Matze 27. Sep 2005 11:16

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Moin!

Könntest du uns auch sagen, woher du diese Units hast?

leddl 27. Sep 2005 11:20

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Warum hast du aus dem Array MusicGenre eine Variable gemacht? Hätte da ne Konstante nich besser gepasst?
Außerdem wäre es so viel platzsparender gegangen:
Delphi-Quellcode:
const MusicGenre : Array[1..MAX_MUSIC_GENRES - 1] =
          ('Blues','Classic Rock','Country','Dance',...
                          ...
                          ...
          'Trash Metal','Anime','JPop','Synthpop');
Außerdem wäre es evtl komfortabel, dieses Array auch im ID3v2 zur Verfügung zu stellen, so daß man da auch darauf zugreifen kann, wenn man es braucht.

Sharky 27. Sep 2005 11:36

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Zitat:

Zitat von Matze
... Könntest du uns auch sagen, woher du diese Units hast?

Und wäre es möglich den Code im Posting auf den Interface-Teil zu beschränken. Mein Scrollrad ist eben schon ganz heiss geworden. ;-)

Alex_ITA01 27. Sep 2005 11:42

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
@Sharky: Sorry tut mir leid um dein Mausrad und dein warmen Finger :-)
Ich wusste nicht, wie ich es am besten mache und habe daher alles gepostet.

@Matze: Ich habe diese Units schon seit bestimmt 1,5Jahren und habe sie zwischendurch immer mal in ein paar Sachen geändert bzw. verfeinert. Ich kann dir ehrlich nicht sagen, wo ich damals das Grundgerüst gefunden habe. Das hat nichts damit zu tun, dass ich keine Namen nennen will sondern das ich es ganz einfach nicht mehr weiß.Sorry

@leddl: Ja hätte ich so machen können aber es ist nunmal so gewachsen :-)
Kannst es gerne ändern... ;-)

MFG Alex

Matze 27. Sep 2005 11:45

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Zitat:

Zitat von Alex_ITA01
@Matze: Ich habe diese Units schon seit bestimmt 1,5Jahren und habe sie zwischendurch immer mal in ein paar Sachen geändert bzw. verfeinert. Ich kann dir ehrlich nicht sagen, wo ich damals das Grundgerüst gefunden habe. Das hat nichts damit zu tun, dass ich keine Namen nennen will sondern das ich es ganz einfach nicht mehr weiß.Sorry

Hier nur ein paar Beispiele:

ID3v1.pas:

- hier im Anhang
- hier ungefähr auf der Mitte der Seite
- oder hier (mit Copyright im Header):

Delphi-Quellcode:
{ *************************************************************************** }
{                                                                             }
{ Audio Tools Library (Freeware)                                             }
{ Class TID3v1 - for manipulating with ID3v1 tags                            }
{                                                                             }
{ Copyright (c) 2001,2002 by Jurgen Faul                                     }
{ E-mail: [email]jfaul@gmx.de[/email]                                                       }
{ [url]http://jfaul.de/atl[/url]                                                        }
{                                                                             }
{ Version 1.0 (25 July 2001)                                                 }
{   - Full support for ID3v1.0 & ID3v1.1 tags (read/write)                   }
{                                                                             }
{ *************************************************************************** }
D3v2.pas:

- Hier im SDC

MPEG-Header.pas:

- hier im DF


Wir müssen das helt wissen, wegen den Copyright-Bestimmungen. :?

Alex_ITA01 27. Sep 2005 12:29

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Ja, ich verstehe das mit den Copyright-Bestimmungen aber ich kann dir sagen, dass die ID3v1 und ID3v2 nicht von den obrigen Seiten sind. Ich will ja damit keinen ärgern oder seinen Namen nicht sagen aber wie gesagt, ich habe diese Units schon ziemlich lange und habe kein Copyright entfernt (falls eins vorhanden war).
Bei der MPEG.pas bin ich mir nicht ganz sicher ob sie aus dem DF ist. Falls es so ist, sage ich einfach mal Gausi aus dem DF danke schön! (Copyright ist aber nicht auf dem Source,oder?)
Aber wie oben schon gesagt, ich weiß es nicht.

MFG Alex

Flocke 27. Sep 2005 12:51

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Also die ID3v1.pas sieht schon sehr ähnlich aus, allerdings scheint die andere Variante (die 2. von Matze) späteren Datums zu sein und einige Verbesserungen/Korrekturen zu haben (Kommentare, Eigenschaft "Changed", Korrekte Versionen von "RemoveTag" und "SaveTag", etc.).

Beide Units haben auf jeden Fall denselben Ursprung, die vielen Gemeinsamkeiten können nicht zufällig sein.

Luckie 27. Sep 2005 12:54

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
Warum eigentlich zwei Klasse für die Tag-Versionen? Wie soll man denn das jetzt anwenden? Erst mit der einen versuchen die Tags auszulesen und wenn das nicht klappt mit der anderen? Warum nicht eine Klasse die die Tag-Version bestimmt und dann entsprechend die Tags ausliest?

Alex_ITA01 27. Sep 2005 12:58

Re: ID3v1-Tag, ID3v2-Tag und MPEG-Header einer MP3 auslesen
 
@Luckie: weil vielleicht nicht jeder alle Tag's braucht und nur z.B. die von ID3v1 haben will...
@Flocke: Ich habe auch nirgendwo gesagt, dass alles selber programmiert ist.Ich weiß nur ehrlich nicht mehr, woher ich sie habe.Aber ich weiß garantiert, dass ich kein Copyright verletzt habe bzw. gelöscht habe.

MFG Alex


Alle Zeitangaben in WEZ +1. Es ist jetzt 23:32 Uhr.
Seite 1 von 3  1 23   

Powered by vBulletin® Copyright ©2000 - 2022, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2021 by Daniel R. Wolf