Du kan prøve med denne unit, som jeg engang fandt på nettet. Jeg havde det samme problem
engang.
Kalder FReadData(var data:TMPEGData;filename:string) : Integer;
Tiden:=Data.Duration;
Timer:=Tiden Div 3600;
Minut:=(Tiden-(Timer*3600)) Div 60;
Sekund:=Tiden-((Timer*3600)+(Minut*60));
{ --- Start ----------------------------------------------------------------------------------------------------- }
unit mpegfile;
interface
uses SysUtils, WinTypes, WinProcs, Classes, Messages, Controls;
type
TMPEGData = packed record
Duration : word; { Song duration }
FileLength : LongInt; { File length }
Version : byte; { MPEG audio version index (1 - Version 1,
2 - Version 2, 3 - Version 2.5,
0 - unknown }
Layer : byte; { Layer (1, 2, 3, 0 - unknown) }
SampleRate : LongInt; { Sampling rate in Hz}
BitRate : LongInt; { Bit Rate }
Mode : byte; { Number of channels (0 - Stereo,
1 - Joint-Stereo, 2 - Dual-channel,
3 - Single-Channel) }
Copyright : Boolean; { Copyrighted? }
Original : Boolean; { Original? }
ErrorProtection : boolean; { Error protected? }
Padding : Boolean; { If frame is padded }
FrameLength : Word; { total frame size including CRC }
CRC : word; { 16 bit File CRC (without TAG).
Not implemented yet. }
encoder : string;
end;
const
{ MPEG version indexes }
MPEG_VERSION_UNKNOWN = 0; { Unknown }
MPEG_VERSION_1 = 1; { Version 1 }
MPEG_VERSION_2 = 2; { Version 2 }
MPEG_VERSION_25 = 3; { Version 2.5 }
{ Description of MPEG version index }
MPEG_VERSIONS : array[0..3] of string = ('Unknown', '1.0', '2.0', '2.5');
{ Channel mode (number of channels) in MPEG file }
MPEG_MD_STEREO = 0; { Stereo }
MPEG_MD_JOINT_STEREO = 1; { Stereo }
MPEG_MD_DUAL_CHANNEL = 2; { Stereo }
MPEG_MD_MONO = 3; { Mono }
{ Description of number of channels }
MPEG_MODES : array[0..3] of string = ('Stereo', 'Joint-Stereo',
'Dual-Channel', 'Single-Channel');
{ Description of layer value }
MPEG_LAYERS : array[0..3] of string = ('Unknown', 'I', 'II', 'III');
{
Sampling rates table.
You can read mpeg sampling frequency as
MPEG_SAMPLE_RATES[mpeg_version_index][samplerate_index]
}
MPEG_SAMPLE_RATES : array[1..3] of array[0..3] of word =
{ Version 1 }
((44100, 48000, 32000, 0),
{ Version 2 }
(22050, 24000, 16000, 0),
{ Version 2.5 }
(11025, 12000, 8000, 0));
{
Predefined bitrate table.
Right bitrate is MPEG_BIT_RATES[mpeg_version_index][layer][bitrate_index]
}
MPEG_BIT_RATES : array[1..3] of array[1..3] of array[0..15] of word =
{ Version 1, Layer I }
(((0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0),
{ Version 1, Layer II }
(0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0),
{ Version 1, Layer III }
(0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0)),
{ Version 2, Layer I }
((0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0),
{ Version 2, Layer II }
(0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0),
{ Version 2, Layer III }
(0, 8,16,24, 32, 64, 80, 56, 64,128,160,112,128,256,320,0)),
{ Version 2.5, Layer I }
((0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0),
{ Version 2.5, Layer II }
(0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0),
{ Version 2.5, Layer III }
(0, 8,16,24, 32, 64, 80, 56, 64,128,160,112,128,256,320,0)));
{ Types of MPEG AUDIO DATAFILE }
MPEG_DF_CUSTOM = 0;
MPEG_DF_CATALOGUE = 1;
MPEG_DF_ORDER_FORM = 2;
{ Description of MPEG AUDIO DATAFILE type }
MPEG_DATAFILE_TYPES : array[0..2] of string = ('Custom','Catalogue',
'Order form');
{ Sign for MPEG Audio Datafile. This is used in MPEG Audio Datafile
header to identify file as such. First eight bytes (i.e #9'MP3DATA')
are file id, and rest two bytes are version and subversion numbers.
Do not change it. }
MPEG_DATAFILE_SIGN : string[9] = 'MP3DATA'+#01+#02;
{ File types that unit can recognize and read }
FT_UNKNOWN = 0; { Unknown }
FT_WINAMP_PLAYLIST = 1; { WinAmp playlist (*.m3u) }
FT_MPEG_DATAFILE = 2; { MPEG Audio Datafile (*.m3d) }
FT_MPEG_AUDIO = 3; { MPEG Audio }
const noencoder:string='Encoder nicht erkannt';
function FReadData(var data:TMPEGData;filename:string) : Integer;
implementation
function CalcFrameLength (SampleRate, BitRate : LongInt; Padding : Boolean) : Integer;
begin
If SampleRate > 0 then
Result := Trunc (144 * BitRate * 1000 / SampleRate + Integer (Padding))
else Result := 0;
end;
function FrameHeaderValid (Data : TMPEGData) : Boolean;
begin
Result := (Data.Version > 0) and
(Data.Layer > 0) and
(Data.BitRate > 0) and (Data.SampleRate > 0);
end;
function DecodeHeader (MPEGHeader : LongInt; var MPEGData : TMpegData) : Boolean;
{ Decode MPEG Frame Header and store data to TMPEGData fields.
Return True if header seems valid }
var
BitrateIndex : byte;
VersionIndex : byte;
bolsche:boolean;
begin
MPEGData.Version := 0;
MPEGData.Layer := 0;
MPEGData.SampleRate := 0;
MPEGData.Mode := 0;
MPEGData.Copyright := False;
MPEGData.Original := False;
MPEGData.ErrorProtection := False;
MPEGData.Padding := False;
MPEGData.BitRate := 0;
MPEGData.FrameLength := 0;
If (MPEGHeader and $ffe00000) = $ffe00000 then begin
VersionIndex := (MPEGHeader shr 19) and $3;
case VersionIndex of
0 : MPEGData.Version := MPEG_VERSION_25; { Version 2.5 }
1 : MPEGData.Version := MPEG_VERSION_UNKNOWN; { Unknown }
2 : MPEGData.Version := MPEG_VERSION_2; { Version 2 }
3 : MPEGData.Version := MPEG_VERSION_1; { Version 1 }
end;
{ if Version is known, read other data }
If MPEGData.Version <> MPEG_VERSION_UNKNOWN then begin
MPEGData.Layer := 4 - ((MPEGHeader shr 17) and $3);
If (MPEGData.Layer > 3) then MPEGData.Layer := 0;
BitrateIndex := ((MPEGHeader shr 12) and $F);
MPEGData.SampleRate := MPEG_SAMPLE_RATES[MPEGData.Version][((MPEGHeader shr 10) and $3)];
MPEGData.ErrorProtection := ((MPEGHeader shr 16) and $1) = 1;
MPEGData.Copyright := ((MPEGHeader shr 3) and $1) = 1;
MPEGData.Original := ((MPEGHeader shr 2) and $1) = 1;
MPEGData.Mode := ((MPEGHeader shr 6) and $3);
MPEGData.Padding := ((MPEGHeader shr 9) and $1) = 1;
bolsche:=(MPEGData.Version in [1..3]) and (MPEGData.Layer in [1..3]) and (BitrateIndex in [0..15]);
if bolsche then
begin
MPEGData.BitRate := MPEG_BIT_RATES[MPEGData.Version][MPEGData.Layer][BitrateIndex];
end;
If MPEGData.BitRate = 0 then MPEGData.Duration := 0
else MPEGData.Duration := (MPEGData.FileLength*8) div (longint(MPEGData.Bitrate)*1000);
MPEGData.FRameLength := CalcFrameLength (MPEGData.SampleRate, MPEGData.BitRate, MPEGData.Padding);
end;
Result := FrameHeaderValid (MPEGData);
end else Result := False;
end;
procedure ResetData(var data:TMPEGData);
{ Empty MPEG data }
const
Notag = '[notag]';
begin
with Data do begin
Duration := 0;
FileLength := 0;
Version := 0;
Layer := 0;
SampleRate := 0;
Mode := 0;
Copyright := False;
Original := False;
ErrorProtection := False;
Padding := False;
FrameLength := 0;
BitRate := 0;
CRC := 0;
encoder:=noencoder;
end; { with }
end; { function }
function FReadData(var data:TMPEGData;filename:string) : Integer;
var
mpfile:file;
mp3hdrread : array[1..8] of byte;
mp3hdr : LongInt ABSOLUTE mp3hdrread;
tempbyte : byte;
frames,tempLongInt : LongInt;
FFirstValidFrameHeaderPosition : LongInt;
FFileDetectionPrecision : Integer;
buffer:array[1..256] of char;
begin
Result := -1;
ResetData(data);
if fileexists(filename) then
begin
assignfile(mpfile,filename);
FileMode := 0;
{$I-}
Reset (mpfile,1);
{$I+}
Result := IOResult;
if (Result=0) and (FileSize(mpfile) > 5) then begin
{ Data.FileDateTime := FileAge (fileName);
Data.FileAttr := FileGetAttr (FileName);}
Data.FileLength := FileSize (mpfile);
repeat
{ read MPEG header from file }
BlockRead (mpfile, mp3hdrread,4);
tempbyte := mp3hdrread[1];
mp3hdrread[1] := mp3hdrread[4];
mp3hdrread[4] := tempbyte;
tempbyte := mp3hdrread[2];
mp3hdrread[2] := mp3hdrread[3];
mp3hdrread[3] := tempbyte;
FFileDetectionPRecision:=0;
While (not DecodeHeader (mp3hdr, Data)) and (not Eof (mpfile)) and
((FilePos(mpfile) <= FFileDetectionPrecision)
or (FFileDetectionPRecision = 0))
do begin
{ if mpeg header is not at the begining of the file, search file
to find proper frame sync. This block can be speed up by reading
blocks of bytes instead reading single byte from file }
mp3hdr := mp3hdr shl 8;
BlockRead (mpfile, tempbyte,1);
mp3hdrread[1] := tempbyte;
end; { while }
FFirstValidFrameHeaderPosition := FilePos (mpfile)-4;
tempLongInt := Filesize(mpfile) - fFirstValidFrameHeaderPosition - data.FrameLength + (2 * Byte(data.ErrorProtection));
If (not FrameHeaderValid(data)) or (TempLongInt <= 0) then begin
ResetData(data);
{ Data.FileName := ExpandFileName (tempStr);}
Data.FileLength := FileSize (mpfile);
end else begin
{ Ok, one header is found, but that is not good proof that file realy
is MPEG Audio. But, if we look for the next header which must be
FrameLength bytes after first one, we may be very sure file is
valid. }
Seek (mpfile, fFirstValidFrameHeaderPosition + data.FrameLength);
BlockRead (mpfile, mp3hdrread,4);
tempbyte := mp3hdrread[1];
mp3hdrread[1] := mp3hdrread[4];
mp3hdrread[4] := tempbyte;
tempbyte := mp3hdrread[2];
mp3hdrread[2] := mp3hdrread[3];
mp3hdrread[3] := tempbyte;
{ if mp3hdrread[1]=$0FF then bolsche:=true else bolsche:=false;
{ If not (data.bitrate<60) and not DecodeHeader (mp3hdr, Data2) then begin
{ well, next header is not valid. this is not MPEG audio file }
{ ResetData(data);
{ Data.FileName := ExpandFileName (tempStr);
Data.FileDateTime := FileAge (Data.fileName);}
{ Data.FileLength := FileSize (mpfile);
{ set file position back to the second byt of header that
seemed valid tolet function read all bytes that were
skipped inatempt tofind second header }
{ Seek (mpfile, fFirstValidFrameHeaderPosition + 1);
end else begin
{ BINGO!!! This realy is MPEG audio file so we may proceed}
{ end; { if }
end; { if }
until FrameHeaderValid(data) or Eof (mpfile) or ((FilePos(mpfile) > FFileDetectionPrecision) and (FFileDetectionPrecision > 0));
if Eof (mpfile) or ((FilePos(mpfile) > FFileDetectionPrecision) and (FFileDetectionPrecision > 0)) then result:=-1 else
begin
seek(mpfile,fFirstValidFrameHeaderPosition+36);
blockread(mpfile,buffer,256);
if (buffer[1]='X') and (buffer[2]='i') and (buffer[3]='n') and (buffer[4]='g') then
if buffer[8]=#15 then
begin
data.encoder:='Audio Catalyst VBR';
frames:=ord(buffer[9]);
frames:=frames*256+ord(buffer[10]);
frames:=frames*256+ord(buffer[11]);
frames:=frames*256+ord(buffer[12]);
data.framelength:=data.FileLength div frames;
data.bitrate:=trunc(data.framelength*data.samplerate / 144000)- Integer (data.Padding);
Data.Duration := (Data.FileLength*8) div (longint(Data.Bitrate)*1000);
end;
seek(mpfile,fFirstValidFrameHeaderPosition);
blockread(mpfile,mp3hdrread,8);
if mp3hdrread[4]=$04 then
begin
if mp3hdrread[7]=$0F then Data.encoder:='Mp3 Compressor'
else Data.encoder:='Xing 2.20';
end;
if mp3hdrread[4]=$44 then
begin
if mp3hdrread[8]=$00 then Data.encoder:='l3Enc'
else
if mp3hdrread[7]=$01 then Data.encoder:='Audioactive P. Studio'
else Data.encoder:='mp3 Producer';
end;
if mp3hdrread[4]=$6C then Data.encoder:='Audio Catalyst';
if mp3hdrread[4]=$4C then Data.encoder:='Audio Catalyst VBR';
end;
end; { if }
closefile(mpfile);
end; {fileexists}
end; { FReadData }
end.
{ --- Slut ------------------------------------------------------------------------------------------------------ }