A WavPack file is made of blocks, and every block starts with this 32-byte header. The format applies from WavPack 4.0 on; older files use the legacy header. Numbers are little-endian.
Fields
| Offset | Size | Type | Field | Meaning |
|---|---|---|---|---|
| 0 | 4 | char[4] | ckID | wvpk |
| 4 | 4 | uint32 | ckSize | Bytes in the block after this field: the block’s total size minus 8. Even, and at least 24 |
| 8 | 2 | int16 | version | The stream version, 0x402 to 0x410 |
| 10 | 1 | uint8 | block_index_u8 | Bits 32 to 39 of block_index |
| 11 | 1 | uint8 | total_samples_u8 | Bits 32 to 39 of total_samples |
| 12 | 4 | uint32 | total_samples | Samples per channel in the file. All 1s in these 32 bits means unknown |
| 16 | 4 | uint32 | block_index | Index of this block’s first sample |
| 20 | 4 | uint32 | block_samples | Samples per channel in this block; 0 means the block has no audio |
| 24 | 4 | uint32 | flags | See below |
| 28 | 4 | uint32 | crc | A checksum of the decoded samples |
Both sample counts are 40 bits, so the most samples a file can hold is 2⁴⁰ − 257.
Flags
| Bits | Mask | Name | Meaning |
|---|---|---|---|
| 0–1 | 0x00000003 | BYTES_STORED | Bytes per sample minus 1, so 0 to 3 for 1 to 4 bytes |
| 2 | 0x00000004 | MONO_FLAG | Mono: not stereo |
| 3 | 0x00000008 | HYBRID_FLAG | Hybrid mode, so the block is lossy on its own |
| 4 | 0x00000010 | JOINT_STEREO | Stereo is coded as mid and side |
| 5 | 0x00000020 | CROSS_DECORR | Cross-channel decorrelation |
| 6 | 0x00000040 | HYBRID_SHAPE | Hybrid noise shaping |
| 7 | 0x00000080 | FLOAT_DATA | IEEE 32-bit floating-point samples |
| 8 | 0x00000100 | INT32_DATA | Integer samples of more than 24 bits, or that need special handling |
| 9 | 0x00000200 | HYBRID_BITRATE | Hybrid parameters control the bit rate, not the noise level |
| 10 | 0x00000400 | HYBRID_BALANCE | Hybrid balance between channels |
| 11 | 0x00000800 | INITIAL_BLOCK | First block of a multichannel set |
| 12 | 0x00001000 | FINAL_BLOCK | Last block of a multichannel set |
| 13–17 | 0x0003E000 | SHIFT | Left shift applied to the data after decoding, 0 to 31 places |
| 18–22 | 0x007C0000 | MAG | The largest magnitude in the block, as a bit count minus 1 |
| 23–26 | 0x07800000 | SRATE | Sample rate index; see below |
| 27 | 0x08000000 | IGNORED_FLAGS | Reserved, and ignored by decoders |
| 28 | 0x10000000 | HAS_CHECKSUM | The block contains a block checksum |
| 29 | 0x20000000 | NEW_SHAPING | Newer noise-shaping method |
| 30 | 0x40000000 | FALSE_STEREO | Mono data stored for a stereo stream: the two channels are the same |
| 31 | 0x80000000 | DSD_FLAG | The block holds DSD audio |
A block carrying one channel’s data has MONO_FLAG or FALSE_STEREO set.
Sample rate index
| Index | Rate | Index | Rate |
|---|---|---|---|
| 0 | 6,000 | 8 | 32,000 |
| 1 | 8,000 | 9 | 44,100 |
| 2 | 9,600 | 10 | 48,000 |
| 3 | 11,025 | 11 | 64,000 |
| 4 | 12,000 | 12 | 88,200 |
| 5 | 16,000 | 13 | 96,000 |
| 6 | 22,050 | 14 | 192,000 |
| 7 | 24,000 | 15 | Another rate: see ID_SAMPLE_RATE |
How blocks make up a stream
A block has one or two channels, so a multichannel stream uses several blocks for each time slice, all covering the same samples. The first has INITIAL_BLOCK set, the last FINAL_BLOCK, and a block with both stands alone.
A block with block_samples of 0 holds only metadata. The reference library
looks past up to 16 of these when opening a file.
Finding a block
To find a block in damaged data, the reference reader looks for wvpk, then checks
that ckSize is even, at least 24 and below 1 MiB, and that the version is
in range. It also requires byte 22 to be below 3 and byte 23 to be 0, which keeps
block_samples under 196,608.
Worked example
Flags for 16-bit joint stereo at 44,100 Hz in a single block:
| Part | Value |
|---|---|
| Bytes stored 2, so 1 | 0x00000001 |
| JOINT_STEREO | 0x00000010 |
| INITIAL_BLOCK and FINAL_BLOCK | 0x00001800 |
| Magnitude 15, shifted by 18 | 0x003C0000 |
| Rate index 9, shifted by 23 | 0x04800000 |
| Total | 0x04BC1811, stored as 11 18 BC 04 |