Add .lwma/lmpc/lmp3 as a way to force files into vgmstream

This commit is contained in:
bnnm 2018-10-20 14:54:49 +02:00
parent 929560b53c
commit 31084446b0
2 changed files with 114 additions and 61 deletions

View File

@ -121,39 +121,80 @@ standard, whose docs discuss extending M3U with arbitrary tags.
## Special cases ## Special cases
vgmstream aims to support most file formats as-is, but some files require extra vgmstream aims to support most audio formats as-is, but some files require extra
handling. handling.
### Renamed files ### Renamed files
A few extensions that vgmstream supports clash with common ones. Since players A few extensions that vgmstream supports clash with common ones. Since players
like foobar or Winamp don't react well to that, they may be renamed for like foobar or Winamp don't react well to that, they may be renamed to make
vgmstream (mainly to get looping in some cases). them playable through vgmstream.
- .aac to .laac - .aac to .laac (tri-Ace games)
- .ac3 to .lac3 - .ac3 to .lac3 (standard AC3)
- .aif to .aiffl or .aifcl - .aif to .aiffl or .aifcl (standard Mac AIF)
- .asf to .sng (EA formats) - .asf to .sng (EA games)
- .flac to .lflac - .flac to .lflac (standard FLAC)
- .mp4 to .lmp4 - .mp2 to .lmp2 (standard MP2)
- .ogg to .logg - .mp3 to .lmp3 (standard MP3)
- .opus to .lopus - .mp4 to .lmp4 (standard M4A)
- .stm to .lstm - .mpc to .lmpc (standard MPC)
- .wav to .lwav - .ogg to .logg (standard OGG)
- .opus to .lopus (standard OPUS or Switch OPUS)
- .stm to .lstm (Rockstar STM)
- .wav to .lwav (standard WAV)
- .wma to .lwma (standard WMA)
- .(any) to .vgmstream (FFmpeg formats or TXTH)
Command line tools don't have this restriction and will accept the original Command line tools don't have this restriction and will accept the original
filename. filename.
When extracting from a bigfile sometimes internal files don't have an actual The main advantage to rename them is that vgmstream may use the file's
internal loop info, or apply subtle fixes, but is also limited in some ways
(like standard/player's tagging).
.vgmstream is a catch-all extension that may work as a last resort to make
a file playable.
When extracting from a bigfile, sometimes internal files don't have an actual
name+extension. Those should be renamed to its proper/common extension, as the name+extension. Those should be renamed to its proper/common extension, as the
extractor program may guess wrong (like .wav instead of .at3 or .wem). If extractor program may guess wrong (like .wav instead of .at3 or .wem). If
there is no known extension usually the header id is used instead. there is no known extension, usually the header id string may be used instead.
### Loop assists Note that vgmstream also accepts certain extension-less files too.
### Demuxed videos
vgmstream also supports audio from videos, but usually must be demuxed (extracted
without modification) first, since vgmstream doesn't attempt to support them.
The easiest way to do this is using VGMToolBox's "Video Demultiplexer" option
for common game video formats (.bik, .vp6, .pss, .pam, .pmf, .usm, .xmv, etc).
For standard videos formats (.avi, .mp4, .webm, .m2v, .ogv, etc) not supported
by VGMToolBox FFmpeg binary may work:
- `ffmpeg.exe -i (input file) -vn -acodec copy (output file)`
Output extension may need to be adjusted to some appropriate audio file depending
on the audio codec used. ffprobe.exe can list this codec, though the correct audio
extension depends on the video itself (like .avi to .wav/mp2/mp3 or .ogv to .ogg).
Some games use custom video formats, demuxer scripts in .bms format may be found
on the internet.
### Companion files
Some formats have companion files with external looping info, and should be Some formats have companion files with external looping info, and should be
left together. left together.
- .mus (playlist for .acm) - .mus (playlist for .acm)
- .pos (loop info for .wav: 32 bit LE loop start sample + loop end sample) - .pos (loop info for .wav, and sometimes .ogg)
- .sli (loop info for .ogg) - .ogg.sli or .sli (loop info for .ogg)
- .sfl (loop info for .ogg) - .ogg.sfl (loop info for .ogg)
- .vgmstream + .pos (FFmpeg formats + loop assist) - .vgmstream.pos (loop info for FFmpeg formats)
- also possible for certain extensions like .lflac.pos
Similarly some formats split header and/or data in separate files (.sgh+sgd,
.wav.str+.wav, (file)_L.dsp+(file)_R.dsp, etc). vgmstream will also detect
and use those as needed and must be tegether, even if only one of the two
will be used to play.
.pos is a small file with 32 bit little endian values: loop start sample
and loop end sample. For FFmpeg formats (.vgmstream.pos) it may optionally
have total samples after those.
### Decryption keys ### Decryption keys
Certain formats have encrypted data, and need a key to decrypt. vgmstream Certain formats have encrypted data, and need a key to decrypt. vgmstream
@ -162,7 +203,7 @@ a companion file:
- .adx: .adxkey (derived 6 byte key, in start/mult/add format) - .adx: .adxkey (derived 6 byte key, in start/mult/add format)
- .ahx: .ahxkey (derived 6 byte key, in start/mult/add format) - .ahx: .ahxkey (derived 6 byte key, in start/mult/add format)
- .hca: .hcakey (8 byte decryption key, a 64-bit number) - .hca: .hcakey (8 byte decryption key, a 64-bit number)
- May be followed by 2 byte AWB derivation value for newer HCA - May be followed by 2 byte AWB scramble key for newer HCA
- .fsb: .fsbkey (decryption key, in hex) - .fsb: .fsbkey (decryption key, in hex)
The key file can be ".(ext)key" (for the whole folder), or "(name).(ext)key" The key file can be ".(ext)key" (for the whole folder), or "(name).(ext)key"
@ -182,11 +223,14 @@ Programs like VGMToolbox can help to create GENH.
".txth" or ".(ext).txth" (for the whole folder), or "(name.ext).txth" (for a ".txth" or ".(ext).txth" (for the whole folder), or "(name.ext).txth" (for a
single file). Contains dynamic text commands to read data from the original single file). Contains dynamic text commands to read data from the original
file, or static values. file, or static values.
**TXTP**: a text playlist that works as a single song. Can contain a list of **TXTP**: a text playlist that works as a single song. Can contain a list of
filenames to play as one (ex. "intro.vag" "loop.vag"), name with subsong index filenames to play as one (ex. "intro.vag" "loop.vag"), name with subsong index
(ex. bgm.sxd#10), or mask channels to only play some (ex. "song.adx#c1,2"). (ex. bgm.sxd#10), or mask channels to only play some (ex. "song.adx#c1,2").
Creation of those files is meant for advanced users, docs can be found in
vgmstream source.
## Supported codec types ## Supported codec types
Quick list of codecs vgmstream supports, including many obscure ones that Quick list of codecs vgmstream supports, including many obscure ones that
@ -241,7 +285,7 @@ are used in few games.
- AAC - AAC
- Bink - Bink
- AC3/SPDIF - AC3/SPDIF
- Xiph Opus (Ogg, Switch, EA, UE4) - Xiph Opus (Ogg, Switch, EA, UE4, Exient)
- Xiph CELT (FSB) - Xiph CELT (FSB)
- Musepack - Musepack
- FLAC - FLAC
@ -250,7 +294,7 @@ are used in few games.
Note that vgmstream doesn't (can't) reproduce in-game music 1:1, as internal Note that vgmstream doesn't (can't) reproduce in-game music 1:1, as internal
resampling, filters, volume, etc, are not replicated. Some codecs are not resampling, filters, volume, etc, are not replicated. Some codecs are not
fully accurate compared to the games due to minor bugs, but in most cases fully accurate compared to the games due to minor bugs, but in most cases
it isn't audible. it isn't audible.
## Supported file types ## Supported file types
@ -494,6 +538,6 @@ This list is not complete and many other files are supported.
- .ahxkey (decryption key for .ahx, in start/mult/add format) - .ahxkey (decryption key for .ahx, in start/mult/add format)
- .hcakey (decryption key for .hca, in HCA Decoder format) - .hcakey (decryption key for .hca, in HCA Decoder format)
- .fsbkey (decryption key for .fsb, in hex) - .fsbkey (decryption key for .fsb, in hex)
- .vgmstream + .pos (FFmpeg formats + loop assist) - .vgmstream + .vgmstream.pos (FFmpeg formats + loop assist)
Enjoy! *hcs* Enjoy! *hcs*

