Solved

Get MP3 File Info

Posted on 1998-12-09
8
333 Views
Last Modified: 2010-04-04
How can I extract information about artist and recording quality (khz and bits) from an MP3 file?

Any help appreciated
Thanks in advance
0
Comment
Question by:friberg
  • 3
  • 3
  • 2
8 Comments
 
LVL 4

Expert Comment

by:jeurk
ID: 1350054
to get artist information you can look at the tag included in the mp3 file, don't know for the rest.
If you want I can retrieve you the link to a component that can read tag's found on torry's
I can remember it for the moment, but I can look at it if you want.
0
 

Author Comment

by:friberg
ID: 1350055
Yes, please give the link, that could be of some help.

Is anyone having a code example on the above?

0
 
LVL 4

Expert Comment

by:jeurk
ID: 1350056
here it is, source code included i think

http://www.torry.ru/vcl/mmedia/mp3tag.zip
0
 
LVL 3

Expert Comment

by:williams2
ID: 1350057
I have made a Header info function that is able to parse all necessary information from the 4 bytes header in the mp3 file. Is that what you need??

Regards,
Williams
0
How to run any project with ease

Manage projects of all sizes how you want. Great for personal to-do lists, project milestones, team priorities and launch plans.
- Combine task lists, docs, spreadsheets, and chat in one
- View and edit from mobile/offline
- Cut down on emails

 

Author Comment

by:friberg
ID: 1350058
Williams, yes I thinks that's exactly what I need. I don't know how the header info is stored, but I need to know about kbps, khz and mono/stereo on mp3 files. Could you please send me the function?
0
 
LVL 3

Accepted Solution

by:
williams2 earned 100 total points
ID: 1350059
If that is what you want, here is your answer:

This version of the MPx header extracter is not proffen to be sure to catch the header, as many headers might be hidden longer inside the file of the MP3. This will be corrected in a future release. There might be some not so pure coding in this, but my skills have been developed since last time I laid my hand on this, but it sure works :-)

Regards,
Williams

unit MPHeUnit;


  // This MPEG Layer 1-3 header extraction utility v1.0 has been developed by
  // Thomas Williams (c) 1997
  // The unit is freeware and can be used in any commercial way as I will be
  // creditet as the author of the functionality.

interface

Uses SysUtils;

Const
  BoolAnswer: Array[0..1] of String = ('No','Yes');
  Modes: Array[0..3] of String = ('Stereo','Joint Stereo','Dual Channel','Mono');
  Freqs: Array[0..6] of Integer =
  ( 44100, 48000, 32000, 22050, 24000, 16000 , 11025 );

  Tabs123: Array[0..(2*3*16-1)] of Integer = (
    0,32,64,96,128,160,192,224,256,288,320,352,384,416,448,0,
    0,32,48,56, 64, 80, 96,112,128,160,192,224,256,320,384,0,
    0,32,40,48, 56, 64, 80, 96,112,128,160,192,224,256,320,0,
    0,32,48,56, 64, 80, 96,112,128,144,160,176,192,224,256,0,
    0, 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0,
    0, 8,16,24, 32, 40, 48, 56, 64, 80, 96,112,128,144,160,0
  );

  Translations: Array[0..(2*3*16-1)] of Integer = (
    0,2,2,2,2,2,2,0,0,0,1,1,1,1,1,0,
    0,2,2,0,0,0,1,1,1,1,1,1,1,1,1,0,
    0,2,2,2,2,2,2,0,0,0,0,0,0,0,0,0,
    0,2,2,0,0,0,0,0,0,0,0,0,0,0,0,0,
    0,3,3,3,3,3,3,0,0,0,1,1,1,1,1,0,
    0,3,3,0,0,0,1,1,1,1,1,1,1,1,1,0
  );

Type

  TMpeg3Head = class
  Private
    //                ver., layer, bitrate
    tabsel_123: Array[0..1, 0..2 , 0..15  ] of Integer;
    Translate:  Array[0..1, 0..2 , 0..15  ] of Integer;
    Stereo: Integer;
    jsbound: Integer;
//    single: Integer;
    II_sblimit: Integer;
    lsf: Integer;
    mpg25: Integer;
