The BODY chunk holds the samples: signed 8-bit values from −128 to 127. If
sCompression in the voice
header is not 0, the whole chunk must be decompressed first, and everything on this
page then applies to the result. An odd-length chunk has a pad byte.
Octaves
The body can hold the same sound at several octaves. They are stored from the highest pitch to the lowest, each one in two parts: first the one-shot part, played once, then the repeating part, which plays as long as the note is held. Each lower octave has twice as many samples as the one above it, covering the same number of cycles.
| Octave | Samples |
|---|---|
| 0, highest | oneShotHiSamples + repeatHiSamples |
| 1 | 2 × that |
| 2 | 4 × that |
| n | 2n × that |
The body holds (2ctOctave − 1) × (oneShotHiSamples
+ repeatHiSamples) samples in all. A three-octave sound of 100 samples in
its highest octave holds 100 + 200 + 400 = 700 samples.
Stereo
A CHAN value of
6 means stereo. The body is then the left channel’s data followed by the right
channel’s, the two the same length: the channels are not interleaved.
Fibonacci-delta compression
With sCompression 1, each sample is stored as a 4-bit code, an index into
a table of differences from the previous sample. The method roughly halves the data and
adds distortion; the specification advises against it for instruments.
| Offset | Size | Name | Description |
|---|---|---|---|
| 0 | 1 | pad | a pad byte, ignored |
| 1 | 1 | initial | the starting value, as a signed byte |
| 2 | n − 2 | codes | 4-bit codes, two to a byte, the high nibble first |
| Code | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| Delta | −34 | −21 | −13 | −8 | −5 | −3 | −2 | −1 |
| Code | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|
| Delta | 0 | 1 | 2 | 3 | 5 | 8 | 13 | 21 |
Decoding starts from the initial value. For each code, add its delta to the running value and output the result as the next sample. A body of n compressed bytes decodes to 2 × (n − 2) samples.
Compressed stereo stores a pad byte, an initial value and the codes separately for each channel, as FFmpeg reads it.
A worked example, with the bytes 00 40 89 7B:
| Step | Code | Delta | Output |
|---|---|---|---|
| initial | 64 | ||
high nibble of 89 | 8 | 0 | 64 |
low nibble of 89 | 9 | 1 | 65 |
high nibble of 7B | 7 | −1 | 64 |
low nibble of 7B | 11 | 3 | 67 |
The initial value is not itself output, so the four codes give four samples: 64, 65, 64 and 67.
Exponential-delta
FFmpeg also reads sCompression 2, which it calls exponential. It works
exactly as above with this table. It is not part of the published specification.
| Code | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |
|---|---|---|---|---|---|---|---|---|
| Delta | −128 | −64 | −32 | −16 | −8 | −4 | −2 | −1 |
| Code | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
|---|---|---|---|---|---|---|---|---|
| Delta | 0 | 1 | 2 | 4 | 8 | 16 | 32 | 64 |