.scd (FFXIII and FFXIV, MPEG, MS ADPCM, and PCM)

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@834 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2010-09-10 23:56:39 +00:00
parent 83f3ad9604
commit e98bb44bb5
14 changed files with 171 additions and 1 deletions

View File

@ -408,6 +408,7 @@ bool input_vgmstream::g_is_our_path(const char * p_path,const char * p_extension
if(!stricmp_utf8(p_extension,"sad")) return 1; if(!stricmp_utf8(p_extension,"sad")) return 1;
if(!stricmp_utf8(p_extension,"sap")) return 1; if(!stricmp_utf8(p_extension,"sap")) return 1;
if(!stricmp_utf8(p_extension,"sc")) return 1; if(!stricmp_utf8(p_extension,"sc")) return 1;
if(!stricmp_utf8(p_extension,"scd")) return 1;
if(!stricmp_utf8(p_extension,"sck")) return 1; if(!stricmp_utf8(p_extension,"sck")) return 1;
if(!stricmp_utf8(p_extension,"sd9")) return 1; if(!stricmp_utf8(p_extension,"sd9")) return 1;
if(!stricmp_utf8(p_extension,"sdt")) return 1; if(!stricmp_utf8(p_extension,"sdt")) return 1;
@ -689,6 +690,7 @@ DECLARE_MULTIPLE_FILE_TYPE("SAB Audio File (*.SAB)", sab);
DECLARE_MULTIPLE_FILE_TYPE("SAD Audio File (*.SAD)", sad); DECLARE_MULTIPLE_FILE_TYPE("SAD Audio File (*.SAD)", sad);
DECLARE_MULTIPLE_FILE_TYPE("SAP Audio File (*.SAP)", sap); DECLARE_MULTIPLE_FILE_TYPE("SAP Audio File (*.SAP)", sap);
DECLARE_MULTIPLE_FILE_TYPE("SC Audio File (*.SC)", sc); DECLARE_MULTIPLE_FILE_TYPE("SC Audio File (*.SC)", sc);
DECLARE_MULTIPLE_FILE_TYPE("SCD Audio File (*.SCD)", scd);
DECLARE_MULTIPLE_FILE_TYPE("SCK Audio File (*.SCK)", sck); DECLARE_MULTIPLE_FILE_TYPE("SCK Audio File (*.SCK)", sck);
DECLARE_MULTIPLE_FILE_TYPE("SD9 Audio File (*.SD9)", sd9); DECLARE_MULTIPLE_FILE_TYPE("SD9 Audio File (*.SD9)", sd9);
DECLARE_MULTIPLE_FILE_TYPE("SDT Audio File (*.SDT)", sdt); DECLARE_MULTIPLE_FILE_TYPE("SDT Audio File (*.SDT)", sdt);

View File

@ -251,6 +251,7 @@ etc:
- .sab (Worms 4 soundpacks) - .sab (Worms 4 soundpacks)
- .s14/.sss (G.722.1) - .s14/.sss (G.722.1)
- .sc (Activision EXAKT SASSC DPCM) - .sc (Activision EXAKT SASSC DPCM)
- .scd (MS ADPCM, MPEG Audio, 16 bit PCM)
- .sd9 (MS ADPCM) - .sd9 (MS ADPCM)
- .smp (MS ADPCM) - .smp (MS ADPCM)
- .spw (FFXI PS-like ADPCM) - .spw (FFXI PS-like ADPCM)

View File

@ -252,7 +252,8 @@ META_OBJS=meta/adx_header.o \
meta/ffw.o \ meta/ffw.o \
meta/ps2_jstm.o \ meta/ps2_jstm.o \
meta/ps3_xvag.o \ meta/ps3_xvag.o \
meta/ps3_cps.o meta/ps3_cps.o \
meta/se_scd.o
OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS) OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS)

View File

@ -79,6 +79,7 @@ void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream,
mpeg_codec_data * data, mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do); sample * outbuf, int32_t samples_to_do);
mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type); mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type);
long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi);
void decode_mpeg(VGMSTREAMCHANNEL * stream, void decode_mpeg(VGMSTREAMCHANNEL * stream,
mpeg_codec_data * data, mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do, int channels); sample * outbuf, int32_t samples_to_do, int channels);
@ -94,6 +95,7 @@ void decode_acm(ACMStream * acm, sample * outbuf,
void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do); void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do);
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do); void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do); void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);

