Differenze tra le versioni di "Estrarre informazioni generali da un file audio flac"

Da Gambas-it.org - Wikipedia.
 
(7 versioni intermedie di uno stesso utente non sono mostrate)
Riga 1: Riga 1:
Il file audio FLAC (''Free Lossless Audio Codec'' è un formato audio simile a MP3, dunque compresso, ma senza perdita di dati, il che significa senza alcuna perdita di qualità.
+
Il file audio FLAC (''Free Lossless Audio Codec'' ) è un formato audio simile a MP3, dunque compresso, ma senza perdita di dati, il che significa senza alcuna perdita di qualità.
  
Il file ha una struttura complessa formata da blocchi e sottoblocchi omogenei di dati. Nel blocco chiamato ''METADATA_BLOCK_STREAMINFO'' sono contenute alcune informazioni di carattere generale del file medesimo che possono ovviamente essere estratte. In questa pagina mostreremo come estrarre tali informazioni dei dati da quel blocco, ed in particolare la frequenza di campionamento, il numero di canali, la risoluzione in bit del campionamento e il numero totale dei campioni.
+
Il file ha una struttura complessa formata da blocchi e sotto-blocchi omogenei di dati. Nel blocco chiamato ''METADATA_BLOCK_STREAMINFO'' sono contenute alcune informazioni di carattere generale del file medesimo che possono ovviamente essere estratte. In questa pagina mostreremo come estrarre tali informazioni dei dati da quel blocco, ed in particolare la frequenza di campionamento, il numero di canali, la risoluzione in bit del campionamento e il numero totale dei campioni.
  
 
Va preliminarmente detto che tali informazioni sono contenute all'interno di 8 byte successivi e contigui a cominciare dal byte di indice 18 (quindi dal 19° byte del file ''flac''). Ogni informazione è indicata da un certo numero di bit - all'interno di quegli otto byte - fino alla concorrenza di 64 bit totali (8 byte). Esse sono così disposte a cominciare, come s'è detto, dal primo bit del byte di indice 18:
 
Va preliminarmente detto che tali informazioni sono contenute all'interno di 8 byte successivi e contigui a cominciare dal byte di indice 18 (quindi dal 19° byte del file ''flac''). Ogni informazione è indicata da un certo numero di bit - all'interno di quegli otto byte - fino alla concorrenza di 64 bit totali (8 byte). Esse sono così disposte a cominciare, come s'è detto, dal primo bit del byte di indice 18:
 
* i primi 20 bit per memorizzare il valore relativo alla ''frequenza di campionamento'';
 
* i primi 20 bit per memorizzare il valore relativo alla ''frequenza di campionamento'';
* i successivi 3 bit per indicare il numero di canali (al valore ottenuto va sempre aggiunta un'unità);
+
* i successivi 3 bit per indicare il numero di canali (<SPAN Style="text-decoration:underline">al valore ottenuto va sempre aggiunta un'unità</span>);
* i successivi 5 bit per indicare la ''risoluzione in bit del campionamento'' (al valore ottenuto va sempre aggiunta un'unità);
+
* i successivi 5 bit per indicare la ''risoluzione in bit del campionamento'' (<SPAN Style="text-decoration:underline">al valore ottenuto va sempre aggiunta un'unità</span>);
 
* i successivi 36 bit per indicare il numero totale dei frame (campioni audio coerenti).
 
* i successivi 36 bit per indicare il numero totale dei frame (campioni audio coerenti).
 
Quest'ultima informazione è importante per ottenere in rapporto alla frequenza di campionamento la durata, espressa in secondi, dell'audio memorizzato nel file ''flac'', secondo la formula:
 
Quest'ultima informazione è importante per ottenere in rapporto alla frequenza di campionamento la durata, espressa in secondi, dell'audio memorizzato nel file ''flac'', secondo la formula:
 
  durata_in_secondi = numero_totale_frame / frequenza_campionamento
 
  durata_in_secondi = numero_totale_frame / frequenza_campionamento
Mostriamo un esempio visivo della disposizione nei 64 bit di ciascuna delle suddette informazioni relative ad un file ''flac'' avente frequenza di campionamento a hz 44100, 2 canali, risoluzione 16-bit e numero 431078 frame:
+
Mostriamo un esempio visivo della disposizione nei 64 bit di ciascuna delle suddette informazioni relative ad un file ''flac'' avente:
 +
<FONT Color=Red>frequenza di campionamento a hz 44100</font>
 +
<FONT Color=blue>2 canali</font>
 +
<FONT Color=orange>risoluzione 16-bit</font>
 +
<FONT Color=green>431078 byte frame audio</font>
 +
 +
in questo caso la rappresentazione in bit sarà:
 
  <FONT Color=Red>00001010110001000100</font><FONT Color=blue>001</font><FONT Color=orange>01111</font><FONT Color=green>000000000000010000011100011100000100</font>
 
  <FONT Color=Red>00001010110001000100</font><FONT Color=blue>001</font><FONT Color=orange>01111</font><FONT Color=green>000000000000010000011100011100000100</font>
 
  
 
==Estrarre le informazioni mediante le sole risorse di Gambas==
 
==Estrarre le informazioni mediante le sole risorse di Gambas==
Riga 26: Riga 31:
 
   Dim l, frame_totali, frequenza As Long
 
   Dim l, frame_totali, frequenza As Long
 
    
 
    
    fileFlac = " <FONT Color=gray>''/percorso/del/file.flac''</font>"
+
  fileFlac = "<FONT Color=gray>''/percorso/del/file.flac''</font>"
    Print "File 'Flac':  "; fileFlac
+
  Print "File 'Flac':  "; fileFlac
 +
 
 +
  fl = Open fileFlac For Read
 +
  Print "Dimensione:  "; Lof(fl); " byte" 
 
    
 
    
    fl = Open fileFlac For Read
 
   
 
 
  <FONT Color=gray>' ''Calcola la frequenza di campionamento:''</font>
 
  <FONT Color=gray>' ''Calcola la frequenza di campionamento:''</font>
    b = SizeOf(gb.Integer)
+
  b = SizeOf(gb.Integer)
    Seek #fl, 18
+
  Seek #fl, 18
     Do
+
  Repeat
      Read #fl, c
+
     Read #fl, c
      i = (i * CInt(2 ^ 8)) Or c
+
    i = (i * CInt(2 ^ 8)) Or c
      Dec b
+
    Dec b
    Loop Until b = 0
+
  Until b == 0
    frequenza = Shr(i, 12)
+
  frequenza = Shr(i, 12)
    Print "Frequenza:    "; frequenza; " Hertz"
+
  Print "Frequenza:    "; frequenza; " Hertz"
 
      
 
      
 
  <FONT Color=gray>' ''Calcola i canali:''</font>
 
  <FONT Color=gray>' ''Calcola i canali:''</font>
    sposta = Shr(i, 9)
+
  sposta = Shr(i, 9)
    canali = CByte(sposta And 7) + 1
+
  canali = CByte(sposta And 7) + 1
    Print "Canali:      "; canali
+
  Print "Canali:      "; canali
 
      
 
      
 
  <FONT Color=gray>' ''Calcola la risoluzione in bit:''</font>
 
  <FONT Color=gray>' ''Calcola la risoluzione in bit:''</font>
    sposta = Shr(i, 4)
+
  sposta = Shr(i, 4)
    bit = CByte(sposta And 31) + 1
+
  bit = CByte(sposta And 31) + 1
    Print "Risoluzione:  "; bit; "-bit"
+
  Print "Risoluzione:  "; bit; "-bit"
 
      
 
      
 
  <FONT Color=gray>' ''Calcola i frame totali:''</font>
 
  <FONT Color=gray>' ''Calcola i frame totali:''</font>
    b = 8
+
  b = 8
    Seek #fl, 18
+
  Seek #fl, 18
     Do
+
  Repeat
      Read #fl, c
+
     Read #fl, c
      l = (l * CInt(2 ^ 8)) Or c
+
    l = (l * CInt(2 ^ 8)) Or c
      Dec b
+
    Dec b
    Loop Until b = 0
+
  Until b == 0
    frame_totali = l And CLong(&FFFFFFFFF)
+
  frame_totali = l And CLong(&FFFFFFFFF)
    Print "Frame totali: "; frame_totali
+
  Print "Frame totali: "; frame_totali
 
          
 
          
 
  <FONT Color=gray>' ''Calcola la durata dell'audio:''</font>
 
  <FONT Color=gray>' ''Calcola la durata dell'audio:''</font>
    Print "Durata:      "; CStr(Date(0, 0, 0, 0, 0, 0, (frame_totali / frequenza) * 1000))
+
  Print "Durata:      "; Time(0, 0, 0, (frame_totali / frequenza) * 1000)
 
      
 
      
    fl.Close
+
  fl.Close
 
    
 
    
 
  '''End'''
 
  '''End'''
Riga 122: Riga 128:
 
   Dim campioni As Long
 
   Dim campioni As Long
 
      
 
      
    fileFlac = "<FONT Color=gray>''/percorso/del/file.flac''</font>"
+
  fileFlac = "<FONT Color=gray>''/percorso/del/file.flac''</font>"
 
      
 
      
    deco = FLAC__stream_decoder_new()
+
  deco = FLAC__stream_decoder_new()
    If deco = 0 Then Error.Raise("Impossibile inizializzare la libreria 'Flac' !")
+
  If deco = 0 Then Error.Raise("Impossibile inizializzare la libreria 'Flac' !")
 
      
 
      
    status = FLAC__stream_decoder_init_file(deco, fileFlac, write_callback, metadata_callback, error_callback, fout)
+
  status = FLAC__stream_decoder_init_file(deco, fileFlac, write_callback, metadata_callback, error_callback, fout)
    If status <> FLAC__STREAM_DECODER_INIT_STATUS_OK Then Error.Raise("Impossibile inizializzare il decodificatore !")
+
  If status <> FLAC__STREAM_DECODER_INIT_STATUS_OK Then Error.Raise("Impossibile inizializzare il decodificatore !")
 
      
 
      
    bo = FLAC__stream_decoder_process_until_end_of_stream(deco)
+
  bo = FLAC__stream_decoder_process_until_end_of_stream(deco)
    If bo = False Then Error.Raise("Decodifica fallita !")
+
  If bo = False Then Error.Raise("Decodifica fallita !")
 
      
 
      
    frequenza = FLAC__stream_decoder_get_sample_rate(deco)
+
  frequenza = FLAC__stream_decoder_get_sample_rate(deco)
    Print "Frequenza:      "; frequenza; " Hertz"
+
  Print "Frequenza:      "; frequenza; " Hertz"
    canali = FLAC__stream_decoder_get_channels(deco)
+
  canali = FLAC__stream_decoder_get_channels(deco)
    Print "Numero canali:  "; canali
+
  Print "Numero canali:  "; canali
    bit = FLAC__stream_decoder_get_bits_per_sample(deco)
+
  bit = FLAC__stream_decoder_get_bits_per_sample(deco)
    Print "Risoluzione:    "; bit; "-bit"
+
  Print "Risoluzione:    "; bit; "-bit"
    campioni = FLAC__stream_decoder_get_total_samples(deco)
+
  campioni = FLAC__stream_decoder_get_total_samples(deco)
    Print "Totale Campioni: "; campioni
+
  Print "Totale Campioni: "; campioni
 
      
 
      
    Print "Durata audio:    "; CStr(Date(0, 0, 0, 0, 0, 0, (campioni / frequenza) * 1000))
+
  Print "Durata audio:    "; CStr(Time(0, 0, 0, (campioni / frequenza) * 1000))
 
      
 
      
    FLAC__stream_decoder_delete(deco)
+
  FLAC__stream_decoder_delete(deco)
 
      
 
      
 
  '''End'''
 
  '''End'''
Riga 160: Riga 166:
 
    
 
    
 
  '''End'''
 
  '''End'''
 
  
  
  
 
=Riferimenti=
 
=Riferimenti=
* https://xiph.org/flac/index.html
+
* https://xiph.org/flac/format.html#stream

Versione attuale delle 20:08, 16 nov 2021

Il file audio FLAC (Free Lossless Audio Codec ) è un formato audio simile a MP3, dunque compresso, ma senza perdita di dati, il che significa senza alcuna perdita di qualità.

Il file ha una struttura complessa formata da blocchi e sotto-blocchi omogenei di dati. Nel blocco chiamato METADATA_BLOCK_STREAMINFO sono contenute alcune informazioni di carattere generale del file medesimo che possono ovviamente essere estratte. In questa pagina mostreremo come estrarre tali informazioni dei dati da quel blocco, ed in particolare la frequenza di campionamento, il numero di canali, la risoluzione in bit del campionamento e il numero totale dei campioni.

Va preliminarmente detto che tali informazioni sono contenute all'interno di 8 byte successivi e contigui a cominciare dal byte di indice 18 (quindi dal 19° byte del file flac). Ogni informazione è indicata da un certo numero di bit - all'interno di quegli otto byte - fino alla concorrenza di 64 bit totali (8 byte). Esse sono così disposte a cominciare, come s'è detto, dal primo bit del byte di indice 18:

  • i primi 20 bit per memorizzare il valore relativo alla frequenza di campionamento;
  • i successivi 3 bit per indicare il numero di canali (al valore ottenuto va sempre aggiunta un'unità);
  • i successivi 5 bit per indicare la risoluzione in bit del campionamento (al valore ottenuto va sempre aggiunta un'unità);
  • i successivi 36 bit per indicare il numero totale dei frame (campioni audio coerenti).

Quest'ultima informazione è importante per ottenere in rapporto alla frequenza di campionamento la durata, espressa in secondi, dell'audio memorizzato nel file flac, secondo la formula:

durata_in_secondi = numero_totale_frame / frequenza_campionamento

Mostriamo un esempio visivo della disposizione nei 64 bit di ciascuna delle suddette informazioni relative ad un file flac avente:

frequenza di campionamento a hz 44100
2 canali
risoluzione 16-bit
431078 byte frame audio

in questo caso la rappresentazione in bit sarà:
0000101011000100010000101111000000000000010000011100011100000100

Estrarre le informazioni mediante le sole risorse di Gambas

Questa modalità prevede l'estrazione delle predette informazioni relative ai dati del file mediante le sole risorse di Gambas.

Mostriamo un esempio:

Public Sub Main()
 
 Dim fileFlac As String
 Dim fl As File
 Dim i, sposta As Integer
 Dim b, c, canali, bit As Byte
 Dim l, frame_totali, frequenza As Long
 
 fileFlac = "/percorso/del/file.flac"
 Print "File 'Flac':  "; fileFlac
 
 fl = Open fileFlac For Read
 Print "Dimensione:   "; Lof(fl); " byte"  
 
' Calcola la frequenza di campionamento:
 b = SizeOf(gb.Integer)
 Seek #fl, 18
 Repeat
   Read #fl, c
   i = (i * CInt(2 ^ 8)) Or c
   Dec b
 Until b == 0
 frequenza = Shr(i, 12)
 Print "Frequenza:    "; frequenza; " Hertz"
   
' Calcola i canali:
 sposta = Shr(i, 9)
 canali = CByte(sposta And 7) + 1
 Print "Canali:       "; canali
   
' Calcola la risoluzione in bit:
 sposta = Shr(i, 4)
 bit = CByte(sposta And 31) + 1
 Print "Risoluzione:  "; bit; "-bit"
   
' Calcola i frame totali:
 b = 8
 Seek #fl, 18
 Repeat
   Read #fl, c
   l = (l * CInt(2 ^ 8)) Or c
   Dec b
 Until b == 0
 frame_totali = l And CLong(&FFFFFFFFF)
 Print "Frame totali: "; frame_totali
       
' Calcola la durata dell'audio:
 Print "Durata:       "; Time(0, 0, 0, (frame_totali / frequenza) * 1000)
   
 fl.Close
  
End


Estrarre le informazioni mediante le funzioni esterne di Libflac

In quest'altro caso si farà uso di alcune risorse della specifica libreria dinamica condivisa "libflac.so.8.3.0", che dovrà essere installata nel sistema ed opportunamente richiamata in Gambas.

Mostriamo un esempio pratico, sottolineando che è necessario prevedere, seppur vuote, le tre funzioni di Callback presenti in questo esempio.

Library "libFLAC:8.3.0"

Private Const FLAC__STREAM_DECODER_INIT_STATUS_OK As Integer = 0

' FLAC__StreamDecoder *FLAC__stream_decoder_new(void)
' Create a new stream decoder instance.
Private Extern FLAC__stream_decoder_new() As Pointer

' FLAC__StreamDecoderInitStatus FLAC__stream_decoder_init_file(FLAC__StreamDecoder *decoder, const char *filename, FLAC__StreamDecoderWriteCallback write_callback, FLAC__StreamDecoderMetadataCallback metadata_callback, FLAC__StreamDecoderErrorCallback error_callback, void *client_data)
' Initialize the decoder instance to decode native FLAC files.
Private Extern FLAC__stream_decoder_init_file(decoder As Pointer, filename As String, write_callback As Pointer, metadata_callback As Pointer, error_callback As Pointer, client_data As Pointer) As Integer

' FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder)
' Decode until the end of the stream.
Private Extern FLAC__stream_decoder_process_until_end_of_stream(decoder As Pointer) As Boolean

' unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder)
' Get the current sample rate in Hz of the stream being decoded.
Private Extern FLAC__stream_decoder_get_sample_rate(decoder As Pointer) As Integer

' unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder)
' Get the current number of channels in the stream being decoded.
Private Extern FLAC__stream_decoder_get_channels(decoder As Pointer) As Byte

' unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder)
' Get the current sample resolution in the stream being decoded.
Private Extern FLAC__stream_decoder_get_bits_per_sample(decoder As Pointer) As Byte

' FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder)
' Get the total number of samples in the stream being decoded.
Private Extern FLAC__stream_decoder_get_total_samples(decoder As Pointer) As Long

' void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)
' Free a decoder instance.
Private Extern FLAC__stream_decoder_delete(decoder As Pointer)


Public Sub Main()

 Dim deco, fout As Pointer
 Dim fileFlac As String
 Dim status, frequenza As Integer
 Dim canali, bit As Byte
 Dim bo As Boolean
 Dim campioni As Long
   
 fileFlac = "/percorso/del/file.flac"
   
 deco = FLAC__stream_decoder_new()
 If deco = 0 Then Error.Raise("Impossibile inizializzare la libreria 'Flac' !")
   
 status = FLAC__stream_decoder_init_file(deco, fileFlac, write_callback, metadata_callback, error_callback, fout)
 If status <> FLAC__STREAM_DECODER_INIT_STATUS_OK Then Error.Raise("Impossibile inizializzare il decodificatore !")
   
 bo = FLAC__stream_decoder_process_until_end_of_stream(deco)
 If bo = False Then Error.Raise("Decodifica fallita !")
   
 frequenza = FLAC__stream_decoder_get_sample_rate(deco)
 Print "Frequenza:       "; frequenza; " Hertz"
 canali = FLAC__stream_decoder_get_channels(deco)
 Print "Numero canali:   "; canali
 bit = FLAC__stream_decoder_get_bits_per_sample(deco)
 Print "Risoluzione:     "; bit; "-bit"
 campioni = FLAC__stream_decoder_get_total_samples(deco)
 Print "Totale Campioni: "; campioni
   
 Print "Durata audio:    "; CStr(Time(0, 0, 0, (campioni / frequenza) * 1000))
   
 FLAC__stream_decoder_delete(deco)
   
End


Private Function write_callback(decoder As Pointer, frame As Pointer, buffer As Pointer, client_data As Pointer)
 
End

Private Function metadata_callback(decoder As Pointer, metadata As Pointer, client_data As Pointer)

End

Private Function error_callback(decoder As Pointer, errori As Integer, client_data As Pointer)
 
End


Riferimenti