Merge pull request #353 from bnnm/txth-bnk-gin-ubi-etc

txth bnk gin ubi etc
This commit is contained in:
Christopher Snowhill 2019-01-14 18:03:49 -08:00 committed by GitHub
commit 4568205890
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1830 additions and 1111 deletions

View File

@ -9,6 +9,10 @@ When an unsupported file is loaded (for instance "bgm01.snd"), vgmstream tries t
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.
You can also use ".(sub).(ext).txth" (if the file is "filename.sub.ext"), to allow mixing slightly different files in the same folder. The "sub" part doesn't need to be an extension, for example:
- 001.1ch.str, 001.1ch.str may use .1ch.txth
- 003.2ch.str, 003.2ch.str may use .2ch.txth
- etc
## Example of a TXTH file
For an unsupported bgm01.vag this would be a simple TXTH for it:
@ -82,6 +86,7 @@ A text file with the above commands must be saved as ".vag.txth" or ".txth", not
# - PCFX PC-FX ADPCM
# - PCM4 PCM 4-bit signed
# - PCM4_U PCM 4-bit unsigned
# - OKI16 OKI ADPCM with 16-bit output (not std/VOX/Dialogic 12-bit)
codec = (codec string)
# Codec variations [OPTIONAL, depends on codec]

View File

