Reading MP3 headers

Share your advanced PureBasic knowledge/code with the community.
User avatar
Thorsten1867
Addict
Addict
Posts: 1366
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Reading MP3 headers

Post by Thorsten1867 »

Code: Select all

; ___ ID ___
#MPEG25 = 0 ; MPEG Version 2.5 (later extension of MPEG 2)
#MPEG2  = 2 ; MPEG Version 2 (ISO/IEC 13818-3)
#MPEG1  = 3 ; MPEG Version 1 (ISO/IEC 11172-3)

; __ Layer ___
#Layer1 = 3
#Layer2 = 2
#Layer3 = 1

; ___ Channel Mode ___
#Stereo   = 0 
#Joint    = 1 ; Joint stereo (Stereo)
#DualMono = 2 ; Dual channel (2 mono channels)
#Mono     = 3 ; Single channel (Mono)

; ___ Emphasis ___
#None     = 0
#MS50_15  = 1 ; 50/15 ms
#CCIT_J17 = 3 ; CCIT J.17

Structure MP3_Structure
  ID.i
  Layer.i
  Protection.i
  Bitrate.i
  Samplingrate.i
  Padding.i
  Private.i
  Channel.i
  Extension.i
  Copyright.i
  Original.i
  Emphasis.i
EndStructure  

Procedure.w uint8(Value.b)
  
  ProcedureReturn Value & $FF
  
EndProcedure

Procedure.i uint16(Value.w, BigEndian.i=#True)

  If BigEndian
    ProcedureReturn (Value>>8&$FF) | (Value<<8&$FF00)
  Else
    ProcedureReturn Value & $FFFF
  EndIf
  
EndProcedure

Procedure.i GetBitrate(ID.i, Layer.i, Value.i)
  
  If ID = #MPEG1 ;{ MPEG 1

    Select Value
      Case 1
        ProcedureReturn 32
      Case 2
        Select Layer
          Case #Layer1   
            ProcedureReturn 64
          Case #Layer2  
            ProcedureReturn 48
          Case #Layer3
            ProcedureReturn 40
        EndSelect    
      Case 3
        Select Layer
          Case #Layer1   
            ProcedureReturn 96
          Case #Layer2  
            ProcedureReturn 56
          Case #Layer3
            ProcedureReturn 48
        EndSelect 
      Case 4
        Select Layer
          Case #Layer1   
            ProcedureReturn 128
          Case #Layer2  
            ProcedureReturn 64
          Case #Layer3
            ProcedureReturn 56
        EndSelect 
      Case 5
        Select Layer
          Case #Layer1   
            ProcedureReturn 160
          Case #Layer2  
            ProcedureReturn 80
          Case #Layer3
            ProcedureReturn 64
        EndSelect 
      Case 6
        Select Layer
          Case #Layer1   
            ProcedureReturn 192
          Case #Layer2  
            ProcedureReturn 96
          Case #Layer3
            ProcedureReturn 80
        EndSelect 
      Case 7
        Select Layer
          Case #Layer1   
            ProcedureReturn 224
          Case #Layer2  
            ProcedureReturn 112
          Case #Layer3
            ProcedureReturn 96
        EndSelect 
      Case 8 
        Select Layer
          Case #Layer1   
            ProcedureReturn 256
          Case #Layer2  
            ProcedureReturn 128
          Case #Layer3
            ProcedureReturn 112
        EndSelect 
      Case 9
        Select Layer
          Case #Layer1   
            ProcedureReturn 288
          Case #Layer2  
            ProcedureReturn 160
          Case #Layer3
            ProcedureReturn 128
        EndSelect 
      Case 10
        Select Layer
          Case #Layer1   
            ProcedureReturn 320
          Case #Layer2  
            ProcedureReturn 192
          Case #Layer3
            ProcedureReturn 160
        EndSelect 
      Case 11
        Select Layer
          Case #Layer1   
            ProcedureReturn 352
          Case #Layer2  
            ProcedureReturn 224
          Case #Layer3
            ProcedureReturn 192
        EndSelect 
      Case 12  
        Select Layer
          Case #Layer1   
            ProcedureReturn 384
          Case #Layer2  
            ProcedureReturn 256
          Case #Layer3
            ProcedureReturn 224
        EndSelect 
      Case 13
        Select Layer
          Case #Layer1   
            ProcedureReturn 416
          Case #Layer2  
            ProcedureReturn 320
          Case #Layer3
            ProcedureReturn 256
        EndSelect 
      Case 14  
        Select Layer
          Case #Layer1   
            ProcedureReturn 448
          Case #Layer2  
            ProcedureReturn 384
          Case #Layer3
            ProcedureReturn 320
        EndSelect 
    EndSelect    
    ;}
  Else
    
    Select Value
      Case 1
        If Layer = #Layer1
          ProcedureReturn 32
        Else
          ProcedureReturn 8
        EndIf  
      Case 2
        If Layer = #Layer1
          ProcedureReturn 48
        Else
          ProcedureReturn 16
        EndIf   
      Case 3
        If Layer = #Layer1
          ProcedureReturn 56
        Else
          ProcedureReturn 24
        EndIf  
      Case 4
        If Layer = #Layer1
          ProcedureReturn 64
        Else
          ProcedureReturn 32
        EndIf   
      Case 5
        If Layer = #Layer1
          ProcedureReturn 80
        Else
          ProcedureReturn 40
        EndIf  
      Case 6
        If Layer = #Layer1
          ProcedureReturn 96
        Else
          ProcedureReturn 48
        EndIf 
      Case 7
        If Layer = #Layer1
          ProcedureReturn 112
        Else
          ProcedureReturn 56
        EndIf  
      Case 8 
        If Layer = #Layer1
          ProcedureReturn 128
        Else
          ProcedureReturn 64
        EndIf  
      Case 9
        If Layer = #Layer1
          ProcedureReturn 144
        Else
          ProcedureReturn 80
        EndIf  
      Case 10
        If Layer = #Layer1
          ProcedureReturn 160
        Else
          ProcedureReturn 96
        EndIf  
      Case 11
        If Layer = #Layer1
          ProcedureReturn 176
        Else
          ProcedureReturn 112
        EndIf  
      Case 12  
        If Layer = #Layer1
          ProcedureReturn 192
        Else
          ProcedureReturn 
        EndIf  
      Case 13
        If Layer = #Layer1
          ProcedureReturn 224
        Else
          ProcedureReturn 144
        EndIf  
      Case 14  
        If Layer = #Layer1
          ProcedureReturn 256
        Else
          ProcedureReturn 160
        EndIf  
    EndSelect
    
  EndIf
  