View File

@ -214,4 +214,8 @@ void decode_mpeg(VGMSTREAMCHANNEL *stream,
} }
} }
long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi) {
return bytes * mi->rate * 8 / (mi->bitrate * 1000);
}
#endif #endif

View File

@ -21,6 +21,10 @@ static const int ADPCMCoeffs[7][2] =
{ 392, -232 } { 392, -232 }
}; };
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) {
return bytes/block_size*((block_size-(7-1)*channels)*2/channels);
}
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) { void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) {
VGMSTREAMCHANNEL *ch1,*ch2; VGMSTREAMCHANNEL *ch1,*ch2;
int i; int i;

View File

@ -890,6 +890,10 @@
RelativePath=".\meta\sdt.c" RelativePath=".\meta\sdt.c"
> >
</File> </File>
<File
RelativePath=".\meta\se_scd.c"
>
</File>
<File <File
RelativePath=".\meta\sfl.c" RelativePath=".\meta\sfl.c"
> >

View File

@ -205,5 +205,6 @@ libmeta_la_SOURCES += ffw.c
libmeta_la_SOURCES += ps2_jstm.c libmeta_la_SOURCES += ps2_jstm.c
libmeta_la_SOURCES += ps3_xvag.c libmeta_la_SOURCES += ps3_xvag.c
libmeta_la_SOURCES += ps3_cps.c libmeta_la_SOURCES += ps3_cps.c
libmeta_la_SOURCES += se_scd.c
EXTRA_DIST = meta.h EXTRA_DIST = meta.h

View File

@ -521,5 +521,6 @@ VGMSTREAM * init_vgmstream_ps3_xvag(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE* streamFile); VGMSTREAM * init_vgmstream_ps3_cps(STREAMFILE* streamFile);
VGMSTREAM * init_vgmstream_se_scd(STREAMFILE* streamFile);
#endif #endif

143
src/meta/se_scd.c Normal file
View File

@ -0,0 +1,143 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
/* Square-Enix SCD (FF XIII, XIV) */
VGMSTREAM * init_vgmstream_se_scd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[260];
off_t start_offset, meta_offset_offset, meta_offset, size_offset;
int32_t loop_start, loop_end;
int loop_flag = 0;
int channel_count;
int codec_id;
int32_t (*read_32bit)(off_t,STREAMFILE*) = NULL;
int16_t (*read_16bit)(off_t,STREAMFILE*) = NULL;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("scd",filename_extension(filename))) goto fail;
/* SEDB */
if (read_32bitBE(0,streamFile) != 0x53454442) goto fail;
/* SSCF */
if (read_32bitBE(4,streamFile) != 0x53534346) goto fail;
if (read_32bitBE(8,streamFile) == 2) {
/* version 2 BE, as seen in FFXIII for PS3 */
read_32bit = read_32bitBE;
read_16bit = read_16bitBE;
size_offset = 0x14;
meta_offset_offset = 0x70;
} else if (read_32bitLE(8,streamFile) == 3 ||
read_32bitLE(8,streamFile) == 2) {
/* version 2/3 LE, as seen in FFXIV for ?? */
read_32bit = read_32bitLE;
read_16bit = read_16bitLE;
size_offset = 0x10;
meta_offset_offset = 0x70;
} else goto fail;
/* check file size with header value */
if (read_32bit(size_offset,streamFile) != get_streamfile_size(streamFile))
goto fail;
/* this is probably some kind of chunk offset (?) */
meta_offset = read_32bit(0x70,streamFile);
/* check that chunk size equals stream size (?) */
loop_start = read_32bit(meta_offset+0x10,streamFile);
loop_end = read_32bit(meta_offset+0x14,streamFile);
loop_flag = (loop_end > 0);
channel_count = read_32bit(meta_offset+4,streamFile);
codec_id = read_32bit(meta_offset+0xc,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bit(meta_offset+8,streamFile);
start_offset = meta_offset + 0x20 + read_32bit(meta_offset+0x18,streamFile);
switch (codec_id) {
case 0x1:
/* PCM */
vgmstream->coding_type = coding_PCM16LE_int;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = read_32bit(meta_offset+0,streamFile) / 2 / channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = loop_start / 2 / channel_count;
vgmstream->loop_end_sample = loop_end / 2 / channel_count;
}
break;
#ifdef VGM_USE_MPEG
case 0x7:
/* MPEG */
{
mpeg_codec_data *mpeg_data = NULL;
struct mpg123_frameinfo mi;
coding_t ct;
mpeg_data = init_mpeg_codec_data(streamFile, start_offset, vgmstream->sample_rate, vgmstream->channels, &ct);
if (!mpeg_data) goto fail;
vgmstream->codec_data = mpeg_data;
if (MPG123_OK != mpg123_info(mpeg_data->m, &mi)) goto fail;
vgmstream->coding_type = ct;
vgmstream->layout_type = layout_mpeg;
if (mi.vbr != MPG123_CBR) goto fail;
vgmstream->num_samples = mpeg_bytes_to_samples(read_32bit(meta_offset+0,streamFile), &mi);
if (loop_flag) {
vgmstream->loop_start_sample = mpeg_bytes_to_samples(loop_start, &mi);
vgmstream->loop_end_sample = mpeg_bytes_to_samples(loop_end, &mi);
}
vgmstream->interleave_block_size = 0;
}
break;
#endif
case 0xC:
/* MS ADPCM */
vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bit(meta_offset+0x2c,streamFile);
vgmstream->num_samples = msadpcm_bytes_to_samples(read_32bit(meta_offset+0,streamFile), vgmstream->interleave_block_size, vgmstream->channels);
if (loop_flag) {
vgmstream->loop_start_sample = msadpcm_bytes_to_samples(loop_start, vgmstream->interleave_block_size, vgmstream->channels);
vgmstream->loop_end_sample = msadpcm_bytes_to_samples(loop_end, vgmstream->interleave_block_size, vgmstream->channels);
}
break;
default:
goto fail;
}
vgmstream->meta_type = meta_SE_SCD;
/* open the file for reading */
{
int i;
STREAMFILE * file;
file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -283,6 +283,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_ps2_jstm, init_vgmstream_ps2_jstm,
init_vgmstream_ps3_xvag, init_vgmstream_ps3_xvag,
init_vgmstream_ps3_cps, init_vgmstream_ps3_cps,
init_vgmstream_se_scd,
}; };
#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0])) #define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]))
@ -2664,6 +2665,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
break; break;
case meta_PS3_CPS: case meta_PS3_CPS:
snprintf(temp,TEMPSIZE,"CPS Header"); snprintf(temp,TEMPSIZE,"CPS Header");
break;
case meta_SE_SCD:
snprintf(temp,TEMPSIZE,"Square-Enix SCD");
break; break;
default: default:
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET"); snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");

