Add Konami BMP .bin (as .lbin) + decoder [Jubeat Clan (AC)]

This commit is contained in:
bnnm 2019-09-08 21:12:13 +02:00
parent 677eeef2b9
commit 1bc7e0e410
10 changed files with 140 additions and 7 deletions

View File

@ -181,6 +181,7 @@ void decode_circus_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channel
/* oki_decoder */ /* oki_decoder */
void decode_pcfx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode); void decode_pcfx(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int mode);
void decode_oki16(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel); void decode_oki16(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_oki4s(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
size_t oki_bytes_to_samples(size_t bytes, int channels); size_t oki_bytes_to_samples(size_t bytes, int channels);
/* ptadpcm_decoder */ /* ptadpcm_decoder */

View File

@ -2,10 +2,13 @@
static const int step_sizes[49] = { /* OKI table (subsection of IMA's table) */ static const int step_sizes[49] = { /* OKI table (subsection of IMA's table) */
16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 16, 17, 19, 21, 23, 25, 28, 31,
55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, 34, 37, 41, 45, 50, 55, 60, 66,
173, 190, 209, 230, 253, 279, 307, 337, 371, 408, 449, 73, 80, 88, 97, 107, 118, 130, 143,
494, 544, 598, 658, 724, 796, 876, 963, 1060, 1166, 1282, 1411, 1552 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
}; };
static const int stex_indexes[16] = { /* OKI table (also from IMA) */ static const int stex_indexes[16] = { /* OKI table (also from IMA) */
@ -60,8 +63,9 @@ static void oki16_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, in
code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf; code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf;
step = step_sizes[*step_index]; step = step_sizes[*step_index];
/* IMA 'mul' style (standard OKI uses 'shift-add') */
delta = (code & 0x7); delta = (code & 0x7);
delta = (((delta * 2) + 1) * step) >> 3; /* IMA 'mul' style (standard OKI uses 'shift-add') */ delta = (((delta * 2) + 1) * step) >> 3;
if (code & 0x8) if (code & 0x8)
delta = -delta; delta = -delta;
*hist1 += delta; *hist1 += delta;
@ -75,6 +79,31 @@ static void oki16_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, in
*out_sample = *hist1; *out_sample = *hist1;
} }
static void oki4s_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index, int16_t *out_sample) {
int code, step, delta;
code = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift) & 0xf;
step = step_sizes[*step_index];
step = step << 4; /* original table has precomputed step_sizes so that this isn't done */
/* IMA 'shift-add' style (like standard OKI) */
delta = step >> 3;
if (code & 1) delta += step >> 2;
if (code & 2) delta += step >> 1;
if (code & 4) delta += step;
if (code & 8) delta = -delta;
*hist1 += delta;
*hist1 = clamp16(*hist1); /* standard OKI clamps hist to 2047,-2048 here */
*step_index += stex_indexes[code];
if (*step_index < 0) *step_index = 0;
if (*step_index > 48) *step_index = 48;
*out_sample = *hist1;
}
/* PC-FX ADPCM decoding, variation of OKI/Dialogic/VOX ADPCM. Based on mednafen/pcfx-music-dump. /* PC-FX ADPCM decoding, variation of OKI/Dialogic/VOX ADPCM. Based on mednafen/pcfx-music-dump.
* Apparently most ADPCM was made with a buggy encoder, resulting in incorrect sound in real hardware * Apparently most ADPCM was made with a buggy encoder, resulting in incorrect sound in real hardware
* and sound clipped at half. Decoding can be controlled with modes: * and sound clipped at half. Decoding can be controlled with modes:
@ -138,6 +167,37 @@ void decode_oki16(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspaci
stream->adpcm_step_index = step_index; stream->adpcm_step_index = step_index;
} }
/* OKI variation with 16-bit output (vs standard's 12-bit) and pre-adjusted tables (shifted by 4), found in Jubeat Clan (AC).
* Reverse engineered from the DLLs. */
void decode_oki4s(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i, sample_count = 0;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
int16_t out_sample;
int is_stereo = channelspacing > 1;
/* external interleave */
/* no header (external setup), pre-clamp for wrong values */
if (step_index < 0) step_index=0;
if (step_index > 48) step_index=48;
/* decode nibbles (layout: varies) */
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 (assumed) */
int nibble_shift =
is_stereo ? (!(channel&1) ? 0:4) : (!(i&1) ? 0:4); /* even = low, odd = high */
oki4s_expand_nibble(stream, byte_offset,nibble_shift, &hist1, &step_index, &out_sample);
outbuf[sample_count] = (out_sample);
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}
size_t oki_bytes_to_samples(size_t bytes, int channels) { size_t oki_bytes_to_samples(size_t bytes, int channels) {
if (channels <= 0) return 0; if (channels <= 0) return 0;

View File

@ -2,7 +2,8 @@
/* Defines the list of accepted extensions. vgmstream doesn't use it internally so it's here /* Defines the list of accepted extensions. vgmstream doesn't use it internally so it's here
* to inform plugins that need it. Common extensions are commented out to avoid stealing them. */ * to inform plugins that need it. Common extensions are commented out to avoid stealing them
* and possibly adding an unwanted association to the player. */
/* Some extensions require external libraries and could be #ifdef, not worth. */ /* Some extensions require external libraries and could be #ifdef, not worth. */
@ -93,6 +94,7 @@ static const char* extension_list[] = {
"bik", "bik",
"bika", "bika",
"bik2", "bik2",
//"bin", //common
"bk2", "bk2",
"bmdx", "bmdx",
"bms", "bms",
@ -237,6 +239,7 @@ static const char* extension_list[] = {
"laifc", //fake extension for .aifc "laifc", //fake extension for .aifc
"lac3", //fake extension for .ac3, FFmpeg/not parsed "lac3", //fake extension for .ac3, FFmpeg/not parsed
"lasf", //fake extension for .asf (various) "lasf", //fake extension for .asf (various)
"lbin", //fake extension for .bin (various)
"leg", "leg",
"lflac", //fake extension for .flac, FFmpeg/not parsed "lflac", //fake extension for .flac, FFmpeg/not parsed
"lin", "lin",
@ -688,6 +691,7 @@ static const coding_info coding_info_list[] = {
{coding_XMD, "Konami XMD 4-bit ADPCM"}, {coding_XMD, "Konami XMD 4-bit ADPCM"},
{coding_PCFX, "PC-FX 4-bit ADPCM"}, {coding_PCFX, "PC-FX 4-bit ADPCM"},
{coding_OKI16, "OKI 4-bit ADPCM (16-bit output)"}, {coding_OKI16, "OKI 4-bit ADPCM (16-bit output)"},
{coding_OKI4S, "OKI 4-bit ADPCM (4-shift)"},
{coding_PTADPCM, "Platinum 4-bit ADPCM"}, {coding_PTADPCM, "Platinum 4-bit ADPCM"},
{coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"}, {coding_SDX2, "Squareroot-delta-exact (SDX2) 8-bit DPCM"},
@ -1205,6 +1209,7 @@ static const meta_info meta_info_list[] = {
{meta_IMA, "Blitz Games .IMA header"}, {meta_IMA, "Blitz Games .IMA header"},
{meta_XMV_VALVE, "Valve XMV header"}, {meta_XMV_VALVE, "Valve XMV header"},
{meta_UBI_HX, "Ubisoft HXx header"}, {meta_UBI_HX, "Ubisoft HXx header"},
{meta_BMP_KONAMI, "Konami BMP header"},
}; };

View File

@ -508,6 +508,10 @@
RelativePath=".\meta\bik.c" RelativePath=".\meta\bik.c"
> >
</File> </File>
<File
RelativePath=".\meta\bmp_konami.c"
>
</File>
<File <File
RelativePath=".\meta\bnk_sony.c" RelativePath=".\meta\bnk_sony.c"
> >

View File

@ -256,6 +256,7 @@
<ClCompile Include="meta\baf.c" /> <ClCompile Include="meta\baf.c" />
<ClCompile Include="meta\bgw.c" /> <ClCompile Include="meta\bgw.c" />
<ClCompile Include="meta\bik.c" /> <ClCompile Include="meta\bik.c" />
<ClCompile Include="meta\bmp_konami.c" />
<ClCompile Include="meta\bnk_sony.c" /> <ClCompile Include="meta\bnk_sony.c" />
<ClCompile Include="meta\bnsf.c" /> <ClCompile Include="meta\bnsf.c" />
<ClCompile Include="meta\brstm.c" /> <ClCompile Include="meta\brstm.c" />

View File

@ -1597,6 +1597,9 @@
<ClCompile Include="meta\bik.c"> <ClCompile Include="meta\bik.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="meta\bmp_konami.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\bnk_sony.c"> <ClCompile Include="meta\bnk_sony.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>

45
src/meta/bmp_konami.c Normal file
View File

@ -0,0 +1,45 @@
#include "meta.h"
/* BMP - from Jubeat Clan (AC) */
VGMSTREAM * init_vgmstream_bmp_konami(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t start_offset;
int loop_flag, channel_count;
/* checks */
/* .bin: actual extension
* .lbin: for plugins */
if (!check_extensions(streamFile, "bin,lbin"))
goto fail;
if (read_32bitBE(0x00,streamFile) != 0x424D5000) /* "BMP\0" "*/
goto fail;
channel_count = read_8bit(0x10,streamFile); /* assumed */
if (channel_count != 2) goto fail;
loop_flag = 0;
start_offset = 0x20;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
vgmstream->meta_type = meta_BMP_KONAMI;
vgmstream->num_samples = read_32bitBE(0x04,streamFile);
vgmstream->sample_rate = read_32bitBE(0x14, streamFile);
vgmstream->coding_type = coding_OKI4S;
vgmstream->layout_type = layout_none;
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
goto fail;
return vgmstream;
fail:
close_vgmstream(vgmstream);
return NULL;
}

View File

@ -866,4 +866,6 @@ VGMSTREAM * init_vgmstream_xmv_valve(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ubi_hx(STREAMFILE * streamFile); VGMSTREAM * init_vgmstream_ubi_hx(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_bmp_konami(STREAMFILE * streamFile);
#endif /*_META_H*/ #endif /*_META_H*/

View File

@ -478,6 +478,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_nub_is14, init_vgmstream_nub_is14,
init_vgmstream_xmv_valve, init_vgmstream_xmv_valve,
init_vgmstream_ubi_hx, init_vgmstream_ubi_hx,
init_vgmstream_bmp_konami,
/* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */ /* lowest priority metas (should go after all metas, and TXTH should go before raw formats) */
init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */ init_vgmstream_txth, /* proper parsers should supersede TXTH, once added */
@ -1150,6 +1151,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_OTNS_IMA: case coding_OTNS_IMA:
case coding_UBI_IMA: case coding_UBI_IMA:
case coding_OKI16: case coding_OKI16:
case coding_OKI4S:
return 1; return 1;
case coding_PCM4: case coding_PCM4:
case coding_PCM4_U: case coding_PCM4_U:
@ -1348,6 +1350,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_BLITZ_IMA: case coding_BLITZ_IMA:
case coding_PCFX: case coding_PCFX:
case coding_OKI16: case coding_OKI16:
case coding_OKI4S:
return 0x01; return 0x01;
case coding_MS_IMA: case coding_MS_IMA:
case coding_RAD_IMA: case coding_RAD_IMA:
@ -2117,6 +2120,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
} }
break; break;
case coding_OKI4S:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_oki4s(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
vgmstream->channels,vgmstream->samples_into_block,samples_to_do, ch);
}
break;
case coding_UBI_ADPCM: case coding_UBI_ADPCM:
decode_ubi_adpcm(vgmstream, buffer+samples_written*vgmstream->channels, samples_to_do); decode_ubi_adpcm(vgmstream, buffer+samples_written*vgmstream->channels, samples_to_do);
break; break;

View File

@ -164,7 +164,8 @@ typedef enum {
coding_DSA, /* Ocean DSA 4-bit ADPCM */ coding_DSA, /* Ocean DSA 4-bit ADPCM */
coding_XMD, /* Konami XMD 4-bit ADPCM */ coding_XMD, /* Konami XMD 4-bit ADPCM */
coding_PCFX, /* PC-FX 4-bit ADPCM */ coding_PCFX, /* PC-FX 4-bit ADPCM */
coding_OKI16, /* OKI 4-bit ADPCM with 16-bit output */ coding_OKI16, /* OKI 4-bit ADPCM with 16-bit output and modified expand */
coding_OKI4S, /* OKI 4-bit ADPCM with 16-bit output and cuadruple step */
coding_PTADPCM, /* Platinum 4-bit ADPCM */ coding_PTADPCM, /* Platinum 4-bit ADPCM */
/* others */ /* others */
@ -712,6 +713,7 @@ typedef enum {
meta_IMA, meta_IMA,
meta_XMV_VALVE, meta_XMV_VALVE,
meta_UBI_HX, meta_UBI_HX,
meta_BMP_KONAMI,
} meta_t; } meta_t;