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 */
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_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);
/* ptadpcm_decoder */

View File

@ -2,10 +2,13 @@
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,
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
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
};
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;
step = step_sizes[*step_index];
/* IMA 'mul' style (standard OKI uses 'shift-add') */
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)
delta = -delta;
*hist1 += delta;
@ -75,6 +79,31 @@ static void oki16_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, in
*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.
* 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:
@ -138,6 +167,37 @@ void decode_oki16(VGMSTREAMCHANNEL * stream, sample_t * outbuf, int channelspaci
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) {
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
* 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. */
@ -93,6 +94,7 @@ static const char* extension_list[] = {
"bik",
"bika",
"bik2",
//"bin", //common
"bk2",
"bmdx",
"bms",
@ -237,6 +239,7 @@ static const char* extension_list[] = {
"laifc", //fake extension for .aifc
"lac3", //fake extension for .ac3, FFmpeg/not parsed
"lasf", //fake extension for .asf (various)
"lbin", //fake extension for .bin (various)
"leg",
"lflac", //fake extension for .flac, FFmpeg/not parsed
"lin",
@ -688,6 +691,7 @@ static const coding_info coding_info_list[] = {
{coding_XMD, "Konami XMD 4-bit ADPCM"},
{coding_PCFX, "PC-FX 4-bit ADPCM"},
{coding_OKI16, "OKI 4-bit ADPCM (16-bit output)"},
{coding_OKI4S, "OKI 4-bit ADPCM (4-shift)"},
{coding_PTADPCM, "Platinum 4-bit ADPCM"},
{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_XMV_VALVE, "Valve XMV header"},
{meta_UBI_HX, "Ubisoft HXx header"},
{meta_BMP_KONAMI, "Konami BMP header"},
};

View File

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

View File

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

View File

@ -1597,6 +1597,9 @@
<ClCompile Include="meta\bik.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\bmp_konami.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\bnk_sony.c">
<Filter>meta\Source Files</Filter>
</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_bmp_konami(STREAMFILE * streamFile);
#endif /*_META_H*/

View File

@ -478,6 +478,7 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
init_vgmstream_nub_is14,
init_vgmstream_xmv_valve,
init_vgmstream_ubi_hx,
init_vgmstream_bmp_konami,
/* 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 */
@ -1150,6 +1151,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_OTNS_IMA:
case coding_UBI_IMA:
case coding_OKI16:
case coding_OKI4S:
return 1;
case coding_PCM4:
case coding_PCM4_U:
@ -1348,6 +1350,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_BLITZ_IMA:
case coding_PCFX:
case coding_OKI16:
case coding_OKI4S:
return 0x01;
case coding_MS_IMA:
case coding_RAD_IMA:
@ -2117,6 +2120,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
}
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:
decode_ubi_adpcm(vgmstream, buffer+samples_written*vgmstream->channels, samples_to_do);
break;

View File

@ -164,7 +164,8 @@ typedef enum {
coding_DSA, /* Ocean DSA 4-bit ADPCM */
coding_XMD, /* Konami XMD 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 */
/* others */
@ -712,6 +713,7 @@ typedef enum {
meta_IMA,
meta_XMV_VALVE,
meta_UBI_HX,
meta_BMP_KONAMI,
} meta_t;