mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-12-01 01:27:20 +01:00
Electronic Arts EA/XA R1,R2,R3 & EA PSX support added
git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@203 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
parent
a25e86e359
commit
5de0c96986
@ -27,4 +27,6 @@ void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing,
|
|||||||
|
|
||||||
void decode_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
void decode_xa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
|
||||||
|
|
||||||
|
void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
68
src/coding/eaxa_decoder.c
Normal file
68
src/coding/eaxa_decoder.c
Normal file
@ -0,0 +1,68 @@
|
|||||||
|
#include "coding.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
long EA_XA_TABLE[28] = {0,0,240,0,460,-208,0x0188,-220,
|
||||||
|
0x0000,0x0000,0x00F0,0x0000,
|
||||||
|
0x01CC,0x0000,0x0188,0x0000,
|
||||||
|
0x0000,0x0000,0x0000,0x0000,
|
||||||
|
-208,-1,-220,-1,
|
||||||
|
0x0000,0x0000,0x0000,0x3F70};
|
||||||
|
|
||||||
|
static int samples;
|
||||||
|
|
||||||
|
void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
|
||||||
|
uint8_t frame_info;
|
||||||
|
int32_t sample_count;
|
||||||
|
long coef1,coef2;
|
||||||
|
int i,shift;
|
||||||
|
off_t channel_offset=stream->channel_start_offset;
|
||||||
|
|
||||||
|
first_sample = first_sample%28;
|
||||||
|
frame_info = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile);
|
||||||
|
|
||||||
|
if(frame_info==0xEE) {
|
||||||
|
|
||||||
|
channel_offset++;
|
||||||
|
stream->adpcm_history1_32 = read_16bitBE(stream->offset+channel_offset+(2*channel),stream->streamfile);
|
||||||
|
stream->adpcm_history2_32 = read_16bitBE(stream->offset+channel_offset+2+(2*channel),stream->streamfile);
|
||||||
|
|
||||||
|
channel_offset+=(2*channelspacing);
|
||||||
|
|
||||||
|
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||||
|
outbuf[sample_count]=read_16bitBE(stream->offset+channel_offset,stream->streamfile);
|
||||||
|
channel_offset+=2;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Only increment offset on complete frame
|
||||||
|
if(channel_offset-stream->channel_start_offset==(2*28)+5)
|
||||||
|
stream->channel_start_offset+=(2*28)+5;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
|
||||||
|
coef1 = EA_XA_TABLE[((frame_info >> 4) & 0x0F) << 1];
|
||||||
|
coef2 = EA_XA_TABLE[(((frame_info >> 4) & 0x0F) << 1) + 1];
|
||||||
|
shift = (frame_info & 0x0F) + 8;
|
||||||
|
|
||||||
|
channel_offset++;
|
||||||
|
|
||||||
|
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
|
||||||
|
uint8_t sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i/2,stream->streamfile);
|
||||||
|
int32_t sample = ((((i&1?
|
||||||
|
sample_byte & 0x0F:
|
||||||
|
sample_byte >> 4
|
||||||
|
) << 0x1C) >> shift) +
|
||||||
|
(coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32)) >> 8;
|
||||||
|
|
||||||
|
outbuf[sample_count] = clamp16(sample);
|
||||||
|
stream->adpcm_history2_32 = stream->adpcm_history1_32;
|
||||||
|
stream->adpcm_history1_32 = sample;
|
||||||
|
}
|
||||||
|
|
||||||
|
channel_offset+=i/2;
|
||||||
|
|
||||||
|
// Only increment offset on complete frame
|
||||||
|
if(channel_offset-stream->channel_start_offset==0x0F)
|
||||||
|
stream->channel_start_offset+=0x0F;
|
||||||
|
}
|
||||||
|
}
|
@ -1,3 +1,4 @@
|
|||||||
|
#include <math.h>
|
||||||
#include "coding.h"
|
#include "coding.h"
|
||||||
#include "../util.h"
|
#include "../util.h"
|
||||||
|
|
||||||
|
@ -54,6 +54,9 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
|
|||||||
case layout_xbox_blocked:
|
case layout_xbox_blocked:
|
||||||
xbox_block_update(vgmstream->next_block_offset,vgmstream);
|
xbox_block_update(vgmstream->next_block_offset,vgmstream);
|
||||||
break;
|
break;
|
||||||
|
case layout_ea_blocked:
|
||||||
|
ea_block_update(vgmstream->next_block_offset,vgmstream);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
60
src/layout/ea_block.c
Normal file
60
src/layout/ea_block.c
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
#include "layout.h"
|
||||||
|
#include "../vgmstream.h"
|
||||||
|
|
||||||
|
/* set up for the block at the given offset */
|
||||||
|
void ea_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
||||||
|
int i;
|
||||||
|
|
||||||
|
// Search for next SCDL or SCEl block ...
|
||||||
|
do {
|
||||||
|
block_offset+=4;
|
||||||
|
if(block_offset>(off_t)get_streamfile_size(vgmstream->ch[0].streamfile))
|
||||||
|
return;
|
||||||
|
} while (read_32bitBE(block_offset,vgmstream->ch[0].streamfile)!=0x5343446C);
|
||||||
|
|
||||||
|
// reset channel offset
|
||||||
|
for(i=0;i<vgmstream->channels;i++) {
|
||||||
|
vgmstream->ch[i].channel_start_offset=0;
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->current_block_offset = block_offset;
|
||||||
|
vgmstream->next_block_offset = block_offset+read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-4;
|
||||||
|
|
||||||
|
if(vgmstream->ea_big_endian) {
|
||||||
|
vgmstream->current_block_size = read_32bitBE(block_offset+8,vgmstream->ch[0].streamfile);
|
||||||
|
|
||||||
|
for(i=0;i<vgmstream->channels;i++) {
|
||||||
|
vgmstream->ch[i].offset=read_32bitBE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels);
|
||||||
|
vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if(vgmstream->coding_type==coding_PSX) {
|
||||||
|
vgmstream->ch[0].offset=vgmstream->current_block_offset+0x10;
|
||||||
|
vgmstream->ch[1].offset=(read_32bitLE(block_offset+0x04,vgmstream->ch[0].streamfile)-0x10)/2;
|
||||||
|
vgmstream->ch[1].offset+=vgmstream->ch[0].offset;
|
||||||
|
vgmstream->current_block_size=read_32bitLE(block_offset+0x0C,vgmstream->ch[0].streamfile)*0x10;
|
||||||
|
} else {
|
||||||
|
vgmstream->current_block_size = read_32bitLE(block_offset+8,vgmstream->ch[0].streamfile);
|
||||||
|
for(i=0;i<vgmstream->channels;i++) {
|
||||||
|
vgmstream->ch[i].offset=read_32bitLE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels);
|
||||||
|
vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->current_block_size /= 28;
|
||||||
|
|
||||||
|
if((vgmstream->ea_compression_version<3) && (vgmstream->coding_type!=coding_PSX)) {
|
||||||
|
for(i=0;i<vgmstream->channels;i++) {
|
||||||
|
if(vgmstream->ea_big_endian) {
|
||||||
|
vgmstream->ch[i].adpcm_history1_32=read_16bitBE(vgmstream->ch[i].offset,vgmstream->ch[0].streamfile);
|
||||||
|
vgmstream->ch[i].adpcm_history2_32=read_16bitBE(vgmstream->ch[i].offset+2,vgmstream->ch[0].streamfile);
|
||||||
|
} else {
|
||||||
|
vgmstream->ch[i].adpcm_history1_32=read_16bitLE(vgmstream->ch[i].offset,vgmstream->ch[0].streamfile);
|
||||||
|
vgmstream->ch[i].adpcm_history2_32=read_16bitLE(vgmstream->ch[i].offset+2,vgmstream->ch[0].streamfile);
|
||||||
|
}
|
||||||
|
vgmstream->ch[i].offset+=4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -14,6 +14,8 @@ void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
|||||||
|
|
||||||
void xbox_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
void xbox_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||||
|
|
||||||
|
void ea_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);
|
||||||
|
@ -6,7 +6,7 @@ void xbox_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
|
|||||||
int i;
|
int i;
|
||||||
vgmstream->current_block_offset = block_offset;
|
vgmstream->current_block_offset = block_offset;
|
||||||
vgmstream->current_block_size = 36*vgmstream->channels;
|
vgmstream->current_block_size = 36*vgmstream->channels;
|
||||||
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size;
|
vgmstream->next_block_offset = vgmstream->current_block_offset+(off_t)vgmstream->current_block_size;
|
||||||
|
|
||||||
for (i=0;i<vgmstream->channels;i++) {
|
for (i=0;i<vgmstream->channels;i++) {
|
||||||
vgmstream->ch[i].offset = vgmstream->current_block_offset +
|
vgmstream->ch[i].offset = vgmstream->current_block_offset +
|
||||||
|
@ -222,6 +222,10 @@
|
|||||||
RelativePath=".\meta\Cstr.c"
|
RelativePath=".\meta\Cstr.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\meta\ea_header.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\meta\gcsw.c"
|
RelativePath=".\meta\gcsw.c"
|
||||||
>
|
>
|
||||||
@ -346,6 +350,10 @@
|
|||||||
RelativePath=".\coding\adx_decoder.c"
|
RelativePath=".\coding\adx_decoder.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\coding\eaxa_decoder.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\coding\g721_decoder.c"
|
RelativePath=".\coding\g721_decoder.c"
|
||||||
>
|
>
|
||||||
@ -402,6 +410,10 @@
|
|||||||
RelativePath=".\layout\blocked.c"
|
RelativePath=".\layout\blocked.c"
|
||||||
>
|
>
|
||||||
</File>
|
</File>
|
||||||
|
<File
|
||||||
|
RelativePath=".\layout\ea_block.c"
|
||||||
|
>
|
||||||
|
</File>
|
||||||
<File
|
<File
|
||||||
RelativePath=".\layout\halpst_blocked.c"
|
RelativePath=".\layout\halpst_blocked.c"
|
||||||
>
|
>
|
||||||
|
241
src/meta/ea_header.c
Normal file
241
src/meta/ea_header.c
Normal file
@ -0,0 +1,241 @@
|
|||||||
|
#include "meta.h"
|
||||||
|
#include "../util.h"
|
||||||
|
|
||||||
|
// Platform constants
|
||||||
|
#define EA_PC 0x00
|
||||||
|
#define EA_PSX 0x01
|
||||||
|
#define EA_PS2 0x05
|
||||||
|
#define EA_GC 0x06
|
||||||
|
#define EA_XBOX 0x07
|
||||||
|
#define EA_X360 0x09
|
||||||
|
|
||||||
|
// Compression Version
|
||||||
|
#define EAXA_R1 0x01
|
||||||
|
#define EAXA_R2 0x02
|
||||||
|
#define EAXA_R3 0x03
|
||||||
|
|
||||||
|
// Compression Type
|
||||||
|
#define EA_VAG 0x01
|
||||||
|
#define EA_EAXA 0x0A
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
int32_t num_samples;
|
||||||
|
int32_t sample_rate;
|
||||||
|
uint8_t channels;
|
||||||
|
uint8_t platform;
|
||||||
|
int32_t interleave;
|
||||||
|
uint8_t compression_type;
|
||||||
|
uint8_t compression_version;
|
||||||
|
} EA_STRUCT;
|
||||||
|
|
||||||
|
extern ea_block_update(off_t block_offset, VGMSTREAM * vgmstream);
|
||||||
|
|
||||||
|
uint32_t readPatch(STREAMFILE* streamFile, off_t* offset) {
|
||||||
|
|
||||||
|
uint32_t result=0;
|
||||||
|
uint8_t byteCount;
|
||||||
|
|
||||||
|
byteCount = read_8bit(*offset,streamFile);
|
||||||
|
(*offset)++;
|
||||||
|
|
||||||
|
for(;byteCount>0;byteCount--) {
|
||||||
|
result <<=8;
|
||||||
|
result+=(uint8_t)read_8bit(*offset,streamFile);
|
||||||
|
(*offset)++;
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Parse_Header(STREAMFILE* streamFile,EA_STRUCT* ea, off_t offset, int length) {
|
||||||
|
|
||||||
|
uint8_t byteRead;
|
||||||
|
off_t begin_offset=offset;
|
||||||
|
|
||||||
|
// default value ...
|
||||||
|
ea->channels=1;
|
||||||
|
ea->compression_type=EA_EAXA;
|
||||||
|
ea->compression_version=0x01;
|
||||||
|
ea->platform=EA_GC;
|
||||||
|
|
||||||
|
if(read_32bitBE(offset, streamFile)==0x47535452) { // GSTR
|
||||||
|
ea->compression_version=0x03;
|
||||||
|
offset+=8;
|
||||||
|
length-=4;
|
||||||
|
} else {
|
||||||
|
if(read_16bitBE(offset,streamFile)!=0x5054) // PT
|
||||||
|
offset+=4;
|
||||||
|
|
||||||
|
ea->platform=(uint8_t)read_16bitLE(offset+2,streamFile);
|
||||||
|
offset+=4;
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
byteRead = read_8bit(offset++,streamFile);
|
||||||
|
|
||||||
|
switch(byteRead) {
|
||||||
|
case 0xFF:
|
||||||
|
case 0xFE:
|
||||||
|
case 0xFC:
|
||||||
|
case 0xFD:
|
||||||
|
break;
|
||||||
|
case 0x80: // compression version
|
||||||
|
ea->compression_version = (uint8_t)readPatch(streamFile, &offset);
|
||||||
|
break;
|
||||||
|
case 0x82: // channels count
|
||||||
|
ea->channels = (uint8_t)readPatch(streamFile, &offset);
|
||||||
|
break;
|
||||||
|
case 0x83: // compression type
|
||||||
|
ea->compression_type = (uint8_t)readPatch(streamFile, &offset);
|
||||||
|
break;
|
||||||
|
case 0x84: // sample frequency
|
||||||
|
ea->sample_rate = readPatch(streamFile,&offset);
|
||||||
|
break;
|
||||||
|
case 0x85: // samples count
|
||||||
|
ea->num_samples = readPatch(streamFile, &offset);
|
||||||
|
break;
|
||||||
|
case 0x86:
|
||||||
|
case 0x87:
|
||||||
|
case 0x8C:
|
||||||
|
case 0x92:
|
||||||
|
case 0x9C:
|
||||||
|
case 0x9D: // unknown patch
|
||||||
|
readPatch(streamFile, &offset);
|
||||||
|
break;
|
||||||
|
case 0x88: // interleave
|
||||||
|
ea->interleave = readPatch(streamFile, &offset);
|
||||||
|
break;
|
||||||
|
case 0xA0: // compression type
|
||||||
|
ea->compression_type = (uint8_t)readPatch(streamFile, &offset);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} while(offset-begin_offset<length);
|
||||||
|
|
||||||
|
if(ea->platform==EA_PSX)
|
||||||
|
ea->compression_type=EA_VAG;
|
||||||
|
}
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_ea(STREAMFILE *streamFile) {
|
||||||
|
VGMSTREAM * vgmstream = NULL;
|
||||||
|
EA_STRUCT ea;
|
||||||
|
char filename[260];
|
||||||
|
|
||||||
|
int loop_flag=0;
|
||||||
|
int channel_count;
|
||||||
|
int header_length;
|
||||||
|
off_t start_offset;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
memset(&ea,0,sizeof(EA_STRUCT));
|
||||||
|
|
||||||
|
/* check extension, case insensitive */
|
||||||
|
streamFile->get_name(streamFile,filename,sizeof(filename));
|
||||||
|
if (strcasecmp("sng",filename_extension(filename)) &&
|
||||||
|
strcasecmp("asf",filename_extension(filename)) &&
|
||||||
|
strcasecmp("str",filename_extension(filename)) &&
|
||||||
|
strcasecmp("eam",filename_extension(filename))) goto fail;
|
||||||
|
|
||||||
|
/* check Header */
|
||||||
|
if (read_32bitBE(0x00,streamFile) != 0x5343486C) // SCHl
|
||||||
|
goto fail;
|
||||||
|
|
||||||
|
header_length = read_32bitLE(0x04,streamFile);
|
||||||
|
start_offset=8;
|
||||||
|
|
||||||
|
if(header_length>0x100) goto fail;
|
||||||
|
|
||||||
|
Parse_Header(streamFile,&ea,start_offset,header_length-8);
|
||||||
|
|
||||||
|
/* unknown loop value for the moment */
|
||||||
|
loop_flag = 0;
|
||||||
|
|
||||||
|
channel_count=ea.channels;
|
||||||
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
/* fill in the vital statistics */
|
||||||
|
vgmstream->channels = channel_count;
|
||||||
|
vgmstream->ea_platform=ea.platform;
|
||||||
|
|
||||||
|
vgmstream->ea_compression_type=ea.compression_type;
|
||||||
|
vgmstream->ea_compression_version=ea.compression_version;
|
||||||
|
|
||||||
|
// Set defaut sample rate if not define in the header
|
||||||
|
if(ea.sample_rate!=0) {
|
||||||
|
vgmstream->sample_rate = ea.sample_rate;
|
||||||
|
} else {
|
||||||
|
switch(vgmstream->ea_platform) {
|
||||||
|
case EA_XBOX:
|
||||||
|
vgmstream->sample_rate=24000;
|
||||||
|
break;
|
||||||
|
case EA_X360:
|
||||||
|
vgmstream->sample_rate=44100;
|
||||||
|
vgmstream->ea_compression_version=0x03;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
vgmstream->sample_rate=22050;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
vgmstream->num_samples=ea.num_samples;
|
||||||
|
|
||||||
|
switch(vgmstream->ea_compression_type) {
|
||||||
|
case EA_EAXA:
|
||||||
|
if(vgmstream->ea_compression_version==0x03)
|
||||||
|
vgmstream->meta_type=meta_EAXA_R3;
|
||||||
|
else
|
||||||
|
vgmstream->meta_type=meta_EAXA_R2;
|
||||||
|
|
||||||
|
vgmstream->coding_type=coding_EAXA;
|
||||||
|
vgmstream->layout_type=layout_ea_blocked;
|
||||||
|
if((vgmstream->ea_platform==EA_GC) || (vgmstream->ea_platform==EA_X360))
|
||||||
|
vgmstream->ea_big_endian=1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
case EA_VAG:
|
||||||
|
vgmstream->meta_type=meta_EAXA_PSX;
|
||||||
|
vgmstream->coding_type=coding_PSX;
|
||||||
|
vgmstream->layout_type=layout_ea_blocked;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* open the file for reading by each channel */
|
||||||
|
{
|
||||||
|
for (i=0;i<channel_count;i++) {
|
||||||
|
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);
|
||||||
|
|
||||||
|
if (!vgmstream->ch[i].streamfile) goto fail;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Special function for .EAM files ...
|
||||||
|
if(!strcasecmp("eam",filename_extension(filename))) {
|
||||||
|
|
||||||
|
size_t file_length=get_streamfile_size(streamFile);
|
||||||
|
size_t block_length;
|
||||||
|
|
||||||
|
vgmstream->next_block_offset=start_offset+header_length;
|
||||||
|
vgmstream->num_samples=0;
|
||||||
|
|
||||||
|
// to initialize the block length
|
||||||
|
ea_block_update(start_offset+header_length,vgmstream);
|
||||||
|
block_length=vgmstream->next_block_offset-start_offset+header_length;
|
||||||
|
|
||||||
|
do {
|
||||||
|
ea_block_update(vgmstream->next_block_offset,vgmstream);
|
||||||
|
vgmstream->num_samples+=vgmstream->current_block_size*28;
|
||||||
|
} while(vgmstream->next_block_offset<(file_length-block_length));
|
||||||
|
}
|
||||||
|
|
||||||
|
ea_block_update(start_offset+header_length,vgmstream);
|
||||||
|
|
||||||
|
return vgmstream;
|
||||||
|
|
||||||
|
/* clean up anything we may have opened */
|
||||||
|
fail:
|
||||||
|
if (vgmstream) close_vgmstream(vgmstream);
|
||||||
|
return NULL;
|
||||||
|
}
|
@ -73,4 +73,6 @@ VGMSTREAM * init_vgmstream_xbox_xwav(STREAMFILE *streamFile);
|
|||||||
|
|
||||||
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile);
|
VGMSTREAM * init_vgmstream_ngc_str(STREAMFILE *streamFile);
|
||||||
|
|
||||||
|
VGMSTREAM * init_vgmstream_ea(STREAMFILE *streamFile);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -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 35
|
#define INIT_VGMSTREAM_FCNS 36
|
||||||
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 */
|
||||||
@ -51,7 +51,8 @@ VGMSTREAM * (*init_vgmstream_fcns[INIT_VGMSTREAM_FCNS])(STREAMFILE *streamFile)
|
|||||||
init_vgmstream_ps2_pnb, /* 31 */
|
init_vgmstream_ps2_pnb, /* 31 */
|
||||||
init_vgmstream_xbox_wavm, /* 32 */
|
init_vgmstream_xbox_wavm, /* 32 */
|
||||||
init_vgmstream_xbox_xwav, /* 33 */
|
init_vgmstream_xbox_xwav, /* 33 */
|
||||||
init_vgmstream_ngc_str /* 34 */
|
init_vgmstream_ngc_str, /* 34 */
|
||||||
|
init_vgmstream_ea /* 35 */
|
||||||
};
|
};
|
||||||
|
|
||||||
/* internal version with all parameters */
|
/* internal version with all parameters */
|
||||||
@ -227,6 +228,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
|||||||
case layout_halpst_blocked:
|
case layout_halpst_blocked:
|
||||||
case layout_xa_blocked:
|
case layout_xa_blocked:
|
||||||
case layout_xbox_blocked:
|
case layout_xbox_blocked:
|
||||||
|
case layout_ea_blocked:
|
||||||
render_vgmstream_blocked(buffer,sample_count,vgmstream);
|
render_vgmstream_blocked(buffer,sample_count,vgmstream);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -255,6 +257,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
|
|||||||
return 28;
|
return 28;
|
||||||
case coding_XBOX:
|
case coding_XBOX:
|
||||||
return 64;
|
return 64;
|
||||||
|
case coding_EAXA:
|
||||||
|
return 28;
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -294,6 +298,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
|
|||||||
return 14*vgmstream->channels;
|
return 14*vgmstream->channels;
|
||||||
case coding_XBOX:
|
case coding_XBOX:
|
||||||
return 64+(4*vgmstream->channels);
|
return 64+(4*vgmstream->channels);
|
||||||
|
case coding_EAXA:
|
||||||
|
return 1; // the frame is variant in size
|
||||||
default:
|
default:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -397,6 +403,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
|
|||||||
samples_to_do);
|
samples_to_do);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case coding_EAXA:
|
||||||
|
for (chan=0;chan<vgmstream->channels;chan++) {
|
||||||
|
decode_eaxa(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
|
||||||
|
vgmstream->channels,vgmstream->samples_into_block,
|
||||||
|
samples_to_do,chan);
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -560,6 +573,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
break;
|
break;
|
||||||
case coding_XBOX:
|
case coding_XBOX:
|
||||||
snprintf(temp,TEMPSIZE,"XBOX 4-bit IMA ADPCM");
|
snprintf(temp,TEMPSIZE,"XBOX 4-bit IMA ADPCM");
|
||||||
|
break;
|
||||||
|
case coding_EAXA:
|
||||||
|
snprintf(temp,TEMPSIZE,"Electronic Arts XA Based 4-bit ADPCM");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
|
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
|
||||||
@ -593,6 +609,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
break;
|
break;
|
||||||
case layout_xbox_blocked:
|
case layout_xbox_blocked:
|
||||||
snprintf(temp,TEMPSIZE,"XBOX blocked");
|
snprintf(temp,TEMPSIZE,"XBOX blocked");
|
||||||
|
break;
|
||||||
|
case layout_ea_blocked:
|
||||||
|
snprintf(temp,TEMPSIZE,"Electronic Arts Audio Blocks");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
|
snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
|
||||||
@ -752,6 +771,15 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
|
|||||||
break;
|
break;
|
||||||
case meta_DSP_STR:
|
case meta_DSP_STR:
|
||||||
snprintf(temp,TEMPSIZE,"assumed Conan Gamecube STR File by .str extension");
|
snprintf(temp,TEMPSIZE,"assumed Conan Gamecube STR File by .str extension");
|
||||||
|
break;
|
||||||
|
case meta_EAXA_R2:
|
||||||
|
snprintf(temp,TEMPSIZE,"Electronic Arts XA R2");
|
||||||
|
break;
|
||||||
|
case meta_EAXA_R3:
|
||||||
|
snprintf(temp,TEMPSIZE,"Electronic Arts XA R3");
|
||||||
|
break;
|
||||||
|
case meta_EAXA_PSX:
|
||||||
|
snprintf(temp,TEMPSIZE,"Electronic Arts With PSX ADPCM");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
|
||||||
|
@ -25,6 +25,7 @@ typedef enum {
|
|||||||
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_XBOX, /* XBOX IMA */
|
||||||
|
coding_EAXA, /* EA/XA ADPCM */
|
||||||
} 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 */
|
||||||
@ -42,6 +43,7 @@ typedef enum {
|
|||||||
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,
|
layout_xbox_blocked,
|
||||||
|
layout_ea_blocked,
|
||||||
#if 0
|
#if 0
|
||||||
layout_strm_blocked, /* */
|
layout_strm_blocked, /* */
|
||||||
#endif
|
#endif
|
||||||
@ -106,6 +108,10 @@ typedef enum {
|
|||||||
meta_XBOX_WAVM, /* XBOX WAVM File */
|
meta_XBOX_WAVM, /* XBOX WAVM File */
|
||||||
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
|
meta_XBOX_RIFF, /* XBOX RIFF/WAVE File */
|
||||||
|
|
||||||
|
meta_EAXA_R2, /* EA XA Release 2 */
|
||||||
|
meta_EAXA_R3, /* EA XA Release 3 */
|
||||||
|
meta_EAXA_PSX, /* EA with PSX ADPCM */
|
||||||
|
|
||||||
meta_RAW, /* RAW PCM file */
|
meta_RAW, /* RAW PCM file */
|
||||||
|
|
||||||
} meta_t;
|
} meta_t;
|
||||||
@ -183,6 +189,11 @@ typedef struct {
|
|||||||
uint8_t xa_channel; /* Selected XA Channel */
|
uint8_t xa_channel; /* Selected XA Channel */
|
||||||
int32_t xa_sector_length; /* XA block */
|
int32_t xa_sector_length; /* XA block */
|
||||||
|
|
||||||
|
uint8_t ea_big_endian; /* Big Endian ? */
|
||||||
|
uint8_t ea_compression_type;
|
||||||
|
uint8_t ea_compression_version;
|
||||||
|
uint8_t ea_platform;
|
||||||
|
|
||||||
void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */
|
void * start_vgmstream; /* a copy of the VGMSTREAM as it was at the beginning of the stream */
|
||||||
} VGMSTREAM;
|
} VGMSTREAM;
|
||||||
|
|
||||||
|
@ -71,7 +71,7 @@ int decode_pos_samples = 0;
|
|||||||
int stream_length_samples = 0;
|
int stream_length_samples = 0;
|
||||||
int fade_samples = 0;
|
int fade_samples = 0;
|
||||||
|
|
||||||
#define EXTENSION_LIST_SIZE 1024
|
#define EXTENSION_LIST_SIZE 2048
|
||||||
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
char working_extension_list[EXTENSION_LIST_SIZE] = {0};
|
||||||
char * extension_list[] = {
|
char * extension_list[] = {
|
||||||
"adx\0ADX Audio File (*.ADX)\0",
|
"adx\0ADX Audio File (*.ADX)\0",
|
||||||
@ -108,7 +108,10 @@ char * extension_list[] = {
|
|||||||
"pnb\0PNB Audio File (*.PNB)\0",
|
"pnb\0PNB Audio File (*.PNB)\0",
|
||||||
"wavm\0WAVM Audio File (*.WAVM)\0",
|
"wavm\0WAVM Audio File (*.WAVM)\0",
|
||||||
"xwav\0XWAV Audio File (*.XWAV)\0",
|
"xwav\0XWAV Audio File (*.XWAV)\0",
|
||||||
"wp2\0WP2 Audio File (*.WP2)\0"
|
"wp2\0WP2 Audio File (*.WP2)\0",
|
||||||
|
"sng\0SNG Audio File (*.SNG)\0",
|
||||||
|
"asf\0ASF Audio File (*.ASF)\0",
|
||||||
|
"eam\0EAM Audio File (*.EAM)\0"
|
||||||
};
|
};
|
||||||
|
|
||||||
void about(HWND hwndParent) {
|
void about(HWND hwndParent) {
|
||||||
|
Loading…
Reference in New Issue
Block a user