A VOC file is a header followed by a list of typed blocks. Every number is
little-endian. Creative’s specification is not public; this page follows the text
VOC.TXT, which is based on it, and the descriptions in the MultimediaWiki, the
Game Modding wiki and SoX’s source code. Disagreements are noted.
File header
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 19 | char | identifier | Creative Voice File |
| 19 | 1 | u8 | end-of-file mark | 0x1A, which stopped the DOS TYPE command printing the rest |
| 20 | 2 | u16 | header size | the offset of the first block, usually 26 |
| 22 | 2 | u16 | version | major in the high byte, minor in the low byte: 0x010A is 1.10 and 0x0114 is 1.20 |
| 24 | 2 | u16 | check | ~version + 0x1234 |
A check word that does not match means the version is invalid. For version 1.10,
~0x010A is 0xFEF5, and adding 0x1234 gives
0x1129, stored as 29 11. For 1.20 the check is
0x111F. SoX’s source calls this a two’s complement, but the worked values
are the one’s complement above.
Block header
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | u8 | type | the block type, 0 to 9 |
| 1 | 3 | u24 | size | the size of the block’s data, without this header |
A type 0 block has no size field. Offsets in the tables below are from the start of a block’s data.
Block types
| Type | Name | Size | Data |
|---|---|---|---|
| 0 | Terminator | none | none; marks the end of the file, and the file may also just end |
| 1 | Sound data | 2 + n | time constant, codec, samples |
| 2 | Sound continue | n | samples, with the settings of the block before |
| 3 | Silence | 3 | length, time constant |
| 4 | Marker | 2 | marker number |
| 5 | Text | n | a zero-terminated string |
| 6 | Repeat start | 2 | repeat count |
| 7 | Repeat end | 0 | none |
| 8 | Extended | 4 | time constant, codec, channels |
| 9 | Sound data, new format | 12 + n | rate, bits, channels, codec, samples |
Type 1: sound data
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 1 | u8 | time constant | sets the sample rate; see Sample rates |
| 1 | 1 | u8 | codec | see Codecs |
| 2 | n | bytes | samples |
The Game Modding wiki says this block is generally found only in older files, superseded by type 9.
Type 2: sound continue
Only samples, using the codec and rate of the previous sound data block. A long sound can be spread over several blocks in this way.
Type 3: silence
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | u16 | length | the length of the silence in samples, minus 1 |
| 2 | 1 | u8 | time constant | as for type 1 |
Type 4: marker
A u16 value, used by a program to synchronise sound with animation or
other actions.
Type 5: text
A zero-terminated ASCII string, for comments.
Types 6 and 7: repeat
Block 6 starts a repeated section. Its data is a u16 count: the number of
times to play the section minus one, so 0 plays it once and 1 twice. A value of
0xFFFF repeats for ever. Block 7, with no data, ends
the section, and playback goes back to the block after the most recent block 6.
Type 8: extended
This block has no audio of its own. It sets the rate, codec and channels for the sound data block after it, overriding that block’s own values. It allows stereo and rates above what a single-byte time constant can reach. Sources differ on whether it came with version 1.10 or 1.20.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 2 | u16 | time constant | see Sample rates |
| 2 | 1 | u8 | codec | as for type 1 |
| 3 | 1 | u8 | mode | 0 for mono, 1 for stereo: the number of channels minus 1 |
SoX and the MultimediaWiki say a type 1 block must follow; the Game Modding wiki says type 2. Stereo samples are stored left, then right.
Type 9: sound data, new format
Probably valid only from version 1.20, the MultimediaWiki notes.
| Offset | Size | Type | Name | Description |
|---|---|---|---|---|
| 0 | 4 | u32 | sample rate | the rate in hertz |
| 4 | 1 | u8 | bits per sample | 8 or 16, for example |
| 5 | 1 | u8 | channels | 1 is mono and 2 stereo: the plain count, unlike type 8 |
| 6 | 2 | u16 | codec | see Codecs |
| 8 | 4 | bytes | reserved | padding, zero |
| 12 | n | bytes | samples |
Example
The header of a version 1.10 file, then a type 1 block of 1,000 mono 8-bit samples at 11,111 Hz:
| Offset | Bytes | Meaning |
|---|---|---|
| 0 | 43 72 65 61 74 69 76 65 20 56 6F 69 63 65 20 46 69 6C 65 | Creative Voice File |
| 19 | 1A | end-of-file mark |
| 20 | 1A 00 | header size 26 |
| 22 | 0A 01 | version 1.10 |
| 24 | 29 11 | check |
| 26 | 01 | block type 1 |
| 27 | EA 03 00 | size 1,002 |
| 30 | A6 | time constant 166: 1000000 ÷ (256 − 166) = 11,111 Hz |
| 31 | 00 | codec 0, 8-bit unsigned PCM |
| 32 | 1,000 bytes | samples |
| 1032 | 00 | terminator |