mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 15:00:11 +01:00
Add Ocean .DSF, .208 and DSA decoder [Last Rites (PC)]
This commit is contained in:
parent
0dbe00d4b0
commit
4c038cb0ea
@ -161,6 +161,9 @@ void decode_fadpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacin
|
||||
/* asf_decoder */
|
||||
void decode_asf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
||||
/* dsa_decoder */
|
||||
void decode_dsa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||
|
||||
/* xmd_decoder */
|
||||
void decode_xmd(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, size_t frame_size);
|
||||
|
||||
|
52
src/coding/dsa_decoder.c
Normal file
52
src/coding/dsa_decoder.c
Normal file
@ -0,0 +1,52 @@
|
||||
#include "coding.h"
|
||||
|
||||
|
||||
static const int dsa_coefs[16] = {
|
||||
0x0, 0x1999, 0x3333, 0x4CCC,
|
||||
0x6666, 0x8000, 0x9999, 0xB333,
|
||||
0xCCCC, 0xE666, 0x10000, 0x11999,
|
||||
0x13333, 0x18000, 0x1CCCC, 0x21999
|
||||
};
|
||||
|
||||
/* Decodes Ocean DSA ADPCM codec from Last Rites (PC).
|
||||
* Reverse engineered from daemon1's reverse engineering. */
|
||||
void decode_dsa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
|
||||
off_t frame_offset;
|
||||
int i, frames_in, sample_count = 0;
|
||||
size_t bytes_per_frame, samples_per_frame;
|
||||
uint8_t header;
|
||||
int shift, filter;
|
||||
int32_t hist1 = stream->adpcm_history1_32;
|
||||
|
||||
/* external interleave (fixed size), mono */
|
||||
bytes_per_frame = 0x08;
|
||||
samples_per_frame = (bytes_per_frame - 0x01) * 2;
|
||||
frames_in = first_sample / samples_per_frame;
|
||||
first_sample = first_sample % samples_per_frame;
|
||||
|
||||
/* parse frame header */
|
||||
frame_offset = stream->offset + bytes_per_frame*frames_in;
|
||||
header = (uint8_t)read_8bit(frame_offset+0x00,stream->streamfile);
|
||||
shift = 0x0c - ((header >> 4) & 0xf);
|
||||
filter = dsa_coefs[header & 0xf];
|
||||
|
||||
/* decode nibbles */
|
||||
for (i = first_sample; i < first_sample + samples_to_do; i++) {
|
||||
int32_t new_sample;
|
||||
uint8_t nibbles = (uint8_t)read_8bit(frame_offset+0x01 + i/2,stream->streamfile);
|
||||
|
||||
new_sample = i&1 ? /* high nibble first */
|
||||
(nibbles >> 0) & 0xf :
|
||||
(nibbles >> 4) & 0xf;
|
||||
|
||||
new_sample = ((int16_t)(new_sample << 0xC) >> shift); /* 16b sign extend + scale */
|
||||
new_sample = new_sample + ((hist1 * filter) >> 0x10);
|
||||
|
||||
outbuf[sample_count] = (int16_t)(new_sample << 2);
|
||||
sample_count += channelspacing;
|
||||
|
||||
hist1 = new_sample;
|
||||
}
|
||||
|
||||
stream->adpcm_history1_32 = hist1;
|
||||
}
|
@ -14,6 +14,7 @@ static const char* extension_list[] = {
|
||||
//"", /* vgmstream can play extensionless files too, but plugins must accept them manually */
|
||||
|
||||
"04sw",
|
||||
"208",
|
||||
"2dx9",
|
||||
"2pfs",
|
||||
"800",
|
||||
@ -122,6 +123,7 @@ static const char* extension_list[] = {
|
||||
"de2",
|
||||
"dec",
|
||||
"dmsg",
|
||||
"dsf",
|
||||
"dsp",
|
||||
"dspw",
|
||||
"dtk",
|
||||
@ -639,6 +641,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_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 (16-bit output)"},
|
||||
@ -1164,6 +1167,8 @@ static const meta_info meta_info_list[] = {
|
||||
{meta_OGG_OPUS, "Ogg Opus header"},
|
||||
{meta_IMC, "iNiS .IMC header"},
|
||||
{meta_GIN, "Electronic Arts Gnsu header"},
|
||||
{meta_DSF, "Ocean DSF header"},
|
||||
{meta_208, "Ocean .208 header"},
|
||||
|
||||
};
|
||||
|
||||
|
@ -296,6 +296,10 @@
|
||||
<Filter
|
||||
Name="Source Files"
|
||||
>
|
||||
<File
|
||||
RelativePath=".\meta\208.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\2dx9.c"
|
||||
>
|
||||
@ -496,10 +500,14 @@
|
||||
RelativePath=".\meta\derf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\dmsg_segh.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\dmsg_segh.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\dsf.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\meta\dsp_adx.c"
|
||||
>
|
||||
@ -1774,6 +1782,10 @@
|
||||
RelativePath=".\coding\derf_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\dsa_decoder.c"
|
||||
>
|
||||
</File>
|
||||
<File
|
||||
RelativePath=".\coding\ea_mt_decoder.c"
|
||||
>
|
||||
|
@ -201,6 +201,7 @@
|
||||
<ClCompile Include="streamfile.c" />
|
||||
<ClCompile Include="util.c" />
|
||||
<ClCompile Include="vgmstream.c" />
|
||||
<ClCompile Include="meta\208.c" />
|
||||
<ClCompile Include="meta\2dx9.c" />
|
||||
<ClCompile Include="meta\a2m.c" />
|
||||
<ClCompile Include="meta\ahv.c" />
|
||||
@ -248,6 +249,7 @@
|
||||
<ClCompile Include="meta\dec.c" />
|
||||
<ClCompile Include="meta\derf.c" />
|
||||
<ClCompile Include="meta\dmsg_segh.c" />
|
||||
<ClCompile Include="meta\dsf.c" />
|
||||
<ClCompile Include="meta\dsp_adx.c" />
|
||||
<ClCompile Include="meta\dsp_bdsp.c" />
|
||||
<ClCompile Include="meta\ea_schl.c" />
|
||||
@ -504,6 +506,7 @@
|
||||
<ClCompile Include="coding\asf_decoder.c" />
|
||||
<ClCompile Include="coding\yamaha_decoder.c" />
|
||||
<ClCompile Include="coding\derf_decoder.c" />
|
||||
<ClCompile Include="coding\dsa_decoder.c" />
|
||||
<ClCompile Include="coding\ea_mt_decoder.c" />
|
||||
<ClCompile Include="coding\ea_xa_decoder.c" />
|
||||
<ClCompile Include="coding\ea_xas_decoder.c" />
|
||||
|
@ -184,6 +184,9 @@
|
||||
<ClCompile Include="vgmstream.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\208.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\2dx9.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -319,6 +322,9 @@
|
||||
<ClCompile Include="meta\dmsg_segh.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\dsf.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="meta\dsp_bdsp.c">
|
||||
<Filter>meta\Source Files</Filter>
|
||||
</ClCompile>
|
||||
@ -1054,6 +1060,9 @@
|
||||
<ClCompile Include="coding\derf_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\dsa_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\ea_mt_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
48
src/meta/208.c
Normal file
48
src/meta/208.c
Normal file
@ -0,0 +1,48 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .208 - from Ocean game(s?) [Last Rites (PC)] */
|
||||
VGMSTREAM * init_vgmstream_208(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count, sample_rate;
|
||||
size_t data_size;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "208"))
|
||||
goto fail;
|
||||
/* possible validation: (0x04 == 0 and 0xcc == 0x1F7D984D) or 0x04 == 0xf0 and 0xcc == 0) */
|
||||
if (!((read_32bitLE(0x04,streamFile) == 0x00 && read_32bitBE(0xcc,streamFile) == 0x1F7D984D) ||
|
||||
(read_32bitLE(0x04,streamFile) == 0xF0 && read_32bitBE(0xcc,streamFile) == 0x00000000)))
|
||||
goto fail;
|
||||
|
||||
start_offset = read_32bitLE(0x00,streamFile);
|
||||
data_size = read_32bitLE(0x0c,streamFile);
|
||||
sample_rate = read_32bitLE(0x34,streamFile);
|
||||
channel_count = read_32bitLE(0x3C,streamFile); /* assumed */
|
||||
loop_flag = 0;
|
||||
|
||||
if (start_offset + data_size != get_streamfile_size(streamFile))
|
||||
goto fail;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_208;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = pcm_bytes_to_samples(data_size, channel_count, 8);
|
||||
vgmstream->coding_type = coding_PCM8_U;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x1;
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
51
src/meta/dsf.c
Normal file
51
src/meta/dsf.c
Normal file
@ -0,0 +1,51 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
|
||||
/* .DSF - from Ocean game(s?) [Last Rites (PC)] */
|
||||
VGMSTREAM * init_vgmstream_dsf(STREAMFILE *streamFile) {
|
||||
VGMSTREAM * vgmstream = NULL;
|
||||
off_t start_offset;
|
||||
int loop_flag, channel_count, sample_rate;
|
||||
size_t data_size;
|
||||
|
||||
|
||||
/* checks */
|
||||
if (!check_extensions(streamFile, "dsf"))
|
||||
goto fail;
|
||||
|
||||
if (read_32bitBE(0x00,streamFile) != 0x4F434541 && /* "OCEA" */
|
||||
read_32bitBE(0x00,streamFile) != 0x4E204453 && /* "N DS" */
|
||||
read_32bitBE(0x00,streamFile) != 0x41000000) /* "A\0\0\0" */
|
||||
goto fail;
|
||||
|
||||
/* 0x10(2): always 1? */
|
||||
/* 0x12(4): total nibbles / 0x10? */
|
||||
/* 0x16(4): always 0? */
|
||||
start_offset = read_32bitLE(0x1a,streamFile);
|
||||
sample_rate = read_32bitLE(0x1e,streamFile);
|
||||
channel_count = read_32bitLE(0x22,streamFile) + 1;
|
||||
data_size = get_streamfile_size(streamFile) - start_offset;
|
||||
loop_flag = 0;
|
||||
|
||||
|
||||
/* build the VGMSTREAM */
|
||||
vgmstream = allocate_vgmstream(channel_count, loop_flag);
|
||||
if (!vgmstream) goto fail;
|
||||
|
||||
vgmstream->meta_type = meta_DSF;
|
||||
vgmstream->sample_rate = sample_rate;
|
||||
vgmstream->num_samples = ((data_size / 0x08 / channel_count) * 14); /* bytes-to-samples */
|
||||
vgmstream->coding_type = coding_DSA;
|
||||
vgmstream->layout_type = layout_interleave;
|
||||
vgmstream->interleave_block_size = 0x08;
|
||||
|
||||
read_string(vgmstream->stream_name,0x20+1, 0x26,streamFile);
|
||||
|
||||
if (!vgmstream_open_stream(vgmstream,streamFile,start_offset))
|
||||
goto fail;
|
||||
return vgmstream;
|
||||
|
||||
fail:
|
||||
close_vgmstream(vgmstream);
|
||||
return NULL;
|
||||
}
|
@ -826,4 +826,8 @@ VGMSTREAM * init_vgmstream_smp(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_gin(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_dsf(STREAMFILE * streamFile);
|
||||
|
||||
VGMSTREAM * init_vgmstream_208(STREAMFILE * streamFile);
|
||||
|
||||
#endif /*_META_H*/
|
||||
|
@ -463,6 +463,8 @@ VGMSTREAM * (*init_vgmstream_functions[])(STREAMFILE *streamFile) = {
|
||||
init_vgmstream_imc_container,
|
||||
init_vgmstream_smp,
|
||||
init_vgmstream_gin,
|
||||
init_vgmstream_dsf,
|
||||
init_vgmstream_208,
|
||||
|
||||
/* 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 */
|
||||
@ -1248,6 +1250,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
||||
return 256; /* (0x8c - 0xc) * 2 */
|
||||
case coding_ASF:
|
||||
return 32; /* (0x11 - 0x1) * 2 */
|
||||
case coding_DSA:
|
||||
return 14; /* (0x08 - 0x1) * 2 */
|
||||
case coding_XMD:
|
||||
return (vgmstream->interleave_block_size - 0x06)*2 + 2;
|
||||
case coding_EA_MT:
|
||||
@ -1424,6 +1428,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
||||
return 0x8c;
|
||||
case coding_ASF:
|
||||
return 0x11;
|
||||
case coding_DSA:
|
||||
return 0x08;
|
||||
case coding_XMD:
|
||||
return vgmstream->interleave_block_size;
|
||||
case coding_EA_MT:
|
||||
@ -2047,6 +2053,12 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
||||
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+samples_written*vgmstream->channels+ch,
|
||||
vgmstream->channels,vgmstream->samples_into_block,samples_to_do);
|
||||
}
|
||||
break;
|
||||
case coding_XMD:
|
||||
for (ch = 0; ch < vgmstream->channels; ch++) {
|
||||
decode_xmd(&vgmstream->ch[ch],buffer+samples_written*vgmstream->channels+ch,
|
||||
|
@ -152,6 +152,7 @@ typedef enum {
|
||||
coding_MC3, /* Paradigm MC3 3-bit ADPCM */
|
||||
coding_FADPCM, /* FMOD FADPCM 4-bit ADPCM */
|
||||
coding_ASF, /* Argonaut ASF 4-bit ADPCM */
|
||||
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 */
|
||||
@ -714,6 +715,8 @@ typedef enum {
|
||||
meta_OGG_OPUS,
|
||||
meta_IMC,
|
||||
meta_GIN,
|
||||
meta_DSF,
|
||||
meta_208,
|
||||
|
||||
} meta_t;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user