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:
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;
Die Funktionen zum ändern und löschen werd ich dann morgen machen...
// 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.