starting support for WS ADPCM, decoder not in place but layout is handled properly

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@282 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2008-07-03 21:21:01 +00:00
parent 253dd60d66
commit 0903e46346
10 changed files with 93 additions and 12 deletions

View File

@ -9,7 +9,8 @@ CODING_OBJS=coding/adx_decoder.o \
coding/xa_decoder.o \ coding/xa_decoder.o \
coding/eaxa_decoder.o \ coding/eaxa_decoder.o \
coding/ogg_vorbis_decoder.o \ coding/ogg_vorbis_decoder.o \
coding/sdx2_decoder.o coding/sdx2_decoder.o \
coding/ws_decoder.o
LAYOUT_OBJS=layout/ast_blocked.o \ LAYOUT_OBJS=layout/ast_blocked.o \
layout/blocked.o \ layout/blocked.o \

View File

@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix AM_MAKEFLAGS=-f Makefile.unix
libcoding_la_LDFLAGS = libcoding_la_LDFLAGS =
libcoding_la_SOURCES = adx_decoder.c eaxa_decoder.c g721_decoder.c ima_decoder.c ngc_afc_decoder.c ngc_dsp_decoder.c ngc_dtk_decoder.c pcm_decoder.c psx_decoder.c xa_decoder.c ogg_vorbis_decoder.c sdx2_decoder.c libcoding_la_SOURCES = adx_decoder.c eaxa_decoder.c g721_decoder.c ima_decoder.c ngc_afc_decoder.c ngc_dsp_decoder.c ngc_dtk_decoder.c pcm_decoder.c psx_decoder.c xa_decoder.c ogg_vorbis_decoder.c sdx2_decoder.c ws_decoder.c
EXTRA_DIST = coding.h g72x_state.h EXTRA_DIST = coding.h g72x_state.h

View File

@ -39,4 +39,6 @@ void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t sa
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ws(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
#endif #endif

20
src/coding/ws_decoder.c Normal file
View File

@ -0,0 +1,20 @@
#include <math.h>
#include "coding.h"
#include "../util.h"
/* Westwood Studios ADPCM */
/* Based on Valery V. Ansimovsky's WS-AUD.txt */
void decode_ws(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int32_t hist = stream->adpcm_history1_32;
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
outbuf[sample_count] = 0;
}
stream->adpcm_history1_32=hist;
}

View File