View File

@ -1,11 +1,13 @@
#include "vgmstream.h" #include "vgmstream.h"
/* defines the list of accepted extensions. vgmstream doesn't use it internally so it's here /* Defines the list of accepted extensions. vgmstream doesn't use it internally so it's here
* to inform plugins that need it. Common extensions are commented out to avoid stealing them. */ * to inform plugins that need it. Common extensions are commented out to avoid stealing them. */
/* some extensions require external libraries and could be #ifdef, not really needed */ /* Some extensions require external libraries and could be #ifdef, not worth. */
/* some formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension is not parsed */
/* Formats marked as "not parsed" mean they'll go through FFmpeg, the header/extension isn't
* parsed by vgmstream and typically won't not be fully accurate. May have a .ext.pos pair for fun. */
static const char* extension_list[] = { static const char* extension_list[] = {
@ -16,16 +18,16 @@ static const char* extension_list[] = {
"2pfs", "2pfs",
"800", "800",
//"aac", //common, also tri-Ace's //"aac", //common
"aa3", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "aa3", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"aaap", "aaap",
"aax", "aax",
"abk", "abk",
//"ac3", //FFmpeg, not parsed //common? //"ac3", //common, FFmpeg/not parsed (AC3)
"ace", //fake, for tri-Ace's formats (to be removed) "ace", //fake extension for tri-Ace's .aac (renamed, to be removed)
"acm", "acm",
"ad", //txth/reserved [Xenosaga Freaks (PS2)] "ad", //txth/reserved [Xenosaga Freaks (PS2)]
"adc", //txth/reserved [Tomb Raider The Last Revelation(DC), Tomb Raider Chronicles(DC)] "adc", //txth/reserved [Tomb Raider The Last Revelation (DC), Tomb Raider Chronicles (DC)]
"adm", "adm",
"adp", "adp",
"adpcm", "adpcm",
@ -38,13 +40,13 @@ static const char* extension_list[] = {
"ai", "ai",
//"aif", //common //"aif", //common
"aifc", //common? "aifc", //common?
"aifcl", //fake extension, for AIF??? "aifcl", //fake extension for .aif???
//"aiff", //common //"aiff", //common
"aiffl", //fake extension, for AIF??? "aiffl", //fake extension for .aif???
"aix", "aix",
"akb", "akb",
"al2", "al2",
"amts", //fake extension/header id for .stm (to be removed) "amts", //fake extension/header id for .stm (renamed? to be removed?)
"ao", "ao",
"apc", "apc",
"as4", "as4",
@ -73,7 +75,7 @@ static const char* extension_list[] = {
"bdsp", "bdsp",
"bfstm", "bfstm",
"bfwav", "bfwav",
"bfwavnsmbu", "bfwavnsmbu", //fake extension for New Super Smash Bros U (renamed to fix bug)
"bg00", "bg00",
"bgm", "bgm",
"bgw", "bgw",
@ -98,7 +100,7 @@ static const char* extension_list[] = {
"cbd2", "cbd2",
"ccc", "ccc",
"cd", "cd",
"cfn", //fake extension/header id for .caf (to be removed) "cfn", //fake extension for CAF (renamed, to be removed?)
"ckb", "ckb",
"ckd", "ckd",
"cks", "cks",
@ -133,6 +135,7 @@ static const char* extension_list[] = {
"fag", "fag",
"ffw", "ffw",
"filp", "filp",
//"flac", //common
"flx", "flx",
"fsb", "fsb",
"fsv", "fsv",
@ -163,7 +166,7 @@ static const char* extension_list[] = {
"iab", "iab",
"iadp", "iadp",
"idsp", "idsp",
"idvi", //fake extension for .pcm (to be removed) "idvi", //fake extension/header id for .pcm (renamed, to be removed)
"idx", "idx",
"ikm", "ikm",
"ild", "ild",
@ -180,30 +183,34 @@ static const char* extension_list[] = {
"jstm", "jstm",
"kces", "kces",
"kcey", //fake extension/header id (to be removed) "kcey", //fake extension/header id for .pcm (renamed, to be removed)
"khv", "khv",
"km9", "km9",
"kovs", //.kvs header id "kovs", //fake extension/header id for .kvs
"kns", "kns",
"kraw", "kraw",
"ktss", //.kns header id "ktss", //fake extension/header id for .kns
"kvs", "kvs",
"l", "l",
"laac", //fake extension, for AAC (tri-Ace/FFmpeg) "laac", //fake extension for .aac (tri-Ace)
"lac3", //fake extension, for AC3 "lac3", //fake extension for .ac3, FFmpeg/not parsed
"leg", "leg",
"lflac", //fake extension, FFmpeg, not parsed, use with .pos pair for fun "lflac", //fake extension for .flac, FFmpeg/not parsed
"lmp4", //fake extension, for MP4s "lmp2", //fake extension for .mp2, FFmpeg/not parsed
"logg", //fake extension, for OGGs "lmp3", //fake extension for .mp3, FFmpeg/not parsed
"lopus", //fake extension, for OPUS "lmp4", //fake extension for .mp4
"lmpc", //fake extension for .mpc, FFmpeg/not parsed
"logg", //fake extension for .ogg
"lopus", //fake extension for .opus
"lpcm", "lpcm",
"lpk", "lpk",
"lps", "lps",
"lse", "lse",
"lsf", "lsf",
"lstm", //fake extension, for STMs "lstm", //fake extension for .stm
"lwav", //fake extension, for WAVs "lwav", //fake extension for .wav
"lwma", //fake extension for .wma, FFmpeg/not parsed
"mab", "mab",
"matx", "matx",
@ -220,9 +227,10 @@ static const char* extension_list[] = {
"mihb", "mihb",
"mnstr", "mnstr",
"mogg", "mogg",
//"mp2", //common
//"mp3", //common //"mp3", //common
//"mp4", //common //"mp4", //common
//"mpc", //FFmpeg, not parsed (musepack) //common //"mpc", //common
"mpdsp", "mpdsp",
"mpds", "mpds",
"mps", //txth/reserved [Scandal (PS2)] "mps", //txth/reserved [Scandal (PS2)]
@ -239,7 +247,7 @@ static const char* extension_list[] = {
"mus", "mus",
"musc", "musc",
"musx", "musx",
"mvb", //txth/reserved [Porsche Challenge(PS1)] "mvb", //txth/reserved [Porsche Challenge (PS1)]
"mwv", "mwv",
"mxst", "mxst",
"myspd", "myspd",
@ -250,14 +258,14 @@ static const char* extension_list[] = {
"nlsd", "nlsd",
"nop", "nop",
"nps", "nps",
"npsf", //fake extension/header id for .nps (to be removed) "npsf", //fake extension/header id for .nps (in bigfiles)
"nus3bank", "nus3bank",
"nwa", "nwa",
"nxa", "nxa",
//"ogg", //common //"ogg", //common
"ogl", "ogl",
"oma", //FFmpeg, not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA) "oma", //FFmpeg/not parsed (ATRAC3/ATRAC3PLUS/MP3/LPCM/WMA)
"omu", "omu",
//"opus", //common //"opus", //common
"otm", "otm",
@ -274,10 +282,10 @@ static const char* extension_list[] = {
"pnb", "pnb",
"pona", "pona",
"pos", "pos",
"ps2stm", //fake extension for .stm (to be removed) "ps2stm", //fake extension for .stm (renamed? to be removed?)
"psh", // fake extension for VSV(?) Dawn of Mana needs to be checked again "psh", // fake extension for VSV(?) Dawn of Mana needs to be checked again
"psnd", "psnd",
"psw", //fake extension for .wam "psw", //fake extension for .wam (renamed, to be removed)
"r", "r",
"rac", //txth/reserved [Manhunt (Xbox)] "rac", //txth/reserved [Manhunt (Xbox)]
@ -293,7 +301,7 @@ static const char* extension_list[] = {
"rsd", "rsd",
"rsf", "rsf",
"rsm", "rsm",
"rstm", //rsm header id "rstm", //fake extension/header id for .rstm (in bigfiles)
"rvws", "rvws",
"rwar", "rwar",
"rwav", "rwav",
@ -335,7 +343,7 @@ static const char* extension_list[] = {
"sli", "sli",
"smc", "smc",
"smp", "smp",
"smpl", //fake extension (to be removed) "smpl", //fake extension/header id for .v0/v1 (renamed, to be removed)
"smv", "smv",
"snd", "snd",
"snds", "snds",
@ -357,7 +365,7 @@ static const char* extension_list[] = {
"ster", "ster",
"sth", "sth",
//"stm", //common //"stm", //common
"stma", //fake extension (to be removed) "stma", //fake extension/header id for .stm
"str", "str",
"stream", "stream",
"strm", "strm",
@ -393,7 +401,7 @@ static const char* extension_list[] = {
"v0", "v0",
//"v1", //dual channel with v0 //"v1", //dual channel with v0
"va3", //konami atrac3, FFMPEG - DDR Supernova 2 AC "va3",
"vag", "vag",
"vai", "vai",
"vas", "vas",
@ -430,6 +438,7 @@ static const char* extension_list[] = {
"wem", "wem",
"wii", "wii",
"wip", //txth/reserved [Colin McRae DiRT (PC)] "wip", //txth/reserved [Colin McRae DiRT (PC)]
"wma", //common
"wmus", "wmus",
"wp2", "wp2",
"wpd", "wpd",
@ -456,7 +465,7 @@ static const char* extension_list[] = {
"xss", "xss",
"xvag", "xvag",
"xvas", "xvas",
"xwav",//fake, to be removed "xwav",//fake extension for .wav (renamed, to be removed)
"xwb", "xwb",
"xmd", "xmd",
"xopus", "xopus",