From a2af7567647ef0b7838eb01aab4e80f4332c78a0 Mon Sep 17 00:00:00 2001 From: soneek Date: Sun, 1 Jun 2014 20:19:05 -0400 Subject: [PATCH] hcs's update for IMA decoder --- src/coding/ima_decoder.c | 1272 +++++++++++++++++++------------------- 1 file changed, 635 insertions(+), 637 deletions(-) diff --git a/src/coding/ima_decoder.c b/src/coding/ima_decoder.c index 434303c4..3700383c 100644 --- a/src/coding/ima_decoder.c +++ b/src/coding/ima_decoder.c @@ -1,637 +1,635 @@ -#include "../util.h" -#include "coding.h" - -const int32_t ADPCMTable[89] = - -{ - - 7, 8, 9, 10, 11, 12, 13, 14, - 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, 1707, 1878, 2066, 2272, 2499, 2749, 3024, - 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, - 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, - 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, - 32767 - -}; - -const int IMA_IndexTable[16] = - -{ - -1, -1, -1, -1, 2, 4, 6, 8, - -1, -1, -1, -1, 2, 4, 6, 8 -}; - -void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i=first_sample; - int32_t sample_count; - int32_t hist1 = stream->adpcm_history1_16; - int step_index = stream->adpcm_step_index; - - if (first_sample==0) { - hist1 = read_16bitLE(stream->offset,stream->streamfile); - step_index = read_16bitLE(stream->offset+2,stream->streamfile); - } - - for (i=first_sample,sample_count=0; ioffset+4+i/2,stream->streamfile) >> (i&1?4:0))&0xf; - int delta; - int step = ADPCMTable[step_index]; - - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - outbuf[sample_count] = clamp16(hist1 - delta); - else - outbuf[sample_count] = clamp16(hist1 + delta); - - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - hist1 = outbuf[sample_count]; - } - - stream->adpcm_history1_16 = hist1; - stream->adpcm_step_index = step_index; -} - -void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i=first_sample; - int32_t sample_count; - int32_t hist1 = stream->adpcm_history1_16; - int step_index = stream->adpcm_step_index; - - if (first_sample==0) { - hist1 = read_16bitLE(stream->offset,stream->streamfile); - step_index = read_8bit(stream->offset+2,stream->streamfile); - } - - for (i=first_sample,sample_count=0; ioffset+4+i/2,stream->streamfile) >> (i&1?0:4))&0xf; - int delta; - int step = ADPCMTable[step_index]; - - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - outbuf[sample_count] = clamp16(hist1 - delta); - else - outbuf[sample_count] = clamp16(hist1 + delta); - - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - hist1 = outbuf[sample_count]; - } - - stream->adpcm_history1_16 = hist1; - stream->adpcm_step_index = step_index; -} - -/* Xbox IMA is MS IMA, but I'll leave it alone for now (esp as it has > 2 channel support) */ -void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { - int i=first_sample; - int sample_nibble; - int sample_decoded; - int delta; - int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - off_t offset=stream->offset; - - first_sample = first_sample % block_samples; - - if (first_sample == 0) { - - hist1 = read_16bitLE(offset+channel*4,stream->streamfile); - step_index = read_16bitLE(offset+channel*4+2,stream->streamfile); - - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + (i/8*4*vgmstream->channels) + (i%8)/2 + 4*channel; - - sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; - - sample_decoded=hist1; - - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - - } - - // Only 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; -} - -// "Radical ADPCM", essentially MS IMA -void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { - int i=first_sample; - int sample_nibble; - int sample_decoded; - int delta; - int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - off_t offset=stream->offset; - - first_sample = first_sample % block_samples; - - if (first_sample == 0) { - - hist1 = read_16bitLE(offset+channel*4+2,stream->streamfile); - step_index = read_16bitLE(offset+channel*4,stream->streamfile); - - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + (i/2*vgmstream->channels) + channel; - - sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; - - sample_decoded=hist1; - - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - - } - - // Only 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; -} - -// "Radical ADPCM", mono form (for use with interleave layout) -// I think this is exactly equivalent to mono MS APDCM, but I need a -// channel-agnostic version to use within an interleave. -void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i=first_sample; - int sample_nibble; - int sample_decoded; - int delta; - int block_samples = 0x14 * 2; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - off_t offset=stream->offset; - - first_sample = first_sample % block_samples; - - if (first_sample == 0) { - - hist1 = read_16bitLE(offset+2,stream->streamfile); - step_index = read_16bitLE(offset,stream->streamfile); - - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ioffset + 4 + (i/2); - - sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; - - sample_decoded=hist1; - - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - - } - - stream->adpcm_history1_32=hist1; - stream->adpcm_step_index=step_index; -} - -void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { - int i=first_sample; - int sample_nibble; - int sample_decoded; - int delta; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - off_t offset=stream->offset; - - if(vgmstream->channels==1) - first_sample = first_sample % 32; - else - first_sample = first_sample % (32*(vgmstream->channels&2)); - - if (first_sample == 0) { - - if(vgmstream->layout_type==layout_ea_blocked) { - hist1 = read_16bitLE(offset,stream->streamfile); - step_index = read_16bitLE(offset+2,stream->streamfile); - } else { - hist1 = read_16bitLE(offset+(channel%2)*4,stream->streamfile); - step_index = read_16bitLE(offset+(channel%2)*4+2,stream->streamfile); - } - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ilayout_type==layout_ea_blocked) - offset = stream->offset + (i/8*4+(i%8)/2+4); - else { - if(channelspacing==1) - offset = stream->offset + 4 + (i/8*4+(i%8)/2+4*(channel%2)); - else - offset = stream->offset + 4*2 + (i/8*4*2+(i%8)/2+4*(channel%2)); - } - - sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; - - sample_decoded=hist1; - - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - } - - // Only increment offset on complete frame - if(vgmstream->layout_type==layout_ea_blocked) { - if(offset-stream->offset==32+3) // ?? - stream->offset+=36; - } else { - if(channelspacing==1) { - if(offset-stream->offset==32+3) // ?? - stream->offset+=36; - } else { - if(offset-stream->offset==64+(4*(channel%2))+3) // ?? - stream->offset+=36*channelspacing; - } - } - stream->adpcm_history1_32=hist1; - stream->adpcm_step_index=step_index; -} - -void decode_int_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { - int i=first_sample; - int sample_nibble; - int sample_decoded; - int delta; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - off_t offset=stream->offset; - - if(vgmstream->channels==1) - first_sample = first_sample % 32; - else - first_sample = first_sample % (32*(vgmstream->channels&2)); - - if (first_sample == 0) { - - hist1 = read_16bitLE(offset,stream->streamfile); - step_index = read_16bitLE(offset+2,stream->streamfile); - - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - } - - for (i=first_sample,sample_count=0; ioffset + 4 + (i/8*4+(i%8)/2); - - sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; - - sample_decoded=hist1; - - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - } - - // Only increment offset on complete frame - if(channelspacing==1) { - if(offset-stream->offset==32+3) // ?? - stream->offset+=36; - } else { - if(offset-stream->offset==64+(4*(channel%2))+3) // ?? - stream->offset+=36*channelspacing; - } - stream->adpcm_history1_32=hist1; - stream->adpcm_step_index=step_index; -} - -void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile); - /* old-style DVI takes high nibble first */ - sample_nibble = (sample_byte >> (i&1?0:4))&0xf; - - sample_decoded = hist1; - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble&0x7]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - } - - stream->adpcm_history1_32=hist1; - stream->adpcm_step_index=step_index; -} - - -void decode_eacs_ima(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { - int i; - VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]); - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - vgmstream->get_high_nibble=!vgmstream->get_high_nibble; - - if((first_sample) && (channelspacing==1)) - vgmstream->get_high_nibble=!vgmstream->get_high_nibble; - - for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); - sample_nibble = (sample_byte >> (vgmstream->get_high_nibble?0:4))&0xf; - - sample_decoded = hist1; - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble&0x7]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - } - - stream->adpcm_history1_32=hist1; - stream->adpcm_step_index=step_index; -} - -void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile); - sample_nibble = (sample_byte >> (i&1?4:0))&0xf; - - sample_decoded = hist1; - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble&0x7]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - } - - stream->adpcm_history1_32=hist1; - stream->adpcm_step_index=step_index; -} - -void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { - int i; - - int32_t sample_count=0; - int16_t hist1=stream->adpcm_history1_16; - int step_index = stream->adpcm_step_index; - - off_t packet_offset = stream->offset + first_sample/64*34; - - first_sample = first_sample % 64; - - if (first_sample == 0) - { - hist1 = (int16_t)((uint16_t)read_16bitBE(packet_offset,stream->streamfile) & 0xff80); - step_index = read_8bit(packet_offset+1,stream->streamfile) & 0x7f; - } - - for (i=first_sample,sample_count=0; istreamfile); - sample_nibble = (sample_byte >> (i&1?4:0))&0xf; - - sample_decoded = hist1; - delta = step >> 3; - if (sample_nibble & 1) delta += step >> 2; - if (sample_nibble & 2) delta += step >> 1; - if (sample_nibble & 4) delta += step; - if (sample_nibble & 8) - sample_decoded -= delta; - else - sample_decoded += delta; - - hist1=clamp16(sample_decoded); - - step_index += IMA_IndexTable[sample_nibble&0x7]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - - outbuf[sample_count]=(short)(hist1); - } - - stream->adpcm_history1_16=hist1; - stream->adpcm_step_index=step_index; -} - -void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { - int i; - - int32_t sample_count=0; - int32_t hist1=stream->adpcm_history1_32; - int step_index = stream->adpcm_step_index; - - for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); - sample_nibble = (sample_byte >> (channel==0?0:4))&0xf; - - // update step before doing current sample - step_index += IMA_IndexTable[sample_nibble]; - if (step_index < 0) step_index=0; - if (step_index > 88) step_index=88; - step = ADPCMTable[step_index]; - - delta = (sample_nibble & 7) * step / 4 + step / 8; - if (sample_nibble & 8) delta = -delta; - sample_decoded = hist1 + delta; - - hist1=clamp16(sample_decoded); - - outbuf[sample_count]=(short)(hist1); - } - - stream->adpcm_history1_32=hist1; - stream->adpcm_step_index=step_index; -} - +#include "../util.h" +#include "coding.h" + +const int32_t ADPCMTable[89] = + +{ + + 7, 8, 9, 10, 11, 12, 13, 14, + 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, 1707, 1878, 2066, 2272, 2499, 2749, 3024, + 3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, + 7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899, + 15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794, + 32767 + +}; + +const int IMA_IndexTable[16] = + +{ + -1, -1, -1, -1, 2, 4, 6, 8, + -1, -1, -1, -1, 2, 4, 6, 8 +}; + +void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + int32_t hist1 = stream->adpcm_history1_16; + int step_index = stream->adpcm_step_index; + + if (first_sample==0) { + hist1 = read_16bitLE(stream->offset,stream->streamfile); + step_index = read_16bitLE(stream->offset+2,stream->streamfile); + } + + for (i=first_sample,sample_count=0; ioffset+4+i/2,stream->streamfile) >> (i&1?4:0))&0xf; + int delta; + int step = ADPCMTable[step_index]; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + outbuf[sample_count] = clamp16(hist1 - delta); + else + outbuf[sample_count] = clamp16(hist1 + delta); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_index; +} + +void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int32_t sample_count; + int32_t hist1 = stream->adpcm_history1_16; + int step_index = stream->adpcm_step_index; + + if (first_sample==0) { + hist1 = read_16bitLE(stream->offset,stream->streamfile); + step_index = read_8bit(stream->offset+2,stream->streamfile); + } + + for (i=first_sample,sample_count=0; ioffset+4+i/2,stream->streamfile) >> (i&1?0:4))&0xf; + int delta; + int step = ADPCMTable[step_index]; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + outbuf[sample_count] = clamp16(hist1 - delta); + else + outbuf[sample_count] = clamp16(hist1 + delta); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + hist1 = outbuf[sample_count]; + } + + stream->adpcm_history1_16 = hist1; + stream->adpcm_step_index = step_index; +} + +/* Xbox IMA is MS IMA, but I'll leave it alone for now (esp as it has > 2 channel support) */ +void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + first_sample = first_sample % block_samples; + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset+channel*4,stream->streamfile); + step_index = read_16bitLE(offset+channel*4+2,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + (i/8*4*vgmstream->channels) + (i%8)/2 + 4*channel; + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + + } + + // Only 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; +} + +// "Radical ADPCM", essentially MS IMA +void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + first_sample = first_sample % block_samples; + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset+channel*4+2,stream->streamfile); + step_index = read_16bitLE(offset+channel*4,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4*vgmstream->channels + (i/2*vgmstream->channels) + channel; + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + + } + + // Only 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; +} + +// "Radical ADPCM", mono form (for use with interleave layout) +// I think this is exactly equivalent to mono MS APDCM, but I need a +// channel-agnostic version to use within an interleave. +void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + int block_samples = 0x14 * 2; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + first_sample = first_sample % block_samples; + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset+2,stream->streamfile); + step_index = read_16bitLE(offset,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4 + (i/2); + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + if(vgmstream->channels==1) + first_sample = first_sample % 32; + else + first_sample = first_sample % (32*(vgmstream->channels&2)); + + if (first_sample == 0) { + + if(vgmstream->layout_type==layout_ea_blocked) { + hist1 = read_16bitLE(offset,stream->streamfile); + step_index = read_16bitLE(offset+2,stream->streamfile); + } else { + hist1 = read_16bitLE(offset+(channel%2)*4,stream->streamfile); + step_index = read_16bitLE(offset+(channel%2)*4+2,stream->streamfile); + } + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ilayout_type==layout_ea_blocked) + offset = stream->offset + (i/8*4+(i%8)/2+4); + else { + if(channelspacing==1) + offset = stream->offset + 4 + (i/8*4+(i%8)/2+4*(channel%2)); + else + offset = stream->offset + 4*2 + (i/8*4*2+(i%8)/2+4*(channel%2)); + } + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + // Only increment offset on complete frame + if(vgmstream->layout_type==layout_ea_blocked) { + if(offset-stream->offset==32+3) // ?? + stream->offset+=36; + } else { + if(channelspacing==1) { + if(offset-stream->offset==32+3) // ?? + stream->offset+=36; + } else { + if(offset-stream->offset==64+(4*(channel%2))+3) // ?? + stream->offset+=36*channelspacing; + } + } + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_int_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) { + int i=first_sample; + int sample_nibble; + int sample_decoded; + int delta; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + off_t offset=stream->offset; + + if(vgmstream->channels==1) + first_sample = first_sample % 32; + else + first_sample = first_sample % (32*(vgmstream->channels&2)); + + if (first_sample == 0) { + + hist1 = read_16bitLE(offset,stream->streamfile); + step_index = read_16bitLE(offset+2,stream->streamfile); + + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + } + + for (i=first_sample,sample_count=0; ioffset + 4 + (i/8*4+(i%8)/2); + + sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf; + + sample_decoded=hist1; + + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + // Only increment offset on complete frame + if(channelspacing==1) { + if(offset-stream->offset==32+3) // ?? + stream->offset+=36; + } else { + if(offset-stream->offset==64+(4*(channel%2))+3) // ?? + stream->offset+=36*channelspacing; + } + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + for (i=first_sample,sample_count=0; ioffset+i/2,stream->streamfile); + /* old-style DVI takes high nibble first */ + sample_nibble = (sample_byte >> (i&1?0:4))&0xf; + + sample_decoded = hist1; + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble&0x7]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + + +void decode_eacs_ima(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i; + VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]); + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + + if((first_sample) && (channelspacing==1)) + vgmstream->get_high_nibble=!vgmstream->get_high_nibble; + + for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); + sample_nibble = (sample_byte >> (vgmstream->get_high_nibble?0:4))&0xf; + + sample_decoded = hist1; + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble&0x7]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + + int32_t sample_count = 0; + int32_t hist1 = stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + for (i = first_sample, sample_count = 0; ioffset + i / 2, stream->streamfile); + sample_nibble = (sample_byte >> (i & 1 ? 4 : 0)) & 0xf; + + sample_decoded = hist1 << 3; + + delta = step * (sample_nibble & 7) * 2 + step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1 = clamp16(sample_decoded >> 3); + + step_index += IMA_IndexTable[sample_nibble & 0x7]; + if (step_index < 0) step_index = 0; + if (step_index > 88) step_index = 88; + + outbuf[sample_count] = (short)(hist1); + } + + stream->adpcm_history1_32 = hist1; + stream->adpcm_step_index = step_index; +} + +void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) { + int i; + + int32_t sample_count=0; + int16_t hist1=stream->adpcm_history1_16; + int step_index = stream->adpcm_step_index; + + off_t packet_offset = stream->offset + first_sample/64*34; + + first_sample = first_sample % 64; + + if (first_sample == 0) + { + hist1 = (int16_t)((uint16_t)read_16bitBE(packet_offset,stream->streamfile) & 0xff80); + step_index = read_8bit(packet_offset+1,stream->streamfile) & 0x7f; + } + + for (i=first_sample,sample_count=0; istreamfile); + sample_nibble = (sample_byte >> (i&1?4:0))&0xf; + + sample_decoded = hist1; + delta = step >> 3; + if (sample_nibble & 1) delta += step >> 2; + if (sample_nibble & 2) delta += step >> 1; + if (sample_nibble & 4) delta += step; + if (sample_nibble & 8) + sample_decoded -= delta; + else + sample_decoded += delta; + + hist1=clamp16(sample_decoded); + + step_index += IMA_IndexTable[sample_nibble&0x7]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_16=hist1; + stream->adpcm_step_index=step_index; +} + +void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) { + int i; + + int32_t sample_count=0; + int32_t hist1=stream->adpcm_history1_32; + int step_index = stream->adpcm_step_index; + + for (i=first_sample,sample_count=0; ioffset+i,stream->streamfile); + sample_nibble = (sample_byte >> (channel==0?0:4))&0xf; + + // update step before doing current sample + step_index += IMA_IndexTable[sample_nibble]; + if (step_index < 0) step_index=0; + if (step_index > 88) step_index=88; + step = ADPCMTable[step_index]; + + delta = (sample_nibble & 7) * step / 4 + step / 8; + if (sample_nibble & 8) delta = -delta; + sample_decoded = hist1 + delta; + + hist1=clamp16(sample_decoded); + + outbuf[sample_count]=(short)(hist1); + } + + stream->adpcm_history1_32=hist1; + stream->adpcm_step_index=step_index; +} +