WavPack’s main path codes integers of up to 24 bits. Floating-point audio, wider integers and DSD each have an extra layer. Float and wide-integer files split each sample into an integer part in the main stream and extra bits in the WVX stream.
Floating point (ID_FLOAT_INFO)
Exactly 4 bytes:
| Offset | Field | Meaning |
|---|---|---|
| 0 | float_flags | See below |
| 1 | float_shift | Left shift of the integer values, up to 31 |
| 2 | float_max_exp | The starting exponent |
| 3 | float_norm_exp | The exponent for normalised output |
| Mask | Name | Meaning |
|---|---|---|
0x01 | FLOAT_SHIFT_ONES | Bits shifted out are filled with 1s |
0x02 | FLOAT_SHIFT_SAME | A WVX bit says whether the low bits are all 1s |
0x04 | FLOAT_SHIFT_SENT | Low bits are read from the WVX stream |
0x08 | FLOAT_ZEROS_SENT | Zero samples carry extra data in the WVX stream |
0x10 | FLOAT_NEG_ZEROS | A sign bit is stored for zero samples |
0x20 | FLOAT_EXCEPTIONS | The block contains exceptions |
Rebuilding a float
- For a zero sample with FLOAT_ZEROS_SENT, the WVX stream has a presence bit. If set: a 23-bit mantissa, an 8-bit exponent (only when the block’s exponent is 25 or more) and a sign bit. If clear and FLOAT_NEG_ZEROS is set, only a sign bit.
- For anything else, shift the integer left by
float_shift. A negative value is negated and gets the sign bit. A magnitude of exactly 0x1000000 means an exponent of 255, with an optional 23-bit mantissa. - Normalise until bit 23 is set, lowering the exponent, and counting the shifts.
- Fill those shifted bits as the flags say.
Without a WVX stream the lossy path shifts down values at or above 0x1000000 and does not compute
the CRC. With one, the update is
crc = crc × 27 + mantissa × 9 + exponent × 3 + sign.
Wide integers (ID_INT32_INFO)
Exactly 4 bytes:
| Offset | Field | After decoding |
|---|---|---|
| 0 | sent_bits | Low-order bits sent in the WVX stream (FFmpeg allows up to 30) |
| 1 | zeros | x <<= zeros |
| 2 | ones | x = ((x + 1) << ones) − 1 |
| 3 | dups | x = ((x + (x & 1)) << dups) − (x & 1) |
The header’s SHIFT is applied too. The extra bits are read from the WVX stream, in widths limited by the largest width given in the newer WVX form.
DSD (ID_DSD_BLOCK)
A block with DSD_FLAG holds 1-bit audio. The sample rate in the header is multiplied by
1 << shift.
| Offset | Field | Meaning |
|---|---|---|
| 0 | Rate shift | 0 to 31. Used from the first stream only |
| 1 | Mode | 0 raw, 1 fast, 3 high. Any other value is an error |
Mode 0: raw
One byte per sample per channel. The data length must be exactly block_samples × channels.
Mode 1: fast
| Field | Size | Meaning |
|---|---|---|
| History bits | 1 | At most 5. There are 1 << bits bins |
| Max probability | 1 | Below 0xFF the table is run-length coded; 0xFF means bins × 256 raw bytes follow |
| Probability table | varies | In the run-length form, codes above the maximum are runs of zeros, others are literal values, and a zero byte ends it |
| Range coder start | 4 | Then the data |
Per-bin sums are capped at bins × 1280.
Mode 3: high
| Field | Size | Meaning |
|---|---|---|
| rate_i | 1 | Used to build a 256-entry probability table |
| rate_s | 1 | Must be 20 |
| Per channel | 7 each | Five filter bytes, shifted left by 12, then a 16-bit signed factor, low byte first |
| Range coder start | 4 | Then the data |
After the rate shift and mode bytes, this mode needs at least 13 bytes for mono (2 + 7 + 4) and 20 for stereo (2 + 14 + 4). A sixth filter value starts at 0.