|
Registriert seit: 22. Sep 2003 1.134 Beiträge Delphi 12 Athens |
#1
Hallo erstmal,
ich schon wieder ![]() Naja, wie gestern versprochen, hier der Source für mein Programm ![]() 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:
ID3v2.pas
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.
Delphi-Quellcode:
MPEG-Header.pas
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.
Delphi-Quellcode:
Beispielprogramm zum laden und speichern füge ich an.
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. Grüße an alle. MFG Alex
Let's fetz sprach der Frosch und sprang in den Mixer
![]() |
![]() |
Ansicht |
![]() |
![]() |
![]() |
ForumregelnEs ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.
BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus. Trackbacks are an
Pingbacks are an
Refbacks are aus
|
|
Nützliche Links |
Heutige Beiträge |
Sitemap |
Suchen |
Code-Library |
Wer ist online |
Alle Foren als gelesen markieren |
Gehe zu... |
LinkBack |
![]() |
![]() |