Creare il blocco d'intestazione di un file WAV

Da Gambas-it.org - Wikipedia.

Il blocco di intestazione (header) di un file WAV è posto all'inizio del file, solitamente formato da 44 byte, e contiene le informazioni generali sui dati audio e sul file medesimo.

Per poter creare un blocco d'inteztazione di un file wav, è necessario tenere conto dei suoi elementi fondamentali:

  • quantità dei dati audio grezzi (in byte);
  • frequenza di campionamento (in hertz);
  • risoluzione di campionamento (in bit);
  • numero dei canali di uscita.

Da questi elementi principali è possibile individuare e quindi porre nel blocco di intestazione del file wav anche gli altri valori che lo compongono.


Mostriamo due modalità.

1a modalità

Nell'esempio che segue, supporremo che i dati audio grezzi, passati alla Procedura mediante una variabile di tipo Stringa come argomento, siano stati acquisiti in precedenza da un file avente le seguenti caratteristiche: 44100 hertz, 16 bit, 2 canali. Si creerà un completo nuovo file WAV unendo il corretto blocco d'intestazione (header) a tali dati grezzi.
Il procedimento del codice mostra l'inserimento passo-passo di ciascun elemento previsto dal blocco header del file wav. Gli elementi non fondamentali verranno per lo più ricavati dai valori degli elementi fondamenti prima sopra elencati.

Private Procedure CreaHeaderWav(dati_grezzi As String)

 Dim fl As File
 Dim ini As String
 Dim bh, bb As New Byte[]
 Dim canali, risoluzione, blal as Byte
 Dim i, i2, frequenza, brps As Integer

' Vengono definiti gli elementi fondamentali del blocco d'intestazione del file wav:
 canali = 2
 frequenza = 44100
 risoluzione = 16 

 fl = Open "/percorso/di/destinazione/del/nuovo/file.wav" For Create

 ini = "RIFF"

 bb = Byte[].FromString(ini)

 i = Len(dati_grezzi)

 i2 = i + 36

' Imposta il valore dimensionale di 4 byte a partire dal 5° byte del futuro file: 
 bb.Push(i2 And &FF)
 bb.Push(Shr(i2 And &FF00&, 8))
 bb.Push(Shr(i2 And &FF0000&, 16))
 bb.Push(Shr(i2 And &FF000000&, 24))

' Vengono aggiunti: il tipo di formato di file e l'identificativo del formato del blocco dei dati audio: 
 bb.Insert(bh.FromString("WAVEfmt "))
 
' Viene aggiunto il valore della lunghezza dei dati del formato (in questo caso il PCM): 
 bh = [&10, &00, &00, &00]
 bb.Insert(bh)

' Viene aggiunto il valore del formato audio (1 = PCM): [Nota 1]
 bb.Insert(bh.FromString(Chr(&01) & Chr(&00)))

' Viene aggiunto il numero dei canali di uscita:
 bb.Insert(bh.FromString(Chr(canali) & Chr(&00)))

' Viene aggiunto il valore della frequenza di campionamento:
 bb.Push(frequenza And &FF)
 bb.Push(Shr(frequenza And &FF00&, 8))
 bb.Push(Shr(frequenza And &FF0000&, 16))
 bb.Push(Shr(frequenza And &FF000000&, 24))

' Viene aggiunto il valore del "Byte rate per secondo":
 brps = frequenza * canali * (risoluzione / 8)
 bb.Push(brps And &FF)
 bb.Push(Shr(brps And &FF00&, 8))
 bb.Push(Shr(brps And &FF0000&, 16))
 bb.Push(Shr(brps And &FF000000&, 24))

' Viene aggiunto il valore del "Block Align":
 blal = canali * risoluzione / 8
 bb.Insert(bh.FromString(Chr(blal) & Chr(&00)))

' Viene aggiunto il valore della risoluzione di campionamento:
 bb.Insert(bh.FromString(Chr(risoluzione) & Chr(&00)))

' Viene aggiunto l'identificativo del Blocco dei dati audio grezzi:
 bb.Insert(bh.FromString("data"))

