mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-18 07:44:43 +01:00
Add MTA2 decoder/meta support [Metal Gear Solid 4 (PS3)]
This commit is contained in:
parent
08a01fec1f
commit
625c18a87e
@ -114,6 +114,9 @@ void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
||||
/* mtaf_decoder */
|
||||
void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels);
|
||||
|
||||
/* mta2_decoder */
|
||||
void decode_mta2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
||||
/* mc3_decoder */
|
||||
void decode_mc3(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
||||
|
186
src/coding/mta2_decoder.c
Normal file
186
src/coding/mta2_decoder.c
Normal file
@ -0,0 +1,186 @@
|
||||
#include "coding.h"
|
||||
#include "../util.h"
|
||||
|
||||
/* MTA2 (EA XAS variant?) decoder based on:
|
||||
* - MGS Developer Wiki: https://www.mgsdevwiki.com/wiki/index.php/MTA2_(Codec) [codec by daemon1]
|
||||
* - Solid4 tools: https://github.com/GHzGangster/Drebin
|
||||
*
|
||||
* MTA2 layout:
|
||||
* - data is divided into N tracks of 0x10 header + 0x90 frame per track channel, forming N streams
|
||||
* ex: 8ch: track0 4ch + track1 4ch + track0 4ch + track1 4ch ...; or 2ch = 1ch track0 + 1ch track1
|
||||
* * up to 16 possible tracks, but max seen is 3 (ex. track0=sneaking, track1=action, track2=ambience)
|
||||
* - each ch frame is divided into 4 headers + 4 vertical groups with nibbles (0x4*4 + 0x20*4)
|
||||
* ex. group1 is 0x04(4) + 0x14(4) + 0x24(4) + 0x34(4) ... (vertically maybe for paralelism?)
|
||||
* - in case of "macroblock" layout, there are also headers before N tracks (like other MGS games)
|
||||
*
|
||||
* Due to this vertical layout and multiple hist/indexes, it decodes everything in a block between calls
|
||||
* but discards unwanted data, instead of trying to skip to the target nibble. Meaning no need to save hist, and
|
||||
* expects samples_to_do to be block_samples at most (could be simplified, I guess).
|
||||
*
|
||||
* Because of how the macroblock/track and stream's offset per channel work, they are supported by
|
||||
* autodetecting and skipping when needed (ideally should keep a special layout/count, but this is simpler).
|
||||
*/
|
||||
|
||||
static const int c1[8] = { /* mod table 1 */
|
||||
0, 240, 460, 392, 488, 460, 460, 240
|
||||
};
|
||||
static const int c2[8] = { /* mod table 2 */
|
||||
0, 0, -208, -220, -240, -240, -220, -104
|
||||
};
|
||||
static const int c3[32] = { /* shift table */
|
||||
256, 335, 438, 573, 749, 979, 1281, 1675,
|
||||
2190, 2864, 3746, 4898, 6406, 8377, 10955, 14327,
|
||||
18736, 24503, 32043, 41905, 54802, 71668, 93724, 122568,
|
||||
160290, 209620, 274133, 358500, 468831, 613119, 801811, 1048576
|
||||
};
|
||||
|
||||
/* expands nibble */
|
||||
static short calculate_output(int nibble, short smp1, short smp2, int mod, int sh) {
|
||||
int output;
|
||||
if (nibble > 7) /* sign extend */
|
||||
nibble = nibble - 16;
|
||||
|
||||
output = (smp1 * c1[mod] + smp2 * c2[mod] + (nibble * c3[sh]) + 128) >> 8;
|
||||
output = clamp16(output);
|
||||
return (short)output;
|
||||
}
|
||||
|
||||
|
||||
/* autodetect and skip "macroblocks" */
|
||||
static void mta2_block_update(VGMSTREAMCHANNEL * stream) {
|
||||
int block_type, block_size, block_tracks, repeat = 1;
|
||||
|
||||
/* may need to skip N empty blocks */
|
||||
do {
|
||||
block_type = read_32bitBE(stream->offset + 0x00, stream->streamfile);
|
||||
block_size = read_32bitBE(stream->offset + 0x04, stream->streamfile); /* including this header */
|
||||
/* 0x08: always null */
|
||||
block_tracks = read_32bitBE(stream->offset + 0x0c, stream->streamfile); /* total tracks of variable size (can be 0) */
|
||||
|
||||
/* 0x10001: music, 0x20001: sfx?, 0xf0: loop control (goes at the end) */
|
||||
if (block_type != 0x00010001 && block_type != 0x00020001 && block_type != 0x000000F0)
|
||||
return; /* not a block */
|
||||
|
||||
/* frame=010001+00/etc can be mistaken as block_type, do extra checks */
|
||||
{
|
||||
int i, track_channels = 0;
|
||||
uint16_t channel_layout = (block_size >> 16);
|
||||
uint16_t track_size = (block_size & 0xFFFF);
|
||||
|
||||
/* has chanel layout == may be a track */
|
||||
if (channel_layout > 0 && channel_layout <= 0xFF) {
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((channel_layout >> i) & 0x01)
|
||||
track_channels++;
|
||||
}
|
||||
if (track_channels*0x90 == track_size)
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (block_size <= 0 || block_tracks < 0) { /* nonsense block (maybe at EOF) */
|
||||
VGM_LOG("MTA2: bad block @ %08lx\n", stream->offset);
|
||||
stream->offset += 0x10;
|
||||
repeat = 0;
|
||||
}
|
||||
else if (block_tracks == 0) { /* empty block (common), keep repeating */
|
||||
stream->offset += block_size;
|
||||
}
|
||||
else { /* normal block, position into next track header */
|
||||
stream->offset += 0x10;
|
||||
repeat = 0;
|
||||
}
|
||||
} while (repeat);
|
||||
}
|
||||
|
||||
/* decodes a block for a channel, skipping macroblocks/tracks if needed */
|
||||
void decode_mta2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
int samples_done = 0, sample_count = 0, channel_block_samples, channel_first_sample, frame_size = 0;
|
||||
int i, group, row, col;
|
||||
int num_track = 0, channel_layout, track_channels = 0, track_channel;
|
||||
|
||||
|
||||
/* block/track skip */
|
||||
do {
|
||||
/* autodetect and skip macroblock header */
|
||||
mta2_block_update(stream);
|
||||
|
||||
/* parse track header (0x10) and skip tracks that our current channel doesn't belong to */
|
||||
num_track = read_8bit(stream->offset+0x00,stream->streamfile); /* 0=first */
|
||||
/* 0x01(3): num_frame (0=first), 0x04(1): 0? */
|
||||
channel_layout = read_8bit(stream->offset+0x05,stream->streamfile); /* bitmask, see mta2.c */
|
||||
frame_size = read_16bitBE(stream->offset+0x06,stream->streamfile); /* not including this header */
|
||||
/* 0x08(8): null */
|
||||
|
||||
if (num_track < 0)
|
||||
break; /* EOF: whatever */
|
||||
|
||||
track_channels = 0;
|
||||
for (i = 0; i < 8; i++) {
|
||||
if ((channel_layout >> i) & 0x01)
|
||||
track_channels++;
|
||||
}
|
||||
|
||||
/* assumes tracks channels are divided evenly in all tracks (ex. not 2ch + 1ch + 1ch) */
|
||||
if (channel / track_channels == num_track)
|
||||
break; /* channel belongs to this track */
|
||||
|
||||
/* keep looping for our track */
|
||||
stream->offset += 0x10 + frame_size;
|
||||
}
|
||||
while (1);
|
||||
|
||||
track_channel = channel % track_channels;
|
||||
channel_block_samples = (0x80*2);
|
||||
channel_first_sample = first_sample % (0x80*2);
|
||||
|
||||
|
||||
/* parse channel frame (header 0x04*4 + data 0x20*4) */
|
||||
for (group = 0; group < 4; group++) {
|
||||
short smp2, smp1, mod, sh, output;
|
||||
int group_header = read_32bitBE(stream->offset + 0x10 + track_channel*0x90 + group*0x4, stream->streamfile);
|
||||
smp2 = (short) ((group_header >> 16) & 0xfff0); /* upper 16b discarding 4b */
|
||||
smp1 = (short) ((group_header >> 4) & 0xfff0); /* lower 16b discarding 4b */
|
||||
mod = (group_header >> 5) & 0x7; /* mid 3b */
|
||||
sh = group_header & 0x1f; /* lower 5b */
|
||||
|
||||
/* write header samples (skips the last 2 group nibbles), like Drebin's decoder
|
||||
* last 2 nibbles and next 2 header hist should match though */
|
||||
if (sample_count >= channel_first_sample && samples_done < samples_to_do) {
|
||||
outbuf[samples_done * channelspacing] = smp2;
|
||||
samples_done++;
|
||||
}
|
||||
sample_count++;
|
||||
if (sample_count >= channel_first_sample && samples_done < samples_to_do) {
|
||||
outbuf[samples_done * channelspacing] = smp1;
|
||||
samples_done++;
|
||||
}
|
||||
sample_count++;
|
||||
|
||||
for (row = 0; row < 8; row++) {
|
||||
for (col = 0; col < 4*2; col++) {
|
||||
uint8_t nibbles = read_8bit(stream->offset + 0x10 + 0x10 + track_channel*0x90 + group*0x4 + row*0x10 + col/2, stream->streamfile);
|
||||
int nibble_shift = (!(col&1) ? 4 : 0); /* upper first */
|
||||
output = calculate_output((nibbles >> nibble_shift) & 0xf, smp1, smp2, mod, sh);
|
||||
|
||||
/* ignore last 2 nibbles (uses first 2 header samples) */
|
||||
if (row < 7 || col < 3*2) {
|
||||
if (sample_count >= channel_first_sample && samples_done < samples_to_do) {
|
||||
outbuf[samples_done * channelspacing] = output;
|
||||
samples_done++;
|
||||
}
|
||||
sample_count++;
|
||||
}
|
||||
|
||||
smp2 = smp1;
|
||||
smp1 = output;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* block fully done */
|
||||
if (channel_first_sample + samples_done == channel_block_samples) {
|
||||
stream->offset += 0x10 + frame_size;
|
||||
}
|
||||
}
|
@ -53,6 +53,7 @@ static const char* extension_list[] = {
|
||||
"bfwav",
|
||||
"bfwavnsmbu",
|
||||
"bg00",
|
||||
"bgm",
|
||||
"bgw",
|
||||
"bh2pcm",
|
||||
"bik",
|
||||
@ -82,6 +83,7 @@ static const char* extension_list[] = {
|
||||
"cps",
|
||||
"cxs",
|
||||
|
||||
"dbm",
|
||||
"dcs",
|
||||
"ddsp",
|
||||
"de2",
|
||||
@ -168,6 +170,7 @@ static const char* extension_list[] = {
|
||||
"msf",
|
||||
"mss",
|
||||
"msvp",
|
||||
"mta2",
|
||||
"mtaf",
|
||||
"mus",
|
||||
"musc",
|
||||
@ -288,11 +291,9 @@ static const char* extension_list[] = {
|
||||
"vgs",
|
||||
"vgv",
|
||||
"vig",
|
||||
|
||||
"vds",
|
||||
"vdm",
|
||||
"vms",
|
||||
"vms",
|
||||
"voi",
|
||||
"vpk",
|
||||
"vs",
|
||||
@ -446,6 +447,7 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_SASSC, "Activision / EXAKT SASSC 8-bit DPCM"},
|
||||
{coding_LSF, "lsf 4-bit ADPCM"},
|
||||
{coding_MTAF, "Konami MTAF 4-bit ADPCM"},
|
||||
{coding_MTA2, "Konami MTA2 4-bit ADPCM"},
|
||||
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
@ -861,6 +863,7 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_GTD, "GTD/GHS header"},
|
||||
{meta_TA_AAC_X360, "tri-Ace AAC (X360) header"},
|
||||
{meta_TA_AAC_PS3, "tri-Ace AAC (PS3) header"},
|
||||
{meta_PS3_MTA2, "Konami MTA2 header"},
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
{meta_OGG_VORBIS, "Ogg Vorbis"},
|
||||
|
@ -966,6 +966,10 @@
|
||||
RelativePath=".\meta\ps3_msf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ps3_mta2.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\ps3_past.c"
|
||||
>
|
||||
@ -1358,6 +1362,10 @@
|
||||
RelativePath=".\coding\mtaf_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\mta2_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\nds_procyon_decoder.c"
|
||||
>
|
||||
|
@ -129,6 +129,7 @@
|
||||
<ClCompile Include="coding\lsf_decoder.c" />
|
||||
<ClCompile Include="coding\mp4_aac_decoder.c" />
|
||||
<ClCompile Include="coding\mtaf_decoder.c" />
|
||||
<ClCompile Include="coding\mta2_decoder.c" />
|
||||
<ClCompile Include="layout\ps2_iab_blocked.c" />
|
||||
<ClCompile Include="layout\ps2_strlr_blocked.c" />
|
||||
<ClCompile Include="layout\scd_int_layout.c" />
|
||||
@ -343,6 +344,7 @@
|
||||
<ClCompile Include="meta\ps2_xau.c" />
|
||||
<ClCompile Include="meta\ps3_cps.c" />
|
||||
<ClCompile Include="meta\ps3_msf.c" />
|
||||
<ClCompile Include="meta\ps3_mta2.c" />
|
||||
<ClCompile Include="meta\ps3_xvag.c" />
|
||||
<ClCompile Include="meta\psx_cdxa.c" />
|
||||
<ClCompile Include="meta\psx_fag.c" />
|
||||
|
@ -580,6 +580,9 @@
|
||||
<ClCompile Include="meta\ps3_msf.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ps3_mta2.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\ps3_xvag.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1009,6 +1012,9 @@
|
||||
<ClCompile Include="coding\mtaf_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\mta2_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\tun.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -677,4 +677,6 @@ VGMSTREAM * init_vgmstream_gtd(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ta_aac_x360(STREAMFILE *streamFile);
|
||||
VGMSTREAM * init_vgmstream_ta_aac_ps3(STREAMFILE *streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_ps3_mta2(STREAMFILE *streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
104
src/meta/ps3_mta2.c
Normal file
104
src/meta/ps3_mta2.c
Normal file
@ -0,0 +1,104 @@
|
||||
#include "meta.h"
|
||||
#include "../util.h"
|
||||
|
||||
|
||||
/* MTA2 - found in Metal Gear Solid 4 */
|
||||
VGMSTREAM * init_vgmstream_ps3_mta2(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t header_offset, start_offset;
|
||||
int loop_flag, channel_count, sample_rate; //block_offset;
|
||||
int32_t loop_start, loop_end;
|
||||
|
||||
|
||||
/* check extension */
|
||||
/* .mta2: normal file, .bgm: mta2 with block layout, .dbm: iPod metadata + block layout mta2 */
|
||||
if ( !check_extensions(streamFile,"mta2,bgm,dbm"))
|
||||
goto fail;
|
||||
|
||||
/* base header (everything is very similar to MGS3's MTAF but BE) */
|
||||
if (read_32bitBE(0x00,streamFile) == 0x4d544132) { /* "MTA2" (.mta) */
|
||||
//block_offset = 0;
|
||||
header_offset = 0x00;
|
||||
} else if (read_32bitBE(0x20,streamFile) == 0x4d544132) { /* "MTA2" @ 0x20 (.bgm) */
|
||||
//block_offset = 0x10;
|
||||
header_offset = 0x20;
|
||||
} else if (read_32bitBE(0x00, streamFile) == 0x444C424D
|
||||
&& read_32bitBE(0x820,streamFile) == 0x4d544132) { /* "DLBM" + "MTA2" @ 0x820 (.dbm) */
|
||||
//block_offset = 0x810;
|
||||
header_offset = 0x820;
|
||||
} else {
|
||||
goto fail;
|
||||
}
|
||||
/* 0x04(4): file size -4-4 (not including block headers in case of block layout) */
|
||||
/* 0x08(4): version? (1), 0x0c(52): null */
|
||||
|
||||
|
||||
/* HEAD chunk */
|
||||
if (read_32bitBE(header_offset+0x40, streamFile) != 0x48454144) /* "HEAD" */
|
||||
goto fail;
|
||||
if (read_32bitBE(header_offset+0x44, streamFile) != 0xB0) /* HEAD size */
|
||||
goto fail;
|
||||
|
||||
|
||||
|
||||
/* 0x48(4): null, 0x4c: ? (0x10), 0x50(4): 0x7F (vol?), 0x54(2): 0x40 (pan?) */
|
||||
channel_count = read_16bitBE(header_offset+0x56, streamFile); /* counting all tracks */
|
||||
/* 0x60(4): full block size (0x110 * channels), indirectly channels_per_track = channels / (block_size / 0x110) */
|
||||
/* 0x80 .. 0xf8: null */
|
||||
|
||||
loop_start = read_32bitBE(header_offset+0x58, streamFile);
|
||||
loop_end = read_32bitBE(header_offset+0x5c, streamFile);
|
||||
loop_flag = (loop_start != loop_end); /* also flag possibly @ 0x73 */
|
||||
#if 0
|
||||
/* those values look like some kind of loop offsets */
|
||||
if (loop_start/0x100 != read_32bitBE(header_offset+0x68, streamFile) ||
|
||||
loop_end /0x100 != read_32bitBE(header_offset+0x6C, streamFile) ) {
|
||||
VGM_LOG("MTA2: wrong loop points\n");
|
||||
goto fail;
|
||||
}
|
||||
#endif
|
||||
|
||||
sample_rate = read_32bitBE(header_offset+0x7c, streamFile);
|
||||
if (sample_rate) { /* sample rate in 32b float (WHY?) typically 48000.0 */
|
||||
float sample_float;
|
||||
memcpy(&sample_float, &sample_rate, 4);
|
||||
sample_rate = (int)sample_float;
|
||||
} else { /* default when not specified (most of the time) */
|
||||
sample_rate = 48000;
|
||||
}
|
||||
|
||||
|
||||
/* TRKP chunks (x16) */
|
||||
/* just seem to contain pan/vol stuff (0x7f/0x40), TRKP per track (sometimes +1 main track?) */
|
||||
/* there is channel layout bitmask @ 0x0f (ex. 1ch = 0x04, 3ch = 0x07, 4ch = 0x33, 6ch = 0x3f), surely:
|
||||
* FRONT_L = 0x01, FRONT_R = 0x02, FRONT_M = 0x04, BACK_L = 0x08, BACK_R = 0x10, BACK_M = 0x20 */
|
||||
|
||||
/* DATA chunk */
|
||||
if (read_32bitBE(header_offset+0x7f8, streamFile) != 0x44415441) // "DATA"
|
||||
goto fail;
|
||||
/* 0x7fc: data size (without blocks in case of blocked layout) */
|
||||
|
||||
start_offset = header_offset + 0x800;
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = loop_end;
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end;
|
||||
|
||||
vgmstream->coding_type = coding_MTA2;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_PS3_MTA2;
|
||||
|
||||
/* open the file for reading */
|
||||
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -360,6 +360,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_rsd6xma,
|
||||
init_vgmstream_ta_aac_x360,
|
||||
init_vgmstream_ta_aac_ps3,
|
||||
init_vgmstream_ps3_mta2,
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
init_vgmstream_mp4_aac_ffmpeg,
|
||||
@ -1065,6 +1066,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
return 54;
|
||||
case coding_MTAF:
|
||||
return 0x80*2;
|
||||
case coding_MTA2:
|
||||
return 0x80*2;
|
||||
case coding_MC3:
|
||||
return 10;
|
||||
case coding_CRI_HCA:
|
||||
@ -1191,6 +1194,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_MSADPCM:
|
||||
case coding_MTAF:
|
||||
return vgmstream->interleave_block_size;
|
||||
case coding_MTA2:
|
||||
return 0x90;
|
||||
case coding_MC3:
|
||||
return 4;
|
||||
default:
|
||||
@ -1735,6 +1740,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
chan, vgmstream->channels);
|
||||
}
|
||||
break;
|
||||
case coding_MTA2:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_mta2(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels, vgmstream->samples_into_block, samples_to_do,
|
||||
chan);
|
||||
}
|
||||
break;
|
||||
case coding_MC3:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_mc3(vgmstream, &vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
|
@ -134,6 +134,7 @@ typedef enum {
|
||||
coding_SASSC, /* Activision EXAKT SASSC DPCM */
|
||||
coding_LSF, /* lsf ADPCM (Fastlane Street Racing iPhone)*/
|
||||
coding_MTAF, /* Konami MTAF ADPCM (IMA-derived) */
|
||||
coding_MTA2, /* Konami MTA2 ADPCM */
|
||||
coding_MC3, /* Paradigm MC3 3-bit ADPCM */
|
||||
|
||||
/* others */
|
||||
@ -615,6 +616,7 @@ typedef enum {
|
||||
meta_GTD, /* Knights Contract (X360/PS3), Valhalla Knights 3 (PSV) */
|
||||
meta_TA_AAC_X360, /* tri-ace AAC (Star Ocean 4, End of Eternity, Infinite Undiscovery) */
|
||||
meta_TA_AAC_PS3, /* tri-ace AAC (Star Ocean International, Resonance of Fate) */
|
||||
meta_PS3_MTA2, /* Metal Gear Solid 4 MTA2 */
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
meta_OGG_VORBIS, /* Ogg Vorbis */
|
||||
|
Loading…
x
Reference in New Issue
Block a user