{

_UAudioFileFAQ

Autor:  Daniel "Gausi" Gaußmann
        Gausi@delphi-forum.de

Da diese Unit meiner Meinung nach keine signifikante Schöpfungshöhe besitzt,
darf sie beliebig verwendet, modifiziert und verbreitet werden.

In dieser Form sind jedoch die Lizenzbestimmungen der verwendeten Unit
MP3FileUtils zu beachten. Wer diese Unit durch eigene oder andere Verfahren
ersetzen möchte, kann dies gerne tun.

Benötigte Units:
----------------
MP3FileUtils:
Download unter: http://www.delphi-forum.de/topic_MP3FileUtils_51410.html
}

unit _UAudioFileFAQ;

interface

uses classes, SysUtils, Mp3FileUtils;

type

    TAudioFile = class
    private
        FPfad: string;
        FDateiname: string;
        FOrdner: string;
        FDateiGroesse: Integer;

        // aus den ID3-Tags (oder andere Meta-Tags)
        FArtist: string;
        FTitel:  string;
        FAlbum:  string;
        FYear:   string;  // Ja, ein String!
        FGenre:  string;
        FKommentar: string;
        FLyrics: string;

        // aus den MPEG-Infos
        FDauer: Integer;
        FBitrate: word;
        Fvbr: boolean;
        FChannelMode: String;
        FSamplerate:Integer;

        procedure SetNA(filename: String);

        procedure GetMp3Info(filename:string);
        //procedure GetWMAInfo(filename:string);
        //procedure GetWAVInfo(filename:string);
        //procedure GetOGGInfo(filename:string);

    public
        property Pfad:      string read FDateiname;
        property Dateiname: string read FDateiname;
        property Ordner:    string read FOrdner;
        property DateiGroesse: Integer read FDateiGroesse;
        // aus den ID3-Tags (oder andere Meta-Tags)
        property Artist: string read FArtist;
        property Titel:  string read FTitel;
        property Album:  string read FAlbum;
        property Year:   string read FYear;  // Ja, ein String!
        property Genre:  string read FGenre;
        property Kommentar: string read FKommentar;
        property Lyrics: string read FLyrics;
        // aus den MPEG-Infos
        property Dauer: Integer read FDauer;
        property Bitrate: word read FBitrate;
        property vbr: boolean read Fvbr;
        property ChannelMode: String read FChannelMode;
        property Samplerate:Integer read FSamplerate;

        constructor create;
        destructor destroy; override;
        procedure GetAudioData(filename:string);
    end;

implementation

 {$I-}


constructor TAudioFile.create;
begin
    inherited create;
    Fdauer       := 0;
    FBitrate     := 0;
    FChannelmode := 'Stereo';
    FSamplerate  := 44100;
    FGenre := 'Other';
    FYear  := '';
end;

destructor TAudioFile.destroy;
begin
    inherited destroy;
end;

procedure TAudioFile.SetNA(filename: String);
Var F: File;
begin
  if FileExists(filename) then
  try
    AssignFile(F, filename);
    FileMode := 0;
    Reset(F,1);
    FDateiGroesse := filesize(F);
    CloseFile(F);
  except
    FDateiGroesse := 0;
  end
  else
    FDateiGroesse := 0;

  FPfad:=filename;
  FOrdner:=(ExtractFileDir(filename));
  FDateiname:=extractfilename(Pfad);

  FTitel:=Dateiname;
  FArtist := '';
  FAlbum := '';
  FYear := '';
  FGenre := '';
  FDauer := 0;
  FBitrate := 0;
  Fvbr := True;
  FChannelmode := 'Unknown';
  FSamplerate := -1;
end;


procedure TAudioFile.GetMp3Info(filename:String);
var MpegInfo:TMpegInfo;
    ID3v2Tag:TID3V2Tag;
    ID3v1tag:TID3v1Tag;
    Stream: TFilestream;