' Imposta il valore dimensionale di 4 byte a partire dal 41° byte del futuro file e relativo alla dimensione dei dati audio grezzi: 
 bb.Push(i And &FF)
 bb.Push(Shr(i And &FF00&, 8))
 bb.Push(Shr(i And &FF0000&, 16))
 bb.Push(Shr(i And &FF000000&, 24))
   
 bb.Insert(Byte[].FromString(dati_grezzi))
   
' Crea il nuovo file wav: 
 bb.Write(fl, 0, bb.Count)

 fl.Close

End


2a modalità

Anche in questo caso presupponiamo che i dati audio grezzi, passati alla Procedura mediante una variabile di tipo Stringa come argomento, siano stati acquisiti in precedenza da un file wav, avente le seguenti caratteristiche: 44100 hertz, 16 bit, 2 canali.

Private Procedure CreaHeaderWav(dati_grezzi As String)
 
 Dim qnt, dim_file, m8 As Integer
 Dim b As Byte
 Dim bb As New Byte[]
 Dim little_endian, primo_chunk As String
    
' Ricaviamo la quantità dei dati audio grezzi contenuti dalla variabile di tipo "Stringa":
 qnt = Len(dati_grezzi)

' Ricaviamo la dimensione totale del futuro file. Essa sarà, dunque, data dai byte del primo blocco ("Chunk", contenente le informazioni sul file WAV ed i dati che lo distinguono ed identificano) pari a 44 byte più i dati audio grezzi del file temporaneo, i quali così vengono a formare il secondo blocco di dati del futuro file WAV.
 dim_file = 44 + qnt
  
' Ricaviamo il formato "little-endian" dellla dimensione del file meno gli otto byte iniziali. Il risultato sarà inserito dal 5° all'8° byte:
 m8 = dim_file - 8
   
 little_endian = Hex(((m8 \ CInt(2 ^ 24)) And &FF) Or ((m8 * CInt(2 ^ 8)) And &FF0000) Or ((m8 \ CInt(2 ^ 8)) And &FF00&) Or ((m8 * CInt(2 ^ 24)) And &FF000000), 8)
   
 For j = 0 To 3
   bb.Push(CByte(Val("&" & Mid(little_endian, (2 * b) + 1, 2))))
 Next

' Quindi ricaviamo il formato "little-endian" della dimensione del file temporaneo dei dati audio grezzi.
' Il risultato sarà inserito alla fine del primo blocco (chunk):
 little_endian = Hex(((qnt \ CInt(2 ^ 24)) And &FF) Or ((qnt * CInt(2 ^ 8)) And &FF0000) Or ((qnt \ CInt(2 ^ 8)) And &FF00&) Or ((qnt * CInt(2 ^ 24)) And &FF000000), 8)

 For b = 0 To 3
   bb.Push(CByte(Val("&" & Mid(little_endian, (2 * b) + 1, 2))))
 Next

' Impostiamo i dati appartenenti al primo blocco del futuro file WAV":
 primo_chunk = "RIFF" & Chr(bb[0]) & Chr(bb[1]) & Chr(bb[2]) & Chr(bb[3]) & "WAVEfmt" & Chr(&20) & Chr(&10) & Chr(&00) &
               Chr(&00) & Chr(&00) & Chr(&01) & Chr(&00) & Chr(&02) & Chr(&00) & Chr(&44) & Chr(&AC) & Chr(&00) &
               Chr(&00) & Chr(&10) & Chr(&B1) & Chr(&02) & Chr(&00) & Chr(&04) & Chr(&00) & Chr(&10) & Chr(&00) &
               "data" & Chr(bb[4]) & Chr(bb[5]) & Chr(bb[6]) & Chr(bb[7])
   
' Ecco, dunque, creiamo il file WAV finale unendo il primo blocco dei dati informativi e caratterizzanti il file WAV con i dati audio grezzi del file temporaneo":
 File.Save("/percorso/del/definitivo/file.wav", primo_chunk & dati_grezzi)

End


Note

[1] Di seguito l'elenco dei formati disponibili:

