diff --git a/src/coding/coding.h b/src/coding/coding.h index 150f909d..68a3b536 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -10,6 +10,7 @@ void g72x_init_state(struct g72x_state *state_ptr); void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_xbox_ima(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_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); diff --git a/src/coding/ima_decoder.c b/src/coding/ima_decoder.c index 81410dfd..7de4652c 100644 --- a/src/coding/ima_decoder.c +++ b/src/coding/ima_decoder.c @@ -114,3 +114,44 @@ void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspac 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; +} diff --git a/src/meta/aifc.c b/src/meta/aifc.c index 62d7bf96..00d28c84 100644 --- a/src/meta/aifc.c +++ b/src/meta/aifc.c @@ -167,6 +167,11 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) { coding_type = coding_SDX2; interleave = 1; break; + case 0x41445034: /* ADP4 */ + coding_type = coding_DVI_IMA; + /* don't know how stereo DVI is laid out */ + if (channel_count != 1) break; + break; default: /* we should probably support uncompressed here */ goto fail; @@ -262,7 +267,10 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) { vgmstream->sample_rate = sample_rate; vgmstream->coding_type = coding_type; - vgmstream->layout_type = layout_interleave; + if (channel_count > 1) + vgmstream->layout_type = layout_interleave; + else + vgmstream->layout_type = layout_none; vgmstream->interleave_block_size = interleave; vgmstream->loop_start_sample = loop_start; vgmstream->loop_end_sample = loop_end; diff --git a/src/meta/genh.c b/src/meta/genh.c index a015f893..aaa8ca2f 100644 --- a/src/meta/genh.c +++ b/src/meta/genh.c @@ -35,8 +35,9 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { /* 2 = NGC ADP/DTK ADPCM */ /* 3 = 16bit big endian PCM */ /* 4 = 16bit little endian PCM */ - /* 5 - 8bit PCM */ - /* 6 - SDX2 */ + /* 5 = 8bit PCM */ + /* 6 = SDX2 */ + /* 7 = DVI IMA */ /* ... others to come */ switch (read_32bitLE(0x18,streamFile)) { case 0: @@ -61,6 +62,9 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { case 6: coding = coding_SDX2; break; + case 7: + coding = coding_DVI_IMA; + break; default: goto fail; } @@ -104,6 +108,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { case coding_PCM8: case coding_SDX2: case coding_PSX: + case coding_DVI_IMA: vgmstream->interleave_block_size = interleave; if (channel_count > 1) { @@ -137,6 +142,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) { case coding_PCM16BE: case coding_PCM16LE: case coding_SDX2: + case coding_DVI_IMA: case coding_PCM8: if (vgmstream->layout_type == layout_interleave) { if (interleave >= 512) { diff --git a/src/vgmstream.c b/src/vgmstream.c index 778b4c17..83336459 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -295,6 +295,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { case coding_NGC_DTK: return 28; case coding_G721: + case coding_DVI_IMA: return 1; case coding_NGC_AFC: return 16; @@ -336,6 +337,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return vgmstream->interleave_block_size; case coding_NGC_DTK: return 32; + case coding_DVI_IMA: case coding_G721: return 0; case coding_NGC_AFC: @@ -480,6 +482,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + case coding_DVI_IMA: + for (chan=0;chanchannels;chan++) { + decode_dvi_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan, + vgmstream->channels,vgmstream->samples_into_block, + samples_to_do); + } + break; } } @@ -669,6 +678,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) { case coding_SDX2: snprintf(temp,TEMPSIZE,"Squareroot-delta-exact (SDX2) 8-bit DPCM"); break; + case coding_DVI_IMA: + snprintf(temp,TEMPSIZE,"Intel DVI 4-bit IMA ADPCM"); + break; default: snprintf(temp,TEMPSIZE,"CANNOT DECODE"); } diff --git a/src/vgmstream.h b/src/vgmstream.h index 56f22e1b..5c995132 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -36,6 +36,7 @@ typedef enum { coding_ogg_vorbis, /* vorbis */ #endif coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */ + coding_DVI_IMA, /* DVI IMA, aka ADP4 */ } coding_t; /* The layout type specifies how the sound data is laid out in the file */