View File

@ -484,6 +484,7 @@ typedef enum {
meta_PS2_JSTM, /* Tantei Jinguji Saburo - Kind of Blue (PS2) */ meta_PS2_JSTM, /* Tantei Jinguji Saburo - Kind of Blue (PS2) */
meta_PS3_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */ meta_PS3_XVAG, /* Ratchet & Clank Future: Quest for Booty (PS3) */
meta_PS3_CPS, /* Eternal Sonata (PS3) */ meta_PS3_CPS, /* Eternal Sonata (PS3) */
meta_SE_SCD, /* Square-Enix SCD */
} meta_t; } meta_t;
typedef struct { typedef struct {

View File

@ -169,6 +169,7 @@ gchar *vgmstream_exts [] = {
"sad", "sad",
"sap", "sap",
"sc", "sc",
"scd",
"sck", "sck",
"sd9", "sd9",
"sdt", "sdt",

View File

@ -235,6 +235,7 @@ char * extension_list[] = {
"sad\0SAD Audio File (*.SAD)\0", "sad\0SAD Audio File (*.SAD)\0",
"sap\0SAP Audio File (*.SAP)\0", "sap\0SAP Audio File (*.SAP)\0",
"sc\0SC Audio File (*.SC)\0", "sc\0SC Audio File (*.SC)\0",
"scd\0SCD Audio File (*.SCD)\0",
"sck\0SCK Audio File (*.SCK)\0", "sck\0SCK Audio File (*.SCK)\0",
"sd9\0SD9 Audio File (*.SD9)\0", "sd9\0SD9 Audio File (*.SD9)\0",
"sdt\0SDT Audio File (*.SDT)\0", "sdt\0SDT Audio File (*.SDT)\0",