mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
Merge pull request #1542 from bnnm/msima-xnb
- Add TXTP frame_size + interleave for MS_IMA [Manhunt (PC)] - Fix some .xnb [Miner: Dig Deep (X360)]
This commit is contained in:
commit
fa68185746
@ -2,13 +2,13 @@
|
||||
This is vgmstream, a library for playing streamed (prerecorded) video game audio.
|
||||
|
||||
Some of vgmstream's features:
|
||||
- [Hundreds of video game music formats and codecs](doc/FORMATS.md), from typical game engine files
|
||||
to obscure single-game codecs, aiming for high accuracy and compatibility.
|
||||
- Decodes [hundreds of video game music formats and codecs](doc/FORMATS.md), from typical
|
||||
game engine files to obscure single-game codecs, aiming for high accuracy and compatibility.
|
||||
- Support for looped BGM, using file's internal metadata for smooth transitions, with accurate
|
||||
sample counts.
|
||||
- [Subsongs](doc/USAGE.md#subsongs), playing a format's multiple internal songs separately.
|
||||
- Many types of companion files (data split into multiple files) and custom containers.
|
||||
- Encryption keys, internal stream names, and many other unusual cases found in game audio.
|
||||
- Encryption keys, internal stream names, and other unusual cases found in game audio.
|
||||
- [TXTH](doc/TXTH.md) function, to add external support for extra formats, including raw audio in
|
||||
many forms.
|
||||
- [TXTP](doc/TXTP.md) function, for real-time and per-file config, like forced looping, removing
|
||||
|
@ -125,6 +125,7 @@ as explained below, but often will use default values. Accepted codec strings:
|
||||
# - MS_IMA Microsoft IMA ADPCM
|
||||
# * For some PC games
|
||||
# * frame_size (or interleave) varies, often multiple of 0x100 [required]
|
||||
# * frame_size + interleave forces mono mode
|
||||
# - APPLE_IMA4 Apple Quicktime IMA ADPCM
|
||||
# * For some Mac/iOS games
|
||||
# - IMA_HV High Voltage's IMA ADPCM
|
||||
|
22
doc/USAGE.md
22
doc/USAGE.md
@ -929,3 +929,25 @@ vgmstream's internals are tailored to play streams so, in other words, it's not
|
||||
possible to add support for sequenced audio unless massive changes were done,
|
||||
basically becoming another program entirely. There are other projects better
|
||||
suited for playing sequences.
|
||||
|
||||
|
||||
## External loop points
|
||||
Most games use audio formats that define loop points inside its files. That is,
|
||||
you get looped/repeated audio in vgmstream simply by opening the files.
|
||||
|
||||
However some games use formats that don't define loops points, and instead store
|
||||
loops in the executable or some external file. For example they could have a bunch
|
||||
of `.ogg` and some text with start/end loop time info for all `.ogg`, or `.opus`
|
||||
files with loop samples defined in a `.bfsar`.
|
||||
|
||||
Since those cases are typically custom/per game, vgmstream can't really read those
|
||||
loop points automatically. Instead, one should make (manually or with some script)
|
||||
one TXTP per file that tells vgmstream about its external loop points, and play
|
||||
the `.txtp`:
|
||||
**BGM_BTL_ACMaster_opus.txtp**: `BGM_BTL_ACMaster_opus.lopus #I 258724 2929972`
|
||||
|
||||
Some games also use intro + loop "segments" in separate files that can be combined
|
||||
with `.txtp` as well.
|
||||
|
||||
This may even happen with formats that do have loops in other games (for example
|
||||
relatively common with `.fsb` and mobile games, that may define loops in a .json file).
|
||||
|
@ -461,14 +461,24 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
|
||||
break;
|
||||
|
||||
case coding_MS_IMA:
|
||||
vgmstream->interleave_block_size = txth.frame_size ? txth.frame_size : txth.interleave;
|
||||
vgmstream->layout_type = layout_none;
|
||||
if (txth.interleave && txth.frame_size) {
|
||||
coding = coding_MS_IMA_mono;
|
||||
vgmstream->frame_size = txth.frame_size;
|
||||
vgmstream->interleave_block_size = txth.interleave;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
}
|
||||
else {
|
||||
vgmstream->frame_size = txth.frame_size ? txth.frame_size : txth.interleave;
|
||||
vgmstream->layout_type = layout_none;
|
||||
}
|
||||
|
||||
vgmstream->allow_dual_stereo = 1; //???
|
||||
//TO-DO: needs to force MS_IMA_mono first if ch = 1, since dual_stereo + MS_IMA = assumes MS_IMA_stereo
|
||||
// (or better do it after init / during setup stream)
|
||||
//vgmstream->allow_dual_stereo = 1;
|
||||
break;
|
||||
|
||||
case coding_MSADPCM:
|
||||
if (vgmstream->channels > 2) goto fail; //can't handle
|
||||
if (vgmstream->channels > 2) goto fail; //can't handle (to-do: only non-mono?)
|
||||
if (txth.interleave && txth.frame_size) {
|
||||
coding = coding_MSADPCM_int;
|
||||
vgmstream->frame_size = txth.frame_size;
|
||||
|
@ -9,27 +9,28 @@ VGMSTREAM* init_vgmstream_xnb(STREAMFILE* sf) {
|
||||
STREAMFILE* sf_h = NULL;
|
||||
off_t start_offset, offset, xma_chunk_offset = 0;
|
||||
int loop_flag = 0, channel_count, num_samples = 0, loop_start = 0, loop_end = 0;
|
||||
int big_endian, flags, codec, sample_rate, block_align, bps;
|
||||
int flags, codec, sample_rate, block_align, bps;
|
||||
size_t data_size;
|
||||
char platform;
|
||||
int is_sound = 0, is_ogg = 0, is_at9 = 0, is_song = 0;
|
||||
char song_name[255+1];
|
||||
|
||||
|
||||
/* checks */
|
||||
if ((read_u32be(0x00, sf) & 0xFFFFFF00) != get_id32be("XNB\0"))
|
||||
goto fail;
|
||||
return NULL;
|
||||
if (!check_extensions(sf,"xnb"))
|
||||
goto fail;
|
||||
return NULL;
|
||||
|
||||
/* XNA Studio platforms: 'w' = Windows, 'm' = Windows Phone 7, 'x' = X360
|
||||
* MonoGame extensions: 'i' = iOS, 'a' = Android, 'X' = MacOSX, 'P' = PS4, 'S' = Switch, etc */
|
||||
platform = read_u8(0x03, sf);
|
||||
big_endian = (platform == 'x');
|
||||
char platform = read_u8(0x03, sf);
|
||||
int big_endian = (platform == 'x');
|
||||
int version = read_u8(0x04,sf);
|
||||
|
||||
if (read_u8(0x04,sf) != 0x04 && /* XNA 3.0? found on Scare Me (XBLIG), no notable diffs */
|
||||
read_u8(0x04,sf) != 0x05) /* XNA 4.0 version */
|
||||
goto fail;
|
||||
if (version != 0x03 && /* XNA 2.0? found on Miner: Dig Deep (XBLIG), no notable diffs */
|
||||
version != 0x04 && /* XNA 3.0? found on Scare Me (XBLIG), no notable diffs */
|
||||
version != 0x05) /* XNA 4.0 version */
|
||||
return NULL;
|
||||
|
||||
flags = read_u8(0x05, sf);
|
||||
//if (flags & 0x01) goto fail; /* "HiDef profile" content (no actual difference) */
|
||||
|
Loading…
Reference in New Issue
Block a user