begin
    FPfad      := filename;
    FOrdner    := ExtractFileDir(filename);
    FDateiname := ExtractFileName(Pfad);
    if NOT FileExists(filename) then exit;

    MpegInfo := TMpegInfo.Create;
    ID3v2Tag := TID3V2Tag.Create;
    ID3v1tag := TID3v1Tag.Create;

    // Datei als Stream öffnen und Daten auslesen
    stream := TFileStream.Create(filename, fmOpenRead or fmShareDenyWrite);
    ID3v1tag.ReadFromStream(stream);
    stream.Seek(0, sobeginning);
    ID3v2Tag.ReadFromStream(stream);

    if Not ID3v2Tag.exists then
      stream.Seek(0, sobeginning)
    else
      stream.Seek(ID3v2Tag.size, soFromBeginning);

    mpeginfo.LoadFromStream(Stream);
    stream.free;

    // ausgelesene Daten aufarbeiten, falls die Datei als mp3-File erkannt wurde:
    //------------------------------------------------------------------
    if mpeginfo.FirstHeaderPosition>-1 then begin
        // aus dem ID3 Tag
        //------------------------------------------------------------------
        // Bei Mp3-Dateien stehen ggf. die Informationen über Titel und Artist
        // doppelt in der Datei. Diese Daten müssen aber nciht norwendigerweise
        // übereinstimmen, und tun dies auch oft nicht.
        // Das liegt daran, dass der neuere ID3V2-Tag auch längere Strings speichern
        // kann als der ältere v1-tag, der auf 30 Zeichen pro Feld beschränkt ist.
        //
        // Da unsere Klasse TAudioFile aber nur ein Feld für Artist etc. hat, müssen
        // wir aus diesen beiden Informationen eine auswählen.
        // Hier hat der v2-tag Vorrang. Ist dieser nicht vorhanden, oder das entsprechende
        // Feld leer, wird der v1-tag genommen.
        if ID3v2Tag.artist <> '' then
          FArtist := ID3v2Tag.artist
        else
          if ID3v1tag.artist <> '' then
            FArtist := ID3v1tag.artist
          else
            FArtist := '';

        if ID3v2Tag.title <> '' then
          FTitel := ID3v2Tag.title
        else
          if ID3v1tag.title <> '' then
            FTitel := ID3v1tag.title
          else
            // An dieser Stelle nehmen wir den Dateinamen als Titel
            FTitel := Dateiname;

        if ID3v2Tag.album <> '' then
          FAlbum := ID3v2Tag.album
        else
          if ID3v1tag.album <> '' then
            FAlbum := ID3v1tag.album
          else FAlbum := '';

        if ID3v2Tag.Year <> '' then
          FYear := ID3v2Tag.Year
        else
          if ID3v1tag.Year <> '' then
            FYear := ID3v1tag.Year
          else FYear := '';

        if ID3v2Tag.genre <> '' then
          Fgenre := ID3v2Tag.genre
        else
          Fgenre := ID3v1tag.genre;

        if ID3v2Tag.Comment <> '' then
          FKommentar := ID3v2Tag.Comment
        else
          if ID3v1tag.Comment <> '' then
            FKommentar := ID3v1tag.Comment
          else
            FKommentar := '';

        // Lyrics können nur im v2-Tag gespeichert werden.
        FLyrics := ID3v2Tag.GetLyrics('*','*');

        // aus den MPEG-Infos
        FDauer        := MpegInfo.dauer;
        FBitrate      := MpegInfo.bitrate;
        Fvbr          := MpegInfo.vbr;
        FDateiGroesse := MpegInfo.FileSize;
        FSampleRate   := MpegInfo.samplerate;

        case MpegInfo.channelmode of
            0: FChannelmode := 'Stereo';
            1: FChannelmode := 'Joint Stereo';
            2: FChannelmode := 'Dual Channel Stereo';
            3: FChannelmode := 'Mono';
            else FChannelmode := 'Unknown';
        end;
    end else
    begin
        // andernfalls: Kein gültiges Mp3File.
        // Standardwerte nehmen
        SetNA(filename);
    end;
    MpegInfo.Free;
    Id3v2Tag.Free;
    Id3v1Tag.Free;
end;


procedure TAudioFile.GetAudioData(filename:string);
begin
  try
      if (AnsiLowerCase(ExtractFileExt(filename)) = '.mp3')
        or (AnsiLowerCase(ExtractFileExt(filename)) = '.mp2')
        or (AnsiLowerCase(ExtractFileExt(filename)) = '.mp1')
      then
        GetMp3Info(Filename)
      else
        // Evtl. andere Dateitypen untersuchen
        //if AnsiLowerCase(ExtractFileExt(filename)) = '.wma' then
        //  GetWMAInfo(Filename)
        //else
        //  if AnsiLowerCase(ExtractFileExt(filename)) = '.wav' then
        //    GetWavInfo(Filename)
        //  else
        //    if AnsiLowerCase(ExtractFileExt(filename)) = '.ogg' then
        //      GetOGGInfo(Filename)
        //    else
        SetNA(filename);
  except
    SetNA(filename);
  end;
end;

end.
