Thema: Mp3FileUtils

Einzelnen Beitrag anzeigen

MW97

Registriert seit: 20. Nov 2010
Ort: Sachsen-Anhalt, Region Magdeburg
13 Beiträge
 
Delphi 7 Personal
 
#53

AW: Mp3FileUtils

  Alt 13. Aug 2011, 20:04
Hier ist mein Code:

Delphi-Quellcode:
  //Typendeklaration für Bibliothek
  type
    TLibrary=record
      Files :TStringList;//Damit ordne ich den Titelinfos die pfade zu
      Cols:Array[1..3] of TStringList;//Col[1] für Titel, Col[2] für Interpret, Col[3] für Spiellänge
      //...
  end;
  
  type
    TMainConfig=record
      Lib:TLibrary;
      //...
  end;
  
  //Typendeklaration für Titelinformationen
  type
    TAudioInf=record;
      Interpret: string;
      Titel : string;
      Pfad : string;
      Album : string;
      Jahr : string;
      Dauer : integer;
  end;

  //Unit mit Prozeduren zum Auslesen der Infos (aus dem Delphitreff)
  unit UAudioInf;

  interface

  uses
   UTypes;

  procedure GetAudioInfo(FileName: string);
  procedure GetMp3Info;
  procedure GetWmaInfo;
  procedure SetUnknown;
  function GetPlaylistTitel:string;

var
  AudioInf: TAudioInf;

implementation

uses
  SysUtils, Mp3FileUtils, ATL_WMAfile, Classes;


//Hauptprozedur für Titelinformationen
procedure GetAudioInfo(FileName: string);
begin
  AudioInf.Pfad := filename;
  if (AnsiLowerCase(ExtractFileExt(FileName)) = '.mp3') then
    GetMp3Info
  else
    if AnsiLowerCase(ExtractFileExt(FileName)) = '.wmathen
      GetWMAInfo
    else
      SetUnknown;
  if AudioInf.Interpret='then AudioInf.Interpret:='Unbekannter Interpret';
  if AudioInf.Album=''     then AudioInf.Album:='Unbekanntes Album';
  if AudioInf.Jahr=''      then AudioInf.Jahr:='unbekanntes Jahr';
end;

//Prozedur für Titelinformationen von MP3-Dateien
procedure GetMp3Info;
var
  MpegInfo: TMpegInfo;
  ID3v2Tag: TID3V2Tag;
  ID3v1tag: TID3v1Tag;
  Stream: TFileStream;
begin

  // Daten mit MP3FileUtils auslesen
  Mpeginfo:=TMpegInfo.Create;
  ID3v2Tag:=TID3V2Tag.Create;
  ID3v1tag:=TID3v1Tag.Create;
  Stream := TFileStream.Create(AudioInf.Pfad, fmOpenRead or fmShareDenyWrite);
  try
  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;
  //Daten übertragen
  if mpeginfo.FirstHeaderPosition >- 1 then
  begin
    if id3v2tag.artist <> 'then
      AudioInf.Interpret := id3v2tag.artist
    else
      AudioInf.Interpret := id3v1tag.artist;
    if id3v2tag.Album <> 'then
      AudioInf.Album :=id3v2tag.Album
    else
      AudioInf.Album:=id3v1tag.Album;
    if id3v2tag.Year<> 'then
      AudioInf.Jahr:=id3v2tag.Year
    else
      AudioInf.Jahr:=id3v1tag.Year;
    if id3v2tag.title <> 'then
      AudioInf.Titel := id3v2tag.title
    else
      if id3v1tag.title <> 'then
        AudioInf.Titel := id3v1tag.title
      else
        AudioInf.Titel := ExtractFileName(AudioInf.Pfad);
    AudioInf.Dauer := mpeginfo.dauer;
  end else
    SetUnknown;
  finally
  MpegInfo.Free;
  Id3v2Tag.Free;
  Id3v1Tag.Free;
  end;
end;

//Prozedur für Titelinformationen von WMA-Dateien
procedure GetWmaInfo;
var
  wmaFile: TWMAfile;
begin
  if Not FileExists(AudioInf.Pfad) then
  begin
    SetUnknown;
    exit;
  end;
  try
  wmaFile := TWMAFile.create;
  if wmaFile.ReadFromFile(AudioInf.Pfad) then
  begin
    if wmaFile.Title <> 'then
      AudioInf.Titel := wmaFile.Title
    else
      AudioInf.Titel := ExtractFilename(AudioInf.Pfad);
      AudioInf.Interpret := wmaFile.Artist;
      AudioInf.Dauer := Round(wmaFile.Duration);
      AudioInf.Album :=wmaFile.Album;
      AudioInf.Jahr :=wmaFile.Year;
  end else
    SetUnknown;
  finally
  wmaFile.Free;
  end;
end;

//Prozedur für Titelinformationen von unbekannten Dateien
procedure SetUnknown;
begin
  AudioInf.Titel := ExtractFileName(AudioInf.Pfad);
  AudioInf.Interpret := '';
  AudioInf.Dauer := 0;
end;

//Prozedur für Titelinformationen nach %Interpret%-%Titel%
function GetPlaylistTitel:string;
begin
  if Trim(AudioInf.Interpret)='then
    result := AudioInf.Titel
  else
    result := AudioInf.Interpret + ' - ' + AudioInf.Titel;
end;
in meiner haupunit habe ich dann unter private ein TMainConfig-Objekt deklariert(ProConfig). Beim Programmstart werden die StringListen erstelt uns aus Dateien geladen.

Bei dieser Prozedur steigt dann der Speicherbedarf enorm an:
Delphi-Quellcode:
//Titelinformationen aktualisieren
procedure TForm1.LibRefreshInf(const Visualize: boolean);
var
  i, a, b: integer;
  Edited: boolean;
begin
  Edited:=false;
  if Visualize then
  begin
    Application.CreateForm(TFrmMakeUp, FrmMakeUp);
    FrmMakeUp.Show;
    FrmMakeUp.ChangesDone:=false;
  end;
  if ProConfig.Lib.Files.Count>0 then
  begin
    if Visualize then
    begin
      FrmMakeUp.ProgressBar1.Max:=ProConfig.Lib.Files.Count;
      FrmMakeUp.ProgressBar1.Position:=0;
    end;
    a:=0;
    for i:=ProConfig.Lib.Files.Count-1 downto 0 do
    begin
      if Visualize then
      begin
        inc(a);
        FrmMakeUp.ProgressBar1.Position:=a;
        FrmMakeUp.MainFile:=ProConfig.Lib.Files[i];
      end
      else
        Application.ProcessMessages;
      if FileExists(ProConfig.Lib.Files[i]) then
      begin
                  GetAudioInfo(ProConfig.Lib.Files[i]);
          if AudioInf.Titel<>ProConfig.Lib.Cols[1][i] then
          begin
            Edited:=true;
            ProConfig.Lib.Cols[1][i]:=AudioInf.Titel;
          end;
          if AudioInf.Interpret<>ProConfig.Lib.Cols[2][i] then
          begin
            Edited:=true;
            ProConfig.Lib.Cols[2][i]:=AudioInf.Interpret;
          end;
          if MsToMinuteSecond(AudioInf.Dauer*1000)<>ProConfig.Lib.Cols[3][i] then //MsToMinuteSecond wandelt
          begin //Sekunden in Minute:Sekunde um
            Edited:=true;
            ProConfig.Lib.Cols[3][i]:=MsToMinuteSecond(AudioInf.Dauer*1000);
          end;
          end;
      if not FileExists(ProConfig.Lib.Files[i]) then
      begin
        ProConfig.Lib.Files.Delete(i);
        for b:=1 to 3 do
          ProConfig.Lib.Cols[b].Delete(i);
      end;
    end;
  end;
  if Visualize then
  begin
    FrmMakeUp.ChangesDone:=true;
    FrmMakeUp.Close;
  end;
end;
Wenn ich der Prozedur true übergebe zeigt sie mir eine kleine form, die den status anzeigt, aber auch wenn ich das ganze im hintergrund machen lasse (false übergeben) steigt der bedarf.

EDIT:Ich habe gerade einen sehr eigenartigen Effekt festgestellt: Wenn ich in der Bibliothek meines Player 224 Elemente habe(Count der Stringlisten=224, Bedarf beim Start~1,8MB) dann steigt der Bedarf der Anwendung beim ausführen der Prozedur LibRefreshInf nicht. Wenn es aber 1014 Titel sind(Bedraf bei Start ~2,5 MB), dann steigt auf auf 182 MB. ???

Geändert von MW97 (13. Aug 2011 um 20:51 Uhr)
  Mit Zitat antworten Zitat