Estrarre informazioni e TAG da un file MP3 con le sole funzioni di Gambas

Da Gambas-it.org - Wikipedia.

E' possibile estrarre informazioni generali e TAG da un file MP3 con le sole funzioni di Gambas.

Un possibile codice è il seguente:

Private initium As Short


Public Sub Main()

Dim fl, s, ver_mp3, layer, prot, medio, circa As String
Dim j, frequenza, num_frame, brVar, totBR, durata1, durata2, durata As Integer
Dim vB, lB, pB, brB, frB As Byte
Dim secundum, tertium, bitrate, cpf As Short
Dim tags As String[]


 fl = "/percorso/del/file.mp3"
 
 Print "File audio mp3: '"; File.Name(fl)

 s = File.Load(fl)
 Print "\nDimensione: "; Len(s); " byte"
 
 initium = 1
 
 tags = EstraeTag(s)

 For j = initium To Len(s) - 1

   If (Asc(s, j) = 255) And (Asc(s, j + 1) > 241) And (Asc(s, j + 2) > 15) Then

   secundum = Asc(s, j + 1)
   tertium = Asc(s, j + 2)

' Individua 2° byte dell'header per estrarre le seguenti informazioni generali sul file mp3:
' - vesione MPEG;
' - layer;
' - protezione.
' I primi 3 bit più significativi (tutti posti a 1) appartengono con quelli del 1° byte all'identificazione dell'header.
 
' Viene individuata la versione del file mp3:
   vB = Asc(s, j + 1) And 24
   Select Case vB
     Case 0
       ver_mp3 = "2.5"
     Case 16
       ver_mp3 = "2"
     Case 24
       ver_mp3 = "1"
   End Select


' Viene individuato il "Layer" del file mp3:
   lB = Asc(s, j + 1) And 6
   Select Case lB
     Case 2
       layer = "III"
     Case 4
       layer = "II"
     Case 6
       layer = "I"
   End Select
   

' Viene verificata la Protezione:
   pB = Asc(s, j + 1) And 1
   Select Case pB
     Case 0
       prot = "Non protetto"
     Case 1
       prot = "Protetto"
   End Select
   
   Print "Versione MPEG = "; ver_mp3, "Layer = "; layer, "Protezione CRC = "; prot


' Si analizza, quindi, il terzo byte per estrarre le seguenti informazioni generali sul file mp3:
' - bitrate;
' - frequenza di campionamento;
' Tali informazioni sono condizionate dalla versione e dal layer del file MPEG.
   brB = Asc(s, j + 2) And 240
   bitrate = EstraeBitRate(ver_mp3, layer, brB)

   frB = Asc(s, j + 2) And 12
   frequenza = EstraeFrequenza(ver_mp3, frB)

     Exit

   Endif

 Next


   For j = 1 To Len(s) - 2
     If (Asc(s, j) = 255) And (Asc(s, j + 1) = secundum) Then Inc num_frame
     If (Asc(s, j) = 255) And (Asc(s, j + 1) = secundum) And (Asc(s, j + 2) <> tertium) Then
       Inc brVar
       brB = Asc(s, j + 2) And 240
       totBR += EstraeBitRate(ver_mp3, layer, brB)
     Endif
   Next


   If brVar > num_frame * 0.1 Then

     Select Case layer
       Case "I"
         cpf = 384
       Case "II"
         cpf = 1152
       Case "III"
         If ver_mp3 = "1" Then
           cpf = 1152
         Else
           cpf = 576
         Endif
     End Select
     durata1 = Fix((num_frame * cpf / frequenza) * 1000)
     bitrate = totBR / brVar
     durata2 = Fix((Len(s) / bitrate) * 8)
     durata = (durata1 + durata2) / 2
     medio = "variabile medio "
     circa = "circa "
   Else
     durata = Fix((Len(s) / bitrate) * 8)

   Endif

   Print "BitRate " & medio & "= "; bitrate
   Print "Frequenza = hz "; frequenza
   Print "Durata " & circa & "= "; Date(0, 0, 0, 0, 0, 0, durata)
 
   Print "\n== T A G =="

   If tags.Count > 0 Then
     For j = 0 To tags.Max
       Print tags[j]
     Next
   Else
       Print "Assenti !"
   Endif

