Ich habe ja in letzter Zeit öfter mal über KI gemeckert, besonders über Googles Bard bzw. jetzt Gemini. Aber Holladiwaldfee ... ChatGPT ist tatsächlich um Welten besser.
Da ich grade dabei bin, bei meiner Audio-Bibliothek auch Opus-Dateien zu unterstützen, habe ich für ein (bereits implementiertes) Teilproblem mal diese KIs befragt.
Mein Input:
Kannst du mir eine Funktion in der Programmiersprache Delphi schreiben, die aus einer gegebenen Ogg-Datei die maximale absolute granule position ermittelt?
Gemini hat (mal wieder) irgendwelche nicht-existenten Klassen herbei-fantasiert und somit nutzlosen Code produziert.
Delphi-Quellcode:
unit OggGranulePosition;
interface
uses
Windows,
Messages,
StdCtrls,
ExtCtrls,
OggVorbis;
implementation
function GetMaxGranulePosition(oggFileName:
string): LongWord;
var
oggFile: TOggVorbisFile;
oggStream: TOggVorbisStream;
granulePosition: LongWord;
granuleCount: LongWord;
i: LongWord;
begin
oggFile := TOggVorbisFile.Create;
try
oggFile.Open(oggFileName, ofRead);
oggStream := TOggVorbisStream.Create(oggFile);
try
granulePosition := 0;
granuleCount := oggStream.Info.Packets;
for i := 0
to granuleCount - 1
do
begin
granulePosition := Max(granulePosition, oggStream.Packets[i].Granulepos);
end;
finally
oggStream.Free;
end;
finally
oggFile.Free;
end;
Result := granulePosition;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
ShowMessage('
Maximal absolute granule position: ' +
IntToStr(GetMaxGranulePosition('
C:\path\to\oggFile.ogg')));
end;
end.
ChatGPT liefert hingegen eine Struktur für den Ogg-Seitenheader, ermittelt nach einer Gültigkeits-Überprüfung daraus den gesuchten Wert. Dann wird korrekt die Größe der Seite berechnet, um sich seitenweise durch die Datei zu hangeln, um dann schließlich auf der letzten Seite den gesuchten Wert zu ermitteln.
Delphi-Quellcode:
program MaxGranulePosition;
uses
Classes, SysUtils;
type
TOggPageHeader =
packed record
CapturePattern:
array[0..3]
of AnsiChar;
Version: Byte;
HeaderType: Byte;
GranulePosition: Int64;
BitstreamSerialNumber: Cardinal;
PageSequenceNumber: Cardinal;
Checksum: Cardinal;
PageSegments: Byte;
end;
function ReadOggPageHeader(Stream: TStream;
out Header: TOggPageHeader): Boolean;
begin
Result := Stream.
Read(Header, SizeOf(TOggPageHeader)) = SizeOf(TOggPageHeader);
end;
function GetMaxGranulePosition(
const FileName:
string): Int64;
var
FileStream: TFileStream;
OggPageHeader: TOggPageHeader;
MaxGranulePosition: Int64;
PageSegments:
array of Byte;
SegmentSize: Integer;
I: Integer;
begin
MaxGranulePosition := 0;
FileStream := TFileStream.Create(FileName, fmOpenRead
or fmShareDenyWrite);
try
while FileStream.Position < FileStream.Size
do
begin
if not ReadOggPageHeader(FileStream, OggPageHeader)
then
Break;
if (OggPageHeader.CapturePattern <> '
OggS')
then
Break;
// Invalid Ogg page
if OggPageHeader.GranulePosition > MaxGranulePosition
then
MaxGranulePosition := OggPageHeader.GranulePosition;
SetLength(PageSegments, OggPageHeader.PageSegments);
FileStream.
Read(PageSegments[0], OggPageHeader.PageSegments);
SegmentSize := 0;
for I := 0
to OggPageHeader.PageSegments - 1
do
Inc(SegmentSize, PageSegments[I]);
FileStream.Seek(SegmentSize, soFromCurrent);
end;
finally
FileStream.Free;
end;
Result := MaxGranulePosition;
end;
var
FileName:
string;
MaxGranule: Int64;
begin
Write('
Enter the Ogg file path: ');
ReadLn(FileName);
try
MaxGranule := GetMaxGranulePosition(FileName);
WriteLn('
Max Granule Position: ', MaxGranule);
except
on E:
Exception do
WriteLn('
Error: ', E.
Message);
end;
ReadLn;
end.
Meine bisherigen Methode, vom Ende der Datei aus den letzten Ogg-Header zu suchen, ist zwar schneller, wenn die Seitengröße klein ist. Aber wenn die fehlschlägt (warum auch immer) ist das, was ChatGPT vorschlägt, die korrekte und sichere Variante.
Hat mich tatsächlich beeindruckt. Vor allem, weil das ja kein "Standard-Problem" ist, was ständig diskutiert wird.
The angels have the phone box.