📄 wave.htm
字号:
dwsegments is not 0, it is followed by that many segment structures, one after the other.
because all fields in a segment structure are an even number of bytes, the length of any
segment will always be even. thus, segments are packed together with no unused bytes
between them. the segments need not be placed in any particular order.</p>
<hr>
<h3>associated data list</h3>
<p>the associated data list contains text "labels" or "names" that are
associated with the cuepoint structures in the cue chunk. in other words, this list
contains the text labels for those cuepoints. </p>
<p>again, we're talking about another imbedded iff list within the wave file.
noooooooooooooo!!!! what's a list? a list is simply a "master chunk" that
contains several "sub-chunks". just like with any other chunk, the "master
chunk" has an id and chunksize, but inside of this chunk are sub-chunks, each with
its own id and chunksize. of course, the chunksize for the master chunk (ie, list)
includes the size of all of these sub-chunks (including their id and chunksize fields).</p>
<p>the "type id" for the associated data list is "adtl". remember that
an iff list header has 3 fields:</p>
<pre>
typedef struct {
id listid; /* 'list' */
long chunksize; /* includes the type id below */
id typeid; /* 'adtl' */
} listheader;
</pre>
<p>there are several sub-chunks that may be found inside of the associated data list. the
ones that are important to wave format have ids of "labl", "note", or
"ltxt". ignore the rest. here are those 3 sub-chunks and their fields: </p>
<p>the associated data list is optional. the wave documentation doesn't specify if more
than one can be contained in a wave file.</p>
<h4>label chunk</h4>
<pre>
#define labelid 'labl' /* chunk id for label chunk */
typedef struct {
id chunkid;
long chunksize;
long dwidentifier;
char dwtext[];
} labelchunk;
</pre>
<p>the id is always <b>labl</b>. chunksize is the number of bytes in the chunk, not
counting the 8 bytes used by id and size fields nor any possible pad byte needed to make
the chunk an even size (ie, chunksize is the number of remaining bytes in the chunk after
the chunksize field, not counting any trailing pad byte). </p>
<p>the dwidentifier field contains a unique number (ie, different than the id number of
any other label chunk). this field should correspond with the dwindentifier field of some
cuepoint stored in the cue chunk. in other words, this label chunk contains the text label
associated with that cuepoint structure with the same id number.</p>
<p>the dwtext array contains the text label. it should be a null-terminated string. (the
null byte is included in the chunksize, therefore the length of the string, including the
null byte, is chunksize - 4).</p>
<h4>note chunk</h4>
<pre>
#define noteid 'note' /* chunk id for note chunk */
typedef struct {
id chunkid;
long chunksize;
long dwidentifier;
char dwtext[];
} notechunk;
</pre>
<p>the note chunk, whose id is <b>note</b>, is otherwise exactly the same as the label
chunk (ie, same fields). see what i mean about pointless duplication? but, in theory, a
note chunk contains a "comment" about a cuepoint, whereas the label chunk is
supposed to contain the actual cuepoint label. so, it's possible that you'll find both a
note and label for a specific cuepoint, each containing different text. </p>
<h4>labeled text chunk</h4>
<pre>
#define labeltextid 'ltxt' /* chunk id for labeled text chunk */
typedef struct {
id chunkid;
long chunksize;
long dwidentifier;
long dwsamplelength;
long dwpurpose;
short wcountry;
short wlanguage;
short wdialect;
short wcodepage;
char dwtext[];
} labeltextchunk;
</pre>
<p>the id is always <b>ltxt</b>. chunksize is the number of bytes in the chunk, not
counting the 8 bytes used by id and size fields nor any possible pad byte needed to make
the chunk an even size (ie, chunksize is the number of remaining bytes in the chunk after
the chunksize field, not counting any trailing pad byte). </p>
<p>the dwidentifier field is the same as the label chunk.</p>
<p>the dwsamplelength field specifies the number of sample points in the segment of
waveform data. in other words, a labeled text chunk contains a label for a <b>section</b>
of the waveform data, not just a specific point, for example the looped section of a
waveform.</p>
<p>the dwpurpose field specifies the type or purpose of the text. for example, dwpurpose
can contain an id like "scrp" for script text or "capt" for
close-caption text. how is this related to waveform data? well, it isn't really. it's just
that associated data lists are used in other file formats, so they contain generic fields
that sometimes don't have much relevance to waveform data.</p>
<p>the wcountry, wlanguage, and wcodepage fields specify the country code,
language/dialect, and code page for the text. an application typically queries these
values from the operating system.</p>
<hr>
<h3>sampler chunk</h3>
<p>the sampler (smpl) chunk defines basic parameters that an instrument, such as a midi
sampler, could use to play the waveform data. most importantly, it includes information
about looping the waveform (ie, during playback, to "sustain" the waveform). of
course, as you've come to expect from the wave file format, it duplicates some of the
information that can be found in the cue and playlist chunks, but fortunately, in a more
sensible, consistent, better-documented way.</p>
<pre>
#define samplerid 'smpl' /* chunk id for sampler chunk */
typedef struct {
id chunkid;
long chunksize;
long dwmanufacturer;
long dwproduct;
long dwsampleperiod;
long dwmidiunitynote;
long dwmidipitchfraction;
long dwsmpteformat;
long dwsmpteoffset;
long csampleloops;
long cbsamplerdata;
struct sampleloop loops[];
} samplerchunk;
</pre>
<p>the id is always <b>smpl</b>. chunksize is the number of bytes in the chunk, not
counting the 8 bytes used by id and size fields nor any possible pad byte needed to make
the chunk an even size (ie, chunksize is the number of remaining bytes in the chunk after
the chunksize field, not counting any trailing pad byte). </p>
<p>the dwmanufacturer field contains the mma manufacturer code for the intended sampler.
each manufacturer of midi products has his own id assigned to him by the midi
manufacturer's association. the high byte of dwmanufacturer indicates the number of low
order bytes (1 or 3) that are valid for the manufacturer code. for example, this value
will be 0x01000013 for digidesign (the mma manufacturer code is one byte, 0x13); whereas
0x03000041 identifies microsoft (the mma manufacturer code is three bytes, 0x00 0x00
0x41). if the wave is not intended for a specific manufacturer, then this field should be
set to 0.</p>
<p>the dwproduct field contains the product code (ie, model id) of the intended sampler
for the dwmanufacturer. contact the manufacturer of the sampler to ascertain the sampler's
model id. if the wave is not intended for a specific manufacturer's product, then this
field should be set to 0.</p>
<p>the dwsampleperiod field specifies the period of one sample in nanoseconds (normally
1/nsamplespersec from the format chunk. but note that this field allows finer tuning than
nsamplespersec). for example, 44.1 khz would be specified as 22675 (0x00005893).</p>
<p>the dwmidiunitynote field is the midi note number at which the instrument plays back
the waveform data without pitch modification (ie, at the same sample rate that was used
when the waveform was created). this value ranges 0 through 127, inclusive. middle c is
60.</p>
<p>the dwmidipitchfraction field specifies the fraction of a semitone up from the
specified dwmidiunitynote. a value of 0x80000000 is 1/2 semitone (50 cents); a value of
0x00000000 represents no fine tuning between semitones.</p>
<p>the dwsmpteformat field specifies the smpte time format used in the dwsmpteoffset
field. possible values are:</p>
<pre>
0 = no smpte offset (dwsmpteoffset should also be 0)
24 = 24 frames per second
25 = 25 frames per second
29 = 30 frames per second with frame dropping ('30 drop')
30 = 30 frames per second
</pre>
<p>the dwsmpteoffset field specifies a time offset for the sample if it is to be
syncronized or calibrated according to a start time other than 0. the format of this value
is 0xhhmmssff. hh is a signed hours value [-23..23]. mm is an unsigned minutes value
[0..59]. ss is unsigned seconds value [0..59]. ff is an unsigned value [0..(<dwsmpteformat> - 1)]. </p>
<p>the csampleloops field is the number (count) of sampleloop structures that are appended
to this chunk. these structures immediately follow the cbsamplerdata field. this field
will be 0 if there are no sampleloop structures.</p>
<p>the cbsamplerdata field specifies the size (in bytes) of any optional fields that an
application wishes to append to this chunk. an application which needed to save additional
information (ie, beyond the above fields) may append additional fields to the end of this
chunk, after all of the sampleloop structures. these additional fields are also reflected
in the chunksize, and remember that the chunk should be padded out to an even number of
bytes. the cbsamplerdata field will be 0 if no additional information is appended to the
chunk.</p>
<p>what follows the above fields are any sampleloop structures. each sampleloop structure
defines one loop (ie, the start and end points of the loop, and how many times it plays).
what follows any sampleloop structures are any additional, proprietary sampler information
that an application chooses to store.</p>
<h4>sampleloop structure</h4>
<pre>
typedef struct {
long dwidentifier;
long dwtype;
long dwstart;
long dwend;
long dwfraction;
long dwplaycount;
} sampleloop;
</pre>
<p>the dwidentifier field contains a unique number (ie, different than the id number of
any other sampleloop structure). this field may correspond with the dwidentifier field of
some cuepoint stored in the cue chunk. in other words, the cuepoint structure which has
the same id number would be considered to be describing the same loop as this sampleloop
structure. furthermore, this field corresponds to the dwindentifier field of any label
stored in the associated data list. in other words, the text string (within some chunk in
the associated data list) which has the same id number would be considered to be this
loop's "name" or "label".</p>
<p>the dwtype field is the loop type (ie, how the loop plays back) as so:</p>
<pre>
0 - loop forward (normal)
1 - alternating loop (forward/backward)
2 - loop backward
3-31 - reserved for future standard types
32-? - sampler specific types (manufacturer defined)
</pre>
<p>the dwstart field specifies the startpoint of the loop. in other words, it's the byte
offset from the start of waveformdata[], where an offset of 0 would be at the start of the
waveformdata[] array (ie, the loop start is at the very first sample point). </p>
<p>the dwend field specifies the endpoint of the loop (ie, a byte offset).</p>
<p>the dwfraction field allows fine-tuning for loop fractional areas between samples.
values range from 0x00000000 to 0xffffffff. a value of 0x80000000 represents 1/2 of a
sample length.</p>
<p>the dwplaycount field is the number of times to play the loop. a value of 0 specifies
an infinite sustain loop (ie, the wave keeps looping until some external force interrupts
playback, such as the musician releasing the key that triggered that wave's playback).</p>
<p>the sampler chunk is optional. i don't know as if there is any limit of one per wave
file. i don't see why there should be such a limit, since after all, an application may
need to deal with several midi samplers.</p>
<h3>the instrument chunk format</h3>
<p>the instrument chunk contains some of the same type of information as the sampler
chunk. so what else is new? </p>
<pre>
#define instrumentid 'inst' /* chunkid for instruments chunk */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -