add preliminary westwood studios aud support

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@277 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2008-07-03 02:20:52 +00:00
parent b95f41a330
commit fd4f7a9eec
16 changed files with 233 additions and 8 deletions

View File

@ -93,6 +93,7 @@ File types supported by this version of vgmstream:
- .aifc (SDX2 DPCM, DVI IMA ADPCM)
- .aiff (8/16 bit PCM)
- .str (SDX2 DPCM)
- .aud (IMA ADPCM)
Enjoy!
-hcs

View File

@ -20,7 +20,8 @@ LAYOUT_OBJS=layout/ast_blocked.o \
layout/caf_blocked.o \
layout/ea_block.o \
layout/wsi_blocked.o \
layout/str_snds_blocked.o
layout/str_snds_blocked.o \
layout/ws_aud_blocked.o
META_OBJS=meta/adx_header.o \
meta/afc_header.o \
@ -60,7 +61,8 @@ META_OBJS=meta/adx_header.o \
meta/ogg_vorbis_file.o \
meta/ps2_bmdx.o \
meta/aifc.o \
meta/str_snds.o
meta/str_snds.o \
meta/ws_aud.o
OBJECTS=vgmstream.o streamfile.o util.o $(CODING_OBJS) $(LAYOUT_OBJS) $(META_OBJS)

View File

@ -11,6 +11,7 @@ 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_xbox_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ima(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);

View File

@ -155,3 +155,43 @@ void decode_dvi_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspaci
stream->adpcm_history1_32=hist1;
stream->adpcm_step_index=step_index;
}
void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count=0;
int32_t hist1=stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int step = ADPCMTable[step_index];
uint8_t sample_byte;
int sample_nibble;
int sample_decoded;
int delta;
sample_byte = read_8bit(stream->offset+i/2,stream->streamfile);
sample_nibble = (sample_byte >> (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&0x7];
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;
}

View File

@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix
liblayout_la_LDFLAGS =
liblayout_la_SOURCES = ast_blocked.c blocked.c caf_blocked.c ea_block.c halpst_blocked.c interleave.c nolayout.c xa_blocked.c wsi_blocked.c str_snds_blocked.c
liblayout_la_SOURCES = ast_blocked.c blocked.c caf_blocked.c ea_block.c halpst_blocked.c interleave.c nolayout.c xa_blocked.c wsi_blocked.c str_snds_blocked.c ws_aud_blocked.c
EXTRA_DIST = layout.h

View File

@ -8,13 +8,23 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
int samples_this_block;
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
if (frame_size == 0) {
/* assume 4 bit */
/* TODO: get_vgmstream_frame_size() really should return bits... */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
}
while (samples_written<sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
if (frame_size == 0) {
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
}
continue;
}
@ -63,11 +73,18 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
case layout_str_snds_blocked:
str_snds_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_ws_aud_blocked:
ws_aud_block_update(vgmstream->next_block_offset,vgmstream);
break;
default:
break;
}
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
if (frame_size == 0) {
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
}
vgmstream->samples_into_block=0;
}

View File

@ -20,6 +20,8 @@ void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ws_aud_block_update(off_t block_offset, 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);

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void ws_aud_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_16bitLE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset +
vgmstream->current_block_size + 8;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
8 + vgmstream->current_block_size*i;
}
}

View File

@ -350,6 +350,10 @@
RelativePath=".\meta\str_snds.c"
>
</File>
<File
RelativePath=".\meta\ws_aud.c"
>
</File>
</Filter>
</Filter>
<Filter
@ -474,6 +478,10 @@
RelativePath=".\layout\str_snds_blocked.c"
>
</File>
<File
RelativePath=".\layout\ws_aud_blocked.c"
>
</File>
</Filter>
</Filter>
</Files>

View File

@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix
libmeta_la_LDFLAGS =
libmeta_la_SOURCES = Cstr.c adx_header.c afc_header.c agsc.c ast.c brstm.c ea_header.c gcsw.c halpst.c nds_strm.c ngc_adpdtk.c ngc_caf.c ngc_dsp_std.c ps2_ads.c ps2_exst.c ps2_ild.c ps2_int.c ps2_mib.c ps2_mic.c ps2_npsf.c ps2_pnb.c ps2_rxw.c ps2_str.c ps2_svag.c ps2_vag.c ps2_vpk.c psx_cdxa.c raw.c rs03.c rsf.c rwsd.c psx_gms.c xbox_xwav.c xbox_wavm.c genh.c ogg_vorbis_file.c ps2_bmdx.c aifc.c str_snds.c
libmeta_la_SOURCES = Cstr.c adx_header.c afc_header.c agsc.c ast.c brstm.c ea_header.c gcsw.c halpst.c nds_strm.c ngc_adpdtk.c ngc_caf.c ngc_dsp_std.c ps2_ads.c ps2_exst.c ps2_ild.c ps2_int.c ps2_mib.c ps2_mic.c ps2_npsf.c ps2_pnb.c ps2_rxw.c ps2_str.c ps2_svag.c ps2_vag.c ps2_vpk.c psx_cdxa.c raw.c rs03.c rsf.c rwsd.c psx_gms.c xbox_xwav.c xbox_wavm.c genh.c ogg_vorbis_file.c ps2_bmdx.c aifc.c str_snds.c ws_aud.c
EXTRA_DIST = meta.h

View File

@ -95,4 +95,6 @@ VGMSTREAM * init_vgmstream_aifc(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_str_snds(STREAMFILE * streamFile);
VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE * streamFile);
#endif

105
src/meta/ws_aud.c Normal file
View File

@ -0,0 +1,105 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* Westwood Studios .aud (WS-AUD) */
VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[260];
coding_t coding_type = -1;
int channel_count;
int new_type = 0; /* if 0 is old type */
int bytes_per_sample = 0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("aud",filename_extension(filename))) goto fail;
/* check for 0x0000DEAF chunk marker for first chunk */
if (read_32bitLE(0x10,streamFile)==0x0000DEAF) { /* new */
new_type = 1;
} else if (read_32bitLE(0x08,streamFile)==0x0000DEAF) { /* old (?) */
new_type = 0;
} else goto fail;
if (!new_type) goto fail; /* TODO: not yet supported */
/* get channel count */
if (read_8bit(0xa,streamFile) & 1)
channel_count = 2;
else
channel_count = 1;
if (channel_count == 2) goto fail; /* TODO: not yet supported */
/* get output format */
if (read_8bit(0xa,streamFile) & 2)
bytes_per_sample = 2;
else
bytes_per_sample = 1;
if (bytes_per_sample == 1) goto fail; /* TODO: not yet supported */
/* check codec type */
switch (read_8bit(0xb,streamFile)) {
case 1: /* Westwood custom */
goto fail; /* TODO: not yet supported */
break;
case 99: /* IMA ADPCM */
coding_type = coding_IMA;
break;
default:
goto fail;
break;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,0);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitLE(0x06,streamFile)/bytes_per_sample/channel_count;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x00,streamFile);
vgmstream->coding_type = coding_type;
if (new_type) {
vgmstream->meta_type = meta_WS_AUD;
} else {
vgmstream->meta_type = meta_WS_AUD_old;
}
vgmstream->layout_type = layout_ws_aud_blocked;
/* open the file for reading by each channel */
{
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;
}
}
/* start me up */
if (new_type) {
ws_aud_block_update(0xc,vgmstream);
} else {
ws_aud_block_update(0x8,vgmstream);
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -63,6 +63,7 @@ VGMSTREAM * (*init_vgmstream_fcns[])(STREAMFILE *streamFile) = {
init_vgmstream_wsi,
init_vgmstream_aifc,
init_vgmstream_str_snds,
init_vgmstream_ws_aud,
};
#define INIT_VGMSTREAM_FCNS (sizeof(init_vgmstream_fcns)/sizeof(init_vgmstream_fcns[0]))
@ -273,6 +274,7 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
case layout_caf_blocked:
case layout_wsi_blocked:
case layout_str_snds_blocked:
case layout_ws_aud_blocked:
render_vgmstream_blocked(buffer,sample_count,vgmstream);
break;
}
@ -298,6 +300,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return 28;
case coding_G721:
case coding_DVI_IMA:
case coding_IMA:
return 1;
case coding_NGC_AFC:
return 16;
@ -340,6 +343,7 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_NGC_DTK:
return 32;
case coding_DVI_IMA:
case coding_IMA:
case coding_G721:
return 0;
case coding_NGC_AFC:
@ -491,6 +495,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do);
}
break;
case coding_IMA:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_ima(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break;
}
}
@ -683,6 +694,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case coding_DVI_IMA:
snprintf(temp,TEMPSIZE,"Intel DVI 4-bit IMA ADPCM");
break;
case coding_IMA:
snprintf(temp,TEMPSIZE,"4-bit IMA ADPCM");
break;
default:
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
}
@ -730,6 +744,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case layout_str_snds_blocked:
snprintf(temp,TEMPSIZE,".str SNDS blocked");
break;
case layout_ws_aud_blocked:
snprintf(temp,TEMPSIZE,"Westwood Studios .aud blocked");
break;
default:
snprintf(temp,TEMPSIZE,"INCONCEIVABLE");
}
@ -930,6 +947,12 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case meta_STR_SNDS:
snprintf(temp,TEMPSIZE,".str SNDS SHDR chunk");
break;
case meta_WS_AUD:
snprintf(temp,TEMPSIZE,"Westwood Studios .aud header");
break;
case meta_WS_AUD_old:
snprintf(temp,TEMPSIZE,"Westwood Studios .aud (old) header");
break;
default:
snprintf(temp,TEMPSIZE,"THEY SHOULD HAVE SENT A POET");
}

View File

@ -36,7 +36,8 @@ typedef enum {
coding_ogg_vorbis, /* vorbis */
#endif
coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */
coding_DVI_IMA, /* DVI IMA, aka ADP4 */
coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */
coding_IMA, /* bare IMA, low nibble first */
} coding_t;
/* The layout type specifies how the sound data is laid out in the file */
@ -57,6 +58,7 @@ typedef enum {
layout_caf_blocked,
layout_wsi_blocked,
layout_str_snds_blocked,
layout_ws_aud_blocked,
#if 0
layout_strm_blocked, /* */
#endif
@ -144,6 +146,8 @@ typedef enum {
meta_AIFC, /* Audio Interchange File Format AIFF-C */
meta_AIFF, /* Audio Interchange File Format */
meta_STR_SNDS, /* .str with SNDS blocks and SHDR header */
meta_WS_AUD, /* Westwood Studios .aud */
meta_WS_AUD_old, /* Westwood Studios .aud, old style */
} meta_t;
typedef struct {

View File

@ -62,6 +62,7 @@ gchar *vgmstream_exts [] = {
"bmdx",
"wsi",
"aifc",
"aud",
/* terminator */
NULL
};

View File

@ -120,6 +120,7 @@ char * extension_list[] = {
"bmdx\0BMDX Audio File (*.BMDX)\0",
"wsi\0WSI Audio File (*.WSI)\0",
"aifc\0AIFC Audio File (*.AIFC)\0",
"aud\0AUD Audio File (*.AUD)\0",
};
void about(HWND hwndParent) {