Fix REF-IMA ADPCM decoding/num_samples, as it's based on MS-IMA

This commit is contained in:
bnnm 2018-02-17 18:19:28 +01:00
parent 5e00485948
commit 05916bdf26
2 changed files with 63 additions and 45 deletions

View File

@ -331,6 +331,62 @@ void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * out
//stream->adpcm_step_index = step_index; //stream->adpcm_step_index = step_index;
} }
/* Reflection's MS-IMA (some layout info from XA2WAV by Deniz Oezmen) */
void decode_ref_ima(VGMSTREAM * vgmstream, VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, samples_read = 0, samples_done = 0, max_samples;
int32_t hist1;// = stream->adpcm_history1_32;
int step_index;// = stream->adpcm_step_index;
/* internal interleave (configurable size), mixed channels (4 byte per ch) */
int block_channel_size = (vgmstream->interleave_block_size - 0x04*vgmstream->channels) / vgmstream->channels;
int block_samples = ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
first_sample = first_sample % block_samples;
/* normal header (hist+step+reserved per channel) */
{
off_t header_offset = stream->offset + 0x04*channel;
hist1 = read_16bitLE(header_offset+0x00,stream->streamfile);
step_index = read_8bit(header_offset+0x02,stream->streamfile); /* 0x03: reserved */
if (step_index < 0) step_index = 0;
if (step_index > 88) step_index = 88;
/* write header sample */
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)hist1;
samples_done++;
}
samples_read++;
}
max_samples = (block_samples - samples_read);
if (max_samples > samples_to_do + first_sample - samples_done)
max_samples = samples_to_do + first_sample - samples_done; /* for smaller last block */
/* decode nibbles (layout: all nibbles from one channel, then other channels) */
for (i = 0; i < max_samples; i++) {
off_t byte_offset = stream->offset + 0x04*vgmstream->channels + block_channel_size*channel + i/2;
int nibble_shift = (i&1?4:0); /* low nibble first */
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
if (samples_read >= first_sample && samples_done < samples_to_do) {
outbuf[samples_done * channelspacing] = (short)(hist1);
samples_done++;
}
samples_read++;
}
/* internal interleave: increment offset on complete frame */
if (first_sample + samples_done == block_samples) {
stream->offset += vgmstream->interleave_block_size;
}
//stream->adpcm_history1_32 = hist1;
//stream->adpcm_step_index = step_index;
}
/* ************************************ */ /* ************************************ */
/* XBOX-IMA */ /* XBOX-IMA */
/* ************************************ */ /* ************************************ */
@ -387,7 +443,7 @@ void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * o
stream->adpcm_step_index = step_index; stream->adpcm_step_index = step_index;
} }
/* mono XBOX ADPCM for interleave */ /* mono XBOX-IMA ADPCM for interleave */
void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0, num_frame; int i, sample_count = 0, num_frame;
int32_t hist1 = stream->adpcm_history1_32; int32_t hist1 = stream->adpcm_history1_32;
@ -674,44 +730,6 @@ void decode_wwise_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample *
stream->adpcm_step_index = step_index; stream->adpcm_step_index = step_index;
} }
/* Reflection's MS-IMA (some layout info from XA2WAV) */
void decode_ref_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i, sample_count;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
//internal interleave (configurable size), mixed channels (4 byte per ch)
int block_channel_size = (vgmstream->interleave_block_size - 4*vgmstream->channels) / vgmstream->channels;
int block_samples = (vgmstream->interleave_block_size - 4*vgmstream->channels) * 2 / vgmstream->channels;
first_sample = first_sample % block_samples;
//normal header (per channel)
if (first_sample == 0) {
off_t header_offset = stream->offset + 4*channel;
hist1 = read_16bitLE(header_offset,stream->streamfile);
step_index = read_8bit(header_offset+2,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
//layout: all nibbles from one channel, then all nibbles from other
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
off_t byte_offset = stream->offset + 4*vgmstream->channels + block_channel_size*channel + i/2;
int nibble_shift = (i&1?4:0); //low nibble first
std_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
outbuf[sample_count] = (short)(hist1);
}
//internal interleave: increment offset on complete frame
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { void decode_awc_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_count; int i, sample_count;

View File

@ -1076,16 +1076,16 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_APPLE_IMA4: case coding_APPLE_IMA4:
return 64; return 64;
case coding_MS_IMA: case coding_MS_IMA:
return ((vgmstream->interleave_block_size-4*vgmstream->channels) * 2 / vgmstream->channels) + 1; case coding_REF_IMA:
return ((vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels) + 1;
case coding_RAD_IMA: case coding_RAD_IMA:
case coding_WWISE_IMA: case coding_WWISE_IMA:
case coding_REF_IMA: return (vgmstream->interleave_block_size - 0x04*vgmstream->channels) * 2 / vgmstream->channels;
return (vgmstream->interleave_block_size-4*vgmstream->channels)*2/vgmstream->channels;
case coding_NDS_IMA: case coding_NDS_IMA:
case coding_DAT4_IMA: case coding_DAT4_IMA:
return (vgmstream->interleave_block_size-4)*2; return (vgmstream->interleave_block_size - 0x04) * 2;
case coding_AWC_IMA: case coding_AWC_IMA:
return (0x800-4)*2; return (0x800 - 0x04) * 2;
case coding_RAD_IMA_mono: case coding_RAD_IMA_mono:
return 32; return 32;