EndProcedure  

Procedure.i GetSamplingRate(ID.i, Value.i)
  
  Select ID
    Case #MPEG1
      Select Value
        Case 0
          ProcedureReturn 44100
        Case 1
          ProcedureReturn 48000
        Case 2
          ProcedureReturn 32000
      EndSelect
    Case #MPEG2
      Select Value
        Case 0
          ProcedureReturn 22050
        Case 1
          ProcedureReturn 24000
        Case 2
          ProcedureReturn 16000
      EndSelect
    Case #MPEG25
      Select Value
        Case 0
          ProcedureReturn 11025
        Case 1
          ProcedureReturn 12000
        Case 2
          ProcedureReturn 8000
      EndSelect
  EndSelect    
  
EndProcedure

Procedure   HeaderMP3(File.s, *MP3.MP3_Structure)
  Define.i FileID, Size, Result
  Define   Bytes.w, Byte.b
  Define   *Memory, *EndMem, *StartMem
  
  FileID = ReadFile(#PB_Any, File)   
  If FileID
    
    Size = Lof(FileID)
    
    If Size
      
      *Memory = AllocateMemory(Size)
    
      If ReadData(FileID, *Memory, Size)
        
        *StartMem = *Memory
        *EndMem   = *Memory + Size
        
        Repeat
          Bytes = uint16(PeekW(*Memory))
          If (Bytes >> 5) & %11111111111 = 2047 : Break : EndIf ; Sync
          *Memory + 1
        Until *Memory >= *EndMem
        
        
        If (Bytes >> 5) & %11111111111 = 2047 
          
          *MP3\ID         = (Bytes >> 3) & %11
          *MP3\Layer      = (Bytes >> 1) & %11
          *MP3\Protection = Bytes & %1
          
          Byte = uint8(PeekB(*Memory + 2))
    
          *MP3\Bitrate      = GetBitrate(*MP3\ID, *MP3\Layer, (Byte >> 4) & %1111)
          *MP3\Samplingrate = GetSamplingRate(*MP3\ID, (Byte >> 2) & %11)
          *MP3\Padding      = (Byte >> 1) & %1
          *MP3\Private      = Byte & %1
          
          Byte = uint8(PeekB(*Memory + 3))
          
          *MP3\Channel   = (Byte >> 6) & %11
          *MP3\Extension = (Byte >> 4) & %11
          *MP3\Copyright = (Byte >> 3) & %1
          *MP3\Original  = (Byte >> 2) & %1
          *MP3\Emphasis  = Byte & %11
          
          Result = #True
        EndIf
        
        FreeMemory(*StartMem)
      EndIf
      
      CloseFile(FileID) 
    EndIf
    
  EndIf
  
  ProcedureReturn Result
EndProcedure

;- ========== Example ===========================

Define MP3.MP3_Structure

MP3File$ = "D:\Temp\Test.mp3"

If HeaderMP3(MP3File$,@MP3)

  Select MP3\ID
    Case #MPEG1
      Debug "Version: MPEG 1"
    Case #MPEG2
      Debug "Version: MPEG 2"
    Case #MPEG25
      Debug "Version: MPEG 2.5"
  EndSelect    
  
  Select MP3\Layer
    Case #Layer1
      Debug "Layer: 1"
    Case #Layer2
      Debug "Layer: 2"
    Case #Layer3  
      Debug "Layer: 3"
  EndSelect
  
  Debug "Bitrate: " + Str(MP3\Bitrate)
  Debug "Sampling rate: " + Str(MP3\Samplingrate) + "Hz"
  
  Select MP3\Channel
    Case #Stereo
      Debug "Channel Mode: Stereo"
    Case #Joint
      Debug "Channel Mode: Joint Stereo"
    Case #DualMono
      Debug "Channel Mode: Dual channel (2 * Mono)"
    Case #Mono
      Debug "Channel Mode: Single channel (Mono)"  
  EndSelect    
  
  If MP3\Copyright
    Debug "Copyright: yes"
  Else
    Debug "Copyright: no"
  EndIf 
  
EndIf
 
Last edited by Thorsten1867 on Tue Apr 14, 2020 8:58 am, edited 6 times in total.
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Reading MP3 headers

Post by Kwai chang caine »

Hello Thorsten1867 :wink:

First...thanks for sharing 8)
I have test your code with a little MP3 file and have that, is it normal ?
Version: MPEG 2.5
Bitrate: 0
Sampling rate: 0Hz
Channel Mode: Stereo
Copyright: no
http://erdsjb.free.fr/purestorage/provisoires/mp3.mp3
ImageThe happiness is a road...
Not a destination
User avatar
Thorsten1867
Addict
Addict
Posts: 1366
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Re: Reading MP3 headers

