compressed NWA decoding, no looping yet

git-svn-id: https://vgmstream.svn.sourceforge.net/svnroot/vgmstream@389 51a99a44-fe44-0410-b1ba-c3e57ba2b86b
This commit is contained in:
halleyscometsw 2008-08-03 14:58:03 +00:00
parent 3f6e5595b8
commit 98d11bd9f2
10 changed files with 591 additions and 36 deletions

View File

@ -105,7 +105,7 @@ File types supported by this version of vgmstream:
- .wav (8/16 bit PCM)
- .lwav (8/16 bit PCM)
- .pos (loop info for .wav)
- .nwa (16 bit PCM)
- .nwa (16 bit PCM, NWA DPCM)
- .xss (16 bit PCM)
- .sl3 (PS2 ADPCM)
- .hgc1 (PS2 ADPCM)

View File

@ -12,7 +12,8 @@ CODING_OBJS=coding/adx_decoder.o \
coding/sdx2_decoder.o \
coding/ws_decoder.o \
coding/mpeg_decoder.o \
coding/acm_decoder.o
coding/acm_decoder.o \
coding/nwa_decoder.o
LAYOUT_OBJS=layout/ast_blocked.o \
layout/blocked.o \

View File

@ -20,5 +20,6 @@ libcoding_la_SOURCES += sdx2_decoder.c
libcoding_la_SOURCES += ws_decoder.c
libcoding_la_SOURCES += mpeg_decoder.c
libcoding_la_SOURCES += acm_decoder.c
libcoding_la_SOURCES += nwa_decoder.c
EXTRA_DIST = coding.h g72x_state.h

View File

@ -64,4 +64,6 @@ void decode_mpeg(VGMSTREAMCHANNEL * stream,
void decode_acm(ACMStream * acm, sample * outbuf,
int32_t samples_to_do, int channelspacing);
void decode_nwa(NWAData *nwa, sample *outbuf, int32_t samples_to_do);
#endif

333
src/coding/nwa_decoder.c Normal file
View File

@ -0,0 +1,333 @@
/* originally from nwatowav.cc 2007.7.28 version, which read: */
/*
* Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* jagarl
*
*
*
* Copyright
*
*
* 使
*
* THIS SOFTWARE IS PROVIDED BY KAZUNORI 'jagarl' UENO ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KAZUNORI UENO BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
#include <stdlib.h>
#include "nwa_decoder.h"
/* can serve up 8 bits at a time */
static int
getbits (STREAMFILE *file, off_t *offset, int *shift, int bits)
{
if (*shift > 8)
{
++*offset;
*shift -= 8;
}
int ret = read_16bitLE(*offset,file) >> *shift;
*shift += bits;
return ret & ((1 << bits) - 1); /* mask */
}
NWAData *
open_nwa (STREAMFILE * streamFile, const char *filename)
{
int i;
NWAData * const nwa = malloc(sizeof(NWAData));
if (!nwa) goto fail;
nwa->channels = read_16bitLE(0x00,streamFile);
nwa->bps = read_16bitLE(0x02,streamFile);
nwa->freq = read_32bitLE(0x04,streamFile);
nwa->complevel = read_32bitLE(0x08,streamFile);
nwa->blocks = read_32bitLE(0x10,streamFile);
nwa->datasize = read_32bitLE(0x14,streamFile);
nwa->compdatasize = read_32bitLE(0x18,streamFile);
nwa->samplecount = read_32bitLE(0x1c,streamFile);
nwa->blocksize = read_32bitLE(0x20,streamFile);
nwa->restsize = read_32bitLE(0x24,streamFile);
nwa->offsets = NULL;
nwa->buffer = NULL;
nwa->buffer_readpos = NULL;
nwa->file = NULL;
/* PCM not handled here */
if (nwa->complevel < 0 || nwa->complevel > 5) goto fail;
if (nwa->channels != 1 && nwa->channels != 2) goto fail;
if (nwa->bps != 8 && nwa->bps != 16) goto fail;
if (nwa->blocks <= 0) goto fail;
if (nwa->compdatasize == 0
|| get_streamfile_size(streamFile) != nwa->compdatasize) goto fail;
if (nwa->datasize != nwa->samplecount * (nwa->bps/8)) goto fail;
if (nwa->samplecount !=
(nwa->blocks-1) * nwa->blocksize + nwa->restsize) goto fail;
nwa->offsets = malloc(sizeof(off_t)*nwa->blocks);
if (!nwa->offsets) goto fail;
for (i = 0; i < nwa->blocks; i++)
{
int32_t o = read_32bitLE(0x2c+i*4,streamFile);
if (o < 0) goto fail;
nwa->offsets[i] = o;
}
if (nwa->offsets[nwa->blocks-1] >= nwa->compdatasize) goto fail;
if (nwa->restsize > nwa->blocksize) nwa->buffer =
malloc(sizeof(sample)*nwa->restsize);
else nwa->buffer =
malloc(sizeof(sample)*nwa->blocksize);
if (nwa->buffer == NULL) goto fail;
nwa->buffer_readpos = nwa->buffer;
nwa->samples_in_buffer = 0;
nwa->curblock = 0;
/* if we got this far, it's probably safe */
nwa->file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!nwa->file) goto fail;
return nwa;
fail:
if (nwa)
{
close_nwa(nwa);
free(nwa);
}
return NULL;
}
void
close_nwa(NWAData * nwa)
{
if (!nwa) return;
if (nwa->offsets)
free (nwa->offsets);
nwa->offsets = NULL;
if (nwa->buffer)
free (nwa->buffer);
nwa->buffer = NULL;
if (nwa->file)
close_streamfile (nwa->file);
nwa->file = NULL;
free(nwa);
}
void
reset_nwa(NWAData *nwa)
{
nwa->curblock = 0;
nwa->buffer_readpos = nwa->buffer;
nwa->samples_in_buffer = 0;
}
static int use_runlength(NWAData *nwa)
{
if (nwa->channels == 2 && nwa->bps == 16 && nwa->complevel == 2)
{
/* sw2 */
return 0;
}
if (nwa->complevel == 5)
{
if (nwa->channels == 2) return 0; /* BGM*.nwa in Little Busters! */
return 1; /* Tomoyo After (.nwk koe file) */
}
return 0;
}
static void
nwa_decode_block(NWAData *nwa)
{
/* 今回読み込む/デコードするデータの大きさを得る */
int curblocksize, curcompsize;
if (nwa->curblock != nwa->blocks - 1)
{
curblocksize = nwa->blocksize * (nwa->bps / 8);
curcompsize = nwa->offsets[nwa->curblock + 1] - nwa->offsets[nwa->curblock];
}
else
{
curblocksize = nwa->restsize * (nwa->bps / 8);
curcompsize = nwa->blocksize * (nwa->bps / 8) * 2;
}
nwa->samples_in_buffer = 0;
nwa->buffer_readpos = nwa->buffer;
{
sample d[2];
int i;
int shift = 0;
off_t offset = nwa->offsets[nwa->curblock];
int dsize = curblocksize / (nwa->bps / 8);
int flip_flag = 0; /* stereo 用 */
int runlength = 0;
/* read initial sample value */
for (i=0;i<nwa->channels;i++)
{
if (nwa->bps == 8) { d[i] = read_8bit(offset,nwa->file); }
else /* bps == 16 */
{
d[i] = read_16bitLE(offset,nwa->file);
offset += 2;
}
}
for (i = 0; i < dsize; i++)
{
if (runlength == 0)
{ /* コピーループ中でないならデータ読み込み */
int type = getbits(nwa->file, &offset, &shift, 3);
/* type により分岐0, 1-6, 7 */
if (type == 7)
{
/* 7 : 大きな差分 */
/* RunLength() 有効時CompLevel==5, 音声ファイル) では無効 */
if (getbits(nwa->file, &offset, &shift, 1) == 1)
{
d[flip_flag] = 0; /* 未使用 */
}
else
{
int BITS, SHIFT;
if (nwa->complevel >= 3)
{
BITS = 8;
SHIFT = 9;
}
else
{
BITS = 8 - nwa->complevel;
SHIFT = 2 + 7 + nwa->complevel;
}
const int MASK1 = (1 << (BITS - 1));
const int MASK2 = (1 << (BITS - 1)) - 1;
int b = getbits(nwa->file, &offset, &shift, BITS);
if (b & MASK1)
d[flip_flag] -= (b & MASK2) << SHIFT;
else
d[flip_flag] += (b & MASK2) << SHIFT;
}
}
else if (type != 0)
{
/* 1-6 : 通常の差分 */
int BITS, SHIFT;
if (nwa->complevel >= 3)
{
BITS = nwa->complevel + 3;
SHIFT = 1 + type;
}
else
{
BITS = 5 - nwa->complevel;
SHIFT = 2 + type + nwa->complevel;
}
const int MASK1 = (1 << (BITS - 1));
const int MASK2 = (1 << (BITS - 1)) - 1;
int b = getbits(nwa->file, &offset, &shift, BITS);
if (b & MASK1)
d[flip_flag] -= (b & MASK2) << SHIFT;
else
d[flip_flag] += (b & MASK2) << SHIFT;
}
else
{ /* type == 0 */
/* ランレングス圧縮なしの場合はなにもしない */
if (use_runlength(nwa))
{
/* ランレングス圧縮ありの場合 */
runlength = getbits(nwa->file, &offset, &shift, 1);
if (runlength == 1)
{
runlength = getbits(nwa->file, &offset, &shift, 2);
if (runlength == 3)
{
runlength = getbits(nwa->file, &offset, &shift, 8);
}
}
}
}
}
else
{
runlength--;
}
if (nwa->bps == 8)
{
nwa->buffer[i] = d[flip_flag]*0x100;
}
else
{
nwa->buffer[i] = d[flip_flag];
}
nwa->samples_in_buffer++;
if (nwa->channels == 2)
flip_flag ^= 1; /* channel 切り替え */
}
}
nwa->curblock++;
return;
}
/* interface to vgmstream */
void
decode_nwa(NWAData *nwa, sample *outbuf,
int32_t samples_to_do)
{
while (samples_to_do > 0)
{
int32_t samples_to_read;
if (nwa->samples_in_buffer > 0)
{
samples_to_read = nwa->samples_in_buffer/nwa->channels;
if (samples_to_read > samples_to_do)
samples_to_read = samples_to_do;
memcpy(outbuf,nwa->buffer_readpos,
sizeof(sample)*samples_to_read*nwa->channels);
nwa->buffer_readpos += samples_to_read*nwa->channels;
nwa->samples_in_buffer -= samples_to_read*nwa->channels;
outbuf += samples_to_read*nwa->channels;
samples_to_do -= samples_to_read;
}
else
{
nwa_decode_block(nwa);
}
}
}

66
src/coding/nwa_decoder.h Normal file
View File

@ -0,0 +1,66 @@
/* originally from nwatowav.cc 2007.7.28 version, which read: */
/*
* Copyright 2001-2007 jagarl / Kazunori Ueno <jagarl@creator.club.ne.jp>
* All Rights Reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted.
*
* jagarl
*
*
*
* Copyright
*
*
* 使
*
* THIS SOFTWARE IS PROVIDED BY KAZUNORI 'jagarl' UENO ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL KAZUNORI UENO BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE
* USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
* DAMAGE.
*
*/
#ifndef _NWA_DECODER_H
#define _NWA_DECODER_H
#include "../streamfile.h"
typedef struct NWAData_s
{
int channels;
int bps; /* bits per sample */
int freq; /* samples per second */
int complevel; /* compression level */
int blocks; /* block count */
int datasize; /* all data size */
int compdatasize; /* compressed data size */
int samplecount; /* all samples */
int blocksize; /* samples per block */
int restsize; /* samples of the last block */
int curblock;
off_t *offsets;
STREAMFILE *file;
/* temporarily store samples */
sample *buffer;
sample *buffer_readpos;
int samples_in_buffer;
} NWAData;
NWAData *open_nwa(STREAMFILE *streamFile, const char *filename);
void close_nwa(NWAData *nwa);
void reset_nwa(NWAData *nwa);
#endif

View File

@ -546,6 +546,10 @@
RelativePath=".\coding\g72x_state.h"
>
</File>
<File
RelativePath=".\coding\nwa_decoder.h"
>
</File>
</Filter>
<Filter
Name="Source Files"
@ -586,6 +590,10 @@
RelativePath=".\coding\ngc_dtk_decoder.c"
>
</File>
<File
RelativePath=".\coding\nwa_decoder.c"
>
</File>
<File
RelativePath=".\coding\ogg_vorbis_decoder.c"
>

View File

@ -1,5 +1,6 @@
#include "meta.h"
#include "../util.h"
#include "../coding/nwa_decoder.h"
#include <string.h>
#include <ctype.h>
@ -9,14 +10,7 @@
#define DIRSEP '/'
#endif
/* NWA - Visual Arts streams
*
* This can apparently get a lot more complicated, I'm only handling the
* raw PCM case at the moment (until I see something else).
*
* Kazunori "jagarl" Ueno's nwatowav was helpful, and will probably be used
* to write coding support if it comes to that.
*/
/* NWA - Visual Art's streams */
VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
@ -28,19 +22,38 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
int32_t loop_end_sample = 0;
int nwainfo_ini_found = 0;
int gameexe_ini_found = 0;
int just_pcm = 0;
int comp_level = -2;
nwa_codec_data *data = NULL;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("nwa",filename_extension(filename))) goto fail;
/* check that we're using raw pcm */
channel_count = read_16bitLE(0x00,streamFile);
if (channel_count != 1 && channel_count != 2) goto fail;
/* check if we're using raw pcm */
if (
read_32bitLE(0x08,streamFile)!=-1 || /* compression level */
read_32bitLE(0x10,streamFile)!=0 || /* block count */
read_32bitLE(0x18,streamFile)!=0 || /* compressed data size */
read_32bitLE(0x20,streamFile)!=0 || /* block size */
read_32bitLE(0x24,streamFile)!=0 /* restsize */
) goto fail;
read_32bitLE(0x08,streamFile)==-1 || /* compression level */
read_32bitLE(0x10,streamFile)==0 || /* block count */
read_32bitLE(0x18,streamFile)==0 || /* compressed data size */
read_32bitLE(0x20,streamFile)==0 || /* block size */
read_32bitLE(0x24,streamFile)==0 /* restsize */
)
{
just_pcm = 1;
}
else
{
comp_level = read_32bitLE(0x08,streamFile);
data = malloc(sizeof(nwa_codec_data));
if (!data) goto fail;
data->nwa = open_nwa(streamFile,filename);
if (!data->nwa) goto fail;
}
/* try to locate NWAINFO.INI in the same directory */
{
@ -132,8 +145,6 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
streamFile->get_realname(streamFile,namebase_array,sizeof(namebase_array));
channel_count = read_16bitLE(0x00,streamFile);
ini_lastslash = strrchr(ininame,DIRSEP);
if (!ini_lastslash) {
strncpy(ininame,"Gameexe.ini",sizeof(ininame));
@ -238,22 +249,54 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
switch (read_16bitLE(0x02,streamFile)) {
case 16:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->interleave_block_size = 2;
break;
case 8:
vgmstream->coding_type = coding_PCM8;
vgmstream->interleave_block_size = 1;
break;
default:
goto fail;
}
vgmstream->num_samples = read_32bitLE(0x1c,streamFile)/channel_count;
if (channel_count > 1) {
vgmstream->layout_type = layout_interleave;
} else {
if (just_pcm) {
switch (read_16bitLE(0x02,streamFile)) {
case 8:
vgmstream->coding_type = coding_PCM8;
vgmstream->interleave_block_size = 1;
break;
case 16:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->interleave_block_size = 2;
break;
default:
goto fail;
}
if (channel_count > 1) {
vgmstream->layout_type = layout_interleave;
} else {
vgmstream->layout_type = layout_none;
}
}
else
{
switch (comp_level)
{
case 0:
vgmstream->coding_type = coding_NWA0;
break;
case 1:
vgmstream->coding_type = coding_NWA1;
break;
case 2:
vgmstream->coding_type = coding_NWA2;
break;
case 3:
vgmstream->coding_type = coding_NWA3;
break;
case 4:
vgmstream->coding_type = coding_NWA4;
break;
case 5:
vgmstream->coding_type = coding_NWA5;
break;
default:
goto fail;
break;
}
vgmstream->layout_type = layout_none;
}
@ -274,8 +317,8 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
}
/* open the file for reading by each channel */
{
if (just_pcm) {
/* open the file for reading by each channel */
STREAMFILE *chstreamfile;
/* have both channels use the same buffer, as interleave is so small */
@ -290,11 +333,22 @@ VGMSTREAM * init_vgmstream_nwa(STREAMFILE *streamFile) {
vgmstream->ch[i].offset=0x2c+(off_t)(i*vgmstream->interleave_block_size);
}
}
else
{
vgmstream->codec_data = data;
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
if (data) {
if (data->nwa)
{
close_nwa(data->nwa);
}
free(data);
}
return NULL;
}

View File

@ -222,6 +222,18 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
reset_vgmstream(data->adxs[i]);
}
}
if (
vgmstream->coding_type == coding_NWA0 ||
vgmstream->coding_type == coding_NWA1 ||
vgmstream->coding_type == coding_NWA2 ||
vgmstream->coding_type == coding_NWA3 ||
vgmstream->coding_type == coding_NWA4 ||
vgmstream->coding_type == coding_NWA5
) {
nwa_codec_data *data = vgmstream->codec_data;
reset_nwa(data->nwa);
}
}
/* simply allocate memory for the VGMSTREAM and its channels */
@ -236,6 +248,12 @@ VGMSTREAM * allocate_vgmstream(int channel_count, int looped) {
vgmstream = calloc(1,sizeof(VGMSTREAM));
if (!vgmstream) return NULL;
vgmstream->ch = NULL;
vgmstream->start_ch = NULL;
vgmstream->loop_ch = NULL;
vgmstream->start_vgmstream = NULL;
vgmstream->codec_data = NULL;
start_vgmstream = calloc(1,sizeof(VGMSTREAM));
if (!start_vgmstream) {
@ -360,6 +378,24 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
free(data);
}
vgmstream->codec_data = NULL;
}
if (
vgmstream->coding_type == coding_NWA0 ||
vgmstream->coding_type == coding_NWA1 ||
vgmstream->coding_type == coding_NWA2 ||
vgmstream->coding_type == coding_NWA3 ||
vgmstream->coding_type == coding_NWA4 ||
vgmstream->coding_type == coding_NWA5
) {
nwa_codec_data *data = vgmstream->codec_data;
close_nwa(data->nwa);
free(data);
vgmstream->codec_data = NULL;
}
/* now that the special cases have had their chance, clean up the standard items */
@ -465,6 +501,12 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
case coding_SDX2:
case coding_SDX2_int:
case coding_ACM:
case coding_NWA0:
case coding_NWA1:
case coding_NWA2:
case coding_NWA3:
case coding_NWA4:
case coding_NWA5:
return 1;
case coding_NDS_IMA:
return (vgmstream->interleave_block_size-4)*2;
@ -523,6 +565,12 @@ int get_vgmstream_frame_size(VGMSTREAM * vgmstream) {
case coding_PCM8_SB_int:
case coding_SDX2:
case coding_SDX2_int:
case coding_NWA0:
case coding_NWA1:
case coding_NWA2:
case coding_NWA3:
case coding_NWA4:
case coding_NWA5:
return 1;
case coding_NDS_IMA:
return vgmstream->interleave_block_size;
@ -794,6 +842,17 @@ void decode_vgmstream(VGMSTREAM * vgmstream, int samples_written, int samples_to
case coding_ACM:
/* handled in its own layout, here to quiet compiler */
break;
case coding_NWA0:
case coding_NWA1:
case coding_NWA2:
case coding_NWA3:
case coding_NWA4:
case coding_NWA5:
decode_nwa(((nwa_codec_data*)vgmstream->codec_data)->nwa,
buffer+samples_written*vgmstream->channels,
samples_to_do
);
break;
}
}
@ -1065,6 +1124,24 @@ void describe_vgmstream(VGMSTREAM * vgmstream, char * desc, int length) {
case coding_ACM:
snprintf(temp,TEMPSIZE,"InterPlay ACM");
break;
case coding_NWA0:
snprintf(temp,TEMPSIZE,"NWA DPCM Level 0");
break;
case coding_NWA1:
snprintf(temp,TEMPSIZE,"NWA DPCM Level 1");
break;
case coding_NWA2:
snprintf(temp,TEMPSIZE,"NWA DPCM Level 2");
break;
case coding_NWA3:
snprintf(temp,TEMPSIZE,"NWA DPCM Level 3");
break;
case coding_NWA4:
snprintf(temp,TEMPSIZE,"NWA DPCM Level 4");
break;
case coding_NWA5:
snprintf(temp,TEMPSIZE,"NWA DPCM Level 5");
break;
default:
snprintf(temp,TEMPSIZE,"CANNOT DECODE");
}

View File

@ -21,6 +21,7 @@
#include <mpg123.h>
#endif
#include "coding/acm_decoder.h"
#include "coding/nwa_decoder.h"
/* The encoding type specifies the format the sound data itself takes */
typedef enum {
@ -79,6 +80,13 @@ typedef enum {
#endif
coding_ACM, /* InterPlay ACM */
/* compressed NWA at various levels */
coding_NWA0,
coding_NWA1,
coding_NWA2,
coding_NWA3,
coding_NWA4,
coding_NWA5,
} coding_t;
/* The layout type specifies how the sound data is laid out in the file */
@ -407,6 +415,11 @@ typedef struct {
VGMSTREAM **adxs;
} aix_codec_data;
/* for compressed NWA */
typedef struct {
NWAData *nwa;
} nwa_codec_data;
/* do format detection, return pointer to a usable VGMSTREAM, or NULL on failure */
VGMSTREAM * init_vgmstream(const char * const filename);