mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
adding xbox decoder + WAVM support
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@194 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
parent
eac7190023
commit
f7de62c8c9
@ -9,6 +9,7 @@ void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
|||||||
void g72x_init_state(struct g72x_state *state_ptr);
|
void g72x_init_state(struct g72x_state *state_ptr);
|
||||||
|
|
||||||
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||||
|
|
||||||
void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
|
||||||
|
@ -63,3 +63,54 @@ void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
|
|||||||
stream->adpcm_history1_16 = hist1;
|
stream->adpcm_history1_16 = hist1;
|
||||||
stream->adpcm_step_index = step_index;
|
stream->adpcm_step_index = step_index;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void decode_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
|
||||||
|
int i=first_sample;
|
||||||
|
int sample_nibble;
|
||||||
|
int sample_decoded;
|
||||||
|
int delta;
|
||||||
|
|
||||||
|
int32_t sample_count=0;
|
||||||
|
int32_t hist1=stream->adpcm_history1_32;
|
||||||
|
int step_index = stream->adpcm_step_index;
|
||||||
|
off_t offset=stream->offset;
|
||||||
|
|
||||||
|
first_sample = first_sample % 64;
|
||||||
|
|
||||||
|
hist1 = read_16bitLE(offset,stream->streamfile);
|
||||||
|
step_index = read_16bitLE(offset+2,stream->streamfile);
|
||||||
|
|
||||||
|
/* Skip sample predictors */
|
||||||
|
offset+=(4*channelspacing)-5;
|
||||||
|
|
||||||
|
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||||
|
int step = ADPCMTable[step_index];
|
||||||
|
|
||||||
|
offset += (i%2?0:1);
|
||||||
|
if(!(i%8) && channelspacing>1) offset+=4;
|
||||||
|
|
||||||
|
sample_nibble = (read_8bit(offset,stream->streamfile) >> (i&1?4:0))&0xf;
|
||||||
|
|
||||||
|
sample_decoded=hist1;
|
||||||
|
|
||||||
|
delta = step >> 3;
|
||||||
|
if (sample_nibble & 1) delta += step >> 2;
|
||||||
|
if (sample_nibble & 2) delta += step >> 1;
|
||||||
|
if (sample_nibble & 4) delta += step;
|
||||||
|
if (sample_nibble & 8)
|
||||||
|
sample_decoded -= delta;
|
||||||
|
else
|
||||||
|
sample_decoded += delta;
|
||||||
|
|
||||||
|
hist1=clamp16(sample_decoded);
|
||||||
|
|
||||||
|
step_index += IMA_IndexTable[sample_nibble];
|
||||||
|
if (step_index < 0) step_index=0;
|
||||||
|
if (step_index > 88) step_index=88;
|
||||||
|
|
||||||
|
outbuf[sample_count]=(short)(hist1);
|
||||||
|
}
|
||||||
|
|
||||||
|
stream->adpcm_history1_32=hist1;
|
||||||
|
stream->adpcm_step_index=step_index;
|
||||||
|
}
|
||||||
|
@ -51,6 +51,9 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||||||
case layout_xa_blocked:
|
case layout_xa_blocked:
|
||||||
xa_block_update(vgmstream->next_block_offset,vgmstream);
|
xa_block_update(vgmstream->next_block_offset,vgmstream);
|
||||||
break;
|
break;
|
||||||
|
case layout_xbox_blocked:
|
||||||
|
xbox_block_update(vgmstream->next_block_offset,vgmstream);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -12,6 +12,8 @@ void halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
|
|||||||
|
|
||||||
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||||
|
|
||||||
|
void xbox_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||||
|
|
||||||
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||||
|
|
||||||
void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||||
|
15
src/layout/xbox_blocked.c
Normal file
15
src/layout/xbox_blocked.c
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
#include "layout.h"
|
||||||
|
#include "../vgmstream.h"
|
||||||
|
|
||||||
|
/* set up for the block at the given offset */
|
||||||
|
void xbox_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||||
|
int i;
|
||||||
|
vgmstream->current_block_offset = block_offset;
|
||||||
|
vgmstream->current_block_size = 36*vgmstream->channels;
|
||||||
|
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size;
|
||||||
|
|
||||||
|
for (i=0;i<vgmstream->channels;i++) {
|
||||||
|
vgmstream->ch[i].offset = vgmstream->current_block_offset +
|
||||||
|
4*i;
|
||||||
|
}
|
||||||
|
}
|
@ -314,6 +314,10 @@
|
|||||||
RelativePath=".\meta\rwsd.c"
|
RelativePath=".\meta\rwsd.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\xbox_wavm.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
<Filter
|
<Filter
|
||||||
@ -410,6 +414,10 @@
|
|||||||
RelativePath=".\layout\xa_blocked.c"
|
RelativePath=".\layout\xa_blocked.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\layout\xbox_blocked.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Filter>
|
</Filter>
|
||||||
</Files>
|
</Files>
|
||||||
|
@ -67,4 +67,6 @@ VGMSTREAM * init_vgmstream_ps2_ild(STREAMFILE *streamFile);
|
|||||||
|
|
||||||
VGMSTREAM * init_vgmstream_ps2_pnb(STREAMFILE *streamFile);
|
VGMSTREAM * init_vgmstream_ps2_pnb(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
67
src/meta/xbox_wavm.c
Normal file
67
src/meta/xbox_wavm.c
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
/* WAVM
|
||||||
|
|
||||||
|
WAVM is an headerless format which can be found on XBOX
|
||||||
|
known extensions : WAVM
|
||||||
|
|
||||||
|
2008-05-23 - Fastelbja : First version ...
|
||||||
|
*/
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_xbox_wavm(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
char filename[260];
|
||||||
|
|
||||||
|
int loop_flag=0;
|
||||||
|
int channel_count;
|
||||||
|
off_t start_offset;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||||
|
if (strcasecmp("wavm",filename_extension(filename))) goto fail;
|
||||||
|
|
||||||
|
/* No loop on wavm */
|
||||||
|
loop_flag = 0;
|
||||||
|
|
||||||
|
/* Always stereo files */
|
||||||
|
channel_count=2;
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
/* fill in the vital statistics */
|
||||||
|
/* allways 2 channels @ 44100 Hz */
|
||||||
|
vgmstream->channels = 2;
|
||||||
|
vgmstream->sample_rate = 44100;
|
||||||
|
|
||||||
|
vgmstream->coding_type = coding_XBOX;
|
||||||
|
vgmstream->num_samples = get_streamfile_size(streamFile) / 36 * 64 / vgmstream->channels;
|
||||||
|
vgmstream->layout_type = layout_xbox_blocked;
|
||||||
|
vgmstream->current_block_size=36*vgmstream->channels;
|
||||||
|
vgmstream->current_block_offset=0;
|
||||||
|
|
||||||
|
xbox_block_update(0,vgmstream);
|
||||||
|
|
||||||
|
vgmstream->meta_type = meta_XBOX_WAVM;
|
||||||
|
|
||||||
|
start_offset = 0;
|
||||||
|
|
||||||
|
/* open the file for reading by each channel */
|
||||||
|
{
|
||||||
|
for (i=0;i<channel_count;i++) {
|
||||||
|
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,36);
|
||||||
|
|
||||||
|
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
/* clean up anything we may have opened */
|
||||||
|
fail:
|
||||||
|
if (vgmstream) close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -15,7 +15,7 @@
|
|||||||
* List of functions that will recognize files. These should correspond pretty
|
* List of functions that will recognize files. These should correspond pretty
|
||||||
* directly to the metadata types
|
* directly to the metadata types
|
||||||
*/
|
*/
|
||||||
#define INIT_VGMSTREAM_FCNS 32
|
#define INIT_VGMSTREAM_FCNS 33
|
||||||
VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(STREAMFILE *streamFile) = {
|
VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(STREAMFILE *streamFile) = {
|
||||||
init_vgmstream_adx, /* 0 */
|
init_vgmstream_adx, /* 0 */
|
||||||
init_vgmstream_brstm, /* 1 */
|
init_vgmstream_brstm, /* 1 */
|
||||||
@ -48,7 +48,8 @@ VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(STREAMFILE *streamFile)
|
|||||||
init_vgmstream_psx_gms, /* 28 */
|
init_vgmstream_psx_gms, /* 28 */
|
||||||
init_vgmstream_ps2_str, /* 29 */
|
init_vgmstream_ps2_str, /* 29 */
|
||||||
init_vgmstream_ps2_ild, /* 30 */
|
init_vgmstream_ps2_ild, /* 30 */
|
||||||
init_vgmstream_ps2_pnb /* 31 */
|
init_vgmstream_ps2_pnb, /* 31 */
|
||||||
|
init_vgmstream_xbox_wavm /* 32 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* internal version with all parameters */
|
/* internal version with all parameters */
|
||||||
@ -223,6 +224,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
|||||||
case layout_ast_blocked:
|
case layout_ast_blocked:
|
||||||
case layout_halpst_blocked:
|
case layout_halpst_blocked:
|
||||||
case layout_xa_blocked:
|
case layout_xa_blocked:
|
||||||
|
case layout_xbox_blocked:
|
||||||
render_vgmstream_blocked(buffer,sample_count,vgmstream);
|
render_vgmstream_blocked(buffer,sample_count,vgmstream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -249,6 +251,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
|||||||
case coding_PSX:
|
case coding_PSX:
|
||||||
case coding_XA:
|
case coding_XA:
|
||||||
return 28;
|
return 28;
|
||||||
|
case coding_XBOX:
|
||||||
|
return 64;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -286,6 +290,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
|||||||
return 16;
|
return 16;
|
||||||
case coding_XA:
|
case coding_XA:
|
||||||
return 14*vgmstream->channels;
|
return 14*vgmstream->channels;
|
||||||
|
case coding_XBOX:
|
||||||
|
return 64+(4*vgmstream->channels);
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -346,6 +352,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
|||||||
vgmstream->channels,vgmstream->samples_into_block,
|
vgmstream->channels,vgmstream->samples_into_block,
|
||||||
samples_to_do);
|
samples_to_do);
|
||||||
}
|
}
|
||||||
|
break;
|
||||||
|
case coding_XBOX:
|
||||||
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
|
decode_xbox_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||||
|
vgmstream->channels,vgmstream->samples_into_block,
|
||||||
|
samples_to_do,chan);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case coding_NGC_DTK:
|
case coding_NGC_DTK:
|
||||||
for (chan=0;chan<vgmstream->channels;chan++) {
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
@ -542,6 +555,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
break;
|
break;
|
||||||
case coding_XA:
|
case coding_XA:
|
||||||
snprintf(temp,TEMPSIZE,"CD-ROM XA 4-bit ADPCM");
|
snprintf(temp,TEMPSIZE,"CD-ROM XA 4-bit ADPCM");
|
||||||
|
break;
|
||||||
|
case coding_XBOX:
|
||||||
|
snprintf(temp,TEMPSIZE,"XBOX 4-bit IMA ADPCM");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
|
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
|
||||||
@ -572,6 +588,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
break;
|
break;
|
||||||
case layout_xa_blocked:
|
case layout_xa_blocked:
|
||||||
snprintf(temp,TEMPSIZE,"CD-ROM XA");
|
snprintf(temp,TEMPSIZE,"CD-ROM XA");
|
||||||
|
break;
|
||||||
|
case layout_xbox_blocked:
|
||||||
|
snprintf(temp,TEMPSIZE,"XBOX blocked");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
|
snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
|
||||||
@ -718,7 +737,10 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
snprintf(temp,TEMPSIZE,"ILD header");
|
snprintf(temp,TEMPSIZE,"ILD header");
|
||||||
break;
|
break;
|
||||||
case meta_PS2_PNB:
|
case meta_PS2_PNB:
|
||||||
snprintf(temp,TEMPSIZE,"assumed PNB (PsychoNauts Bgm File) by .pnb header");
|
snprintf(temp,TEMPSIZE,"assumed PNB (PsychoNauts Bgm File) by .pnb extension");
|
||||||
|
break;
|
||||||
|
case meta_XBOX_WAVM:
|
||||||
|
snprintf(temp,TEMPSIZE,"assumed Xbox WAVM file by .wavm extension");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
||||||
|
@ -24,6 +24,7 @@ typedef enum {
|
|||||||
coding_NGC_AFC, /* NGC ADPCM, called AFC */
|
coding_NGC_AFC, /* NGC ADPCM, called AFC */
|
||||||
coding_PSX, /* PSX & PS2 ADPCM */
|
coding_PSX, /* PSX & PS2 ADPCM */
|
||||||
coding_XA, /* PSX CD-XA */
|
coding_XA, /* PSX CD-XA */
|
||||||
|
coding_XBOX, /* XBOX IMA */
|
||||||
} coding_t;
|
} coding_t;
|
||||||
|
|
||||||
/* The layout type specifies how the sound data is laid out in the file */
|
/* The layout type specifies how the sound data is laid out in the file */
|
||||||
@ -40,6 +41,7 @@ typedef enum {
|
|||||||
layout_ast_blocked, /* .ast STRM with BLCK blocks*/
|
layout_ast_blocked, /* .ast STRM with BLCK blocks*/
|
||||||
layout_halpst_blocked, /* blocks with HALPST-format header */
|
layout_halpst_blocked, /* blocks with HALPST-format header */
|
||||||
layout_xa_blocked,
|
layout_xa_blocked,
|
||||||
|
layout_xbox_blocked,
|
||||||
#if 0
|
#if 0
|
||||||
layout_strm_blocked, /* */
|
layout_strm_blocked, /* */
|
||||||
#endif
|
#endif
|
||||||
@ -98,6 +100,8 @@ typedef enum {
|
|||||||
meta_PS2_PNB, /* PsychoNauts Bgm File */
|
meta_PS2_PNB, /* PsychoNauts Bgm File */
|
||||||
meta_PSX_XA, /* CD-XA with RIFF header */
|
meta_PSX_XA, /* CD-XA with RIFF header */
|
||||||
|
|
||||||
|
meta_XBOX_WAVM, /* XBOX WAVM File */
|
||||||
|
|
||||||
meta_RAW, /* RAW PCM file */
|
meta_RAW, /* RAW PCM file */
|
||||||
|
|
||||||
} meta_t;
|
} meta_t;
|
||||||
|
@ -105,7 +105,8 @@ char * extension_list[] = {
|
|||||||
"gms\0GMS Audio File (*.GMS)\0",
|
"gms\0GMS Audio File (*.GMS)\0",
|
||||||
"str\0STR Audio File (*.STR)\0",
|
"str\0STR Audio File (*.STR)\0",
|
||||||
"ild\0ILD Audio File (*.ILD)\0",
|
"ild\0ILD Audio File (*.ILD)\0",
|
||||||
"pnb\0PNB Audio File (*.PNB)\0"
|
"pnb\0PNB Audio File (*.PNB)\0",
|
||||||
|
"wavm\0WAVM Audio File (*.WAVM)\0"
|
||||||
};
|
};
|
||||||
|
|
||||||
void about(HWND hwndParent) {
|
void about(HWND hwndParent) {
|
||||||
|
Loading…
Reference in New Issue
Block a user