@ -80,6 +80,10 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM *
break; break;
} }
/* for VBR these may change */
frame_size = get_vgmstream_frame_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
if (frame_size == 0) { if (frame_size == 0) {
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else { } else {

View File

@ -11,6 +11,13 @@ void ws_aud_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->next_block_offset = vgmstream->current_block_offset +
vgmstream->current_block_size + 8; vgmstream->current_block_size + 8;
if (vgmstream->coding_type == coding_WS) {
/* this only works if the output sample size is 8 bit */
vgmstream->ws_output_samples = read_16bitLE(
vgmstream->current_block_offset+2,
vgmstream->ch[0].streamfile);
}
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 +
8 + vgmstream->current_block_size*i; 8 + vgmstream->current_block_size*i;

View File

@ -422,6 +422,10 @@
RelativePath=".\coding\sdx2_decoder.c" RelativePath=".\coding\sdx2_decoder.c"
> >
</File> </File>
<File
RelativePath=".\coding\ws_decoder.c"
>
</File>
</Filter> </Filter>
</Filter> </Filter>
<Filter <Filter

View File

@ -9,6 +9,7 @@ VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE *streamFile) {
char filename[260]; char filename[260];
coding_t coding_type = -1; coding_t coding_type = -1;
off_t format_offset;
int channel_count; int channel_count;
int new_type = 0; /* if 0 is old type */ int new_type = 0; /* if 0 is old type */
@ -22,32 +23,36 @@ VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE *streamFile) {
/* check for 0x0000DEAF chunk marker for first chunk */ /* check for 0x0000DEAF chunk marker for first chunk */
if (read_32bitLE(0x10,streamFile)==0x0000DEAF) { /* new */ if (read_32bitLE(0x10,streamFile)==0x0000DEAF) { /* new */
new_type = 1; new_type = 1;
} else if (read_32bitLE(0x08,streamFile)==0x0000DEAF) { /* old (?) */ } else if (read_32bitLE(0x0C,streamFile)==0x0000DEAF) { /* old */
new_type = 0; new_type = 0;
} else goto fail; } else goto fail;
if (!new_type) goto fail; /* TODO: not yet supported */ if (new_type)
format_offset = 0xa;
else
format_offset = 0x6;
/* get channel count */ /* get channel count */
if (read_8bit(0xa,streamFile) & 1) if (read_8bit(format_offset,streamFile) & 1)
channel_count = 2; channel_count = 2;
else else
channel_count = 1; channel_count = 1;
if (channel_count == 2) goto fail; /* TODO: not yet supported */ if (channel_count == 2) goto fail; /* TODO: not yet supported (largely
because not yet seen) */
/* get output format */ /* get output format */
if (read_8bit(0xa,streamFile) & 2) if (read_8bit(format_offset+1,streamFile) & 2)
bytes_per_sample = 2; bytes_per_sample = 2;
else else
bytes_per_sample = 1; bytes_per_sample = 1;
if (bytes_per_sample == 1) goto fail; /* TODO: not yet supported */
/* check codec type */ /* check codec type */
switch (read_8bit(0xb,streamFile)) { switch (read_8bit(format_offset+1,streamFile)) {
case 1: /* Westwood custom */ case 1: /* Westwood custom */
goto fail; /* TODO: not yet supported */ coding_type = coding_WS;
/* shouldn't happen? */
if (bytes_per_sample != 1) goto fail;
break; break;
case 99: /* IMA ADPCM */ case 99: /* IMA ADPCM */
coding_type = coding_IMA; coding_type = coding_IMA;
@ -63,7 +68,28 @@ VGMSTREAM * init_vgmstream_ws_aud(STREAMFILE *streamFile) {
if (!vgmstream) goto fail; if (!vgmstream) goto fail;
/* fill in the vital statistics */ /* fill in the vital statistics */
if (new_type) {
vgmstream->num_samples = read_32bitLE(0x06,streamFile)/bytes_per_sample/channel_count; vgmstream->num_samples = read_32bitLE(0x06,streamFile)/bytes_per_sample/channel_count;
} else {
/* Doh, no output size in old type files. We have to read through the
* file looking at chunk headers! Crap! */
int32_t out_size = 0;
off_t current_offset = 0x8;
off_t file_size = get_streamfile_size(streamFile);
while (current_offset < file_size) {
int16_t chunk_size;
chunk_size = read_16bitLE(current_offset,streamFile);
out_size += read_16bitLE(current_offset+2,streamFile);
/* while we're here might as well check for valid chunks */
if (read_32bitLE(current_offset+4,streamFile) != 0x0000DEAF) goto fail;
current_offset+=8+chunk_size;
}
vgmstream->num_samples = out_size/bytes_per_sample/channel_count;
}
/* they tend to not actually have data for the last odd sample */
if (vgmstream->num_samples & 1) vgmstream->num_samples--; if (vgmstream->num_samples & 1) vgmstream->num_samples--;
vgmstream->sample_rate = (uint16_t)read_16bitLE(0x00,streamFile); vgmstream->sample_rate = (uint16_t)read_16bitLE(0x00,streamFile);

View File

@ -312,6 +312,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
return 64; return 64;
case coding_EAXA: case coding_EAXA:
return 28; return 28;
case coding_WS:
return vgmstream->ws_output_samples;
default: default:
return 0; return 0;
} }
@ -357,6 +359,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
return 36; return 36;
case coding_EAXA: case coding_EAXA:
return 1; // the frame is variant in size return 1; // the frame is variant in size
case coding_WS:
return vgmstream->current_block_size;
default: default:
return 0; return 0;
} }
@ -502,6 +506,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
samples_to_do); samples_to_do);
} }
break; break;
case coding_WS:
for (chan=0;chan<vgmstream->channels;chan++) {
decode_ws(&vgmstream->ch[chan],buffer+samples_written*vgmstream->channels+chan,
vgmstream->channels,vgmstream->samples_into_block,
samples_to_do);
}
break;
} }
} }
@ -697,6 +708,9 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case coding_IMA: case coding_IMA:
snprintf(temp,TEMPSIZE,"4-bit IMA ADPCM"); snprintf(temp,TEMPSIZE,"4-bit IMA ADPCM");
break; break;
case coding_WS:
snprintf(temp,TEMPSIZE,"Westwood Studios ADPCM");
break;
default: default:
snprintf(temp,TEMPSIZE,"CANNOT DECODE"); snprintf(temp,TEMPSIZE,"CANNOT DECODE");
} }

View File

@ -38,6 +38,7 @@ typedef enum {
coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */ coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */
coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */ coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */
coding_IMA, /* bare IMA, low nibble first */ coding_IMA, /* bare IMA, low nibble first */
coding_WS, /* Westwood Studios' custom VBR 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 */
@ -228,6 +229,8 @@ typedef struct {
uint8_t ea_compression_version; uint8_t ea_compression_version;
uint8_t ea_platform; uint8_t ea_platform;
int32_t ws_output_samples; /* output samples for this block */
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 */
/* Data the codec needs for the whole stream. This is for codecs too /* Data the codec needs for the whole stream. This is for codecs too