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
|
||||
- Platinum 4-bit ADPCM
|
||||
- Argonaut ASF 4-bit ADPCM
|
||||
- Tantalus 4-bit ADPCM
|
||||
- Ocean DSA 4-bit ADPCM
|
||||
- Circus XPCM ADPCM
|
||||
- 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);
|
||||
|
||||
|
||||
/* 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 */
|
||||
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 */
|
||||
case coding_ASF:
|
||||
return 32; /* (0x11 - 0x1) * 2 */
|
||||
case coding_TANTALUS:
|
||||
return 30; /* (0x10 - 0x01) * 2 */
|
||||
case coding_DSA:
|
||||
return 14; /* (0x08 - 0x1) * 2 */
|
||||
case coding_XMD:
|
||||
@ -716,6 +718,8 @@ int get_vgmstream_frame_size(VGMSTREAM* vgmstream) {
|
||||
return 0x8c;
|
||||
case coding_ASF:
|
||||
return 0x11;
|
||||
case coding_TANTALUS:
|
||||
return 0x10;
|
||||
case coding_DSA:
|
||||
return 0x08;
|
||||
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);
|
||||
}
|
||||
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:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
decode_dsa(&vgmstream->ch[ch], buffer+ch,
|
||||
|
@ -515,6 +515,7 @@ static const char* extension_list[] = {
|
||||
"sxd2",
|
||||
"sxd3",
|
||||
|
||||
"tad",
|
||||
"tec",
|
||||
"tgq",
|
||||
"thp",
|
||||
@ -787,6 +788,7 @@ static const coding_info coding_info_list[] = {
|
||||
{coding_MC3, "Paradigm MC3 3-bit ADPCM"},
|
||||
{coding_FADPCM, "FMOD FADPCM 4-bit ADPCM"},
|
||||
{coding_ASF, "Argonaut ASF 4-bit ADPCM"},
|
||||
{coding_TANTALUS, "Tantalus 4-bit ADPCM"},
|
||||
{coding_DSA, "Ocean DSA 4-bit ADPCM"},
|
||||
{coding_XMD, "Konami XMD 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_DSP_KWA, "Kuju London .KWA 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) {
|
||||
|
@ -1201,6 +1201,10 @@
|
||||
<File
|
||||
RelativePath=".\meta\pcm_success.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\piff_tpcm.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\scd_pcm.c"
|
||||
@ -2354,6 +2358,10 @@
|
||||
RelativePath=".\coding\tac_decoder_lib.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\tantalus_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\ubi_adpcm_decoder.c"
|
||||
>
|
||||
|
@ -430,6 +430,7 @@
|
||||
<ClCompile Include="meta\xa_xa30.c" />
|
||||
<ClCompile Include="meta\pcm_sre.c" />
|
||||
<ClCompile Include="meta\pcm_success.c" />
|
||||
<ClCompile Include="meta\piff_tpcm.c" />
|
||||
<ClCompile Include="meta\scd_pcm.c" />
|
||||
<ClCompile Include="meta\pona.c" />
|
||||
<ClCompile Include="meta\pos.c" />
|
||||
@ -646,6 +647,7 @@
|
||||
<ClCompile Include="coding\speex_decoder.c" />
|
||||
<ClCompile Include="coding\tac_decoder.c" />
|
||||
<ClCompile Include="coding\tac_decoder_lib.c" />
|
||||
<ClCompile Include="coding\tantalus_decoder.c" />
|
||||
<ClCompile Include="coding\ubi_adpcm_decoder.c" />
|
||||
<ClCompile Include="coding\vadpcm_decoder.c" />
|
||||
<ClCompile Include="coding\vorbis_custom_decoder.c" />
|
||||
|
@ -787,6 +787,9 @@
|
||||
<ClCompile Include="meta\pcm_success.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\piff_tpcm.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\scd_pcm.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1408,6 +1411,9 @@
|
||||
<ClCompile Include="coding\tac_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\tantalus_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\tac_decoder_lib.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
@ -951,4 +951,6 @@ VGMSTREAM* init_vgmstream_ogv_3rdeye(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_sspr(STREAMFILE* sf);
|
||||
|
||||
VGMSTREAM* init_vgmstream_piff_tpcm(STREAMFILE* sf);
|
||||
|
||||
#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_ogv_3rdeye,
|
||||
init_vgmstream_sspr,
|
||||
init_vgmstream_piff_tpcm,
|
||||
|
||||
/* 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 */
|
||||
|
@ -164,6 +164,7 @@ typedef enum {
|
||||
coding_ASF, /* Argonaut ASF 4-bit ADPCM */
|
||||
coding_DSA, /* Ocean DSA 4-bit ADPCM */
|
||||
coding_XMD, /* Konami XMD 4-bit ADPCM */
|
||||
coding_TANTALUS, /* Tantalus 4-bit ADPCM */
|
||||
coding_PCFX, /* PC-FX 4-bit ADPCM */
|
||||
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 */
|
||||
@ -752,6 +753,7 @@ typedef enum {
|
||||
meta_IDSP_TOSE,
|
||||
meta_DSP_KWA,
|
||||
meta_OGV_3RDEYE,
|
||||
meta_PIFF_TPCM,
|
||||
} meta_t;
|
||||
|
||||
/* standard WAVEFORMATEXTENSIBLE speaker positions */
|
||||
|
Loading…
Reference in New Issue
Block a user