Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Multimedia (https://www.delphipraxis.net/16-multimedia/)
-   -   Delphi WAV File Info? (https://www.delphipraxis.net/211446-wav-file-info.html)

PeterPanino 16. Sep 2022 23:39

WAV File Info?
 
Hallo, kennt jemand eine Unit, mit der man grundlegende Informationen aus einer .WAV Datei extrahieren kann:

- Dauer (Spieldauer)
- Channels (Mono/Stereo)
- Sample-Rate
- Bits per Sample

Zur Präzisierung: Ich möchte die Datei nicht abspielen, sondern nur die obigen Informationen der .WAV Datei erhalten.

Ich habe jetzt eine Zeit lang recherchiert und experimentiert. Die Vielfalt bei .WAV Dateien scheint in der Praxis doch größer zu sein, als ich anfangs dachte. Aber vielleicht hat ja jemand einen Code, der funktioniert.

venice2 17. Sep 2022 00:37

AW: WAV File Info?
 
Suche mal nach AudioWerkzeugeBibliothek von Gausi.
Da gibt es die WavFiles.pas dort dürfte eigentlich alles übergeben werden.

Delphi-Quellcode:
    Twavfile = class(TBaseAudioFile)
        private
            procedure fResetData;
        protected
            function fGetFileSize  : Int64;   override;
            function fGetDuration  : Integer; override;
            function fGetBitrate   : Integer; override;
            function fGetSamplerate : Integer; override;
            function fGetChannels  : Integer; override;
            function fGetValid     : Boolean; override;

            procedure fSetTitle          (aValue: UnicodeString); override;
            procedure fSetArtist         (aValue: UnicodeString); override;
            procedure fSetAlbum          (aValue: UnicodeString); override;
            procedure fSetYear           (aValue: UnicodeString); override;
            procedure fSetTrack          (aValue: UnicodeString); override;
            procedure fSetGenre          (aValue: UnicodeString); override;

            function fGetTitle           : UnicodeString; override;
            function fGetArtist          : UnicodeString; override;
            function fGetAlbum           : UnicodeString; override;
            function fGetYear            : UnicodeString; override;
            function fGetTrack           : UnicodeString; override;
            function fGetGenre           : UnicodeString; override;

        public
            { Public declarations }
            constructor Create;
            function ReadFromFile(aFilename: UnicodeString): TAudioError;  override;
            function WriteToFile(aFilename: UnicodeString): TAudioError;   override;
            function RemoveFromFile(aFilename: UnicodeString): TAudioError; override;
        end;

PeterPanino 17. Sep 2022 00:58

AW: WAV File Info?
 
Vielen Dank, aber ich kann deinen Code nicht nachvollziehen, da die Klasse Twavfile unvollstänig ist. Hast du einen Link zur vollständigen Klasse?

venice2 17. Sep 2022 01:03

AW: WAV File Info?
 
Zitat:

Zitat von PeterPanino (Beitrag 1511961)
Vielen Dank, aber ich kann deinen Code nicht nachvollziehen, da die Klasse Twavfile unvollstänig ist. Hast du einen Link zur vollständigen Klasse?

Dachte eigentlich hätte dir entsprechende Infos gegeben..
Zitat:

Suche mal nach AudioWerkzeugeBibliothek von Gausi.
Aber gut hier!
https://www.delphipraxis.net/1456247-post5.html
Falls du den Link nicht findest.. dann hier
https://github.com/DanielGausi/AudioWerkzeugeBibliothek

PeterPanino 17. Sep 2022 01:04

AW: WAV File Info?
 
Liste der Anhänge anzeigen (Anzahl: 1)
Ich habe hier die Unit W32Waves gefunden (die schon etwas älter zu sein scheint):

https://www.swissdelphicenter.com/en...ode.php?id=692

Ich habe daraus die angehängte Demo gemacht. Diese crasht aber in der Zeile 90 mit einer Access Violation:

Delphi-Quellcode:
FillChar(Info^, SizeOf(TWaveInformation), #0); { Initialize first }
Kann man einfach für einen Record (TWaveInformation) eine Reihe von Null-Bytes in den Speicher schreiben, ohne vorher einen entsprechenden Speicher zu reservieren? Oder wieso gibt es hier sonst eine Access Violation?

Anhang 55386

venice2 17. Sep 2022 01:04

AW: WAV File Info?
 
Zitat:

Zitat von PeterPanino (Beitrag 1511963)
Ich habe hier die Unit W32Waves gefunden (die schon etwas älter zu sein scheint):

https://www.swissdelphicenter.com/en...ode.php?id=692

Ich habe daraus die angehängte Demo gemacht. Diese crasht aber in der Zeile 90 mit einer Access Violation:

Delphi-Quellcode:
FillChar(Info^, SizeOf(TWaveInformation), #0); { Initialize first }
Kann man einfach für einen Record (TWaveInformation) eine Reihe von Null-Bytes in den Speicher schreiben, ohne vorher einen entsprechenden Speicher zu reservieren? Oder wieso gibt es hier sonst eine Access Violation?

Anhang 55386

Nochmal!
https://github.com/DanielGausi/AudioWerkzeugeBibliothek

PeterPanino 17. Sep 2022 01:45

AW: WAV File Info?
 
[/quote]

Du brauchst nicht NOCHMAL den Link einzufügen. Ich habe es schon längst von github heruntergeladen und ausprobiert:

Die Länge liest er offenbar ein, auch wenn bei WAV Dateien, die unter einer Sekunde Dauer haben, diese auf 0 (!) abgerundet wird.

Und Die Samplerate hat mit der akustischen Schwingungs-Frequenz-Einheit HZ nichts zu tun. Aber die anderen Werte liest er offenbar korrekt ein.

PS: Trotzdem wäre ich neugierig, wieso bei FillChar eine Access Violation erfolgt.

venice2 17. Sep 2022 02:52

AW: WAV File Info?
 
Zitat:

PS: Trotzdem wäre ich neugierig, wieso bei FillChar eine Access Violation erfolgt.
Sorry man sollte schon wissen was man tut.

1. Variable ist falsch
Delphi-Quellcode:
var
  WavInfo: W32Waves.PWaveInformation;
WavInfo ist definitiv nicht initialisiert.
Daher..
Delphi-Quellcode:
var
  WavInfo: W32Waves.TWaveInformation;
2. Aufruf ändern
Delphi-Quellcode:
if W32Waves.GetWaveInformationFromFile(PChar(Trim(Edit.Text)), WavInfo) then

zu
Delphi-Quellcode:
if W32Waves.GetWaveInformationFromFile(PChar(Trim(Edit.Text)), @WavInfo) then


3. Diese Funktion ändern
Delphi-Quellcode:
function GetWaveInformationFromFile(const aFileName: AnsiString; Info: pWaveInformation): Winapi.Windows.Bool;

zu
Delphi-Quellcode:
function GetWaveInformationFromFile(const aFileName: PWideChar; Info: pWaveInformation): Winapi.Windows.Bool;

abschließend
Delphi-Quellcode:
hdmmio := Winapi.MMSystem.mmioOpen(PChar(aFileName), nil, Winapi.MMSystem.MMIO_READ);;

zu
Delphi-Quellcode:
hdmmio := Winapi.MMSystem.mmioOpen(aFileName, nil, Winapi.MMSystem.MMIO_READ);

Zitat:

Oder wieso gibt es hier sonst eine Access Violation?
Weil WavInfo vorher nicht initialisiert wurde.

Fazit:
Ja auch Debuggen ist mit unter eine Kunst!

Gausi 17. Sep 2022 07:17

AW: WAV File Info?
 
Zitat:

Zitat von PeterPanino (Beitrag 1511965)
Die Länge liest er offenbar ein, auch wenn bei WAV Dateien, die unter einer Sekunde Dauer haben, diese auf 0 (!) abgerundet wird.

Und Die Samplerate hat mit der akustischen Schwingungs-Frequenz-Einheit HZ nichts zu tun. Aber die anderen Werte liest er offenbar korrekt ein.

Die Länge wird in dieser Unit (bzw. für alle Formate dort) in Sekunden ausgegeben. Wenn du genauere Angaben brauchst, musst du die Zeile
Delphi-Quellcode:
fDuration := dataSize DIV BytesPerSec
ersetzen durch
Delphi-Quellcode:
fDuration := Round(1000 * dataSize / BytesPerSec)
. Dann hast du die Länge in Millisekunden. Wenn dich das Round dort auch noch stört, musst du den Typ ändern auf einen Float-Typen.

In welcher Einheit wird denn die Samplerate sonst gemessen, bzw. was ist das dann anderes als die Anzahl der Samples pro Sekunde (oder SamplesPerSec)? Da ist mein Code mit dem von SwissDelphiCenter ja auch identisch, nur lesen die einen Datenblock als Record ein, und ich mache das dort einzeln. Wobei ich diesen Teil damals vermutlich eh aus den alten ATLs (AudioToolsLibrary) übernommen habe. Die waren ganz gut, nur sollte man damit keine ID3Tags schreiben. Das Konzept nahm nämlich massiven Datenverlust in Kauf - aber das ist ja ein anderes Thema ...

PeterPanino 17. Sep 2022 10:23

AW: WAV File Info?
 
Zitat:

Ja auch Debuggen ist mit unter eine Kunst!
Danke für das Debuggen desCodes. Ich ziehe meinen Hut vor dem Debug-Künstler.

Danke an @Gausi für die AudioWerkzeugeBibliothek (v2.0) mit der ID3Tags-Fähigkeit. Respekt!

PeterPanino 17. Sep 2022 10:48

AW: WAV File Info?
 
Ich stelle hier mal die Ergebnisse des freundlicherweise von @venice2 debuggten Codes und der AudioWerkzeugeBibliothek (v2.0) von @Gausi anhand dieser WAV-Datei gegenüber:

C:\Windows\Media\Windows Logon.wav

W32Waves:

WaveFormat: 1
Channels: 2
SampleRate: 22050
BitsPerSample: 16
SamplesNumber: 384452
Length: 17,4354648526077

AudioWerkzeugeBibliothek (v2.0):

Type: RIFF WAVE
FileSize 384496 Bytes
Duration 4 sec
Bitrate 705 kBit/s
Samplerate 22050 Hz
Channels: 2

bzw. mit der von @Gausi vorgeschlagenen Divisions-Änderung:

Type: RIFF WAVE
FileSize 384496 Bytes
Duration 4359 millisec
Bitrate 705 kBit/s
Samplerate 22050 Hz
Channels: 2

Gausi 17. Sep 2022 12:18

AW: WAV File Info?
 
Da die Werte nicht übereinstimmen, und ich für eine der beiden Varianten verantwortlich bin, habe ich die Datei mal mit foobar2000 gestartet.
Der sagt mir eine Dauer von 4,359 Sekunden, bei 96113 Samples, 2 Channels und eine Bitrate von 706kbps. Die angezeigte Abspieldauer deckt sich auch mit der tatsächlichen Dauer beim Abspielen.

Das entspricht (bis auf eine andere Rundung bei der Bitrate) den Werten meiner Unit.

Die Dauer und die Anzahl der Samples bei der W32Waves-Variante weichen jeweils um den Faktor 4 ab. Woher das kommt, weiß ich nicht.

venice2 17. Sep 2022 12:21

AW: WAV File Info?
 
Zitat:

Das entspricht (bis auf eine andere Rundung bei der Bitrate) den Werten meiner Unit.
Deine Unit ist IO! :thumb:

Auch Audacity gibt mir die gleichen werte.

PeterPanino 17. Sep 2022 12:46

AW: WAV File Info?
 
Auch ich vertraue der LIBRARY AudioWerkzeugeBibliothek (v2.0).

PeterPanino 17. Sep 2022 13:34

AW: WAV File Info?
 
PS: Endlich mal ein schöner deutscher Name für eine Delphi Bibliothek!

PeterPanino 17. Sep 2022 16:05

AW: WAV File Info?
 
Liste der Anhänge anzeigen (Anzahl: 2)
EurekaLog meldet: Die AudioWerkzeugeBibliothek (v2.0) erzeugt Memory Leaks:

Anhang 55391

Hier ist der EurekaLog CallStack:

Anhang 55392

PeterPanino 17. Sep 2022 16:48

AW: WAV File Info?
 
Man kann die Memory Leaks vermeiden, indem man diesen Code einsetzt:

Code:
procedure TSimpleTagger.FormDestroy(Sender: TObject);
begin
  MainAudioFile.Free;
end;
Alternativ kann man auch diesen Code verwenden:

Code:
MainAudioFile := AudioFileFactory.CreateAudioFile(FileListBox1.FileName);
  try
    if assigned(MainAudioFile) then
    begin
      MainAudioFile.ReadFromFile(FileListBox1.FileName);

      EdtTitle.Text := MainAudioFile.Title;
      EdtArtist.Text := MainAudioFile.Artist;
      EdtAlbum.Text := MainAudioFile.Album;
      EdtGenre.Text := MainAudioFile.Genre;
      EdtYear.Text := MainAudioFile.Year;
      EdtTrack.Text := MainAudioFile.Track;
      Memo1.Clear;
      Memo1.Lines.Add(Format('Type:     %s', [MainAudioFile.FileTypeDescription]));
      Memo1.Lines.Add(Format('FileSize  %d Bytes', [MainAudioFile.FileSize]));
      Memo1.Lines.Add(Format('Duration  %d millisec', [MainAudioFile.Duration]));
      Memo1.Lines.Add(Format('Bitrate   %d kBit/s', [MainAudioFile.Bitrate div 1000]));
      Memo1.Lines.Add(Format('Samplerate %d Hz', [MainAudioFile.Samplerate]));
      Memo1.Lines.Add(Format('Channels: %d', [MainAudioFile.Channels]));
    end
    else
    begin
      EdtTitle.Text := '';
      EdtArtist.Text := '';
      EdtAlbum.Text := '';
      EdtGenre.Text := '';
      EdtYear.Text := '';
      EdtTrack.Text := '';
      Memo1.Clear;
    end;
  finally
    MainAudioFile.Free;
  end;

Gausi 17. Sep 2022 17:09

AW: WAV File Info?
 
Bei der Alternative solltest du dann aber nicht mehr auf "speichern" klicken. Denn dann ist das MainAudioFile schon zerstört, aber nicht NIL, so dass der Zugriff darauf dann (vermutlich) fehlschlägt. Das ist in dieser simplen Demo ein "globales" Objekt, und auch sonst ist es sinnvoll, das auf der global für die Form zu haben, nicht nur in den einzelnen Actions.

Das Free beim Beenden ist natürlich sinnvoll. Aber danach ist es ja eh weg. ;-)

PeterPanino 17. Sep 2022 18:25

AW: WAV File Info?
 
Zitat:

Das Free beim Beenden ist natürlich sinnvoll. Aber danach ist es ja eh weg.
Danke für den Hinweis - habe ich auch schon bemerkt. Ich mache es jetzt in Destroy. Weil mich die Eurekalog-Meldungen beim Beenden stören.

Danke nochmals für die Bibliothek - es ist wirklich ein Glanzstück!


Alle Zeitangaben in WEZ +1. Es ist jetzt 01:11 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