Differenze tra le versioni di "Estrarre informazioni generali da un file audio flac"
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 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. | ||
− | + | Va preliminarmente detto che tali informazioni sono contenute all'interno di 8 byte, scritti in ''big-endian'', 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 | ||
+ | ==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: | |
− | =Estrarre le informazioni mediante le funzioni esterne di Libflac= | + | ==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 e 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 | ||
+ | |||
+ | <FONT Color=gray>' ''FLAC__StreamDecoder *FLAC__stream_decoder_new(void)'' | ||
+ | ' ''Create a new stream decoder instance.''</font> | ||
+ | Private Extern FLAC__stream_decoder_new() As Pointer | ||
+ | |||
+ | <FONT Color=gray size=1>' ''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.''</font> | ||
+ | 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 | ||
+ | |||
+ | <FONT Color=gray>' ''FLAC__bool FLAC__stream_decoder_process_until_end_of_stream(FLAC__StreamDecoder *decoder)'' | ||
+ | ' ''Decode until the end of the stream.''</font> | ||
+ | Private Extern FLAC__stream_decoder_process_until_end_of_stream(decoder As Pointer) As Boolean | ||
+ | |||
+ | <FONT Color=gray>' ''unsigned FLAC__stream_decoder_get_sample_rate(const FLAC__StreamDecoder *decoder)'' | ||
+ | ' ''Get the current sample rate in Hz of the stream being decoded.''</font> | ||
+ | Private Extern FLAC__stream_decoder_get_sample_rate(decoder As Pointer) As Integer | ||
+ | |||
+ | <FONT Color=gray>' ''unsigned FLAC__stream_decoder_get_channels(const FLAC__StreamDecoder *decoder)'' | ||
+ | ' ''Get the current number of channels in the stream being decoded.''</font> | ||
+ | Private Extern FLAC__stream_decoder_get_channels(decoder As Pointer) As Byte | ||
+ | |||
+ | <FONT Color=gray>' ''unsigned FLAC__stream_decoder_get_bits_per_sample(const FLAC__StreamDecoder *decoder)'' | ||
+ | ' ''Get the current sample resolution in the stream being decoded.''</font> | ||
+ | Private Extern FLAC__stream_decoder_get_bits_per_sample(decoder As Pointer) As Byte | ||
+ | |||
+ | <FONT Color=gray>' ''FLAC__uint64 FLAC__stream_decoder_get_total_samples(const FLAC__StreamDecoder *decoder)'' | ||
+ | ' ''Get the total number of samples in the stream being decoded.''</font> | ||
+ | Private Extern FLAC__stream_decoder_get_total_samples(decoder As Pointer) As Long | ||
+ | |||
+ | <FONT Color=gray>' ''void FLAC__stream_decoder_delete(FLAC__StreamDecoder *decoder)'' | ||
+ | ' ''Free a decoder instance.''</font> | ||
+ | Private Extern FLAC__stream_decoder_delete(decoder As Pointer) | ||
+ | |||
+ | |||
+ | '''Public''' Sub Main() | ||
+ | |||
Dim deco, fout As Pointer | Dim deco, fout As Pointer | ||
Dim fileFlac As String | Dim fileFlac As String | ||
Riga 57: | Riga 69: | ||
Dim bo As Boolean | Dim bo As Boolean | ||
Dim campioni As Long | Dim campioni As Long | ||
− | + | ||
− | fileFlac = "/percorso/del/ | + | 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' !") | ||
Riga 65: | Riga 77: | ||
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 !") | ||
Riga 77: | Riga 89: | ||
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(Date(0, 0, 0, 0, 0, 0, (campioni / frequenza) * 1000)) | ||
− | + | ||
FLAC__stream_decoder_delete(deco) | FLAC__stream_decoder_delete(deco) | ||
− | + | ||
− | End | + | '''End''' |
− | + | ||
− | + | ||
− | Private Function write_callback(decoder As Pointer, frame As Pointer, buffer As Pointer, client_data As Pointer) | + | '''Private''' Function write_callback(decoder As Pointer, frame As Pointer, buffer As Pointer, client_data As Pointer) |
− | End | + | '''End''' |
− | + | ||
− | Private Function metadata_callback(decoder As Pointer, metadata As Pointer, client_data As Pointer) | + | '''Private''' Function metadata_callback(decoder As Pointer, metadata As Pointer, client_data As Pointer) |
− | + | ||
− | End | + | '''End''' |
− | + | ||
− | Private Function error_callback(decoder As Pointer, errori As Integer, client_data As Pointer) | + | '''Private''' Function error_callback(decoder As Pointer, errori As Integer, client_data As Pointer) |
− | End | + | '''End''' |
Versione delle 01:46, 27 set 2016
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.
Va preliminarmente detto che tali informazioni sono contenute all'interno di 8 byte, scritti in big-endian, 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
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:
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 e 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(Date(0, 0, 0, 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
Pagina in costruzione !