ESOMod:RIFF File Format

Although RIFF files are a very popular data type used for saving WAV files, those used in the game files have modified, shortened headers which cannot be interpreted by media players. This page describes the relatively simple procedure required to make these otherwise-normal WAV files readable by any media player.

EsoAudioSoundSets.mnf Format

The sound files are in the WAVE_FORMAT_EXTENSIBLE structure. All numerical values are little endian.

Original Format

The original header format for WAV files is as such:

    byte  RIFF[4]    = "RIFF"
    dword fileSize
    byte  WAVE[4]    = "WAVE"
    byte  fmt_[4]    = "fmt "
    dword fmtSize    = 0x28000000    //40 bytes
    word  fmtTag     = 0xFEFF        //WAVE_FORMAT_EXTENSIBLE
    word  nChannels
    dword nSamplesPerSec
    dword nAvgBytesPerSec
    word  nBlockAlign
    word  nBitsPerSample
    word  cbSize     = 0x1600        //22 extra bytes of format info
    word  nValidBitsPerSample
    dword channelMask                //See below
    byte  subFormat[16] = 0x0100000000001000800000AA00389B71
    byte  DATA[4]    = "DATA"        //Might be "cue " in later versions
    dword dataSize

For more info on ChannelMask, refer to this site.     

Game Format

The header format for the extracted audio is slightly different:

    byte  RIFF[4]    = "RIFF"
    dword fileSize
    byte  WAVE[4]    = "WAVE"
    byte  fmt_[4]    = "fmt "
    dword fmtSize    = 0x18000000    //24 bytes, not 40
    word  fmtTag     = 0xFEFF        //WAVE_FORMAT_EXTENSIBLE
    word  nChannels
    dword nSamplesPerSec
    dword nAvgBytesPerSec
    word  nBlockAlign
    word  nBitsPerSample
    word  cbSize     = 0x0600        //6 extra bytes of format info, not 22
    word  null1      = 0x0000
    dword channelMask                //Same as above
    byte  JUNK[4]    = "JUNK"
    dword junkSize   = 0x04000000
    dword null2      = 0x00000000
    byte  DATA[4]    = "DATA"
    dword dataSize

Changing Format

In order to modify the header of the sound file, a hex editor has to be used. HxD is recommended, but you can use the one of your preference. Do NOT try using Notepad.

For this example we will examine 164171.riff, which can be extracted from depot\version\eso0028.dat.

Below, the first 64 bytes are listed in the unmodified header. The bytes that will be modified are indicated below:

    52 49 46 46   57 41 56 45 66 6D 74 20    RIFFÄ.¯.WAVEfmt 
      00 00 00 FE FF 02 00 C0 5D 00 00 00 77 01 00    ....þÿ..À]...w..
    04 00 10 00   00   03 00 00 00      ............JUNK
      64 61 74 61 8C 09 AF 01    ........dataŒ.¯.

The modified version of this will be 68 bytes long:

    52 49 46 46   57 41 56 45 66 6D 74 20    RIFFÄ.¯.WAVEfmt     Size increased by 4 bytes
      00 00 00 FE FF 02 00 C0 5D 00 00 00 77 01 00    (...þÿ..À]...w..    fmtSize increased from 0x18 to 0x28
    04 00 10 00   00   03 00 00 00      ................    cbSize increased from 0x06 to 0x16, null1 replaced with nValidBitsPerSample;
      64 61 74 61    ....€..ª.8›qdata    JUNK block replaced with subFormat
    8C 09 AF 01                                        Œ.¯.

Finally, rename the file "164171.wav". Now you're good to go!


EsoAudioEn.mnf Format
The voice over sound files (vo_en) are similarly RIFF format but have a different header format and the previous method doesn't work. You can instead use the ww2ogg utility to convert the RIFF files to OGG with the following comand:

     ww2ogg 000011.riff --pcb packed_codebooks_aoTuV_603.bin


Notes

This conversion process is very crude, but it works for at least some files. Some files do not seem to work with this process, but it's possible that the header can be tweaked to fix these.