Merge pull request #567 from bnnm/psx-nub-awc

psx nub awc
This commit is contained in:
bnnm 2020-03-02 01:08:23 +01:00 committed by GitHub
commit c40d364e87
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 2429 additions and 2280 deletions

View File

@ -360,7 +360,17 @@ If your player isn't picking tags make sure vgmstream is detecting the song
(as other plugins can steal its extensions, see above), .m3u is properly (as other plugins can steal its extensions, see above), .m3u is properly
named and that filenames inside match the song filename. For Winamp you need named and that filenames inside match the song filename. For Winamp you need
to make sure *options > titles > advanced title formatting* checkbox is set and to make sure *options > titles > advanced title formatting* checkbox is set and
the format defined. the format defined. For foobar2000 don't forget you need to force refresh when
tags change (for reasons outside vgmstream's control):
**select songs > shift + right click > Tagging > Reload info from file(s)**.
Currently there is no tool to aid in the creation of there m3u, but you can create
a base m3u and edit as a text file.
If you are not satisfied with vgmstream's tagging format, foobar2000 has other
plugins (with write support) that may be of use:
- m-TAGS: http://www.m-tags.org/
- foo_external_tags: https://foobar.hyv.fi/?view=foo_external_tags
## Virtual TXTP files ## Virtual TXTP files
Some of vgmstream's plugins allow you to use virtual .txtp files, that combined Some of vgmstream's plugins allow you to use virtual .txtp files, that combined

View File

@ -79,8 +79,8 @@ void decode_pcmfloat(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelsp
size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample); size_t pcm_bytes_to_samples(size_t bytes, int channels, int bits_per_sample);
/* psx_decoder */ /* psx_decoder */
void decode_psx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int is_badflags); void decode_psx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int is_badflags, int config);
void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size); void decode_psx_configurable(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size, int config);
void decode_psx_pivotal(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size); void decode_psx_pivotal(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size);
int ps_find_loop_offsets(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end); int ps_find_loop_offsets(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end);
int ps_find_loop_offsets_full(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end); int ps_find_loop_offsets_full(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, size_t interleave, int32_t * out_loop_start, int32_t * out_loop_end);

View File