@ -101,7 +101,8 @@ void decode_ea_xa_v2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac
void decode_maxis_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
/* ea_xas_decoder */
void decode_ea_xas(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xas_v0(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ea_xas_v1(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
/* sdx2_decoder */
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
@ -170,9 +171,10 @@ void decode_derf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
/* circus_decoder */
void decode_circus_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* pcfx_decoder */
/* oki_decoder */
void decode_pcfx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode);
size_t pcfx_bytes_to_samples(size_t bytes, int channels);
void decode_oki16(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
size_t oki_bytes_to_samples(size_t bytes, int channels);
/* ea_mt_decoder*/
ea_mt_codec_data *init_ea_mt(int channels, int type);
@ -341,6 +343,7 @@ void xma2_parse_fmt_chunk_extra(STREAMFILE *streamFile, off_t chunk_offset, int
void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * channels, int * sample_rate, int * loop_flag, int32_t * num_samples, int32_t * loop_start_sample, int32_t * loop_end_sample);
void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples);
void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, int channel_per_stream, int fix_num_samples, int fix_loop_samples);
int riff_get_fact_skip_samples(STREAMFILE * streamFile, off_t start_offset);

View File

@ -799,14 +799,13 @@ void wma_get_samples(ms_sample_data * msd, STREAMFILE *streamFile, int block_ali
/* XMA hell for precise looping and gapless support, fixes raw sample values from headers
* that don't count XMA's final subframe/encoder delay/encoder padding, and FFmpeg stuff.
* Configurable since different headers vary for maximum annoyance. */
void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples) {
void xma_fix_raw_samples_ch(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, int channels_per_stream, int fix_num_samples, int fix_loop_samples) {
const int bytes_per_packet = 2048;
const int samples_per_frame = 512;
const int samples_per_subframe = 128;
const int bits_frame_size = 15;
int xma_version = 2; /* works ok even for XMA1 */
int channels_per_stream = xma_get_channels_per_stream(streamFile, chunk_offset, vgmstream->channels);
off_t first_packet = stream_offset;
off_t last_packet = stream_offset + stream_size - bytes_per_packet;
int32_t start_skip = 0, end_skip = 0;
@ -872,6 +871,12 @@ void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stre
#endif
}
void xma_fix_raw_samples(VGMSTREAM *vgmstream, STREAMFILE*streamFile, off_t stream_offset, size_t stream_size, off_t chunk_offset, int fix_num_samples, int fix_loop_samples) {
int channels_per_stream = xma_get_channels_per_stream(streamFile, chunk_offset, vgmstream->channels);
xma_fix_raw_samples_ch(vgmstream, streamFile, stream_offset, stream_size, channels_per_stream, fix_num_samples, fix_loop_samples);
}
/* ******************************************** */
/* HEADER PARSING */
/* ******************************************** */

View File

@ -9,11 +9,11 @@ static const int EA_XA_TABLE[20] = {
0, -1, -3, -4
};
/* EA-XAS, evolution of EA-XA and cousin of MTA2. From FFmpeg (general info) + MTA2 (layout) + EA-XA (decoding)
/* EA-XAS v1, evolution of EA-XA/XAS and cousin of MTA2. From FFmpeg (general info) + MTA2 (layout) + EA-XA (decoding)
*
* Layout: blocks of 0x4c per channel (128 samples), divided into 4 headers + 4 vertical groups of 15 bytes (for parallelism?).
* To simplify, always decodes the block and discards unneeded samples, so doesn't use external hist. */
void decode_ea_xas(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
void decode_ea_xas_v1(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int group, row, i;
int samples_done = 0, sample_count = 0;
@ -77,3 +77,64 @@ void decode_ea_xas(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacin
stream->offset += 0x4c * channelspacing;
}
}
/* EA-XAS v0, without complex layouts and closer to EA-XA. Somewhat based on daemon1's decoder */
void decode_ea_xas_v0(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
off_t frame_offset;
int i;
int block_samples, frames_in, samples_done = 0, sample_count = 0;
/* external interleave (fixed size), mono */
block_samples = 32;
frames_in = first_sample / block_samples;
first_sample = first_sample % block_samples;
frame_offset = stream->offset + (0x0f+0x02+0x02)*frames_in;
/* process frames */
{
int coef1, coef2;
int16_t hist1, hist2;
uint8_t shift;
uint32_t frame_header = (uint32_t)read_32bitLE(frame_offset, stream->streamfile); /* always LE */
coef1 = EA_XA_TABLE[(uint8_t)(frame_header & 0x0F) + 0];
coef2 = EA_XA_TABLE[(uint8_t)(frame_header & 0x0F) + 4];
hist2 = (int16_t)(frame_header & 0xFFF0);
hist1 = (int16_t)((frame_header >> 16) & 0xFFF0);
shift = 20 - ((frame_header >> 16) & 0x0F);
/* write header samples (needed) */
if (sample_count >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = hist2;
samples_done++;
}
sample_count++;
if (sample_count >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = hist1;
samples_done++;
}
sample_count++;
/* process nibbles */
for (i = 0; i < 0x0f*2; i++) {
uint8_t sample_byte = (uint8_t)read_8bit(frame_offset + 0x02 + 0x02 + i/2, stream->streamfile);
int sample;
sample = get_nibble_signed(sample_byte, !(i&1)); /* upper first */
sample = sample << shift;
sample = (sample + hist1 * coef1 + hist2 * coef2 + 128) >> 8;
sample = clamp16(sample);
if (sample_count >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = sample;
samples_done++;
}
sample_count++;
hist2 = hist1;
hist1 = sample;
}
}
}

View File

@ -1,14 +1,14 @@
#include "coding.h"
static const int step_sizes[49] = { /* OKI table */
static const int step_sizes[49] = { /* OKI table (subsection of IMA's table) */
16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50,
55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157,
173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449,
494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552
};
static const int stex_indexes[16] = { /* IMA table */
static const int stex_indexes[16] = { /* OKI table (also from IMA) */
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
@ -54,6 +54,26 @@ static void pcfx_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int
}
}
static void oki16_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index, int16_t *out_sample) {
int code, step, delta;
code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf;
step = step_sizes[*step_index];
delta = (code & 0x7);
delta = (((delta * 2) + 1) * step) >> 3; /* IMA 'mul' style (standard OKI uses 'shift-add') */
if (code & 0x8)
delta = -delta;
*hist1 += delta;
/* standard OKI clamps hist to 2047,-2048 here */
*step_index += stex_indexes[code];
if (*step_index < 0) *step_index = 0;
if (*step_index > 48) *step_index = 48;
*out_sample = *hist1;
}
/* PC-FX ADPCM decoding, variation of OKI/Dialogic/VOX ADPCM. Based on mednafen/pcfx-music-dump.
* Apparently most ADPCM was made with a buggy encoder, resulting in incorrect sound in real hardware
@ -65,7 +85,7 @@ static void pcfx_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int
*
* PC-FX ISOs don't have a standard filesystem nor file formats (raw data must be custom-ripped),
* so it's needs GENH/TXTH. Sample rate can only be base_value divided by 1/2/3/4, where
* base_value is approximately ~31468.5 (follows hardware clocks), mono or stereo-interleaved.
* base_value is approximately ~31468.5 (follows hardware clocks), mono or interleaved for stereo.
*/
void decode_pcfx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode) {
int i, sample_count = 0;
@ -86,7 +106,40 @@ void decode_pcfx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
stream->adpcm_step_index = step_index;
}
size_t pcfx_bytes_to_samples(size_t bytes, int channels) {
/* OKI variation with 16-bit output (vs standard's 12-bit), found in FrontWing's PS2 games (Sweet Legacy, Hooligan).
* Reverse engineered from the ELF with help from the folks at hcs. */
void decode_oki16(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
int16_t out_sample;
int is_stereo = channelspacing > 1;
/* external interleave */
/* no header (external setup), pre-clamp for wrong values */
if (step_index < 0) step_index=0;
if (step_index > 48) step_index=48;
/* decode nibbles (layout: varies) */
for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) {
off_t byte_offset = is_stereo ?
stream->offset + i : /* stereo: one nibble per channel */
stream->offset + i/2; /* mono: consecutive nibbles (assumed) */
int nibble_shift =
is_stereo ? (!(channel&1) ? 0:4) : (!(i&1) ? 0:4); /* even = low, odd = high */
oki16_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index, &out_sample);
outbuf[sample_count] = (out_sample);
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
size_t oki_bytes_to_samples(size_t bytes, int channels) {
/* 2 samples per byte (2 nibbles) in stereo or mono config */
return bytes * 2 / channels;
}

View File

@ -155,6 +155,7 @@ static const char* extension_list[] = {
"gcub",
"gcw",
"genh",
"gin",
"gms",
"gsb",
//"gsf", //conflicts with GBA gsf plugins?
@ -194,7 +195,7 @@ static const char* extension_list[] = {
"kces",
"kcey", //fake extension/header id for .pcm (renamed, to be removed)
"khv",
"khv", //fake extension/header id for .vas (renamed, to be removed)
"km9",
"kovs", //fake extension/header id for .kvs
"kns",
@ -586,7 +587,8 @@ static const coding_info coding_info_list[] = {
{coding_EA_XA_int, "Electronic Arts EA-XA 4-bit ADPCM v1 (mono/interleave)"},
{coding_EA_XA_V2, "Electronic Arts EA-XA 4-bit ADPCM v2"},
{coding_MAXIS_XA, "Maxis EA-XA 4-bit ADPCM"},
{coding_EA_XAS, "Electronic Arts EA-XAS 4-bit ADPCM"},
{coding_EA_XAS_V0, "Electronic Arts EA-XAS 4-bit ADPCM v0"},
{coding_EA_XAS_V1, "Electronic Arts EA-XAS 4-bit ADPCM v1"},
{coding_IMA, "IMA 4-bit ADPCM"},
{coding_IMA_int, "IMA 4-bit ADPCM (mono/interleave)"},
@ -633,6 +635,7 @@ static const coding_info coding_info_list[] = {
{coding_ASF, "Argonaut ASF 4-bit ADPCM"},
{coding_XMD, "Konami XMD 4-bit ADPCM"},
{coding_PCFX, "PC-FX 4-bit ADPCM"},
{coding_OKI16, "OKI 4-bit ADPCM (16-bit output)"},
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
{coding_SDX2_int, "Squareroot-delta-exact (SDX2) 8-bit DPCM with 1 byte interleave"},
@ -995,7 +998,7 @@ static const meta_info meta_info_list[] = {
{meta_PS3_CPS, "tri-Crescendo CPS Header"},
{meta_SQEX_SCD, "Square-Enix SCD header"},
{meta_NGC_NST_DSP, "Animaniacs NST header"},
{meta_BAF, ".baf WAVE header"},
{meta_BAF, "Bizarre Creations .baf header"},
{meta_PS3_MSF, "Sony MSF header"},
{meta_NUB_VAG, "Namco NUB VAG header"},
{meta_PS3_PAST, "SNDP header"},
@ -1155,6 +1158,7 @@ static const meta_info meta_info_list[] = {
{meta_DSP_ADPCMX, "AQUASTYLE ADPY header"},
{meta_OGG_OPUS, "Ogg Opus header"},
{meta_IMC, "iNiS .IMC header"},
{meta_GIN, "Electronic Arts Gnsu header"},
};

View File

@ -576,10 +576,14 @@
RelativePath=".\meta\gcsw.c"
>
</File>
<File
RelativePath=".\meta\genh.c"
>
</File>
<File
RelativePath=".\meta\genh.c"
>
</File>
<File
RelativePath=".\meta\gin.c"
>
</File>
<File
RelativePath=".\meta\bar.c"
>
@ -1058,10 +1062,6 @@
RelativePath=".\meta\ps2_kces.c"
>
</File>
<File
RelativePath=".\meta\ps2_khv.c"
>
</File>
<File
RelativePath=".\meta\ps2_leg.c"
>
@ -1887,7 +1887,7 @@
>
</File>
<File
RelativePath=".\coding\pcfx_decoder.c"
RelativePath=".\coding\oki_decoder.c"
>
</File>
<File

View File

@ -264,6 +264,7 @@
<ClCompile Include="meta\gca.c" />
<ClCompile Include="meta\gcsw.c" />
<ClCompile Include="meta\genh.c" />
<ClCompile Include="meta\gin.c" />
<ClCompile Include="meta\bar.c" />
<ClCompile Include="meta\gsp_gsb.c" />
<ClCompile Include="meta\gtd.c" />
@ -366,7 +367,6 @@
<ClCompile Include="meta\ps2_joe.c" />
<ClCompile Include="meta\ps2_jstm.c" />
<ClCompile Include="meta\ps2_kces.c" />
<ClCompile Include="meta\ps2_khv.c" />
<ClCompile Include="meta\ps2_leg.c" />
<ClCompile Include="meta\ps2_lpcm.c" />
<ClCompile Include="meta\ps2_mcg.c" />
@ -526,7 +526,7 @@
<ClCompile Include="coding\ngc_dtk_decoder.c" />
<ClCompile Include="coding\nwa_decoder.c" />
<ClCompile Include="coding\ogg_vorbis_decoder.c" />
<ClCompile Include="coding\pcfx_decoder.c" />
<ClCompile Include="coding\oki_decoder.c" />
<ClCompile Include="coding\pcm_decoder.c" />
<ClCompile Include="coding\psv_decoder.c" />
<ClCompile Include="coding\psx_decoder.c" />

View File

@ -364,6 +364,9 @@
<ClCompile Include="meta\genh.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\gin.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\bar.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -655,9 +658,6 @@
<ClCompile Include="meta\ps2_kces.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_khv.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\ps2_leg.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
@ -1117,7 +1117,7 @@
<ClCompile Include="coding\ogg_vorbis_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\pcfx_decoder.c">
<ClCompile Include="coding\oki_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\pcm_decoder.c">

View File

@ -1,9 +1,189 @@
#include "meta.h"
#include "../coding/coding.h"
/* .BAF - Bizarre Creations (Blur, James Bond 007: Blood Stone, etc) */
/* .BAF - Bizarre Creations bank file [Blur (PS3), Project Gotham Racing 4 (X360), Geometry Wars (PC)] */
VGMSTREAM * init_vgmstream_baf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t WAVE_size, DATA_size;
off_t start_offset, header_offset, name_offset;
size_t stream_size;
int loop_flag, channel_count, sample_rate, version, codec;
int total_subsongs, target_subsong = streamFile->stream_index;
int32_t (*read_32bit)(off_t,STREAMFILE*);
/* checks */
if (!check_extensions(streamFile, "baf"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x42414E4B) /* "BANK" */
goto fail;
/* use BANK size to check endianness */
if (guess_endianness32bit(0x04,streamFile)) {
read_32bit = read_32bitBE;
} else {
read_32bit = read_32bitLE;
}
/* 0x04: bank size */
version = read_32bit(0x08,streamFile);
if (version != 0x03 && version != 0x04)
goto fail;
total_subsongs = read_32bit(0x0c,streamFile);
if (target_subsong == 0) target_subsong = 1;
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* - in v3 */
/* 0x10: 0? */
/* 0x11: bank name */
/* - in v4 */
/* 0x10: 1? */
/* 0x11: padding flag? */
/* 0x12: bank name */
/* find target WAVE chunk */
{
int i;
off_t offset = read_32bit(0x04, streamFile);
for (i = 0; i < total_subsongs; i++) {
if (i+1 == target_subsong)
break;
offset += read_32bit(offset+0x04, streamFile); /* WAVE size, variable per codec */
}
header_offset = offset;
}
/* parse header */
if (read_32bitBE(header_offset+0x00, streamFile) != 0x57415645) /* "WAVE" */
goto fail;
codec = read_32bit(header_offset+0x08, streamFile);
name_offset = header_offset + 0x0c;
start_offset = read_32bit(header_offset+0x2c, streamFile);
stream_size = read_32bit(header_offset+0x30, streamFile);
switch(codec) {
case 0x03:
switch(version) {
case 0x03: /* Geometry Wars (PC) */
sample_rate = read_32bit(header_offset + 0x38, streamFile);
channel_count = read_32bit(header_offset + 0x40, streamFile);
/* no actual flag, just loop +15sec songs */
loop_flag = (pcm_bytes_to_samples(stream_size, channel_count, 16) > 15*sample_rate);
break;
case 0x04: /* Project Gotham Racing 4 (X360) */
sample_rate = read_32bit(header_offset + 0x3c, streamFile);
channel_count = read_32bit(header_offset + 0x44, streamFile);
loop_flag = read_8bit(header_offset+0x4b, streamFile);
break;
}
break;
case 0x07: /* Blur (PS3) */
sample_rate = read_32bit(header_offset+0x40, streamFile);
loop_flag = read_8bit(header_offset+0x48, streamFile);
channel_count = read_8bit(header_offset+0x4b, streamFile);
break;
case 0x08: /* Project Gotham Racing (X360) */
sample_rate = read_32bit(header_offset+0x3c, streamFile);
channel_count = read_32bit(header_offset+0x44, streamFile);
loop_flag = read_8bit(header_offset+0x54, streamFile) != 0;
break;
default:
VGM_LOG("BAF: unknown version %x\n", version);
goto fail;
}
/* others: pan/vol? fixed values? (0x19, 0x10) */
/* after WAVEs there may be padding then DATAs chunks, but offsets point after DATA size */
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_BAF;
vgmstream->sample_rate = sample_rate;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size;
switch(codec) {
case 0x03:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
vgmstream->num_samples = pcm_bytes_to_samples(stream_size, channel_count, 16);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
case 0x07:
vgmstream->coding_type = coding_PSX_cfg;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x21;
vgmstream->num_samples = read_32bit(header_offset+0x44, streamFile);
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
case 0x08: {
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xma1(buf,0x100, vgmstream->num_samples, stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, buf,bytes, start_offset,stream_size);
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
/* need to manually find sample offsets, it was a thing with XMA1 */
{
ms_sample_data msd = {0};
msd.xma_version = 1;
msd.channels = channel_count;
msd.data_offset = start_offset;
msd.data_size = stream_size;
msd.loop_flag = loop_flag;
msd.loop_start_b = read_32bit(header_offset+0x4c, streamFile);
msd.loop_end_b = read_32bit(header_offset+0x50, streamFile);
msd.loop_start_subframe = (read_8bit(header_offset+0x55, streamFile) >> 0) & 0x0f;
msd.loop_end_subframe = (read_8bit(header_offset+0x55, streamFile) >> 4) & 0x0f;
xma_get_samples(&msd, streamFile);
vgmstream->num_samples = msd.num_samples; /* also at 0x58, but unreliable? */
vgmstream->loop_start_sample = msd.loop_start_sample;
vgmstream->loop_end_sample = msd.loop_end_sample;
}
xma_fix_raw_samples_ch(vgmstream, streamFile, start_offset, stream_size, channel_count, 1,1);
break;
}
default:
VGM_LOG("BAF: unknown codec %x\n", codec);
goto fail;
}
read_string(vgmstream->stream_name,0x20+1, name_offset,streamFile);
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}
/* awful PS3 splits of the above with bad offsets and all */
VGMSTREAM * init_vgmstream_baf_badrip(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t WAVE_size, stream_size;
off_t start_offset;
long sample_count;
int sample_rate;
@ -13,38 +193,31 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *streamFile) {
int channels;
int loop_flag = 0;
/* check extensions */
/* checks */
if ( !check_extensions(streamFile, "baf") )
goto fail;
/* check WAVE */
if (read_32bitBE(0,streamFile) != 0x57415645) /* "WAVE" */
goto fail;
WAVE_size = read_32bitBE(4,streamFile);
if (WAVE_size != 0x4c) /* && WAVE_size != 0x50*/
goto fail;
/* check for DATA after WAVE */
if (read_32bitBE(WAVE_size,streamFile) != 0x44415441) /* "DATA"*/
goto fail;
/* check that WAVE size is data size */
DATA_size = read_32bitBE(0x30,streamFile);
if (read_32bitBE(WAVE_size+4,streamFile)-8 != DATA_size) goto fail;
stream_size = read_32bitBE(0x30,streamFile);
if (read_32bitBE(WAVE_size+4,streamFile)-8 != stream_size) goto fail;
/*if (WAVE_size == 0x50) sample_count = DATA_size * frame_samples / frame_size / channels;*/
sample_count = read_32bitBE(0x44,streamFile);
/*if (WAVE_size == 0x50) sample_rate = read_32bitBE(0x3c,streamFile);*/
sample_rate = read_32bitBE(0x40,streamFile);
/* unsure how to detect channel count, so use a hack */
channels = (long long)DATA_size / frame_size * frame_samples / sample_count;
channels = (long long)stream_size / frame_size * frame_samples / sample_count;
start_offset = WAVE_size + 8;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = WAVE_size + 8;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = sample_count;
@ -53,14 +226,11 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *streamFile) {
vgmstream->interleave_block_size = frame_size;
vgmstream->meta_type = meta_BAF;
/* open the file for reading */
if ( !vgmstream_open_stream(vgmstream, streamFile, start_offset) )
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -3,16 +3,16 @@
typedef enum { PSX, PCM16, ATRAC9, HEVAG } bnk_codec;
/* BNK - Sony's Scream Tool bank format [Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */
/* .BNK - Sony's Scream Tool bank format [Puyo Puyo Tetris (PS4), NekoBuro: Cats Block (Vita)] */
VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
#if 1
VGMSTREAM * vgmstream = NULL;
off_t start_offset, stream_offset, name_offset = 0;
size_t stream_size, interleave = 0;
off_t sblk_offset, data_offset;
size_t data_size;
int channel_count = 0, loop_flag, sample_rate, parts, version;
int channel_count = 0, loop_flag, sample_rate, parts, version, big_endian;
int loop_start = 0, loop_end = 0;
uint32_t pitch, flags;
uint32_t atrac9_info = 0;
int total_subsongs, target_subsong = streamFile->stream_index;
@ -28,10 +28,12 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
if (read_32bitBE(0x00,streamFile) == 0x00000003) { /* PS3 */
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
big_endian = 1;
}
else if (read_32bitBE(0x00,streamFile) == 0x03000000) { /* Vita/PS4 */
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
big_endian = 0;
}
else {
goto fail;
@ -44,11 +46,13 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
/* 0x0c: sklb size */
data_offset = read_32bit(0x10,streamFile);
data_size = read_32bit(0x14,streamFile);
/* when sblk_offset >= 0x20: */
/* 0x18: ZLSD small footer, rare [Yakuza 6's Puyo Puyo (PS4)] */
/* 0x1c: ZLSD size */
/* SE banks, also used for music. Most table fields seems reserved/defaults and
* don't change much between subsongs or files, so they aren't described in detail */
* don't change much between subsongs or files, so they aren't described in detail.
* Entry sizes are variable (usually flag + extra size xN) so table offsets are needed. */
/* SBlk part: parse header */
@ -63,7 +67,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
off_t table1_offset, table2_offset, table3_offset, table4_offset;
size_t section_entries, material_entries, stream_entries;
size_t table1_entry_size;
off_t table1_suboffset, table2_suboffset, table3_suboffset;
off_t table1_suboffset, table2_suboffset;
off_t table2_entry_offset = 0, table3_entry_offset = 0;
int table4_entry_id = -1;
off_t table4_entries_offset, table4_names_offset;
@ -75,7 +79,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
case 0x09: /* Puyo Puyo Tetris (PS4) */
section_entries = (uint16_t)read_16bit(sblk_offset+0x16,streamFile); /* entry size: ~0x0c */
material_entries = (uint16_t)read_16bit(sblk_offset+0x18,streamFile); /* entry size: ~0x08 */
stream_entries = (uint16_t)read_16bit(sblk_offset+0x1a,streamFile); /* entry size: ~0x60 */
stream_entries = (uint16_t)read_16bit(sblk_offset+0x1a,streamFile); /* entry size: ~0x18 + variable */
table1_offset = sblk_offset + read_32bit(sblk_offset+0x1c,streamFile);
table2_offset = sblk_offset + read_32bit(sblk_offset+0x20,streamFile);
table3_offset = sblk_offset + read_32bit(sblk_offset+0x34,streamFile);
@ -84,7 +88,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
table1_entry_size = 0x0c;
table1_suboffset = 0x08;
table2_suboffset = 0x00;
table3_suboffset = 0x10;
break;
case 0x0d: /* Polara (Vita), Crypt of the Necrodancer (Vita) */
@ -95,12 +98,11 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
table4_offset = sblk_offset + read_32bit(sblk_offset+0x30,streamFile);
section_entries = (uint16_t)read_16bit(sblk_offset+0x38,streamFile); /* entry size: ~0x24 */
material_entries = (uint16_t)read_16bit(sblk_offset+0x3a,streamFile); /* entry size: ~0x08 */
stream_entries = (uint16_t)read_16bit(sblk_offset+0x3c,streamFile); /* entry size: ~0x90 + variable (sometimes) */
stream_entries = (uint16_t)read_16bit(sblk_offset+0x3c,streamFile); /* entry size: ~0x5c + variable */
table1_entry_size = 0x24;
table1_suboffset = 0x0c;
table2_suboffset = 0x00;
table3_suboffset = 0x44;
break;
default:
@ -150,14 +152,64 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
if (target_subsong < 0 || target_subsong > total_subsongs || total_subsongs < 1) goto fail;
/* this means some subsongs repeat streams, that can happen in some sfx banks, whatevs */
if (total_subsongs != stream_entries) {
//;VGM_LOG("BNK: subsongs %i vs table3 %i don't match\n", total_subsongs, stream_entries);
VGM_LOG("BNK: subsongs %i vs table3 %i don't match\n", total_subsongs, stream_entries);
/* find_dupes...? */
}
//;VGM_LOG("BNK: header entry at %lx\n", table3_offset+table3_entry_offset);
/* parse sounds */
stream_offset = read_32bit(table3_offset+table3_entry_offset+table3_suboffset+0x00,streamFile);
stream_size = read_32bit(table3_offset+table3_entry_offset+table3_suboffset+0x04,streamFile);
switch(version) {
case 0x03:
case 0x04:
case 0x09:
pitch = (uint8_t)read_8bit(table3_offset+table3_entry_offset+0x02,streamFile);
flags = (uint8_t)read_8bit(table3_offset+table3_entry_offset+0x0f,streamFile);
stream_offset = read_32bit(table3_offset+table3_entry_offset+0x10,streamFile);
stream_size = read_32bit(table3_offset+table3_entry_offset+0x14,streamFile);
/* must use some log/formula but whatevs */
switch(pitch) {
case 0xC6: sample_rate = 50000; break; //?
case 0xC4: sample_rate = 48000; break;
case 0xC3: sample_rate = 46000; break; //?
case 0xC2: sample_rate = 44100; break;
case 0xBC: sample_rate = 36000; break; //?
case 0xBA: sample_rate = 32000; break; //?
case 0xB6: sample_rate = 22050; break;
case 0xAA: sample_rate = 11025; break;
default:
VGM_LOG("BNK: unknown pitch %x\n", pitch);
goto fail;
}
break;
case 0x0d:
case 0x0e:
flags = (uint8_t)read_8bit(table3_offset+table3_entry_offset+0x12,streamFile);
stream_offset = read_32bit(table3_offset+table3_entry_offset+0x44,streamFile);
stream_size = read_32bit(table3_offset+table3_entry_offset+0x48,streamFile);
pitch = (uint32_t)read_32bit(table3_offset+table3_entry_offset+0x4c,streamFile);
/* this looks like "((pitch >> 9) & 0xC000) | ((pitch >> 8) & 0xFFFF)" but... why??? */
switch(pitch) {
case 0x467A0000: sample_rate = 64000; break; //?
case 0x46BB8000: sample_rate = 48000; break;
case 0x473B8000: sample_rate = 48000; break;
case 0x46AC4400: sample_rate = 44100; break;
case 0x47AC4400: sample_rate = 44100; break;
case 0x472C4400: sample_rate = 44100; break;
default:
VGM_LOG("BNK: unknown pitch %x\n", pitch);
goto fail;
}
break;
default:
goto fail;
}
//;VGM_LOG("BNK: stream at %lx + %x\n", stream_offset, stream_size);
/* parse names */
switch(version) {
@ -215,7 +267,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
switch(version) {
case 0x03:
case 0x04:
sample_rate = 48000; /* seems ok */
channel_count = 1;
/* hack for PS3 files that use dual subsongs as stereo */
@ -224,14 +275,19 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
stream_size = stream_size*channel_count;
total_subsongs = 1;
}
interleave = stream_size / channel_count;
if (flags & 0x80) {
codec = PCM16; /* rare [Wipeout HD (PS3)] */
}
else {
loop_flag = ps_find_loop_offsets(streamFile, start_offset, stream_size, channel_count, interleave, &loop_start, &loop_end);
loop_flag = (flags & 0x40); /* no loops values in sight so may only apply to PS-ADPCM flags */
codec = PSX;
}
//postdata_size = 0x10; /* last frame may be garbage */
loop_flag = ps_find_loop_offsets(streamFile, start_offset, stream_size, channel_count, interleave, &loop_start, &loop_end);
loop_flag = (loop_start > 28); /* ignore full loops since they just fadeout + repeat */
codec = PSX;
break;
case 0x09:
@ -243,7 +299,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
case 0x05: /* ATRAC9 stereo */
if (read_32bit(start_offset+0x08,streamFile) + 0x08 != extradata_size) /* repeat? */
goto fail;
sample_rate = 48000; /* seems ok */
channel_count = (type == 0x02) ? 1 : 2;
atrac9_info = (uint32_t)read_32bitBE(start_offset+0x0c,streamFile);
@ -274,7 +329,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
case 0x05: /* ATRAC9 stereo */
if (read_32bit(start_offset+0x10,streamFile) + 0x10 != extradata_size) /* repeat? */
goto fail;
sample_rate = 48000; /* seems ok */
channel_count = (type == 0x02) ? 1 : 2;
atrac9_info = (uint32_t)read_32bitBE(start_offset+0x14,streamFile);
@ -291,7 +345,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
case 0x01: /* PCM16LE mono? (NekoBuro/Polara sfx) */
case 0x04: /* PCM16LE stereo? (NekoBuro/Polara sfx) */
sample_rate = 48000; /* seems ok */
/* 0x10: null? */
channel_count = read_32bit(start_offset+0x14,streamFile);
interleave = 0x02;
@ -304,7 +357,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
break;
case 0x00: /* PS-ADPCM (test banks) */
sample_rate = 48000; /* seems ok */
/* 0x10: null? */
channel_count = read_32bit(start_offset+0x14,streamFile);
interleave = 0x02;
@ -366,7 +418,7 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
}
#endif
case PCM16:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->coding_type = big_endian ? coding_PCM16BE : coding_PCM16LE;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
@ -376,7 +428,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
break;
case PSX:
vgmstream->sample_rate = 48000;
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
@ -387,7 +438,6 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
break;
case HEVAG:
vgmstream->sample_rate = 48000;
vgmstream->coding_type = coding_HEVAG;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
@ -410,6 +460,22 @@ VGMSTREAM * init_vgmstream_bnk_sony(STREAMFILE *streamFile) {
return vgmstream;
fail:
close_vgmstream(vgmstream);
#endif
return NULL;
}
#if 0
/* .BNK - Sony's bank, earlier version [Jak and Daxter (PS2), NCAA Gamebreaker 2001 (PS2)] */
VGMSTREAM * init_vgmstream_bnk_sony_v2(STREAMFILE *streamFile) {
/* 0x00: 0x00000001
* 0x04: sections (2 or 3)
* 0x08+ similar to v3 but "SBv2"
* table formats is a bit different
* header is like v3 but stream size is in other table?
*/
fail:
close_vgmstream(vgmstream);
return NULL;
}
#endif

View File

@ -121,7 +121,7 @@ VGMSTREAM * init_vgmstream_ea_snu(STREAMFILE *streamFile) {
}
header_offset = 0x10; /* SNR header */
start_offset = read_32bit(0x08,streamFile); /* SPS blocks */
start_offset = read_32bit(0x08,streamFile); /* SNS blocks */
vgmstream = init_vgmstream_eaaudiocore_header(streamFile, streamFile, header_offset, start_offset, meta_EA_SNU);
if (!vgmstream) goto fail;
@ -583,6 +583,15 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
VGM_LOG("EA EAAC: unknown actual looping for codec %x\n", eaac.codec);
goto fail;
}
if (eaac.version == EAAC_VERSION_V0) {
/* SNR+SNS are separate so offsets are relative to the data start
* (first .SNS block, or extra data before the .SNS block in case of .SNU) */
eaac.loop_offset = eaac.stream_offset + eaac.loop_offset;
} else {
/* SPS have headers+data together so offsets are relative to the file start [ex. FIFA 18 (PC)] */
eaac.loop_offset = header_offset - 0x04 + eaac.loop_offset;
}
}
/* accepted channel configs only seem to be mono/stereo/quad/5.1/7.1, from debug strings */
@ -640,7 +649,7 @@ static VGMSTREAM * init_vgmstream_eaaudiocore_header(STREAMFILE * streamHead, ST
#endif
case EAAC_CODEC_XAS: /* "Xas1": EA-XAS [Dead Space (PC/PS3)] */
vgmstream->coding_type = coding_EA_XAS;
vgmstream->coding_type = coding_EA_XAS_V1;
vgmstream->layout_type = layout_blocked_ea_sns;
break;
@ -785,7 +794,7 @@ static size_t get_snr_size(STREAMFILE *streamFile, off_t offset) {
static segmented_layout_data* build_segmented_eaaudiocore_looping(STREAMFILE *streamData, eaac_header *eaac) {
segmented_layout_data *data = NULL;
STREAMFILE* temp_streamFile[2] = {0};
off_t offsets[2] = { eaac->stream_offset, eaac->stream_offset + eaac->loop_offset };
off_t offsets[2] = { eaac->stream_offset, eaac->loop_offset };
int num_samples[2] = { eaac->loop_start, eaac->num_samples - eaac->loop_start};
int segment_count = 2; /* intro/loop */
int i;

View File

@ -115,11 +115,11 @@ VGMSTREAM * init_vgmstream_ea_schl(STREAMFILE *streamFile) {
/* check extension */
/* they don't seem enforced by EA's tools but usually:
* .asf: ~early [ex. Need for Speed (PC)]
* .asf: ~early (audio stream file?) [ex. Need for Speed (PC)]
* .str: ~early [ex. FIFA 2002 (PS1)]
* .eam: ~mid (fake?)
* .exa: ~mid [ex. 007 - From Russia with Love]
* .sng: ~late (fake?)
* .sng: ~late (FIFA games)
* .aud: ~late [ex. FIFA 14 (3DS)]
* .strm: MySims Kingdom (Wii)
* .stm: FIFA 12 (3DS)

View File

@ -32,7 +32,7 @@ VGMSTREAM * init_vgmstream_fag(STREAMFILE *streamFile) {
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_FAG;
vgmstream->sample_rate = 24000;
vgmstream->sample_rate = 22050;
vgmstream->num_streams = total_subsongs;
vgmstream->stream_size = stream_size;

View File

@ -6,33 +6,34 @@
/* known GENH types */
typedef enum {
PSX = 0, /* PSX ADPCM */
XBOX = 1, /* XBOX IMA ADPCM */
NGC_DTK = 2, /* NGC ADP/DTK ADPCM */
PCM16BE = 3, /* 16bit big endian PCM */
PCM16LE = 4, /* 16bit little endian PCM */
PCM8 = 5, /* 8bit PCM */
SDX2 = 6, /* SDX2 (3D0 games) */
DVI_IMA = 7, /* DVI IMA ADPCM */
MPEG = 8, /* MPEG (MP3) */
IMA = 9, /* IMA ADPCM */
AICA = 10, /* AICA ADPCM (dreamcast) */
MSADPCM = 11, /* MS ADPCM (windows) */
NGC_DSP = 12, /* NGC DSP (GC) */
PCM8_U_int = 13, /* 8bit unsigned PCM (interleaved) */
PSX_bf = 14, /* PSX ADPCM bad flagged */
MS_IMA = 15, /* Microsoft IMA ADPCM */
PCM8_U = 16, /* 8bit unsigned PCM */
APPLE_IMA4 = 17, /* Apple Quicktime 4-bit IMA ADPCM */
ATRAC3 = 18, /* raw ATRAC3 */
ATRAC3PLUS = 19, /* raw ATRAC3PLUS */
XMA1 = 20, /* raw XMA1 */
XMA2 = 21, /* raw XMA2 */
FFMPEG = 22, /* any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
PCFX = 24, /* PC-FX ADPCM */
PCM4 = 25, /* 4bit signed PCM */
PCM4_U = 26, /* 4bit unsigned PCM */
PSX = 0, /* PS-ADPCM */
XBOX = 1, /* XBOX IMA ADPCM */
NGC_DTK = 2, /* NGC ADP/DTK ADPCM */
PCM16BE = 3, /* 16-bit big endian PCM */
PCM16LE = 4, /* 16-bit little endian PCM */
PCM8 = 5, /* 8-bit PCM */
SDX2 = 6, /* SDX2 (3D0 games) */
DVI_IMA = 7, /* DVI IMA ADPCM (high nibble first) */
MPEG = 8, /* MPEG (MP3) */
IMA = 9, /* IMA ADPCM (low nibble first) */
AICA = 10, /* AICA ADPCM (Dreamcast games) */
MSADPCM = 11, /* MS ADPCM (Windows games) */
NGC_DSP = 12, /* NGC DSP (Nintendo games) */
PCM8_U_int = 13, /* 8-bit unsigned PCM (interleaved) */
PSX_bf = 14, /* PS-ADPCM with bad flags */
MS_IMA = 15, /* Microsoft IMA ADPCM */
PCM8_U = 16, /* 8-bit unsigned PCM */
APPLE_IMA4 = 17, /* Apple Quicktime 4-bit IMA ADPCM */
ATRAC3 = 18, /* Raw ATRAC3 */
ATRAC3PLUS = 19, /* Raw ATRAC3PLUS */
XMA1 = 20, /* Raw XMA1 */
XMA2 = 21, /* Raw XMA2 */
FFMPEG = 22, /* Any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
PCFX = 24, /* PC-FX ADPCM */
PCM4 = 25, /* 4-bit signed PCM (3rd and 4th gen games) */
PCM4_U = 26, /* 4-bit unsigned PCM (3rd and 4th gen games) */
OKI16 = 27, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */
} genh_type;
typedef struct {
@ -118,6 +119,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
case PCFX: coding = coding_PCFX; break;
case PCM4: coding = coding_PCM4; break;
case PCM4_U: coding = coding_PCM4_U; break;
case OKI16: coding = coding_OKI16; break;
default:
goto fail;
}
@ -204,6 +206,10 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
vgmstream->codec_config = genh.codec_mode;
break;
case coding_OKI16:
vgmstream->layout_type = layout_none;
break;
case coding_MS_IMA:
if (!genh.interleave) goto fail; /* creates garbage */

53
src/meta/gin.c Normal file
View File

@ -0,0 +1,53 @@
#include "meta.h"
#include "../coding/coding.h"
/* .gin - EA engine sounds [Need for Speed: Most Wanted (multi)] */
VGMSTREAM * init_vgmstream_gin(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count, sample_rate, num_samples;
/* checks */
if (!check_extensions(streamFile, "gin"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x476E7375) /* "Gnsu" */
goto fail;
/* contains mapped values for engine RPM sounds but we'll just play the whole thing */
/* 0x04: size? "20\00\00"? */
/* 0x08/0c: min/max float RPM? */
/* 0x10: RPM up? (pitch/frequency) table size */
/* 0x14: RPM ??? table size */
/* always LE even on X360/PS3 */
num_samples = read_32bitLE(0x18, streamFile);
sample_rate = read_32bitLE(0x1c, streamFile);
start_offset = 0x20 +
(read_32bitLE(0x10, streamFile) + 1) * 0x04 +
(read_32bitLE(0x14, streamFile) + 1) * 0x04;
channel_count = 1;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_GIN;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = num_samples;
vgmstream->coding_type = coding_EA_XAS_V0;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x13;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -472,8 +472,6 @@ VGMSTREAM * init_vgmstream_ps2_msa(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_voi(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps2_khv(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_rkv(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_p3d(STREAMFILE* streamFile);
@ -511,6 +509,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ngc_nst_dsp(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_baf(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_baf_badrip(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE* streamFile);
@ -823,4 +822,6 @@ VGMSTREAM * init_vgmstream_imc_container(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_smp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_gin(STREAMFILE * streamFile);
#endif /*_META_H*/

View File

@ -174,7 +174,13 @@ VGMSTREAM * init_vgmstream_ps2_ads(STREAMFILE *streamFile) {
loop_end_offset = loop_end * 0x10;
}
#endif
if (loop_end <= body_size / 0x70 && coding_type == coding_PCM16LE) { /* close to body_size */
if (loop_end <= body_size / 0x200 && coding_type == coding_PCM16LE) { /* close to body_size */
/* Gofun-go no Sekai: loops is address * 0x200 */
loop_flag = 1;
loop_start_offset = loop_start * 0x200;
loop_end_offset = loop_end * 0x200;
}
else if (loop_end <= body_size / 0x70 && coding_type == coding_PCM16LE) { /* close to body_size */
/* Armored Core - Nexus: loops is address * 0x70 */
loop_flag = 1;
loop_start_offset = loop_start * 0x70;

View File

@ -1,65 +0,0 @@
#include "meta.h"
#include "../util.h"
/* KHV (from Kingdom Hearts 2) */
/* VAG files with custom headers */
VGMSTREAM * init_vgmstream_ps2_khv(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag = 0;
int channel_count;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("khv",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x56414770) /* "VAGp" */
goto fail;
loop_flag = (read_32bitBE(0x14,streamFile)!=0);
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x60;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile);
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x10;
vgmstream->meta_type = meta_PS2_KHV;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -6,33 +6,34 @@
/* known TXTH types */
typedef enum {
PSX = 0, /* PSX ADPCM */
XBOX = 1, /* XBOX IMA ADPCM */
NGC_DTK = 2, /* NGC ADP/DTK ADPCM */
PCM16BE = 3, /* 16bit big endian PCM */
PCM16LE = 4, /* 16bit little endian PCM */
PCM8 = 5, /* 8bit PCM */
SDX2 = 6, /* SDX2 (3D0 games) */
DVI_IMA = 7, /* DVI IMA ADPCM */
MPEG = 8, /* MPEG (MP3) */
IMA = 9, /* IMA ADPCM */
AICA = 10, /* AICA ADPCM (dreamcast) */
MSADPCM = 11, /* MS ADPCM (windows) */
NGC_DSP = 12, /* NGC DSP (GC) */
PCM8_U_int = 13, /* 8bit unsigned PCM (interleaved) */
PSX_bf = 14, /* PSX ADPCM bad flagged */
MS_IMA = 15, /* Microsoft IMA ADPCM */
PCM8_U = 16, /* 8bit unsigned PCM */
APPLE_IMA4 = 17, /* Apple Quicktime 4-bit IMA ADPCM */
ATRAC3 = 18, /* raw ATRAC3 */
ATRAC3PLUS = 19, /* raw ATRAC3PLUS */
XMA1 = 20, /* raw XMA1 */
XMA2 = 21, /* raw XMA2 */
FFMPEG = 22, /* any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
PCFX = 24, /* PC-FX ADPCM */
PCM4 = 25, /* 4bit signed PCM */
PCM4_U = 26, /* 4bit unsigned PCM */
PSX = 0, /* PS-ADPCM */
XBOX = 1, /* XBOX IMA ADPCM */
NGC_DTK = 2, /* NGC ADP/DTK ADPCM */
PCM16BE = 3, /* 16-bit big endian PCM */
PCM16LE = 4, /* 16-bit little endian PCM */
PCM8 = 5, /* 8-bit PCM */
SDX2 = 6, /* SDX2 (3D0 games) */
DVI_IMA = 7, /* DVI IMA ADPCM (high nibble first) */
MPEG = 8, /* MPEG (MP3) */
IMA = 9, /* IMA ADPCM (low nibble first) */
AICA = 10, /* AICA ADPCM (Dreamcast games) */
MSADPCM = 11, /* MS ADPCM (Windows games) */
NGC_DSP = 12, /* NGC DSP (Nintendo games) */
PCM8_U_int = 13, /* 8-bit unsigned PCM (interleaved) */
PSX_bf = 14, /* PS-ADPCM with bad flags */
MS_IMA = 15, /* Microsoft IMA ADPCM */
PCM8_U = 16, /* 8-bit unsigned PCM */
APPLE_IMA4 = 17, /* Apple Quicktime 4-bit IMA ADPCM */
ATRAC3 = 18, /* Raw ATRAC3 */
ATRAC3PLUS = 19, /* Raw ATRAC3PLUS */
XMA1 = 20, /* Raw XMA1 */
XMA2 = 21, /* Raw XMA2 */
FFMPEG = 22, /* Any headered FFmpeg format */
AC3 = 23, /* AC3/SPDIF */
PCFX = 24, /* PC-FX ADPCM */
PCM4 = 25, /* 4-bit signed PCM (3rd and 4th gen games) */
PCM4_U = 26, /* 4-bit unsigned PCM (3rd and 4th gen games) */
OKI16 = 27, /* OKI ADPCM with 16-bit output (unlike OKI/VOX/Dialogic ADPCM's 12-bit) */
} txth_type;
typedef struct {
@ -180,6 +181,7 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
case PCFX: coding = coding_PCFX; break;
case PCM4: coding = coding_PCM4; break;
case PCM4_U: coding = coding_PCM4_U; break;
case OKI16: coding = coding_OKI16; break;
default:
goto fail;
}
@ -280,6 +282,10 @@ VGMSTREAM * init_vgmstream_txth(STREAMFILE *streamFile) {
vgmstream->codec_config = txth.codec_mode;
break;
case coding_OKI16:
vgmstream->layout_type = layout_none;
break;
case coding_MS_IMA:
if (!txth.interleave) goto fail; /* creates garbage */
@ -477,8 +483,10 @@ fail:
static STREAMFILE * open_txth(STREAMFILE * streamFile) {
char basename[PATH_LIMIT];
char filename[PATH_LIMIT];
char fileext[PATH_LIMIT];
const char *subext;
STREAMFILE * streamText;
/* try "(path/)(name.ext).txth" */
@ -487,6 +495,22 @@ static STREAMFILE * open_txth(STREAMFILE * streamFile) {
streamText = open_streamfile(streamFile,filename);
if (streamText) return streamText;
/* try "(path/)(.sub.ext).txth" */
get_streamfile_basename(streamFile,basename,PATH_LIMIT);
subext = filename_extension(basename);
if (subext != NULL) {
get_streamfile_path(streamFile,filename,PATH_LIMIT);
get_streamfile_ext(streamFile,fileext,PATH_LIMIT);
strcat(filename,".");
strcat(filename, subext);
strcat(filename,".");
strcat(filename, fileext);
strcat(filename, ".txth");
streamText = open_streamfile(streamFile,filename);
if (streamText) return streamText;
}
/* try "(path/)(.ext).txth" */
get_streamfile_path(streamFile,filename,PATH_LIMIT);
get_streamfile_ext(streamFile,fileext,PATH_LIMIT);
@ -596,6 +620,7 @@ static int parse_keyval(STREAMFILE * streamFile_, txth_header * txth, const char
else if (0==strcmp(val,"PCFX")) txth->codec = PCFX;
else if (0==strcmp(val,"PCM4")) txth->codec = PCM4;
else if (0==strcmp(val,"PCM4_U")) txth->codec = PCM4_U;
else if (0==strcmp(val,"OKI16")) txth->codec = OKI16;
else goto fail;
}
else if (0==strcmp(key,"codec_mode")) {
@ -954,7 +979,8 @@ static int get_bytes_to_samples(txth_header * txth, uint32_t bytes) {
case AICA:
return aica_bytes_to_samples(bytes, txth->channels);
case PCFX:
return pcfx_bytes_to_samples(bytes, txth->channels);
case OKI16:
return oki_bytes_to_samples(bytes, txth->channels);
/* untested */
case SDX2:

View File

@ -32,7 +32,7 @@ typedef struct {
int subtypes_count[9];
} ubi_bao_header;
static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset);
static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset, int target_subsong);
static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile);
static VGMSTREAM * init_vgmstream_ubi_bao_main(ubi_bao_header * bao, STREAMFILE *streamFile);
static STREAMFILE * setup_bao_streamfile(ubi_bao_header *bao, STREAMFILE *streamFile);
@ -265,7 +265,7 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) {
size_t index_size, index_header_size;
off_t bao_offset, resources_offset;
int target_subsong = streamFile->stream_index;
uint8_t *index_buffer = NULL;
STREAMFILE *streamIndex = NULL;
STREAMFILE *streamTest = NULL;
@ -274,6 +274,8 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) {
goto fail;
/* index and resources always LE */
if (target_subsong == 0) target_subsong = 1;
/* 0x01(3): version, major/minor/release (numbering continues from .sb0/sm0) */
index_size = read_32bitLE(0x04, streamFile); /* can be 0, not including */
resources_offset = read_32bitLE(0x08, streamFile); /* always found even if not used */
@ -294,21 +296,22 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) {
VGM_LOG("BAO: index too big\n");
goto fail;
}
index_buffer = malloc(index_size);
read_streamfile(index_buffer, index_header_size, index_size, streamFile);
/* use smaller I/O buffer for performance, as this read lots of small BAO headers all over the place */
/* use smaller I/O buffers for performance, as this read lots of small headers all over the place */
streamIndex = reopen_streamfile(streamFile, index_size);
if (!streamIndex) goto fail;
streamTest = reopen_streamfile(streamFile, 0x100);
if (!streamTest) goto fail;
/* parse index to get target subsong N = Nth audio header BAO */
bao_offset = index_header_size + index_size;
for (i = 0; i < index_entries; i++) {
//uint32_t bao_id = get_32bitLE(index_buffer + 0x08*i+ 0x00);
size_t bao_size = get_32bitLE(index_buffer + 0x08*i + 0x04);
//uint32_t bao_id = read_32bitLE(index_header_size + 0x08*i + 0x00, streamIndex);
size_t bao_size = read_32bitLE(index_header_size + 0x08*i + 0x04, streamIndex);
/* parse and continue to find out total_subsongs */
if (!parse_bao(bao, streamTest, bao_offset))
if (!parse_bao(bao, streamTest, bao_offset, target_subsong))
goto fail;
bao_offset += bao_size; /* files simply concat BAOs */
@ -407,21 +410,20 @@ static int parse_pk_header(ubi_bao_header * bao, STREAMFILE *streamFile) {
;VGM_LOG("BAO stream: id=%x, offset=%x, size=%x, res=%s\n", bao->stream_id, (uint32_t)bao->stream_offset, bao->stream_size, (bao->is_external ? bao->resource_name : "internal"));
free(index_buffer);
close_streamfile(streamIndex);
close_streamfile(streamTest);
return 1;
fail:
free(index_buffer);
close_streamfile(streamIndex);
close_streamfile(streamTest);
return 0;
}
/* parse a single BAO (binary audio object) descriptor */
static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset) {
static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset, int target_subsong) {
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
uint32_t bao_version, descriptor_type, descriptor_subtype;
size_t header_size;
int target_subsong = streamFile->stream_index;
/* 0x00(1): class? usually 0x02 but older BAOs have 0x01 too */
@ -463,11 +465,11 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset)
/* for debugging purposes */
switch(descriptor_subtype) {
case 0x00000001: bao->subtypes_count[1]++; break; /* standard */
case 0x00000002: bao->subtypes_count[2]++; break; /* multilayer??? related to other header BAOs? */
case 0x00000002: bao->subtypes_count[2]++; break; /* related to localized BAOs? (.lpk) */
case 0x00000003: bao->subtypes_count[3]++; break; /* related to other header BAOs? */
case 0x00000004: bao->subtypes_count[4]++; break; /* related to other header BAOs? */
case 0x00000005: bao->subtypes_count[5]++; break; /* related to other header BAOs? */
case 0x00000006: bao->subtypes_count[6]++; break; /* some multilayer/table? may contain sounds??? */
case 0x00000006: bao->subtypes_count[6]++; break; /* multilayer with multiple sounds */
case 0x00000007: bao->subtypes_count[7]++; break; /* related to other header BAOs? */
case 0x00000008: bao->subtypes_count[8]++; break; /* ? (almost empty with some unknown value) */
default:
@ -476,13 +478,26 @@ static int parse_bao(ubi_bao_header * bao, STREAMFILE *streamFile, off_t offset)
}
//;VGM_ASSERT(descriptor_subtype != 0x01, "UBI BAO: subtype %x at %lx (%lx)\n", descriptor_subtype, offset, offset+header_size+0x04);
if (descriptor_subtype == 0x06) {
;VGM_LOG("UBI BAO: layer subtype at %lx (%lx)\n", offset, offset+header_size+0x04);
/* todo fix layers
* for scott pilgrim:
* - 0x50: layer count
* - 0x78: layer headers size?
* - 0x7c: prefetch size
* - 0xb4: layer header xN (size 0x30)
* (this header has sample rate, channels, codec, various sizes/num samples)
* - 0x114: good ol' Ubi SB layer header v0x00100009 with classic v0x03 blocked data
* (standard prefetch style, part of data then cut in the middle and links to stream)
*/
goto fail;
}
/* ignore unknown subtypes */
if (descriptor_subtype != 0x00000001)
return 1;
bao->total_subsongs++;
if (target_subsong == 0) target_subsong = 1;
if (target_subsong != bao->total_subsongs)
return 1;

File diff suppressed because it is too large Load Diff

View File

@ -19,8 +19,10 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
* .swag: Frantix (PSP)
* .str: Ben10 Galactic Racing
* .vig: MX vs. ATV Untamed (PS2)
* .l/r: Crash Nitro Kart (PS2), Gradius V (PS2) */
if ( !check_extensions(streamFile,"vag,swag,str,vig,l,r") )
* .l/r: Crash Nitro Kart (PS2), Gradius V (PS2)
* .vas: Kingdom Hearts II (PS2)
* .khv: fake for .vas */
if ( !check_extensions(streamFile,"vag,swag,str,vig,l,r,vas,khv") )
goto fail;
/* check VAG Header */
@ -112,7 +114,7 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
interleave = 0x10;
loop_flag = 0;
}
else if (check_extensions(streamFile,"swag")) { /* algo "VAGp" at (file_size / channels) */
else if (check_extensions(streamFile,"swag")) { /* also "VAGp" at (file_size / channels) */
/* Frantix (PSP) */
start_offset = 0x40; /* channel_size ignores empty frame */
channel_count = 2;
@ -188,6 +190,19 @@ VGMSTREAM * init_vgmstream_vag(STREAMFILE *streamFile) {
channel_size = channel_size / channel_count;
loop_flag = ps_find_loop_offsets(streamFile, start_offset, channel_size*channel_count, channel_count, interleave, &loop_start_sample, &loop_end_sample);
}
else if (version == 0x00000004 && channel_size == file_size - 0x60 && read_32bitBE(0x1c, streamFile) != 0) { /* also .vas */
/* Kingdom Hearts II (PS2) */
start_offset = 0x60;
interleave = 0x10;
loop_start_sample = read_32bitBE(0x14,streamFile);
loop_end_sample = read_32bitBE(0x18,streamFile);
loop_flag = (loop_end_sample > 0); /* maybe at 0x1d */
channel_count = read_8bit(0x1e,streamFile);
/* 0x1f: possibly volume */
channel_size = channel_size / channel_count;
/* mono files also have channel/volume, but start at 0x30 and are probably named .vag */
}
else {
/* standard PS1/PS2/PS3 .vag [Ecco the Dolphin (PS2), Legasista (PS3)] */
start_offset = 0x30;

View File

@ -253,7 +253,6 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_smpl,
init_vgmstream_ps2_msa,
init_vgmstream_ps2_voi,
init_vgmstream_ps2_khv,
init_vgmstream_ngc_rkv,
init_vgmstream_dsp_ddsp,
init_vgmstream_p3d,
@ -279,6 +278,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_sqex_scd,
init_vgmstream_ngc_nst_dsp,
init_vgmstream_baf,
init_vgmstream_baf_badrip,
init_vgmstream_ps3_msf,
init_vgmstream_nub_vag,
init_vgmstream_ps3_past,
@ -460,6 +460,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_imc,
init_vgmstream_imc_container,
init_vgmstream_smp,
init_vgmstream_gin,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
@ -1142,6 +1143,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_SNDS_IMA:
case coding_OTNS_IMA:
case coding_UBI_IMA:
case coding_OKI16:
return 1;
case coding_IMA_int:
case coding_DVI_IMA_int:
@ -1188,7 +1190,9 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_EA_XA_V2:
case coding_MAXIS_XA:
return 28;
case coding_EA_XAS:
case coding_EA_XAS_V0:
return 32;
case coding_EA_XAS_V1:
return 128;
case coding_MSADPCM:
@ -1323,6 +1327,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_ALP_IMA:
case coding_FFTA2_IMA:
case coding_PCFX:
case coding_OKI16:
return 0x01;
case coding_MS_IMA:
case coding_RAD_IMA:
@ -1370,7 +1375,9 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 0x0F*vgmstream->channels;
case coding_EA_XA_V2:
return 0; /* variable (ADPCM frames of 0x0f or PCM frames of 0x3d) */
case coding_EA_XAS:
case coding_EA_XAS_V0:
return 0xF+0x02+0x02;
case coding_EA_XAS_V1:
return 0x4c*vgmstream->channels;
case coding_MSADPCM:
@ -1706,9 +1713,15 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
}
break;
case coding_EA_XAS:
case coding_EA_XAS_V0:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_ea_xas(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
decode_ea_xas_v0(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
}
break;
case coding_EA_XAS_V1:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_ea_xas_v1(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
}
break;
@ -2040,6 +2053,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, vgmstream->codec_config);
}
break;
case coding_OKI16:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_oki16(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
}
break;
case coding_EA_MT:
for (ch = 0; ch < vgmstream->channels; ch++) {

View File

@ -106,7 +106,8 @@ typedef enum {
coding_EA_XA_int, /* Electronic Arts EA-XA ADPCM v1 (mono/interleave) */
coding_EA_XA_V2, /* Electronic Arts EA-XA ADPCM v2 */
coding_MAXIS_XA, /* Maxis EA-XA ADPCM */
coding_EA_XAS, /* Electronic Arts EA-XAS ADPCM */
coding_EA_XAS_V0, /* Electronic Arts EA-XAS ADPCM v0 */
coding_EA_XAS_V1, /* Electronic Arts EA-XAS ADPCM v1 */
coding_IMA, /* IMA ADPCM (stereo or mono, low nibble first) */
coding_IMA_int, /* IMA ADPCM (mono/interleave, low nibble first) */
@ -152,6 +153,7 @@ typedef enum {
coding_ASF, /* Argonaut ASF 4-bit ADPCM */
coding_XMD, /* Konami XMD 4-bit ADPCM */
coding_PCFX, /* PC-FX 4-bit ADPCM */
coding_OKI16, /* OKI 4-bit ADPCM with 16-bit output */
/* others */
coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression DPCM */
@ -532,7 +534,6 @@ typedef enum {
meta_PS2_SMPL, /* Homura */
meta_PS2_MSA, /* Psyvariar -Complete Edition- */
meta_PS2_VOI, /* RAW Danger (Zettaizetsumei Toshi 2 - Itetsuita Kiokutachi) [PS2] */
meta_PS2_KHV, /* Kingdom Hearts 2 VAG streams */
meta_P3D, /* Prototype P3D */
meta_PS2_TK1, /* Tekken (NamCollection) */
meta_NGC_RKV, /* Legacy of Kain - Blood Omen 2 (GC) */
@ -712,6 +713,7 @@ typedef enum {
meta_DSP_ADPCMX,
meta_OGG_OPUS,
meta_IMC,
meta_GIN,
} meta_t;