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)