Post by Thorsten1867 »

Currently only works if the header is at the beginning of the file.
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
Thorsten1867
Addict
Addict
Posts: 1366
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Re: Reading MP3 headers

Post by Thorsten1867 »

Update: Search first valid frame
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Reading MP3 headers

Post by Kwai chang caine »

I don't know if it's normal, but with your new code and the same file mp3 i have an IMA in HeaderMP3 procedure line :wink:

Code: Select all

FreeMemory(*Memory)
ImageThe happiness is a road...
Not a destination
User avatar
Thorsten1867
Addict
Addict
Posts: 1366
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Re: Reading MP3 headers

Post by Thorsten1867 »

Fixed
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
User avatar
Kwai chang caine
Always Here
Always Here
Posts: 5342
Joined: Sun Nov 05, 2006 11:42 pm
Location: Lyon - France

Re: Reading MP3 headers

Post by Kwai chang caine »

Thanks a lot for your quick fix 8)
That works now
Version: MPEG 1
Layer: 3
Bitrate: 128
Sampling rate: 44100Hz
Channel Mode: Stereo
Copyright: no
Again thanks for sharing 8)
ImageThe happiness is a road...
Not a destination
Kuzmat
User
User
Posts: 13
Joined: Mon Jan 27, 2014 9:09 am

Re: Reading MP3 headers

Post by Kuzmat »

Code: Select all

  Select MP3\Layer
    Case #Layer1
      Debug "Layer: 3"
    Case #Layer2
      Debug "Layer: 3"
    Case #Layer3 
      Debug "Layer: 3"
  EndSelect
It is right?
User avatar
Thorsten1867
Addict
Addict
Posts: 1366
Joined: Wed Aug 24, 2005 4:02 pm
Location: Germany

Re: Reading MP3 headers

Post by Thorsten1867 »

No! :shock:
Translated with http://www.DeepL.com/Translator

Download of PureBasic - Modules
Download of PureBasic - Programs

[Windows 11 x64] [PB V5.7x]
Post Reply