Differenze tra le versioni di "Estrarre informazioni da un file .wav"
(Una versione intermedia di uno stesso utente non è mostrata) | |||
Riga 77: | Riga 77: | ||
− | + | Public Sub Main() | |
− | + | Dim fileWAV As String | |
− | + | Dim wav As File | |
− | + | Dim hw As New Header_Wav | |
− | fileWAV = "<FONT color= | + | fileWAV = "<FONT color=darkgreen>''/percorso/del/file.wav''</font>" |
wav = Open fileWAV For Read | wav = Open fileWAV For Read | ||
Riga 106: | Riga 106: | ||
wav.Close | wav.Close | ||
− | + | End | |
− | + | Private Function legge_stringa(fl As File) As String | |
− | + | Dim s As String | |
Read #fl, s, 4 | Read #fl, s, 4 | ||
Riga 117: | Riga 117: | ||
Return s | Return s | ||
− | + | End | |
− | + | Private Function legge_intero(fl As File) As Integer | |
− | + | Dim i As Integer | |
Read #fl, i | Read #fl, i | ||
Riga 128: | Riga 128: | ||
Return i | Return i | ||
− | + | End | |
− | + | Private Function legge_corto(fl As File) As Short | |
− | + | Dim sh As Short | |
Read #fl, sh | Read #fl, sh | ||
Riga 139: | Riga 139: | ||
Return sh | Return sh | ||
− | + | End | |
====Leggendo e gestendo il file WAV come ''stringa''==== | ====Leggendo e gestendo il file WAV come ''stringa''==== | ||
In questo caso leggeremo e gestiremo l'intero file WAV come una ''stringa''. | In questo caso leggeremo e gestiremo l'intero file WAV come una ''stringa''. | ||
− | + | Public Sub Main() | |
− | + | Dim per, s, dati_grezzi As String | |
− | + | Dim d, i, campionamento, formato, durata As Integer | |
− | + | Dim canali, bit As Short | |
<FONT Color=gray>' '''''Estrae alcune informazioni sul file:'''''</font> | <FONT Color=gray>' '''''Estrae alcune informazioni sul file:'''''</font> | ||
− | + | ||
− | per = "<FONT Color= | + | per = "<FONT Color=darkgreen>''/percorso/del/file.wav''</font>" |
Print "Percorso del file audio: "; per | Print "Percorso del file audio: "; per | ||
Riga 179: | Riga 179: | ||
dati_grezzi = Right(s, i) | dati_grezzi = Right(s, i) | ||
− | + | End | |
====Usando una variabile vettoriale di tipo ''Byte[]'' - 1==== | ====Usando una variabile vettoriale di tipo ''Byte[]'' - 1==== | ||
Potremo utilizzare un vettore di tipo ''Byte[]'' per contenere i dati del file wav: | Potremo utilizzare un vettore di tipo ''Byte[]'' per contenere i dati del file wav: | ||
− | + | Public Sub Main() | |
− | + | Dim percorsoFile As String | |
− | + | Dim fl As File | |
− | + | Dim j, b, formato, canali, risoluzione As Byte | |
− | + | Dim buf As New Byte[] | |
− | + | Dim frequenza, dimensione As Integer | |
− | + | percorsoFile = "<FONT Color=darkgreen>''/percorso/del/file.wav''</font>" | |
− | percorsoFile = "''/percorso/del/file.wav''" | ||
<FONT color=gray>' ''Carica un file audio Wav:''</font> | <FONT color=gray>' ''Carica un file audio Wav:''</font> | ||
Riga 219: | Riga 218: | ||
canali = canali Or buf[22] | canali = canali Or buf[22] | ||
Print "Numero canali = "; canali | Print "Numero canali = "; canali | ||
− | |||
<FONT color=gray>' ''Rileva la frequenza di campionamento (legge 4 byte):''</font> | <FONT color=gray>' ''Rileva la frequenza di campionamento (legge 4 byte):''</font> | ||
Riga 227: | Riga 225: | ||
frequenza = frequenza Or buf[24] | frequenza = frequenza Or buf[24] | ||
Print "Frequenza = hrz "; frequenza | Print "Frequenza = hrz "; frequenza | ||
− | |||
<FONT color=gray>' ''Rileva la risoluzione del campionamento (legge 2 byte):''</font> | <FONT color=gray>' ''Rileva la risoluzione del campionamento (legge 2 byte):''</font> | ||
Riga 233: | Riga 230: | ||
risoluzione = risoluzione Or buf[34] | risoluzione = risoluzione Or buf[34] | ||
Print "Risoluzione = "; risoluzione; " bit" | Print "Risoluzione = "; risoluzione; " bit" | ||
− | |||
<FONT color=gray>' ''Rileva la quantità dei soli dati grezzi (legge 4 byte):''</font> | <FONT color=gray>' ''Rileva la quantità dei soli dati grezzi (legge 4 byte):''</font> | ||
Riga 245: | Riga 241: | ||
Print "Durata del brano: "; Time(0, 0, 0, Fix((dimensione * 8) / (frequenza * risoluzione * canali)) * 1000) | Print "Durata del brano: "; Time(0, 0, 0, Fix((dimensione * 8) / (frequenza * risoluzione * canali)) * 1000) | ||
− | |||
fl.Close | fl.Close | ||
− | + | End | |
====Usando una variabile vettoriale di tipo ''Byte[]'' - 2==== | ====Usando una variabile vettoriale di tipo ''Byte[]'' - 2==== | ||
Per estrarre le informazioni possiamo anche utilizzare un Vettore di tipo ''Byte[]'': | Per estrarre le informazioni possiamo anche utilizzare un Vettore di tipo ''Byte[]'': | ||
− | + | Public Sub Main() | |
− | |||
− | |||
− | |||
− | |||
− | |||
+ | Dim percorsoFile As String | ||
+ | Dim fl As File | ||
+ | Dim bb As Byte[] | ||
+ | Dim solo_dati, frequenza As Integer | ||
− | percorsoFile = "''/percorso/del/file.wav''" | + | percorsoFile = "<FONT color=darkgreen>''/percorso/del/file.wav''</font>" |
fl = Open percorsoFile For Read | fl = Open percorsoFile For Read | ||
Riga 302: | Riga 296: | ||
fl.Close | fl.Close | ||
− | + | End | |
Riga 317: | Riga 311: | ||
− | + | Public Sub Main() | |
− | + | Dim fileWav As String | |
− | + | Dim datiwav As New INFOWAV | |
− | datiwav.fileWav = "''/percorso/del/file.wav''" | + | datiwav.fileWav = "<FONT color=darkgreen>''/percorso/del/file.wav''</font>" |
EstraeDatiAudio(datiwav) | EstraeDatiAudio(datiwav) | ||
− | <FONT Color=gray>' ''Mostra in console le informazioni ottenute:</font> | + | <FONT Color=gray>' ''Mostra in console le informazioni ottenute:''</font> |
With datiwav | With datiwav | ||
Print "File wav caricato: "; .fileWAV | Print "File wav caricato: "; .fileWAV | ||
Riga 335: | Riga 329: | ||
End With | End With | ||
− | + | End | |
− | + | Private Function EstraeDatiAudio(iw As INFOWAV) | |
Dim fl As File | Dim fl As File | ||
Riga 366: | Riga 360: | ||
fl.Close | fl.Close | ||
− | + | End | |
====Usando la funzione ''Seek''==== | ====Usando la funzione ''Seek''==== | ||
Potremo anche più semplicemente spostarci all'interno del flusso mediante la funzione ''Seek'': | Potremo anche più semplicemente spostarci all'interno del flusso mediante la funzione ''Seek'': | ||
− | + | Public Sub Main() | |
− | + | Dim fileWAV As String | |
− | + | Dim fl As File | |
− | + | Dim formato, canali, risoluzione As Byte | |
− | + | Dim d As Short | |
− | + | Dim frequenza, dimensione As Integer | |
− | |||
− | fileWAV = "''/percorso/del/file.wav''" | + | fileWAV = "<FONT color=darkgreen>''/percorso/del/file.wav''</font>" |
d = Instr(File.Load(fileWAV), "data") | d = Instr(File.Load(fileWAV), "data") | ||
Riga 403: | Riga 396: | ||
Read #fl, canali | Read #fl, canali | ||
Print "Numero canali = "; canali | Print "Numero canali = "; canali | ||
− | |||
<FONT color=gray>' ''Rileva la frequenza di campionamento (legge 4 byte):''</font> | <FONT color=gray>' ''Rileva la frequenza di campionamento (legge 4 byte):''</font> | ||
Riga 409: | Riga 401: | ||
Read #fl, frequenza | Read #fl, frequenza | ||
Print "Frequenza = hrz "; frequenza | Print "Frequenza = hrz "; frequenza | ||
− | + | ||
− | |||
<FONT color=gray>' ''Rileva la risoluzione del campionamento (legge 2 byte):''</font> | <FONT color=gray>' ''Rileva la risoluzione del campionamento (legge 2 byte):''</font> | ||
Seek #fl, 34 | Seek #fl, 34 | ||
Read #fl, risoluzione | Read #fl, risoluzione | ||
Print "Risoluzione = "; risoluzione; " bit" | Print "Risoluzione = "; risoluzione; " bit" | ||
− | + | ||
− | |||
<FONT color=gray>' ''Rileva la quantità dei soli dati grezzi (legge 4 byte):''</font> | <FONT color=gray>' ''Rileva la quantità dei soli dati grezzi (legge 4 byte):''</font> | ||
seek #fl, d + 3 | seek #fl, d + 3 | ||
Read #fl, dimensione | Read #fl, dimensione | ||
Print "Quantità dei soli dati grezzi = "; dimensione; " byte" | Print "Quantità dei soli dati grezzi = "; dimensione; " byte" | ||
− | + | ||
− | |||
<FONT color=gray>' ''Calcola la durata del brano audio:''</font> | <FONT color=gray>' ''Calcola la durata del brano audio:''</font> | ||
Print "Durata del brano: "; Time(0, 0, 0, Fix((dimensione * 8) / (frequenza * risoluzione * canali)) * 1000) | Print "Durata del brano: "; Time(0, 0, 0, Fix((dimensione * 8) / (frequenza * risoluzione * canali)) * 1000) | ||
− | + | ||
− | |||
fl.Close | fl.Close | ||
− | + | End | |
Riga 458: | Riga 446: | ||
End Struct | End Struct | ||
− | Public | + | Public Struct sox_format_t |
filename As Pointer | filename As Pointer | ||
signal As Struct Sox_signalinfo_t | signal As Struct Sox_signalinfo_t | ||
Riga 473: | Riga 461: | ||
− | + | Public Sub Main() | |
Dim err As Integer | Dim err As Integer | ||
Dim fileWAV As String | Dim fileWAV As String | ||
− | + | ||
− | fileWAV = "<FONT color= | + | fileWAV = "<FONT color=darkgreen>''/percorso/del/file.wav''</font>" |
err = sox_init() | err = sox_init() | ||
Riga 493: | Riga 481: | ||
End With | End With | ||
− | + | End | |
Riga 500: | Riga 488: | ||
[1] [http://it.wikipedia.org/wiki/Ordine_dei_byte Ordine dei byte] | [1] [http://it.wikipedia.org/wiki/Ordine_dei_byte Ordine dei byte] | ||
− | [2] Vedi anche la seguente pagina: [[ | + | [2] Vedi anche la seguente pagina: [[Calcolare la durata di un file audio WAV]] |
Versione attuale delle 14:50, 18 giu 2024
Il file .wav è un sottotipo del file RIFF.
Le informazioni generali di un file WAVE sono contenute nei primi 44 byte del file medesimo.
Il file WAVE è sostanzialmente composto da un solo blocco (chunk), a sua volta composto da due sottoblocchi: il primo blocco, appunto, formato da 44 byte contiene - come già detto - le informazioni relative alle caratteristiche del file; il secondo blocco contiene i dati audio veri e propri della forma d'onda digitalizzata.
Indice
- 1 Estrazione delle informazioni con le sole funzioni Gambas
- 1.1 Formato audio
- 1.2 Numero di canali
- 1.3 Frequenza di campionamento
- 1.4 ByteRate
- 1.5 block align
- 1.6 Risoluzione del campionamento
- 1.7 La lunghezza del file
- 1.8 Numero dei campioni (samples)
- 1.9 Overall BitRate
- 1.10 Ottenere la durata del file wav
- 1.11 Esempi pratici
- 1.11.1 Assegnando i dati letti dall'Header del file wav ai membri di un'apposita Struttura
- 1.11.2 Leggendo e gestendo il file WAV come stringa
- 1.11.3 Usando una variabile vettoriale di tipo Byte[] - 1
- 1.11.4 Usando una variabile vettoriale di tipo Byte[] - 2
- 1.11.5 Usando una variabile vettoriale di tipo Byte[] - 3
- 1.11.6 Usando la funzione Seek
- 1.12 Estrazione delle informazioni da un file wav contenente testo nel proprio header
- 2 Estrazione delle informazioni con le funzioni esterne del API di SOX
- 3 Note
- 4 Riferimenti
Estrazione delle informazioni con le sole funzioni Gambas
Volendo estrarre le informazioni più importanti relative ad un file WAV mediante le sole risorse interne di Gambas, andremo a leggere alcuni byte spcifici appartenenti al primo sotto-blocco. Bisogna sottolineare che i le informzioni sono espresse all'interno del primo sotto-blocco in modalità little-endian. [Nota 1]
Formato audio
Le informazioni relative al formato audio sono contenute in little-endian nel 21° e nel 22° byte (indice offset: 20, 21).
Numero di canali
Le informazioni relative al numero di canali del file WAV sono contenute in little-endian nel 23° e 24° byte (indice offset: 22, 23).
Frequenza di campionamento
Le informazioni relative alla frequenza di campionamento del file WAV sono contenute in little-endian nel 25°, 26° 27° e 28° byte (indice offset: 24, 25, 26 e 27).
ByteRate
Le informazioni relative al ByteRate sono contenute in Little-Endian nel 29°, 30, 31° e 32° byte (indice offset: 28, 29, 30 e 31).
block align
Il Block Align rappresenta la quantità di byte che costituisce un campione audio significativo.
Esso è un valore di tipo Short in Little-Endian, posto al byte d'indice offset n. 32, ed è dato anche dalla seguente formula:
Block_Align = (Risoluzione_del_campionamento_in_bit / 8-bit) * Canali
Risoluzione del campionamento
La risoluzione del campionamento audio è espresso in bit per un campione audio e rappresenta la gamma di valori che detto campione audio può assumere. Una gamma più ampia conferisce ovviamente un campionamento più dinamico e ricco.
Le informazioni relative alla risoluzione in bit del campionamento del file WAV sono contenute in little-endian nel 35° e 36° byte (indice offset: 34 - 35).
Un'altra modalità, per ottenere il valore della risoluzione in bit, è - conoscendo la durata dell'esecuzione audio del file - effettuare il seguente calcolo:
bit = ((quantità_dati_audio_del_file * 8) / durata_in_secondi) / (frequenza_di_campionamento * numero_canali_audio)
La lunghezza del file
Il file WAV contiene immediatamente dopo il primo sotto-blocco iniziale quattro byte che indicano la quantità di byte contenuta dal secondo sotto-blocco (quello formato dai veri e propri dati audio grezzi). Per conoscere la totale dimensione del file WAV, pertanto, basterà aggiungere a tale valore il numero di byte costituenti il blocco d'intestazione del file wav, solitamente 44 byte, che formano il primo sotto-blocco informativo del file.
Numero dei campioni (samples)
Il numero di campioni si ottiene con la seguente formula:
campioni = dimensione_dei_dati_grezzi_in_byte / block_align
Overall BitRate
Per ottenere il valore del Overall BitRate, bisogna moltiplicare la frequenza di campionamento per la risoluzione in bit per il numero dei canali:
Overall BitRate = frequenza * ris_bit * canali
Ottenere la durata del file wav
Per ottenere la durata dei dati audio wav [Nota 2], si possono adottare due modalità di calcolo:
La prima modalità prevede la seguente formula:
durata = (dimensione_dei_dati_grezzi_in_byte * 8) / (frequenza * ris_bit * canali)
La seconda modalità prevede la seguente formula:
durata = (dimensione_dei_dati_grezzi_in_byte / block_align) / frequenza
Esempi pratici
Per estrarre le suddette informazioni, potremo, dunque, realizzare alcuni codici come quelli che seguono.
Assegnando i dati letti dall'Header del file wav ai membri di un'apposita Struttura
In questo esempio assegneremo i dati letti dall'Header del file wav ai membri di un'apposita "Struttura":
Public Struct Header_Wav riff As String ' tipo file "RIFF" lung_rest As Integer ' lunghezza del resto del file = dimensione restante dell'header (36 byte) + lunghezza dei dati audio grezzi wave As String ' sottotipo file "wav" fmt As String ' inizio blocco "fmt " del file lungh_fmt As Integer ' lunghezza del blocco "fmt" pcm As Short ' formato MS PCM canali As Short ' canali audio di ucita (mono = 1, stereo = 2) frequenza As Integer ' frequenza di campionamento per secondo byte_rate As Integer ' byte per secondo = frequenza * byte_campione byte_campione As Short ' block align (byte per campione) = canali * bit_per_campione / 8 bit_campione As Short ' bit per campione (risoluzione del campionamento) = 8, 16 o 24 data As String ' "data" lungh_dati As Integer ' lunghezza dei dati audio grezzi End Struct Public Sub Main() Dim fileWAV As String Dim wav As File Dim hw As New Header_Wav fileWAV = "/percorso/del/file.wav" wav = Open fileWAV For Read ' Leggiamo ed assegnamo alla Struttura tutte le informazioni presenti nell'Header del file wav: With hw .riff = legge_stringa(wav) .lung_rest = legge_intero(wav) .wave = legge_stringa(wav) .fmt = legge_stringa(wav) .lungh_fmt = legge_intero(wav) .pcm = legge_corto(wav) .canali = legge_corto(wav) .frequenza = legge_intero(wav) .byte_rate = legge_intero(wav) .byte_campione = legge_corto(wav) .bit_campione = legge_corto(wav) .data = legge_stringa(wav) .lungh_dati = legge_intero(wav) End With wav.Close End Private Function legge_stringa(fl As File) As String Dim s As String Read #fl, s, 4 Return s End Private Function legge_intero(fl As File) As Integer Dim i As Integer Read #fl, i Return i End Private Function legge_corto(fl As File) As Short Dim sh As Short Read #fl, sh Return sh End
Leggendo e gestendo il file WAV come stringa
In questo caso leggeremo e gestiremo l'intero file WAV come una stringa.
Public Sub Main() Dim per, s, dati_grezzi As String Dim d, i, campionamento, formato, durata As Integer Dim canali, bit As Short ' Estrae alcune informazioni sul file: per = "/percorso/del/file.wav" Print "Percorso del file audio: "; per ' Legge e carica nella variabile di tipo Stringa "s" tutti i byte del file audio WAV: s = File.Load(per) Print "Dimensione del file: "; Len(s); " byte" d = InStr(s, "data", 0, gb.Binary) i = Int@(s[d + 3]) Print "Totale dei soli byte audio: "; i; " byte" d = InStr(s, "fmt ", 0, gb.Binary) canali = Short@(s[d + 9]) Print "Numero canali audio: "; canali campionamento = Int@(s[d + 11]) Print "Frequenza di campionamento: "; campionamento; " hertz" bit = Short@(s[d + 21]) Print "Profondità campionamento: "; bit; " bit" durata = (i * 8) / (campionamento * bit * canali) Print "Durata del brano audio: "; CStr(Time(0, 0, 0, durata * 1000)) ' Raccoglie i soli byte dei dati audio grezzi: dati_grezzi = Right(s, i) End
Usando una variabile vettoriale di tipo Byte[] - 1
Potremo utilizzare un vettore di tipo Byte[] per contenere i dati del file wav:
Public Sub Main() Dim percorsoFile As String Dim fl As File Dim j, b, formato, canali, risoluzione As Byte Dim buf As New Byte[] Dim frequenza, dimensione As Integer percorsoFile = "/percorso/del/file.wav" ' Carica un file audio Wav: fl = Open percorsoFile For Read For j = 0 To 43 Read #fl, b buf.Add(b) Next Print "== Caratteristiche del file: "; File.Name(percorsoFile); " ==\n" ' Rileva il formato audio (legge 2 byte): formato = buf[21] * CInt(2 ^ 8) formato = formato Or buf[20] If formato = 1 Then Print "Formato audio = PCM" Else Print "Formato audio = "; formato Endif ' Rileva il numero di canali (legge 2 byte): canali = buf[23] * CInt(2 ^ 8) canali = canali Or buf[22] Print "Numero canali = "; canali ' Rileva la frequenza di campionamento (legge 4 byte): frequenza = buf[27] * CInt(2 ^ 24) frequenza = frequenza Or buf[26] * CInt(2 ^ 16) frequenza = frequenza Or buf[25] * CInt(2 ^ 8) frequenza = frequenza Or buf[24] Print "Frequenza = hrz "; frequenza ' Rileva la risoluzione del campionamento (legge 2 byte): risoluzione = buf[35] * CInt(2 ^ 8) risoluzione = risoluzione Or buf[34] Print "Risoluzione = "; risoluzione; " bit" ' Rileva la quantità dei soli dati grezzi (legge 4 byte): dimensione = buf[43] * CInt(2 ^ 24) dimensione = dimensione Or buf[42] * CInt(2 ^ 16) dimensione = dimensione Or buf[41] * CInt(2 ^ 8) dimensione = dimensione Or buf[40] Print "Quantità dei soli dati grezzi = "; dimensione; " byte" ' Calcola la durata del brano audio: Print "Durata del brano: "; Time(0, 0, 0, Fix((dimensione * 8) / (frequenza * risoluzione * canali)) * 1000) fl.Close End
Usando una variabile vettoriale di tipo Byte[] - 2
Per estrarre le informazioni possiamo anche utilizzare un Vettore di tipo Byte[]:
Public Sub Main() Dim percorsoFile As String Dim fl As File Dim bb As Byte[] Dim solo_dati, frequenza As Integer percorsoFile = "/percorso/del/file.wav" fl = Open percorsoFile For Read bb = New Byte[44] bb.Read(fl, 0, 44) If bb.ToString(0, 4) <> "RIFF" Then Error.Raise("Il file caricato non è di tipo 'RIFF' !") If bb.ToString(8, 4) <> "WAVE" Then Error.Raise("Il file caricato non è di tipo 'WAVE' !") If bb.ToString(12, 4) <> "fmt " Then Error.Raise("Il file caricato non è di tipo 'fmt ' !") Print "== Caratteristiche del file: "; File.Name(percorsoFile); " ==\n" Print "Dimensioni totali del file: "; Stat(percorsoFile).Size; " byte" solo_dati = Stat(percorsoFile).Size - 44 Print "Dimensione dei soli dati audio grezzi: "; solo_dati; " byte" If bb[20] = 1 Then Print "Formato audio: PCM" Else Print "Formato audio: "; bb[20] Endif Print "Canali di uscita audio: "; bb[22] frequenza = Val("&" & Hex(bb[27]) & Hex(bb[26]) & Hex(bb[25]) & Hex(bb[24])) Print "Frequenza di campionamento: Hz "; frequenza Print "Byte rate: "; Val("&" & Hex(bb[31]) & Hex(bb[30]) & Hex(bb[29]) & Hex(bb[28])); " Bps" Print "Risoluzione di campionamento a "; bb[34]; " bit" Print "Durata del brano: "; Time(0, 0, 0, Fix((solo_dati * 8) / (frequenza * bb[34] * bb[22])) * 1000) fl.Close End
Usando una variabile vettoriale di tipo Byte[] - 3
In questo esempio vengono caricati in un'apposita Struttura alcuni dati del file Wav: numero canali, frequenza di campionamento, risoluzione, block align (quest'ultimo sarà utile per ottenere la durata del brano audio). Tali dati verranno poi mostrati in console ed utilizzati alcuni per calcolare la durata di esecuzione del file Wav:
Public Struct INFOWAV fileWAV As String ' Percorso del file wav canali As Short ' Numero dei canali frequenza As Integer ' Frequenza di campionamento bit As Short ' Risoluzione di campionamento in bit block_align As Short ' Block Align durata As Float ' Durata di esecuzione del file wav End Struct Public Sub Main() Dim fileWav As String Dim datiwav As New INFOWAV datiwav.fileWav = "/percorso/del/file.wav" EstraeDatiAudio(datiwav) ' Mostra in console le informazioni ottenute: With datiwav Print "File wav caricato: "; .fileWAV Print "Numero canali: "; .canali Print "Frequenza di campionamento: hz"; .frequenza Print "Risoluzione: "; .bit; " bit" Print "Durata esecuzione: "; CStr(Time(0, 0, 0, .durata * 1000)) End With End Private Function EstraeDatiAudio(iw As INFOWAV) Dim fl As File ' Carica il file audio Wav: fl = Open iw.fileWAV For Read ' Legge il numero dei canali al byte d'indice (offset) 22: Seek #fl, 22 iw.canali = Read #fl As Short ' Legge la frequenza di campionamento dei dati audio al byte d'indice (offset) 24: Seek #fl, 24 iw.frequenza = Read #fl As Integer ' Legge il valore del "block align" al byte d'indice (offset) 32: Seek #fl, 32 iw.block_align = Read #fl As Short ' Legge la risoluzione bit del campionamento al byte d'indice (offset) 34: Seek #fl, 34 iw.bit = Read #fl As Short ' Calcola la durata dell'esecuzione del file wav: iw.durata = (Lof(fl) / iw.block_align) / iw.frequenza fl.Close End
Usando la funzione Seek
Potremo anche più semplicemente spostarci all'interno del flusso mediante la funzione Seek:
Public Sub Main() Dim fileWAV As String Dim fl As File Dim formato, canali, risoluzione As Byte Dim d As Short Dim frequenza, dimensione As Integer fileWAV = "/percorso/del/file.wav" d = Instr(File.Load(fileWAV), "data") ' Carica un file audio Wav: fl = Open fileWAV For Read Print "== Caratteristiche del file: "; File.Name(fileWAV); " ==\n" ' Rileva il formato audio (legge 2 byte): Seek #fl, 20 Read #fl, formato If formato = 1 Then Print "Formato audio = PCM" Else Print "Formato audio = "; formato Endif ' Rileva il numero di canali (legge 2 byte): Seek #fl, 22 Read #fl, canali Print "Numero canali = "; canali ' Rileva la frequenza di campionamento (legge 4 byte): Seek #fl, 24 Read #fl, frequenza Print "Frequenza = hrz "; frequenza ' Rileva la risoluzione del campionamento (legge 2 byte): Seek #fl, 34 Read #fl, risoluzione Print "Risoluzione = "; risoluzione; " bit" ' Rileva la quantità dei soli dati grezzi (legge 4 byte): seek #fl, d + 3 Read #fl, dimensione Print "Quantità dei soli dati grezzi = "; dimensione; " byte" ' Calcola la durata del brano audio: Print "Durata del brano: "; Time(0, 0, 0, Fix((dimensione * 8) / (frequenza * risoluzione * canali)) * 1000) fl.Close End
Estrazione delle informazioni da un file wav contenente testo nel proprio header
Talvolta, seppur raramente, i file wav possono contenere delle informazioni aggiuntive in formato testuale poste all'interno del proprio header, il quale pertanto risulterà complessivamente essere formato da una quantità di byte superiore a quella ordinaria di 44 byte.
Ciò determina che i riferimenti e, dunque, calcoli esposti nei paragrafi precedenti risultino non più utili.
Per individuare i nuovi riferimenti di indice, va considerato che le suddette eventuali informazioni testuali sono poste tra l'ultimo valore a 16 bit del file wav, che fornisce l'informazione del "bit per campione" (risoluzione del campionamento) e che è posto all'indice di offset 34, e il tag "data".
Pertanto, tale eventuale presenza testuale non pregiudica la consueta e agevole estrazione dei dati attinenti alle caratteristiche del file wav in esame.
Estrazione delle informazioni con le funzioni esterne del API di SOX
La libreria Sox contiene risorse per poter gestire ampiamente i file audio: riproduzione e registrazione, conversione di vari formati audio in altri formati, nonché applicazione di vari effetti.
Le risorse del API di Sox consentono anche di ottenere facilmente varie informazioni dai file audio, richiamando l'attuale versione della libreria: "libsox.so.2.0.1"
Potremo procedere con un codice simile al seguente:
Private sfIn As New Sox_format_t Library "libsox:2.0.1" Public Struct sox_signalinfo_t rate As Float ' sox_rate_t: samples per second, 0 if unknown (typedef double sox_rate_t) channels As Integer ' number of sound channels, 0 if unknown precision As Integer ' bits per sample, 0 if unknown length As Long ' samples * chans in file, 0 if unknown, -1 if unspecified (typedef unsigned long sox_uint64_t;) mult As Pointer ' Effects headroom multiplier; may be null End Struct Public Struct sox_format_t filename As Pointer signal As Struct Sox_signalinfo_t End Struct Private Const SOX_SUCCESS As Byte = 0 ' int sox_init(void) ' Client API: Initialize effects library. SOX_SUCCESS if successful. Private Extern sox_init() As Integer ' sox_format_t * sox_open_read(char const *path, sox_signalinfo_t const *signal, sox_encodinginfo_t const *encoding, char const *filetype) Private Extern sox_open_read(path As String, signalP As Pointer, encoding As Pointer, filetype As String) As Sox_format_t Public Sub Main() Dim err As Integer Dim fileWAV As String fileWAV = "/percorso/del/file.wav" err = sox_init() If err <> SOX_SUCCESS Then Error.Raise("Impossibile inizializzare la libreria 'libsox' !") sfIn = sox_open_read(fileWAV, Null, Null, Null) With sfIn Print "File audio: "; String@(.filename) Print "Frequenza di campionamento: hrz "; .signal.rate Print "Numero di canali: "; .signal.channels Print "Risoluzione campionamento: "; .signal.precision; " bit" Print "Dimensione dei soli dati grezzi del file wav: "; .signal.length * .signal.channels; " byte" ' (tale valore è privo dei byte del blocco di intestazione del file wav = 44 byte) End With End
Note
[1] Ordine dei byte
[2] Vedi anche la seguente pagina: Calcolare la durata di un file audio WAV
Riferimenti
Per un ulteriore e dettagliata spiegazione rinviamo ai seguenti siti:
- http://en.wikipedia.org/wiki/Resource_Interchange_File_Format
- http://it.wikipedia.org/wiki/WAV
- https://ccrma.stanford.edu/courses/
- http://www.topherlee.com/software/pcm-tut-wavformat.html
- http://msdn.microsoft.com/en-us/library/windows/desktop/ee415713%28v=vs.85%29.aspx
- https://msdn.microsoft.com/en-us/library/windows/desktop/dd757712(v=vs.85).aspx
- https://blogs.msdn.microsoft.com/dawate/2009/06/23/intro-to-audio-programming-part-2-demystifying-the-wav-format/
- http://www.digitalpreservation.gov/formats/fdd/fdd000001.shtml
- http://unusedino.de/ec64/technical/formats/wav.html
- http://www-mmsp.ece.mcgill.ca/Documents/AudioFormats/WAVE/WAVE.html
- http://sharkysoft.com/archive/lava/docs/javadocs/lava/riff/wave/doc-files/riffwave-frameset.htm
- http://www.johnloomis.org/cpe102/asgn/asgn1/riff.html
- http://www.lightlink.com/tjweber/StripWav/Canon.html
- http://paulbourke.net/dataformats/audio/
- https://tecnologiamusicale.wordpress.com/2012/08/19/il-formato-wave-dei-file-audio/
- Formato WAV