This is how to build the WAV header for a wav file in VB. It took me a while to learn how, so i though i’d post it here in case anyone did a search in the future. So far, I haven’t figured out how to get the WAV data from FMOD recorded samples because of pointer problems

‘ format is as follows. % indicates a hex value for 1 ASCII byte
‘ RIFF(4 bytes specifying file size minus 8 bytes which is also 36 bytes plus the raw wav data)
‘ WAVEfmt(%20)
‘ (%10%00%00%00)(%01%00)(%01 for mono, %02 for stereo)%00
‘ (4 bytes for sample rate)(4 bytes = SampleRate * NumChannels * BitsPerSample/8)
‘ (2 bytes = NumChannels * BitsPerSample/8 or %02%00 for mono 16 bit)
‘ (2 bytes BitsPerSample usu 8 or 16, i.e. %08%00 or %10%00)data
‘ (4 bytes for file size minus 44, the actual size of the raw wav data which follows immediately)(raw wav data)
‘ 8-bit samples are stored as unsigned single bytes, ranging from 0 to 255, in hex that’s 00 to FF
‘ 16-bit samples are stored as 2 bytes per sample in a format called 2’s-complement and signed, ranging from -32768 to 32767. In hex, that’s 0000 up to 7FFF for positive and FFFF down to 8000 for negative. Oddly enough, 8000 is the lowest negative value.
‘ stereo alternates left and right channel samples.

‘ below is an example creating header for 16 bit mono
Kill “test.wav”
wav_data$ = “RIFF” & dec2endian(samplebytes + 36) & “WAVEfmt” & chr$(32) & Chr$(16) & Chr$(0) & Chr$(0) & _
Chr$(0) & Chr$(1) & Chr$(0) & Chr$(1) & Chr$(0) & dec2endian(samplerate) & dec2endian(Int(samplerate * 2)) & _
Chr$(2) & Chr$(0) & Chr$(16) & Chr$(0) & “data” & dec2endian(samplebytes) & raw_data ‘ raw_data is the actual wav data
Open “test.wav” For Binary As #1
Put #1, , wav_data$ ‘ without the $ it was printing 4 bytes before RIFF
Close #1

Public Function dec2endian(ByVal dec_num As Long) As String
‘ converts a decimal number to a 4 byte little endian ascii character string
Dim a, b, c, d As String
Dim aa, bb, cc, dd As Long
dd = Int(dec_num / 16777216)
cc = Int((dec_num – dd * 16777216) / 65536)
bb = Int((dec_num – dd * 16777216 – cc * 65536) / 256)
aa = dec_num – dd * 16777216 – cc * 65536 – bb * 256
a = Chr$(aa): b = Chr$(bb): c = Chr$(cc): d = Chr$(dd)
dec2endian = a & b & c & d
End Function

  • You must to post comments
  • You must to post comments

It’s nice seeing the proper way in the link above, but i like forming the WAV header with only one line of code as in my example and seeing each byte.

i forgot to mention that “RIFF” is the beginninf of the WAV file as seen with a hex editor which is necessary for diagnosing problems when formatting WAV headers yourself. All the data in a wav file except for the text “RIFF”, “WAVEfmt”, and “DATA” are in “little endian” which means the lower valued hex byte comes first. For example, a sample rate of 16,000 samples per second is “3E80” in hex (%3E%80 in my notation above which is same as cgi URL notation), which is 2 bytes, but the sample rate field in the header is 4 bytes so it’s actually %00%00%3E%80, but it’s supposed to be stored in little endian so you reverse the BYTES (not the bits, nor the nibles, nor the words) so you use %80%3E%00%00 in the header for 16,000 samples/sec. This complication is the reason for the dec2endian function.

Each chr$() returns a byte of ASCII text (a hex value in bits). It helps to have a calculator with base conversion and an ascii chart in hex and decimal. Note that chr(1)=%01, chr(2)=%02, chr(16)=%10, chr(15)=%FF, and chr(32)=%20=(space).

  • You must to post comments

The only difference i see is the endianess support, the wav file created with my function is a 100 % riff wave.

  • You must to post comments
Showing 3 results
Your Answer

Please first to submit.