mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-19 08:07:23 +01:00
Merge pull request #831 from bnnm/nus-msadpcm
- Fix .nus3audio with dummy entries [Gundam Extreme Vs Maxi Boost ON (PS4)] - Fix .xsew [Mega Man X Legacy Collection (PC)] - Improve MSADPCM performance (~50%) + doc spec diffs - Add partial .str+wav support for Zapper Beta (PS2)
This commit is contained in:
commit
ce033e53b3
@ -147,6 +147,7 @@ class TxtpMaker(object):
|
||||
self.stream_count = self._get_value("stream count: ")
|
||||
self.stream_index = self._get_value("stream index: ")
|
||||
self.stream_name = self._get_text("stream name: ")
|
||||
self.encoding = self._get_text("encoding: ")
|
||||
|
||||
if self.channels <= 0 or self.sample_rate <= 0:
|
||||
raise ValueError('Incorrect command result')
|
||||
@ -204,6 +205,8 @@ class TxtpMaker(object):
|
||||
p = re.compile(cfg.include_regex)
|
||||
if p.match(self.stream_name) is None:
|
||||
return True
|
||||
if self.encoding.lower() == 'silence':
|
||||
return True
|
||||
return False
|
||||
|
||||
def _get_stream_mask(self, layer):
|
||||
|
@ -156,6 +156,8 @@ void free_nwa(nwa_codec_data* data);
|
||||
STREAMFILE* nwa_get_streamfile(nwa_codec_data* data);
|
||||
|
||||
/* msadpcm_decoder */
|
||||
#define MSADPCM_MAX_BLOCK_SIZE 0x800 /* known max and RIFF spec seems to concur, while MS's encoders may be lower (typical stereo: 0x8c, 0x2C, 0x48, 0x400) */
|
||||
|
||||
void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
|
||||
|
@ -1,7 +1,9 @@
|
||||
#include "../util.h"
|
||||
#include "coding.h"
|
||||
|
||||
/* table values are interpreted as fixed point 8.8 signed values */
|
||||
|
||||
/* AdaptionTable */
|
||||
static const int16_t msadpcm_steps[16] = {
|
||||
230, 230, 230, 230,
|
||||
307, 409, 512, 614,
|
||||
@ -9,6 +11,7 @@ static const int16_t msadpcm_steps[16] = {
|
||||
307, 230, 230, 230
|
||||
};
|
||||
|
||||
/* aCoeff table, normally included with container and (in theory) encoder may add extra coefs but first 7 are preset coefs */
|
||||
static const int16_t msadpcm_coefs[7][2] = {
|
||||
{ 256, 0 },
|
||||
{ 512, -256 },
|
||||
@ -19,16 +22,23 @@ static const int16_t msadpcm_coefs[7][2] = {
|
||||
{ 392, -232 }
|
||||
};
|
||||
|
||||
|
||||
/* Decodes MSADPCM as explained in the spec (RIFFNEW / msadpcm.c).
|
||||
* Though RIFFNEW spec uses "predictor / 256", msadpcm.c uses "predictor >> 8" = diffs on negs (silly MS).
|
||||
* SHR is also true in Windows msadp32.acm decoders (up to Win10), that seem to use same code.
|
||||
* Some non-Windows implementations or engines (like UE4) use DIV though (more accurate).
|
||||
* On invalid coef index, msadpcm.c returns 0 decoded samples but here we clamp and keep on trucking.
|
||||
* In theory blocks may be 0-padded and should use samples_per_frame from header, in practice seems to
|
||||
* decode up to block length or available data. */
|
||||
void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first_sample, int32_t samples_to_do) {
|
||||
VGMSTREAMCHANNEL *ch1,*ch2;
|
||||
STREAMFILE *streamfile;
|
||||
VGMSTREAMCHANNEL *stream1, *stream2;
|
||||
uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0};
|
||||
int i, frames_in;
|
||||
size_t bytes_per_frame, samples_per_frame;
|
||||
off_t frame_offset;
|
||||
|
||||
ch1 = &vgmstream->ch[0];
|
||||
ch2 = &vgmstream->ch[1];
|
||||
streamfile = ch1->streamfile;
|
||||
stream1 = &vgmstream->ch[0];
|
||||
stream2 = &vgmstream->ch[1];
|
||||
|
||||
/* external interleave (variable size), stereo */
|
||||
bytes_per_frame = vgmstream->frame_size;
|
||||
@ -36,61 +46,63 @@ void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first
|
||||
frames_in = first_sample / samples_per_frame;
|
||||
first_sample = first_sample % samples_per_frame;
|
||||
|
||||
frame_offset = ch1->offset + frames_in*bytes_per_frame;
|
||||
frame_offset = stream1->offset + frames_in * bytes_per_frame;
|
||||
read_streamfile(frame, frame_offset, bytes_per_frame, stream1->streamfile); /* ignore EOF errors */
|
||||
|
||||
/* parse frame header */
|
||||
/* parse frame header (ADPCMBLOCKHEADER) */
|
||||
if (first_sample == 0) {
|
||||
ch1->adpcm_coef[0] = msadpcm_coefs[read_8bit(frame_offset+0x00,streamfile) & 0x07][0];
|
||||
ch1->adpcm_coef[1] = msadpcm_coefs[read_8bit(frame_offset+0x00,streamfile) & 0x07][1];
|
||||
ch2->adpcm_coef[0] = msadpcm_coefs[read_8bit(frame_offset+0x01,streamfile)][0];
|
||||
ch2->adpcm_coef[1] = msadpcm_coefs[read_8bit(frame_offset+0x01,streamfile)][1];
|
||||
ch1->adpcm_scale = read_16bitLE(frame_offset+0x02,streamfile);
|
||||
ch2->adpcm_scale = read_16bitLE(frame_offset+0x04,streamfile);
|
||||
ch1->adpcm_history1_16 = read_16bitLE(frame_offset+0x06,streamfile);
|
||||
ch2->adpcm_history1_16 = read_16bitLE(frame_offset+0x08,streamfile);
|
||||
ch1->adpcm_history2_16 = read_16bitLE(frame_offset+0x0a,streamfile);
|
||||
ch2->adpcm_history2_16 = read_16bitLE(frame_offset+0x0c,streamfile);
|
||||
stream1->adpcm_coef[0] = msadpcm_coefs[get_u8(frame+0x00) & 0x07][0]; /* bPredictor[0] index > iCoef1 */
|
||||
stream1->adpcm_coef[1] = msadpcm_coefs[get_u8(frame+0x00) & 0x07][1]; /* bPredictor[0] index > iCoef2 */
|
||||
stream2->adpcm_coef[0] = msadpcm_coefs[get_u8(frame+0x01) & 0x07][0]; /* bPredictor[1] index > iCoef1 */
|
||||
stream2->adpcm_coef[1] = msadpcm_coefs[get_u8(frame+0x01) & 0x07][1]; /* bPredictor[1] index > iCoef2 */
|
||||
stream1->adpcm_scale = get_s16le(frame+0x02); /* iDelta[0] */
|
||||
stream2->adpcm_scale = get_s16le(frame+0x04); /* iDelta[0] */
|
||||
stream1->adpcm_history1_16 = get_s16le(frame+0x06); /* iSamp1[0] */
|
||||
stream2->adpcm_history1_16 = get_s16le(frame+0x08); /* iSamp1[0] */
|
||||
stream1->adpcm_history2_16 = get_s16le(frame+0x0a); /* iSamp2[0] */
|
||||
stream2->adpcm_history2_16 = get_s16le(frame+0x0c); /* iSamp2[1] */
|
||||
}
|
||||
|
||||
/* write header samples (needed) */
|
||||
if (first_sample==0) {
|
||||
outbuf[0] = ch1->adpcm_history2_16;
|
||||
outbuf[1] = ch2->adpcm_history2_16;
|
||||
outbuf[0] = stream1->adpcm_history2_16;
|
||||
outbuf[1] = stream2->adpcm_history2_16;
|
||||
outbuf += 2;
|
||||
first_sample++;
|
||||
samples_to_do--;
|
||||
}
|
||||
if (first_sample == 1 && samples_to_do > 0) {
|
||||
outbuf[0] = ch1->adpcm_history1_16;
|
||||
outbuf[1] = ch2->adpcm_history1_16;
|
||||
outbuf[0] = stream1->adpcm_history1_16;
|
||||
outbuf[1] = stream2->adpcm_history1_16;
|
||||
outbuf += 2;
|
||||
first_sample++;
|
||||
samples_to_do--;
|
||||
}
|
||||
|
||||
/* decode nibbles */
|
||||
for (i = first_sample; i < first_sample+samples_to_do; i++) {
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
int ch;
|
||||
|
||||
for (ch = 0; ch < 2; ch++) {
|
||||
VGMSTREAMCHANNEL *stream = &vgmstream->ch[ch];
|
||||
int32_t hist1,hist2, predicted;
|
||||
int sample_nibble = (ch == 0) ? /* L = high nibble first */
|
||||
get_high_nibble_signed(read_8bit(frame_offset+0x07*2+(i-2),streamfile)) :
|
||||
get_low_nibble_signed (read_8bit(frame_offset+0x07*2+(i-2),streamfile));
|
||||
VGMSTREAMCHANNEL* stream = &vgmstream->ch[ch];
|
||||
int32_t hist1, hist2, predicted;
|
||||
uint8_t byte = get_u8(frame+0x07*2+(i-2));
|
||||
int sample_nibble = (ch == 0) ? /* L = high nibble first (iErrorDelta) */
|
||||
get_high_nibble_signed(byte) :
|
||||
get_low_nibble_signed (byte);
|
||||
|
||||
hist1 = stream->adpcm_history1_16;
|
||||
hist2 = stream->adpcm_history2_16;
|
||||
predicted = hist1*stream->adpcm_coef[0] + hist2*stream->adpcm_coef[1];
|
||||
predicted = predicted / 256;
|
||||
predicted = predicted + sample_nibble*stream->adpcm_scale;
|
||||
outbuf[0] = clamp16(predicted);
|
||||
predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1];
|
||||
predicted = predicted / 256; /* 256 = FIXED_POINT_COEF_BASE (though MS code uses SHR) */
|
||||
predicted = predicted + (sample_nibble * stream->adpcm_scale);
|
||||
outbuf[0] = clamp16(predicted); /* lNewSample */
|
||||
|
||||
stream->adpcm_history2_16 = stream->adpcm_history1_16;
|
||||
stream->adpcm_history1_16 = outbuf[0];
|
||||
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) / 256;
|
||||
if (stream->adpcm_scale < 0x10)
|
||||
stream->adpcm_scale = 0x10;
|
||||
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) / 256; /* 256 = FIXED_POINT_ADAPTION_BASE */
|
||||
if (stream->adpcm_scale < 16) /* min delta */
|
||||
stream->adpcm_scale = 16;
|
||||
|
||||
outbuf++;
|
||||
}
|
||||
@ -98,7 +110,8 @@ void decode_msadpcm_stereo(VGMSTREAM* vgmstream, sample_t* outbuf, int32_t first
|
||||
}
|
||||
|
||||
void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL *stream = &vgmstream->ch[channel];
|
||||
VGMSTREAMCHANNEL* stream = &vgmstream->ch[channel];
|
||||
uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0};
|
||||
int i, frames_in;
|
||||
size_t bytes_per_frame, samples_per_frame;
|
||||
off_t frame_offset;
|
||||
@ -109,15 +122,16 @@ void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspac
|
||||
frames_in = first_sample / samples_per_frame;
|
||||
first_sample = first_sample % samples_per_frame;
|
||||
|
||||
frame_offset = stream->offset + frames_in*bytes_per_frame;
|
||||
frame_offset = stream->offset + frames_in * bytes_per_frame;
|
||||
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
|
||||
|
||||
/* parse frame header */
|
||||
if (first_sample == 0) {
|
||||
stream->adpcm_coef[0] = msadpcm_coefs[read_8bit(frame_offset+0x00,stream->streamfile) & 0x07][0];
|
||||
stream->adpcm_coef[1] = msadpcm_coefs[read_8bit(frame_offset+0x00,stream->streamfile) & 0x07][1];
|
||||
stream->adpcm_scale = read_16bitLE(frame_offset+0x01,stream->streamfile);
|
||||
stream->adpcm_history1_16 = read_16bitLE(frame_offset+0x03,stream->streamfile);
|
||||
stream->adpcm_history2_16 = read_16bitLE(frame_offset+0x05,stream->streamfile);
|
||||
stream->adpcm_coef[0] = msadpcm_coefs[get_u8(frame+0x00) & 0x07][0];
|
||||
stream->adpcm_coef[1] = msadpcm_coefs[get_u8(frame+0x00) & 0x07][1];
|
||||
stream->adpcm_scale = get_s16le(frame+0x01);
|
||||
stream->adpcm_history1_16 = get_s16le(frame+0x03);
|
||||
stream->adpcm_history2_16 = get_s16le(frame+0x05);
|
||||
}
|
||||
|
||||
/* write header samples (needed) */
|
||||
@ -135,33 +149,35 @@ void decode_msadpcm_mono(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspac
|
||||
}
|
||||
|
||||
/* decode nibbles */
|
||||
for (i = first_sample; i < first_sample+samples_to_do; i++) {
|
||||
int32_t hist1,hist2, predicted;
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
int32_t hist1, hist2, predicted;
|
||||
uint8_t byte = get_u8(frame+0x07+(i-2)/2);
|
||||
int sample_nibble = (i & 1) ? /* high nibble first */
|
||||
get_low_nibble_signed (read_8bit(frame_offset+0x07+(i-2)/2,stream->streamfile)) :
|
||||
get_high_nibble_signed(read_8bit(frame_offset+0x07+(i-2)/2,stream->streamfile));
|
||||
get_low_nibble_signed (byte) :
|
||||
get_high_nibble_signed(byte);
|
||||
|
||||
hist1 = stream->adpcm_history1_16;
|
||||
hist2 = stream->adpcm_history2_16;
|
||||
predicted = hist1*stream->adpcm_coef[0] + hist2*stream->adpcm_coef[1];
|
||||
predicted = hist1 * stream->adpcm_coef[0] + hist2 * stream->adpcm_coef[1];
|
||||
predicted = predicted / 256;
|
||||
predicted = predicted + sample_nibble*stream->adpcm_scale;
|
||||
predicted = predicted + (sample_nibble * stream->adpcm_scale);
|
||||
outbuf[0] = clamp16(predicted);
|
||||
|
||||
stream->adpcm_history2_16 = stream->adpcm_history1_16;
|
||||
stream->adpcm_history1_16 = outbuf[0];
|
||||
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) / 256;
|
||||
if (stream->adpcm_scale < 0x10)
|
||||
stream->adpcm_scale = 0x10;
|
||||
if (stream->adpcm_scale < 16) /* min delta */
|
||||
stream->adpcm_scale = 16;
|
||||
|
||||
outbuf += channelspacing;
|
||||
}
|
||||
}
|
||||
|
||||
/* Cricket Audio's MSADPCM, same thing with reversed hist and nibble order
|
||||
* (their tools may convert to float/others but internally it's all PCM16, from debugging). */
|
||||
/* Cricket Audio's MSADPCM, same thing with reversed hist and nibble order, reverse engineered from the exe.
|
||||
* (their tools may convert to float/others but internally it's all PCM16). */
|
||||
void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL *stream = &vgmstream->ch[channel];
|
||||
VGMSTREAMCHANNEL* stream = &vgmstream->ch[channel];
|
||||
uint8_t frame[MSADPCM_MAX_BLOCK_SIZE] = {0};
|
||||
int i, frames_in;
|
||||
size_t bytes_per_frame, samples_per_frame;
|
||||
off_t frame_offset;
|
||||
@ -172,15 +188,16 @@ void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacin
|
||||
frames_in = first_sample / samples_per_frame;
|
||||
first_sample = first_sample % samples_per_frame;
|
||||
|
||||
frame_offset = stream->offset + frames_in*bytes_per_frame;
|
||||
frame_offset = stream->offset + frames_in * bytes_per_frame;
|
||||
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
|
||||
|
||||
/* parse frame header */
|
||||
if (first_sample == 0) {
|
||||
stream->adpcm_coef[0] = msadpcm_coefs[read_8bit(frame_offset+0x00,stream->streamfile) & 0x07][0];
|
||||
stream->adpcm_coef[1] = msadpcm_coefs[read_8bit(frame_offset+0x00,stream->streamfile) & 0x07][1];
|
||||
stream->adpcm_scale = read_16bitLE(frame_offset+0x01,stream->streamfile);
|
||||
stream->adpcm_history2_16 = read_16bitLE(frame_offset+0x03,stream->streamfile); /* hist2 first, unlike normal MSADPCM */
|
||||
stream->adpcm_history1_16 = read_16bitLE(frame_offset+0x05,stream->streamfile);
|
||||
stream->adpcm_coef[0] = msadpcm_coefs[get_u8(frame+0x00) & 0x07][0];
|
||||
stream->adpcm_coef[1] = msadpcm_coefs[get_u8(frame+0x00) & 0x07][1];
|
||||
stream->adpcm_scale = get_s16le(frame+0x01);
|
||||
stream->adpcm_history2_16 = get_s16le(frame+0x03); /* hist2 first, unlike normal MSADPCM */
|
||||
stream->adpcm_history1_16 = get_s16le(frame+0x05);
|
||||
}
|
||||
|
||||
/* write header samples (needed) */
|
||||
@ -200,22 +217,23 @@ void decode_msadpcm_ck(VGMSTREAM* vgmstream, sample_t* outbuf, int channelspacin
|
||||
/* decode nibbles */
|
||||
for (i = first_sample; i < first_sample+samples_to_do; i++) {
|
||||
int32_t hist1,hist2, predicted;
|
||||
uint8_t byte = get_u8(frame+0x07+(i-2)/2);
|
||||
int sample_nibble = (i & 1) ? /* low nibble first, unlike normal MSADPCM */
|
||||
get_high_nibble_signed (read_8bit(frame_offset+0x07+(i-2)/2,stream->streamfile)) :
|
||||
get_low_nibble_signed(read_8bit(frame_offset+0x07+(i-2)/2,stream->streamfile));
|
||||
get_high_nibble_signed(byte) :
|
||||
get_low_nibble_signed (byte);
|
||||
|
||||
hist1 = stream->adpcm_history1_16;
|
||||
hist2 = stream->adpcm_history2_16;
|
||||
predicted = hist1*stream->adpcm_coef[0] + hist2*stream->adpcm_coef[1];
|
||||
predicted = predicted >> 8; /* probably no difference vs MSADPCM */
|
||||
predicted = predicted + sample_nibble*stream->adpcm_scale;
|
||||
predicted = hist1 * stream->adpcm_coef[0] + hist2 *stream->adpcm_coef[1];
|
||||
predicted = predicted >> 8; /* not DIV unlike spec */
|
||||
predicted = predicted + (sample_nibble * stream->adpcm_scale);
|
||||
outbuf[0] = clamp16(predicted);
|
||||
|
||||
stream->adpcm_history2_16 = stream->adpcm_history1_16;
|
||||
stream->adpcm_history1_16 = outbuf[0];
|
||||
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) >> 8;
|
||||
if (stream->adpcm_scale < 0x10)
|
||||
stream->adpcm_scale = 0x10;
|
||||
stream->adpcm_scale = (msadpcm_steps[sample_nibble & 0xf] * stream->adpcm_scale) >> 8; /* not DIV but same here (always >=0) */
|
||||
if (stream->adpcm_scale < 16)
|
||||
stream->adpcm_scale = 16;
|
||||
|
||||
outbuf += channelspacing;
|
||||
}
|
||||
@ -230,7 +248,7 @@ long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) {
|
||||
/* test if MSADPCM coefs were re-defined (possible in theory but not used in practice) */
|
||||
int msadpcm_check_coefs(STREAMFILE* sf, off_t offset) {
|
||||
int i;
|
||||
int count = read_16bitLE(offset, sf);
|
||||
int count = read_u16le(offset, sf);
|
||||
if (count != 7) {
|
||||
VGM_LOG("MSADPCM: bad count %i at %lx\n", count, offset);
|
||||
goto fail;
|
||||
@ -238,8 +256,8 @@ int msadpcm_check_coefs(STREAMFILE* sf, off_t offset) {
|
||||
|
||||
offset += 0x02;
|
||||
for (i = 0; i < 7; i++) {
|
||||
int16_t coef1 = read_16bitLE(offset + 0x00, sf);
|
||||
int16_t coef2 = read_16bitLE(offset + 0x02, sf);
|
||||
int16_t coef1 = read_s16le(offset + 0x00, sf);
|
||||
int16_t coef2 = read_s16le(offset + 0x02, sf);
|
||||
|
||||
if (coef1 != msadpcm_coefs[i][0] || coef2 != msadpcm_coefs[i][1]) {
|
||||
VGM_LOG("MSADPCM: bad coef %i/%i vs %i/%i\n", coef1, coef2, msadpcm_coefs[i][0], msadpcm_coefs[i][1]);
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
typedef enum { IDSP, OPUS, RIFF, } nus3audio_codec;
|
||||
|
||||
/* .nus3audio - Namco's newest newest audio container [Super Smash Bros. Ultimate (Switch)] */
|
||||
/* .nus3audio - Namco's newest newest audio container [Super Smash Bros. Ultimate (Switch), Mobile Suit Gundam: Extreme Vs. Maxi Boost ON (PS4)] */
|
||||
VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
||||
VGMSTREAM* vgmstream = NULL;
|
||||
STREAMFILE* temp_sf = NULL;
|
||||
@ -11,7 +11,7 @@ VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
||||
size_t subfile_size = 0;
|
||||
nus3audio_codec codec;
|
||||
const char* fake_ext = NULL;
|
||||
int total_subsongs, target_subsong = sf->stream_index;
|
||||
int total_subsongs, target_subsong = sf->stream_index, found = 0;
|
||||
|
||||
|
||||
/* checks */
|
||||
@ -51,6 +51,7 @@ VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
||||
case 0x41444F46: /* "ADOF": audio offsets (absolute, inside PACK) */
|
||||
subfile_offset = read_u32le(offset+0x08 + 0x08*(target_subsong-1) + 0x00,sf);
|
||||
subfile_size = read_u32le(offset+0x08 + 0x08*(target_subsong-1) + 0x04,sf);
|
||||
found = 1;
|
||||
break;
|
||||
|
||||
case 0x544E4944: /* "TNID": tone ids? */
|
||||
@ -64,11 +65,23 @@ VGMSTREAM* init_vgmstream_nus3audio(STREAMFILE* sf) {
|
||||
offset += 0x08 + chunk_size;
|
||||
}
|
||||
|
||||
if (total_subsongs == 0 || subfile_offset == 0 || subfile_size == 0) {
|
||||
if (total_subsongs == 0 || !found) {
|
||||
VGM_LOG("NUS3AUDIO: subfile not found\n");
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* handle dummy entries, ex. Gundam EvM (PS4) */
|
||||
if (subfile_offset == 0 && subfile_size == 0) {
|
||||
vgmstream = init_vgmstream_silence(0, 0, 0);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->num_streams = total_subsongs;
|
||||
snprintf(vgmstream->stream_name, STREAM_NAME_SIZE, "%s", "dummy");
|
||||
|
||||
return vgmstream;
|
||||
}
|
||||
|
||||
|
||||
codec_id = read_u32be(subfile_offset, sf);
|
||||
switch(codec_id) {
|
||||
case 0x49445350: /* "IDSP" */
|
||||
|
@ -333,7 +333,7 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
||||
* .adx: Remember11 (PC) sfx
|
||||
* .adp: Headhunter (DC)
|
||||
* .xss: Spider-Man The Movie (Xbox)
|
||||
* .xsew: Mega Man X Legacy Collections (PC)
|
||||
* .xsew: Mega Man X Legacy Collection (PC)
|
||||
* .adpcm: Angry Birds Transformers (Android)
|
||||
* .adw: Dead Rising 2 (PC)
|
||||
* .wd: Genma Onimusha (Xbox) voices
|
||||
@ -416,6 +416,9 @@ VGMSTREAM* init_vgmstream_riff(STREAMFILE* sf) {
|
||||
|
||||
else if (codec == 0xFFFE && riff_size + 0x08 + 0x30 == file_size)
|
||||
riff_size += 0x30; /* [E.X. Troopers (PS3)] (adds "ver /eBIT/tIME/mrkr" empty chunks but RIFF size wasn't updated) */
|
||||
|
||||
else if (codec == 0x0002 && riff_size + 0x08 + 0x1c == file_size)
|
||||
riff_size += 0x1c; /* [Mega Man X Legacy Collection (PC)] (adds "ver /tIME/ver " chunks but RIFF size wasn't updated) */
|
||||
}
|
||||
|
||||
/* check for truncated RIFF */
|
||||
|
@ -362,6 +362,29 @@ static int parse_header(STREAMFILE* sf_h, strwav_header* strwav) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Zapper: One Wicked Cricket! Beta (PS2)[2005] */
|
||||
if ( read_u32be(0x04,sf_h) == 0x00000900 &&
|
||||
read_u32le(0x2c,sf_h) == 44100 && /* sample rate */
|
||||
read_u32le(0x70,sf_h) == 0 && /* sample rate repeat? */
|
||||
header_size == 0x78
|
||||
) {
|
||||
strwav->num_samples = read_u32le(0x5c,sf_h);
|
||||
strwav->sample_rate = read_u32le(0x2c,sf_h);
|
||||
strwav->flags = read_u32le(0x34,sf_h);
|
||||
strwav->loop_start = 0;
|
||||
strwav->loop_end = 0;
|
||||
|
||||
strwav->channels = read_u32le(0x60,sf_h) * (strwav->flags & 0x02 ? 2 : 1); /* tracks of 2/1ch */
|
||||
strwav->loop_flag = strwav->flags & 0x01;
|
||||
strwav->interleave = strwav->channels > 2 ? 0x8000 : 0x8000;
|
||||
//todo: tracks are stereo blocks of size 0x20000*tracks, containing 4 interleaves of 0x8000:
|
||||
// | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | 1 2 1 2 | 3 4 3 4 | 5 6 5 6 | ...
|
||||
|
||||
strwav->codec = PSX;
|
||||
;VGM_LOG("STR+WAV: header Zapper Beta (PS2)\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Zapper: One Wicked Cricket! (PS2)[2005] */
|
||||
if ( read_32bitBE(0x04,sf_h) == 0x00000900 &&
|
||||
read_32bitLE(0x24,sf_h) == read_32bitLE(0x70,sf_h) && /* sample rate repeat */
|
||||
|
@ -1530,6 +1530,14 @@ int vgmstream_open_stream_bf(VGMSTREAM* vgmstream, STREAMFILE* sf, off_t start_o
|
||||
vgmstream->frame_size = vgmstream->interleave_block_size;
|
||||
}
|
||||
|
||||
if ((vgmstream->coding_type == coding_MSADPCM ||
|
||||
vgmstream->coding_type == coding_MSADPCM_ck ||
|
||||
vgmstream->coding_type == coding_MSADPCM_int) &&
|
||||
(vgmstream->frame_size > MSADPCM_MAX_BLOCK_SIZE)) {
|
||||
VGM_LOG("VGMSTREAM: MSADPCM decoder with wrong frame size %x\n", vgmstream->frame_size);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
/* big interleaved values for non-interleaved data may result in incorrect behavior,
|
||||
* quick fix for now since layouts are finicky, with 'interleave' left for meta info
|
||||
* (certain layouts+codecs combos results in funny output too, should rework the whole thing) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user