Documentations
To go further
Wav format
A very complete and clear description of the file format can be found at
http://www.borg.com/~jglatt/tech/wave.htm
PCM format is the "standard" format for sound samples. Data is not compressed and can be easily accessed. There is some possible variations about PCM/Wave format but the most popular of them has a 44 bytes header. This header contains very important data about the rest of the file and will tell you the number of channels, the frequency, etc...
The first 12 bytes give you the.
• 1 - FORMAT
• You find at first the « RIFF » mention ($52, $49, $42, $42 in hexadecimal. These are the ASCII values for R,I,F,F letters)
• You find then the TOTAL size of the file coded as a long integer (4 bytes)
• You find then the « WAVE» mention (4 lettres): $57,$41,$56,$45
This first part is followed by the
• 2- Sound desciption : sampling frequency, number of bytes per sample, etc. Those datas are exactly ordered as in the WAVEFORMAT structure, (Microsoft) descripted in Microsoft APIs documentation.
• zone descriptor : « fmt » (4 characters) take care! the last character is a "space" : $66,$6D,$74,$20. « fmt » is an abbreviation for « format ». This is to tell us that the following is a format description (as you will see)
• size of the WAVEFORMAT structure as a long integer (4 bytes). WAVEFORMAT is 16 bytes long, so you will find the $10,00,00,00 value here. ($10 in hexa equal to 16 in decimal)
• wFormatTag.w (2 octets) : for PCM files, this value must be 1
• nChannels.w (2 octets) : number of channels. 1 for mono, 2 for stereo. In can be more.
• nSamplesPerSec.l (4 octets) : number of samples per seconde.
• nAvgBytesPerSec.l (4 octets) : Average bytes per seconde. This value is a combination of other values recorded in this chunck. You HAVE to complete it if you generate a wave file and want to be compatible with all softwares. The formula to compute it is: nAvgBytesPerSec= nSamplesPerSec* nBitsPerSample/8* nChannels
(nBitsPerSample is the number of BITS per seconde. One byte equal to 8 bits)
• nBlockAlign.w (2 octets) : total size of a sample. This value is a combination of other values recorded in this chunck. You HAVE to complete it if you generate a wave file and want to be compatible with all softwares. The formula to compute it is: nBlockAlign = nBitsPerSample/8* nChannels*
(nBitsPerSample is the number of BITS per seconde. One byte equals to 8 bits)
• nBitsPerSample.w (2 octets) : number of bits per sample.
The following of the fil contains the.
• 3 - DATAS
• zone descriptor : «data» (4 characters) : $64,$61,$74,$61.
• Data size as a long integer (4 bytes). Duration of the sound can be computed uppon this value :
Duration = DataSize/ nAvgBytesPerSec
CAUTION : DataSize must ALLWAYS be a multiple of nBlockAlign. You can be sure of that by doing :
Newsize.l = Newsize/ nBlockAlign ; It will "round" newsize
Newsize = Newsize* nBlockAlign ; Restore the good rounded value
Summary:
offset (hexa) |
name |
length (byte) |
description |
|
0 |
00h |
rID |
4 |
contains "RIFF" |
4 |
04h |
rLen |
4 |
size of the file |
8 |
08h |
wID |
4 |
contains "WAVE" |
Format Chunk:
offset (hexa) |
name |
length (byte) |
description |
|
12 |
0Ch |
fId |
4 |
contains "fmt " ("fmt space ") |
16 |
10h |
fLen |
4 |
Chunck length |
20 |
14h |
wFormatTag |
2 |
format (1 = Microsoft Pulse Code Modulation PCM) |
22 |
16h |
nChannels |
2 |
number of channels (1=mono, 2=stereo) |
24 |
18h |
nSamplesPerSec |
4 |
Sampling frequency (in Hz) |
28 |
1Ch |
nAvgBytesPerSec |
4 |
= nChannels * nSamplesPerSec * (nBitsPerSample/8) |
32 |
20h |
nBlockAlign |
2 |
= nChannels * (nBitsPerSample / 8) |
34 |
22h |
nBitsPerSample |
2 |
length of one sample in bits (8, 16, 24 ou 32) |
WAVE Data Chunk:
offset (hexa) |
name |
length (octet) |
description |
|
36 |
24h |
dId |
4 |
contain"data" |
40 |
28h |
dLen |
4 |
length of dData chunck(in bytes) |
44 et plus |
2Ch |
dData |
dLen |
Sound datas |
NOTE FOR PUREBASIC
There is not any problem to read, transform and write 16, or 32 bits data.
Data.l = PeekW (*adress) or PeekL(*adress)
.
. your job here
.
PokeW(*adress,Data) or PokeL(*adress,Data)
It's a bit less simple with 8 bits data because PureBasic always considere that datas are signed and it's not the case with 8 bits datas. The mid point for a 8 bits sample is 127, it's not zero. So, you have to do that :
Read 8 bits datas
Data.l = PeekB(*adress)
If Data<0 : Data + 256 : EndIf ; transform signed to unsigned
Data - 127 ; set mid point to zero
Store 8 bits datas
If Data>127 : Data = 127 : Endif
Data + 127
PokeB (*adress,Data)
Convert 8 bits to 16 bits :
Data = PeekB(*Sourceadress)
If Data<0 : Data + 256 : EndIf
Data - 127
Data * 256
PokeW(*Destinationadress,Data)