//    down_sample: Integer;
//    header_change: Integer;
//    block_size: Integer;
    lay: Integer;
    error_protection: Integer;
    bitrate_index: Integer;
    sampling_frequency: Integer;
    padding: Integer;
    extension: Integer;
    mode: Integer;
    mode_ext: Integer;
    copyright_: Integer;
    original_: Integer;
    emphasis_: Integer;
    Privat_: Integer;
    Size_: Integer;
    MSB,LSB: Word;
    Bit: Array[0..31] of 0..1;
    Procedure SetBits;
    Procedure Get_II_stuff;
  Public
    Error: String;
    Version: String;
    Frames: String;
    Length: String;
    Frequency: String;
    Layer: String;
    BitRate, BitRateExt: String;
    OutputMode, OutputModeExt: String;
    Privat: String;
    CRC: String;
    Copyright: String;
    Original: String;
    Emphasis: String;
    Header: String;
    Size: String;
    Constructor Create;
    Function GetHeader(FilePath, FileName: String): Boolean;
  End;

implementation

  Function getLength(var S: String): Integer;
  Begin Result:= Length(S) End;

  Constructor TMpeg3Head.Create;
  var  //
    x,y,z,i: Integer;
  Begin
    i:= 0;
    For z:= 0 to 1 do
      For y:= 0 to 2 do
        For x:= 0 to 15 do
        begin
          Tabsel_123[z,y,x]:= Tabs123[i];
          Translate[z,y,x]:= Translations[i];
          inc(i);
        End;
    Error:= '';
  End;

  Procedure TMpeg3Head.SetBits;
  var
    i: Integer;
  Begin
    For i:= 0 to 15 do
      Bit[i]:= (LSB Shr i) AND $1;
    For i:= 0 to 15 do
      Bit[i+16]:= (MSB Shr i) AND $1;
  End;

  Procedure TMpeg3Head.Get_II_stuff;
  Const
    sblims: Array[0..4] of Integer = ( 27 , 30 , 8, 12 , 30 );
  var
    table: Integer;
  Begin
    if lsf<>0 then
      table := 4
    else
      table := translate[sampling_frequency,2 - stereo,bitrate_index];
    II_sblimit := sblims[table];;
//    static struct al_table *tables[5] =
//         { alloc_0, alloc_1, alloc_2, alloc_3 , alloc_4 };
//    fr->alloc = tables[table];
  End;

  Function TMpeg3Head.GetHeader(FilePath, FileName: String): Boolean;
  Const
    RIFF_SKIP = $46;
  var
    FrameSize,Frames_,Secs: Integer;
    Bytes: Array[1..4] of Byte;
    F: File of Byte;
  Begin
    Try
      AssignFile(F,FilePath+FileName);
      FileMode := 0; // Read Only
      Reset(F);
      Size_:= FileSize(F);
      If Size_<4 then Error:='Invalid MPEG file' else
      Begin
        Read(F,Bytes[1],Bytes[2],Bytes[3],Bytes[4]);
        If   (Bytes[1]=Ord('R')) AND (Bytes[2]=Ord('I'))
         AND (Bytes[3]=Ord('F')) AND (Bytes[4]=Ord('F')) then
        If Size_<=(RIFF_SKIP +4) then Error:='Invalid MPEG file' else
        Begin
          Seek(F,RIFF_SKIP);
          Read(F,Bytes[1],Bytes[2],Bytes[3],Bytes[4]);
          Dec(Size_,RIFF_SKIP);
        End;
        MSB:= Bytes[1]*256+Bytes[2];
        LSB:= Bytes[3]*256+Bytes[4];
        SetBits;
        If (MSB And $ffe0) <> $ffe0 then Error:= 'Invalid Header' else
        Begin
          Error:= '';
          if Bit[20]=1 then
          Begin
            lsf:= 1-Bit[19];
            mpg25:= 0;
          End else
          Begin
            lsf:= 1;
            mpg25:= 1;
          End;
          lay := 4 - (Bit[18]*2+Bit[17]);//((MSB shr 1) AND 3);
          BitRate_index := ((LSB shr 12) AND $F);
          If Bit[11]*2+Bit[10]=3 then Error:= 'Stream Error!';
          if mpg25=1 then
            sampling_frequency := 6
          else
            sampling_frequency := (Bit[11]*2+Bit[10]) + lsf * 3;
          error_protection := Bit[16] XOR 1;
          Padding:=    Bit[9];
          Extension:=  Bit[8];
          Mode:=       Bit[7]*2+Bit[6];
          Mode_Ext:=   Bit[5]*2+Bit[4];
          Copyright_:= Bit[3];
          Original_:=  Bit[2];
          Privat_:=    Bit[1];
          Emphasis_:=  Bit[0];
          If mode = 3 then // MD_MONO
            Stereo:= 1 else Stereo:= 2;
          If BitRate_Index=0 then Error:= 'Free format not Supported';
          Case lay Of
            1 : Begin
                  if mode=1 then
                    jsbound:= mode_ext*4+4
                  else
                    jsbound:= 32;
                  FrameSize:=  Tabsel_123[lsf,0,BitRate_index]*12000;
                  FrameSize:=  FrameSize div Freqs[sampling_frequency];
                  FrameSize:= (FrameSize + Padding) * 4 - 4;
                End;
            2 : Begin
                  Get_II_stuff;
                  if mode=1 then
                    jsbound:= mode_ext*4+4
                  else
                    jsbound:= II_Sblimit;
                  FrameSize:=  Tabsel_123[lsf,1,BitRate_index]*144000;
                  FrameSize:=  FrameSize div Freqs[sampling_frequency];
                  FrameSize:=  FrameSize + Padding - 4;
                End;
            3 : Begin
                  FrameSize:=  Tabsel_123[lsf,2,BitRate_index]*144000;
                  FrameSize:=  FrameSize div Freqs[sampling_frequency];
                  FrameSize:=  FrameSize + Padding - 4;
                End;
           Else Begin
                  Error:= 'Layer not supported!';
                  Result:= False;
                  Exit
                End;
          End;
          Inc(FrameSize,3); // Skip Header Info
          If mpg25=1 then Version:='MPEG 2.5' else
            If lsf=0 then Version:= 'MPEG 1.0' else Version:= 'MPEG 2.0';
          Frames_ := size_ div FrameSize;
          Frames := IntToStr(Frames_ * 2);
          Secs := (Frames_*2) div 77;
          Length:= IntToStr(Secs mod 60);
          If getLength(Length)=1 then Length:= '0'+Length;

          Length := IntToStr(Secs Div 60)+':'+Length;
          Layer := 'Layer '+IntToStr(Lay);
          Frequency := IntToStr(freqs[sampling_frequency])+'Hz';
          BitRate := IntToStr(tabsel_123[lsf,lay-1,bitrate_index])+' Kbits/s';
          BitRateExt := IntToStr(Extension);
          OutputMode := Modes[Mode];
          OutputModeExt := IntToStr(Mode_Ext);
          CRC := BoolAnswer[error_protection];
          Copyright := BoolAnswer[Copyright_];
          Original := BoolAnswer[Original_];
          Privat:= BoolAnswer[Privat_];
          Emphasis := BoolAnswer[Emphasis_];
          Header:= IntToHex(MSB,4)+IntToHex(LSB,4);
          Size:= IntToStr(Size_);
        End;
      End;
    finally
      CloseFile(F);
    End;
    Result:= Error='';
  End;

end.

0
 

Author Comment

by:friberg
ID: 1350060
Thanks again, just what I needed.
0
 
LVL 3

Expert Comment

by:williams2
ID: 1350061
That's allright my friend! Should it be another time?

Cheers,
Williams
0

Featured Post

How your wiki can always stay up-to-date

Quip doubles as a “living” wiki and a project management tool that evolves with your organization. As you finish projects in Quip, the work remains, easily accessible to all team members, new and old.
- Increase transparency
- Onboard new hires faster
- Access from mobile/offline

Join & Write a Comment

A lot of questions regard threads in Delphi.   One of the more specific questions is how to show progress of the thread.   Updating a progressbar from inside a thread is a mistake. A solution to this would be to send a synchronized message to the…
Introduction I have seen many questions in this Delphi topic area where queries in threads are needed or suggested. I know bumped into a similar need. This article will address some of the concepts when dealing with a multithreaded delphi database…
Sending a Secure fax is easy with eFax Corporate (http://www.enterprise.efax.com). First, Just open a new email message.  In the To field, type your recipient's fax number @efaxsend.com. You can even send a secure international fax — just include t…
This video explains how to create simple products associated to Magento configurable product and offers fast way of their generation with Store Manager for Magento tool.

746 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now