📄 wave file format.mht
字号:
are meant=20
to be "played" (ie, sent to a DAC) simultaneously are stored =
contiguously.=20
<P>The sample points that are meant to be "played" (ie, sent to a DAC)=20
simultaneously are collectively called a <B>sample frame</B>. In the =
example of=20
our stereo waveform, every two sample points makes up another sample =
frame. This=20
is illustrated below for that stereo example. <PRE> sample sample =
sample
frame 0 frame 1 frame N
_____ _____ _____ _____ _____ _____
| ch1 | ch2 | ch1 | ch2 | . . . | ch1 | ch2 |
|_____|_____|_____|_____| |_____|_____|
_____
| | =3D one sample point
|_____|
</PRE>For a monophonic waveform, a sample frame is merely a single =
sample point=20
(ie, there's nothing to interleave). For multichannel waveforms, you =
should=20
follow the conventions shown below for which order to store channels =
within the=20
sample frame. (ie, Below, a single sample frame is displayed for each =
example of=20
a multichannel waveform). <PRE> channels 1 2
_________ _________=20
| left | right |
stereo | | |
|_________|_________|
1 2 3
_________ _________ _________=20
| left | right | center |
3 channel | | | |
|_________|_________|_________|
1 2 3 4
_________ _________ _________ _________=20
| front | front | rear | rear |
quad | left | right | left | right |
|_________|_________|_________|_________|
1 2 3 4
_________ _________ _________ _________=20
| left | center | right | surround|
4 channel | | | | |
|_________|_________|_________|_________|
1 2 3 4 5 6
_________ _________ _________ _________ _________ _________
| left | left | center | right | right |surround =
|
6 channel | center | | | center | | =
|
=
|_________|_________|_________|_________|_________|_________|
</PRE>The sample points within a sample frame are packed together; there =
are no=20
unused bytes between them. Likewise, the sample frames are packed =
together with=20
no pad bytes.=20
<P>Note that the above discussion outlines the format of data within an=20
uncompressed data chunk. There are some techniques of storing compressed =
data in=20
a data chunk. Obviously, that data would need to be uncompressed, and =
then it=20
will adhere to the above layout.</P>
<HR>
<H3><FONT color=3D#ff8040>Format chunk</FONT></H3>The Format (fmt) chunk =
describes=20
fundamental parameters of the waveform data such as sample rate, bit =
resolution,=20
and how many channels of digital audio are stored in the WAVE. =
<PRE><B><FONT size=3D3><FONT color=3Dgreen>#define</FONT> FormatID 'fmt =
' <FONT color=3Dbrown>/* chunkID for Format Chunk. NOTE: There is a =
space at the end of this ID. */</FONT>
<FONT color=3Dgreen>typedef struct</FONT> {
ID chunkID;
<FONT color=3Dgreen>long</FONT> chunkSize;
<FONT color=3Dgreen>short</FONT> wFormatTag;
<FONT color=3Dgreen>unsigned short</FONT> wChannels;
<FONT color=3Dgreen>unsigned long</FONT> dwSamplesPerSec;
<FONT color=3Dgreen>unsigned long</FONT> dwAvgBytesPerSec;
<FONT color=3Dgreen>unsigned short</FONT> wBlockAlign;
<FONT color=3Dgreen>unsigned short</FONT> wBitsPerSample;
<FONT color=3Dbrown>/* Note: there may be additional fields here, =
depending upon wFormatTag. */</FONT>
} FormatChunk;
</FONT></B></PRE>The ID is always "<B>fmt </B>". The chunkSize field is =
the=20
number of bytes in the chunk. This does not include the 8 bytes used by =
ID and=20
Size fields. For the Format Chunk, chunkSize may vary according to what =
"format"=20
of WAVE file is specified (ie, depends upon the value of wFormatTag).=20
<P>WAVE data may be stored without compression, in which case the sample =
points=20
are stored as described in <B>Sample Points and Sample Frames</B>. =
Alternately,=20
different forms of compression may be used when storing the sound data =
in the=20
Data chunk. With compression, each sample point may take a differing =
number of=20
bytes to store. The wFormatTag indicates whether compression is used =
when=20
storing the data.</P>
<P>If compression is used (ie, WFormatTag is some value other than 1), =
then=20
there will be additional fields appended to the Format chunk which give =
needed=20
information for a program wishing to retrieve and decompress that stored =
data.=20
The first such additional field will be an unsigned short that indicates =
how=20
many more bytes have been appended (after this unsigned short). =
Furthermore,=20
compressed formats must have a Fact chunk which contains an unsigned =
long=20
indicating the size (in sample points) of the waveform after it has been =
decompressed. There are (too) many compressed formats. Details about =
them can be=20
gotten from Microsoft's web site.</P>
<P>If no compression is used (ie, wFormatTag =3D 1), then there are no =
further=20
fields.</P>
<P>The wChannels field contains the number of audio channels for the =
sound. A=20
value of 1 means monophonic sound, 2 means stereo, 4 means four channel =
sound,=20
etc. Any number of audio channels may be represented. For multichannel =
sounds,=20
single sample points from each channel are interleaved. A set of =
interleaved=20
sample points is called a sample frame.</P>
<P>The actual waveform data is stored in another chunk, the Data Chunk, =
which=20
will be described later.</P>
<P>The dwSamplesPerSec field is the sample rate at which the sound is to =
be=20
played back in sample frames per second (ie, Hertz). The 3 standard MPC =
rates=20
are 11025, 22050, and 44100 KHz, although other rates may be used.</P>
<P>The dwAvgBytesPerSec field indicates how many bytes play every =
second.=20
dwAvgBytesPerSec may be used by an application to estimate what size RAM =
buffer=20
is needed to properly playback the WAVE without latency problems. Its =
value=20
should be equal to the following formula rounded up to the next whole=20
number:</P>
<P>dwSamplesPerSec * wBlockAlign</P>
<P>The wBlockAlign field should be equal to the following formula, =
rounded to=20
the next whole number:</P>
<P>wChannels * (wBitsPerSample / 8)</P>
<P>Essentially, wBlockAlign is the size of a sample frame, in terms of =
bytes.=20
(eg, A sample frame for a 16-bit mono wave is 2 bytes. A sample frame =
for a=20
16-bit stereo wave is 4 bytes. Etc).</P>
<P>The wBitsPerSample field indicates the bit resolution of a sample =
point (ie,=20
a 16-bit waveform would have wBitsPerSample =3D 16).</P>
<P>One, and only one, Format Chunk is required in every WAVE.</P>
<HR>
<H3><FONT color=3D#ff8040>Data chunk</FONT></H3>
<P>The Data (data) chunk contains the actual sample frames (ie, all =
channels of=20
waveform data).</P><PRE><B><FONT size=3D3><FONT =
color=3Dgreen>#define</FONT> DataID 'data' <FONT color=3Dbrown>/* chunk =
ID for data Chunk */</FONT>
<FONT color=3Dgreen>typedef struct</FONT> {
ID chunkID;
<FONT color=3Dgreen>long</FONT> chunkSize;
<FONT color=3Dgreen>unsigned char</FONT> waveformData[];
} DataChunk;
</FONT></B></PRE>The ID is always <B>data</B>. chunkSize is the number =
of bytes=20
in the chunk, not counting the 8 bytes used by ID and Size fields nor =
any=20
possible pad byte needed to make the chunk an even size (ie, chunkSize =
is the=20
number of remaining bytes in the chunk after the chunkSize field, not =
counting=20
any trailing pad byte).=20
<P>Remember that the bit resolution, and other information is gotten =
from the=20
Format chunk.</P>
<P>The following discussion assumes uncompressed data.</P>
<P>The waveformData array contains the actual waveform data. The data is =
arranged into what are called <EM>sample frames</EM>. For more =
information on=20
the arrangment of data, see "Sample Points and Sample Frames".</P>
<P>You can determine how many bytes of actual waveform data there is =
from the=20
Data chunk's chunkSize field. The number of sample frames in =
waveformData is=20
determined by dividing this chunkSize by the Format chunk's =
wBlockAlign.</P>
<P>The Data Chunk is required. One, and only one, Data Chunk may appear =
in a=20
WAVE.</P>
<H4>Another way of storing waveform data</H4>So, you're thinking "This =
WAVE=20
format isn't that bad. It seems to make sense and there aren't all that =
many=20
inconsistencies, duplications, and inefficiencies". You fool! We're just =
getting=20
started with our first excursion into unnecessary inconsistencies, =
duplications,=20
and inefficiency.=20
<P>Sure, countless brain-damaged programmers have inflicted literally =
dozens of=20
compressed data formats upon the Data chunk, but apparently someone felt =
that=20
even this wasn't enough to make your life difficult in trying to support =
WAVE=20
files. No, some half-wit decided that it would be a good idea to screw =
around=20
with storing waveform data in something other than one Data chunk.=20
NOOOOOOOOOOOOOO!!!!!!</P>
<P>For some god-forsaken reason, someone came up with the idea of using =
an=20
imbedded IFF List inside of the WAVE file. NOOOOOOOOOOOOOOOOO!!!!!!!! =
And this=20
"Wave List" would contain multiple 'data' and 'slnt' chunks.=20
NOOOOOOOOOOOOOOOO!!!! The Type ID for this List is 'wavl'.</P>
<P>I strongly suggest that you refuse to support any WAVE file that =
exhibits=20
this Wave List nonsense. There's no need for it, and hopefully, the =
misguided=20
programmer who conjured it up will be embarrassed into hanging his head =
in shame=20
when nobody agrees to support his foolishness. Just say=20
"NOOOOOOOOOOOOOO!!!!"</P>
<HR>
<H3><FONT color=3D#ff8040>Cue chunk</FONT></H3>The Cue chunk contains =
one or more=20
"cue points" or "markers". Each cue point references a specific offset =
within=20
the waveformData array, and has its own CuePoint structure within this =
chunk.=20
<P>In conjunction with the Playlist chunk, the Cue chunk can be used to =
store=20
looping information.</P>
<H4>CuePoint Structure</H4><PRE><B><FONT size=3D3><FONT =
color=3Dgreen>typedef struct</FONT> {
<FONT color=3Dgreen>long</FONT> dwIdentifier;
<FONT color=3Dgreen>long</FONT> dwPosition;
ID fccChunk;
<FONT color=3Dgreen>long</FONT> dwChunkStart;
<FONT color=3Dgreen>long</FONT> dwBlockStart;
<FONT color=3Dgreen>long</FONT> dwSampleOffset;
} CuePoint;
</FONT></B></PRE>The dwIdentifier field contains a unique number (ie, =
different=20
than the ID number of any other CuePoint structure). This is used to =
associate a=20
CuePoint structure with other structures used in other chunks which will =
be=20
described later.=20
<P>The dwPosition field specifies the position of the cue point within =
the "play=20
order" (as determined by the Playlist chunk. See that chunk for a =
discussion of=20
the play order).</P>
<P>The fccChunk field specifies the chunk ID of the Data or Wave List =
chunk=20
which actually contains the waveform data to which this CuePoint refers. =
If=20
there is only one Data chunk in the file, then this field is set to the =
ID=20
'data'. On the other hand, if the file contains a Wave List (which can =
contain=20
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -