From 0903e46346bc85fda833cf2010c90e7e53fbbabc Mon Sep 17 00:00:00 2001 From: halleyscometsw Date: Thu, 3 Jul 2008 21:21:01 +0000 Subject: [PATCH] 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 --- src/Makefile | 3 ++- src/coding/Makefile.unix.am | 2 +- src/coding/coding.h | 2 ++ src/coding/ws_decoder.c | 20 ++++++++++++++++ src/layout/blocked.c | 4 ++++ src/layout/ws_aud_blocked.c | 7 ++++++ src/libvgmstream.vcproj | 4 ++++ src/meta/ws_aud.c | 46 +++++++++++++++++++++++++++++-------- src/vgmstream.c | 14 +++++++++++ src/vgmstream.h | 3 +++ 10 files changed, 93 insertions(+), 12 deletions(-) create mode 100644 src/coding/ws_decoder.c diff --git a/src/Makefile b/src/Makefile index 8e47d534..f6fa02e0 100644 --- a/src/Makefile +++ b/src/Makefile @@ -9,7 +9,8 @@ CODING_OBJS=coding/adx_decoder.o \ coding/xa_decoder.o \ coding/eaxa_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/blocked.o \ diff --git a/src/coding/Makefile.unix.am b/src/coding/Makefile.unix.am index bc9eea86..53439127 100644 --- a/src/coding/Makefile.unix.am +++ b/src/coding/Makefile.unix.am @@ -4,6 +4,6 @@ AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir) AM_MAKEFLAGS=-f Makefile.unix 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 diff --git a/src/coding/coding.h b/src/coding/coding.h index 863a4f98..a430db4d 100644 --- a/src/coding/coding.h +++ b/src/coding/coding.h @@ -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_ws(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do); + #endif diff --git a/src/coding/ws_decoder.c b/src/coding/ws_decoder.c new file mode 100644 index 00000000..82d67a2f --- /dev/null +++ b/src/coding/ws_decoder.c @@ -0,0 +1,20 @@ +#include +#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; iadpcm_history1_32=hist; +} diff --git a/src/layout/blocked.c b/src/layout/blocked.c index 545883d9..ce8720af 100644 --- a/src/layout/blocked.c +++ b/src/layout/blocked.c @@ -80,6 +80,10 @@ void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * 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) { samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; } else { diff --git a/src/layout/ws_aud_blocked.c b/src/layout/ws_aud_blocked.c index 4e56579c..982e2a2e 100644 --- a/src/layout/ws_aud_blocked.c +++ b/src/layout/ws_aud_blocked.c @@ -11,6 +11,13 @@ void ws_aud_block_update(off_t block_offset, VGMSTREAM * vgmstream) { vgmstream->next_block_offset = vgmstream->current_block_offset + 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;ichannels;i++) { vgmstream->ch[i].offset = vgmstream->current_block_offset + 8 + vgmstream->current_block_size*i; diff --git a/src/libvgmstream.vcproj b/src/libvgmstream.vcproj index ba558537..703b894e 100644 --- a/src/libvgmstream.vcproj +++ b/src/libvgmstream.vcproj @@ -422,6 +422,10 @@ RelativePath=".\coding\sdx2_decoder.c" > + + num_samples = read_32bitLE(0x06,streamFile)/bytes_per_sample/channel_count; + if (new_type) { + 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--; vgmstream->sample_rate = (uint16_t)read_16bitLE(0x00,streamFile); diff --git a/src/vgmstream.c b/src/vgmstream.c index b748030f..bf6b0318 100644 --- a/src/vgmstream.c +++ b/src/vgmstream.c @@ -312,6 +312,8 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) { return 64; case coding_EAXA: return 28; + case coding_WS: + return vgmstream->ws_output_samples; default: return 0; } @@ -357,6 +359,8 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) { return 36; case coding_EAXA: return 1; // the frame is variant in size + case coding_WS: + return vgmstream->current_block_size; default: return 0; } @@ -502,6 +506,13 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to samples_to_do); } break; + case coding_WS: + for (chan=0;chanchannels;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: snprintf(temp,TEMPSIZE,"4-bit IMA ADPCM"); break; + case coding_WS: + snprintf(temp,TEMPSIZE,"Westwood Studios ADPCM"); + break; default: snprintf(temp,TEMPSIZE,"CANNOT DECODE"); } diff --git a/src/vgmstream.h b/src/vgmstream.h index 9ae63c9d..019ccace 100644 --- a/src/vgmstream.h +++ b/src/vgmstream.h @@ -38,6 +38,7 @@ typedef enum { coding_SDX2, /* SDX2 2:1 Squareroot-Delta-Exact compression */ coding_DVI_IMA, /* DVI (bare IMA, high nibble first), aka ADP4 */ coding_IMA, /* bare IMA, low nibble first */ + coding_WS, /* Westwood Studios' custom VBR ADPCM */ } coding_t; /* 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_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 */ /* Data the codec needs for the whole stream. This is for codecs too