@ -2,12 +2,24 @@
/* PS-ADPCM table, defined as rational numbers (as in the spec) */ /* PS-ADPCM table, defined as rational numbers (as in the spec) */
static const float ps_adpcm_coefs_f[5][2] = { static const float ps_adpcm_coefs_f[16][2] = {
{ 0.0 , 0.0 }, //{ 0.0 , 0.0 }, { 0.0 , 0.0 }, //{ 0.0 , 0.0 },
{ 0.9375 , 0.0 }, //{ 60.0 / 64.0 , 0.0 }, { 0.9375 , 0.0 }, //{ 60.0 / 64.0 , 0.0 },
{ 1.796875 , -0.8125 }, //{ 115.0 / 64.0 , -52.0 / 64.0 }, { 1.796875 , -0.8125 }, //{ 115.0 / 64.0 , -52.0 / 64.0 },
{ 1.53125 , -0.859375 }, //{ 98.0 / 64.0 , -55.0 / 64.0 }, { 1.53125 , -0.859375 }, //{ 98.0 / 64.0 , -55.0 / 64.0 },
{ 1.90625 , -0.9375 }, //{ 122.0 / 64.0 , -60.0 / 64.0 }, { 1.90625 , -0.9375 }, //{ 122.0 / 64.0 , -60.0 / 64.0 },
/* extended table used in few PS3 games, found in ELFs */
{ 0.46875 , -0.0 }, //{ 30.0 / 64.0 , -0.0 / 64.0 },
{ 0.8984375 , -0.40625 }, //{ 57.5 / 64.0 , -26.0 / 64.0 },
{ 0.765625 , -0.4296875 }, //{ 49.0 / 64.0 , -27.5 / 64.0 },
{ 0.953125 , -0.46875 }, //{ 61.0 / 64.0 , -30.0 / 64.0 },
{ 0.234375 , -0.0 }, //{ 15.0 / 64.0 , -0.0 / 64.0 },
{ 0.44921875, -0.203125 }, //{ 28.75/ 64.0 , -13.0 / 64.0 },
{ 0.3828125 , -0.21484375}, //{ 24.5 / 64.0 , -13.75/ 64.0 },
{ 0.4765625 , -0.234375 }, //{ 30.5 / 64.0 , -15.0 / 64.0 },
{ 0.5 , -0.9375 }, //{ 32.0 / 64.0 , -60.0 / 64.0 },
{ 0.234375 , -0.9375 }, //{ 15.0 / 64.0 , -60.0 / 64.0 },
{ 0.109375 , -0.9375 }, //{ 7.0 / 64.0 , -60.0 / 64.0 },
}; };
/* PS-ADPCM table, defined as spec_coef*64 (for int implementations) */ /* PS-ADPCM table, defined as spec_coef*64 (for int implementations) */
@ -38,12 +50,12 @@ static const int ps_adpcm_coefs_i[5][2] = {
* Very similar to XA ADPCM (see xa_decoder for extended info). * Very similar to XA ADPCM (see xa_decoder for extended info).
* *
* Some official PC tools decode using float coefs (from the spec), as does this code, but * Some official PC tools decode using float coefs (from the spec), as does this code, but
* consoles/games/libs would vary (PS1 could do it in hardware using BRR/XA's logic, FMOD/PS3 * consoles/games/libs would vary (PS1 could do it in hardware using BRR/XA's logic, FMOD may
* may use int math in software, etc). There are inaudible rounding diffs between implementations. * depend on platform, PS3 games use floats, etc). There are rounding diffs between implementations.
*/ */
/* standard PS-ADPCM (float math version) */ /* standard PS-ADPCM (float math version) */
void decode_psx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int is_badflags) { void decode_psx(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int is_badflags, int config) {
uint8_t frame[0x10] = {0}; uint8_t frame[0x10] = {0};
off_t frame_offset; off_t frame_offset;
int i, frames_in, sample_count = 0; int i, frames_in, sample_count = 0;
@ -51,6 +63,7 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing
uint8_t coef_index, shift_factor, flag; uint8_t coef_index, shift_factor, flag;
int32_t hist1 = stream->adpcm_history1_32; int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32; int32_t hist2 = stream->adpcm_history2_32;
int extended_mode = (config == 1);
/* external interleave (fixed size), mono */ /* external interleave (fixed size), mono */
@ -66,11 +79,14 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing
shift_factor = (frame[0] >> 0) & 0xf; shift_factor = (frame[0] >> 0) & 0xf;
flag = frame[1]; /* only lower nibble needed */ flag = frame[1]; /* only lower nibble needed */
/* upper filters only used in few PS3 games, normally 0 */
if (!extended_mode) {
VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset); VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset);
if (coef_index > 5) /* needed by inFamous (PS3) (maybe it's supposed to use more filters?) */ if (coef_index > 5)
coef_index = 0; /* upper filters aren't used in PS1/PS2, maybe in PSP/PS3? */ coef_index = 0;
if (shift_factor > 12) if (shift_factor > 12)
shift_factor = 9; /* supposedly, from Nocash PSX docs */ shift_factor = 9; /* supposedly, from Nocash PSX docs */
}
if (is_badflags) /* some games store garbage or extra internal logic in the flags, must be ignored */ if (is_badflags) /* some games store garbage or extra internal logic in the flags, must be ignored */
flag = 0; flag = 0;
@ -107,8 +123,8 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing
/* PS-ADPCM with configurable frame size and no flag (int math version). /* PS-ADPCM with configurable frame size and no flag (int math version).
* Found in some PC/PS3 games (FF XI in sizes 0x3/0x5/0x9/0x41, Afrika in size 0x4, Blur/James Bond in size 0x33, etc). * Found in some PC/PS3 games (FF XI in sizes 0x3/0x5/0x9/0x41, Afrika in size 0x4, Blur/James Bond in size 0x33, etc).
* *
* Uses int math to decode, which seems more likely (based on FF XI PC's code in Moogle Toolbox). */ * Uses int/float math depending on config (PC/other code may be int, PS3 float). */
void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size) { void decode_psx_configurable(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int frame_size, int config) {
uint8_t frame[0x50] = {0}; uint8_t frame[0x50] = {0};
off_t frame_offset; off_t frame_offset;
int i, frames_in, sample_count = 0; int i, frames_in, sample_count = 0;
@ -116,6 +132,8 @@ void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int c
uint8_t coef_index, shift_factor; uint8_t coef_index, shift_factor;
int32_t hist1 = stream->adpcm_history1_32; int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32; int32_t hist2 = stream->adpcm_history2_32;
int extended_mode = (config == 1);
int float_mode = (config == 1);
/* external interleave (variable size), mono */ /* external interleave (variable size), mono */
@ -130,11 +148,14 @@ void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int c
coef_index = (frame[0] >> 4) & 0xf; coef_index = (frame[0] >> 4) & 0xf;
shift_factor = (frame[0] >> 0) & 0xf; shift_factor = (frame[0] >> 0) & 0xf;
/* upper filters only used in few PS3 games, normally 0 */
if (!extended_mode) {
VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset); VGM_ASSERT_ONCE(coef_index > 5 || shift_factor > 12, "PS-ADPCM: incorrect coefs/shift at %x\n", (uint32_t)frame_offset);
if (coef_index > 5) /* needed by Afrika (PS3) (maybe it's supposed to use more filters?) */ if (coef_index > 5)
coef_index = 0; /* upper filters aren't used in PS1/PS2, maybe in PSP/PS3? */ coef_index = 0;
if (shift_factor > 12) if (shift_factor > 12)
shift_factor = 9; /* supposedly, from Nocash PSX docs */ shift_factor = 9; /* supposedly, from Nocash PSX docs */
}
/* decode nibbles */ /* decode nibbles */
@ -146,7 +167,9 @@ void decode_psx_configurable(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int c
(nibbles >> 4) & 0x0f : (nibbles >> 4) & 0x0f :
(nibbles >> 0) & 0x0f; (nibbles >> 0) & 0x0f;
sample = (int16_t)((sample << 12) & 0xf000) >> shift_factor; /* 16b sign extend + scale */ sample = (int16_t)((sample << 12) & 0xf000) >> shift_factor; /* 16b sign extend + scale */
sample = sample + ((ps_adpcm_coefs_i[coef_index][0]*hist1 + ps_adpcm_coefs_i[coef_index][1]*hist2) >> 6); sample = float_mode ?
(int32_t)(sample + ps_adpcm_coefs_f[coef_index][0]*hist1 + ps_adpcm_coefs_f[coef_index][1]*hist2) :
sample + ((ps_adpcm_coefs_i[coef_index][0]*hist1 + ps_adpcm_coefs_i[coef_index][1]*hist2) >> 6);
sample = clamp16(sample); sample = clamp16(sample);
outbuf[sample_count] = sample; outbuf[sample_count] = sample;

View File

@ -4,19 +4,21 @@
#include "../vgmstream.h" #include "../vgmstream.h"
static size_t get_block_header_size(STREAMFILE *streamFile, off_t offset, int channels, int big_endian); static size_t get_channel_header_size(STREAMFILE* sf, off_t offset, int channels, int big_endian);
static size_t get_block_header_size(STREAMFILE* sf, off_t offset, size_t channel_header_size, int channels, int big_endian);
/* AWC music chunks */ /* AWC music chunks */
void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream) { void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* streamFile = vgmstream->ch[0].streamfile; STREAMFILE* sf = vgmstream->ch[0].streamfile;
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE; int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
size_t header_size, entries, block_size, block_samples; size_t header_size, entries, block_size, block_samples;
size_t channel_header_size;
int i; int i;
/* assumed only AWC_IMA enters here, MPEG/XMA2 need special parsing as blocked layout is too limited */ /* assumed only AWC_IMA enters here, MPEG/XMA2 need special parsing as blocked layout is too limited */
entries = read_32bit(block_offset + 0x04, sf); /* se first channel, assume all are the same */
entries = read_32bit(block_offset + 0x18*0 + 0x04, streamFile); /* assumed same for all channels */ //block_samples = entries * (0x800-4)*2; //todo use
block_samples = entries * (0x800-4)*2; block_samples = read_32bit(block_offset + 0x0c, sf);
block_size = vgmstream->full_block_size; block_size = vgmstream->full_block_size;
vgmstream->current_block_offset = block_offset; vgmstream->current_block_offset = block_offset;
@ -25,32 +27,45 @@ void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream) {
/* starts with a header block */ /* starts with a header block */
/* for each channel /* for each channel
* 0x00: start entry within channel (ie. entries * ch) * 0x00: start entry within channel (ie. entries * ch) but may be off by +1/+2
* 0x04: entries * 0x04: entries
* 0x08: samples to discard in the beginning of this block (MPEG only?) * 0x08: samples to discard in the beginning of this block (MPEG only?)
* 0x0c: samples in channel (for MPEG/XMA2 can vary between channels) * 0x0c: samples in channel (for MPEG/XMA2 can vary between channels)
* 0x10: MPEG only: close to number of frames but varies a bit? * (next fields don't exist in later versions for IMA)
* 0x14: MPEG only: channel usable data size (not counting padding) * 0x10: (MPEG only, empty otherwise) close to number of frames but varies a bit?
* 0x14: (MPEG only, empty otherwise) channel usable data size (not counting padding)
* for each channel * for each channel
* 32b * entries = global samples per frame in each block (for MPEG probably per full frame) * 32b * entries = global samples per frame in each block (for MPEG probably per full frame)
*/ */
header_size = get_block_header_size(streamFile, block_offset, vgmstream->channels, vgmstream->codec_endian); channel_header_size = get_channel_header_size(sf, block_offset, vgmstream->channels, vgmstream->codec_endian);
header_size = get_block_header_size(sf, block_offset, channel_header_size, vgmstream->channels, vgmstream->codec_endian);
for (i = 0; i < vgmstream->channels; i++) { for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = block_offset + header_size + 0x800*entries*i; vgmstream->ch[i].offset = block_offset + header_size + 0x800*entries*i;
VGM_ASSERT(entries != read_32bit(block_offset + channel_header_size*i + 0x04, sf), "AWC: variable number of entries found at %lx\n", block_offset);
} }
} }
static size_t get_block_header_size(STREAMFILE *streamFile, off_t offset, int channels, int big_endian) { static size_t get_channel_header_size(STREAMFILE* sf, off_t offset, int channels, int big_endian) {
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
/* later games have an smaller channel header, try to detect using
* an empty field not in IMA */
if (read_32bit(offset + 0x14, sf) == 0x00)
return 0x18;
return 0x10;
}
static size_t get_block_header_size(STREAMFILE* sf, off_t offset, size_t channel_header_size, int channels, int big_endian) {
size_t header_size = 0; size_t header_size = 0;
int i; int i;
int entries = channels; int entries = channels;
int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE; int32_t (*read_32bit)(off_t,STREAMFILE*) = big_endian ? read_32bitBE : read_32bitLE;
for (i = 0; i < entries; i++) { for (i = 0; i < entries; i++) {
header_size += 0x18; header_size += channel_header_size;
header_size += read_32bit(offset + 0x18*i + 0x04, streamFile) * 0x04; /* entries in the table */ header_size += read_32bit(offset + channel_header_size*i + 0x04, sf) * 0x04; /* entries in the table */
} }
if (header_size % 0x800) /* padded */ if (header_size % 0x800) /* padded */

View File

@ -209,6 +209,21 @@ static void load_awb_name(STREAMFILE *streamFile, STREAMFILE *acbFile, VGMSTREAM
} }
} }
/* try (name)_(name)_R001.awb + (name).acb [Sengoku Basara Battle Party (Mobile)] */
if (!acbFile) {
char *cmp = "_R001";
get_streamfile_basename(streamFile, filename, sizeof(filename));
len_name = strlen(filename);
len_cmp = strlen(cmp);
if (len_name > len_cmp && strcmp(filename + len_name - len_cmp, cmp) == 0) {
filename[(len_name - len_cmp) / 2] = '\0';
strcat(filename, ".acb");
VGM_LOG("%s\n", filename);
acbFile = open_streamfile_by_filename(streamFile, filename);
}
}
/* probably loaded */ /* probably loaded */
load_acb_wave_name(acbFile, vgmstream, waveid, is_memory); load_acb_wave_name(acbFile, vgmstream, waveid, is_memory);