&h0000:  "Microsoft Unknown Wave Format";
&h0001:  "Microsoft PCM";
&h0002:  "Microsoft ADPCM";
&h0003:  "IEEE Float";
&h0004:  "Compaq Computer VSELP";
&h0005:  "IBM CVSD";
&h0006:  "Microsoft A-Law";
&h0007:  "Microsoft mu-Law";
&h0008:  "Microsoft DTS";
&h0009:  "Microsoft DRM Encrypted Audio";
&h000A:  "Windows Media Audio 9 Voice";
&h000B:  "Windows Media RT Voice";

&h0010:  "OKI ADPCM";
&h0011:  "Intel DVI/IMA ADPCM";
&h0012:  "Videologic MediaSpace ADPCM";
&h0013:  "Sierra ADPCM";
&h0014:  "Antex G.723 ADPCM";
&h0015:  "DSP Solutions DigiSTD";
&h0016:  "DSP Solutions DigiFIX";
&h0017:  "Dialogic OKI ADPCM";
&h0018:  "MediaVision ADPCM";
&h0019:  "Hewlett-Packard CU";

&h0020:  "Yamaha ADPCM";
&h0021:  "Speech Compression Sonarc";
&h0022:  "DSP Group TrueSpeech";
&h0023:  "Echo Speech EchoSC1";
&h0024:  "Audiofile AF36";
&h0025:  "Audio Processing Technology APTX";
&h0026:  "AudioFile AF10";
&h0027:  "Prosody 1612";
&h0028:  "LRC";

&h0030:  "Dolby AC2";
&h0031:  "Microsoft GSM 6.10";
&h0032:  "MSNAudio";
&h0033:  "Antex ADPCME";
&h0034:  "Control Resources VQLPC";
&h0035:  "DigiREAL";
&h0036:  "DigiADPCM";
&h0037:  "Control Resources CR10";
&h0038:  "Natural MicroSystems VBXADPCM";
&h0039:  "Crystal IMA ADPCM";
&h003A:  "EchoSC3";
&h003B:  "Rockwell ADPCM";
&h003C:  "Rockwell Digit LK";
&h003D:  "Xebec";

&h0040:  "Antex Electronics G.721 ADPCM";
&h0041:  "G.728 CELP";
&h0042:  "MS G.723";
&h0043:  "MS G.723.1";
&h0044:  "MS G.729";
&h0045:  "SP G.726";

&h0050:  "MPEG Layer-2 or Layer-1";

&h0052:  "RT24";
&h0053:  "PAC";

&h0055:  "MPEG Layer-3";

&h0059:  "Lucent G.723";

&h0060:  "Cirrus";
&h0061:  "ESPCM";
&h0062:  "Voxware";
&h0063:  "Canopus Atrac";
&h0064:  "G.726 ADPCM";
&h0065:  "G.722 ADPCM";
&h0066:  "DSAT";
&h0067:  "DSAT Display";

&h0069:  "Voxware Byte Aligned";

&h0070:  "Voxware AC8";
&h0071:  "Voxware AC10";
&h0072:  "Voxware AC16";
&h0073:  "Voxware AC20";
&h0074:  "Voxware MetaVoice";
&h0075:  "Voxware MetaSound";
&h0076:  "Voxware RT29HW";
&h0077:  "Voxware VR12";
&h0078:  "Voxware VR18";
&h0079:  "Voxware TQ40";

&h0080:  "Softsound";
&h0081:  "Voxware TQ60";
&h0082:  "MSRT24";
&h0083:  "G.729A";
&h0084:  "MVI MV12";
&h0085:  "DF G.726";
&h0086:  "DF GSM610";

&h0088:  "ISIAudio";
&h0089:  "Onlive";

&h0091:  "SBC24";
&h0092:  "Dolby AC3 SPDIF";
&h0093:  "MediaSonic G.723";
&h0094:  "Aculab PLC  Prosody 8kbps";

&h0097:  "ZyXEL ADPCM";
&h0098:  "Philips LPCBB";
&h0099:  "Packed";

&h00FF:  "AAC";

&h0100:  "Rhetorex ADPCM";
&h0101:  "IBM mu-law";
&h0102:  "IBM A-law";
&h0103:  "IBM AVC ADPCM";

&h0111:  "Vivo G.723";
&h0112:  "Vivo Siren";

&h0123:  "Digital G.723";

