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
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.
### Renamed files
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
vgmstream (mainly to get looping in some cases).
- .aac to .laac
- .ac3 to .lac3
- .aif to .aiffl or .aifcl
- .asf to .sng (EA formats)
- .flac to .lflac
- .mp4 to .lmp4
- .ogg to .logg
- .opus to .lopus
- .stm to .lstm
- .wav to .lwav
like foobar or Winamp don't react well to that, they may be renamed to make
them playable through vgmstream.
- .aac to .laac (tri-Ace games)
- .ac3 to .lac3 (standard AC3)
- .aif to .aiffl or .aifcl (standard Mac AIF)
- .asf to .sng (EA games)
- .flac to .lflac (standard FLAC)
- .mp2 to .lmp2 (standard MP2)
- .mp3 to .lmp3 (standard MP3)
- .mp4 to .lmp4 (standard M4A)
- .mpc to .lmpc (standard MPC)
- .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
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
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
left together.
- .mus (playlist for .acm)
- .pos (loop info for .wav: 32 bit LE loop start sample + loop end sample)
- .sli (loop info for .ogg)
- .sfl (loop info for .ogg)
- .vgmstream + .pos (FFmpeg formats + loop assist)
- .pos (loop info for .wav, and sometimes .ogg)
- .ogg.sli or .sli (loop info for .ogg)
- .ogg.sfl (loop info for .ogg)
- .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
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)
- .ahx: .ahxkey (derived 6 byte key, in start/mult/add format)
- .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)
The key file can be ".(ext)key" (for the whole folder), or "(name).(ext)key"
@ -187,6 +228,9 @@ file, or static values.
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").
Creation of those files is meant for advanced users, docs can be found in
vgmstream source.
## Supported codec types
Quick list of codecs vgmstream supports, including many obscure ones that
@ -241,7 +285,7 @@ are used in few games.
- AAC
- Bink
- AC3/SPDIF
- Xiph Opus (Ogg, Switch, EA, UE4)
- Xiph Opus (Ogg, Switch, EA, UE4, Exient)
- Xiph CELT (FSB)
- Musepack
- FLAC
@ -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)
- .hcakey (decryption key for .hca, in HCA Decoder format)
- .fsbkey (decryption key for .fsb, in hex)
- .vgmstream + .pos (FFmpeg formats + loop assist)
- .vgmstream + .vgmstream.pos (FFmpeg formats + loop assist)
Enjoy! *hcs*

View File

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