![]() |
Re: WAV-Dateien und ID3Tag?
Okay, ich werden das dann mal versuchen umzusetzen, aber eine Frage noch:
Wie meinst du das mit den 1024 Byte einlesen? Wenn ich die 100.000 Byte direkt von dem Stream in einem String lese, kann ich doch dann auch direkt in diesem String mit Pos() nach 'INFO' suchen, oder wird das "zu groß" für einen String? Ein anderes Problem was ich noch überhaupt nicht berücksichtigt habe: Ich gehe einfach davon aus, dass die Datei mit dem INFO Chunk endet und danach nichts mehr kommt. Was aber wenn danach noch ein anderer Chunk kommt, der nicht zu dem INFO-Teil gehört? Wie erkenne ich, ob ein anderer Chunk beginnt? Oder ist das immer so, das der INFO Chunk ganz am Ende der Datei steht (was bei meinen Testdateien immer so war) ? |
Re: WAV-Dateien und ID3Tag?
Zitat:
Zitat:
Gruß |
Re: WAV-Dateien und ID3Tag?
Ja unter
![]() |
Re: WAV-Dateien und ID3Tag?
Zitat:
Entsprechend kannst Du die Wave-Datei auf vorhandene INFO-Chunks prüfen, ungetestet ungefähr so:
Delphi-Quellcode:
So ganz grob sollte das klappen. Natürlich ist auch hier das lesen von 2x4 Zeichen nicht wirklich effizient, nur werden mehr Zeichen nicht betrachtet. Besser wäre es sicherlich trotzdem einen Puffer von 8 Byte zu verwenden und die Daten dann in die Variablen zu kopieren, aber das ist eine andere Sache. Hier greift (hoffentlich) die Compileroptimierung und passt das gleich sinnvoll an.
function hasInfoChunk(const file: TStream): Boolean;
var ChunkId: String; count: Cardinal; begin result := false; setLength(ChunkId, 4); // Prüfen ob Datei größer als Header (12 Byte) und erstes Chunk (mind. 8 Byte) if (file.size >= 20) then begin while (file.Position + 8 < file.Size) and (not result) do begin file.Position := 16; file.Read(ChunkId, 4); file.Read(count, 4); // prüfen ob das gelesene Chunk ein Info-Chunk ist if ChunkId = 'Info' then begin result := true; end else begin file.Position := file.Position + count; end; end; end; end; Jedenfalls kannst Du auf die gleiche Art auch den Offset zu dem entsprechenden Chunk zurückgeben lassen, das wäre eben File.Position - 8 (da Du ja mit ChunkId und Count schon weiter gelaufen bist) und könntest so auch gleich das ganze Chunk entfernen (alles bis dorthin und alles dahinter - count sagt Dir ja wie groß das Chunk ist - abschneiden/rauskopieren, Du weißt schon. |
Re: WAV-Dateien und ID3Tag?
Hmm, gut gut...
Du hast mir wirklich sehr viel geholfen. Werde mich heute Abend vielleicht nochmal näher damit beschäftigen. Danke erstmal! Leider hab ich nicht immer so die Zeit... Wenn es geht, würde ich viel mehr Zeit mit Programmieren und hier im Forum verbringen. |
Re: WAV-Dateien und ID3Tag?
So, hab jetzt erstmal das Lesen des INFO Chunks komplett überarbeitet.
Ich springe jetzt nicht mehr 100000 Bytes vom Dateiende rückwärts, sondern lese sauber ein, wie viel Bytes die anderen Chunks der WAV-Datei groß sind und überspringe sie. Des weiteren berücksichtige ich auch, dass der LIST Chunk nicht nur den INFO Chunk enthalten kann, sondern auch noch andere List Chunks. (der INFO Chunk wird mit einem INFO eingeleitet und ist dann zuende, wenn die Chunk ID nicht mehr mit einem 'I' beginnt, denn alle Chunk IDs des INFO Chunks beginnen mit einem 'I') Außerdem hab ich der Einfachheit halber mal die Funktionen ReadID und ReadSize ausgelagert. ReadID liest die ID (Name) eines Chunks ein (4-Byte String) ReadSize liest die Größe des folgenden Blocks ein (4-Byte Integer, folgt auf die ID)
Delphi-Quellcode:
Die Funktionen zum ändern und löschen werd ich dann morgen machen...
type
String4 = array[0..3] of Char; function ReadINFOListChunk(const FileName: string; var ChunkID, Description: TStrings): Boolean; var Stream: TFileStream; function ReadID: String4; begin if Stream.Read(Result, 4) <> 4 then raise Exception.Create('Invalid WAVE Format'); end; function ReadSize: Cardinal; begin if Stream.Read(Result, 4) <> 4 then raise Exception.Create('Invalid WAVE Format'); end; var EndPos: Cardinal; // gibt die Endposition des LIST Chunks an chunk: String4; // zum Speichern der Chunk ID desc: array[0..255] of Char; // zum Einlesen der Beschreibung begin Result := False; Stream := TFileStream.Create(FileName, fmOpenRead, fmShareDenyWrite); try // allgemeiner Header für WAV-Dateien if (ReadID <> 'RIFF') or (ReadSize <> Stream.Size - 8) or (ReadID <> 'WAVE') then raise Exception.Create('Invalid WAVE Format'); // zum LIST Chunk springen while (Stream.Position < Stream.Size) and (ReadID <> 'LIST') do Stream.Seek(ReadSize, soFromCurrent); if Stream.Position < Stream.Size then // enthält LIST Chunk begin EndPos := ReadSize + Stream.Position; // zum INFO Chunk springen while (Stream.Position < EndPos) and (ReadID <> 'INFO') do Stream.Seek(ReadSize, soFromCurrent); if Stream.Position < EndPos then // enthält INFO Chunk begin Result := True; chunk := ReadID; // INFO Chunks einlesen: ID muss mit 'I' beginnen while chunk[0] = 'I' do begin ChunkID.Append(chunk); // Chunk ID hinzufügen Stream.Read(desc, ReadSize); // Beschreibung auslesen Description.Append(desc); // Beschreibung hinzufügen // nächste Chunk ID einlesen, falls LIST Chunk noch nicht zuende if Stream.Position < EndPos then chunk := ReadID else Break; end; end; end; finally Stream.Free; end; end; // Nachtrag: Ich gehe mal davon aus, dass WAVE-Dateien nicht größer als 4 GB sind (also High(Cardinal)). Das sollte eigentlich auch nicht möglich sein, da nach dem RIFF im Header ein 4-Byte Integer folgt, der die gesamte Dateigröße angibt. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 16:57 Uhr. |
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz