mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
Add Tantalus .tad decoder [House of the Dead (SAT)]
This commit is contained in:
parent
2fcc3d69e4
commit
93339ba2bc
@ -751,6 +751,7 @@ are used in few games.
|
|||||||
- Konami XMD 4-bit ADPCM
|
- Konami XMD 4-bit ADPCM
|
||||||
- Platinum 4-bit ADPCM
|
- Platinum 4-bit ADPCM
|
||||||
- Argonaut ASF 4-bit ADPCM
|
- Argonaut ASF 4-bit ADPCM
|
||||||
|
- Tantalus 4-bit ADPCM
|
||||||
- Ocean DSA 4-bit ADPCM
|
- Ocean DSA 4-bit ADPCM
|
||||||
- Circus XPCM ADPCM
|
- Circus XPCM ADPCM
|
||||||
- Circus XPCM VQ
|
- Circus XPCM VQ
|
||||||
|
@ -224,6 +224,11 @@ void decode_dsa(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing,
|
|||||||
void decode_xmd(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
|
void decode_xmd(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
|
||||||
|
|
||||||
|
|
||||||
|
/* tantalus_decoder */
|
||||||
|
void decode_tantalus(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
int32_t tantalus_bytes_to_samples(size_t bytes, int channels);
|
||||||
|
|
||||||
|
|
||||||
/* derf_decoder */
|
/* derf_decoder */
|
||||||
void decode_derf(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_derf(VGMSTREAMCHANNEL* stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
|
||||||
|
63
src/coding/tantalus_decoder.c
Normal file
63
src/coding/tantalus_decoder.c
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
#include "coding.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* Decodes Tantalus TADC ADPCM codec, used in Saturn games.
|
||||||
|
* Guessed based on other XA-style codecs values. */
|
||||||
|
void decode_tantalus(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||||
|
uint8_t frame[0x10] = {0};
|
||||||
|
off_t frame_offset;
|
||||||
|
int i, frames_in, sample_count = 0;
|
||||||
|
size_t bytes_per_frame, samples_per_frame;
|
||||||
|
int shift, filter, coef1, coef2;
|
||||||
|
int32_t hist1 = stream->adpcm_history1_32;
|
||||||
|
int32_t hist2 = stream->adpcm_history2_32;
|
||||||
|
|
||||||
|
|
||||||
|
/* external interleave (fixed size), mono */
|
||||||
|
bytes_per_frame = 0x10;
|
||||||
|
samples_per_frame = (bytes_per_frame - 0x01) * 2;
|
||||||
|
frames_in = first_sample / samples_per_frame;
|
||||||
|
//first_sample = first_sample % samples_per_frame; /* for flat layout */
|
||||||
|
|
||||||
|
/* parse frame header */
|
||||||
|
frame_offset = stream->offset + bytes_per_frame*frames_in;
|
||||||
|
read_streamfile(frame, frame_offset, bytes_per_frame, stream->streamfile); /* ignore EOF errors */
|
||||||
|
filter = (frame[0x00] >> 4) & 0xf; /* 0 in tested files */
|
||||||
|
shift = (frame[0x00] >> 0) & 0xf;
|
||||||
|
if (filter != 0) {
|
||||||
|
VGM_LOG_ONCE("TANTALUS: unknown filter\n");
|
||||||
|
coef1 = 64;
|
||||||
|
coef2 = 64; /* will sound horrid and hopefully reported */
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
coef1 = 64;
|
||||||
|
coef2 = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* decode nibbles */
|
||||||
|
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||||
|
uint8_t nibbles = frame[0x01 + i/2];
|
||||||
|
int32_t sample;
|
||||||
|
|
||||||
|
sample = i&1 ? /* low nibble first */
|
||||||
|
get_high_nibble_signed(nibbles) :
|
||||||
|
get_low_nibble_signed(nibbles);
|
||||||
|
sample = sample << (shift + 6);
|
||||||
|
sample = (sample + (hist1 * coef1) + (hist2 * coef2)) >> 6;
|
||||||
|
|
||||||
|
outbuf[sample_count] = clamp16(sample);
|
||||||
|
sample_count += channelspacing;
|
||||||
|
|
||||||
|
hist2 = hist1;
|
||||||
|
hist1 = sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->adpcm_history1_32 = hist1;
|
||||||
|
stream->adpcm_history2_32 = hist2;
|
||||||
|
}
|
||||||
|
|
||||||
|
int32_t tantalus_bytes_to_samples(size_t bytes, int channels) {
|
||||||
|
if (channels <= 0) return 0;
|
||||||
|
return bytes / channels / 0x10 * 30;
|
||||||
|
}
|
10
src/decode.c
10
src/decode.c
@ -503,6 +503,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM* vgmstream) {
|
|||||||
return 256; /* (0x8c - 0xc) * 2 */
|
return 256; /* (0x8c - 0xc) * 2 */
|
||||||
case coding_ASF:
|
case coding_ASF:
|
||||||
return 32; /* (0x11 - 0x1) * 2 */
|
return 32; /* (0x11 - 0x1) * 2 */
|
||||||
|
case coding_TANTALUS:
|
||||||
|
return 30; /* (0x10 - 0x01) * 2 */
|
||||||
case coding_DSA:
|
case coding_DSA:
|
||||||
return 14; /* (0x08 - 0x1) * 2 */
|
return 14; /* (0x08 - 0x1) * 2 */
|
||||||
case coding_XMD:
|
case coding_XMD:
|
||||||
@ -716,6 +718,8 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
|
|||||||
return 0x8c;
|
return 0x8c;
|
||||||
case coding_ASF:
|
case coding_ASF:
|
||||||
return 0x11;
|
return 0x11;
|
||||||
|
case coding_TANTALUS:
|
||||||
|
return 0x10;
|
||||||
case coding_DSA:
|
case coding_DSA:
|
||||||
return 0x08;
|
return 0x08;
|
||||||
case coding_XMD:
|
case coding_XMD:
|
||||||
@ -1386,6 +1390,12 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
|
|||||||
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
|
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case coding_TANTALUS:
|
||||||
|
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||||
|
decode_tantalus(&vgmstream->ch[ch], buffer+ch,
|
||||||
|
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
|
||||||
|
}
|
||||||
|
break;
|
||||||
case coding_DSA:
|
case coding_DSA:
|
||||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||||
decode_dsa(&vgmstream->ch[ch], buffer+ch,
|
decode_dsa(&vgmstream->ch[ch], buffer+ch,
|
||||||
|
@ -515,6 +515,7 @@ static const char* extension_list[] = {
|
|||||||
"sxd2",
|
"sxd2",
|
||||||
"sxd3",
|
"sxd3",
|
||||||
|
|
||||||
|
"tad",
|
||||||
"tec",
|
"tec",
|
||||||
"tgq",
|
"tgq",
|
||||||
"thp",
|
"thp",
|
||||||
@ -787,6 +788,7 @@ static const coding_info coding_info_list[] = {
|
|||||||
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
|
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
|
||||||
{coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"},
|
{coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"},
|
||||||
{coding_ASF, "Argonaut ASF 4-bit ADPCM"},
|
{coding_ASF, "Argonaut ASF 4-bit ADPCM"},
|
||||||
|
{coding_TANTALUS, "Tantalus 4-bit ADPCM"},
|
||||||
{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"},
|
||||||
@ -1350,6 +1352,7 @@ static const meta_info meta_info_list[] = {
|
|||||||
{meta_IDSP_TOSE, "TOSE .IDSP header"},
|
{meta_IDSP_TOSE, "TOSE .IDSP header"},
|
||||||
{meta_DSP_KWA, "Kuju London .KWA header"},
|
{meta_DSP_KWA, "Kuju London .KWA header"},
|
||||||
{meta_OGV_3RDEYE, "3rdEye .OGV header"},
|
{meta_OGV_3RDEYE, "3rdEye .OGV header"},
|
||||||
|
{meta_PIFF_TPCM, "Tantalus PIFF TPCM header"},
|
||||||
};
|
};
|
||||||
|
|
||||||
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
|
void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
|
||||||
|
@ -1201,6 +1201,10 @@
|
|||||||
<File
|
<File
|
||||||
RelativePath=".\meta\pcm_success.c"
|
RelativePath=".\meta\pcm_success.c"
|
||||||
>
|
>
|
||||||
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\piff_tpcm.c"
|
||||||
|
>
|
||||||
</File>
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\scd_pcm.c"
|
RelativePath=".\meta\scd_pcm.c"
|
||||||
@ -2354,6 +2358,10 @@
|
|||||||
RelativePath=".\coding\tac_decoder_lib.c"
|
RelativePath=".\coding\tac_decoder_lib.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\coding\tantalus_decoder.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\coding\ubi_adpcm_decoder.c"
|
RelativePath=".\coding\ubi_adpcm_decoder.c"
|
||||||
>
|
>
|
||||||
|
@ -430,6 +430,7 @@
|
|||||||
<ClCompile Include="meta\xa_xa30.c" />
|
<ClCompile Include="meta\xa_xa30.c" />
|
||||||
<ClCompile Include="meta\pcm_sre.c" />
|
<ClCompile Include="meta\pcm_sre.c" />
|
||||||
<ClCompile Include="meta\pcm_success.c" />
|
<ClCompile Include="meta\pcm_success.c" />
|
||||||
|
<ClCompile Include="meta\piff_tpcm.c" />
|
||||||
<ClCompile Include="meta\scd_pcm.c" />
|
<ClCompile Include="meta\scd_pcm.c" />
|
||||||
<ClCompile Include="meta\pona.c" />
|
<ClCompile Include="meta\pona.c" />
|
||||||
<ClCompile Include="meta\pos.c" />
|
<ClCompile Include="meta\pos.c" />
|
||||||
@ -646,6 +647,7 @@
|
|||||||
<ClCompile Include="coding\speex_decoder.c" />
|
<ClCompile Include="coding\speex_decoder.c" />
|
||||||
<ClCompile Include="coding\tac_decoder.c" />
|
<ClCompile Include="coding\tac_decoder.c" />
|
||||||
<ClCompile Include="coding\tac_decoder_lib.c" />
|
<ClCompile Include="coding\tac_decoder_lib.c" />
|
||||||
|
<ClCompile Include="coding\tantalus_decoder.c" />
|
||||||
<ClCompile Include="coding\ubi_adpcm_decoder.c" />
|
<ClCompile Include="coding\ubi_adpcm_decoder.c" />
|
||||||
<ClCompile Include="coding\vadpcm_decoder.c" />
|
<ClCompile Include="coding\vadpcm_decoder.c" />
|
||||||
<ClCompile Include="coding\vorbis_custom_decoder.c" />
|
<ClCompile Include="coding\vorbis_custom_decoder.c" />
|
||||||
|
@ -787,6 +787,9 @@
|
|||||||
<ClCompile Include="meta\pcm_success.c">
|
<ClCompile Include="meta\pcm_success.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="meta\piff_tpcm.c">
|
||||||
|
<Filter>meta\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="meta\scd_pcm.c">
|
<ClCompile Include="meta\scd_pcm.c">
|
||||||
<Filter>meta\Source Files</Filter>
|
<Filter>meta\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
@ -1408,6 +1411,9 @@
|
|||||||
<ClCompile Include="coding\tac_decoder.c">
|
<ClCompile Include="coding\tac_decoder.c">
|
||||||
<Filter>coding\Source Files</Filter>
|
<Filter>coding\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
<ClCompile Include="coding\tantalus_decoder.c">
|
||||||
|
<Filter>coding\Source Files</Filter>
|
||||||
|
</ClCompile>
|
||||||
<ClCompile Include="coding\tac_decoder_lib.c">
|
<ClCompile Include="coding\tac_decoder_lib.c">
|
||||||
<Filter>coding\Source Files</Filter>
|
<Filter>coding\Source Files</Filter>
|
||||||
</ClCompile>
|
</ClCompile>
|
||||||
|
@ -951,4 +951,6 @@ VGMSTREAM* init_vgmstream_ogv_3rdeye(STREAMFILE* sf);
|
|||||||
|
|
||||||
VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf);
|
VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf);
|
||||||
|
|
||||||
|
VGMSTREAM* init_vgmstream_piff_tpcm(STREAMFILE* sf);
|
||||||
|
|
||||||
#endif /*_META_H*/
|
#endif /*_META_H*/
|
||||||
|
54
src/meta/piff_tpcm.c
Normal file
54
src/meta/piff_tpcm.c
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../coding/coding.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* PIFF TADH - from Tantalus games [House of the Dead (SAT)] */
|
||||||
|
VGMSTREAM* init_vgmstream_piff_tpcm(STREAMFILE* sf) {
|
||||||
|
VGMSTREAM* vgmstream = NULL;
|
||||||
|
off_t start_offset, header_offset, data_size;
|
||||||
|
int loop_flag, channels, sample_rate;
|
||||||
|
|
||||||
|
|
||||||
|
/* checks */
|
||||||
|
/* .tad: from internal filenames */
|
||||||
|
if (!check_extensions(sf, "tad"))
|
||||||
|
goto fail;
|
||||||
|
/* Tantalus also has PIFF without this */
|
||||||
|
if (!is_id32be(0x00,sf, "PIFF") || !is_id32be(0x08,sf, "TPCM") || !is_id32be(0x0c,sf, "TADH"))
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
header_offset = 0x14;
|
||||||
|
/* 0x00: 1? */
|
||||||
|
/* 0x01: 1? */
|
||||||
|
channels = read_u16le(header_offset + 0x02,sf);
|
||||||
|
sample_rate = read_s32le(header_offset + 0x04,sf);
|
||||||
|
/* 0x08+: ? (mostly fixed, maybe related to ADPCM?) */
|
||||||
|
loop_flag = 0;
|
||||||
|
|
||||||
|
if (!is_id32be(0x38,sf, "BODY"))
|
||||||
|
goto fail;
|
||||||
|
start_offset = 0x40;
|
||||||
|
data_size = read_u32le(0x3c,sf);
|
||||||
|
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channels, loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
vgmstream->meta_type = meta_PIFF_TPCM;
|
||||||
|
vgmstream->sample_rate = sample_rate;
|
||||||
|
|
||||||
|
vgmstream->coding_type = coding_TANTALUS;
|
||||||
|
vgmstream->layout_type = layout_interleave;
|
||||||
|
vgmstream->interleave_block_size = 0x10;
|
||||||
|
|
||||||
|
vgmstream->num_samples = tantalus_bytes_to_samples(data_size, channels);
|
||||||
|
|
||||||
|
if (!vgmstream_open_stream(vgmstream, sf, start_offset))
|
||||||
|
goto fail;
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
fail:
|
||||||
|
close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -525,6 +525,7 @@ VGMSTREAM* (*init_vgmstream_functions[])(STREAMFILE* sf) = {
|
|||||||
init_vgmstream_dsp_kwa,
|
init_vgmstream_dsp_kwa,
|
||||||
init_vgmstream_ogv_3rdeye,
|
init_vgmstream_ogv_3rdeye,
|
||||||
init_vgmstream_sspr,
|
init_vgmstream_sspr,
|
||||||
|
init_vgmstream_piff_tpcm,
|
||||||
|
|
||||||
/* 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 */
|
||||||
|
@ -164,6 +164,7 @@ typedef enum {
|
|||||||
coding_ASF, /* Argonaut ASF 4-bit ADPCM */
|
coding_ASF, /* Argonaut ASF 4-bit ADPCM */
|
||||||
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_TANTALUS, /* Tantalus 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 and modified expand */
|
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_OKI4S, /* OKI 4-bit ADPCM with 16-bit output and cuadruple step */
|
||||||
@ -752,6 +753,7 @@ typedef enum {
|
|||||||
meta_IDSP_TOSE,
|
meta_IDSP_TOSE,
|
||||||
meta_DSP_KWA,
|
meta_DSP_KWA,
|
||||||
meta_OGV_3RDEYE,
|
meta_OGV_3RDEYE,
|
||||||
|
meta_PIFF_TPCM,
|
||||||
} meta_t;
|
} meta_t;
|
||||||
|
|
||||||
/* standard WAVEFORMATEXTENSIBLE speaker positions */
|
/* standard WAVEFORMATEXTENSIBLE speaker positions */
|
||||||
|
Loading…
Reference in New Issue
Block a user