Add 3DS IMA for BCSTM and fix old IMA regression (HWAS/SWAV/SAD/AUD/etc)

Standard IMA algorithm was changed for BCSTM, subtly altering regular
IMA's waveforms (not too audible). Now this 3DS variation is separate.
This commit is contained in:
bnnm 2017-11-18 22:25:44 +01:00
parent d37deb8d80
commit ea634ad473
6 changed files with 40 additions and 6 deletions

View File

@ -22,6 +22,7 @@ void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_standard_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int is_stereo, int is_high_first);
void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);

View File

@ -41,8 +41,8 @@ static const int IMA_IndexTable[16] =
};
/* Alt IMA */
static void ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
/* 3DS IMA (Mario Golf, Mario Tennis; maybe other Camelot games) */
static void n3ds_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
//"original" ima nibble expansion
@ -64,7 +64,7 @@ static void ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int
if (*step_index > 88) *step_index=88;
}
/* Microsoft's IMA (most common) */
/* Standard IMA (most common) */
static void ms_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
@ -86,7 +86,7 @@ static void ms_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, i
if (*step_index > 88) *step_index=88;
}
/* Apple's MS IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend) */
/* Apple's IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend) */
static void ms_ima_expand_nibble_16(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int16_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
@ -472,7 +472,29 @@ void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
off_t byte_offset = stream->offset + i/2;
int nibble_shift = (i&1?4:0); //low nibble order
ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
void decode_3ds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
//external interleave
//no header
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + i/2;
int nibble_shift = (i&1?4:0); //low nibble order
n3ds_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
}

View File

@ -442,6 +442,7 @@ static const coding_info coding_info_list[] = {
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (interleaved)"},
{coding_IMA_int, "IMA 4-bit ADPCM (interleaved)"},
{coding_IMA, "IMA 4-bit ADPCM"},
{coding_3DS_IMA, "3DS IMA 4-bit ADPCM"},
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
{coding_RAD_IMA, "Radical 4-bit IMA ADPCM"},
{coding_RAD_IMA_mono, "Radical 4-bit IMA ADPCM (mono)"},

View File

@ -75,7 +75,7 @@ VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
if (seek_offset == 0) goto fail;
if ((uint32_t)read_32bitBE(seek_offset, streamFile) != 0x5345454B) { /* "SEEK" If this header doesn't exist, assuming that the file is IMA */
ima = 1;
coding_type = coding_IMA_int;
coding_type = coding_3DS_IMA;
}
else
coding_type = coding_NGC_DSP;

View File

@ -1026,6 +1026,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return 1;
case coding_IMA_int:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
case coding_AICA:
return 2;
case coding_NGC_AFC:
@ -1211,6 +1212,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_IMA_int:
case coding_DVI_IMA:
case coding_DVI_IMA_int:
case coding_3DS_IMA:
case coding_AICA:
return 1;
case coding_APPLE_IMA4:
@ -1627,6 +1629,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_3DS_IMA:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_3ds_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break;
case coding_APPLE_IMA4:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_apple_ima4(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,

View File

@ -135,6 +135,7 @@ typedef enum {
coding_REF_IMA, /* Reflections IMA ADPCM */
coding_AWC_IMA, /* Rockstar AWC IMA ADPCM */
coding_UBI_IMA, /* Ubisoft IMA ADPCM */
coding_3DS_IMA, /* 3DS IMA ADPCM */
coding_MSADPCM, /* Microsoft ADPCM */
coding_WS, /* Westwood Studios VBR ADPCM */