mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Fuse EACS and DVI IMA decoder into a configurable IMA decoder
EACS was just DVI (high nibble first) with stereo and mono modes, while old DVI was mono only. This unifies both decoders, so DVI_IMA (not interleaved) works with mono and stereo while DVI_IMA_int (interleaved) forces mono. Some metas needed to explicitly set DVI_IMA_int but others work with no change.
This commit is contained in:
parent
4dfbc3cf6a
commit
4a2cf9dd91
@ -19,9 +19,8 @@ void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
||||
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_xbox_ima(VGMSTREAM * vgmstream,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);
|
||||
void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
void decode_eacs_ima(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, 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_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);
|
||||
|
@ -426,8 +426,11 @@ void decode_xbox_ima_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
|
||||
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, sample_count;
|
||||
/* Standard DVI/IMA ADPCM (as in, ADPCM recommended by the IMA using Intel/DVI's implementation).
|
||||
* Configurable: stereo or mono/interleave nibbles, and high or low nibble first.
|
||||
* For vgmstream, low nibble is called "IMA ADPCM" and high nibble is "DVI IMA ADPCM" (same thing though). */
|
||||
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) {
|
||||
int i, sample_count = 0;
|
||||
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
int step_index = stream->adpcm_step_index;
|
||||
@ -436,37 +439,13 @@ void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
||||
|
||||
//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?0:4); //high nibble first (old-style DVI)
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/* basically DVI stereo (high=L + low=R nibbles) and DVI mono (high=L, low=L) all-in-one, can be simplified/removed */
|
||||
void decode_eacs_ima(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
|
||||
VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);//todo pass externally for consistency
|
||||
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 = channelspacing == 1 ?
|
||||
stream->offset + i/2 : /* mono mode */
|
||||
stream->offset + i; /* stereo mode */
|
||||
int nibble_shift = channelspacing == 1 ?
|
||||
(!(i%2) ? 4:0) : /* mono mode (high first) */
|
||||
(channel==0 ? 4:0); /* stereo mode (high=L,low=R) */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++, sample_count += channelspacing) {
|
||||
off_t byte_offset = is_stereo ?
|
||||
stream->offset + i : /* stereo: one nibble per channel */
|
||||
stream->offset + i/2; /* mono: consecutive nibbles */
|
||||
int nibble_shift = is_high_first ?
|
||||
is_stereo ? (!(channel&1) ? 4:0) : (!(i&1) ? 4:0) : /* even = high, odd = low */
|
||||
is_stereo ? (!(channel&1) ? 0:4) : (!(i&1) ? 0:4); /* even = low, odd = high */
|
||||
|
||||
ms_ima_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index);
|
||||
outbuf[sample_count] = (short)(hist1);
|
||||
|
@ -440,7 +440,6 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_CBD2_int, "Cuberoot-delta-exact (CBD2) 8-bit DPCM with 1 byte interleave"},
|
||||
{coding_DVI_IMA, "Intel DVI 4-bit IMA ADPCM"},
|
||||
{coding_DVI_IMA_int, "Intel DVI 4-bit IMA ADPCM (interleaved)"},
|
||||
{coding_EACS_IMA, "EACS 4-bit IMA ADPCM"},
|
||||
{coding_IMA_int, "IMA 4-bit ADPCM (interleaved)"},
|
||||
{coding_IMA, "IMA 4-bit ADPCM"},
|
||||
{coding_MS_IMA, "Microsoft 4-bit IMA ADPCM"},
|
||||
|
@ -91,7 +91,7 @@ void ea_schl_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
break;
|
||||
|
||||
/* id, size, IMA hist, stereo/mono data */
|
||||
case coding_EACS_IMA:
|
||||
case coding_DVI_IMA:
|
||||
for(i = 0; i < vgmstream->channels; i++) {
|
||||
off_t header_offset = block_offset + 0xc + i*4;
|
||||
vgmstream->ch[i].adpcm_history1_32 = read_16bitLE(header_offset+0x00, vgmstream->ch[i].streamfile);
|
||||
@ -196,7 +196,7 @@ void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||
|
||||
vgmstream->current_block_size=block_size-8;
|
||||
|
||||
if(vgmstream->coding_type==coding_EACS_IMA) {
|
||||
if(vgmstream->coding_type==coding_DVI_IMA) {
|
||||
vgmstream->current_block_size=read_32bitLE(block_offset,vgmstream->ch[0].streamfile);
|
||||
|
||||
for(i=0;i<vgmstream->channels;i++) {
|
||||
|
@ -27,7 +27,7 @@ VGMSTREAM * init_vgmstream_dc_kcey(STREAMFILE *streamFile) {
|
||||
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
|
||||
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
|
||||
|
||||
vgmstream->coding_type = coding_EACS_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA;
|
||||
vgmstream->layout_type = layout_none;
|
||||
vgmstream->meta_type = meta_DC_KCEY;
|
||||
|
||||
|
@ -65,7 +65,7 @@ VGMSTREAM * init_vgmstream_eacs(STREAMFILE *streamFile) {
|
||||
vgmstream->coding_type = coding_PCM8_int;
|
||||
}
|
||||
else
|
||||
vgmstream->coding_type = coding_EACS_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA;
|
||||
|
||||
vgmstream->layout_type = layout_eacs_blocked;
|
||||
vgmstream->meta_type = meta_EACS_PC;
|
||||
|
@ -66,7 +66,7 @@ VGMSTREAM * init_vgmstream_ea_schl_fixed(STREAMFILE *streamFile) {
|
||||
break;
|
||||
|
||||
case EA_CODEC_IMA:
|
||||
vgmstream->coding_type = coding_EACS_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA;
|
||||
break;
|
||||
|
||||
default:
|
||||
|
@ -28,10 +28,10 @@ VGMSTREAM * init_vgmstream_tun(STREAMFILE *streamFile) {
|
||||
start_offset = 0x10;
|
||||
vgmstream->channels = channel_count;
|
||||
vgmstream->sample_rate = 22050;
|
||||
vgmstream->coding_type = coding_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->num_samples = (get_streamfile_size(streamFile)) - 0x10;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 1;
|
||||
vgmstream->interleave_block_size = 0x01;
|
||||
vgmstream->meta_type = meta_TUN;
|
||||
|
||||
/* open the file for reading */
|
||||
|
@ -36,7 +36,7 @@ VGMSTREAM * init_vgmstream_x360_tra(STREAMFILE *streamFile) {
|
||||
vgmstream->channels = 2;
|
||||
vgmstream->sample_rate = 24000;
|
||||
|
||||
vgmstream->coding_type = coding_DVI_IMA;
|
||||
vgmstream->coding_type = coding_DVI_IMA_int;
|
||||
vgmstream->num_samples = (int32_t)(get_streamfile_size(streamFile) - ((get_streamfile_size(streamFile)/0x204)*4));
|
||||
vgmstream->layout_type = layout_tra_blocked;
|
||||
|
||||
|
@ -1019,7 +1019,6 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
return 28;
|
||||
case coding_G721:
|
||||
case coding_DVI_IMA:
|
||||
case coding_EACS_IMA:
|
||||
case coding_SNDS_IMA:
|
||||
case coding_IMA:
|
||||
case coding_OTNS_IMA:
|
||||
@ -1175,9 +1174,6 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
return 0x14;
|
||||
case coding_NGC_DTK:
|
||||
return 32;
|
||||
case coding_EACS_IMA:
|
||||
return 1;
|
||||
case coding_DVI_IMA:
|
||||
case coding_IMA:
|
||||
case coding_G721:
|
||||
case coding_SNDS_IMA:
|
||||
@ -1213,6 +1209,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
case coding_WS:
|
||||
return vgmstream->current_block_size;
|
||||
case coding_IMA_int:
|
||||
case coding_DVI_IMA:
|
||||
case coding_DVI_IMA_int:
|
||||
case coding_AICA:
|
||||
return 1;
|
||||
@ -1614,16 +1611,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
case coding_DVI_IMA:
|
||||
case coding_DVI_IMA_int:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_dvi_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
int is_stereo = vgmstream->channels > 1 && vgmstream->coding_type == coding_DVI_IMA;
|
||||
int is_high_first = vgmstream->coding_type == coding_DVI_IMA || vgmstream->coding_type == coding_DVI_IMA_int;
|
||||
|
||||
decode_standard_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do);
|
||||
}
|
||||
break;
|
||||
case coding_EACS_IMA:
|
||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||
decode_eacs_ima(vgmstream,buffer+samples_written*vgmstream->channels+chan,
|
||||
vgmstream->channels,vgmstream->samples_into_block,
|
||||
samples_to_do,chan);
|
||||
samples_to_do, chan, is_stereo, is_high_first);
|
||||
}
|
||||
break;
|
||||
case coding_IMA:
|
||||
|
@ -120,10 +120,9 @@ typedef enum {
|
||||
coding_XBOX_int, /* XBOX IMA ADPCM (interleaved) */
|
||||
coding_IMA, /* IMA ADPCM (low nibble first) */
|
||||
coding_IMA_int, /* IMA ADPCM (interleaved) */
|
||||
coding_DVI_IMA, /* DVI IMA ADPCM (high nibble first), aka ADP4 */
|
||||
coding_DVI_IMA_int, /* DVI IMA ADPCM (Interleaved) */
|
||||
coding_DVI_IMA, /* DVI IMA ADPCM (stereo or mono, high nibble first) */
|
||||
coding_DVI_IMA_int, /* DVI IMA ADPCM (mono/interleave, high nibble first) */
|
||||
coding_NDS_IMA, /* IMA ADPCM w/ NDS layout */
|
||||
coding_EACS_IMA, /* Electronic Arts IMA ADPCM */
|
||||
coding_MS_IMA, /* Microsoft IMA ADPCM */
|
||||
coding_RAD_IMA, /* Radical IMA ADPCM */
|
||||
coding_RAD_IMA_mono, /* Radical IMA ADPCM, mono (for interleave) */
|
||||
|
Loading…
x
Reference in New Issue
Block a user