mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-28 00:20:47 +01:00
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:
parent
b95f41a330
commit
fd4f7a9eec
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
18
src/layout/ws_aud_blocked.c
Normal file
18
src/layout/ws_aud_blocked.c
Normal 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;
|
||||
}
|
||||
}
|
@ -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>
|
||||
|
@ -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
|
||||
|
@ -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
105
src/meta/ws_aud.c
Normal 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;
|
||||
}
|
@ -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");
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -62,6 +62,7 @@ gchar *vgmstream_exts [] = {
|
||||
"bmdx",
|
||||
"wsi",
|
||||
"aifc",
|
||||
"aud",
|
||||
/* terminator */
|
||||
NULL
|
||||
};
|
||||
|
@ -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) {
|
||||
|
Loading…
Reference in New Issue
Block a user