AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Multimedia Delphi WAV-Dateien und ID3Tag?

WAV-Dateien und ID3Tag?

Ein Thema von Martin K · begonnen am 11. Aug 2007 · letzter Beitrag vom 13. Aug 2007
Antwort Antwort
Seite 2 von 2     12
Benutzerbild von Martin K
Martin K

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

Re: WAV-Dateien und ID3Tag?

  Alt 13. Aug 2007, 14:43
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) ?
Mit den Menschen ist es wie mit Computern -
es gibt Nullen und Einsen.
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#12

Re: WAV-Dateien und ID3Tag?

  Alt 13. Aug 2007, 14:59
Zitat von Martin K:
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?
Genau hier liegt das Problem, es ist immer sehr schwer eine pauschale Grenze anzugeben. Das kann schon mit der Größe der jeweiligen Caches und der entsprechenden Strategie Deiner CPU variieren, wo die optimale Größe liegt, vom Algorithmus abhängen und natürlich von der Größe des Perfomance-Unterschieds (in den meisten Fällen sind ein paar zig-ms mehr oder weniger egal, woanders zählt jede ns).

Zitat von Martin K:
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) ?
Das wurde schon angesprochen, Du müsstest Dich hier schlau machen, wie eine WAVE-Datei aufgebaut ist. Hat die z.B. einen Header, der die Größe der Chunks angibt, eine Art TOC oder auch einen Footer, der immer angibt wie groß das vorhergehende Chunk ist? Sowas kannst Du immer der entsprechenden Spezifikation entnehmen. Leichter und sinnvoller ist es aber allemal, dass man hier auf bestehende Komponenten zurückgreift (soweit vorhanden). Da wurde (wenn ich mich recht entsinne) auch schon in diesem Thread auf ein paar hingewiesen, die solltest Du Dir dann einfach mal anschauen.

Gruß
  Mit Zitat antworten Zitat
Benutzerbild von Martin K
Martin K

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

Re: WAV-Dateien und ID3Tag?

  Alt 13. Aug 2007, 15:09
Ja unter dieser URL gibt es eine Unit WAVfile.pas, doch leider weiß ich damit nichts so recht anzufangen. Wenn ich das richtig sehe, kann man hier nur allgemeine Infos zur WAV-Datei auslesen (Bitrate, Anzahl der Kanäle und so), aber wie man damit die Position des INFO Chunk oder ähnliches erhalten soll?!?
Mit den Menschen ist es wie mit Computern -
es gibt Nullen und Einsen.
  Mit Zitat antworten Zitat
Der_Unwissende

Registriert seit: 13. Dez 2003
Ort: Berlin
1.756 Beiträge
 
#14

Re: WAV-Dateien und ID3Tag?

  Alt 13. Aug 2007, 15:41
Zitat von Martin K:
aber wie man damit die Position des INFO Chunk oder ähnliches erhalten soll?!?
Das kannst Du dem Link zum Wiki-Eintrag entnehmen. Eine Wave-Datei hat einen recht einfachen Aufbau, Du hast einen Header "RIFF"<Größe der Datei>"WAVE", dem folgen dann die Chunks in der Form <ChunkID><Größe><Daten>. ChunkID ist dabei genau wie die Größe immer exakt 4 Byte groß. Während Du die ID also einfach in einen String der Länge 4 einlesen kannst, kannst Du die Größe in ein Cardinal einlesen.
Entsprechend kannst Du die Wave-Datei auf vorhandene INFO-Chunks prüfen, ungetestet ungefähr so:

Delphi-Quellcode:
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 = 'Infothen
      begin
        result := true;
      end
      else
      begin
        file.Position := file.Position + count;
      end;
    end;
  end;
end;
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.

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.
  Mit Zitat antworten Zitat
Benutzerbild von Martin K
Martin K

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

Re: WAV-Dateien und ID3Tag?

  Alt 13. Aug 2007, 16:00
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.
Mit den Menschen ist es wie mit Computern -
es gibt Nullen und Einsen.
  Mit Zitat antworten Zitat
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
Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es 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

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:27 Uhr.
Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz