mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-18 07:44:43 +01:00
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:
parent
3f6e5595b8
commit
98d11bd9f2
@ -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)
|
||||
|
@ -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 \
|
||||
|
@ -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
|
||||
|
@ -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
333
src/coding/nwa_decoder.c
Normal 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
66
src/coding/nwa_decoder.h
Normal 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
|
@ -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"
|
||||
>
|
||||
|
122
src/meta/nwa.c
122
src/meta/nwa.c
@ -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;
|
||||
}
|
||||
|
@ -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");
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user