View File

@ -301,7 +301,7 @@ static int parse_awc_header(STREAMFILE* streamFile, awc_header* awc) {
(awc->codec && awc->codec != codec)) { (awc->codec && awc->codec != codec)) {
VGM_LOG("AWC: found header diffs in channel %i, ns=%i vs %i, sr=%i vs %i, c=%i vs %i\n", VGM_LOG("AWC: found header diffs in channel %i, ns=%i vs %i, sr=%i vs %i, c=%i vs %i\n",
ch, awc->num_samples, num_samples, awc->sample_rate, sample_rate, awc->codec, codec); ch, awc->num_samples, num_samples, awc->sample_rate, sample_rate, awc->codec, codec);
goto fail; //goto fail; //todo some Max Payne 3 cutscene channels have huge sample diffs
} }
awc->num_samples = num_samples; awc->num_samples = num_samples;

View File

@ -860,6 +860,7 @@ VGMSTREAM * init_vgmstream_nub_wav(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nub_vag(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_nub_vag(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_nub_at3(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nub_at3(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile); VGMSTREAM * init_vgmstream_nub_xma(STREAMFILE *streamFile);
VGMSTREAM * init_vgmstream_nub_dsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nub_idsp(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nub_idsp(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_nub_is14(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_nub_is14(STREAMFILE * streamFile);

View File

@ -120,6 +120,11 @@ VGMSTREAM * init_vgmstream_nub(STREAMFILE *streamFile) {
init_vgmstream_function = init_vgmstream_nub_xma; init_vgmstream_function = init_vgmstream_nub_xma;
break; break;
case 0x05: /* "dsp\0" */
fake_ext = "dsp";
init_vgmstream_function = init_vgmstream_nub_dsp;
break;
case 0x06: /* "idsp" */ case 0x06: /* "idsp" */
fake_ext = "idsp"; fake_ext = "idsp";
init_vgmstream_function = init_vgmstream_nub_idsp; init_vgmstream_function = init_vgmstream_nub_idsp;
@ -130,7 +135,6 @@ VGMSTREAM * init_vgmstream_nub(STREAMFILE *streamFile) {
init_vgmstream_function = init_vgmstream_nub_is14; init_vgmstream_function = init_vgmstream_nub_is14;
break; break;
case 0x05:
default: default:
VGM_LOG("NUB: unknown codec %x\n", codec); VGM_LOG("NUB: unknown codec %x\n", codec);
goto fail; goto fail;
@ -512,6 +516,40 @@ fail:
return NULL; return NULL;
} }
/* .nub dsp - from Namco NUB archives [Taiko no Tatsujin Wii Chou Goukanban (Wii)] */
VGMSTREAM * init_vgmstream_nub_dsp(STREAMFILE *streamFile) {
VGMSTREAM *vgmstream = NULL;
STREAMFILE *temp_sf = NULL;
off_t header_offset, stream_offset;
size_t header_size, stream_size;
/* checks */
if (!check_extensions(streamFile,"dsp"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x64737000) /* "dsp\0" */
goto fail;
/* paste header+data together and pass to meta, which has loop info too */
header_offset = 0xBC;
stream_size = read_32bitBE(0x14, streamFile);
header_size = read_32bitBE(0x1c, streamFile);
stream_offset = align_size_to_block(header_offset + header_size, 0x10);
temp_sf = setup_nub_streamfile(streamFile, header_offset, header_size, stream_offset, stream_size, "dsp");
if (!temp_sf) goto fail;
vgmstream = init_vgmstream_ngc_dsp_std(temp_sf);
if (!vgmstream) goto fail;
close_streamfile(temp_sf);
return vgmstream;
fail:
close_streamfile(temp_sf);
close_vgmstream(vgmstream);
return NULL;
}
/* .nub idsp - from Namco NUB archives [Soul Calibur Legends (Wii), Sky Crawlers: Innocent Aces (Wii)] */ /* .nub idsp - from Namco NUB archives [Soul Calibur Legends (Wii), Sky Crawlers: Innocent Aces (Wii)] */
VGMSTREAM * init_vgmstream_nub_idsp(STREAMFILE *streamFile) { VGMSTREAM * init_vgmstream_nub_idsp(STREAMFILE *streamFile) {
VGMSTREAM *vgmstream = NULL; VGMSTREAM *vgmstream = NULL;

View File

@ -221,7 +221,7 @@ static int read_fmt(int big_endian, STREAMFILE * streamFile, off_t current_chunk
goto fail; goto fail;
#endif #endif
case 0x270: /* ATRAC3 */ case 0x0270: /* ATRAC3 */
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
fmt->coding_type = coding_FFmpeg; fmt->coding_type = coding_FFmpeg;
fmt->is_at3 = 1; fmt->is_at3 = 1;
@ -312,6 +312,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
int32_t loop_start_wsmp = -1, loop_end_wsmp = -1; int32_t loop_start_wsmp = -1, loop_end_wsmp = -1;
int32_t loop_start_smpl = -1, loop_end_smpl = -1; int32_t loop_start_smpl = -1, loop_end_smpl = -1;
int32_t loop_start_cue = -1; int32_t loop_start_cue = -1;
int32_t loop_start_nxbf = -1;
int FormatChunkFound = 0, DataChunkFound = 0, JunkFound = 0; int FormatChunkFound = 0, DataChunkFound = 0, JunkFound = 0;
@ -340,7 +341,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
* .wvx: Godzilla - Destroy All Monsters Melee (Xbox) * .wvx: Godzilla - Destroy All Monsters Melee (Xbox)
* .str: Harry Potter and the Philosopher's Stone (Xbox) * .str: Harry Potter and the Philosopher's Stone (Xbox)
* .at3: standard ATRAC3 * .at3: standard ATRAC3
* .rws: Climax games (Silent Hill Origins PSP, Oblivion PSP) ATRAC3 * .rws: Climax ATRAC3 [Silent Hill Origins (PSP), Oblivion (PSP)]
* .aud: EA Replay ATRAC3 * .aud: EA Replay ATRAC3
* .at9: standard ATRAC9 * .at9: standard ATRAC9
* .saf: Whacked! (Xbox) * .saf: Whacked! (Xbox)
@ -377,6 +378,8 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
riff_size -= 0x04; /* [Halo 2 (PC)] (possibly bad extractor? 'Gravemind Tool') */ riff_size -= 0x04; /* [Halo 2 (PC)] (possibly bad extractor? 'Gravemind Tool') */
else if (riff_size == file_size && codec == 0x0300) else if (riff_size == file_size && codec == 0x0300)
riff_size -= 0x08; /* [Chrono Ma:gia (Android)] */ riff_size -= 0x08; /* [Chrono Ma:gia (Android)] */
else if (riff_size >= file_size && read_32bitBE(0x24,streamFile) == 0x4E584246) /* "NXBF" */
riff_size = file_size - 0x08; /* [R:Racing Evolution (Xbox)] */
} }
/* check for truncated RIFF */ /* check for truncated RIFF */
@ -506,6 +509,23 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
} }
break; break;
case 0x4E584246: /* "NXBF" (Namco NUS v1) [R:Racing Evolution (Xbox)] */
/* 0x00: "NXBF" again */
/* 0x04: always 0x1000? */
/* 0x08: data size */
/* 0x0c: channels */
/* 0x10: null */
loop_start_nxbf = read_32bitLE(current_chunk + 0x08 + 0x14, streamFile);
/* 0x18: sample rate */
/* 0x1c: volume? */
/* 0x20: type/flags? */
/* 0x24: codec? */
/* 0x28: null */
/* 0x2c: null */
/* 0x30: type/flags? */
loop_flag = (loop_start_nxbf >= 0);
break;
case 0x4A554E4B: /* "JUNK" */ case 0x4A554E4B: /* "JUNK" */
JunkFound = 1; JunkFound = 1;
break; break;
@ -778,6 +798,14 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
vgmstream->loop_start_sample = loop_start_cue; vgmstream->loop_start_sample = loop_start_cue;
vgmstream->loop_end_sample = vgmstream->num_samples; vgmstream->loop_end_sample = vgmstream->num_samples;
} }
else if (loop_start_nxbf != -1) {
switch (fmt.coding_type) {
case coding_PCM16LE:
vgmstream->loop_start_sample = pcm_bytes_to_samples(loop_start_nxbf, vgmstream->channels, 16);
vgmstream->loop_end_sample = vgmstream->num_samples;
break;
}
}
} }
if (mwv) { if (mwv) {
vgmstream->meta_type = meta_RIFF_WAVE_MWV; vgmstream->meta_type = meta_RIFF_WAVE_MWV;

View File

@ -153,10 +153,11 @@ VGMSTREAM * init_vgmstream_sgxd(STREAMFILE *streamFile) {
break; break;
} }
#endif #endif
case 0x05: /* Short PS-ADPCM [Afrika (PS3)] */ case 0x05: /* Short PS-ADPCM [Afrika (PS3), LocoRoco Cocoreccho! (PS3)] */
vgmstream->coding_type = coding_PSX_cfg; vgmstream->coding_type = coding_PSX_cfg;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x4; vgmstream->interleave_block_size = 0x4;
vgmstream->codec_config = 1; /* needs extended table */
break; break;

View File

@ -285,7 +285,7 @@ VGMSTREAM * init_vgmstream_ta_aac_mobile(STREAMFILE *streamFile) {
switch(codec) { switch(codec) {
case 0x0d: case 0x0d:
if (read_32bitLE(0x144, streamFile) != 0x40) goto fail; /* frame size */ if (read_32bitLE(0x144, streamFile) != 0x40) goto fail; /* frame size */
if (read_32bitLE(0x148, streamFile) != (0x40-0x04*channel_count)*2 / channel_count) goto fail; /* frame samples */ /* 0x148 or 0x150 (later games): frame samples */
if (channel_count > 2) goto fail; /* unknown data layout */ if (channel_count > 2) goto fail; /* unknown data layout */
vgmstream->coding_type = coding_ASKA; vgmstream->coding_type = coding_ASKA;

View File

@ -622,7 +622,7 @@ static VGMSTREAM * init_vgmstream_ubi_hx_header(ubi_hx_header *hx, STREAMFILE *s
switch(hx->codec) { switch(hx->codec) {
case PCM: case PCM:
vgmstream->coding_type = coding_PCM16LE; vgmstream->coding_type = hx->big_endian ? coding_PCM16BE : coding_PCM16LE;
vgmstream->layout_type = layout_interleave; vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02; vgmstream->interleave_block_size = 0x02;

View File

@ -2966,12 +2966,14 @@ static int config_sb_version(ubi_sb_header * sb, STREAMFILE *streamFile) {
} }
/* TMNT (2007)(X360)-bank 0x00190002 */ /* TMNT (2007)(X360)-bank 0x00190002 */
/* My Word Coach (2007)(Wii)-bank 0x00190002 */
/* Prince of Persia: Rival Swords (2007)(Wii)-bank 0x00190003 */ /* Prince of Persia: Rival Swords (2007)(Wii)-bank 0x00190003 */
/* Rainbow Six Vegas (2007)(PS3)-bank 0x00190005 */ /* Rainbow Six Vegas (2007)(PS3)-bank 0x00190005 */
/* Surf's Up (2007)(PS3)-bank 0x00190005 */ /* Surf's Up (2007)(PS3)-bank 0x00190005 */
/* Surf's Up (2007)(X360)-bank 0x00190005 */ /* Surf's Up (2007)(X360)-bank 0x00190005 */
/* Splinter Cell: Double Agent (2007)(PS3)-map 0x00190005 */ /* Splinter Cell: Double Agent (2007)(PS3)-map 0x00190005 */
if ((sb->version == 0x00190002 && sb->platform == UBI_X360) || if ((sb->version == 0x00190002 && sb->platform == UBI_X360) ||
(sb->version == 0x00190002 && sb->platform == UBI_WII) ||
(sb->version == 0x00190003 && sb->platform == UBI_WII) || (sb->version == 0x00190003 && sb->platform == UBI_WII) ||
(sb->version == 0x00190005 && sb->platform == UBI_PS3) || (sb->version == 0x00190005 && sb->platform == UBI_PS3) ||
(sb->version == 0x00190005 && sb->platform == UBI_X360)) { (sb->version == 0x00190005 && sb->platform == UBI_X360)) {
@ -3009,6 +3011,16 @@ static int config_sb_version(ubi_sb_header * sb, STREAMFILE *streamFile) {
return 1; return 1;
} }
/* Cranium Kabookii (2007)(Wii)-bank 0x001a0003 */
if (sb->version == 0x001a0003 && sb->platform == UBI_WII) {
config_sb_entry(sb, 0x6c, 0x78);
config_sb_audio_fs(sb, 0x2c, 0x30, 0x34);
config_sb_audio_he(sb, 0x40, 0x44, 0x4c, 0x54, 0x5c, 0x60);
return 1;
}
/* Rainbow Six Vegas 2 (2008)(PS3)-bank */ /* Rainbow Six Vegas 2 (2008)(PS3)-bank */
/* Rainbow Six Vegas 2 (2008)(X360)-bank */ /* Rainbow Six Vegas 2 (2008)(X360)-bank */
if ((sb->version == 0x001C0000 && sb->platform == UBI_PS3) || if ((sb->version == 0x001C0000 && sb->platform == UBI_PS3) ||

View File

@ -213,7 +213,7 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
goto fail; goto fail;
} }
if (ww.codec == IMA || ww.codec == VORBIS || ww.codec == XMA2 || ww.codec == OPUSNX) if (ww.codec == PCM || ww.codec == IMA || ww.codec == VORBIS || ww.codec == XMA2 || ww.codec == OPUSNX)
ww.truncated = 1; /* only seen those, probably all exist */ ww.truncated = 1; /* only seen those, probably all exist */
else else
goto fail; goto fail;
@ -242,6 +242,10 @@ VGMSTREAM * init_vgmstream_wwise(STREAMFILE *streamFile) {
vgmstream->layout_type = ww.channels > 1 ? layout_interleave : layout_none; vgmstream->layout_type = ww.channels > 1 ? layout_interleave : layout_none;
vgmstream->interleave_block_size = 0x02; vgmstream->interleave_block_size = 0x02;
if (ww.truncated) {
ww.data_size = ww.file_size - ww.data_offset;
}
vgmstream->num_samples = pcm_bytes_to_samples(ww.data_size, ww.channels, ww.bits_per_sample); vgmstream->num_samples = pcm_bytes_to_samples(ww.data_size, ww.channels, ww.bits_per_sample);
break; break;

View File

@ -132,12 +132,14 @@ VGMSTREAM * init_vgmstream_xvag(STREAMFILE *streamFile) {
switch (xvag.codec) { switch (xvag.codec) {
case 0x06: /* VAG (PS-ADPCM): God of War III (PS3), Uncharted 1/2 (PS3), Ratchet and Clank Future (PS3) */ case 0x06: /* VAG (PS-ADPCM): God of War III (PS3), Uncharted 1/2 (PS3), Ratchet and Clank Future (PS3) */
case 0x07: /* SVAG? (PS-ADPCM with extended table?): inFamous 1 (PS3) */ case 0x07: /* SVAG? (PS-ADPCM with extended table): inFamous 1 (PS3) */
if (xvag.subsongs > 1 && xvag.layers > 1) goto fail; if (xvag.subsongs > 1 && xvag.layers > 1) goto fail;
if (xvag.layers > 1 && xvag.layers != xvag.channels) goto fail; if (xvag.layers > 1 && xvag.layers != xvag.channels) goto fail;
if (xvag.subsongs > 1 && xvag.channels > 1) goto fail; /* unknown layout */ if (xvag.subsongs > 1 && xvag.channels > 1) goto fail; /* unknown layout */
vgmstream->coding_type = coding_PSX; vgmstream->coding_type = coding_PSX;
if (xvag.codec == 0x07)
vgmstream->codec_config = 1; /* needs extended table */
if (xvag.subsongs > 1) { /* God of War 3 (PS4) */ if (xvag.subsongs > 1) { /* God of War 3 (PS4) */
vgmstream->layout_type = layout_blocked_xvag_subsong; vgmstream->layout_type = layout_blocked_xvag_subsong;

View File

@ -1694,19 +1694,19 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
case coding_PSX: case coding_PSX:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_psx(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, decode_psx(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, 0); vgmstream->channels,vgmstream->samples_into_block,samples_to_do, 0, vgmstream->codec_config);
} }
break; break;
case coding_PSX_badflags: case coding_PSX_badflags:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_psx(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, decode_psx(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, 1); vgmstream->channels,vgmstream->samples_into_block,samples_to_do, 1, vgmstream->codec_config);
} }
break; break;
case coding_PSX_cfg: case coding_PSX_cfg:
for (ch = 0; ch < vgmstream->channels; ch++) { for (ch = 0; ch < vgmstream->channels; ch++) {
decode_psx_configurable(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch, decode_psx_configurable(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, vgmstream->interleave_block_size); vgmstream->channels,vgmstream->samples_into_block,samples_to_do, vgmstream->interleave_block_size, vgmstream->codec_config);
} }
break; break;
case coding_PSX_pivotal: case coding_PSX_pivotal: