Add ADPCM .xpcm [Eternal Fantasy (PC)]

This commit is contained in:
bnnm 2018-11-10 00:09:03 +01:00
parent 9b7161a207
commit ab90e08484
9 changed files with 61 additions and 4 deletions

View File

@ -0,0 +1,29 @@
#include "coding.h"
/* Circus XPCM mode 2 decoding, verified vs EF.exe (info from foo_adpcm/libpcm and https://github.com/lioncash/ExtractData) */
void decode_circus_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i, sample_pos = 0;
int32_t hist = stream->adpcm_history1_32;
int scale = stream->adpcm_scale;
off_t frame_offset = stream->offset; /* frame size is 1 */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
int8_t code = read_8bit(frame_offset+i,stream->streamfile);
hist += code << scale;
if (code == 0) {
if (scale > 0)
scale--;
}
else if (code == 127 || code == -128) {
if (scale < 8)
scale++;
}
outbuf[sample_pos] = hist;
}
stream->adpcm_history1_32 = hist;
stream->adpcm_scale = scale;
}

View File

@ -165,6 +165,8 @@ void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
/* derf_decoder */
void decode_derf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* circus_decoder */
void decode_circus_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
/* ea_mt_decoder*/
ea_mt_codec_data *init_ea_mt(int channels, int type);

View File

@ -605,6 +605,7 @@ static const coding_info coding_info_list[] = {
{coding_DERF, "Xilam DERF 8-bit DPCM"},
{coding_ACM, "InterPlay ACM"},
{coding_NWA, "VisualArt's NWA DPCM"},
{coding_CIRCUS_ADPCM, "Circus 8-bit ADPCM"},
{coding_EA_MT, "Electronic Arts MicroTalk"},

View File

@ -1726,6 +1726,14 @@
RelativePath=".\coding\yamaha_decoder.c"
>
</File>
<File
RelativePath=".\coding\celt_fsb_decoder.c"
>
</File>
<File
RelativePath=".\coding\circus_decoder.c"
>
</File>
<File
RelativePath=".\coding\coding_utils.c"
>

View File

@ -126,6 +126,7 @@
<ClCompile Include="coding\at3plus_decoder.c" />
<ClCompile Include="coding\atrac9_decoder.c" />
<ClCompile Include="coding\celt_fsb_decoder.c" />
<ClCompile Include="coding\circus_decoder.c" />
<ClCompile Include="coding\coding_utils.c" />
<ClCompile Include="coding\ffmpeg_decoder.c" />
<ClCompile Include="coding\ffmpeg_decoder_custom_opus.c" />

View File

@ -1417,6 +1417,9 @@
<ClCompile Include="coding\celt_fsb_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\circus_decoder.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\bcstm.c">
<Filter>meta\Source Files</Filter>
</ClCompile>

View File

@ -9,7 +9,6 @@ VGMSTREAM * init_vgmstream_xpcm(STREAMFILE *streamFile) {
int loop_flag, channel_count, codec, subcodec, sample_rate;
/* checks */
if (!check_extensions(streamFile, "pcm"))
goto fail;
@ -27,7 +26,7 @@ VGMSTREAM * init_vgmstream_xpcm(STREAMFILE *streamFile) {
/* 0x14: average bitrate */
/* 0x18: block size */
/* 0x1a: output bits (16) */
start_offset = 0x1c;
start_offset = 0x1c; /* compressed size in codec 0x01/03 */
loop_flag = 0;
@ -47,11 +46,16 @@ VGMSTREAM * init_vgmstream_xpcm(STREAMFILE *streamFile) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x02;
break;
case 0x02:
if (subcodec != 0) goto fail;
vgmstream->coding_type = coding_CIRCUS_ADPCM;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x01;
break;
case 0x01: /* LZSS + VQ */
case 0x02: /* ADPCM */
case 0x03: /* unknown */
default:
/* 0x1c contains compressed size for those */
goto fail;
}

View File

@ -1124,6 +1124,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_DERF:
case coding_NWA:
case coding_SASSC:
case coding_CIRCUS_ADPCM:
return 1;
case coding_IMA:
@ -1299,6 +1300,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_DERF:
case coding_NWA:
case coding_SASSC:
case coding_CIRCUS_ADPCM:
return 0x01;
case coding_IMA:
@ -1743,6 +1745,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
}
break;
case coding_CIRCUS_ADPCM:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_circus_adpcm(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
}
break;
case coding_IMA:
case coding_IMA_int:

View File

@ -159,6 +159,7 @@ typedef enum {
coding_DERF, /* DERF 8-bit DPCM */
coding_ACM, /* InterPlay ACM */
coding_NWA, /* VisualArt's NWA */
coding_CIRCUS_ADPCM, /* Circus 8-bit ADPCM */
coding_EA_MT, /* Electronic Arts MicroTalk (linear-predictive speech codec) */