End



Private Function EstraeBitRate(Vmpeg As String, layB As String, bitB As Byte) As Short
 
   Dim velCamp As Short
 
   If Vmpeg = "1" Then   ' Nel caso di Mpeg vers. 1
   
     Select Case layB   ' Verifica il Layer
       Case "I"
         Select Case bitB
           Case 16
             velCamp = 32
           Case 32
             velCamp = 64
           Case 48
             velCamp = 96
           Case 64
             velCamp = 128
           Case 80
             velCamp = 160
           Case 96
             velCamp = 192
           Case 112
             velCamp = 224
           Case 128
             velCamp = 256
           Case 144
             velCamp = 288
           Case 160
             velCamp = 320
           Case 176
             velCamp = 352
           Case 192
             velCamp = 384
           Case 208
             velCamp = 416
           Case 224
             velCamp = 448
         End Select
       Case "II"
         Select Case bitB
           Case 16
             velCamp = 32
           Case 32
             velCamp = 48
           Case 48
             velCamp = 56
           Case 64
             velCamp = 64
           Case 80
             velCamp = 80
           Case 96
             velCamp = 96
           Case 112
             velCamp = 112
           Case 128
             velCamp = 128
           Case 144
             velCamp = 160
           Case 160
             velCamp = 192
           Case 176
             velCamp = 224
           Case 192
             velCamp = 256
           Case 208
             velCamp = 320
           Case 224
             velCamp = 384
         End Select
       Case "III"
         Select Case bitB
           Case 16
             velCamp = 32
           Case 32
             velCamp = 40
           Case 48
             velCamp = 48
           Case 64
             velCamp = 56
           Case 80
             velCamp = 64
           Case 96
             velCamp = 80
           Case 112
             velCamp = 96
           Case 128
             velCamp = 112
           Case 144
             velCamp = 128
           Case 160
             velCamp = 160
           Case 176
             velCamp = 192
           Case 192
             velCamp = 224
           Case 208
             velCamp = 256
           Case 224
             velCamp = 320
         End Select
     End Select
     
   Else
     
     Select Case layB    ' Verifica il Layer
       Case "I"
         Select Case bitB
           Case 16
             velCamp = 32
           Case 32
             velCamp = 48
           Case 48
             velCamp = 56
           Case 64
             velCamp = 64
           Case 80
             velCamp = 80
           Case 96
             velCamp = 96
           Case 112
             velCamp = 112
           Case 128
             velCamp = 128
           Case 144
             velCamp = 144
           Case 160
             velCamp = 160
           Case 176
             velCamp = 176
           Case 192
             velCamp = 192
           Case 208
             velCamp = 224
           Case 224
             velCamp = 256
         End Select
       Case "II" To "III"
         Select Case bitB
           Case 16
             velCamp = 8
           Case 32
             velCamp = 16
           Case 48
             velCamp = 24
           Case 64
             velCamp = 32
           Case 80
             velCamp = 40
           Case 96
             velCamp = 48
           Case 112
             velCamp = 56
           Case 128
             velCamp = 64
           Case 144
             velCamp = 80
           Case 160
             velCamp = 96
           Case 176
             velCamp = 112
           Case 192
             velCamp = 128
           Case 208
             velCamp = 144
           Case 224
             velCamp = 320
         End Select
     End Select
     
   Endif
   
   Return velCamp
 
End


Private Function EstraeFrequenza(Vmpeg As String, fre As Byte) As Integer
 
 Dim frq As Integer
 
 
   Select Case Vmpeg
     Case "1"         '  Nel caso di Mpeg vers. 1
       Select Case fre
         Case 0
           frq = 44100
         Case 4
           frq = 48000
         Case 8
           frq = 32000
       End Select
     Case "2"         ' Nel caso di Mpeg vers. 2
       Select Case fre
         Case 0
           frq = 22050
         Case 4
           frq = 24000
         Case 8
           frq = 16000
       End Select
     Case "2.5"       ' Nel caso di Mpeg vers. 2.5
       Select Case fre
         Case 0
           frq = 11025
         Case 4
           frq = 12000
         Case 8
           frq = 8000
       End Select
   End Select

   Return frq
   
