Thema: Delphi WAV-Dateien und ID3Tag?

Einzelnen Beitrag anzeigen

Benutzerbild von Martin K
Martin K

Registriert seit: 20. Okt 2005
919 Beiträge
 
Turbo Delphi für Win32
 
#16

Re: WAV-Dateien und ID3Tag?

  Alt 13. Aug 2007, 23:52
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] = 'Ido
        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.
Mit den Menschen ist es wie mit Computern -
es gibt Nullen und Einsen.
  Mit Zitat antworten Zitat