vgmstream/doc/TXTH.md
2018-09-22 18:06:15 +02:00

6.9 KiB

TXTH FORMAT

TXTH is a simple text file that uses text commands to simulate a header for files unsupported by vgmstream, mainly headerless audio.

When an unsupported file is loaded, vgmstream tries to find a TXTH header in the same dir, in this order:

  • (filename.ext).txth
  • .(ext).txth
  • .txth

If found and parsed correctly (the TXTH may be rejected if incorrect commands are found) vgmstream will try to play the file as described. Extension must be accepted/added to vgmstream (plugins like foobar2000 only load extensions from a whitelist in formats.c), or one could rename to any supported extension (like .vgmstream), or leave the file extensionless.

Example of a TXTH file

For an unsupported bgm01.vag this would be a simple TXTH for it:

id_value = 0x534E4420       #test that file starts with "SND "
id_offset = @0x00:BE        #test is done at offset 0, big endian value
codec = PSX
sample_rate = @0x10$2       #get sample rate at offset 0x10, 16 bit value
channels = @0x14            #get number of channels at offset 14
interleave = 0x1000         #fixed value
start_offset = 0x100
num_samples = data_size     #find automatically number of samples in the file
loop_flag = auto

A text file with the above commands must be saved as ".vag.txth" or ".txth", notice it starts with a "." (dot). On Windows files starting with a dot can be created by appending a dot at the end: ".txth."

Available commands

######################################################

# comments start with #, can be inline
# The file is made lines of "key = value" describing a header.
# Spaces are optional: key=value, key=   value, and so on are all ok.
# The parser is fairly simple and may be buggy or unexpected in some cases.
# The order of keys is variable but some things won't work if others aren't defined
# (ex. bytes-to-samples may not work without channels or interleave).

# Common values:
# - (number): constant number in dec/hex.
#   Examples: 44100, 40, 0x40 (dec=64)
# - (offset): format is @(number)[:LE|BE][$1|2|3|4]
#   * @(number): value at offset (required)
#   * :LE|BE: value is little/big endian (optional, defaults to LE)
#   * $1|2|3|4: value has size of 8/16/24/32 bit (optional, defaults to 4)
#   Examples: @0x10:BE$2 (get big endian 16b value at 0x10)
# - {string}: special values for certain keys, described below

# Codec used to encode the data [REQUIRED]
# Accepted codec strings:
# - PSX            PlayStation ADPCM
# - XBOX           Xbox IMA ADPCM
# - NGC_DTK        Nintendo ADP/DTK ADPCM
# - PCM16BE        PCM RAW 16bit big endian
# - PCM16LE        PCM RAW 16bit little endian
# - PCM8           PCM RAW 8bit
# - SDX2           Squareroot-delta-exact 8-bit DPCM (3DO games)
# - DVI_IMA        DVI IMA ADPCM
# - MPEG           MPEG Audio Layer File (MP1/2/3)
# - IMA            IMA ADPCM
# - AICA           Yamaha AICA ADPCM (Dreamcast)
# - MSADPCM        Microsoft ADPCM (Windows)
# - NGC_DSP        Nintendo GameCube ADPCM
# - PCM8_U_int     PCM RAW 8bit unsigned (interleaved)
# - PSX_bf         PlayStation ADPCM with bad flags
# - MS_IMA         Microsoft IMA ADPCM
# - PCM8_U         PCM RAW 8bit unsigned
# - APPLE_IMA4     Apple Quicktime IMA ADPCM
# - ATRAC3         raw ATRAC3
# - ATRAC3PLUS     raw ATRAC3PLUS
# - XMA1           raw XMA1
# - XMA2           raw XMA2
# - FFMPEG         any headered FFmpeg format
codec = (codec string)
 
# Varies with codec:
# - NGC_DSP: 0=normal interleave, 1=byte interleave, 2=no interleave
# - ATRAC3: 0=autodetect joint stereo, 1=force joint stereo, 2=force normal stereo
# - XMA1|XMA2: 0=dual multichannel (2ch xN), 1=single multichannel (1ch xN)
# - XBOX: 0=standard (mono or stereo interleave), 1=force mono interleave mode
# - others: ignored
codec_mode = (number)
 
# Interleave or block size [REQUIRED/OPTIONAL, depends on codec]
# For mono/interleaved codecs it's the amount of data between channels.
# For codecs with variable-sized frames (MSADPCM, MS-IMA, ATRAC3/plus)
# it's the block size (size of a single frame).
# Interleave 0 means "stereo mode" for some codecs (IMA, AICA, etc).
interleave = (number)|(offset)

# Validate that id_value matches value at id_offset [OPTIONAL]
# Can be redefined several times, it's checked whenever a new id_offset is found.
id_value = (number)|(offset)
id_offset = (number)|(offset)
 
# Number of channels [REQUIRED]
channels = (number)|(offset)
 
# Music frequency in hz [REQUIRED]
sample_rate = (number)|(offset)
 
# Data start [OPTIONAL, default to 0]
start_offset = (number)|(offset)
 
# Variable that can be used in sample values [OPTIONAL]
# Defaults to (file_size - start_offset), re-calculated when start_offset is set.
data_size = (number)|(offset)
 
 
# Modifies the meaning of sample fields when set *before* them [OPTIONAL, defaults to samples]
# - samples: exact sample
# - bytes: automatically converts bytes/offset to samples
# - blocks: same as bytes, but value is given in blocks/frames
#   Value is internally converted from blocks to bytes first: bytes = (value * interleave*channels)
# It's possible to re-define values multiple times:
#  * samples_type=bytes ... num_samples=@0x10
#  * samples_type=sample ... loop_end_sample=@0x14
# Sometimes "bytes" values are given for a single channel only. In that case you can temporally set 1 channel
#  * channels=1 ... sample_type=bytes ... num_samples=@0x10 ... channels=2
# Some codecs can't convert bytes-to-samples at the moment: MPEG/FFMPEG
# For XMA1/2 bytes does special parsing, with loop values being bit offsets within data.
sample_type = samples|bytes|blocks
 
# Various sample values [REQUIRED (num_samples) / OPTIONAL (rest)]
num_samples         = (number)|(offset)|data_size
loop_start_sample   = (number)|(offset)
loop_end_sample     = (number)|(offset)|data_size

# For XMA1/2 + sample_type=bytes it means loop subregion, if read after loop values.
# For other codecs its added to loop start/end, if read before loop values
# (rarely a format may have rough loop offset/bytes, then a loop adjust in samples).
loop_adjust = (number)|(offset)

# Force loop, on (>0) or off (0), as loop start/end may be defined but not used [OPTIONAL]
# By default it loops when loop_end_sample is defined
# auto tries to autodetect loop points for PS-ADPCM data, which may include loop flags.
loop_flag = (number)|(offset)|auto

# beginning samples to skip (encoder delay), for codecs that need them (ATRAC3/XMA/etc)
skip_samples = (number)|(offset)


# DSP coefficients [REQUIRED for NGC_DSP]
# Coefs start
coef_offset = (number)|(offset)
# offset separation per channel, usually 0x20
# - Example: channel N coefs are read at coef_offset + coef_spacing * N
coef_spacing = (number)|(offset)
# Format, usually BE; with (offset): 0=LE, >0=BE
coef_endianness = BE|LE|(offset)
# Split/normal coefs [NOT IMPLEMENTED YET]
#coef_mode = (number)|(offset)