End


Private Function EstraeTag(s As String) As String[]
 
 Dim ordo As New Integer[]
 Dim j, rm, k, a As Integer
 Dim tag As String
 Dim tagg As New String[]
 
 
   With ordo
     .add(InStr(s, "TALB"))  
     .add(InStr(s, "TCOM"))  
     .add(InStr(s, "TCOP"))  
     .add(InStr(s, "TDAT"))  
     .add(InStr(s, "TDEN"))  
     .add(InStr(s, "TDLY"))  
     .add(InStr(s, "TDRC"))  
     .add(InStr(s, "TENC"))  
     .add(InStr(s, "TFLP"))  
     .add(InStr(s, "TIT1"))  
     .add(InStr(s, "TIT2"))  
     .add(InStr(s, "TIT3"))  
     .add(InStr(s, "TKEY"))  
     .add(InStr(s, "TLAN"))  
     .add(InStr(s, "TLEN"))  
     .add(InStr(s, "TMCL"))  
     .add(InStr(s, "TMED"))  
     .add(InStr(s, "TOAL"))  
     .add(InStr(s, "TOFN"))  
     .add(InStr(s, "TOLY"))  
     .add(InStr(s, "TOPE"))  
     .add(InStr(s, "TORY"))  
     .add(InStr(s, "TOWN"))  
     .add(InStr(s, "TPE1"))  
     .add(InStr(s, "TPE2"))  
     .add(InStr(s, "TPE3"))  
     .add(InStr(s, "TPE4"))  
     .add(InStr(s, "TPUB"))  
     .add(InStr(s, "TCON"))  
     .add(InStr(s, "TDRC"))  
     .add(InStr(s, "TRCK"))  
     .add(InStr(s, "TRDA"))  
     .add(InStr(s, "TRSN"))  
     .add(InStr(s, "TRSO"))  
     .add(InStr(s, "TSRC"))  
     .add(InStr(s, "TSSE"))  
     .add(InStr(s, "TYER"))  
     .add(InStr(s, "TXXX"))  
     .add(RInStr(s, "TXXX"))  
     .add(InStr(s, "COMM"))  
     .add(InStr(s, "PRIV"))  
     .add(RInStr(s, "PRIV"))  
     .add(RInStr(s, "WXXX")) 
   End With

  If ordo.Count > 0 Then    ' Se è stato trovato almeno un Tag

   While j < ordo.Count
     If ordo[j] = 0 Then
       ordo.Remove(j)
       Inc rm
       Dec j
     Endif
     Inc j
   Wend

  
   ordo.Sort()

   
   For j = 0 To ordo.Max

     k = ordo[j]

     While k < ordo[ordo.max] + 24
       
       If j < ordo.Max Then
' Verifica che il carattere ASCII sia una lettera o un numero oppure un segno di punteggiatura:
         If (k < ordo[j + 1]) And ((IsLetter(Mid(s, k, 1))) Or (IsDigit(Mid(s, k, 1))) Or (IsPunct(Mid(s, k, 1)))) Then
           tag &= Mid(s, k, 1)
         Else
           tag &= " "
         Endif
       Else
' Verifica che il carattere ASCII sia una lettera o un numero oppure un segno di punteggiatura:
         If ((IsLetter(Mid(s, k, 1))) Or (IsDigit(Mid(s, k, 1))) Or (IsPunct(Mid(s, k, 1)))) Then
           tag &= Mid(s, k, 1)
         Else
           tag &= " "
         Endif

       Endif
       
       Inc k
      
     Wend
     
     tagg.Add(tag)
     tag = Null
   
' Cerca di evitare di leggere l'header del 1° frame all'interno del gruppo dei Tag:
     For a = 0 To ordo.Max - 1 
       If ordo[a + 1] - ordo[a] > 68 Then initium = ordo[a] + 24
     Next

   Next
   
   Endif

   Return tagg
 
End


Riferimenti

[1] La struttura di un file MPEG