&h0125:  "Sanyo LD ADPCM";

&h0130:  "Sipro Lab Telecom ACELP NET / RealAudio 4.0/5.0)";
&h0131:  "Sipro Lab Telecom ACELP 4800";
&h0132:  "Sipro Lab Telecom ACELP 8V3";
&h0133:  "Sipro Lab Telecom G.729";
&h0134:  "Sipro Lab Telecom G.729A";
&h0135:  "Sipro Lab Telecom Kelvin";

&h0140:  "Windows Media Video V8";

&h0150:  "Qualcomm PureVoice";
&h0151:  "Qualcomm HalfRate";

&h0155:  "Ring Zero Systems TUB GSM";

&h0160:  "Microsoft Audio 1";
&h0161:  "Windows Media 7/8/9";
&h0162:  "Windows Media 9 Professional";
&h0163:  "Windows Media 9 Lossess";
&h0164:  "Windows Media Professional over S/PDIF";

&h0180:  "MPEG-2 AAC";

&h0190:  "DTS";

&h0200:  "Creative Labs ADPCM";

&h0202:  "Creative Labs FastSpeech8";
&h0203:  "Creative Labs FastSpeech10";

&h0210:  "UHER Informatic GmbH ADPCM";

&h0215:  "Ulead DV Audio NTSC";
&h0216:  "Ulead DV Audio PAL";

&h0220:  "Quarterdeck";

&h0230:  "I-link Worldwide VC";

&h0240:  "Aureal RAW Sport";

&h0250:  "Interactive Products HSX";
&h0251:  "Interactive Products RPELP";

&h0260:  "Consistent Software CS2";

&h0270:  "Sony SCX / RealAudio 8.0";
&h0271:  "Sony SCY";
&h0272:  "Sony ATRAC3";
&h0273:  "Sony SPC";

&h0300:  "Fujitsu FM Towns Snd";

&h0400:  "BTV Digital";
&h0401:  "Intel Music Coder";

&h0450:  "QDesign Music";

&h0680:  "VME VMPCM";
&h0681:  "AT&T Labs TPC";

&h08AE:  "ClearJump LiteWave";

&h1000:  "Olivetti GSM";
&h1001:  "Olivetti ADPCM";
&h1002:  "Olivetti CELP";
&h1003:  "Olivetti SBC";
&h1004:  "Olivetti OPR";

&h1100:  "L&H Codec";
&h1101:  "L&H CELP";
&h1102:  "L&H SBC 0x1102";
&h1103:  "L&H SBC 0x1103";
&h1104:  "L&H SBC 0x1104";
       
&h1400:  "Norris";
&h1401:  "AT&T ISIAudio";

&h1500:  "Soundspace Music Compression";

&h181C:  "VoxWare RT24 Speech";

&h1971:  "Sonic Foundry Perfect Clarity Audio (PCA)";

&h1FC4:  "NCT Soft ALF2CD";

&h2000:  "Dolby AC3";
&h2001:  "Dolby DTS";
&h2002:  "RealAudio 1.0 (14.4K)";
&h2003:  "RealAudio 2.0 (28.8K)";
&h2004:  "RealAudio G2 (Cook)";
&h2005:  "RealAudio 3.0 (DolbyNet AC3)";
&h2006:  "RealAudio 10.0 (LC-AAC)";
&h2007:  "RealAudio 10.0 (HE-AAC)";

&h2048:  "Sonic";

&h4143:  "Divio AAC";

&h4201:  "Nokia AMR";

&h566F:  "Vorbis";

&h5756:  "WavPack";
       
&h674F:  "Ogg Vorbis 1";
&h6750:  "Ogg Vorbis 2";
&h6751:  "Ogg Vorbis 3";
&h676F:  "Ogg Vorbis 1+";
&h6770:  "Ogg Vorbis 2+";
&h6771:  "Ogg Vorbis 3+";

&h7A21:  "Adaptive Multirate";
&h7A22:  "Adaptive Multirate w/ silence detection";

&h706D:  "AAC";

&h77A1:  "TTA";

&hA106:  "MPEG-4 AAC";

&hA109:  "Speex";

&hF1AC:  "FLAC"


Riferimenti