mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-29 19:37:30 +01:00
Add Konami BMP .bin (as .lbin) + decoder [Jubeat Clan (AC)]
This commit is contained in:
parent
677eeef2b9
commit
1bc7e0e410
@ -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 */
|
||||
|
@ -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;
|
||||
|
@ -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"},
|
||||
|
||||
};
|
||||
|
||||
|
@ -508,6 +508,10 @@
|
||||
RelativePath=".\meta\bik.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\bmp_konami.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\bnk_sony.c"
|
||||
>
|
||||
|
@ -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" />
|
||||
|
@ -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
45
src/meta/bmp_konami.c
Normal 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;
|
||||
}
|
@ -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*/
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user