Added vgmstream plugin

CQTexperiment
Chris Moeller 2014-02-25 23:50:54 -08:00
parent 85cc09e07f
commit a4d0959623
320 changed files with 46076 additions and 0 deletions

View File

@ -141,6 +141,7 @@
8359009D17FF06570060F3ED /* ArchiveSource.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8359FF3117FEF35D0060F3ED /* ArchiveSource.bundle */; };
8360EF6D17F92E56005208A4 /* HighlyComplete.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8360EF0517F92B24005208A4 /* HighlyComplete.bundle */; };
836D28A818086386005B7299 /* MiniModeMenuTitleTransformer.m in Sources */ = {isa = PBXBuildFile; fileRef = 836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */; };
836F706218BDD1230095E648 /* vgmstream.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836F6B2E18BDB80E0095E648 /* vgmstream.bundle */; };
836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 836FB5471820538800B3AD2D /* Hively.bundle */; };
8375B36517FFEF130092A79F /* Opus.bundle in CopyFiles */ = {isa = PBXBuildFile; fileRef = 8375B05717FFEA410092A79F /* Opus.bundle */; };
83790D501809F4980073CF51 /* NSObject+SPInvocationGrabbing.m in Sources */ = {isa = PBXBuildFile; fileRef = 83790D4D1809F4980073CF51 /* NSObject+SPInvocationGrabbing.m */; };
@ -434,6 +435,13 @@
remoteGlobalIDString = 8360EEE417F92AC8005208A4;
remoteInfo = HighlyComplete;
};
836F6B2D18BDB80E0095E648 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */;
proxyType = 2;
remoteGlobalIDString = 836F6B1018BDB80D0095E648;
remoteInfo = vgmstream;
};
836FB5461820538800B3AD2D /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 836FB5421820538700B3AD2D /* Hively.xcodeproj */;
@ -620,6 +628,7 @@
dstPath = "";
dstSubfolderSpec = 13;
files = (
836F706218BDD1230095E648 /* vgmstream.bundle in CopyFiles */,
836FB5A718206F2500B3AD2D /* Hively.bundle in CopyFiles */,
83A0F4E31816DBF900119DB4 /* playptmod.bundle in CopyFiles */,
83B06704180D579E008E3612 /* MIDI.bundle in CopyFiles */,
@ -866,6 +875,7 @@
8360EF0017F92B23005208A4 /* HighlyComplete.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = HighlyComplete.xcodeproj; path = Plugins/HighlyComplete/HighlyComplete.xcodeproj; sourceTree = "<group>"; };
836D28A618086386005B7299 /* MiniModeMenuTitleTransformer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = MiniModeMenuTitleTransformer.h; path = Window/MiniModeMenuTitleTransformer.h; sourceTree = "<group>"; };
836D28A718086386005B7299 /* MiniModeMenuTitleTransformer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = MiniModeMenuTitleTransformer.m; path = Window/MiniModeMenuTitleTransformer.m; sourceTree = "<group>"; };
836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = vgmstream.xcodeproj; path = Plugins/vgmstream/vgmstream.xcodeproj; sourceTree = "<group>"; };
836FB5421820538700B3AD2D /* Hively.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Hively.xcodeproj; path = Plugins/Hively/Hively.xcodeproj; sourceTree = "<group>"; };
8375B05117FFEA400092A79F /* Opus.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; name = Opus.xcodeproj; path = Plugins/Opus/Opus.xcodeproj; sourceTree = "<group>"; };
83790D4C1809F4980073CF51 /* NSObject+SPInvocationGrabbing.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSObject+SPInvocationGrabbing.h"; sourceTree = "<group>"; };
@ -1221,6 +1231,7 @@
83B0669C180D5668008E3612 /* MIDI.xcodeproj */,
83A0F4841816CE5E00119DB4 /* playptmod.xcodeproj */,
836FB5421820538700B3AD2D /* Hively.xcodeproj */,
836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */,
);
name = PlugIns;
sourceTree = "<group>";
@ -1551,6 +1562,14 @@
name = Products;
sourceTree = "<group>";
};
836F6B2618BDB80D0095E648 /* Products */ = {
isa = PBXGroup;
children = (
836F6B2E18BDB80E0095E648 /* vgmstream.bundle */,
);
name = Products;
sourceTree = "<group>";
};
836FB5431820538700B3AD2D /* Products */ = {
isa = PBXGroup;
children = (
@ -1908,6 +1927,10 @@
ProductGroup = 17C808B10C3BD1C5005707C4 /* Products */;
ProjectRef = 17C808B00C3BD1C5005707C4 /* TagLib.xcodeproj */;
},
{
ProductGroup = 836F6B2618BDB80D0095E648 /* Products */;
ProjectRef = 836F6B2518BDB80D0095E648 /* vgmstream.xcodeproj */;
},
{
ProductGroup = 17C808B80C3BD1D2005707C4 /* Products */;
ProjectRef = 17C808B70C3BD1D2005707C4 /* Vorbis.xcodeproj */;
@ -2044,6 +2067,13 @@
remoteRef = 8360EF0417F92B24005208A4 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
836F6B2E18BDB80E0095E648 /* vgmstream.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;
path = vgmstream.bundle;
remoteRef = 836F6B2D18BDB80E0095E648 /* PBXContainerItemProxy */;
sourceTree = BUILT_PRODUCTS_DIR;
};
836FB5471820538800B3AD2D /* Hively.bundle */ = {
isa = PBXReferenceProxy;
fileType = wrapper.cfbundle;

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,2 @@
/* Localized versions of Info.plist keys */

View File

@ -0,0 +1,33 @@
noinst_LTLIBRARIES = libcoding.la
AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix
libcoding_la_LDFLAGS =
libcoding_la_SOURCES =
libcoding_la_SOURCES += adx_decoder.c
libcoding_la_SOURCES += eaxa_decoder.c
libcoding_la_SOURCES += g721_decoder.c
libcoding_la_SOURCES += ima_decoder.c
libcoding_la_SOURCES += ngc_afc_decoder.c
libcoding_la_SOURCES += ngc_dsp_decoder.c
libcoding_la_SOURCES += ngc_dtk_decoder.c
libcoding_la_SOURCES += pcm_decoder.c
libcoding_la_SOURCES += psx_decoder.c
libcoding_la_SOURCES += xa_decoder.c
libcoding_la_SOURCES += ogg_vorbis_decoder.c
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
libcoding_la_SOURCES += aica_decoder.c
libcoding_la_SOURCES += msadpcm_decoder.c
libcoding_la_SOURCES += nds_procyon_decoder.c
libcoding_la_SOURCES += l5_555_decoder.c
libcoding_la_SOURCES += SASSC_decoder.c
libcoding_la_SOURCES += g7221_decoder.c
libcoding_la_SOURCES += lsf_decoder.c
libcoding_la_SOURCES += mtaf_decoder.c
EXTRA_DIST = coding.h g72x_state.h

View File

@ -0,0 +1,77 @@
#include "coding.h"
#include "../util.h"
/* Activision / EXAKT Entertainment's DPCM for Supercar Street Challenge */
#if 0
To build table:
int32_t bring_round(int32_t v)
{
return v | (v >> 12);
}
for (i=0x00;i<0x20;i++)
SASSC_steps[i] = bring_round(i<<4);
for (i=0x20;i<0x40;i++)
SASSC_steps[i] = bring_round(((i-0x20)*7+0x20)<<4);
for (i=0x40;i<0x60;i++)
SASSC_steps[i] = bring_round(((i-0x40)*24+0x100)<<4);
for (i=0x60;i<0x80;i++)
SASSC_steps[i] = bring_round(((i-0x60)*96+0x400)<<4);
for (i=0x80;i<0xFF;i++)
SASSC_steps[i] = -SASSC_steps[i-0x80];
SASSC_steps[0xFF] = SASSC_steps[0x7F];
#endif
int32_t SASSC_steps[256] =
{
0, 16, 32, 48, 64, 80, 96, 112,
128, 144, 160, 176, 192, 208, 224, 240,
256, 272, 288, 304, 320, 336, 352, 368,
384, 400, 416, 432, 448, 464, 480, 496,
512, 624, 736, 848, 960, 1072, 1184, 1296,
1408, 1520, 1632, 1744, 1856, 1968, 2080, 2192,
2304, 2416, 2528, 2640, 2752, 2864, 2976, 3088,
3200, 3312, 3424, 3536, 3648, 3760, 3872, 3984,
4097, 4481, 4865, 5249, 5633, 6017, 6401, 6785,
7169, 7553, 7937, 8322, 8706, 9090, 9474, 9858,
10242, 10626, 11010, 11394, 11778, 12162, 12547, 12931,
13315, 13699, 14083, 14467, 14851, 15235, 15619, 16003,
16388, 17924, 19460, 20997, 22533, 24069, 25606, 27142,
28679, 30215, 31751, 33288, 34824, 36360, 37897, 39433,
40970, 42506, 44042, 45579, 47115, 48651, 50188, 51724,
53261, 54797, 56333, 57870, 59406, 60942, 62479, 64015,
0, -16, -32, -48, -64, -80, -96, -112,
-128, -144, -160, -176, -192, -208, -224, -240,
-256, -272, -288, -304, -320, -336, -352, -368,
-384, -400, -416, -432, -448, -464, -480, -496,
-512, -624, -736, -848, -960, -1072, -1184, -1296,
-1408, -1520, -1632, -1744, -1856, -1968, -2080, -2192,
-2304, -2416, -2528, -2640, -2752, -2864, -2976, -3088,
-3200, -3312, -3424, -3536, -3648, -3760, -3872, -3984,
-4097, -4481, -4865, -5249, -5633, -6017, -6401, -6785,
-7169, -7553, -7937, -8322, -8706, -9090, -9474, -9858,
-10242, -10626, -11010, -11394, -11778, -12162, -12547, -12931,
-13315, -13699, -14083, -14467, -14851, -15235, -15619, -16003,
-16388, -17924, -19460, -20997, -22533, -24069, -25606, -27142,
-28679, -30215, -31751, -33288, -34824, -36360, -37897, -39433,
-40970, -42506, -44042, -45579, -47115, -48651, -50188, -51724,
-53261, -54797, -56333, -57870, -59406, -60942, -62479, 64015,
};
void decode_SASSC(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
int32_t hist = stream->adpcm_history1_32;
for(i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
hist = hist + SASSC_steps[(uint8_t)read_8bit(stream->offset+i,stream->streamfile)];
outbuf[sample_count] = clamp16(hist);
}
stream->adpcm_history1_32 = hist;
}

View File

@ -0,0 +1,839 @@
/*
* ACM decoder.
*
* Copyright (c) 2004-2008, Marko Kreen
* Copyright (c) 2008, Adam Gashlin
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "coding.h"
#include "../vgmstream.h"
#include "../streamtypes.h"
#include "acm_decoder.h"
#define ACM_EXPECTED_EOF -99
typedef int (*filler_t)(ACMStream *acm, unsigned ind, unsigned col);
/**************************************
* Stream processing
**************************************/
/* NB: bits <= 31! Thus less checks in code. */
static int get_bits_reload(ACMStream *acm, unsigned bits)
{
int got;
unsigned data, b_data, b_avail;
data = acm->bit_data;
got = acm->bit_avail;
bits -= got;
switch (acm->data_len - acm->buf_start_ofs) {
case 0:
b_data = 0;
b_avail = 8;
break;
case 1:
b_data = (uint8_t)read_8bit(acm->buf_start_ofs,acm->streamfile);
b_avail = 8;
acm->buf_start_ofs += 1;
break;
case 2:
b_data = (uint16_t)read_16bitLE(acm->buf_start_ofs,acm->streamfile);
b_avail = 16;
acm->buf_start_ofs += 2;
break;
case 3:
b_data = (uint8_t)read_8bit(acm->buf_start_ofs,acm->streamfile);
b_data |= (int32_t)(uint16_t)read_16bitLE(acm->buf_start_ofs+1,acm->streamfile)<<8;
b_avail = 24;
acm->buf_start_ofs += 3;
break;
case 4:
default:
if (acm->data_len - acm->buf_start_ofs <= 0) {
b_data = 0;
b_avail = 8;
break;
}
b_data = read_32bitLE(acm->buf_start_ofs,acm->streamfile);
b_avail = 32;
acm->buf_start_ofs += 4;
break;
}
data |= (b_data & ((1 << bits) - 1)) << got;
acm->bit_data = b_data >> bits;
acm->bit_avail = b_avail - bits;
return data;
}
#define GET_BITS_NOERR(tmpval, acm, bits) do { \
if (acm->bit_avail >= bits) { \
tmpval = acm->bit_data & ((1 << bits) - 1); \
acm->bit_data >>= bits; \
acm->bit_avail -= bits; \
} else \
tmpval = get_bits_reload(acm, bits); \
} while (0)
#define GET_BITS(res, acm, bits) do { \
int tmpval; \
GET_BITS_NOERR(tmpval, acm, bits); \
if (tmpval < 0) \
return tmpval; \
res = tmpval; \
} while (0)
#define GET_BITS_EXPECT_EOF(res, acm, bits) do { \
int tmpval; \
GET_BITS_NOERR(tmpval, acm, bits); \
if (tmpval < 0) { \
if (tmpval == ACM_ERR_UNEXPECTED_EOF) \
return ACM_EXPECTED_EOF; \
return tmpval; \
} \
res = tmpval; \
} while (0)
/*************************************************
* Table filling
*************************************************/
static const int map_1bit[] = { -1, +1 };
static const int map_2bit_near[] = { -2, -1, +1, +2 };
static const int map_2bit_far[] = { -3, -2, +2, +3 };
static const int map_3bit[] = { -4, -3, -2, -1, +1, +2, +3, +4 };
static int mul_3x3[3*3*3];
static int mul_3x5[5*5*5];
static int mul_2x11[11*11];
static int tables_generated;
static void generate_tables(void)
{
int x1, x2, x3;
if (tables_generated)
return;
for (x3 = 0; x3 < 3; x3++)
for (x2 = 0; x2 < 3; x2++)
for (x1 = 0; x1 < 3; x1++)
mul_3x3[x1 + x2*3 + x3*3*3] =
x1 + (x2 << 4) + (x3 << 8);
for (x3 = 0; x3 < 5; x3++)
for (x2 = 0; x2 < 5; x2++)
for (x1 = 0; x1 < 5; x1++)
mul_3x5[x1 + x2*5 + x3*5*5] =
x1 + (x2 << 4) + (x3 << 8);
for (x2 = 0; x2 < 11; x2++)
for (x1 = 0; x1 < 11; x1++)
mul_2x11[x1 + x2*11] = x1 + (x2 << 4);
tables_generated = 1;
}
/* IOW: (r * acm->subblock_len) + c */
#define set_pos(acm, r, c, idx) do { \
unsigned _pos = ((r) << acm->info.acm_level) + (c); \
acm->block[_pos] = acm->midbuf[idx]; \
} while (0)
/************ Fillers **********/
static int f_zero(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i;
for (i = 0; i < acm->info.acm_rows; i++)
set_pos(acm, i, col, 0);
return 1;
}
static int f_bad(ACMStream *acm, unsigned ind, unsigned col)
{
/* corrupt block? */
return ACM_ERR_CORRUPT;
}
static int f_linear(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned int i;
int b, middle = 1 << (ind - 1);
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, ind);
set_pos(acm, i, col, b - middle);
}
return 1;
}
static int f_k13(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i++, col, 0);
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i, col, 0);
continue;
}
GET_BITS(b, acm, 1);
if (b == 0) {
/* 1, 0 */
set_pos(acm, i, col, 0);
continue;
}
/* 1, 1, ? */
GET_BITS(b, acm, 1);
set_pos(acm, i, col, map_1bit[b]);
}
return 1;
}
static int f_k12(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i, col, 0);
continue;
}
/* 1, ? */
GET_BITS(b, acm, 1);
set_pos(acm, i, col, map_1bit[b]);
}
return 1;
}
static int f_k24(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i++, col, 0);
if (i >= acm->info.acm_rows) break;
set_pos(acm, i, col, 0);
continue;
}
GET_BITS(b, acm, 1);
if (b == 0) {
/* 1, 0 */
set_pos(acm, i, col, 0);
continue;
}
/* 1, 1, ?, ? */
GET_BITS(b, acm, 2);
set_pos(acm, i, col, map_2bit_near[b]);
}
return 1;
}
static int f_k23(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i, col, 0);
continue;
}
/* 1, ?, ? */
GET_BITS(b, acm, 2);
set_pos(acm, i, col, map_2bit_near[b]);
}
return 1;
}
static int f_k35(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i++, col, 0);
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i, col, 0);
continue;
}
GET_BITS(b, acm, 1);
if (b == 0) {
/* 1, 0 */
set_pos(acm, i, col, 0);
continue;
}
GET_BITS(b, acm, 1);
if (b == 0) {
/* 1, 1, 0, ? */
GET_BITS(b, acm, 1);
set_pos(acm, i, col, map_1bit[b]);
continue;
}
/* 1, 1, 1, ?, ? */
GET_BITS(b, acm, 2);
set_pos(acm, i, col, map_2bit_far[b]);
}
return 1;
}
static int f_k34(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i, col, 0);
continue;
}
GET_BITS(b, acm, 1);
if (b == 0) {
/* 1, 0, ? */
GET_BITS(b, acm, 1);
set_pos(acm, i, col, map_1bit[b]);
continue;
}
/* 1, 1, ?, ? */
GET_BITS(b, acm, 2);
set_pos(acm, i, col, map_2bit_far[b]);
}
return 1;
}
static int f_k45(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i, col, 0); i++;
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i, col, 0);
continue;
}
GET_BITS(b, acm, 1);
if (b == 0) {
/* 1, 0 */
set_pos(acm, i, col, 0);
continue;
}
/* 1, 1, ?, ?, ? */
GET_BITS(b, acm, 3);
set_pos(acm, i, col, map_3bit[b]);
}
return 1;
}
static int f_k44(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
for (i = 0; i < acm->info.acm_rows; i++) {
GET_BITS(b, acm, 1);
if (b == 0) {
/* 0 */
set_pos(acm, i, col, 0);
continue;
}
/* 1, ?, ?, ? */
GET_BITS(b, acm, 3);
set_pos(acm, i, col, map_3bit[b]);
}
return 1;
}
static int f_t15(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
int n1, n2, n3;
for (i = 0; i < acm->info.acm_rows; i++) {
/* b = (x1) + (x2 * 3) + (x3 * 9) */
GET_BITS(b, acm, 5);
n1 = (mul_3x3[b] & 0x0F) - 1;
n2 = ((mul_3x3[b] >> 4) & 0x0F) - 1;
n3 = ((mul_3x3[b] >> 8) & 0x0F) - 1;
set_pos(acm, i++, col, n1);
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i++, col, n2);
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i, col, n3);
}
return 1;
}
static int f_t27(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
int n1, n2, n3;
for (i = 0; i < acm->info.acm_rows; i++) {
/* b = (x1) + (x2 * 5) + (x3 * 25) */
GET_BITS(b, acm, 7);
n1 = (mul_3x5[b] & 0x0F) - 2;
n2 = ((mul_3x5[b] >> 4) & 0x0F) - 2;
n3 = ((mul_3x5[b] >> 8) & 0x0F) - 2;
set_pos(acm, i++, col, n1);
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i++, col, n2);
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i, col, n3);
}
return 1;
}
static int f_t37(ACMStream *acm, unsigned ind, unsigned col)
{
unsigned i, b;
int n1, n2;
for (i = 0; i < acm->info.acm_rows; i++) {
/* b = (x1) + (x2 * 11) */
GET_BITS(b, acm, 7);
n1 = (mul_2x11[b] & 0x0F) - 5;
n2 = ((mul_2x11[b] >> 4) & 0x0F) - 5;
set_pos(acm, i++, col, n1);
if (i >= acm->info.acm_rows)
break;
set_pos(acm, i, col, n2);
}
return 1;
}
/****************/
static const filler_t filler_list[] = {
f_zero, f_bad, f_bad, f_linear, /* 0..3 */
f_linear, f_linear, f_linear, f_linear, /* 4..7 */
f_linear, f_linear, f_linear, f_linear, /* 8..11 */
f_linear, f_linear, f_linear, f_linear, /* 12..15 */
f_linear, f_k13, f_k12, f_t15, /* 16..19 */
f_k24, f_k23, f_t27, f_k35, /* 20..23 */
f_k34, f_bad, f_k45, f_k44, /* 24..27 */
f_bad, f_t37, f_bad, f_bad /* 28..31 */
};
static int fill_block(ACMStream *acm)
{
unsigned i, ind;
int err;
for (i = 0; i < acm->info.acm_cols; i++) {
GET_BITS_EXPECT_EOF(ind, acm, 5);
err = filler_list[ind](acm, ind, i);
if (err < 0)
return err;
}
return 1;
}
/**********************************************
* Decompress code
**********************************************/
static void juggle(int *wrap_p, int *block_p, unsigned sub_len, unsigned sub_count)
{
unsigned int i, j;
int *p, r0, r1, r2, r3;
for (i = 0; i < sub_len; i++) {
p = block_p;
r0 = wrap_p[0];
r1 = wrap_p[1];
for (j = 0; j < sub_count/2; j++) {
r2 = *p; *p = r1*2 + (r0 + r2); p += sub_len;
r3 = *p; *p = r2*2 - (r1 + r3); p += sub_len;
r0 = r2; r1 = r3;
}
*wrap_p++ = r0;
*wrap_p++ = r1;
block_p++;
}
}
static void juggle_block(ACMStream *acm)
{
unsigned sub_count, sub_len, todo_count, step_subcount, i;
int *wrap_p, *block_p, *p;
/* juggle only if subblock_len > 1 */
if (acm->info.acm_level == 0)
return;
/* 2048 / subblock_len */
if (acm->info.acm_level > 9)
step_subcount = 1;
else
step_subcount = (2048 >> acm->info.acm_level) - 2;
/* Apply juggle() (rows)x(cols)
* from (step_subcount * 2) x (subblock_len/2)
* to (step_subcount * subblock_len) x (1)
*/
todo_count = acm->info.acm_rows;
block_p = acm->block;
while (1) {
wrap_p = acm->wrapbuf;
sub_count = step_subcount;
if (sub_count > todo_count)
sub_count = todo_count;
sub_len = acm->info.acm_cols / 2;
sub_count *= 2;
juggle(wrap_p, block_p, sub_len, sub_count);
wrap_p += sub_len*2;
for (i = 0, p = block_p; i < sub_count; i++) {
p[0]++;
p += sub_len;
}
while (sub_len > 1) {
sub_len /= 2;
sub_count *= 2;
juggle(wrap_p, block_p, sub_len, sub_count);
wrap_p += sub_len*2;
}
if (todo_count <= step_subcount)
break;
todo_count -= step_subcount;
block_p += step_subcount << acm->info.acm_level;
}
}
/***************************************************************/
static int decode_block(ACMStream *acm)
{
int pwr, count, val, i, x, err;
acm->block_ready = 0;
acm->block_pos = 0;
/* read header */
GET_BITS_EXPECT_EOF(pwr, acm, 4);
GET_BITS_EXPECT_EOF(val, acm, 16);
/* generate tables */
count = 1 << pwr;
for (i = 0, x = 0; i < count; i++) {
acm->midbuf[i] = x;
x += val;
}
for (i = 1, x = -val; i <= count; i++) {
acm->midbuf[-i] = x;
x -= val;
}
/* to_check? */
if ((err = fill_block(acm)) <= 0)
return err;
juggle_block(acm);
acm->block_ready = 1;
return 1;
}
/******************************
* Output formats
******************************/
static unsigned char *out_s16le(int *src, unsigned char *dst, unsigned n, unsigned shift)
{
while (n--) {
int val = *src++ >> shift;
*dst++ = val & 0xFF;
*dst++ = (val >> 8) & 0xFF;
}
return dst;
}
static unsigned char *out_s16be(int *src, unsigned char *dst, unsigned n, unsigned shift)
{
while (n--) {
int val = *src++ >> shift;
*dst++ = (val >> 8) & 0xFF;
*dst++ = val & 0xFF;
}
return dst;
}
static unsigned char *out_u16le(int *src, unsigned char *dst, unsigned n, unsigned shift)
{
while (n--) {
int val = (*src++ >> shift) + 0x8000;
*dst++ = val & 0xFF;
*dst++ = (val >> 8) & 0xFF;
}
return dst;
}
static unsigned char *out_u16be(int *src, unsigned char *dst, unsigned n, unsigned shift)
{
while (n--) {
int val = (*src++ >> shift) + 0x8000;
*dst++ = (val >> 8) & 0xFF;
*dst++ = val & 0xFF;
}
return dst;
}
static int output_values(int *src, unsigned char *dst, int n,
int acm_level, int bigendianp, int wordlen, int sgned)
{
unsigned char *res = NULL;
if (wordlen == 2) {
if (bigendianp == 0) {
if (sgned)
res = out_s16le(src, dst, n, acm_level);
else
res = out_u16le(src, dst, n, acm_level);
} else {
if (sgned)
res = out_s16be(src, dst, n, acm_level);
else
res = out_u16be(src, dst, n, acm_level);
}
}
if (res != NULL)
return res - dst;
return ACM_ERR_BADFMT;
}
/*
* Header parsing.
*/
static int read_header(ACMStream *acm)
{
int tmp;
/* read header */
GET_BITS(acm->info.acm_id, acm, 24);
if (acm->info.acm_id != ACM_ID)
return ACM_ERR_NOT_ACM;
GET_BITS(acm->info.acm_version, acm, 8);
if (acm->info.acm_version != 1)
return ACM_ERR_NOT_ACM;
GET_BITS(acm->total_values, acm, 16);
GET_BITS(tmp, acm, 16);
acm->total_values += tmp << 16;
if (acm->total_values == 0)
return ACM_ERR_NOT_ACM;
GET_BITS(acm->info.channels, acm, 16);
if (acm->info.channels < 1)
return ACM_ERR_NOT_ACM;
/* we play music, music is stereo, though not all headers agree */
acm->info.channels = 2;
GET_BITS(acm->info.rate, acm, 16);
GET_BITS(acm->info.acm_level, acm, 4);
GET_BITS(acm->info.acm_rows, acm, 12);
return 0;
}
/***********************************************
* Public functions
***********************************************/
int acm_open_decoder(ACMStream **res, STREAMFILE *facilitator_file,
const char *const filename)
{
int err = ACM_ERR_OTHER;
ACMStream *acm;
acm = malloc(sizeof(*acm));
if (!acm)
return err;
memset(acm, 0, sizeof(*acm));
acm->streamfile = facilitator_file->open(facilitator_file,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!acm->streamfile)
{
err = ACM_ERR_OPEN;
goto err_out;
}
acm->data_len = get_streamfile_size(acm->streamfile);
/* read header data */
err = ACM_ERR_NOT_ACM;
if (read_header(acm) < 0)
goto err_out;
/* calculate blocks */
acm->info.acm_cols = 1 << acm->info.acm_level;
acm->wrapbuf_len = 2 * acm->info.acm_cols - 2;
acm->block_len = acm->info.acm_rows * acm->info.acm_cols;
/* allocate */
acm->block = malloc(acm->block_len * sizeof(int));
acm->wrapbuf = malloc(acm->wrapbuf_len * sizeof(int));
acm->ampbuf = malloc(0x10000 * sizeof(int));
acm->midbuf = acm->ampbuf + 0x8000;
memset(acm->wrapbuf, 0, acm->wrapbuf_len * sizeof(int));
generate_tables();
*res = acm;
return ACM_OK;
err_out:
acm_close(acm);
return err;
}
int acm_read(ACMStream *acm, void *dst, unsigned numbytes,
int bigendianp, int wordlen, int sgned)
{
int avail, gotbytes = 0, err;
int *src, numwords;
if (wordlen == 2)
numwords = numbytes / 2;
else
return ACM_ERR_BADFMT;
if (acm->stream_pos >= acm->total_values)
return 0;
if (!acm->block_ready) {
err = decode_block(acm);
if (err == ACM_EXPECTED_EOF)
return 0;
if (err < 0)
return err;
}
/* check how many words can be read */
avail = acm->block_len - acm->block_pos;
if (avail < numwords)
numwords = avail;
if (acm->stream_pos + numwords > acm->total_values)
numwords = acm->total_values - acm->stream_pos;
if (acm->info.channels > 1)
numwords -= numwords % acm->info.channels;
/* convert, but if dst == NULL, simulate */
if (dst != NULL) {
src = acm->block + acm->block_pos;
gotbytes = output_values(src, dst, numwords,
acm->info.acm_level,
bigendianp, wordlen, sgned);
} else
gotbytes = numwords * wordlen;
if (gotbytes >= 0) {
acm->stream_pos += numwords;
acm->block_pos += numwords;
if (acm->block_pos == acm->block_len)
acm->block_ready = 0;
}
return gotbytes;
}
void acm_close(ACMStream *acm)
{
if (acm == NULL)
return;
if (acm->streamfile) {
close_streamfile(acm->streamfile);
acm->streamfile = NULL;
}
if (acm->block)
free(acm->block);
if (acm->wrapbuf)
free(acm->wrapbuf);
if (acm->ampbuf)
free(acm->ampbuf);
free(acm);
}
void acm_reset(ACMStream *acm)
{
acm->bit_avail = 0;
acm->bit_data = 0;
acm->stream_pos = 0;
acm->block_pos = 0;
acm->block_ready = 0;
acm->buf_start_ofs = ACM_HEADER_LEN;
memset(acm->wrapbuf, 0, acm->wrapbuf_len * sizeof(int));
}
/* interface to vgmstream */
void decode_acm(ACMStream * acm, sample * outbuf,
int32_t samples_to_do, int channelspacing) {
int32_t samples_read = 0;
while (samples_read < samples_to_do) {
int32_t bytes_read_just_now;
bytes_read_just_now =
acm_read(acm,(char*)(
outbuf+samples_read*channelspacing),
(samples_to_do-samples_read)*sizeof(sample)*
channelspacing,0,2,1);
if (bytes_read_just_now > 0) {
samples_read +=
bytes_read_just_now/sizeof(sample)/channelspacing;
} else {
return;
}
}
}

View File

@ -0,0 +1,91 @@
/*
* libacm - Interplay ACM audio decoder.
*
* Copyright (c) 2004-2008, Marko Kreen
* Copyright (c) 2008, Adam Gashlin
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
* ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
* ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#ifndef __LIBACM_H
#define __LIBACM_H
#ifdef BUILD_VGMSTREAM
#include "../streamfile.h"
#else
#include "streamfile.h"
#endif
#define LIBACM_VERSION "1.0-svn"
#define ACM_ID 0x032897
#define ACM_WORD 2
#define ACM_HEADER_LEN 14
#define ACM_OK 0
#define ACM_ERR_OTHER -1
#define ACM_ERR_OPEN -2
#define ACM_ERR_NOT_ACM -3
#define ACM_ERR_READ_ERR -4
#define ACM_ERR_BADFMT -5
#define ACM_ERR_CORRUPT -6
#define ACM_ERR_UNEXPECTED_EOF -7
#define ACM_ERR_NOT_SEEKABLE -8
typedef struct ACMInfo {
unsigned channels;
unsigned rate;
unsigned acm_id;
unsigned acm_version;
unsigned acm_level;
unsigned acm_cols; /* 1 << acm_level */
unsigned acm_rows;
} ACMInfo;
struct ACMStream {
ACMInfo info;
unsigned total_values;
/* acm data stream */
STREAMFILE *streamfile;
unsigned data_len;
/* acm stream buffer */
unsigned bit_avail;
unsigned bit_data;
unsigned buf_start_ofs;
/* block lengths (in samples) */
unsigned block_len;
unsigned wrapbuf_len;
/* buffers */
int *block;
int *wrapbuf;
int *ampbuf;
int *midbuf; /* pointer into ampbuf */
/* result */
unsigned block_ready:1;
unsigned file_eof:1;
unsigned stream_pos; /* in words. absolute */
unsigned block_pos; /* in words, relative */
};
typedef struct ACMStream ACMStream;
/* decode.c */
int acm_open_decoder(ACMStream **res, STREAMFILE *facilitator_file, const char *const filename);
int acm_read(ACMStream *acm, void *buf, unsigned nbytes,
int bigendianp, int wordlen, int sgned);
void acm_close(ACMStream *acm);
void acm_reset(ACMStream *acm);
#endif

View File

@ -0,0 +1,81 @@
#include "coding.h"
#include "../util.h"
void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
int framesin = first_sample/32;
int32_t scale = read_16bitBE(stream->offset+framesin*18,stream->streamfile) + 1;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int coef1 = stream->adpcm_coef[0];
int coef2 = stream->adpcm_coef[1];
first_sample = first_sample%32;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(stream->offset+framesin*18+2+i/2,stream->streamfile);
outbuf[sample_count] = clamp16(
(i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale +
((coef1 * hist1 + coef2 * hist2) >> 12)
);
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2;
}
void adx_next_key(VGMSTREAMCHANNEL * stream)
{
stream->adx_xor = ( stream->adx_xor * stream->adx_mult + stream->adx_add ) & 0x7fff;
}
void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
int framesin = first_sample/32;
int32_t scale = ((read_16bitBE(stream->offset+framesin*18,stream->streamfile) ^ stream->adx_xor)&0x1fff) + 1;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int coef1 = stream->adpcm_coef[0];
int coef2 = stream->adpcm_coef[1];
first_sample = first_sample%32;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(stream->offset+framesin*18+2+i/2,stream->streamfile);
outbuf[sample_count] = clamp16(
(i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale +
((coef1 * hist1 + coef2 * hist2) >> 12)
);
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2;
if (!(i % 32)) {
for (i=0;i<stream->adx_channels;i++)
{
adx_next_key(stream);
}
}
}

View File

@ -0,0 +1,50 @@
#include "../util.h"
#include "coding.h"
/* fixed point (.8) amount to scale the current step size by */
/* part of the same series as used in MS ADPCM "ADPCMTable" */
static const unsigned int scale_step[16] =
{
230, 230, 230, 230, 307, 409, 512, 614,
230, 230, 230, 230, 307, 409, 512, 614
};
/* expand an unsigned four bit delta to a wider signed range */
static const int scale_delta[16] =
{
1, 3, 5, 7, 9, 11, 13, 15,
-1, -3, -5, -7, -9,-11,-13,-15
};
/* Yamaha AICA ADPCM (as seen in Dreamcast) */
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
int32_t hist1 = stream->adpcm_history1_16;
unsigned long step_size = stream->adpcm_step_index;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_nibble =
(
(unsigned)read_8bit(stream->offset+i/2,stream->streamfile) >>
(i&1?4:0)
)&0xf;
int32_t sample_delta = (int32_t)step_size * scale_delta[sample_nibble];
int32_t new_sample;
new_sample = hist1 + sample_delta/8;
outbuf[sample_count] = clamp16(new_sample);
hist1 = outbuf[sample_count];
step_size = (step_size * scale_step[sample_nibble])/0x100;
if (step_size < 0x7f) step_size = 0x7f;
if (step_size > 0x6000) step_size = 0x6000;
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_step_index = step_size;
}

View File

@ -0,0 +1,40 @@
#include "../vgmstream.h"
#ifdef VGM_USE_MAIATRAC3PLUS
#include "maiatrac3plus.h"
#include "coding.h"
#include "../util.h"
void decode_at3plus(VGMSTREAM * vgmstream,
sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
VGMSTREAMCHANNEL *ch = &vgmstream->ch[0];
maiatrac3plus_codec_data *data = vgmstream->codec_data;
int i;
int first_sample = vgmstream->samples_into_block % 2048;
if (0 == channel && (0 == first_sample || data->samples_discard == first_sample))
{
uint8_t code_buffer[0x8000];
int blocks_to_decode = 1;
int max_blocks_to_decode = (ch->offset - ch->channel_start_offset) / vgmstream->interleave_block_size + 1;
if (data->samples_discard) blocks_to_decode = 8;
if (blocks_to_decode > max_blocks_to_decode) blocks_to_decode = max_blocks_to_decode;
while (blocks_to_decode--) {
ch->streamfile->read(ch->streamfile, code_buffer, ch->offset - blocks_to_decode * vgmstream->interleave_block_size, vgmstream->interleave_block_size);
Atrac3plusDecoder_decodeFrame(data->handle, code_buffer, vgmstream->interleave_block_size, &data->channels, (void**)&data->buffer);
}
data->samples_discard = 0;
}
for (i = 0; i < samples_to_do; i++)
{
outbuf[i*channelspacing] = data->buffer[(first_sample+i)*data->channels+channel];
}
if (0 == channel && 2048 == first_sample + samples_to_do) {
ch->offset += vgmstream->interleave_block_size;
}
}
#endif

View File

@ -0,0 +1,128 @@
#ifndef _CODING_H
#define _CODING_H
#include "../vgmstream.h"
void decode_adx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_adx_enc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void adx_next_key(VGMSTREAMCHANNEL * stream);
void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
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_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_int_xbox_ima(VGMSTREAM * vgmstream,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_eacs_ima(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem);
int32_t dsp_nibbles_to_samples(int32_t nibbles);
void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_pcm16LE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16LE_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm16BE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_invert_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_psx_badflags(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ffxi_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_xa(VGMSTREAM * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void init_get_high_nibble(VGMSTREAM * vgmstream);
void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel);
void decode_ea_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
#ifdef VGM_USE_VORBIS
void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
#endif
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels);
#endif
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
#ifdef VGM_USE_MPEG
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL * stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do);
mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels);
long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi);
void decode_mpeg(VGMSTREAMCHANNEL * stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do, int channels);
#endif
#ifdef VGM_USE_G7221
void decode_g7221(VGMSTREAM *vgmstream,
sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
#endif
#ifdef VGM_USE_MAIATRAC3PLUS
void decode_at3plus(VGMSTREAM *vgmstream,
sample * outbuf, int channelspacing, int32_t samples_to_do, int channel);
#endif
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);
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels);
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do);
void decode_aica(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_SASSC(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels);
#endif

View File

@ -0,0 +1,170 @@
#include "coding.h"
#include "../util.h"
long EA_XA_TABLE[28] = {0,0,240,0,460,-208,0x0188,-220,
0x0000,0x0000,0x00F0,0x0000,
0x01CC,0x0000,0x0188,0x0000,
0x0000,0x0000,0x0000,0x0000,
-208,-1,-220,-1,
0x0000,0x0000,0x0000,0x3F70};
long EA_TABLE[20]= { 0x00000000, 0x000000F0, 0x000001CC, 0x00000188,
0x00000000, 0x00000000, 0xFFFFFF30, 0xFFFFFF24,
0x00000000, 0x00000001, 0x00000003, 0x00000004,
0x00000007, 0x00000008, 0x0000000A, 0x0000000B,
0x00000000, 0xFFFFFFFF, 0xFFFFFFFD, 0xFFFFFFFC};
void decode_eaxa(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
uint8_t frame_info;
int32_t sample_count;
long coef1,coef2;
int i,shift;
off_t channel_offset=stream->channel_start_offset;
first_sample = first_sample%28;
frame_info = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile);
if(frame_info==0xEE) {
channel_offset++;
stream->adpcm_history1_32 = read_16bitBE(stream->offset+channel_offset,stream->streamfile);
stream->adpcm_history2_32 = read_16bitBE(stream->offset+channel_offset+2,stream->streamfile);
channel_offset+=4;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
outbuf[sample_count]=read_16bitBE(stream->offset+channel_offset,stream->streamfile);
channel_offset+=2;
}
// Only increment offset on complete frame
if(channel_offset-stream->channel_start_offset==(2*28)+5)
stream->channel_start_offset+=(2*28)+5;
} else {
coef1 = EA_XA_TABLE[((frame_info >> 4) & 0x0F) << 1];
coef2 = EA_XA_TABLE[(((frame_info >> 4) & 0x0F) << 1) + 1];
shift = (frame_info & 0x0F) + 8;
channel_offset++;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i/2,stream->streamfile);
int32_t sample = ((((i&1?
sample_byte & 0x0F:
sample_byte >> 4
) << 0x1C) >> shift) +
(coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32)) >> 8;
outbuf[sample_count] = clamp16(sample);
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
}
channel_offset+=i/2;
// Only increment offset on complete frame
if(channel_offset-stream->channel_start_offset==0x0F)
stream->channel_start_offset+=0x0F;
}
}
void decode_ea_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
uint8_t frame_info;
int32_t sample_count;
long coef1,coef2;
int i,shift;
VGMSTREAMCHANNEL *stream = &(vgmstream->ch[channel]);
off_t channel_offset=stream->channel_start_offset;
vgmstream->get_high_nibble=!vgmstream->get_high_nibble;
first_sample = first_sample%28;
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
coef1 = EA_TABLE[(vgmstream->get_high_nibble? frame_info & 0x0F: frame_info >> 4)];
coef2 = EA_TABLE[(vgmstream->get_high_nibble? frame_info & 0x0F: frame_info >> 4) + 4];
channel_offset++;
frame_info = read_8bit(stream->offset+channel_offset,stream->streamfile);
shift = (vgmstream->get_high_nibble? frame_info & 0x0F : frame_info >> 4)+8;
channel_offset++;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte;
int32_t sample;
sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset+i,stream->streamfile);
sample = ((((vgmstream->get_high_nibble?
sample_byte & 0x0F:
sample_byte >> 4
) << 0x1C) >> shift) +
(coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32) + 0x80) >> 8;
outbuf[sample_count] = clamp16(sample);
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
}
channel_offset+=i;
// Only increment offset on complete frame
if(channel_offset-stream->channel_start_offset==0x1E)
stream->channel_start_offset+=0x1E;
}
void decode_maxis_adpcm(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
uint8_t frame_info;
int32_t sample_count;
long coef1,coef2;
int i,shift;
int frameSize = channelspacing*15;//mono samples have a frame of 15, stereo files have frames of 30
VGMSTREAMCHANNEL *stream = &(vgmstream->ch[channel]);
off_t channel_offset=stream->channel_start_offset;
first_sample = first_sample%28;
frame_info = read_8bit(channel_offset,stream->streamfile);
coef1 = EA_TABLE[frame_info >> 4];
coef2 = EA_TABLE[(frame_info >> 4) + 4];
shift = (frame_info & 0x0F)+8;
channel_offset+=channelspacing;
//stream->offset = first_sample*channelspacing/2;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t sample_byte;
int32_t sample;
sample_byte = (uint8_t)read_8bit(stream->offset+channel_offset,stream->streamfile);
sample = (((((i&1)?
sample_byte & 0x0F:
sample_byte >> 4
) << 0x1C) >> shift) +
(coef1 * stream->adpcm_history1_32) + (coef2 * stream->adpcm_history2_32) + 0x80) >> 8;
outbuf[sample_count] = clamp16(sample);
stream->adpcm_history2_32 = stream->adpcm_history1_32;
stream->adpcm_history1_32 = sample;
if(i&1)
stream->offset+=channelspacing;
}
channel_offset+=i;
// Only increment offset on complete frame
if(channel_offset-stream->channel_start_offset==frameSize) {
stream->channel_start_offset+=frameSize;
stream->offset=0;
}
}

View File

@ -0,0 +1,471 @@
/* G.721 decoder, from Sun's public domain CCITT-ADPCM sources,
* retrieved from ftp://ftp.cwi.nl/pub/audio/ccitt-adpcm.tar.gz
*
* For reference, here's the original license:
*
* This source code is a product of Sun Microsystems, Inc. and is provided
* for unrestricted use. Users may copy or modify this source code without
* charge.
*
* SUN SOURCE CODE IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING
* THE WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
* PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
*
* Sun source code is provided with no support and without any obligation on
* the part of Sun Microsystems, Inc. to assist in its use, correction,
* modification or enhancement.
*
* SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
* INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY THIS SOFTWARE
* OR ANY PART THEREOF.
*
* In no event will Sun Microsystems, Inc. be liable for any lost revenue
* or profits or other special, indirect and consequential damages, even if
* Sun has been advised of the possibility of such damages.
*
* Sun Microsystems, Inc.
* 2550 Garcia Avenue
* Mountain View, California 94043
*
*/
#include "coding.h"
#include "../util.h"
static short power2[15] = {1, 2, 4, 8, 0x10, 0x20, 0x40, 0x80,
0x100, 0x200, 0x400, 0x800, 0x1000, 0x2000, 0x4000};
/*
* quan()
*
* quantizes the input val against the table of size short integers.
* It returns i if table[i - 1] <= val < table[i].
*
* Using linear search for simple coding.
*/
static int
quan(
int val,
short *table,
int size)
{
int i;
for (i = 0; i < size; i++)
if (val < *table++)
break;
return (i);
}
/*
* fmult()
*
* returns the integer product of the 14-bit integer "an" and
* "floating point" representation (4-bit exponent, 6-bit mantessa) "srn".
*/
static int
fmult(
int an,
int srn)
{
short anmag, anexp, anmant;
short wanexp, wanmant;
short retval;
anmag = (an > 0) ? an : ((-an) & 0x1FFF);
anexp = quan(anmag, power2, 15) - 6;
anmant = (anmag == 0) ? 32 :
(anexp >= 0) ? anmag >> anexp : anmag << -anexp;
wanexp = anexp + ((srn >> 6) & 0xF) - 13;
wanmant = (anmant * (srn & 077) + 0x30) >> 4;
retval = (wanexp >= 0) ? ((wanmant << wanexp) & 0x7FFF) :
(wanmant >> -wanexp);
return (((an ^ srn) < 0) ? -retval : retval);
}
/*
* g72x_init_state()
*
* This routine initializes and/or resets the g72x_state structure
* pointed to by 'state_ptr'.
* All the initial state values are specified in the CCITT G.721 document.
*/
void
g72x_init_state(
struct g72x_state *state_ptr)
{
int cnta;
state_ptr->yl = 34816;
state_ptr->yu = 544;
state_ptr->dms = 0;
state_ptr->dml = 0;
state_ptr->ap = 0;
for (cnta = 0; cnta < 2; cnta++) {
state_ptr->a[cnta] = 0;
state_ptr->pk[cnta] = 0;
state_ptr->sr[cnta] = 32;
}
for (cnta = 0; cnta < 6; cnta++) {
state_ptr->b[cnta] = 0;
state_ptr->dq[cnta] = 32;
}
state_ptr->td = 0;
}
/*
* predictor_zero()
*
* computes the estimated signal from 6-zero predictor.
*
*/
int
predictor_zero(
struct g72x_state *state_ptr)
{
int i;
int sezi;
sezi = fmult(state_ptr->b[0] >> 2, state_ptr->dq[0]);
for (i = 1; i < 6; i++) /* ACCUM */
sezi += fmult(state_ptr->b[i] >> 2, state_ptr->dq[i]);
return (sezi);
}
/*
* predictor_pole()
*
* computes the estimated signal from 2-pole predictor.
*
*/
int
predictor_pole(
struct g72x_state *state_ptr)
{
return (fmult(state_ptr->a[1] >> 2, state_ptr->sr[1]) +
fmult(state_ptr->a[0] >> 2, state_ptr->sr[0]));
}
/*
* step_size()
*
* computes the quantization step size of the adaptive quantizer.
*
*/
int
step_size(
struct g72x_state *state_ptr)
{
int y;
int dif;
int al;
if (state_ptr->ap >= 256)
return (state_ptr->yu);
else {
y = state_ptr->yl >> 6;
dif = state_ptr->yu - y;
al = state_ptr->ap >> 2;
if (dif > 0)
y += (dif * al) >> 6;
else if (dif < 0)
y += (dif * al + 0x3F) >> 6;
return (y);
}
}
/*
* reconstruct()
*
* Returns reconstructed difference signal 'dq' obtained from
* codeword 'i' and quantization step size scale factor 'y'.
* Multiplication is performed in log base 2 domain as addition.
*/
int
reconstruct(
int sign, /* 0 for non-negative value */
int dqln, /* G.72x codeword */
int y) /* Step size multiplier */
{
short dql; /* Log of 'dq' magnitude */
short dex; /* Integer part of log */
short dqt;
short dq; /* Reconstructed difference signal sample */
dql = dqln + (y >> 2); /* ADDA */
if (dql < 0) {
return ((sign) ? -0x8000 : 0);
} else { /* ANTILOG */
dex = (dql >> 7) & 15;
dqt = 128 + (dql & 127);
dq = (dqt << 7) >> (14 - dex);
return ((sign) ? (dq - 0x8000) : dq);
}
}
/*
* update()
*
* updates the state variables for each output code
*/
void
update(
/*int code_size,*/ /* distinguish 723_40 with others */
int y, /* quantizer step size */
int wi, /* scale factor multiplier */
int fi, /* for long/short term energies */
int dq, /* quantized prediction difference */
int sr, /* reconstructed signal */
int dqsez, /* difference from 2-pole predictor */
struct g72x_state *state_ptr) /* coder state pointer */
{
int cnt;
short mag, exp; /* Adaptive predictor, FLOAT A */
short a2p; /* LIMC */
short a1ul; /* UPA1 */
short pks1; /* UPA2 */
short fa1;
char tr; /* tone/transition detector */
short ylint, thr2, dqthr;
short ylfrac, thr1;
short pk0;
pk0 = (dqsez < 0) ? 1 : 0; /* needed in updating predictor poles */
mag = dq & 0x7FFF; /* prediction difference magnitude */
/* TRANS */
ylint = state_ptr->yl >> 15; /* exponent part of yl */
ylfrac = (state_ptr->yl >> 10) & 0x1F; /* fractional part of yl */
thr1 = (32 + ylfrac) << ylint; /* threshold */
thr2 = (ylint > 9) ? 31 << 10 : thr1; /* limit thr2 to 31 << 10 */
dqthr = (thr2 + (thr2 >> 1)) >> 1; /* dqthr = 0.75 * thr2 */
if (state_ptr->td == 0) /* signal supposed voice */
tr = 0;
else if (mag <= dqthr) /* supposed data, but small mag */
tr = 0; /* treated as voice */
else /* signal is data (modem) */
tr = 1;
/*
* Quantizer scale factor adaptation.
*/
/* FUNCTW & FILTD & DELAY */
/* update non-steady state step size multiplier */
state_ptr->yu = y + ((wi - y) >> 5);
/* LIMB */
if (state_ptr->yu < 544) /* 544 <= yu <= 5120 */
state_ptr->yu = 544;
else if (state_ptr->yu > 5120)
state_ptr->yu = 5120;
/* FILTE & DELAY */
/* update steady state step size multiplier */
state_ptr->yl += state_ptr->yu + ((-state_ptr->yl) >> 6);
/*
* Adaptive predictor coefficients.
*/
if (tr == 1) { /* reset a's and b's for modem signal */
state_ptr->a[0] = 0;
state_ptr->a[1] = 0;
state_ptr->b[0] = 0;
state_ptr->b[1] = 0;
state_ptr->b[2] = 0;
state_ptr->b[3] = 0;
state_ptr->b[4] = 0;
state_ptr->b[5] = 0;
a2p=0; /* won't be used, clear warning */
} else { /* update a's and b's */
pks1 = pk0 ^ state_ptr->pk[0]; /* UPA2 */
/* update predictor pole a[1] */
a2p = state_ptr->a[1] - (state_ptr->a[1] >> 7);
if (dqsez != 0) {
fa1 = (pks1) ? state_ptr->a[0] : -state_ptr->a[0];
if (fa1 < -8191) /* a2p = function of fa1 */
a2p -= 0x100;
else if (fa1 > 8191)
a2p += 0xFF;
else
a2p += fa1 >> 5;
if (pk0 ^ state_ptr->pk[1])
/* LIMC */
if (a2p <= -12160)
a2p = -12288;
else if (a2p >= 12416)
a2p = 12288;
else
a2p -= 0x80;
else if (a2p <= -12416)
a2p = -12288;
else if (a2p >= 12160)
a2p = 12288;
else
a2p += 0x80;
}
/* TRIGB & DELAY */
state_ptr->a[1] = a2p;
/* UPA1 */
/* update predictor pole a[0] */
state_ptr->a[0] -= state_ptr->a[0] >> 8;
if (dqsez != 0) {
if (pks1 == 0)
state_ptr->a[0] += 192;
else
state_ptr->a[0] -= 192;
}
/* LIMD */
a1ul = 15360 - a2p;
if (state_ptr->a[0] < -a1ul)
state_ptr->a[0] = -a1ul;
else if (state_ptr->a[0] > a1ul)
state_ptr->a[0] = a1ul;
/* UPB : update predictor zeros b[6] */
for (cnt = 0; cnt < 6; cnt++) {
/*if (code_size == 5)*/ /* for 40Kbps G.723 */
/* state_ptr->b[cnt] -= state_ptr->b[cnt] >> 9;*/
/*else*/ /* for G.721 and 24Kbps G.723 */
state_ptr->b[cnt] -= state_ptr->b[cnt] >> 8;
if (dq & 0x7FFF) { /* XOR */
if ((dq ^ state_ptr->dq[cnt]) >= 0)
state_ptr->b[cnt] += 128;
else
state_ptr->b[cnt] -= 128;
}
}
}
for (cnt = 5; cnt > 0; cnt--)
state_ptr->dq[cnt] = state_ptr->dq[cnt-1];
/* FLOAT A : convert dq[0] to 4-bit exp, 6-bit mantissa f.p. */
if (mag == 0) {
state_ptr->dq[0] = (dq >= 0) ? 0x20 : 0xFC20;
} else {
exp = quan(mag, power2, 15);
state_ptr->dq[0] = (dq >= 0) ?
(exp << 6) + ((mag << 6) >> exp) :
(exp << 6) + ((mag << 6) >> exp) - 0x400;
}
state_ptr->sr[1] = state_ptr->sr[0];
/* FLOAT B : convert sr to 4-bit exp., 6-bit mantissa f.p. */
if (sr == 0) {
state_ptr->sr[0] = 0x20;
} else if (sr > 0) {
exp = quan(sr, power2, 15);
state_ptr->sr[0] = (exp << 6) + ((sr << 6) >> exp);
} else if (sr > -32768) {
mag = -sr;
exp = quan(mag, power2, 15);
state_ptr->sr[0] = (exp << 6) + ((mag << 6) >> exp) - 0x400;
} else
state_ptr->sr[0] = 0xFC20;
/* DELAY A */
state_ptr->pk[1] = state_ptr->pk[0];
state_ptr->pk[0] = pk0;
/* TONE */
if (tr == 1) /* this sample has been treated as data */
state_ptr->td = 0; /* next one will be treated as voice */
else if (a2p < -11776) /* small sample-to-sample correlation */
state_ptr->td = 1; /* signal may be data */
else /* signal is voice */
state_ptr->td = 0;
/*
* Adaptation speed control.
*/
state_ptr->dms += (fi - state_ptr->dms) >> 5; /* FILTA */
state_ptr->dml += (((fi << 2) - state_ptr->dml) >> 7); /* FILTB */
if (tr == 1)
state_ptr->ap = 256;
else if (y < 1536) /* SUBTC */
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (state_ptr->td == 1)
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else if (abs((state_ptr->dms << 2) - state_ptr->dml) >=
(state_ptr->dml >> 3))
state_ptr->ap += (0x200 - state_ptr->ap) >> 4;
else
state_ptr->ap += (-state_ptr->ap) >> 4;
}
/*
* Maps G.721 code word to reconstructed scale factor normalized log
* magnitude values.
*/
static short _dqlntab[16] = {-2048, 4, 135, 213, 273, 323, 373, 425,
425, 373, 323, 273, 213, 135, 4, -2048};
/* Maps G.721 code word to log of scale factor multiplier. */
static short _witab[16] = {-12, 18, 41, 64, 112, 198, 355, 1122,
1122, 355, 198, 112, 64, 41, 18, -12};
/*
* Maps G.721 code words to a set of values whose long and short
* term averages are computed and then compared to give an indication
* how stationary (steady state) the signal is.
*/
static short _fitab[16] = {0, 0, 0, 0x200, 0x200, 0x200, 0x600, 0xE00,
0xE00, 0x600, 0x200, 0x200, 0x200, 0, 0, 0};
/*
* g721_decoder()
*
* Description:
*
* Decodes a 4-bit code of G.721 encoded data of i and
* returns the resulting linear PCM, A-law or u-law value.
* return -1 for unknown out_coding value.
*/
int
g721_decoder(
int i,
struct g72x_state *state_ptr)
{
short sezi, sei, sez, se; /* ACCUM */
short y; /* MIX */
short sr; /* ADDB */
short dq;
short dqsez;
i &= 0x0f; /* mask to get proper bits */
sezi = predictor_zero(state_ptr);
sez = sezi >> 1;
sei = sezi + predictor_pole(state_ptr);
se = sei >> 1; /* se = estimated signal */
y = step_size(state_ptr); /* dynamic quantizer step size */
dq = reconstruct(i & 0x08, _dqlntab[i], y); /* quantized diff. */
sr = (dq < 0) ? (se - (dq & 0x3FFF)) : se + dq; /* reconst. signal */
dqsez = sr - se + sez; /* pole prediction diff. */
update(y, _witab[i] << 5, _fitab[i], dq, sr, dqsez, state_ptr);
return (sr << 2); /* sr was 14-bit dynamic range */
}
void decode_g721(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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]=
g721_decoder(
read_8bit(stream->offset+i/2,stream->streamfile)>>(i&1?4:0),
&(stream->g72x_state)
);
}
}

View File

@ -0,0 +1,28 @@
#include "../vgmstream.h"
#ifdef VGM_USE_G7221
#include "g7221.h"
#include "coding.h"
#include "../util.h"
void decode_g7221(VGMSTREAM * vgmstream,
sample * outbuf, int channelspacing, int32_t samples_to_do, int channel) {
VGMSTREAMCHANNEL *ch = &vgmstream->ch[channel];
g7221_codec_data *data = vgmstream->codec_data;
g7221_codec_data *ch_data = &data[channel];
int i;
if (0 == vgmstream->samples_into_block)
{
int16_t code_buffer[960/8];
vgmstream->ch[channel].streamfile->read(ch->streamfile, (uint8_t*)code_buffer, ch->offset, vgmstream->interleave_block_size);
g7221_decode_frame(ch_data->handle, code_buffer, ch_data->buffer);
}
for (i = 0; i < samples_to_do; i++)
{
outbuf[i*channelspacing] = ch_data->buffer[vgmstream->samples_into_block+i];
}
}
#endif

View File

@ -0,0 +1,35 @@
/*
* streamtypes.h - widely used type definitions
*/
#ifndef _G72X_STATE_H
#define _G72X_STATE_H
struct g72x_state {
long yl; /* Locked or steady state step size multiplier. */
short yu; /* Unlocked or non-steady state step size multiplier. */
short dms; /* Short term energy estimate. */
short dml; /* Long term energy estimate. */
short ap; /* Linear weighting coefficient of 'yl' and 'yu'. */
short a[2]; /* Coefficients of pole portion of prediction filter. */
short b[6]; /* Coefficients of zero portion of prediction filter. */
short pk[2]; /*
* Signs of previous two samples of a partially
* reconstructed signal.
*/
short dq[6]; /*
* Previous 6 samples of the quantized difference
* signal represented in an internal floating point
* format.
*/
short sr[2]; /*
* Previous 2 samples of the quantized difference
* signal represented in an internal floating point
* format.
*/
char td; /* delayed tone detect, new in 1988 version */
};
#endif

View File

@ -0,0 +1,637 @@
#include "../util.h"
#include "coding.h"
const int32_t ADPCMTable[89] =
{
7, 8, 9, 10, 11, 12, 13, 14,
16, 17, 19, 21, 23, 25, 28, 31,
34, 37, 41, 45, 50, 55, 60, 66,
73, 80, 88, 97, 107, 118, 130, 143,
157, 173, 190, 209, 230, 253, 279, 307,
337, 371, 408, 449, 494, 544, 598, 658,
724, 796, 876, 963, 1060, 1166, 1282, 1411,
1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484,
7132, 7845, 8630, 9493, 10442, 11487, 12635, 13899,
15289, 16818, 18500, 20350, 22385, 24623, 27086, 29794,
32767
};
const int IMA_IndexTable[16] =
{
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
void decode_nds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
int32_t hist1 = stream->adpcm_history1_16;
int step_index = stream->adpcm_step_index;
if (first_sample==0) {
hist1 = read_16bitLE(stream->offset,stream->streamfile);
step_index = read_16bitLE(stream->offset+2,stream->streamfile);
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_nibble =
(read_8bit(stream->offset+4+i/2,stream->streamfile) >> (i&1?4:0))&0xf;
int delta;
int step = ADPCMTable[step_index];
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)
outbuf[sample_count] = clamp16(hist1 - delta);
else
outbuf[sample_count] = clamp16(hist1 + delta);
step_index += IMA_IndexTable[sample_nibble];
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_step_index = step_index;
}
void decode_dat4_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
int32_t hist1 = stream->adpcm_history1_16;
int step_index = stream->adpcm_step_index;
if (first_sample==0) {
hist1 = read_16bitLE(stream->offset,stream->streamfile);
step_index = read_8bit(stream->offset+2,stream->streamfile);
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_nibble =
(read_8bit(stream->offset+4+i/2,stream->streamfile) >> (i&1?0:4))&0xf;
int delta;
int step = ADPCMTable[step_index];
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)
outbuf[sample_count] = clamp16(hist1 - delta);
else
outbuf[sample_count] = clamp16(hist1 + delta);
step_index += IMA_IndexTable[sample_nibble];
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_step_index = step_index;
}
/* Xbox IMA is MS IMA, but I'll leave it alone for now (esp as it has > 2 channel support) */
void decode_ms_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i=first_sample;
int sample_nibble;
int sample_decoded;
int delta;
int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels;
int32_t sample_count=0;
int32_t hist1=stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
off_t offset=stream->offset;
first_sample = first_sample % block_samples;
if (first_sample == 0) {
hist1 = read_16bitLE(offset+channel*4,stream->streamfile);
step_index = read_16bitLE(offset+channel*4+2,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int step = ADPCMTable[step_index];
offset = stream->offset + 4*vgmstream->channels + (i/8*4*vgmstream->channels) + (i%8)/2 + 4*channel;
sample_nibble = (read_8bit(offset,stream->streamfile) >> (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];
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
outbuf[sample_count]=(short)(hist1);
}
// Only increment offset on complete frame
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
stream->adpcm_history1_32=hist1;
stream->adpcm_step_index=step_index;
}
// "Radical ADPCM", essentially MS IMA
void decode_rad_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i=first_sample;
int sample_nibble;
int sample_decoded;
int delta;
int block_samples = (vgmstream->interleave_block_size - vgmstream->channels * 4) * 2 / vgmstream->channels;
int32_t sample_count=0;
int32_t hist1=stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
off_t offset=stream->offset;
first_sample = first_sample % block_samples;
if (first_sample == 0) {
hist1 = read_16bitLE(offset+channel*4+2,stream->streamfile);
step_index = read_16bitLE(offset+channel*4,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int step = ADPCMTable[step_index];
offset = stream->offset + 4*vgmstream->channels + (i/2*vgmstream->channels) + channel;
sample_nibble = (read_8bit(offset,stream->streamfile) >> (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];
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
outbuf[sample_count]=(short)(hist1);
}
// Only increment offset on complete frame
if (i == block_samples) stream->offset += vgmstream->interleave_block_size;
stream->adpcm_history1_32=hist1;
stream->adpcm_step_index=step_index;
}
// "Radical ADPCM", mono form (for use with interleave layout)
// I think this is exactly equivalent to mono MS APDCM, but I need a
// channel-agnostic version to use within an interleave.
void decode_rad_ima_mono(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int sample_nibble;
int sample_decoded;
int delta;
int block_samples = 0x14 * 2;
int32_t sample_count=0;
int32_t hist1=stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
off_t offset=stream->offset;
first_sample = first_sample % block_samples;
if (first_sample == 0) {
hist1 = read_16bitLE(offset+2,stream->streamfile);
step_index = read_16bitLE(offset,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int step = ADPCMTable[step_index];
offset = stream->offset + 4 + (i/2);
sample_nibble = (read_8bit(offset,stream->streamfile) >> (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];
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;
}
void decode_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i=first_sample;
int sample_nibble;
int sample_decoded;
int delta;
int32_t sample_count=0;
int32_t hist1=stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
off_t offset=stream->offset;
if(vgmstream->channels==1)
first_sample = first_sample % 32;
else
first_sample = first_sample % (32*(vgmstream->channels&2));
if (first_sample == 0) {
if(vgmstream->layout_type==layout_ea_blocked) {
hist1 = read_16bitLE(offset,stream->streamfile);
step_index = read_16bitLE(offset+2,stream->streamfile);
} else {
hist1 = read_16bitLE(offset+(channel%2)*4,stream->streamfile);
step_index = read_16bitLE(offset+(channel%2)*4+2,stream->streamfile);
}
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int step = ADPCMTable[step_index];
if(vgmstream->layout_type==layout_ea_blocked)
offset = stream->offset + (i/8*4+(i%8)/2+4);
else {
if(channelspacing==1)
offset = stream->offset + 4 + (i/8*4+(i%8)/2+4*(channel%2));
else
offset = stream->offset + 4*2 + (i/8*4*2+(i%8)/2+4*(channel%2));
}
sample_nibble = (read_8bit(offset,stream->streamfile) >> (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];
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
outbuf[sample_count]=(short)(hist1);
}
// Only increment offset on complete frame
if(vgmstream->layout_type==layout_ea_blocked) {
if(offset-stream->offset==32+3) // ??
stream->offset+=36;
} else {
if(channelspacing==1) {
if(offset-stream->offset==32+3) // ??
stream->offset+=36;
} else {
if(offset-stream->offset==64+(4*(channel%2))+3) // ??
stream->offset+=36*channelspacing;
}
}
stream->adpcm_history1_32=hist1;
stream->adpcm_step_index=step_index;
}
void decode_int_xbox_ima(VGMSTREAM * vgmstream,VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do,int channel) {
int i=first_sample;
int sample_nibble;
int sample_decoded;
int delta;
int32_t sample_count=0;
int32_t hist1=stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
off_t offset=stream->offset;
if(vgmstream->channels==1)
first_sample = first_sample % 32;
else
first_sample = first_sample % (32*(vgmstream->channels&2));
if (first_sample == 0) {
hist1 = read_16bitLE(offset,stream->streamfile);
step_index = read_16bitLE(offset+2,stream->streamfile);
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int step = ADPCMTable[step_index];
offset = stream->offset + 4 + (i/8*4+(i%8)/2);
sample_nibble = (read_8bit(offset,stream->streamfile) >> (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];
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
outbuf[sample_count]=(short)(hist1);
}
// Only increment offset on complete frame
if(channelspacing==1) {
if(offset-stream->offset==32+3) // ??
stream->offset+=36;
} else {
if(offset-stream->offset==64+(4*(channel%2))+3) // ??
stream->offset+=36*channelspacing;
}
stream->adpcm_history1_32=hist1;
stream->adpcm_step_index=step_index;
}
void decode_dvi_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);
/* old-style DVI takes high nibble first */
sample_nibble = (sample_byte >> (i&1?0:4))&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;
}
void decode_eacs_ima(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i;
VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);
int32_t sample_count=0;
int32_t hist1=stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
vgmstream->get_high_nibble=!vgmstream->get_high_nibble;
if((first_sample) && (channelspacing==1))
vgmstream->get_high_nibble=!vgmstream->get_high_nibble;
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,stream->streamfile);
sample_nibble = (sample_byte >> (vgmstream->get_high_nibble?0:4))&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;
}
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;
}
void decode_apple_ima4(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count=0;
int16_t hist1=stream->adpcm_history1_16;
int step_index = stream->adpcm_step_index;
off_t packet_offset = stream->offset + first_sample/64*34;
first_sample = first_sample % 64;
if (first_sample == 0)
{
hist1 = (int16_t)((uint16_t)read_16bitBE(packet_offset,stream->streamfile) & 0xff80);
step_index = read_8bit(packet_offset+1,stream->streamfile) & 0x7f;
}
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(packet_offset+2+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_16=hist1;
stream->adpcm_step_index=step_index;
}
void decode_snds_ima(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
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;
uint8_t sample_byte;
int sample_nibble;
int sample_decoded;
int delta;
sample_byte = read_8bit(stream->offset+i,stream->streamfile);
sample_nibble = (sample_byte >> (channel==0?0:4))&0xf;
// update step before doing current sample
step_index += IMA_IndexTable[sample_nibble];
if (step_index < 0) step_index=0;
if (step_index > 88) step_index=88;
step = ADPCMTable[step_index];
delta = (sample_nibble & 7) * step / 4 + step / 8;
if (sample_nibble & 8) delta = -delta;
sample_decoded = hist1 + delta;
hist1=clamp16(sample_decoded);
outbuf[sample_count]=(short)(hist1);
}
stream->adpcm_history1_32=hist1;
stream->adpcm_step_index=step_index;
}

View File

@ -0,0 +1,58 @@
#include "coding.h"
#include "../util.h"
static const int32_t l5_scales[32] = {
0x00001000, 0x0000144E, 0x000019C5, 0x000020B4, 0x00002981, 0x000034AC, 0x000042D9, 0x000054D6,
0x00006BAB, 0x000088A4, 0x0000AD69, 0x0000DC13, 0x0001174C, 0x00016275, 0x0001C1D8, 0x00023AE5,
0x0002D486, 0x0003977E, 0x00048EEE, 0x0005C8F3, 0x00075779, 0x0009513E, 0x000BD31C, 0x000F01B5,
0x00130B82, 0x00182B83, 0x001EAC92, 0x0026EDB2, 0x00316777, 0x003EB2E6, 0x004F9232, 0x0064FBD1
};
void decode_l5_555(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
int framesin = first_sample/32;
uint16_t header = (uint16_t)read_16bitLE(framesin*0x12+stream->offset,stream->streamfile);
int32_t pos_scale = l5_scales[(header>>5)&0x1f];
int32_t neg_scale = l5_scales[header&0x1f];
int coef_index = (header >> 10) & 0x1f;
int16_t hist1 = stream->adpcm_history1_16;
int16_t hist2 = stream->adpcm_history2_16;
int16_t hist3 = stream->adpcm_history3_16;
int32_t coef1 = stream->adpcm_coef_3by32[coef_index*3];
int32_t coef2 = stream->adpcm_coef_3by32[coef_index*3+1];
int32_t coef3 = stream->adpcm_coef_3by32[coef_index*3+2];
/*printf("offset: %x\nscale: %d\nindex: %d (%lf,%lf)\nhist: %d %d\n",
(unsigned)stream->offset,scale,coef_index,coef1/2048.0,coef2/2048.0,hist1,hist2);*/
first_sample = first_sample%32;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*0x12+stream->offset+2+i/2,stream->streamfile);
int nibble = (i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte));
int32_t prediction =
-(hist1 * coef1 + hist2 * coef2 + hist3 * coef3);
if (nibble >= 0)
{
outbuf[sample_count] = clamp16((prediction + nibble * pos_scale) >> 12);
}
else
{
outbuf[sample_count] = clamp16((prediction + nibble * neg_scale) >> 12);
}
hist3 = hist2;
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_history2_16 = hist2;
stream->adpcm_history3_16 = hist3;
}

View File

@ -0,0 +1,52 @@
#include "coding.h"
#include "../util.h"
/* lsf ADPCM, as seen in Fastlane Street Racing */
static const short lsf_coefs[5][2] = {
{0x73, -0x34},
{0, 0},
{0x62, -0x37},
{0x3C, 0},
{0x7A, -0x3c}
};
void decode_lsf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
const int bytes_per_frame = 0x1c;
const int samples_per_frame = (bytes_per_frame-1)*2;
int framesin = first_sample/samples_per_frame;
uint8_t q = 0xFF - read_8bit(framesin*bytes_per_frame + stream->offset,stream->streamfile);
int scale = (q&0xF0)>>4;
int coef_idx = q&0x0F;
int32_t hist1 = stream->adpcm_history1_16;
int32_t hist2 = stream->adpcm_history2_16;
first_sample = first_sample%samples_per_frame;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*bytes_per_frame+stream->offset+1+i/2,stream->streamfile);
long prediction =
(hist1 * lsf_coefs[coef_idx][0] +
hist2 * lsf_coefs[coef_idx][1]) / 0x40;
prediction += (i&1?
get_high_nibble_signed(sample_byte):
get_low_nibble_signed(sample_byte)
) * (1 << (12-scale));
prediction = clamp16(prediction);
hist2 = hist1;
hist1 = prediction;
outbuf[sample_count] = prediction;
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_history2_16 = hist2;
}

View File

@ -0,0 +1,85 @@
#include "../vgmstream.h"
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
static void convert_samples(INT_PCM * src, sample * dest, int32_t count) {
int32_t i;
for ( i = 0; i < count; i++ ) {
INT_PCM sample = *src++;
sample >>= SAMPLE_BITS - 16;
if ( ( sample + 0x8000 ) & 0xFFFF0000 ) sample = 0x7FFF ^ ( sample >> 31 );
*dest++ = sample;
}
}
void decode_mp4_aac(mp4_aac_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels) {
int samples_done = 0;
uint8_t * buffer = NULL;
uint32_t buffer_size;
UINT ubuffer_size, bytes_valid;
CStreamInfo * stream_info = aacDecoder_GetStreamInfo( data->h_aacdecoder );
int32_t samples_remain = data->samples_per_frame - data->sample_ptr;
if ( data->samples_discard ) {
if ( samples_remain <= data->samples_discard ) {
data->samples_discard -= samples_remain;
samples_remain = 0;
}
else {
samples_remain -= data->samples_discard;
data->sample_ptr += data->samples_discard;
data->samples_discard = 0;
}
}
if ( samples_remain > samples_to_do ) samples_remain = samples_to_do;
convert_samples( data->sample_buffer + data->sample_ptr * stream_info->numChannels, outbuf, samples_remain * stream_info->numChannels );
outbuf += samples_remain * stream_info->numChannels;
data->sample_ptr += samples_remain;
samples_done += samples_remain;
while ( samples_done < samples_to_do ) {
if (data->sampleId >= data->numSamples) {
memset(outbuf, 0, (samples_to_do - samples_done) * stream_info->numChannels * sizeof(sample));
break;
}
if (!MP4ReadSample( data->h_mp4file, data->track_id, ++data->sampleId, (uint8_t**)(&buffer), (uint32_t*)(&buffer_size), 0, 0, 0, 0)) return;
ubuffer_size = buffer_size;
bytes_valid = buffer_size;
if ( aacDecoder_Fill( data->h_aacdecoder, &buffer, &ubuffer_size, &bytes_valid ) || bytes_valid ) {
free( buffer );
return;
}
if ( aacDecoder_DecodeFrame( data->h_aacdecoder, data->sample_buffer, ( (6) * (2048)*4 ), 0 ) ) {
free( buffer );
return;
}
free( buffer ); buffer = NULL;
stream_info = aacDecoder_GetStreamInfo( data->h_aacdecoder );
samples_remain = data->samples_per_frame = stream_info->frameSize;
data->sample_ptr = 0;
if ( data->samples_discard ) {
if ( samples_remain <= data->samples_discard ) {
data->samples_discard -= samples_remain;
samples_remain = 0;
}
else {
samples_remain -= data->samples_discard;
data->sample_ptr = data->samples_discard;
data->samples_discard = 0;
}
}
if ( samples_remain > samples_to_do - samples_done ) samples_remain = samples_to_do - samples_done;
convert_samples( data->sample_buffer + data->sample_ptr * stream_info->numChannels, outbuf, samples_remain * stream_info->numChannels );
samples_done += samples_remain;
outbuf += samples_remain * stream_info->numChannels;
data->sample_ptr = samples_remain;
}
}
#endif

View File

@ -0,0 +1,229 @@
#include "../vgmstream.h"
#ifdef VGM_USE_MPEG
#include <string.h>
#include <mpg123.h>
#include "coding.h"
#include "../util.h"
/* mono, mpg123 expects frames of 0x414 (160kbps, 22050Hz) but they
* actually vary and are much shorter */
void decode_fake_mpeg2_l2(VGMSTREAMCHANNEL *stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do) {
int samples_done = 0;
while (samples_done < samples_to_do) {
size_t bytes_done;
int rc;
if (!data->buffer_full) {
/* fill buffer up to next frame ending (or file ending) */
int bytes_into_header = 0;
const uint8_t header[4] = {0xff,0xf5,0xe0,0xc0};
off_t frame_offset = 0;
/* assume that we are starting at a header, skip it and look for the
* next one */
read_streamfile(data->buffer, stream->offset+frame_offset, 4,
stream->streamfile);
frame_offset += 4;
do {
uint8_t byte;
byte =
read_8bit(stream->offset+frame_offset,stream->streamfile);
data->buffer[frame_offset] = byte;
frame_offset++;
if (byte == header[bytes_into_header]) {
bytes_into_header++;
} else {
/* This might have been the first byte of the header, so
* we need to check again.
* No need to get more complicated than this, though, since
* there are no repeated characters in the search string. */
if (bytes_into_header>0) {
frame_offset--;
}
bytes_into_header=0;
}
if (bytes_into_header==4) {
break;
}
} while (frame_offset < AHX_EXPECTED_FRAME_SIZE);
if (bytes_into_header==4) frame_offset-=4;
memset(data->buffer+frame_offset,0,
AHX_EXPECTED_FRAME_SIZE-frame_offset);
data->buffer_full = 1;
data->buffer_used = 0;
stream->offset += frame_offset;
}
if (!data->buffer_used) {
rc = mpg123_decode(data->m,
data->buffer,AHX_EXPECTED_FRAME_SIZE,
(unsigned char *)(outbuf+samples_done),
(samples_to_do-samples_done)*sizeof(sample),
&bytes_done);
data->buffer_used = 1;
} else {
rc = mpg123_decode(data->m,
NULL,0,
(unsigned char *)(outbuf+samples_done),
(samples_to_do-samples_done)*sizeof(sample),
&bytes_done);
}
if (rc == MPG123_NEED_MORE) data->buffer_full = 0;
samples_done += bytes_done/sizeof(sample);
}
}
mpeg_codec_data *init_mpeg_codec_data(STREAMFILE *streamfile, off_t start_offset, long given_sample_rate, int given_channels, coding_t *coding_type, int * actual_sample_rate, int * actual_channels) {
int rc;
off_t read_offset;
mpeg_codec_data *data = NULL;
data = calloc(1,sizeof(mpeg_codec_data));
if (!data) goto mpeg_fail;
data->m = mpg123_new(NULL,&rc);
if (rc==MPG123_NOT_INITIALIZED) {
if (mpg123_init()!=MPG123_OK) goto mpeg_fail;
data->m = mpg123_new(NULL,&rc);
if (rc!=MPG123_OK) goto mpeg_fail;
} else if (rc!=MPG123_OK) {
goto mpeg_fail;
}
mpg123_param(data->m,MPG123_REMOVE_FLAGS,MPG123_GAPLESS,0.0);
if (mpg123_open_feed(data->m)!=MPG123_OK) {
goto mpeg_fail;
}
/* check format */
read_offset=0;
do {
size_t bytes_done;
if (read_streamfile(data->buffer, start_offset+read_offset,
MPEG_BUFFER_SIZE,streamfile) !=
MPEG_BUFFER_SIZE) goto mpeg_fail;
read_offset+=1;
rc = mpg123_decode(data->m,data->buffer,MPEG_BUFFER_SIZE,
NULL,0,&bytes_done);
if (rc != MPG123_OK && rc != MPG123_NEW_FORMAT &&
rc != MPG123_NEED_MORE) goto mpeg_fail;
} while (rc != MPG123_NEW_FORMAT);
{
long rate;
int channels,encoding;
struct mpg123_frameinfo mi;
rc = mpg123_getformat(data->m,&rate,&channels,&encoding);
if (rc != MPG123_OK) goto mpeg_fail;
//fprintf(stderr,"getformat ok, sr=%ld (%ld) ch=%d (%d) enc=%d (%d)\n",rate,given_sample_rate,channels,vgmstream->channels,encoding,MPG123_ENC_SIGNED_16);
if ((given_sample_rate != -1 && rate != given_sample_rate) ||
(given_channels != -1 && channels != given_channels) ||
encoding != MPG123_ENC_SIGNED_16) goto mpeg_fail;
mpg123_info(data->m,&mi);
if (given_sample_rate != -1 &&
mi.rate != given_sample_rate) goto mpeg_fail;
//fprintf(stderr,"mi.version=%d, mi.layer=%d\n",mi.version,mi.layer);
if (mi.version == MPG123_1_0 && mi.layer == 1)
*coding_type = coding_MPEG1_L1;
else if (mi.version == MPG123_1_0 && mi.layer == 2)
*coding_type = coding_MPEG1_L2;
else if (mi.version == MPG123_1_0 && mi.layer == 3)
*coding_type = coding_MPEG1_L3;
else if (mi.version == MPG123_2_0 && mi.layer == 1)
*coding_type = coding_MPEG2_L1;
else if (mi.version == MPG123_2_0 && mi.layer == 2)
*coding_type = coding_MPEG2_L2;
else if (mi.version == MPG123_2_0 && mi.layer == 3)
*coding_type = coding_MPEG2_L3;
else if (mi.version == MPG123_2_5 && mi.layer == 1)
*coding_type = coding_MPEG25_L1;
else if (mi.version == MPG123_2_5 && mi.layer == 2)
*coding_type = coding_MPEG25_L2;
else if (mi.version == MPG123_2_5 && mi.layer == 3)
*coding_type = coding_MPEG25_L3;
else goto mpeg_fail;
if ( actual_sample_rate ) *actual_sample_rate = rate;
if ( actual_channels ) *actual_channels = channels;
}
/* reinit, to ignore the reading we've done so far */
mpg123_open_feed(data->m);
return data;
mpeg_fail:
fprintf(stderr, "mpeg_fail start_offset=%x\n",(unsigned int)start_offset);
if (data) {
mpg123_delete(data->m);
free(data);
}
return NULL;
}
/* decode anything mpg123 can */
void decode_mpeg(VGMSTREAMCHANNEL *stream,
mpeg_codec_data * data,
sample * outbuf, int32_t samples_to_do, int channels) {
int samples_done = 0;
while (samples_done < samples_to_do) {
size_t bytes_done;
int rc;
if (!data->buffer_full) {
data->bytes_in_buffer = read_streamfile(data->buffer,
stream->offset,MPEG_BUFFER_SIZE,stream->streamfile);
if (!data->bytes_in_buffer) {
memset(outbuf + samples_done * channels, 0, (samples_to_do - samples_done) * sizeof(sample));
break;
}
data->buffer_full = 1;
data->buffer_used = 0;
stream->offset += data->bytes_in_buffer;
}
if (!data->buffer_used) {
rc = mpg123_decode(data->m,
data->buffer,data->bytes_in_buffer,
(unsigned char *)(outbuf+samples_done*channels),
(samples_to_do-samples_done)*sizeof(sample)*channels,
&bytes_done);
data->buffer_used = 1;
} else {
rc = mpg123_decode(data->m,
NULL,0,
(unsigned char *)(outbuf+samples_done*channels),
(samples_to_do-samples_done)*sizeof(sample)*channels,
&bytes_done);
}
if (rc == MPG123_NEED_MORE) data->buffer_full = 0;
samples_done += bytes_done/sizeof(sample)/channels;
}
}
long mpeg_bytes_to_samples(long bytes, const struct mpg123_frameinfo *mi) {
return (int64_t)bytes * mi->rate * 8 / (mi->bitrate * 1000);
}
#endif

View File

@ -0,0 +1,163 @@
#include "../util.h"
#include "coding.h"
/* used to compute next scale */
static const int ADPCMTable[16] =
{
230, 230, 230, 230,
307, 409, 512, 614,
768, 614, 512, 409,
307, 230, 230, 230
};
static const int ADPCMCoeffs[7][2] =
{
{ 256, 0 },
{ 512, -256 },
{ 0, 0 },
{ 192, 64 },
{ 240, 0 },
{ 460, -208 },
{ 392, -232 }
};
long msadpcm_bytes_to_samples(long bytes, int block_size, int channels) {
return bytes/block_size*((block_size-(7-1)*channels)*2/channels);
}
void decode_msadpcm_stereo(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) {
VGMSTREAMCHANNEL *ch1,*ch2;
int i;
int framesin;
STREAMFILE *streamfile;
off_t offset;
framesin = first_sample/get_vgmstream_samples_per_frame(vgmstream);
first_sample = first_sample%get_vgmstream_samples_per_frame(vgmstream);
ch1 = &vgmstream->ch[0];
ch2 = &vgmstream->ch[1];
streamfile = ch1->streamfile;
offset = ch1->offset+framesin*get_vgmstream_frame_size(vgmstream);
if (first_sample==0) {
ch1->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset,streamfile)][0];
ch1->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset,streamfile)][1];
ch2->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset+1,streamfile)][0];
ch2->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset+1,streamfile)][1];
ch1->adpcm_scale = read_16bitLE(offset+2,streamfile);
ch2->adpcm_scale = read_16bitLE(offset+4,streamfile);
ch1->adpcm_history1_16 = read_16bitLE(offset+6,streamfile);
ch2->adpcm_history1_16 = read_16bitLE(offset+8,streamfile);
ch1->adpcm_history2_16 = read_16bitLE(offset+10,streamfile);
ch2->adpcm_history2_16 = read_16bitLE(offset+12,streamfile);
outbuf[0] = ch1->adpcm_history2_16;
outbuf[1] = ch2->adpcm_history2_16;
outbuf+=2;
first_sample++;
samples_to_do--;
}
if (first_sample==1 && samples_to_do > 0) {
outbuf[0] = ch1->adpcm_history1_16;
outbuf[1] = ch2->adpcm_history1_16;
outbuf+=2;
first_sample++;
samples_to_do--;
}
for (i=first_sample; i<first_sample+samples_to_do; i++) {
int j;
for (j=0;j<2;j++)
{
VGMSTREAMCHANNEL *ch = &vgmstream->ch[j];
int sample_nibble =
(j == 0 ?
get_high_nibble_signed(read_8bit(offset+14+i-2,streamfile)) :
get_low_nibble_signed(read_8bit(offset+14+i-2,streamfile))
);
int32_t hist1,hist2;
int32_t predicted;
hist1 = ch->adpcm_history1_16;
hist2 = ch->adpcm_history2_16;
predicted = hist1 * ch->adpcm_coef[0] + hist2 * ch->adpcm_coef[1];
predicted /= 256;
predicted += sample_nibble*ch->adpcm_scale;
outbuf[0] = clamp16(predicted);
ch->adpcm_history2_16 = ch->adpcm_history1_16;
ch->adpcm_history1_16 = outbuf[0];
ch->adpcm_scale = (ADPCMTable[sample_nibble&0xf] *
ch->adpcm_scale) / 256;
if (ch->adpcm_scale < 0x10) ch->adpcm_scale = 0x10;
outbuf++;
}
}
}
void decode_msadpcm_mono(VGMSTREAM * vgmstream, sample * outbuf, int32_t first_sample, int32_t samples_to_do) {
VGMSTREAMCHANNEL *ch1;
int i;
int framesin;
STREAMFILE *streamfile;
off_t offset;
framesin = first_sample/get_vgmstream_samples_per_frame(vgmstream);
first_sample = first_sample%get_vgmstream_samples_per_frame(vgmstream);
ch1 = &vgmstream->ch[0];
streamfile = ch1->streamfile;
offset = ch1->offset+framesin*get_vgmstream_frame_size(vgmstream);
if (first_sample==0) {
ch1->adpcm_coef[0] = ADPCMCoeffs[read_8bit(offset,streamfile)][0];
ch1->adpcm_coef[1] = ADPCMCoeffs[read_8bit(offset,streamfile)][1];
ch1->adpcm_scale = read_16bitLE(offset+1,streamfile);
ch1->adpcm_history1_16 = read_16bitLE(offset+3,streamfile);
ch1->adpcm_history2_16 = read_16bitLE(offset+5,streamfile);
outbuf[0] = ch1->adpcm_history2_16;
outbuf++;
first_sample++;
samples_to_do--;
}
if (first_sample==1 && samples_to_do > 0) {
outbuf[0] = ch1->adpcm_history1_16;
outbuf++;
first_sample++;
samples_to_do--;
}
for (i=first_sample; i<first_sample+samples_to_do; i++) {
{
VGMSTREAMCHANNEL *ch = &vgmstream->ch[0];
int sample_nibble =
(i & 1 ?
get_low_nibble_signed(read_8bit(offset+7+(i-2)/2,streamfile)) :
get_high_nibble_signed(read_8bit(offset+7+(i-2)/2,streamfile))
);
int32_t hist1,hist2;
int32_t predicted;
hist1 = ch->adpcm_history1_16;
hist2 = ch->adpcm_history2_16;
predicted = hist1 * ch->adpcm_coef[0] + hist2 * ch->adpcm_coef[1];
predicted /= 256;
predicted += sample_nibble*ch->adpcm_scale;
outbuf[0] = clamp16(predicted);
ch->adpcm_history2_16 = ch->adpcm_history1_16;
ch->adpcm_history1_16 = outbuf[0];
ch->adpcm_scale = (ADPCMTable[sample_nibble&0xf] *
ch->adpcm_scale) / 256;
if (ch->adpcm_scale < 0x10) ch->adpcm_scale = 0x10;
outbuf++;
}
}
}

View File

@ -0,0 +1,154 @@
//#include <stdlib.h>
//#include <stdio.h>
#include "coding.h"
#include "../util.h"
// A hybrid of IMA and Yamaha ADPCM found in Metal Gear Solid 3
// Thanks to X_Tra (http://metalgear.in/) for pointing me to the step size table.
int index_table[16] = {
-1, -1, -1, -1, 2, 4, 6, 8,
-1, -1, -1, -1, 2, 4, 6, 8
};
static int16_t step_size[32][16] = {
{ 1, 5, 9, 13, 16, 20, 24, 28,
-1, -5, -9, -13, -16, -20, -24, -28, },
{ 2, 6, 11, 15, 20, 24, 29, 33,
-2, -6, -11, -15, -20, -24, -29, -33, },
{ 2, 7, 13, 18, 23, 28, 34, 39,
-2, -7, -13, -18, -23, -28, -34, -39, },
{ 3, 9, 15, 21, 28, 34, 40, 46,
-3, -9, -15, -21, -28, -34, -40, -46, },
{ 3, 11, 18, 26, 33, 41, 48, 56,
-3, -11, -18, -26, -33, -41, -48, -56, },
{ 4, 13, 22, 31, 40, 49, 58, 67,
-4, -13, -22, -31, -40, -49, -58, -67, },
{ 5, 16, 26, 37, 48, 59, 69, 80,
-5, -16, -26, -37, -48, -59, -69, -80, },
{ 6, 19, 31, 44, 57, 70, 82, 95,
-6, -19, -31, -44, -57, -70, -82, -95, },
{ 7, 22, 38, 53, 68, 83, 99, 114,
-7, -22, -38, -53, -68, -83, -99, -114, },
{ 9, 27, 45, 63, 81, 99, 117, 135,
-9, -27, -45, -63, -81, -99, -117, -135, },
{ 10, 32, 53, 75, 96, 118, 139, 161,
-10, -32, -53, -75, -96, -118, -139, -161, },
{ 12, 38, 64, 90, 115, 141, 167, 193,
-12, -38, -64, -90, -115, -141, -167, -193, },
{ 15, 45, 76, 106, 137, 167, 198, 228,
-15, -45, -76, -106, -137, -167, -198, -228, },
{ 18, 54, 91, 127, 164, 200, 237, 273,
-18, -54, -91, -127, -164, -200, -237, -273, },
{ 21, 65, 108, 152, 195, 239, 282, 326,
-21, -65, -108, -152, -195, -239, -282, -326, },
{ 25, 77, 129, 181, 232, 284, 336, 388,
-25, -77, -129, -181, -232, -284, -336, -388, },
{ 30, 92, 153, 215, 276, 338, 399, 461,
-30, -92, -153, -215, -276, -338, -399, -461, },
{ 36, 109, 183, 256, 329, 402, 476, 549,
-36, -109, -183, -256, -329, -402, -476, -549, },
{ 43, 130, 218, 305, 392, 479, 567, 654,
-43, -130, -218, -305, -392, -479, -567, -654, },
{ 52, 156, 260, 364, 468, 572, 676, 780,
-52, -156, -260, -364, -468, -572, -676, -780, },
{ 62, 186, 310, 434, 558, 682, 806, 930,
-62, -186, -310, -434, -558, -682, -806, -930, },
{ 73, 221, 368, 516, 663, 811, 958, 1106,
-73, -221, -368, -516, -663, -811, -958, -1106, },
{ 87, 263, 439, 615, 790, 966, 1142, 1318,
-87, -263, -439, -615, -790, -966, -1142, -1318, },
{ 104, 314, 523, 733, 942, 1152, 1361, 1571,
-104, -314, -523, -733, -942, -1152, -1361, -1571, },
{ 124, 374, 623, 873, 1122, 1372, 1621, 1871,
-124, -374, -623, -873, -1122, -1372, -1621, -1871, },
{ 148, 445, 743, 1040, 1337, 1634, 1932, 2229,
-148, -445, -743, -1040, -1337, -1634, -1932, -2229, },
{ 177, 531, 885, 1239, 1593, 1947, 2301, 2655,
-177, -531, -885, -1239, -1593, -1947, -2301, -2655, },
{ 210, 632, 1053, 1475, 1896, 2318, 2739, 3161,
-210, -632, -1053, -1475, -1896, -2318, -2739, -3161, },
{ 251, 753, 1255, 1757, 2260, 2762, 3264, 3766,
-251, -753, -1255, -1757, -2260, -2762, -3264, -3766, },
{ 299, 897, 1495, 2093, 2692, 3290, 3888, 4486,
-299, -897, -1495, -2093, -2692, -3290, -3888, -4486, },
{ 356, 1068, 1781, 2493, 3206, 3918, 4631, 5343,
-356, -1068, -1781, -2493, -3206, -3918, -4631, -5343, },
{ 424, 1273, 2121, 2970, 3819, 4668, 5516, 6365,
-424, -1273, -2121, -2970, -3819, -4668, -5516, -6365, },
};
void decode_mtaf(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, int channels) {
int32_t sample_count;
int framesin = first_sample / 0x100;
unsigned long cur_off = stream->offset + framesin*(0x10+0x80*2)*(channels/2);
int i;
int c = channel%2;
int16_t init_idx = read_16bitLE(cur_off+4+c*2, stream->streamfile);
int16_t init_hist = read_16bitLE(cur_off+8+c*4, stream->streamfile);
int32_t hist = stream->adpcm_history1_16;
int step_idx = stream->adpcm_step_index;
//printf("channel %d: first_sample = %d, stream->offset = 0x%lx, cur_off = 0x%lx init_idx = %d\n", channel, first_sample, (unsigned long)stream->offset, cur_off, init_idx);
#if 0
if (init_idx < 0 || init_idx > 31) {
fprintf(stderr, "step idx out of range at 0x%lx ch %d\n", cur_off, c);
exit(1);
}
if (0 != read_16bitLE(cur_off+10+c*4, stream->streamfile)) {
fprintf(stderr, "exp. zero after hist at 0x%lx ch %d\n", cur_off, c);
exit(1);
}
#endif
first_sample = first_sample%0x100;
if (first_sample%0x100 == 0) {
hist = init_hist;
#if 0
if (step_idx != init_idx) {
fprintf(stderr, "step_idx does not match at 0x%lx, %d!=%d\n",cur_off,step_idx, init_idx);
exit(1);
}
#endif
step_idx = init_idx;
}
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
uint8_t byte, nibble;
byte = read_8bit(cur_off + 0x10 + 0x80*c + i/2, stream->streamfile);
if (i%2!=1)
{
// low nibble first
nibble = byte&0xf;
}
else
{
// high nibble last
nibble = byte >> 4;
}
hist = clamp16(hist+step_size[step_idx][nibble]);
outbuf[sample_count] = hist;
step_idx += index_table[nibble];
if (step_idx < 0)
{
step_idx = 0;
}
if (step_idx > 31)
{
step_idx = 31;
}
} /* end sample loop */
// update state
stream->adpcm_step_index = step_idx;
stream->adpcm_history1_16 = hist;
}

View File

@ -0,0 +1,60 @@
#include "coding.h"
#include "../util.h"
/* ADPCM found in NDS games using Procyon Studio Digital Sound Elements */
static const int8_t proc_coef[5][2] =
{
{0x00,0x00},
{0x3C,0x00},
{0x73,0xCC},
{0x62,0xC9},
{0x7A,0xC4},
};
void decode_nds_procyon(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
int framesin = first_sample/30;
uint8_t header = read_8bit(framesin*16+15+stream->offset,stream->streamfile) ^ 0x80;
int scale = 12 - (header & 0xf);
int coef_index = (header >> 4) & 0xf;
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
int32_t coef1;
int32_t coef2;
if (coef_index > 4) coef_index = 0;
coef1 = proc_coef[coef_index][0];
coef2 = proc_coef[coef_index][1];
first_sample = first_sample%30;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*16+stream->offset+i/2,stream->streamfile) ^ 0x80;
int32_t sample =
(int32_t)
(i&1?
get_high_nibble_signed(sample_byte):
get_low_nibble_signed(sample_byte)
) * 64 * 64;
if (scale < 0)
{
sample <<= -scale;
}
else
sample >>= scale;
sample = (hist1 * coef1 + hist2 * coef2 + 32) / 64 + (sample * 64);
hist2 = hist1;
hist1 = sample;
outbuf[sample_count] = clamp16((sample + 32) / 64) / 64 * 64;
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2;
}

View File

@ -0,0 +1,58 @@
#include "coding.h"
#include "../util.h"
const short afc_coef[16][2] =
{{0,0},
{0x0800,0},
{0,0x0800},
{0x0400,0x0400},
{0x1000,0xf800},
{0x0e00,0xfa00},
{0x0c00,0xfc00},
{0x1200,0xf600},
{0x1068,0xf738},
{0x12c0,0xf704},
{0x1400,0xf400},
{0x0800,0xf800},
{0x0400,0xfc00},
{0xfc00,0x0400},
{0xfc00,0},
{0xf800,0}};
void decode_ngc_afc(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
int framesin = first_sample/16;
int8_t header = read_8bit(framesin*9+stream->offset,stream->streamfile);
int32_t scale = 1 << ((header>>4) & 0xf);
int coef_index = (header & 0xf);
int32_t hist1 = stream->adpcm_history1_16;
int32_t hist2 = stream->adpcm_history2_16;
int coef1 = afc_coef[coef_index][0];
int coef2 = afc_coef[coef_index][1];
/*printf("offset: %x\nscale: %d\nindex: %d (%lf,%lf)\nhist: %d %d\n",
(unsigned)stream->offset,scale,coef_index,coef1/2048.0,coef2/2048.0,hist1,hist2);*/
first_sample = first_sample%16;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*9+stream->offset+1+i/2,stream->streamfile);
outbuf[sample_count] = clamp16((
(((i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale)<<11) +
(coef1 * hist1 + coef2 * hist2))>>11
);
/*printf("%hd\n",outbuf[sample_count]);*/
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_history2_16 = hist2;
}

View File

@ -0,0 +1,106 @@
#include "coding.h"
#include "../util.h"
void decode_ngc_dsp(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i=first_sample;
int32_t sample_count;
int framesin = first_sample/14;
int8_t header = read_8bit(framesin*8+stream->offset,stream->streamfile);
int32_t scale = 1 << (header & 0xf);
int coef_index = (header >> 4) & 0xf;
int32_t hist1 = stream->adpcm_history1_16;
int32_t hist2 = stream->adpcm_history2_16;
int coef1 = stream->adpcm_coef[coef_index*2];
int coef2 = stream->adpcm_coef[coef_index*2+1];
first_sample = first_sample%14;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*8+stream->offset+1+i/2,stream->streamfile);
#ifdef DEBUG
if (hist1==stream->loop_history1 && hist2==stream->loop_history2) fprintf(stderr,"yo! %#x (start %#x) %d\n",stream->offset+framesin*8+i/2,stream->channel_start_offset,stream->samples_done);
stream->samples_done++;
#endif
outbuf[sample_count] = clamp16((
(((i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale)<<11) + 1024 +
(coef1 * hist1 + coef2 * hist2))>>11
);
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_history2_16 = hist2;
}
/* read from memory rather than a file */
void decode_ngc_dsp_mem(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, uint8_t * mem) {
int i=first_sample;
int32_t sample_count;
int framesin = first_sample/14;
int8_t header = mem[framesin*8];
int32_t scale = 1 << (header & 0xf);
int coef_index = (header >> 4) & 0xf;
int32_t hist1 = stream->adpcm_history1_16;
int32_t hist2 = stream->adpcm_history2_16;
int coef1 = stream->adpcm_coef[coef_index*2];
int coef2 = stream->adpcm_coef[coef_index*2+1];
first_sample = first_sample%14;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = mem[framesin*8+1+i/2];
#ifdef DEBUG
if (hist1==stream->loop_history1 && hist2==stream->loop_history2) fprintf(stderr,"yo! %#x (start %#x) %d\n",stream->offset+framesin*8+i/2,stream->channel_start_offset,stream->samples_done);
stream->samples_done++;
#endif
outbuf[sample_count] = clamp16((
(((i&1?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) * scale)<<11) + 1024 +
(coef1 * hist1 + coef2 * hist2))>>11
);
hist2 = hist1;
hist1 = outbuf[sample_count];
}
stream->adpcm_history1_16 = hist1;
stream->adpcm_history2_16 = hist2;
}
/*
* The original DSP spec uses nibble counts for loop points, and some
* variants don't have a proper sample count, so we (who are interested
* in sample counts) need to do this conversion occasionally.
*/
int32_t dsp_nibbles_to_samples(int32_t nibbles) {
int32_t whole_frames = nibbles/16;
int32_t remainder = nibbles%16;
/*
fprintf(stderr,"%d (%#x) nibbles => %x bytes and %d samples\n",nibbles,nibbles,whole_frames*8,remainder);
*/
#if 0
if (remainder > 0 && remainder < 14)
return whole_frames*14 + remainder;
else if (remainder >= 14)
fprintf(stderr,"***** last frame %d leftover nibbles makes no sense\n",remainder);
#endif
if (remainder>0) return whole_frames*14+remainder-2;
else return whole_frames*14;
}

View File

@ -0,0 +1,53 @@
#include "coding.h"
#include "../util.h"
void decode_ngc_dtk(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
int i=first_sample;
int32_t sample_count;
int framesin = first_sample/28;
uint8_t q = read_8bit(framesin*32+stream->offset+channel,stream->streamfile);
int32_t hist1 = stream->adpcm_history1_32;
int32_t hist2 = stream->adpcm_history2_32;
first_sample = first_sample%28;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int sample_byte = read_8bit(framesin*32+stream->offset+4+i,stream->streamfile);
int32_t hist=0;
switch (q>>4)
{
case 0:
hist = 0;
break;
case 1:
hist = (hist1 * 0x3c);
break;
case 2:
hist = (hist1 * 0x73) - (hist2 * 0x34);
break;
case 3:
hist = (hist1 * 0x62) - (hist2 * 0x37);
break;
}
hist = (hist+0x20)>>6;
if (hist > 0x1fffff) hist = 0x1fffff;
if (hist < -0x200000) hist = -0x200000;
hist2 = hist1;
hist1 = ((((channel==0?
get_low_nibble_signed(sample_byte):
get_high_nibble_signed(sample_byte)
) << 12) >> (q & 0xf)) << 6) + hist;
outbuf[sample_count] = clamp16(hist1 >> 6);
}
stream->adpcm_history1_32 = hist1;
stream->adpcm_history2_32 = hist2;
}

View File

@ -0,0 +1,351 @@
/* 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)
{
int ret;
if (*shift > 8)
{
++*offset;
*shift -= 8;
}
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);
}
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;
}
void
seek_nwa(NWAData *nwa, int32_t seekpos)
{
int dest_block = seekpos/(nwa->blocksize/nwa->channels);
int32_t remainder = seekpos%(nwa->blocksize/nwa->channels);
nwa->curblock = dest_block;
nwa_decode_block(nwa);
nwa->buffer_readpos = nwa->buffer + remainder*nwa->channels;
nwa->samples_in_buffer -= remainder*nwa->channels;
}
/* 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);
}
}
}

View File

@ -0,0 +1,71 @@
/* 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
#ifdef BUILD_VGMSTREAM
#include "../streamfile.h"
#else
#include "streamfile.h"
#endif
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);
void seek_nwa(NWAData *nwa, int32_t seekpos);
#endif

View File

@ -0,0 +1,22 @@
#include "../vgmstream.h"
#ifdef VGM_USE_VORBIS
#include <vorbis/vorbisfile.h>
#include "coding.h"
#include "../util.h"
void decode_ogg_vorbis(ogg_vorbis_codec_data * data, sample * outbuf, int32_t samples_to_do, int channels) {
int samples_done = 0;
OggVorbis_File *ogg_vorbis_file = &data->ogg_vorbis_file;
do {
long rc = ov_read(ogg_vorbis_file, (char *)(outbuf + samples_done*channels),
(samples_to_do - samples_done)*sizeof(sample)*channels, 0,
sizeof(sample), 1, &data->bitstream);
if (rc > 0) samples_done += rc/sizeof(sample)/channels;
else return;
} while (samples_done < samples_to_do);
}
#endif

View File

@ -0,0 +1,87 @@
#include "coding.h"
#include "../util.h"
void decode_pcm16LE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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]=read_16bitLE(stream->offset+i*2,stream->streamfile);
}
}
void decode_pcm16BE(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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]=read_16bitBE(stream->offset+i*2,stream->streamfile);
}
}
void decode_pcm8(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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]=read_8bit(stream->offset+i,stream->streamfile)*0x100;
}
}
void decode_pcm8_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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]=read_8bit(stream->offset+i*channelspacing,stream->streamfile)*0x100;
}
}
void decode_pcm8_sb_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int16_t v = (uint8_t)read_8bit(stream->offset+i*channelspacing,stream->streamfile);
if (v&0x80) v = 0-(v&0x7f);
outbuf[sample_count] = v*0x100;
}
}
void decode_pcm8_unsigned_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int16_t v = (uint8_t)read_8bit(stream->offset+i*channelspacing,stream->streamfile);
outbuf[sample_count] = v*0x100 - 0x8000;
}
}
void decode_pcm8_unsigned(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int i;
int32_t sample_count;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
int16_t v = (uint8_t)read_8bit(stream->offset+i,stream->streamfile);
outbuf[sample_count] = v*0x100 - 0x8000;
}
}
void decode_pcm16LE_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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]=read_16bitLE(stream->offset+i*2*channelspacing,stream->streamfile);
}
}
void decode_pcm16LE_XOR_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
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]=read_16bitLE(stream->offset+i*2*channelspacing,stream->streamfile)^stream->key_xor;
}
}

View File

@ -0,0 +1,214 @@
#include <math.h>
#include "coding.h"
#include "../util.h"
double VAG_f[5][2] = { { 0.0 , 0.0 },
{ 60.0 / 64.0 , 0.0 },
{ 115.0 / 64.0 , -52.0 / 64.0 },
{ 98.0 / 64.0 , -55.0 / 64.0 } ,
{ 122.0 / 64.0 , -60.0 / 64.0 } } ;
long VAG_coefs[5][2] = { { 0 , 0 },
{ 60 , 0 },
{ 115 , -52 },
{ 98 , -55 } ,
{ 122 , -60 } } ;
void decode_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int predict_nr, shift_factor, sample;
int32_t hist1=stream->adpcm_history1_32;
int32_t hist2=stream->adpcm_history2_32;
short scale;
int i;
int32_t sample_count;
uint8_t flag;
int framesin = first_sample/28;
predict_nr = read_8bit(stream->offset+framesin*16,stream->streamfile) >> 4;
shift_factor = read_8bit(stream->offset+framesin*16,stream->streamfile) & 0xf;
flag = read_8bit(stream->offset+framesin*16+1,stream->streamfile);
first_sample = first_sample % 28;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
sample=0;
if(flag<0x07) {
short sample_byte = (short)read_8bit(stream->offset+(framesin*16)+2+i/2,stream->streamfile);
scale = ((i&1 ?
sample_byte >> 4 :
sample_byte & 0x0f)<<12);
sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]);
}
outbuf[sample_count] = clamp16(sample);
hist2=hist1;
hist1=sample;
}
stream->adpcm_history1_32=hist1;
stream->adpcm_history2_32=hist2;
}
void decode_invert_psx(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int predict_nr, shift_factor, sample;
int32_t hist1=stream->adpcm_history1_32;
int32_t hist2=stream->adpcm_history2_32;
short scale;
int i;
int32_t sample_count;
uint8_t flag;
int framesin = first_sample/28;
int head = read_8bit(stream->offset+framesin*16,stream->streamfile) ^ stream->bmdx_xor;
predict_nr = ((head >> 4) & 0xf);
shift_factor = (head & 0xf);
flag = read_8bit(stream->offset+framesin*16+1,stream->streamfile);
first_sample = first_sample % 28;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
sample=0;
if(flag<0x07) {
short sample_byte = (short)read_8bit(stream->offset+(framesin*16)+2+i/2,stream->streamfile);
if (i/2 == 0)
sample_byte = (short)(int8_t)(sample_byte+stream->bmdx_add);
scale = ((i&1 ?
sample_byte >> 4 :
sample_byte & 0x0f)<<12);
sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]);
}
outbuf[sample_count] = clamp16(sample);
hist2=hist1;
hist1=sample;
}
stream->adpcm_history1_32=hist1;
stream->adpcm_history2_32=hist2;
}
/* some TAITO games have garbage (?) in their flags, this decoder
* just ignores that byte */
void decode_psx_badflags(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int predict_nr, shift_factor, sample;
int32_t hist1=stream->adpcm_history1_32;
int32_t hist2=stream->adpcm_history2_32;
short scale;
int i;
int32_t sample_count;
int framesin = first_sample/28;
predict_nr = read_8bit(stream->offset+framesin*16,stream->streamfile) >> 4;
shift_factor = read_8bit(stream->offset+framesin*16,stream->streamfile) & 0xf;
first_sample = first_sample % 28;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+(framesin*16)+2+i/2,stream->streamfile);
scale = ((i&1 ?
sample_byte >> 4 :
sample_byte & 0x0f)<<12);
sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]);
outbuf[sample_count] = clamp16(sample);
hist2=hist1;
hist1=sample;
}
stream->adpcm_history1_32=hist1;
stream->adpcm_history2_32=hist2;
}
/* FF XI's Vag-ish format */
void decode_ffxi_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int predict_nr, shift_factor, sample;
int32_t hist1=stream->adpcm_history1_32;
int32_t hist2=stream->adpcm_history2_32;
short scale;
int i;
int32_t sample_count;
long predictor;
int framesin = first_sample/16;
predict_nr = read_8bit(stream->offset+framesin*9,stream->streamfile) >> 4;
shift_factor = read_8bit(stream->offset+framesin*9,stream->streamfile) & 0xf;
first_sample = first_sample % 16;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+(framesin*9)+1+i/2,stream->streamfile);
sample=0;
scale = ((i&1 ?
sample_byte >> 4 :
sample_byte & 0x0f)<<12);
#if 1
predictor =
(int)((hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]));
#else
predictor =
(hist1*VAG_coefs[predict_nr][0]+hist2*VAG_coefs[predict_nr][1])/64;
#endif
sample=(scale >> shift_factor) + predictor;
outbuf[sample_count] = clamp16(sample);
hist2=hist1;
hist1=sample;
}
stream->adpcm_history1_32=hist1;
stream->adpcm_history2_32=hist2;
}
void decode_baf_adpcm(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
int predict_nr, shift_factor, sample;
int32_t hist1=stream->adpcm_history1_32;
int32_t hist2=stream->adpcm_history2_32;
short scale;
int i;
int32_t sample_count;
int framesin = first_sample/64;
predict_nr = read_8bit(stream->offset+framesin*33,stream->streamfile) >> 4;
shift_factor = read_8bit(stream->offset+framesin*33,stream->streamfile) & 0xf;
first_sample = first_sample % 64;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+(framesin*33)+1+i/2,stream->streamfile);
scale = ((i&1 ?
sample_byte >> 4 :
sample_byte & 0x0f)<<12);
sample=(int)((scale >> shift_factor)+hist1*VAG_f[predict_nr][0]+hist2*VAG_f[predict_nr][1]);
outbuf[sample_count] = clamp16(sample);
hist2=hist1;
hist1=sample;
}
stream->adpcm_history1_32=hist1;
stream->adpcm_history2_32=hist2;
}

View File

@ -0,0 +1,118 @@
#include <math.h>
#include "coding.h"
#include "../util.h"
/* SDX2 - 2:1 Squareroot-delta-exact compression */
/* CBD2 - 2:1 Cuberoot-delta-exact compression (from the unreleased 3DO M2) */
/* for (i=-128;i<128;i++) squares[i+128]=i<0?(-i*i)*2:(i*i)*2; */
static int16_t squares[256] = {
-32768,-32258,-31752,-31250,-30752,-30258,-29768,-29282,-28800,-28322,-27848,
-27378,-26912,-26450,-25992,-25538,-25088,-24642,-24200,-23762,-23328,-22898,
-22472,-22050,-21632,-21218,-20808,-20402,-20000,-19602,-19208,-18818,-18432,
-18050,-17672,-17298,-16928,-16562,-16200,-15842,-15488,-15138,-14792,-14450,
-14112,-13778,-13448,-13122,-12800,-12482,-12168,-11858,-11552,-11250,-10952,
-10658,-10368,-10082, -9800, -9522, -9248, -8978, -8712, -8450, -8192, -7938,
-7688, -7442, -7200, -6962, -6728, -6498, -6272, -6050, -5832, -5618, -5408,
-5202, -5000, -4802, -4608, -4418, -4232, -4050, -3872, -3698, -3528, -3362,
-3200, -3042, -2888, -2738, -2592, -2450, -2312, -2178, -2048, -1922, -1800,
-1682, -1568, -1458, -1352, -1250, -1152, -1058, -968, -882, -800, -722,
-648, -578, -512, -450, -392, -338, -288, -242, -200, -162, -128,
-98, -72, -50, -32, -18, -8, -2, 0, 2, 8, 18,
32, 50, 72, 98, 128, 162, 200, 242, 288, 338, 392,
450, 512, 578, 648, 722, 800, 882, 968, 1058, 1152, 1250,
1352, 1458, 1568, 1682, 1800, 1922, 2048, 2178, 2312, 2450, 2592,
2738, 2888, 3042, 3200, 3362, 3528, 3698, 3872, 4050, 4232, 4418,
4608, 4802, 5000, 5202, 5408, 5618, 5832, 6050, 6272, 6498, 6728,
6962, 7200, 7442, 7688, 7938, 8192, 8450, 8712, 8978, 9248, 9522,
9800, 10082, 10368, 10658, 10952, 11250, 11552, 11858, 12168, 12482, 12800,
13122, 13448, 13778, 14112, 14450, 14792, 15138, 15488, 15842, 16200, 16562,
16928, 17298, 17672, 18050, 18432, 18818, 19208, 19602, 20000, 20402, 20808,
21218, 21632, 22050, 22472, 22898, 23328, 23762, 24200, 24642, 25088, 25538,
25992, 26450, 26912, 27378, 27848, 28322, 28800, 29282, 29768, 30258, 30752,
31250, 31752, 32258
};
//for (i=-128;i<128;i++)
//{
// double j = (i/2)/2.0;
// cubes[i+128]=floor(j*j*j);
//}
static int16_t cubes[256]={
-32768,-31256,-31256,-29791,-29791,-28373,-28373,-27000,-27000,-25672,-25672,
-24389,-24389,-23149,-23149,-21952,-21952,-20797,-20797,-19683,-19683,-18610,
-18610,-17576,-17576,-16581,-16581,-15625,-15625,-14706,-14706,-13824,-13824,
-12978,-12978,-12167,-12167,-11391,-11391,-10648,-10648, -9938, -9938, -9261,
-9261, -8615, -8615, -8000, -8000, -7415, -7415, -6859, -6859, -6332, -6332,
-5832, -5832, -5359, -5359, -4913, -4913, -4492, -4492, -4096, -4096, -3724,
-3724, -3375, -3375, -3049, -3049, -2744, -2744, -2460, -2460, -2197, -2197,
-1953, -1953, -1728, -1728, -1521, -1521, -1331, -1331, -1158, -1158, -1000,
-1000, -857, -857, -729, -729, -614, -614, -512, -512, -422, -422,
-343, -343, -275, -275, -216, -216, -166, -166, -125, -125, -91,
-91, -64, -64, -43, -43, -27, -27, -16, -16, -8, -8,
-3, -3, -1, -1, 0, 0, 0, 0, 0, 0, 0,
1, 1, 3, 3, 8, 8, 16, 16, 27, 27, 43,
43, 64, 64, 91, 91, 125, 125, 166, 166, 216, 216,
275, 275, 343, 343, 422, 422, 512, 512, 614, 614, 729,
729, 857, 857, 1000, 1000, 1158, 1158, 1331, 1331, 1521, 1521,
1728, 1728, 1953, 1953, 2197, 2197, 2460, 2460, 2744, 2744, 3049,
3049, 3375, 3375, 3724, 3724, 4096, 4096, 4492, 4492, 4913, 4913,
5359, 5359, 5832, 5832, 6332, 6332, 6859, 6859, 7415, 7415, 8000,
8000, 8615, 8615, 9261, 9261, 9938, 9938, 10648, 10648, 11391, 11391,
12167, 12167, 12978, 12978, 13824, 13824, 14706, 14706, 15625, 15625, 16581,
16581, 17576, 17576, 18610, 18610, 19683, 19683, 20797, 20797, 21952, 21952,
23149, 23149, 24389, 24389, 25672, 25672, 27000, 27000, 28373, 28373, 29791,
29791, 31256, 31256};
static void decode_delta_exact(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) {
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) {
int8_t sample_byte = read_8bit(stream->offset+i,stream->streamfile);
int16_t sample;
if (!(sample_byte & 1)) hist = 0;
sample = hist + table[sample_byte+128];
hist = outbuf[sample_count] = clamp16(sample);
}
stream->adpcm_history1_32=hist;
}
static void decode_delta_exact_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int16_t * table) {
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) {
int8_t sample_byte = read_8bit(stream->offset+i*channelspacing,stream->streamfile);
int16_t sample;
if (!(sample_byte & 1)) hist = 0;
sample = hist + table[sample_byte+128];
hist = outbuf[sample_count] = clamp16(sample);
}
stream->adpcm_history1_32=hist;
}
void decode_sdx2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
decode_delta_exact(stream, outbuf, channelspacing, first_sample, samples_to_do, squares);
}
void decode_sdx2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
decode_delta_exact_int(stream, outbuf, channelspacing, first_sample, samples_to_do, squares);
}
void decode_cbd2(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
decode_delta_exact(stream, outbuf, channelspacing, first_sample, samples_to_do, cubes);
}
void decode_cbd2_int(VGMSTREAMCHANNEL * stream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
decode_delta_exact_int(stream, outbuf, channelspacing, first_sample, samples_to_do, cubes);
}

View File

@ -0,0 +1,146 @@
#include <math.h>
#include "coding.h"
#include "../util.h"
/* Westwood Studios ADPCM */
/* Based on Valery V. Anisimovsky's WS-AUD.txt */
static char WSTable2bit[4]={-2,-1,0,1};
static char WSTable4bit[16]={-9,-8,-6,-5,-4,-3,-2,-1,
0, 1, 2, 3, 4, 5 ,6, 8};
/* We pass in the VGMSTREAM here, unlike in other codings, because
the decoder has to know about the block structure. */
void decode_ws(VGMSTREAM * vgmstream, int channel, sample * outbuf, int channelspacing, int32_t first_sample,
int32_t samples_to_do) {
VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);
int16_t hist = stream->adpcm_history1_16;
off_t offset = stream->offset;
int samples_left_in_frame = stream->samples_left_in_frame;
off_t header_off = stream->frame_header_offset;
int i;
int32_t sample_count;
if (vgmstream->ws_output_size == vgmstream->current_block_size) {
/* uncompressed, we just need to convert to 16-bit */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing,offset++) {
outbuf[sample_count]=((uint8_t)read_8bit(offset,stream->streamfile)-0x80)*0x100;
}
} else {
if (first_sample == 0) {
hist = 0x80;
samples_left_in_frame = 0;
}
/* actually decompress */
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; ) {
uint8_t header;
uint8_t count;
if (samples_left_in_frame == 0) {
header_off = offset;
offset++;
}
header = read_8bit(header_off,stream->streamfile);
count = header & 0x3f;
switch (header>>6) { /* code */
case 0: /* 2-bit ADPCM */
if (samples_left_in_frame == 0) {
samples_left_in_frame = (count + 1)*4;
}
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
int twobit = ((count + 1)*4-samples_left_in_frame)%4;
uint8_t sample;
sample = read_8bit(offset,stream->streamfile);
sample = (sample >> (twobit*2)) & 0x3;
hist += WSTable2bit[sample];
if (hist < 0) hist = 0;
if (hist > 0xff) hist = 0xff;
outbuf[sample_count]=(hist-0x80)*0x100;
if (twobit == 3)
offset++; /* done with that byte */
}
break;
case 1: /* 4-bit ADPCM */
if (samples_left_in_frame == 0) {
samples_left_in_frame = (count + 1)*2;
}
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
int nibble = ((count + 1)*4-samples_left_in_frame)%2;
uint8_t sample;
sample = read_8bit(offset,stream->streamfile);
if (nibble == 0)
sample &= 0xf;
else
sample >>= 4;
hist += WSTable4bit[sample];
if (hist < 0) hist = 0;
if (hist > 0xff) hist = 0xff;
outbuf[sample_count]=(hist-0x80)*0x100;
if (nibble == 1)
offset++; /* done with that byte */
}
break;
case 2: /* no compression */
if (count & 0x20) { /* delta */
/* Note no checks against samples_to_do here,
at the top of the for loop we can always do at
least one sample */
/* low 5 bits are a signed delta */
if (count & 0x10) {
hist -= ((count & 0xf)^0xf) + 1;
} else {
hist += count & 0xf;
}
/* Valery doesn't specify this, but I will assume */
if (hist < 0) hist = 0;
if (hist > 0xff) hist = 0xff;
outbuf[sample_count]=(hist-0x80)*0x100;
sample_count+=channelspacing;
i++;
/* just one, and we got it */
samples_left_in_frame = 0;
} else { /* copy bytes verbatim */
if (samples_left_in_frame == 0)
samples_left_in_frame=count+1;
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
offset++, /* done with a byte */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
outbuf[sample_count]=((hist=(uint8_t)read_8bit(offset,stream->streamfile))-0x80)*0x100;
}
}
break;
case 3: /* RLE */
if (samples_left_in_frame == 0)
samples_left_in_frame=count+1;
for (;samples_left_in_frame>0 && /* read this frame */
i<first_sample+samples_to_do; /* up to samples_to_do */
i++,sample_count+=channelspacing, /* done with writing a sample */
samples_left_in_frame--) { /* done with reading a sample */
outbuf[sample_count]=(hist-0x80)*0x100;
}
}
}
}
stream->offset = offset;
stream->adpcm_history1_16 = hist;
stream->samples_left_in_frame = samples_left_in_frame;
stream->frame_header_offset = header_off;
}

View File

@ -0,0 +1,72 @@
#include "coding.h"
#include "../util.h"
const int SH = 4;
const int SHC = 10;
double K0[4] = { 0.0, 0.9375, 1.796875, 1.53125};
double K1[4] = { 0.0, 0.0, -0.8125,-0.859375};
int IK0(int fid)
{ return ((int)((-K0[fid]) * (1 << SHC))); }
int IK1(int fid)
{ return ((int)((-K1[fid]) * (1 << SHC))); }
int CLAMP(int value, int Minim, int Maxim)
{
if (value < Minim) value = Minim;
if (value > Maxim) value = Maxim;
return value;
}
void init_get_high_nibble(VGMSTREAM *vgmstream) {
vgmstream->get_high_nibble=1;
}
void decode_xa(VGMSTREAM * vgmstream, sample * outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel) {
VGMSTREAMCHANNEL * stream = &(vgmstream->ch[channel]);
int predict_nr, shift_factor, sample;
int32_t hist1=stream->adpcm_history1_32;
int32_t hist2=stream->adpcm_history2_32;
int HeadTable[8]={0,2,8,10};
short scale;
int i;
int32_t sample_count;
int framesin = first_sample / (56 / channelspacing);
first_sample = first_sample % 28;
vgmstream->get_high_nibble=!vgmstream->get_high_nibble;
if((first_sample) && (channelspacing==1))
vgmstream->get_high_nibble=!vgmstream->get_high_nibble;
predict_nr = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) >> 4;
shift_factor = read_8bit(stream->offset+HeadTable[framesin]+vgmstream->get_high_nibble,stream->streamfile) & 0xf;
for (i=first_sample,sample_count=0; i<first_sample+samples_to_do; i++,sample_count+=channelspacing) {
short sample_byte = (short)read_8bit(stream->offset+16+framesin+(i*4),stream->streamfile);
scale = ((vgmstream->get_high_nibble ?
sample_byte >> 4 :
sample_byte & 0x0f)<<12);
sample = (short)(scale & 0xf000) >> shift_factor;
sample <<= SH;
sample -= (IK0(predict_nr) * hist1 + (IK1(predict_nr) * hist2)) >> SHC;
hist2=hist1;
hist1=sample;
sample = CLAMP(sample, -32768 << SH, 32767 << SH);
outbuf[sample_count] = (short)(sample >> SH);
}
stream->adpcm_history1_32=hist1;
stream->adpcm_history2_32=hist2;
}

View File

@ -0,0 +1,41 @@
noinst_LTLIBRARIES = liblayout.la
AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix
liblayout_la_LDFLAGS =
liblayout_la_SOURCES =
liblayout_la_SOURCES += ast_blocked.c
liblayout_la_SOURCES += blocked.c
liblayout_la_SOURCES += caf_blocked.c
liblayout_la_SOURCES += ea_block.c
liblayout_la_SOURCES += halpst_blocked.c
liblayout_la_SOURCES += interleave.c
liblayout_la_SOURCES += nolayout.c
liblayout_la_SOURCES += xa_blocked.c
liblayout_la_SOURCES += wsi_blocked.c
liblayout_la_SOURCES += str_snds_blocked.c
liblayout_la_SOURCES += ws_aud_blocked.c
liblayout_la_SOURCES += interleave_byte.c
liblayout_la_SOURCES += mus_acm_layout.c
liblayout_la_SOURCES += aix_layout.c
liblayout_la_SOURCES += ims_block.c
liblayout_la_SOURCES += de2_blocked.c
liblayout_la_SOURCES += xvas_block.c
liblayout_la_SOURCES += vs_blocked.c
liblayout_la_SOURCES += emff_blocked.c
liblayout_la_SOURCES += thp_blocked.c
liblayout_la_SOURCES += gsb_blocked.c
liblayout_la_SOURCES += filp_blocked.c
liblayout_la_SOURCES += aax_layout.c
liblayout_la_SOURCES += ivaud_layout.c
liblayout_la_SOURCES += mxch_blocked.c
liblayout_la_SOURCES += psx_mgav_blocked.c
liblayout_la_SOURCES += ps2_adm_blocked.c
liblayout_la_SOURCES += bdsp_blocked.c
liblayout_la_SOURCES += tra_blocked.c
liblayout_la_SOURCES += ps2_iab_blocked.c
liblayout_la_SOURCES += ps2_strlr_blocked.c
liblayout_la_SOURCES += scd_int_layout.c
EXTRA_DIST = layout.h

View File

@ -0,0 +1,67 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../coding/coding.h"
void render_vgmstream_aax(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
int samples_written=0;
aax_codec_data *data = vgmstream->codec_data;
while (samples_written<sample_count) {
int samples_to_do;
int samples_this_block = data->sample_counts[data->current_segment];
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
int i;
data->current_segment = data->loop_segment;
reset_vgmstream(data->adxs[data->current_segment]);
/* carry over the history from the loop point */
if (data->loop_segment > 0)
{
for (i=0;i<data->adxs[0]->channels;i++)
{
data->adxs[data->loop_segment]->ch[i].adpcm_history1_32 =
data->adxs[data->loop_segment-1]->ch[i].adpcm_history1_32;
data->adxs[data->loop_segment]->ch[i].adpcm_history2_32 =
data->adxs[data->loop_segment-1]->ch[i].adpcm_history2_32;
}
}
vgmstream->samples_into_block = 0;
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, 1, vgmstream);
/*printf("samples_to_do=%d,samples_this_block=%d,samples_written=%d,sample_count=%d\n",samples_to_do,samples_this_block,samples_written,sample_count);*/
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
if (samples_to_do == 0)
{
int i;
data->current_segment++;
/*printf("advance to %d at %d samples\n",data->current_segment,vgmstream->current_sample);*/
reset_vgmstream(data->adxs[data->current_segment]);
/* carry over the history from the previous segment */
for (i=0;i<data->adxs[0]->channels;i++)
{
data->adxs[data->current_segment]->ch[i].adpcm_history1_32 =
data->adxs[data->current_segment-1]->ch[i].adpcm_history1_32;
data->adxs[data->current_segment]->ch[i].adpcm_history2_32 =
data->adxs[data->current_segment-1]->ch[i].adpcm_history2_32;
}
vgmstream->samples_into_block = 0;
continue;
}
render_vgmstream(&buffer[samples_written*data->adxs[data->current_segment]->channels],
samples_to_do,data->adxs[data->current_segment]);
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
}
}

View File

@ -0,0 +1,92 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../coding/coding.h"
void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
int samples_written=0;
aix_codec_data *data = vgmstream->codec_data;
while (samples_written<sample_count) {
int samples_to_do;
int samples_this_block = data->sample_counts[data->current_segment];
int current_stream;
int channels_sofar = 0;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
data->current_segment = 1;
for (current_stream = 0; current_stream < data->stream_count; current_stream++)
{
int i;
reset_vgmstream(data->adxs[data->current_segment*data->stream_count+current_stream]);
/* carry over the history from the loop point */
for (i=0;i<data->adxs[data->stream_count+current_stream]->channels;i++)
{
data->adxs[1*data->stream_count+current_stream]->ch[i].adpcm_history1_32 =
data->adxs[0+current_stream]->ch[i].adpcm_history1_32;
data->adxs[1*data->stream_count+current_stream]->ch[i].adpcm_history2_32 =
data->adxs[0+current_stream]->ch[i].adpcm_history2_32;
}
}
vgmstream->samples_into_block = 0;
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, 1, vgmstream);
/*printf("samples_to_do=%d,samples_this_block=%d,samples_written=%d,sample_count=%d\n",samples_to_do,samples_this_block,samples_written,sample_count);*/
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
if (samples_to_do == 0)
{
int i;
data->current_segment++;
/*printf("next %d, %d samples\n",data->current_file,data->files[data->current_file]->total_values/data->files[data->current_file]->info.channels);*/
for (current_stream = 0; current_stream < data->stream_count; current_stream++)
{
reset_vgmstream(data->adxs[data->current_segment*data->stream_count+current_stream]);
/* carry over the history from the previous segment */
for (i=0;i<data->adxs[data->current_segment*data->stream_count+current_stream]->channels;i++)
{
data->adxs[data->current_segment*data->stream_count+current_stream]->ch[i].adpcm_history1_32 =
data->adxs[(data->current_segment-1)*data->stream_count+current_stream]->ch[i].adpcm_history1_32;
data->adxs[data->current_segment*data->stream_count+current_stream]->ch[i].adpcm_history2_32 =
data->adxs[(data->current_segment-1)*data->stream_count+current_stream]->ch[i].adpcm_history2_32;
}
}
vgmstream->samples_into_block = 0;
continue;
}
/*printf("decode %d samples file %d\n",samples_to_do,data->current_file);*/
if (samples_to_do > AIX_BUFFER_SIZE/2)
{
samples_to_do = AIX_BUFFER_SIZE/2;
}
for (current_stream = 0; current_stream < data->stream_count; current_stream++)
{
int i,j;
VGMSTREAM *adx = data->adxs[data->current_segment*data->stream_count+current_stream];
render_vgmstream(data->buffer,samples_to_do,adx);
for (i = 0; i < samples_to_do; i++)
{
for (j = 0; j < adx->channels; j++)
{
buffer[(i+samples_written)*vgmstream->channels+channels_sofar+j] = data->buffer[i*adx->channels+j];
}
}
channels_sofar += adx->channels;
}
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
}
}

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void ast_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitBE(
vgmstream->current_block_offset+4,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset +
vgmstream->current_block_size*vgmstream->channels + 0x20;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
0x20 + vgmstream->current_block_size*i;
}
}

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void dsp_bdsp_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitBE(vgmstream->current_block_offset,vgmstream->ch[0].streamfile)/7*8;
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0xC0;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=vgmstream->current_block_offset*i;
}
}

View File

@ -0,0 +1,150 @@
#include "layout.h"
#include "../vgmstream.h"
void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
int samples_written=0;
int frame_size = get_vgmstream_frame_size(vgmstream);
int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
int samples_this_block;
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)) {
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;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
if (vgmstream->current_block_offset>=0)
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer);
else {
int i;
/* we've run off the end! */
for (i=samples_written*vgmstream->channels;
i<(samples_written+samples_to_do)*vgmstream->channels;i++)
buffer[i]=0;
}
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
if (vgmstream->samples_into_block==samples_this_block) {
switch (vgmstream->layout_type) {
case layout_ast_blocked:
ast_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_mxch_blocked:
mxch_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_halpst_blocked:
if (vgmstream->next_block_offset>=0)
halpst_block_update(vgmstream->next_block_offset,vgmstream);
else
vgmstream->current_block_offset=-1;
break;
case layout_xa_blocked:
xa_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_ea_blocked:
ea_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_eacs_blocked:
eacs_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_caf_blocked:
caf_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_wsi_blocked:
wsi_block_update(vgmstream->next_block_offset,vgmstream);
break;
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;
case layout_matx_blocked:
matx_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_de2_blocked:
de2_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_emff_ps2_blocked:
emff_ps2_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_emff_ngc_blocked:
emff_ngc_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_gsb_blocked:
gsb_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_vs_blocked:
vs_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_xvas_blocked:
xvas_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_thp_blocked:
thp_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_filp_blocked:
filp_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_ivaud_blocked:
ivaud_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_psx_mgav_blocked:
psx_mgav_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_ps2_adm_blocked:
ps2_adm_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_dsp_bdsp_blocked:
dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_tra_blocked:
tra_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_ps2_iab_blocked:
ps2_iab_block_update(vgmstream->next_block_offset,vgmstream);
break;
case layout_ps2_strlr_blocked:
ps2_strlr_block_update(vgmstream->next_block_offset,vgmstream);
break;
default:
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 {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
}
vgmstream->samples_into_block=0;
}
}
}

View File

@ -0,0 +1,26 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitBE(
vgmstream->current_block_offset+0x14,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset +
(off_t)read_32bitBE(vgmstream->current_block_offset+0x04,
vgmstream->ch[0].streamfile);
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
read_32bitBE(block_offset+0x10+(8*i),vgmstream->ch[0].streamfile);
}
/* coeffs */
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(block_offset+0x34+(2*i),vgmstream->ch[0].streamfile);
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(block_offset+0x60+(2*i),vgmstream->ch[0].streamfile);
}
}

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void de2_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = block_offset+8+read_32bitLE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile);
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + 8;
}
}

View File

@ -0,0 +1,149 @@
#include "layout.h"
#include "../coding/coding.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void ea_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
init_get_high_nibble(vgmstream);
// Search for next SCDL or SCEl block ...
do {
block_offset+=4;
if(block_offset>=(off_t)get_streamfile_size(vgmstream->ch[0].streamfile)) {
vgmstream->next_block_offset=block_offset;
return;
}
} while (read_32bitBE(block_offset,vgmstream->ch[0].streamfile)!=0x5343446C);
// reset channel offset
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].channel_start_offset=0;
}
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset+read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-4;
if(vgmstream->ea_big_endian) {
vgmstream->current_block_size = read_32bitBE(block_offset+8,vgmstream->ch[0].streamfile);
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset=read_32bitBE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels);
vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C;
}
vgmstream->current_block_size /= 28;
} else {
switch(vgmstream->coding_type) {
case coding_PSX:
vgmstream->ch[0].offset=vgmstream->current_block_offset+0x10;
vgmstream->ch[1].offset=(read_32bitLE(block_offset+0x04,vgmstream->ch[0].streamfile)-0x10)/vgmstream->channels;
vgmstream->ch[1].offset+=vgmstream->ch[0].offset;
vgmstream->current_block_size=read_32bitLE(block_offset+0x04,vgmstream->ch[0].streamfile)-0x10;
vgmstream->current_block_size/=vgmstream->channels;
break;
case coding_EA_ADPCM:
vgmstream->current_block_size = read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile);
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset=vgmstream->current_block_offset+0x0C+(4*vgmstream->channels);
vgmstream->ch[i].adpcm_history1_32=(uint32_t)read_16bitLE(vgmstream->current_block_offset+0x0c+(i*4),vgmstream->ch[0].streamfile);
vgmstream->ch[i].adpcm_history2_32=(uint32_t)read_16bitLE(vgmstream->current_block_offset+0x0e +(i*4),vgmstream->ch[0].streamfile);
}
break;
case coding_PCM16BE:
vgmstream->current_block_size = read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-0x14;
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset=block_offset+0x14+vgmstream->current_block_size/vgmstream->channels*i;
}
vgmstream->current_block_size/=vgmstream->channels;
break;
case coding_PCM16LE_int:
vgmstream->current_block_size = read_32bitLE(block_offset+4,vgmstream->ch[0].streamfile)-0x0C;
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset=block_offset+0x0C+(i*2);
}
vgmstream->current_block_size/=2;
vgmstream->current_block_size-=2;
break;
case coding_XBOX:
vgmstream->current_block_size = read_32bitLE(block_offset+0x10,vgmstream->ch[0].streamfile);
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset=read_32bitLE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels);
vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C;
}
break;
default:
vgmstream->current_block_size = read_32bitLE(block_offset+8,vgmstream->ch[0].streamfile);
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset=read_32bitLE(block_offset+0x0C+(i*4),vgmstream->ch[0].streamfile)+(4*vgmstream->channels);
vgmstream->ch[i].offset+=vgmstream->current_block_offset+0x0C;
}
vgmstream->current_block_size /= 28;
}
}
if((vgmstream->ea_compression_version<3) && (vgmstream->coding_type!=coding_PSX) && (vgmstream->coding_type!=coding_EA_ADPCM) && (vgmstream->coding_type!=coding_XBOX) && (vgmstream->coding_type!=coding_PCM16BE)) {
for(i=0;i<vgmstream->channels;i++) {
if(vgmstream->ea_big_endian) {
vgmstream->ch[i].adpcm_history1_32=read_16bitBE(vgmstream->ch[i].offset,vgmstream->ch[0].streamfile);
vgmstream->ch[i].adpcm_history2_32=read_16bitBE(vgmstream->ch[i].offset+2,vgmstream->ch[0].streamfile);
} else {
vgmstream->ch[i].adpcm_history1_32=read_16bitLE(vgmstream->ch[i].offset,vgmstream->ch[0].streamfile);
vgmstream->ch[i].adpcm_history2_32=read_16bitLE(vgmstream->ch[i].offset+2,vgmstream->ch[0].streamfile);
}
vgmstream->ch[i].offset+=4;
}
}
}
void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
off_t block_size=vgmstream->current_block_size;
if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) {
block_offset+=0x0C;
}
vgmstream->current_block_offset = block_offset;
if(read_32bitBE(block_offset,vgmstream->ch[0].streamfile)==0x31534E64) { /* 1Snd */
block_offset+=4;
if(vgmstream->ea_platform==0)
block_size=read_32bitLE(vgmstream->current_block_offset+0x04,
vgmstream->ch[0].streamfile);
else
block_size=read_32bitBE(vgmstream->current_block_offset+0x04,
vgmstream->ch[0].streamfile);
block_offset+=4;
}
vgmstream->current_block_size=block_size-8;
if(vgmstream->coding_type==coding_EACS_IMA) {
init_get_high_nibble(vgmstream);
vgmstream->current_block_size=read_32bitLE(block_offset,vgmstream->ch[0].streamfile);
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].adpcm_step_index = read_32bitLE(block_offset+0x04+i*4,vgmstream->ch[0].streamfile);
vgmstream->ch[i].adpcm_history1_32 = read_32bitLE(block_offset+0x04+i*4+(4*vgmstream->channels),vgmstream->ch[0].streamfile);
vgmstream->ch[i].offset = block_offset+0x14;
}
} else {
if(vgmstream->coding_type==coding_PSX) {
for (i=0;i<vgmstream->channels;i++)
vgmstream->ch[i].offset = vgmstream->current_block_offset+8+(i*(vgmstream->current_block_size/2));
} else {
for (i=0;i<vgmstream->channels;i++) {
if(vgmstream->coding_type==coding_PCM16LE_int)
vgmstream->ch[i].offset = block_offset+(i*2);
else
vgmstream->ch[i].offset = block_offset+i;
}
}
vgmstream->current_block_size/=vgmstream->channels;
}
vgmstream->next_block_offset = vgmstream->current_block_offset +
(off_t)block_size;
}

View File

@ -0,0 +1,34 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void emff_ps2_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(
vgmstream->current_block_offset+0x10,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x20;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(vgmstream->current_block_size*i);
}
}
void emff_ngc_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitBE(
vgmstream->current_block_offset+0x20,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x40;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x40+(vgmstream->current_block_size*i);
}
}

View File

@ -0,0 +1,19 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(
vgmstream->current_block_offset+0x18,
vgmstream->ch[0].streamfile)-0x800;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x800;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x800+(vgmstream->current_block_size*i);
}
}

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void gsb_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = 0x10000; /*read_32bitLE(
vgmstream->current_block_offset+0x10,
vgmstream->ch[0].streamfile); */
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size+0x20;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(vgmstream->current_block_size*i);
}
}

View File

@ -0,0 +1,19 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void halpst_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitBE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile)/vgmstream->channels;
vgmstream->next_block_offset = read_32bitBE(
vgmstream->current_block_offset+8,
vgmstream->ch[0].streamfile);
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
0x20 + vgmstream->current_block_size*i;
}
}

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void matx_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size + 8;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + 8;
}
}

View File

@ -0,0 +1,65 @@
#include "layout.h"
#include "../vgmstream.h"
void render_vgmstream_interleave(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
int samples_written=0;
int frame_size = get_vgmstream_frame_size(vgmstream);
int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
int samples_this_block;
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
if (vgmstream->layout_type == layout_interleave_shortblock &&
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block> vgmstream->num_samples) {
frame_size = get_vgmstream_shortframe_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame;
}
while (samples_written<sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
/* we assume that the loop is not back into a short block */
if (vgmstream->layout_type == layout_interleave_shortblock) {
frame_size = get_vgmstream_frame_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
samples_this_block = vgmstream->interleave_block_size / frame_size * samples_per_frame;
}
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
/*printf("vgmstream_samples_to_do(samples_this_block=%d,samples_per_frame=%d,vgmstream) returns %d\n",samples_this_block,samples_per_frame,samples_to_do);*/
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer);
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
if (vgmstream->samples_into_block==samples_this_block) {
int chan;
if (vgmstream->layout_type == layout_interleave_shortblock &&
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
frame_size = get_vgmstream_shortframe_size(vgmstream);
samples_per_frame = get_vgmstream_samples_per_shortframe(vgmstream);
samples_this_block = vgmstream->interleave_smallblock_size / frame_size * samples_per_frame;
for (chan=0;chan<vgmstream->channels;chan++)
vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*(vgmstream->channels-chan)+vgmstream->interleave_smallblock_size*chan;
} else {
for (chan=0;chan<vgmstream->channels;chan++)
vgmstream->ch[chan].offset+=vgmstream->interleave_block_size*vgmstream->channels;
}
vgmstream->samples_into_block=0;
}
}
}

View File

@ -0,0 +1,62 @@
#include "layout.h"
#include "../vgmstream.h"
/* for formats where the interleave is smaller than a frame, so we need to
* deinterleave in memory before passing it along to a specialized decoder which
* reads from memory
*/
/* just do one frame at a time */
void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
/* frame sizes are much smaller than this */
uint8_t sample_data[0x400];
int samples_written=0;
int frame_size = get_vgmstream_frame_size(vgmstream);
int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
int samples_this_block;
samples_this_block = samples_per_frame;
while (samples_written<sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
{
int i,j;
for (j=0;j<vgmstream->channels;j++) {
for (i=0;i<frame_size;i++) {
sample_data[i] = read_8bit(vgmstream->ch[j].offset+
i/vgmstream->interleave_block_size*
vgmstream->interleave_block_size*
vgmstream->channels+
i%vgmstream->interleave_block_size,
vgmstream->ch[j].streamfile);
}
decode_vgmstream_mem(vgmstream, samples_written,
samples_to_do, buffer, sample_data, j);
}
}
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
if (vgmstream->samples_into_block==samples_this_block) {
int chan;
for (chan=0;chan<vgmstream->channels;chan++)
vgmstream->ch[chan].offset+=frame_size*vgmstream->channels;
vgmstream->samples_into_block=0;
}
}
}

View File

@ -0,0 +1,25 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void ivaud_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
off_t start_offset;
off_t interleave_size;
int32_t nextFrame=0;
STREAMFILE *streamFile=vgmstream->ch[0].streamfile;
vgmstream->current_block_offset = block_offset;
nextFrame=(read_32bitLE(vgmstream->current_block_offset+0x28,streamFile)<<12)+0x800;
vgmstream->next_block_offset = vgmstream->current_block_offset + nextFrame;
vgmstream->current_block_size=read_32bitLE(block_offset+0x24,streamFile)/2;
start_offset=vgmstream->current_block_offset + 0x800;
interleave_size=(read_32bitLE(block_offset+0x28,streamFile)<<12)/2;
for(i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = start_offset + (i*interleave_size);
}
}

View File

@ -0,0 +1,79 @@
#ifndef _LAYOUT_H
#define _LAYOUT_H
#include "../streamtypes.h"
#include "../vgmstream.h"
void ast_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void mxch_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void render_vgmstream_blocked(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void halpst_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ea_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void eacs_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void caf_block_update(off_t block_offset, VGMSTREAM * vgmstream);
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 matx_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void de2_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void vs_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void emff_ps2_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void emff_ngc_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void gsb_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void xvas_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void filp_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ivaud_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);
void render_vgmstream_interleave_byte(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_aix(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_aax(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void dsp_bdsp_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void tra_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void mtaf_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ps2_iab_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ps2_strlr_block_update(off_t block_offset, VGMSTREAM * vgmstream);
void ps2_mtaf_block_update(off_t block_ofset, VGMSTREAM * vgmstream);
#endif

View File

@ -0,0 +1,50 @@
#include "layout.h"
#include "../vgmstream.h"
#include "../coding/acm_decoder.h"
#include "../coding/coding.h"
void render_vgmstream_mus_acm(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
int samples_written=0;
mus_acm_codec_data *data = vgmstream->codec_data;
while (samples_written<sample_count) {
ACMStream *acm = data->files[data->current_file];
int samples_to_do;
int samples_this_block = acm->total_values / acm->info.channels;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
data->current_file = data->loop_start_file;
acm_reset(data->files[data->current_file]);
vgmstream->samples_into_block = 0;
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, 1, vgmstream);
/*printf("samples_to_do=%d,samples_this_block=%d,samples_written=%d,sample_count=%d\n",samples_to_do,samples_this_block,samples_written,sample_count);*/
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
if (samples_to_do == 0)
{
data->current_file++;
/*printf("next %d, %d samples\n",data->current_file,data->files[data->current_file]->total_values/data->files[data->current_file]->info.channels);*/
/* force loop back to first file in case we're still playing for some
* reason, prevent out of bounds stuff */
if (data->current_file >= data->file_count) data->current_file = 0;
acm_reset(data->files[data->current_file]);
vgmstream->samples_into_block = 0;
continue;
}
/*printf("decode %d samples file %d\n",samples_to_do,data->current_file);*/
decode_acm(acm,
buffer+samples_written*vgmstream->channels,
samples_to_do, vgmstream->channels);
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
}
}

View File

@ -0,0 +1,22 @@
#include "layout.h"
#include "../vgmstream.h"
//MxCh blocked layout as used by Lego Island
void mxch_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset +
read_32bitLE(vgmstream->current_block_offset+4,vgmstream->ch[0].streamfile)+8;
/* skip pad blocks */
while (
read_32bitBE(vgmstream->current_block_offset,
vgmstream->ch[0].streamfile) == 0x70616420)
{
vgmstream->current_block_offset = vgmstream->next_block_offset;
vgmstream->next_block_offset = vgmstream->current_block_offset +
read_32bitLE(vgmstream->current_block_offset+4,vgmstream->ch[0].streamfile)+8;
}
vgmstream->current_block_size =
read_32bitLE(vgmstream->current_block_offset+4, vgmstream->ch[0].streamfile)-0xe;
// only one channel for now
vgmstream->ch[0].offset = vgmstream->current_block_offset+8+0xe;
}

View File

@ -0,0 +1,28 @@
#include "layout.h"
#include "../vgmstream.h"
void render_vgmstream_nolayout(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
int samples_written=0;
const int samples_this_block = vgmstream->num_samples;
int samples_per_frame = get_vgmstream_samples_per_frame(vgmstream);
while (samples_written<sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
continue;
}
samples_to_do = vgmstream_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_written+samples_to_do > sample_count)
samples_to_do=sample_count-samples_written;
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer);
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block+=samples_to_do;
}
}

View File

@ -0,0 +1,18 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void ps2_adm_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = 0x1000; /*read_32bitLE(
vgmstream->current_block_offset+0x10,
vgmstream->ch[0].streamfile); */
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size;
//vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+(0x400*i);
}
}

View File

@ -0,0 +1,17 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void ps2_iab_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset+0x08,vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x10;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x10+(vgmstream->current_block_size*i);
}
}

View File

@ -0,0 +1,19 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void ps2_strlr_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(
vgmstream->current_block_offset+0x4,
vgmstream->ch[0].streamfile)*2;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x40;
//vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x20+(0x800*i);
}
}

View File

@ -0,0 +1,17 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void psx_mgav_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(vgmstream->current_block_offset+0x04,vgmstream->ch[0].streamfile)-0x1C;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+0x1C;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+0x1C+(vgmstream->current_block_size*i);
}
}

View File

@ -0,0 +1,38 @@
#include "layout.h"
#include "../vgmstream.h"
/* TODO: currently only properly handles mono substreams */
/* TODO: there must be a reasonable way to respect the loop settings, as is
the substreams are in their own little world */
#define INTERLEAVE_BUF_SIZE 512
void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
sample interleave_buf[INTERLEAVE_BUF_SIZE];
int32_t samples_done = 0;
scd_int_codec_data *data = vgmstream->codec_data;
while (samples_done < sample_count)
{
int32_t samples_to_do = INTERLEAVE_BUF_SIZE;
int c;
if (samples_to_do > sample_count - samples_done)
samples_to_do = sample_count - samples_done;
for (c=0; c < data->substream_count; c++)
{
int32_t i;
render_vgmstream(interleave_buf,
samples_to_do, data->substreams[c]);
for (i=0; i < samples_to_do; i++)
{
buffer[(samples_done+i)*data->substream_count + c] = interleave_buf[i];
}
}
samples_done += samples_to_do;
}
}

View File

@ -0,0 +1,54 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void str_snds_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
off_t current_chunk;
size_t file_size;
int i;
STREAMFILE *streamfile;
int FoundSSMP = 0;
off_t SSMP_offset = -1;
current_chunk = block_offset;
streamfile = vgmstream->ch[0].streamfile;
file_size = get_streamfile_size(streamfile);
/* we may have to skip some chunks */
while (!FoundSSMP && current_chunk < file_size) {
if (current_chunk+read_32bitBE(current_chunk+4,streamfile)>=file_size)
break;
switch (read_32bitBE(current_chunk,streamfile)) {
case 0x534e4453: /* SNDS */
/* SSMP */
if (read_32bitBE(current_chunk+0x10,streamfile)==0x53534d50) {
FoundSSMP = 1;
SSMP_offset = current_chunk;
}
break;
case 0x46494c4c: /* FILL, the main culprit */
default:
break;
}
current_chunk += read_32bitBE(current_chunk+4,streamfile);
}
if (!FoundSSMP) {
/* if we couldn't find it all we can do is try playing the current
* block, which is going to suck */
vgmstream->current_block_offset = block_offset;
}
vgmstream->current_block_offset = SSMP_offset;
vgmstream->current_block_size = (read_32bitBE(
vgmstream->current_block_offset+4,
vgmstream->ch[0].streamfile) - 0x18) / vgmstream->channels;
vgmstream->next_block_offset = vgmstream->current_block_offset +
read_32bitBE(vgmstream->current_block_offset+4,
vgmstream->ch[0].streamfile);
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x18;
}
}

View File

@ -0,0 +1,31 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void thp_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i,j;
STREAMFILE *streamFile=vgmstream->ch[0].streamfile;
off_t start_offset;
int32_t nextFrameSize;
vgmstream->current_block_offset = block_offset;
nextFrameSize=read_32bitBE(vgmstream->current_block_offset,streamFile);
vgmstream->next_block_offset = vgmstream->current_block_offset
+ vgmstream->thpNextFrameSize;
vgmstream->thpNextFrameSize=nextFrameSize;
start_offset=vgmstream->current_block_offset
+ read_32bitBE(vgmstream->current_block_offset+0x08,streamFile)+0x10;
vgmstream->current_block_size=read_32bitBE(start_offset,streamFile);
start_offset+=8;
for(i=0;i<vgmstream->channels;i++) {
for(j=0;j<16;j++) {
vgmstream->ch[i].adpcm_coef[j]=read_16bitBE(start_offset+(i*0x20)+(j*2),streamFile);
}
vgmstream->ch[i].adpcm_history1_16=read_16bitBE(start_offset + (0x20*vgmstream->channels) + (i*4),streamFile);
vgmstream->ch[i].adpcm_history2_16=read_16bitBE(start_offset + (0x20*vgmstream->channels) + (i*4) + 2,streamFile);
vgmstream->ch[i].offset = start_offset + (0x24*vgmstream->channels)+(i*vgmstream->current_block_size);
}
}

View File

@ -0,0 +1,17 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset (first 32bytes is useless for decoding) */
void tra_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = 0x400;
vgmstream->next_block_offset = vgmstream->current_block_offset+vgmstream->current_block_size+8;
vgmstream->current_block_size/=vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset+(vgmstream->current_block_size*i)+0x4*(i+1);
}
}

View File

@ -0,0 +1,17 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void vs_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->current_block_offset = block_offset;
vgmstream->current_block_size = read_32bitLE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile);
vgmstream->next_block_offset = vgmstream->current_block_offset + vgmstream->current_block_size + 0x4;
vgmstream->ch[i].offset = vgmstream->current_block_offset + 0x4;
if(i==0) block_offset=vgmstream->next_block_offset;
}
}

View File

@ -0,0 +1,24 @@
#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;
if (vgmstream->coding_type == coding_WS) {
vgmstream->ws_output_size = read_16bitLE(
vgmstream->current_block_offset+2,
vgmstream->ch[0].streamfile);
}
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
8 + vgmstream->current_block_size*i;
}
}

View File

@ -0,0 +1,23 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void wsi_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
/* assume that all channels have the same size for this block */
vgmstream->current_block_offset = block_offset;
/* current_block_size is the data size in this block, so subtract header */
vgmstream->current_block_size = read_32bitBE(
vgmstream->current_block_offset,
vgmstream->ch[0].streamfile) - 0x10;
vgmstream->next_block_offset =
vgmstream->current_block_offset +
(vgmstream->current_block_size + 0x10) * vgmstream->channels;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset +
0x10 + (vgmstream->current_block_size+0x10)*i;
}
}

View File

@ -0,0 +1,51 @@
#include "layout.h"
#include "../coding/coding.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void xa_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
int8_t currentChannel=0;
int8_t subAudio=0;
init_get_high_nibble(vgmstream);
if(vgmstream->samples_into_block!=0)
// don't change this variable in the init process
vgmstream->xa_sector_length+=128;
// We get to the end of a sector ?
if(vgmstream->xa_sector_length==(18*128)) {
vgmstream->xa_sector_length=0;
// 0x30 of unused bytes/sector :(
if (!vgmstream->xa_headerless) {
block_offset+=0x30;
begin:
// Search for selected channel & valid audio
currentChannel=read_8bit(block_offset-7,vgmstream->ch[0].streamfile);
subAudio=read_8bit(block_offset-6,vgmstream->ch[0].streamfile);
// audio is coded as 0x64
if(!((subAudio==0x64) && (currentChannel==vgmstream->xa_channel))) {
// go to next sector
block_offset+=2352;
if(currentChannel!=-1) goto begin;
}
}
}
vgmstream->current_block_offset = block_offset;
// Quid : how to stop the current channel ???
// i set up 0 to current_block_size to make vgmstream not playing bad samples
// another way to do it ???
// (as the number of samples can be false in cd-xa due to multi-channels)
vgmstream->current_block_size = (currentChannel==-1?0:112);
vgmstream->next_block_offset = vgmstream->current_block_offset+128;
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset;
}
}

View File

@ -0,0 +1,24 @@
#include "layout.h"
#include "../vgmstream.h"
/* set up for the block at the given offset */
void xvas_block_update(off_t block_offset, VGMSTREAM * vgmstream) {
int i;
vgmstream->current_block_offset = block_offset;
if((vgmstream->current_block_offset-get_streamfile_size(vgmstream->ch[0].streamfile))>(0x20000-0x20))
vgmstream->current_block_size = 0x20000-0x20;
else
vgmstream->current_block_size = vgmstream->current_block_offset-get_streamfile_size(vgmstream->ch[0].streamfile)-0x20;
vgmstream->next_block_offset =
vgmstream->current_block_offset +
(vgmstream->current_block_size + 0x20);
for (i=0;i<vgmstream->channels;i++) {
vgmstream->ch[i].offset = vgmstream->current_block_offset;
}
vgmstream->current_block_size /=2;
}

View File

@ -0,0 +1,69 @@
#include "meta.h"
#include "../util.h"
/* 2DX9 (found in beatmaniaIIDX16 - EMPRESS (Arcade) */
VGMSTREAM * init_vgmstream_2dx9(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("2dx9",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x32445839) /* 2DX9 */
goto fail;
if (read_32bitBE(0x18,streamFile) != 0x52494646) /* RIFF */
goto fail;
if (read_32bitBE(0x20,streamFile) != 0x57415645) /* WAVE */
goto fail;
if (read_32bitBE(0x24,streamFile) != 0x666D7420) /* fmt */
goto fail;
if (read_32bitBE(0x6a,streamFile) != 0x64617461) /* data */
goto fail;
loop_flag = 0;
channel_count = read_16bitLE(0x2e,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x72;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x30,streamFile);
vgmstream->coding_type = coding_MSADPCM;
vgmstream->num_samples = read_32bitLE(0x66,streamFile);
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = read_16bitLE(0x38,streamFile);
vgmstream->meta_type = meta_2DX9;
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,303 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
/* .dsp w/ Cstr header, seen in Star Fox Assault and Donkey Konga */
VGMSTREAM * init_vgmstream_Cstr(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag;
off_t start_offset;
off_t first_data;
off_t loop_offset;
size_t interleave;
int loop_adjust;
int double_loop_end = 0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("dsp",filename_extension(filename))) goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x43737472) /* "Cstr" */
goto fail;
#ifdef DEBUG
fprintf(stderr,"header ok\n");
#endif
if (read_8bit(0x1b,streamFile)==1) {
/* mono version, much simpler to handle */
/* Only seen in R Racing Evolution radio sfx */
start_offset = 0x80;
loop_flag = read_16bitBE(0x2c,streamFile);
/* check initial predictor/scale */
if (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(start_offset,streamFile))
goto fail;
/* check type==0 and gain==0 */
if (read_16bitBE(0x2e,streamFile) || read_16bitBE(0x5c,streamFile))
goto fail;
loop_offset = start_offset+read_32bitBE(0x10,streamFile);
if (loop_flag) {
if (read_16bitBE(0x64,streamFile) != (uint8_t)read_8bit(loop_offset,streamFile)) goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(1,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
vgmstream->num_samples = read_32bitBE(0x20,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = dsp_nibbles_to_samples(
read_32bitBE(0x30,streamFile));
vgmstream->loop_end_sample = dsp_nibbles_to_samples(
read_32bitBE(0x34,streamFile))+1;
}
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_DSP_CSTR;
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x3c+i*2,streamFile);
}
/* open the file for reading by each channel */
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
vgmstream->ch[0].channel_start_offset=
vgmstream->ch[0].offset=
start_offset;
return vgmstream;
} /* end mono */
interleave = read_16bitBE(0x06,streamFile);
start_offset = 0xe0;
first_data = start_offset+read_32bitBE(0x0c,streamFile);
loop_flag = read_16bitBE(0x2c,streamFile);
if (!loop_flag) {
/* Nonlooped tracks seem to follow no discernable pattern
* with where they actually start.
* But! with the magic of initial p/s redundancy, we can guess.
*/
while (first_data<start_offset+0x800 &&
(read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(first_data,streamFile) ||
read_16bitBE(0xbe,streamFile) != (uint8_t)read_8bit(first_data+interleave,streamFile)))
first_data+=8;
#ifdef DEBUG
fprintf(stderr,"guessed first_data at %#x\n",first_data);
#endif
}
/* check initial predictor/scale */
if (read_16bitBE(0x5e,streamFile) != (uint8_t)read_8bit(first_data,streamFile))
goto fail;
if (read_16bitBE(0xbe,streamFile) != (uint8_t)read_8bit(first_data+interleave,streamFile))
goto fail;
#ifdef DEBUG
fprintf(stderr,"p/s ok\n");
#endif
/* check type==0 and gain==0 */
if (read_16bitBE(0x2e,streamFile) || read_16bitBE(0x5c,streamFile))
goto fail;
if (read_16bitBE(0x8e,streamFile) || read_16bitBE(0xbc,streamFile))
goto fail;
#ifdef DEBUG
fprintf(stderr,"type & gain ok\n");
#endif
/* check for loop flag agreement */
if (read_16bitBE(0x2c,streamFile) != read_16bitBE(0x8c,streamFile))
goto fail;
#ifdef DEBUG
fprintf(stderr,"loop flags agree\n");
#endif
loop_offset = start_offset+read_32bitBE(0x10,streamFile)*2;
if (loop_flag) {
int loops_ok=0;
/* check loop predictor/scale */
/* some fuzz allowed */
for (loop_adjust=0;loop_adjust>=-0x10;loop_adjust-=8) {
#ifdef DEBUG
fprintf(stderr,"looking for loop p/s at %#x,%#x\n",loop_offset-interleave+loop_adjust,loop_offset+loop_adjust);
#endif
if (read_16bitBE(0x64,streamFile) == (uint8_t)read_8bit(loop_offset-interleave+loop_adjust,streamFile) &&
read_16bitBE(0xc4,streamFile) == (uint8_t)read_8bit(loop_offset+loop_adjust,streamFile)) {
loops_ok=1;
break;
}
}
if (!loops_ok)
for (loop_adjust=interleave;loop_adjust<=interleave+0x10;loop_adjust+=8) {
#ifdef DEBUG
fprintf(stderr,"looking for loop p/s at %#x,%#x\n",loop_offset-interleave+loop_adjust,loop_offset+loop_adjust);
#endif
if (read_16bitBE(0x64,streamFile) == (uint8_t)read_8bit(loop_offset-interleave+loop_adjust,streamFile) &&
read_16bitBE(0xc4,streamFile) == (uint8_t)read_8bit(loop_offset+loop_adjust,streamFile)) {
loops_ok=1;
break;
}
}
if (!loops_ok) goto fail;
#ifdef DEBUG
fprintf(stderr,"loop p/s ok (with %#4x adjust)\n",loop_adjust);
#endif
/* check for agreement */
/* loop end (channel 1 & 2 headers) */
if (read_32bitBE(0x34,streamFile) != read_32bitBE(0x94,streamFile))
goto fail;
/* Mr. Driller oddity */
if (dsp_nibbles_to_samples(read_32bitBE(0x34,streamFile)*2)+1 <= read_32bitBE(0x20,streamFile)) {
#ifdef DEBUG
fprintf(stderr,"loop end <= half total samples, should be doubled\n");
#endif
double_loop_end = 1;
}
/* loop start (Cstr header and channel 1 header) */
if (read_32bitBE(0x30,streamFile) != read_32bitBE(0x10,streamFile)
#if 0
/* this particular glitch only true for SFA, though it
* seems like something similar happens in Donkey Konga */
/* loop start (Cstr, channel 1 & 2 headers) */
|| (read_32bitBE(0x0c,streamFile)+read_32bitLE(0x30,streamFile)) !=
read_32bitBE(0x90,streamFile)
#endif
)
/* alternatively (Donkey Konga) the header loop is 0x0c+0x10 */
if (
/* loop start (Cstr header and channel 1 header) */
read_32bitBE(0x30,streamFile) != read_32bitBE(0x10,streamFile)+
read_32bitBE(0x0c,streamFile))
/* further alternatively (Donkey Konga), if we loop back to
* the very first frame 0x30 might be 0x00000002 (which
* is a *valid* std dsp loop start, imagine that) while 0x10
* is 0x00000000 */
if (!(read_32bitBE(0x30,streamFile) == 2 &&
read_32bitBE(0x10,streamFile) == 0))
/* lest there be too few alternatives, in Mr. Driller we
* find that [0x30] + [0x0c] + 8 = [0x10]*2 */
if (!(double_loop_end &&
read_32bitBE(0x30,streamFile) +
read_32bitBE(0x0c,streamFile) + 8 ==
read_32bitBE(0x10,streamFile)*2))
goto fail;
#ifdef DEBUG
fprintf(stderr,"loop points agree\n");
#endif
}
/* assure that sample counts, sample rates agree */
if (
/* sample count (channel 1 & 2 headers) */
read_32bitBE(0x20,streamFile) != read_32bitBE(0x80,streamFile) ||
/* sample rate (channel 1 & 2 headers) */
read_32bitBE(0x28,streamFile) != read_32bitBE(0x88,streamFile) ||
/* sample count (Cstr header and channel 1 header) */
read_32bitLE(0x14,streamFile) != read_32bitBE(0x20,streamFile) ||
/* sample rate (Cstr header and channel 1 header) */
(uint16_t)read_16bitLE(0x18,streamFile) != read_32bitBE(0x28,streamFile))
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(2,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->sample_rate = read_32bitBE(0x28,streamFile);
/* This is a slight hack to counteract their hack.
* All the data is ofset by first_data so that the loop
* point occurs at a block boundary. However, I always begin decoding
* right after the header, as that is the start of the first block and
* my interleave code relies on starting at the beginning of a block.
* So we decode a few silent samples at the beginning, and here we make up
* for it by lengthening the track by that much.
*/
vgmstream->num_samples = read_32bitBE(0x20,streamFile) +
(first_data-start_offset)/8*14;
if (loop_flag) {
off_t loop_start_bytes = loop_offset-start_offset-interleave;
vgmstream->loop_start_sample = dsp_nibbles_to_samples((loop_start_bytes/(2*interleave)*interleave+loop_start_bytes%(interleave*2))*2);
/*dsp_nibbles_to_samples(loop_start_bytes);*/
/*dsp_nibbles_to_samples(read_32bitBE(0x30,streamFile)*2-inter);*/
vgmstream->loop_end_sample = dsp_nibbles_to_samples(
read_32bitBE(0x34,streamFile))+1;
if (double_loop_end)
vgmstream->loop_end_sample =
dsp_nibbles_to_samples(read_32bitBE(0x34,streamFile)*2)+1;
if (vgmstream->loop_end_sample > vgmstream->num_samples) {
#ifdef DEBUG
fprintf(stderr,"loop_end_sample > num_samples, adjusting\n");
#endif
vgmstream->loop_end_sample = vgmstream->num_samples;
}
}
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = interleave;
vgmstream->meta_type = meta_DSP_CSTR;
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(0x3c+i*2,streamFile);
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i]=read_16bitBE(0x9c+i*2,streamFile);
}
#ifdef DEBUG
vgmstream->ch[0].loop_history1 = read_16bitBE(0x66,streamFile);
vgmstream->ch[0].loop_history2 = read_16bitBE(0x68,streamFile);
vgmstream->ch[1].loop_history1 = read_16bitBE(0xc6,streamFile);
vgmstream->ch[1].loop_history2 = read_16bitBE(0xc8,streamFile);
#endif
/* open the file for reading by each channel */
{
int i;
for (i=0;i<2;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,interleave);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
start_offset+interleave*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,241 @@
noinst_LTLIBRARIES = libmeta.la
AM_CFLAGS = -Wall @CFLAGS@ -I$(top_builddir) -I$(top_srcdir)
AM_MAKEFLAGS=-f Makefile.unix
libmeta_la_LDFLAGS =
libmeta_la_SOURCES =
libmeta_la_SOURCES += Cstr.c
libmeta_la_SOURCES += adx_header.c
libmeta_la_SOURCES += afc_header.c
libmeta_la_SOURCES += agsc.c
libmeta_la_SOURCES += ast.c
libmeta_la_SOURCES += brstm.c
libmeta_la_SOURCES += ea_header.c
libmeta_la_SOURCES += gcsw.c halpst.c
libmeta_la_SOURCES += nds_strm.c
libmeta_la_SOURCES += ngc_adpdtk.c
libmeta_la_SOURCES += ngc_caf.c
libmeta_la_SOURCES += ngc_dsp_std.c
libmeta_la_SOURCES += ps2_ads.c
libmeta_la_SOURCES += ps2_exst.c
libmeta_la_SOURCES += ps2_ild.c
libmeta_la_SOURCES += ps2_int.c
libmeta_la_SOURCES += ps2_mib.c
libmeta_la_SOURCES += ps2_mic.c
libmeta_la_SOURCES += ps2_npsf.c
libmeta_la_SOURCES += ps2_pnb.c
libmeta_la_SOURCES += ps2_rxw.c
libmeta_la_SOURCES += ps2_str.c
libmeta_la_SOURCES += ps2_svag.c
libmeta_la_SOURCES += ps2_vag.c
libmeta_la_SOURCES += ps2_vpk.c
libmeta_la_SOURCES += psx_cdxa.c
libmeta_la_SOURCES += raw.c
libmeta_la_SOURCES += rs03.c
libmeta_la_SOURCES += rsf.c
libmeta_la_SOURCES += rwsd.c
libmeta_la_SOURCES += psx_gms.c
libmeta_la_SOURCES += xbox_xwav.c
libmeta_la_SOURCES += xbox_wavm.c
libmeta_la_SOURCES += genh.c
libmeta_la_SOURCES += ogg_vorbis_file.c
libmeta_la_SOURCES += ps2_bmdx.c
libmeta_la_SOURCES += aifc.c
libmeta_la_SOURCES += str_snds.c
libmeta_la_SOURCES += ws_aud.c
libmeta_la_SOURCES += ahx.c
libmeta_la_SOURCES += ivb.c
libmeta_la_SOURCES += svs.c
libmeta_la_SOURCES += riff.c
libmeta_la_SOURCES += pos.c
libmeta_la_SOURCES += nwa.c
libmeta_la_SOURCES += ps2_rws.c
libmeta_la_SOURCES += ps2_hgc1.c
libmeta_la_SOURCES += xss.c
libmeta_la_SOURCES += ps2_sl3.c
libmeta_la_SOURCES += ps2_aus.c
libmeta_la_SOURCES += fsb.c
libmeta_la_SOURCES += rsd.c
libmeta_la_SOURCES += rwx.c
libmeta_la_SOURCES += xwb.c
libmeta_la_SOURCES += ea_old.c
libmeta_la_SOURCES += ps2_xa30.c
libmeta_la_SOURCES += musc.c
libmeta_la_SOURCES += ps2_leg.c
libmeta_la_SOURCES += ps2_filp.c
libmeta_la_SOURCES += ps2_ikm.c
libmeta_la_SOURCES += musx.c
libmeta_la_SOURCES += ps2_sfs.c
libmeta_la_SOURCES += sat_dvi.c
libmeta_la_SOURCES += ps2_bg00.c
libmeta_la_SOURCES += dc_kcey.c
libmeta_la_SOURCES += ps2_rstm.c
libmeta_la_SOURCES += acm.c
libmeta_la_SOURCES += ps2_kces.c
libmeta_la_SOURCES += ps2_dxh.c
libmeta_la_SOURCES += ps2_psh.c
libmeta_la_SOURCES += mus_acm.c
libmeta_la_SOURCES += sli.c
libmeta_la_SOURCES += sfl.c
libmeta_la_SOURCES += pcm.c
libmeta_la_SOURCES += ps2_psw.c
libmeta_la_SOURCES += rkv.c
libmeta_la_SOURCES += ps2_vas.c
libmeta_la_SOURCES += ps2_tec.c
libmeta_la_SOURCES += ps2_enth.c
libmeta_la_SOURCES += sdt.c
libmeta_la_SOURCES += aix.c
libmeta_la_SOURCES += ngc_tydsp.c
libmeta_la_SOURCES += wvs.c
libmeta_la_SOURCES += xbox_stma.c
libmeta_la_SOURCES += xbox_ims.c
libmeta_la_SOURCES += de2.c
libmeta_la_SOURCES += dc_str.c
libmeta_la_SOURCES += xbox_xmu.c
libmeta_la_SOURCES += ngc_bh2pcm.c
libmeta_la_SOURCES += sat_sap.c
libmeta_la_SOURCES += dc_idvi.c
libmeta_la_SOURCES += ps2_rnd.c
libmeta_la_SOURCES += xbox_xvas.c
libmeta_la_SOURCES += kraw.c
libmeta_la_SOURCES += ps2_xa2.c
libmeta_la_SOURCES += idsp.c
libmeta_la_SOURCES += ngc_ymf.c
libmeta_la_SOURCES += nds_sad.c
libmeta_la_SOURCES += ps2_ccc.c
libmeta_la_SOURCES += psx_fag.c
libmeta_la_SOURCES += ps2_mihb.c
libmeta_la_SOURCES += ngc_pdt.c
libmeta_la_SOURCES += wii_mus.c
libmeta_la_SOURCES += dc_asd.c
libmeta_la_SOURCES += naomi_spsd.c
libmeta_la_SOURCES += bgw.c
libmeta_la_SOURCES += ps2_ass.c
libmeta_la_SOURCES += ngc_waa_wac_wad_wam.c
libmeta_la_SOURCES += seg.c
libmeta_la_SOURCES += str_asr.c
libmeta_la_SOURCES += zwdsp.c
libmeta_la_SOURCES += gca.c
libmeta_la_SOURCES += ish_isd.c
libmeta_la_SOURCES += spt_spd.c
libmeta_la_SOURCES += ydsp.c
libmeta_la_SOURCES += gsp_gsb.c
libmeta_la_SOURCES += ngc_ssm.c
libmeta_la_SOURCES += msvp.c
libmeta_la_SOURCES += ps2_joe.c
libmeta_la_SOURCES += vs.c
libmeta_la_SOURCES += vgs.c
libmeta_la_SOURCES += dc_dcsw_dcs.c
libmeta_la_SOURCES += wii_smp.c
libmeta_la_SOURCES += ss_stream.c
libmeta_la_SOURCES += emff.c
libmeta_la_SOURCES += thp.c
libmeta_la_SOURCES += wii_sts.c
libmeta_la_SOURCES += capdsp.c
libmeta_la_SOURCES += wii_sng.c
libmeta_la_SOURCES += aax.c
libmeta_la_SOURCES += ps2_p2bt.c
libmeta_la_SOURCES += ps2_gbts.c
libmeta_la_SOURCES += ngc_ffcc_str.c
libmeta_la_SOURCES += sat_baka.c
libmeta_la_SOURCES += nds_swav.c
libmeta_la_SOURCES += vsf.c
libmeta_la_SOURCES += nds_rrds.c
libmeta_la_SOURCES += ps2_tk5.c
libmeta_la_SOURCES += ads.c
libmeta_la_SOURCES += wii_str.c
libmeta_la_SOURCES += zsd.c
libmeta_la_SOURCES += ps2_mcg.c
libmeta_la_SOURCES += redspark.c
libmeta_la_SOURCES += ivaud.c
libmeta_la_SOURCES += ps2_vgs.c
libmeta_la_SOURCES += ps2_sps.c
libmeta_la_SOURCES += nds_hwas.c
libmeta_la_SOURCES += ngc_lps.c
libmeta_la_SOURCES += ps2_snd.c
libmeta_la_SOURCES += naomi_adpcm.c
libmeta_la_SOURCES += sd9.c
libmeta_la_SOURCES += 2dx9.c
libmeta_la_SOURCES += ngc_dsp_ygo.c
libmeta_la_SOURCES += ps2_vgv.c
libmeta_la_SOURCES += ngc_gcub.c
libmeta_la_SOURCES += maxis_xa.c
libmeta_la_SOURCES += ngc_sck_dsp.c
libmeta_la_SOURCES += apple_caff.c
libmeta_la_SOURCES += pc_mxst.c
libmeta_la_SOURCES += pc_sob.c
libmeta_la_SOURCES += exakt_sc.c
libmeta_la_SOURCES += wii_bns.c
libmeta_la_SOURCES += pona.c
libmeta_la_SOURCES += xbox_hlwav.c
libmeta_la_SOURCES += stx.c
libmeta_la_SOURCES += ps2_stm.c
libmeta_la_SOURCES += myspd.c
libmeta_la_SOURCES += his.c
libmeta_la_SOURCES += ps2_ast.c
libmeta_la_SOURCES += dmsg_segh.c
libmeta_la_SOURCES += ngc_dsp_konami.c
libmeta_la_SOURCES += ps2_ster.c
libmeta_la_SOURCES += bnsf.c
libmeta_la_SOURCES += ps2_wb.c
libmeta_la_SOURCES += s14_sss.c
libmeta_la_SOURCES += ps2_gcm.c
libmeta_la_SOURCES += ps2_smpl.c
libmeta_la_SOURCES += ps2_msa.c
libmeta_la_SOURCES += pc_smp.c
libmeta_la_SOURCES += p3d.c
libmeta_la_SOURCES += ps2_adsc.c
libmeta_la_SOURCES += psx_str_mgav.c
libmeta_la_SOURCES += ngc_bo2.c
libmeta_la_SOURCES += ngc_dsp_mpds.c
libmeta_la_SOURCES += ps2_khv.c
libmeta_la_SOURCES += ps2_voi.c
libmeta_la_SOURCES += dsp_sth_str.c
libmeta_la_SOURCES += ps2_b1s.c
libmeta_la_SOURCES += ps2_wad.c
libmeta_la_SOURCES += ps2_lpcm.c
libmeta_la_SOURCES += ps2_adm.c
libmeta_la_SOURCES += dsp_bdsp.c
libmeta_la_SOURCES += ps2_vms.c
libmeta_la_SOURCES += ps2_xau.c
libmeta_la_SOURCES += gh3_bar.c
libmeta_la_SOURCES += ffw.c
libmeta_la_SOURCES += ps2_jstm.c
libmeta_la_SOURCES += ps3_xvag.c
libmeta_la_SOURCES += ps3_cps.c
libmeta_la_SOURCES += sqex_scd.c
libmeta_la_SOURCES += ngc_nst_dsp.c
libmeta_la_SOURCES += baf.c
libmeta_la_SOURCES += ps3_msf.c
libmeta_la_SOURCES += nub.c
libmeta_la_SOURCES += ps3_past.c
libmeta_la_SOURCES += ps3_sgh_sgb.c
libmeta_la_SOURCES += ngca.c
libmeta_la_SOURCES += wii_ras.c
libmeta_la_SOURCES += ps2_spm.c
libmeta_la_SOURCES += x360_tra.c
libmeta_la_SOURCES += ps2_iab.c
libmeta_la_SOURCES += ps2_strlr.c
libmeta_la_SOURCES += lsf.c
libmeta_la_SOURCES += ps3_vawx.c
libmeta_la_SOURCES += pc_snds.c
libmeta_la_SOURCES += ps2_wmus.c
libmeta_la_SOURCES += mattel_hyperscan.c
libmeta_la_SOURCES += ios_psnd.c
libmeta_la_SOURCES += pc_adp.c
libmeta_la_SOURCES += excitebots.c
libmeta_la_SOURCES += ps2_mtaf.c
libmeta_la_SOURCES += ps3_klbs.c
libmeta_la_SOURCES += tun.c
libmeta_la_SOURCES += wpd.c
libmeta_la_SOURCES += mn_str.c
libmeta_la_SOURCES += ps2_mss.c
libmeta_la_SOURCES += ps2_hsf.c
libmeta_la_SOURCES += ps3_ivag.c
libmeta_la_SOURCES += ps2_2pfs.c
libmeta_la_SOURCES += ubi_ckd.c
libmeta_la_SOURCES += otm.c
libmeta_la_SOURCES += bcstm.c
EXTRA_DIST = meta.h

View File

@ -0,0 +1,846 @@
#include "../vgmstream.h"
#include "meta.h"
#include "../util.h"
typedef struct _AAXSTREAMFILE
{
STREAMFILE sf;
STREAMFILE *real_file;
off_t start_physical_offset;
size_t file_size;
} AAXSTREAMFILE;
static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size);
struct utf_query
{
/* if 0 */
const char *name;
int index;
};
struct offset_size_pair
{
uint32_t offset;
uint32_t size;
};
struct utf_query_result
{
int valid; /* table is valid */
int found;
int type; /* one of COLUMN_TYPE_* */
union
{
uint64_t value_u64;
uint32_t value_u32;
uint16_t value_u16;
uint8_t value_u8;
float value_float;
struct offset_size_pair value_data;
uint32_t value_string;
} value;
/* info for the queried table */
uint32_t rows;
uint32_t name_offset;
uint32_t string_table_offset;
uint32_t data_offset;
};
static struct utf_query_result analyze_utf(STREAMFILE *infile, long offset,
const struct utf_query *query);
static struct utf_query_result query_utf(STREAMFILE *infile, long offset,
const struct utf_query *query);
static struct utf_query_result query_utf_nofail(STREAMFILE *infile, const long offset,
const struct utf_query *query, int *error);
static struct utf_query_result query_utf_key(STREAMFILE *infile, const long offset,
int index, const char *name, int *error);
static uint8_t query_utf_1byte(STREAMFILE *infile, const long offset,
int index, const char *name, int *error);
static struct offset_size_pair query_utf_data(STREAMFILE *infile, const long offset,
int index, const char *name, int *error);
#define COLUMN_STORAGE_MASK 0xf0
#define COLUMN_STORAGE_PERROW 0x50
#define COLUMN_STORAGE_CONSTANT 0x30
#define COLUMN_STORAGE_ZERO 0x10
#define COLUMN_TYPE_MASK 0x0f
#define COLUMN_TYPE_DATA 0x0b
#define COLUMN_TYPE_STRING 0x0a
#define COLUMN_TYPE_FLOAT 0x08
#define COLUMN_TYPE_8BYTE 0x06
#define COLUMN_TYPE_4BYTE 0x04
#define COLUMN_TYPE_2BYTE2 0x03
#define COLUMN_TYPE_2BYTE 0x02
#define COLUMN_TYPE_1BYTE2 0x01
#define COLUMN_TYPE_1BYTE 0x00
struct utf_column_info
{
uint8_t type;
const char *column_name;
long constant_offset;
};
struct utf_table_info
{
long table_offset;
uint32_t table_size;
uint32_t schema_offset;
uint32_t rows_offset;
uint32_t string_table_offset;
uint32_t data_offset;
const char *string_table;
const char *table_name;
uint16_t columns;
uint16_t row_width;
uint32_t rows;
const struct utf_column_info *schema;
};
/* Actual AAX init fcn */
VGMSTREAM * init_vgmstream_aax(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileAAX = NULL;
STREAMFILE * streamFileADX = NULL;
char filename[PATH_LIMIT];
off_t *segment_offset = NULL;
off_t *segment_size = NULL;
int32_t sample_count;
int table_error = 0;
int loop_flag = 0;
int32_t loop_start_sample=0;
int32_t loop_end_sample=0;
int loop_segment = 0;
aax_codec_data *data = NULL;
const long AAX_offset = 0;
int channel_count = 0, segment_count;
int sample_rate = 0;
int i;
long aax_data_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("aax",filename_extension(filename))) goto fail;
/* get AAX entry count, data offset */
{
struct utf_query_result result;
long aax_string_table_offset;
long aax_string_table_size;
result = query_utf_nofail(streamFile, AAX_offset, NULL, &table_error);
if (table_error) goto fail;
segment_count = result.rows;
aax_string_table_offset = AAX_offset + 8 + result.string_table_offset;
aax_data_offset = AAX_offset + 8 + result.data_offset;
aax_string_table_size = aax_data_offset - aax_string_table_offset;
if (result.name_offset+4 > aax_string_table_size) goto fail;
if (read_32bitBE(aax_string_table_offset + result.name_offset,
streamFile) != 0x41415800) /* "AAX\0" */
goto fail;
}
segment_offset = calloc(segment_count,sizeof(off_t));
if (!segment_offset)
goto fail;
segment_size = calloc(segment_count,sizeof(off_t));
if (!segment_size)
goto fail;
/* get offsets of constituent ADXs */
for (i = 0; i < segment_count; i++)
{
struct offset_size_pair offset_size;
offset_size = query_utf_data(streamFile, AAX_offset, i, "data", &table_error);
if (table_error) goto fail;
segment_offset[i] = aax_data_offset + offset_size.offset;
segment_size[i] = offset_size.size;
}
streamFileAAX = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!streamFileAAX) goto fail;
data = malloc(sizeof(aax_codec_data));
if (!data) goto fail;
data->segment_count = segment_count;
data->adxs = malloc(sizeof(STREAMFILE *)*segment_count);
if (!data->adxs) goto fail;
for (i=0;i<segment_count;i++) {
data->adxs[i] = NULL;
}
data->sample_counts = calloc(segment_count,sizeof(int32_t));
if (!data->sample_counts) goto fail;
/* for each segment */
for (i = 0; i < segment_count; i++)
{
VGMSTREAM *adx;
/*printf("try opening segment %d/%d %x\n",i,segment_count,segment_offset[i]);*/
streamFileADX = open_aax_with_STREAMFILE(streamFileAAX,segment_offset[i],segment_size[i]);
if (!streamFileADX) goto fail;
adx = data->adxs[i] = init_vgmstream_adx(streamFileADX);
if (!adx)
goto fail;
data->sample_counts[i] = adx->num_samples;
close_streamfile(streamFileADX); streamFileADX = NULL;
if (i == 0)
{
channel_count = adx->channels;
sample_rate = adx->sample_rate;
}
else
{
if (channel_count != adx->channels)
goto fail;
if (sample_rate != adx->sample_rate)
goto fail;
}
if (adx->loop_flag != 0)
goto fail;
/* save start things so we can restart for seeking/looping */
/* copy the channels */
memcpy(adx->start_ch,adx->ch,sizeof(VGMSTREAMCHANNEL)*adx->channels);
/* copy the whole VGMSTREAM */
memcpy(adx->start_vgmstream,adx,sizeof(VGMSTREAM));
}
sample_count = 0;
loop_flag = 0;
for (i = 0; i < segment_count; i++)
{
int segment_loop_flag = query_utf_1byte(streamFile, AAX_offset, i,
"lpflg", &table_error);
if (table_error) segment_loop_flag = 0;
if (!loop_flag && segment_loop_flag)
{
loop_start_sample = sample_count;
loop_segment = i;
}
sample_count += data->sample_counts[i];
if (!loop_flag && segment_loop_flag)
{
loop_end_sample = sample_count;
loop_flag = 1;
}
}
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = sample_rate;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->coding_type = data->adxs[0]->coding_type;
vgmstream->layout_type = layout_aax;
vgmstream->meta_type = meta_AAX;
vgmstream->ch[0].streamfile = streamFileAAX;
data->current_segment = 0;
data->loop_segment = loop_segment;
vgmstream->codec_data = data;
free(segment_offset);
free(segment_size);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (streamFileAAX) close_streamfile(streamFileAAX);
if (streamFileADX) close_streamfile(streamFileADX);
if (vgmstream) close_vgmstream(vgmstream);
if (segment_offset) free(segment_offset);
if (segment_size) free(segment_size);
if (data) {
if (data->adxs)
{
int i;
for (i=0;i<data->segment_count;i++)
if (data->adxs)
close_vgmstream(data->adxs[i]);
free(data->adxs);
}
if (data->sample_counts)
{
free(data->sample_counts);
}
free(data);
}
return NULL;
}
/* virtual file, a piece of the overall file */
static size_t read_aax(AAXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
{
/* truncate at end of logical file */
if (offset+length > streamfile->file_size)
{
long signed_length = length;
signed_length = streamfile->file_size - offset;
if (signed_length < 0) signed_length = 0;
length = signed_length;
}
return read_streamfile(dest,
streamfile->start_physical_offset+offset,
length,streamfile->real_file);
}
static void close_aax(AAXSTREAMFILE *streamfile)
{
free(streamfile);
return;
}
static size_t get_size_aax(AAXSTREAMFILE *streamfile)
{
return 0;
}
static size_t get_offset_aax(AAXSTREAMFILE *streamfile)
{
long offset = streamfile->real_file->get_offset(streamfile->real_file);
offset -= streamfile->start_physical_offset;
if (offset < 0) offset = 0;
if (offset > streamfile->file_size) offset = streamfile->file_size;
return offset;
}
static void get_name_aax(AAXSTREAMFILE *streamfile,char *buffer,size_t length)
{
strncpy(buffer,"ARBITRARY.ADX",length);
buffer[length-1]='\0';
}
static STREAMFILE *open_aax_impl(AAXSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
{
AAXSTREAMFILE *newfile;
if (strcmp(filename,"ARBITRARY.ADX"))
return NULL;
newfile = malloc(sizeof(AAXSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(AAXSTREAMFILE));
return &newfile->sf;
}
static STREAMFILE *open_aax_with_STREAMFILE(STREAMFILE *file,off_t start_offset,size_t file_size)
{
AAXSTREAMFILE *streamfile = malloc(sizeof(AAXSTREAMFILE));
if (!streamfile)
return NULL;
/* success, set our pointers */
streamfile->sf.read = (void*)read_aax;
streamfile->sf.get_size = (void*)get_size_aax;
streamfile->sf.get_offset = (void*)get_offset_aax;
streamfile->sf.get_name = (void*)get_name_aax;
streamfile->sf.get_realname = (void*)get_name_aax;
streamfile->sf.open = (void*)open_aax_impl;
streamfile->sf.close = (void*)close_aax;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = NULL;
streamfile->sf.get_error_count = NULL;
#endif
streamfile->real_file = file;
streamfile->start_physical_offset = start_offset;
streamfile->file_size = file_size;
return &streamfile->sf;
}
/* @UTF table reading, abridged */
static struct utf_query_result analyze_utf(STREAMFILE *infile, const long offset, const struct utf_query *query)
{
unsigned char buf[4];
struct utf_table_info table_info;
char *string_table = NULL;
struct utf_column_info * schema = NULL;
struct utf_query_result result;
uint32_t table_name_string;
int string_table_size;
result.valid = 0;
table_info.table_offset = offset;
/* check header */
{
static const char UTF_signature[4] = "@UTF"; /* intentionally unterminated */
if (4 != read_streamfile(buf, offset, 4, infile)) goto cleanup_error;
if (memcmp(buf, UTF_signature, sizeof(UTF_signature)))
{
goto cleanup_error;
}
}
/* get table size */
table_info.table_size = read_32bitBE(offset+4, infile);
table_info.schema_offset = 0x20;
table_info.rows_offset = read_32bitBE(offset+8, infile);
table_info.string_table_offset = read_32bitBE(offset+0xc,infile);
table_info.data_offset = read_32bitBE(offset+0x10,infile);
table_name_string = read_32bitBE(offset+0x14,infile);
table_info.columns = read_16bitBE(offset+0x18,infile);
table_info.row_width = read_16bitBE(offset+0x1a,infile);
table_info.rows = read_32bitBE(offset+0x1c,infile);
/* allocate for string table */
string_table_size = table_info.data_offset-table_info.string_table_offset;
string_table = malloc(string_table_size+1);
if (!string_table) goto cleanup_error;
table_info.string_table = string_table;
memset(string_table, 0, string_table_size+1);
/* load schema */
schema = malloc(sizeof(struct utf_column_info) * table_info.columns);
if (!schema) goto cleanup_error;
{
int i;
long schema_current_offset = table_info.schema_offset;
for (i = 0; i < table_info.columns; i++)
{
schema[i].type = read_8bit(schema_current_offset,infile);
schema_current_offset ++;
schema[i].column_name = string_table + read_32bitBE(schema_current_offset,infile);
schema_current_offset += 4;
if ((schema[i].type & COLUMN_STORAGE_MASK) == COLUMN_STORAGE_CONSTANT)
{
schema[i].constant_offset = schema_current_offset;
switch (schema[i].type & COLUMN_TYPE_MASK)
{
case COLUMN_TYPE_8BYTE:
case COLUMN_TYPE_DATA:
schema_current_offset+=8;
break;
case COLUMN_TYPE_STRING:
case COLUMN_TYPE_FLOAT:
case COLUMN_TYPE_4BYTE:
schema_current_offset+=4;
break;
case COLUMN_TYPE_2BYTE2:
case COLUMN_TYPE_2BYTE:
schema_current_offset+=2;
break;
case COLUMN_TYPE_1BYTE2:
case COLUMN_TYPE_1BYTE:
schema_current_offset++;
break;
default:
goto cleanup_error;
}
}
}
}
table_info.schema = schema;
/* read string table */
read_streamfile((unsigned char *)string_table,
table_info.string_table_offset+8+offset,
string_table_size, infile);
table_info.table_name = table_info.string_table+table_name_string;
/* fill in the default stuff */
result.found = 0;
result.rows = table_info.rows;
result.name_offset = table_name_string;
result.string_table_offset = table_info.string_table_offset;
result.data_offset = table_info.data_offset;
/* explore the values */
if (query) {
int i, j;
for (i = 0; i < table_info.rows; i++)
{
uint32_t row_offset =
table_info.table_offset + 8 + table_info.rows_offset +
i * table_info.row_width;
const uint32_t row_start_offset = row_offset;
if (query && i != query->index) continue;
for (j = 0; j < table_info.columns; j++)
{
uint8_t type = table_info.schema[j].type;
long constant_offset = table_info.schema[j].constant_offset;
int constant = 0;
int qthis = (query && i == query->index &&
!strcmp(table_info.schema[j].column_name, query->name));
if (qthis)
{
result.found = 1;
result.type = schema[j].type & COLUMN_TYPE_MASK;
}
switch (schema[j].type & COLUMN_STORAGE_MASK)
{
case COLUMN_STORAGE_PERROW:
break;
case COLUMN_STORAGE_CONSTANT:
constant = 1;
break;
case COLUMN_STORAGE_ZERO:
if (qthis)
{
memset(&result.value, 0,
sizeof(result.value));
}
continue;
default:
goto cleanup_error;
}
if (1)
{
long data_offset;
int bytes_read;
if (constant)
{
data_offset = constant_offset;
}
else
{
data_offset = row_offset;
}
switch (type & COLUMN_TYPE_MASK)
{
case COLUMN_TYPE_STRING:
{
uint32_t string_offset;
string_offset = read_32bitBE(data_offset, infile);
bytes_read = 4;
if (qthis)
{
result.value.value_string = string_offset;
}
}
break;
case COLUMN_TYPE_DATA:
{
uint32_t vardata_offset, vardata_size;
vardata_offset = read_32bitBE(data_offset, infile);
vardata_size = read_32bitBE(data_offset+4, infile);
bytes_read = 8;
if (qthis)
{
result.value.value_data.offset = vardata_offset;
result.value.value_data.size = vardata_size;
}
}
break;
case COLUMN_TYPE_8BYTE:
{
uint64_t value =
read_32bitBE(data_offset, infile);
value <<= 32;
value |=
read_32bitBE(data_offset+4, infile);
if (qthis)
{
result.value.value_u64 = value;
}
bytes_read = 8;
break;
}
case COLUMN_TYPE_4BYTE:
{
uint32_t value =
read_32bitBE(data_offset, infile);
if (qthis)
{
result.value.value_u32 = value;
}
bytes_read = 4;
}
break;
case COLUMN_TYPE_2BYTE2:
case COLUMN_TYPE_2BYTE:
{
uint16_t value =
read_16bitBE(data_offset, infile);
if (qthis)
{
result.value.value_u16 = value;
}
bytes_read = 2;
}
break;
case COLUMN_TYPE_FLOAT:
if (sizeof(float) == 4)
{
union {
float float_value;
uint32_t int_value;
} int_float;
int_float.int_value = read_32bitBE(data_offset, infile);
if (qthis)
{
result.value.value_float = int_float.float_value;
}
}
else
{
read_32bitBE(data_offset, infile);
if (qthis)
{
goto cleanup_error;
}
}
bytes_read = 4;
break;
case COLUMN_TYPE_1BYTE2:
case COLUMN_TYPE_1BYTE:
{
uint8_t value =
read_8bit(data_offset, infile);
if (qthis)
{
result.value.value_u8 = value;
}
bytes_read = 1;
}
break;
default:
goto cleanup_error;
}
if (!constant)
{
row_offset += bytes_read;
}
} /* useless if end */
} /* column for loop end */
if (row_offset - row_start_offset != table_info.row_width)
goto cleanup_error;
if (query && i >= query->index) break;
} /* row for loop end */
} /* explore values block end */
//cleanup:
result.valid = 1;
cleanup_error:
if (string_table)
{
free(string_table);
string_table = NULL;
}
if (schema)
{
free(schema);
schema = NULL;
}
return result;
}
static struct utf_query_result query_utf(STREAMFILE *infile, const long offset, const struct utf_query *query)
{
return analyze_utf(infile, offset, query);
}
static struct utf_query_result query_utf_nofail(STREAMFILE *infile, const long offset, const struct utf_query *query, int *error)
{
const struct utf_query_result result = query_utf(infile, offset, query);
if (error)
{
*error = 0;
if (!result.valid) *error = 1;
if (query && !result.found) *error = 1;
}
return result;
}
static struct utf_query_result query_utf_key(STREAMFILE *infile, const long offset, int index, const char *name, int *error)
{
struct utf_query query;
query.index = index;
query.name = name;
return query_utf_nofail(infile, offset, &query, error);
}
static uint8_t query_utf_1byte(STREAMFILE *infile, const long offset, int index, const char *name, int *error)
{
struct utf_query_result result = query_utf_key(infile, offset, index, name, error);
if (error)
{
if (result.type != COLUMN_TYPE_1BYTE) *error = 1;
}
return result.value.value_u8;
}
static uint32_t query_utf_4byte(STREAMFILE *infile, const long offset, int index, const char *name, int *error)
{
struct utf_query_result result = query_utf_key(infile, offset, index, name, error);
if (error)
{
if (result.type != COLUMN_TYPE_4BYTE) *error = 1;
}
return result.value.value_u32;
}
static struct offset_size_pair query_utf_data(STREAMFILE *infile, const long offset,
int index, const char *name, int *error)
{
struct utf_query_result result = query_utf_key(infile, offset, index, name, error);
if (error)
{
if (result.type != COLUMN_TYPE_DATA) *error = 1;
}
return result.value.value_data;
}
/* CRI's UTF wrapper around DSP */
VGMSTREAM * init_vgmstream_utf_dsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int table_error = 0;
int loop_flag = 0;
const long top_offset = 0;
int channel_count;
int sample_rate;
long sample_count;
long top_data_offset, segment_count;
long body_offset, body_size;
long header_offset, header_size;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
//if (strcasecmp("aax",filename_extension(filename))) goto fail;
/* get entry count, data offset */
{
struct utf_query_result result;
long top_string_table_offset;
long top_string_table_size;
long name_offset;
result = query_utf_nofail(streamFile, top_offset, NULL, &table_error);
if (table_error) goto fail;
segment_count = result.rows;
if (segment_count != 1) goto fail; // only simple stuff for now
top_string_table_offset = top_offset + 8 + result.string_table_offset;
top_data_offset = top_offset + 8 + result.data_offset;
top_string_table_size = top_data_offset - top_string_table_offset;
if (result.name_offset+10 > top_string_table_size) goto fail;
name_offset = top_string_table_offset + result.name_offset;
if (read_32bitBE(name_offset, streamFile) != 0x41445043 ||// "ADPC"
read_32bitBE(name_offset+4, streamFile) != 0x4D5F5749 ||// "M_WI"
read_16bitBE(name_offset+8, streamFile) != 0x4900) // "I\0"
goto fail;
}
{
struct offset_size_pair offset_size;
offset_size = query_utf_data(streamFile, top_offset, 0, "data", &table_error);
if (table_error) goto fail;
body_offset = top_data_offset + offset_size.offset;
body_size = offset_size.size;
offset_size = query_utf_data(streamFile, top_offset, 0, "header", &table_error);
if (table_error) goto fail;
header_offset = top_data_offset + offset_size.offset;
header_size = offset_size.size;
}
channel_count = query_utf_1byte(streamFile, top_offset, 0, "nch", &table_error);
sample_count = query_utf_4byte(streamFile, top_offset, 0, "nsmpl", &table_error);
sample_rate = query_utf_4byte(streamFile, top_offset, 0, "sfreq", &table_error);
if (table_error) goto fail;
if (channel_count != 1 && channel_count != 2) goto fail;
if (header_size != channel_count * 0x60) goto fail;
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = sample_rate;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_UTF_DSP;
{
int i,j;
long channel_size = (body_size+7)/8*8/channel_count;
for (i = 0; i < channel_count; i++)
{
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset =
vgmstream->ch[i].offset = body_offset + i * channel_size;
for (j=0;j<16;j++)
{
vgmstream->ch[i].adpcm_coef[j] =
read_16bitBE(header_offset + 0x60*i + 0x1c + j*2, streamFile);
}
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,66 @@
#include "../vgmstream.h"
#include "meta.h"
#include "../util.h"
#include "../coding/acm_decoder.h"
/* InterPlay ACM */
/* The real work is done by libacm */
VGMSTREAM * init_vgmstream_acm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
ACMStream *acm_stream = NULL;
mus_acm_codec_data *data;
char filename[PATH_LIMIT];
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("acm",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x0,streamFile) != 0x97280301)
goto fail;
data = calloc(1,sizeof(mus_acm_codec_data));
if (!data) goto fail;
data->files = calloc(1,sizeof(ACMStream *));
if (!data->files) {
free(data); data = NULL;
goto fail;
}
/* gonna do this a little backwards, open and parse the file
before creating the vgmstream */
if (acm_open_decoder(&acm_stream,streamFile,filename) != ACM_OK) {
goto fail;
}
channel_count = acm_stream->info.channels;
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
vgmstream->channels = channel_count;
vgmstream->sample_rate = acm_stream->info.rate;
vgmstream->coding_type = coding_ACM;
vgmstream->num_samples = acm_stream->total_values / acm_stream->info.channels;
vgmstream->layout_type = layout_acm;
vgmstream->meta_type = meta_ACM;
data->file_count = 1;
data->current_file = 0;
data->files[0] = acm_stream;
/*data->end_file = -1;*/
vgmstream->codec_data = data;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,120 @@
#include "meta.h"
#include "../util.h"
/* ADS (from Gauntlet Dark Legends (GC)) */
VGMSTREAM * init_vgmstream_ads(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
int identifer_byte;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ads",filename_extension(filename))) goto fail;
/* check dhSS Header */
if (read_32bitBE(0x00,streamFile) != 0x64685353)
goto fail;
/* check dbSS Header */
if (read_32bitBE(0x20,streamFile) != 0x64625353)
goto fail;
loop_flag = 1;
channel_count = read_32bitBE(0x10,streamFile);
if (channel_count > 0x2)
goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
identifer_byte = read_32bitBE(0x08,streamFile);
switch (identifer_byte) {
case 0x00000020:
start_offset = 0xE8;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x28,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
if (channel_count == 1){
vgmstream->layout_type = layout_none;
} else if (channel_count == 2){
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitBE(0x14,streamFile);
}
break;
case 0x00000021:
start_offset = 0x28;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0c,streamFile);
vgmstream->coding_type = coding_INT_XBOX;
vgmstream->num_samples = (read_32bitBE(0x24,streamFile) / 36 *64 / vgmstream->channels)-64; // to avoid the "pop" at the loop point
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x24;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
break;
default:
goto fail;
}
vgmstream->meta_type = meta_ADS;
{
int i;
for (i=0;i<16;i++)
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x44+i*2,streamFile);
if (channel_count == 2) {
for (i=0;i<16;i++)
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0xA4+i*2,streamFile);
}
}
/* open the file for reading */
if (vgmstream->coding_type == coding_NGC_DSP) {
int i,c;
for (c=0;c<channel_count;c++) {
for (i=0;i<16;i++) {
vgmstream->ch[c].adpcm_coef[i] =
read_16bitBE(0x44+c*0x60 +i*2,streamFile);
}
}
}
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
start_offset+vgmstream->interleave_block_size*i;
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset;
}
}
return vgmstream;
fail:
/* clean up anything we may have opened */
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,598 @@
#ifdef _MSC_VER
#define _USE_MATH_DEFINES
#endif
#include <math.h>
#include <string.h>
#include <limits.h>
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add);
VGMSTREAM * init_vgmstream_adx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t stream_offset;
size_t filesize;
uint16_t version_signature;
int loop_flag=0;
int channel_count;
int32_t loop_start_offset=0;
int32_t loop_end_offset=0;
int32_t loop_start_sample=0;
int32_t loop_end_sample=0;
meta_t header_type;
int16_t coef1, coef2;
uint16_t cutoff;
char filename[PATH_LIMIT];
int coding_type = coding_CRI_ADX;
uint16_t xor_start=0,xor_mult=0,xor_add=0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("adx",filename_extension(filename))) goto fail;
filesize = get_streamfile_size(streamFile);
/* check first 2 bytes */
if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail;
/* get stream offset, check for CRI signature just before */
stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4;
if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */
(uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */
) goto fail;
/* check for encoding type */
/* 2 is for some unknown fixed filter, 3 is standard ADX, 4 is
* ADX with exponential scale, 0x11 is AHX */
if (read_8bit(4,streamFile) != 3) goto fail;
/* check for frame size (only 18 is supported at the moment) */
if (read_8bit(5,streamFile) != 18) goto fail;
/* check for bits per sample? (only 4 makes sense for ADX) */
if (read_8bit(6,streamFile) != 4) goto fail;
/* check version signature, read loop info */
version_signature = read_16bitBE(0x12,streamFile);
/* encryption */
if (version_signature == 0x0408) {
if (find_key(streamFile, 8, &xor_start, &xor_mult, &xor_add))
{
coding_type = coding_CRI_ADX_enc_8;
version_signature = 0x0400;
}
}
else if (version_signature == 0x0409) {
if (find_key(streamFile, 9, &xor_start, &xor_mult, &xor_add))
{
coding_type = coding_CRI_ADX_enc_9;
version_signature = 0x0400;
}
}
if (version_signature == 0x0300) { /* type 03 */
header_type = meta_ADX_03;
if (stream_offset-6 >= 0x2c) { /* enough space for loop info? */
loop_flag = (read_32bitBE(0x18,streamFile) != 0);
loop_start_sample = read_32bitBE(0x1c,streamFile);
loop_start_offset = read_32bitBE(0x20,streamFile);
loop_end_sample = read_32bitBE(0x24,streamFile);
loop_end_offset = read_32bitBE(0x28,streamFile);
}
} else if (version_signature == 0x0400) {
off_t ainf_info_length=0;
if((uint32_t)read_32bitBE(0x24,streamFile)==0x41494E46) /* AINF Header */
ainf_info_length = (off_t)read_32bitBE(0x28,streamFile);
header_type = meta_ADX_04;
if (stream_offset-ainf_info_length-6 >= 0x38) { /* enough space for loop info? */
if (read_32bitBE(0x24,streamFile) == 0xFFFEFFFE)
loop_flag = 0;
else
loop_flag = (read_32bitBE(0x24,streamFile) != 0);
loop_start_sample = read_32bitBE(0x28,streamFile);
loop_start_offset = read_32bitBE(0x2c,streamFile);
loop_end_sample = read_32bitBE(0x30,streamFile);
loop_end_offset = read_32bitBE(0x34,streamFile);
}
} else if (version_signature == 0x0500) { /* found in some SFD : Buggy Heat, appears to have no loop */
header_type = meta_ADX_05;
} else goto fail; /* not a known/supported version signature */
/* At this point we almost certainly have an ADX file,
* so let's build the VGMSTREAM. */
/* high-pass cutoff frequency, always 500 that I've seen */
cutoff = (uint16_t)read_16bitBE(0x10,streamFile);
if (loop_start_sample == 0 && loop_end_sample == 0) {
loop_flag = 0;
}
channel_count = read_8bit(7,streamFile);
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(0xc,streamFile);
vgmstream->sample_rate = read_32bitBE(8,streamFile);
/* channels and loop flag are set by allocate_vgmstream */
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->coding_type = coding_type;
if (channel_count==1)
vgmstream->layout_type = layout_none;
else
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = header_type;
vgmstream->interleave_block_size=18;
/* calculate filter coefficients */
{
double x,y,z,a,b,c;
x = cutoff;
y = vgmstream->sample_rate;
z = cos(2.0*M_PI*x/y);
a = M_SQRT2-z;
b = M_SQRT2-1.0;
c = (a-sqrt((a+b)*(a-b)))/b;
coef1 = floor(c*8192);
coef2 = floor(c*c*-4096);
}
{
int i;
STREAMFILE * chstreamfile;
/* ADX is so tightly interleaved that having two buffers is silly */
chstreamfile = streamFile->open(streamFile,filename,18*0x400);
if (!chstreamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = chstreamfile;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
stream_offset+18*i;
vgmstream->ch[i].adpcm_coef[0] = coef1;
vgmstream->ch[i].adpcm_coef[1] = coef2;
if (coding_type == coding_CRI_ADX_enc_8 ||
coding_type == coding_CRI_ADX_enc_9)
{
int j;
vgmstream->ch[i].adx_channels = channel_count;
vgmstream->ch[i].adx_xor = xor_start;
vgmstream->ch[i].adx_mult = xor_mult;
vgmstream->ch[i].adx_add = xor_add;
for (j=0;j<i;j++)
adx_next_key(&vgmstream->ch[i]);
}
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
/* guessadx stuff */
/* type 8 keys */
static struct {
uint16_t start,mult,add;
} keys_8[] = {
/* Clover Studio (GOD HAND, Okami) */
/* I'm pretty sure this is right, based on a decrypted version of some GOD HAND tracks. */
/* Also it is the 2nd result from guessadx */
{0x49e1,0x4a57,0x553d},
/* Grasshopper Manufacture 0 (Blood+) */
/* this is estimated */
{0x5f5d,0x58bd,0x55ed},
/* Grasshopper Manufacture 1 (Killer7) */
/* this is estimated */
{0x50fb,0x5803,0x5701},
/* Grasshopper Manufacture 2 (Samurai Champloo) */
/* confirmed unique with guessadx */
{0x4f3f,0x472f,0x562f},
/* Moss Ltd (Raiden III) */
/* this is estimated */
{0x66f5,0x58bd,0x4459},
/* Sonic Team 0 (Phantasy Star Universe) */
/* this is estimated */
{0x5deb,0x5f27,0x673f},
/* G.rev 0 (Senko no Ronde) */
/* this is estimated */
{0x46d3,0x5ced,0x474d},
/* Sonic Team 1 (NiGHTS: Journey of Dreams) */
/* this seems to be dead on, but still estimated */
{0x440b,0x6539,0x5723},
/* from guessadx (unique?), unknown source */
{0x586d,0x5d65,0x63eb},
/* Navel (Shuffle! On the Stage) */
/* 2nd key from guessadx */
{0x4969,0x5deb,0x467f},
/* Success (Aoishiro) */
/* 1st key from guessadx */
{0x4d65,0x5eb7,0x5dfd},
/* Sonic Team 2 (Sonic and the Black Knight) */
/* confirmed unique with guessadx */
{0x55b7,0x6191,0x5a77},
/* Enterbrain (Amagami) */
/* one of 32 from guessadx */
{0x5a17,0x509f,0x5bfd},
/* Yamasa (Yamasa Digi Portable: Matsuri no Tatsujin) */
/* confirmed unique with guessadx */
{0x4c01,0x549d,0x676f},
/* Kadokawa Shoten (Fragments Blue) */
/* confirmed unique with guessadx */
{0x5803,0x4555,0x47bf},
/* Namco (Soulcalibur IV) */
/* confirmed unique with guessadx */
{0x59ed,0x4679,0x46c9},
/* G.rev 1 (Senko no Ronde DUO) */
/* from guessadx */
{0x6157,0x6809,0x4045},
/* ASCII Media Works 0 (Nogizaka Haruka no Himitsu: Cosplay Hajimemashita) */
/* 2nd from guessadx, other was {0x45ad,0x5f27,0x10fd} */
{0x45af,0x5f27,0x52b1},
/* D3 Publisher 0 (Little Anchor) */
/* confirmed unique with guessadx */
{0x5f65,0x5b3d,0x5f65},
/* Marvelous 0 (Hanayoi Romanesque: Ai to Kanashimi) */
/* 2nd from guessadx, other was {0x5562,0x5047,0x1433} */
{0x5563,0x5047,0x43ed},
/* Capcom (Mobile Suit Gundam: Gundam vs. Gundam NEXT PLUS) */
/* confirmed unique with guessadx */
{0x4f7b,0x4fdb,0x5cbf},
/* Developer: Bridge NetShop
* Publisher: Kadokawa Shoten (Shoukan Shoujo: Elemental Girl Calling) */
/* confirmed unique with guessadx */
{0x4f7b,0x5071,0x4c61},
/* Developer: Net Corporation
* Publisher: Tecmo (Rakushou! Pachi-Slot Sengen 6: Rio 2 Cruising Vanadis) */
/* confirmed unique with guessadx */
{0x53e9,0x586d,0x4eaf},
/* Developer: Aquaplus
* Tears to Tiara Gaiden Avalon no Kagi (PS3) */
/* confirmed unique with guessadx */
{0x47e1,0x60e9,0x51c1},
/* Developer: Broccoli
* Neon Genesis Evangelion: Koutetsu no Girlfriend 2nd (PS2) */
/* confirmed unique with guessadx */
{0x481d,0x4f25,0x5243},
/* Developer: Marvelous
* Futakoi Alternative (PS2) */
/* confirmed unique with guessadx */
{0x413b,0x543b,0x57d1},
/* Developer: Marvelous
* Gakuen Utopia - Manabi Straight! KiraKira Happy Festa! (PS2)
* Second guess from guessadx, other was
* {0x440b,0x4327,0x564b}
**/
{0x440d,0x4327,0x4fff},
/* Developer: Datam Polystar
* Soshite Kono Uchuu ni Kirameku Kimi no Shi XXX (PS2) */
/* confirmed unique with guessadx */
{0x5f5d,0x552b,0x5507},
/* Developer: Sega
* Sakura Taisen: Atsuki Chishio Ni (PS2) */
/* confirmed unique with guessadx */
{0x645d,0x6011,0x5c29},
/* Developer: Sega
* Sakura Taisen 3 ~Paris wa Moeteiru ka~ (PS2) */
/* confirmed unique with guessadx */
{0x62ad,0x4b13,0x5957},
/* Developer: Jinx
* Sotsugyou 2nd Generation (PS2)
* First guess from guessadx, other was
* {0x6307,0x509f,0x2ac5}
*/
{0x6305,0x509f,0x4c01},
/*
* La Corda d'Oro (2005)(-)(Koei)[PSP]
* confirmed unique with guessadx */
{0x55b7,0x67e5,0x5387},
/*
* Nanatsuiro * Drops Pure!! (2007)(Media Works)[PS2]
* confirmed unique with guessadx */
{0x6731,0x645d,0x566b},
/*
* Shakugan no Shana (2006)(Vridge)(Media Works)[PS2]
* confirmed unique with guessadx */
{0x5fc5,0x63d9,0x599f},
/*
* Uragiri wa Boku no Namae o Shitteiru (2010)(Kadokawa Shoten)[PS2]
* confirmed unique with guessadx */
{0x4c73,0x4d8d,0x5827},
/*
* StormLover Kai!! (2012)(D3 Publisher)[PSP]
* confirmed unique with guessadx */
{0x5a11,0x67e5,0x6751},
/*
* Sora no Otoshimono - DokiDoki Summer Vacation (2010)(Kadokawa Shoten)[PSP]
* confirmed unique with guessadx */
{0x5e75,0x4a89,0x4c61},
/*
* Boku wa Koukuu Kanseikan - Airport Hero Naha (2006)(Sonic Powered)(Electronic Arts)[PSP]
* confirmed unique with guessadx */
{0x64ab,0x5297,0x632f},
/*
* Lucky Star - Net Idol Meister (2009)(Kadokawa Shoten)[PSP]
* confirmed unique with guessadx */
{0x4d82,0x5243,0x685},
/*
* Ishin Renka: Ryouma Gaiden (2010-11-25)(-)(D3 Publisher)[PSP]
*/
{0x54d1,0x526d,0x5e8b},
/*
* Lucky Star - Ryouou Gakuen Outousai Portable (2010-12-22)(-)(Kadokawa Shoten)[PSP]
*/
{0x4d06,0x663b,0x7d09},
/*
* Marriage Royale - Prism Story (2010-04-28)(-)(ASCII Media Works)[PSP]
*/
{0x40a9,0x46b1,0x62ad},
/*
* Nogizaka Haruka no Himitsu - Doujinshi Hajime Mashita (2010-10-28)(-)(ASCII Media Works)[PSP]
*/
{0x4601,0x671f,0x0455},
/*
* Slotter Mania P - Mach Go Go Go III (2011-01-06)(-)(Dorart)[PSP]
*/
{0x41ef,0x463d,0x5507},
/*
* Nichijou - Uchuujin (2011-07-28)(-)(Kadokawa Shoten)[PSP]
*/
{0x4369,0x486d,0x5461},
/*
* R-15 Portable (2011-10-27)(-)(Kadokawa Shoten)[PSP]
*/
{0x6809,0x5fd5,0x5bb1},
/*
* Suzumiya Haruhi-chan no Mahjong (2011-07-07)(-)(Kadokawa Shoten)[PSP]
*/
{0x5c33,0x4133,0x4ce7},
};
/* type 9 keys */
static struct {
uint16_t start,mult,add;
} keys_9[] = {
/* Phantasy Star Online 2
* guessed with degod */
{0x07d2,0x1ec5,0x0c7f},
};
static const int keys_8_count = sizeof(keys_8)/sizeof(keys_8[0]);
static const int keys_9_count = sizeof(keys_9)/sizeof(keys_9[0]);
/* return 0 if not found, 1 if found and set parameters */
static int find_key(STREAMFILE *file, uint8_t type, uint16_t *xor_start, uint16_t *xor_mult, uint16_t *xor_add)
{
uint16_t * scales = NULL;
uint16_t * prescales = NULL;
int bruteframe=0,bruteframecount=-1;
int startoff, endoff;
int rc = 0;
startoff=read_16bitBE(2, file)+4;
endoff=(read_32bitBE(12, file)+31)/32*18*read_8bit(7, file)+startoff;
/* how many scales? */
{
int framecount=(endoff-startoff)/18;
if (framecount<bruteframecount || bruteframecount<0)
bruteframecount=framecount;
}
/* find longest run of nonzero frames */
{
int longest=-1,longest_length=-1;
int i;
int length=0;
for (i=0;i<bruteframecount;i++) {
static const unsigned char zeroes[18]={0};
unsigned char buf[18];
read_streamfile(buf, startoff+i*18, 18, file);
if (memcmp(zeroes,buf,18)) length++;
else length=0;
if (length > longest_length) {
longest_length=length;
longest=i-length+1;
if (longest_length >= 0x8000) break;
}
}
if (longest==-1) {
goto find_key_cleanup;
}
bruteframecount = longest_length;
bruteframe = longest;
}
{
/* try to guess key */
#define MAX_FRAMES (INT_MAX/0x8000)
int scales_to_do;
int key_id;
/* allocate storage for scales */
scales_to_do = (bruteframecount > MAX_FRAMES ? MAX_FRAMES : bruteframecount);
scales = malloc(scales_to_do*sizeof(uint16_t));
if (!scales) {
goto find_key_cleanup;
}
/* prescales are those scales before the first frame we test
* against, we use these to compute the actual start */
if (bruteframe > 0) {
int i;
/* allocate memory for the prescales */
prescales = malloc(bruteframe*sizeof(uint16_t));
if (!prescales) {
goto find_key_cleanup;
}
/* read the prescales */
for (i=0; i<bruteframe; i++) {
prescales[i] = read_16bitBE(startoff+i*18, file);
}
}
/* read in the scales */
{
int i;
for (i=0; i < scales_to_do; i++) {
scales[i] = read_16bitBE(startoff+(bruteframe+i)*18, file);
}
}
if (type == 8)
{
/* guess each of the keys */
for (key_id=0;key_id<keys_8_count;key_id++) {
/* test pre-scales */
uint16_t xor = keys_8[key_id].start;
uint16_t mult = keys_8[key_id].mult;
uint16_t add = keys_8[key_id].add;
int i;
for (i=0;i<bruteframe &&
((prescales[i]&0x6000)==(xor&0x6000) ||
prescales[i]==0);
i++) {
xor = xor * mult + add;
}
if (i == bruteframe)
{
/* test */
for (i=0;i<scales_to_do &&
(scales[i]&0x6000)==(xor&0x6000);i++) {
xor = xor * mult + add;
}
if (i == scales_to_do)
{
*xor_start = keys_8[key_id].start;
*xor_mult = keys_8[key_id].mult;
*xor_add = keys_8[key_id].add;
rc = 1;
goto find_key_cleanup;
}
}
}
}
else if (type == 9)
{
/* smarter XOR as seen in PSO2, can't do an exact match so we
* have to search for the lowest */
long best_score = MAX_FRAMES * 0x1fff;
/* guess each of the keys */
for (key_id=0;key_id<keys_9_count;key_id++) {
/* run past pre-scales */
uint16_t xor = keys_9[key_id].start;
uint16_t mult = keys_9[key_id].mult;
uint16_t add = keys_9[key_id].add;
int i;
long total_score = 0;
for (i=0;i<bruteframe;i++) {
xor = xor * mult + add;
}
if (i == bruteframe)
{
/* test */
for (i=0;i<scales_to_do && total_score < best_score;i++) {
xor = xor * mult + add;
total_score += (scales[i]^xor)&0x1fff;
}
if (total_score < best_score)
{
*xor_start = keys_9[key_id].start;
*xor_mult = keys_9[key_id].mult;
*xor_add = keys_9[key_id].add;
best_score = total_score;
}
}
}
/* arbitrarily decide if we have won? */
if (best_score < scales_to_do * 0x1000)
{
rc = 1;
}
}
}
find_key_cleanup:
if (scales) free(scales);
if (prescales) free(prescales);
return rc;
}

View File

@ -0,0 +1,67 @@
#include "meta.h"
#include "../util.h"
VGMSTREAM * init_vgmstream_afc(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag;
const int channel_count = 2; /* .afc seems to be stereo only */
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("afc",filename_extension(filename))) goto fail;
/* don't grab AIFF-C with .afc extension */
if ((uint32_t)read_32bitBE(0x0,streamFile)==0x464F524D) /* FORM */
goto fail;
/* we will get a sample rate, that's as close to checking as I think
* we can get */
/* build the VGMSTREAM */
loop_flag = read_32bitBE(0x10,streamFile);
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(0x04,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitBE(0x08,streamFile);
/* channels and loop flag are set by allocate_vgmstream */
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_NGC_AFC;
vgmstream->layout_type = layout_interleave;
vgmstream->meta_type = meta_AFC;
/* frame-level interleave (9 bytes) */
vgmstream->interleave_block_size = 9;
/* open the file for reading by each channel */
{
STREAMFILE *chstreamfile;
int i;
/* both channels use same buffer, as interleave is so small */
chstreamfile = streamFile->open(streamFile,filename,9*channel_count*0x100);
if (!chstreamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = chstreamfile;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
0x20 + i*vgmstream->interleave_block_size;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,73 @@
#include "meta.h"
#include "../util.h"
/* .agsc - from Metroid Prime 2 */
VGMSTREAM * init_vgmstream_agsc(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t header_offset;
off_t start_offset;
int channel_count;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("agsc",filename_extension(filename))) goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x00000001)
goto fail;
/* count length of name, including terminating 0 */
for (header_offset=4;header_offset < get_streamfile_size(streamFile) && read_8bit(header_offset,streamFile)!='\0';header_offset++);
header_offset ++;
channel_count = 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(1,1);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(header_offset+0xda,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitBE(header_offset+0xd8,streamFile);
vgmstream->loop_start_sample = read_32bitBE(header_offset+0xde,streamFile);
/* this is cute, we actually have a "loop length" */
vgmstream->loop_end_sample = (vgmstream->loop_start_sample + read_32bitBE(header_offset+0xe2,streamFile))-1;
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_DSP_AGSC;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i]=read_16bitBE(header_offset+0xf6+i*2,streamFile);
}
start_offset = header_offset+0x116;
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
start_offset;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,121 @@
#include "../vgmstream.h"
#ifdef VGM_USE_MPEG
#include "meta.h"
#include "../util.h"
/* AHX is a CRI format which contains an MPEG-2 Layer 2 audio stream.
* Although the MPEG frame headers are incorrect... */
VGMSTREAM * init_vgmstream_ahx(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
off_t stream_offset;
size_t filesize;
char filename[PATH_LIMIT];
int channel_count = 1;
int loop_flag = 0;
mpeg_codec_data *data = NULL;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ahx",filename_extension(filename))) goto fail;
filesize = get_streamfile_size(streamFile);
/* check first 2 bytes */
if ((uint16_t)read_16bitBE(0,streamFile)!=0x8000) goto fail;
/* get stream offset, check for CRI signature just before */
stream_offset = (uint16_t)read_16bitBE(2,streamFile) + 4;
if ((uint16_t)read_16bitBE(stream_offset-6,streamFile)!=0x2863 ||/* "(c" */
(uint32_t)read_32bitBE(stream_offset-4,streamFile)!=0x29435249 /* ")CRI" */
) goto fail;
/* check for encoding type */
/* 2 is for some unknown fixed filter, 3 is standard ADX, 4 is
* ADX with exponential scale, 0x11 is AHX */
/* Sappharad reports that old AHXs (Sonic Adventure 2) don't have this flag.
* When I see one perhaps I can add an exception for those. */
if (read_8bit(4,streamFile) != 0x11) goto fail;
/* check for frame size (0 for AHX) */
if (read_8bit(5,streamFile) != 0) goto fail;
/* check for bits per sample? (0 for AHX) */
if (read_8bit(6,streamFile) != 0) goto fail;
/* check channel count (only mono AHXs are known) */
if (read_8bit(7,streamFile) != 1) goto fail;
/* At this point we almost certainly have an ADX file,
* so let's build the VGMSTREAM. */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(0xc,streamFile);
/* This is the One True Samplerate, the MPEG headers lie. */
vgmstream->sample_rate = read_32bitBE(8,streamFile);
vgmstream->coding_type = coding_fake_MPEG2_L2;
vgmstream->layout_type = layout_fake_mpeg;
vgmstream->meta_type = meta_AHX;
{
int i;
STREAMFILE * chstreamfile;
chstreamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!chstreamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = chstreamfile;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
stream_offset;
}
}
/* ooh, fun part, set up mpg123 */
{
int rc;
data = calloc(1,sizeof(mpeg_codec_data));
if (!data) goto fail;
data->m = mpg123_new(NULL,&rc);
if (rc==MPG123_NOT_INITIALIZED) {
if (mpg123_init()!=MPG123_OK) goto fail;
data->m = mpg123_new(NULL,&rc);
if (rc!=MPG123_OK) goto fail;
} else if (rc!=MPG123_OK) {
goto fail;
}
if (mpg123_open_feed(data->m)!=MPG123_OK) {
goto fail;
}
vgmstream->codec_data = data;
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (data) {
if (data->m) {
mpg123_delete(data->m);
data->m = NULL;
}
free(data);
data = NULL;
}
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
#endif

View File

@ -0,0 +1,310 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* Audio Interchange File Format AIFF-C */
/* also plain AIFF, for good measure */
/* Included primarily for 3DO */
/* for reading integers inexplicably packed into 80 bit floats */
uint32_t read80bitSANE(off_t offset, STREAMFILE *streamFile) {
uint8_t buf[10];
int32_t exponent;
int32_t mantissa;
int i;
if (read_streamfile(buf,offset,10,streamFile) != 10) return 0;
exponent = ((buf[0]<<8)|(buf[1]))&0x7fff;
exponent -= 16383;
mantissa = 0;
for (i=0;i<8;i++) {
int32_t shift = exponent-7-i*8;
if (shift >= 0)
mantissa |= buf[i+2] << shift;
else if (shift > -8)
mantissa |= buf[i+2] >> -shift;
}
return mantissa*((buf[0]&0x80)?-1:1);
}
uint32_t find_marker(STREAMFILE *streamFile, off_t MarkerChunkOffset,
int marker_id) {
uint16_t marker_count;
int i;
off_t marker_offset;
marker_count = read_16bitBE(MarkerChunkOffset+8,streamFile);
marker_offset = MarkerChunkOffset+10;
for (i=0;i<marker_count;i++) {
int name_length;
if (read_16bitBE(marker_offset,streamFile) == marker_id)
return read_32bitBE(marker_offset+2,streamFile);
name_length = (uint8_t)read_8bit(marker_offset+6,streamFile) + 1;
if (name_length % 2) name_length++;
marker_offset += 6 + name_length;
}
return -1;
}
VGMSTREAM * init_vgmstream_aifc(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t file_size = -1;
int channel_count = 0;
int sample_count = 0;
int sample_size = 0;
int sample_rate = 0;
int coding_type = -1;
off_t start_offset = -1;
int interleave = -1;
int loop_flag = 0;
int32_t loop_start = -1;
int32_t loop_end = -1;
int AIFFext = 0;
int AIFCext = 0;
int AIFF = 0;
int AIFC = 0;
int FormatVersionChunkFound = 0;
int CommonChunkFound = 0;
int SoundDataChunkFound = 0;
int MarkerChunkFound = 0;
off_t MarkerChunkOffset = -1;
int InstrumentChunkFound =0;
off_t InstrumentChunkOffset = -1;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (!strcasecmp("aifc",filename_extension(filename)) ||
!strcasecmp("afc",filename_extension(filename)) ||
!strcasecmp("aifcl",filename_extension(filename)) ||
!strcasecmp("cbd2",filename_extension(filename)))
{
AIFCext = 1;
}
else if (!strcasecmp("aiff",filename_extension(filename)) ||
!strcasecmp("aif",filename_extension(filename)) ||
!strcasecmp("aiffl",filename_extension(filename)))
{
AIFFext = 1;
}
else goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)==0x464F524D && /* "FORM" */
/* check that file = header (8) + data */
(uint32_t)read_32bitBE(4,streamFile)+8==get_streamfile_size(streamFile))
{
if ((uint32_t)read_32bitBE(8,streamFile)==0x41494643) /* "AIFC" */
{
if (!AIFCext) goto fail;
AIFC = 1;
}
else if ((uint32_t)read_32bitBE(8,streamFile)==0x41494646) /* "AIFF" */
{
if (!AIFFext) goto fail;
AIFF = 1;
}
else goto fail;
} else goto fail;
file_size = get_streamfile_size(streamFile);
/* read through chunks to verify format and find metadata */
{
off_t current_chunk = 0xc; /* start with first chunk within FORM */
while (current_chunk < file_size) {
uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
off_t chunk_size = read_32bitBE(current_chunk+4,streamFile);
/* chunks must be padded to an even number of bytes but chunk
* size does not include that padding */
if (chunk_size % 2) chunk_size++;
if (current_chunk+8+chunk_size > file_size) goto fail;
switch(chunk_type) {
case 0x46564552: /* FVER */
/* only one per file */
if (FormatVersionChunkFound) goto fail;
/* plain AIFF shouldn't have */
if (AIFF) goto fail;
FormatVersionChunkFound = 1;
/* specific size */
if (chunk_size != 4) goto fail;
/* Version 1 of AIFF-C spec timestamp */
if ((uint32_t)read_32bitBE(current_chunk+8,streamFile) !=
0xA2805140) goto fail;
break;
case 0x434F4D4D: /* COMM */
/* only one per file */
if (CommonChunkFound) goto fail;
CommonChunkFound = 1;
channel_count = read_16bitBE(current_chunk+8,streamFile);
if (channel_count <= 0) goto fail;
sample_count = (uint32_t)read_32bitBE(current_chunk+0xa,streamFile);
sample_size = read_16bitBE(current_chunk+0xe,streamFile);
sample_rate = read80bitSANE(current_chunk+0x10,streamFile);
if (AIFC) {
switch (read_32bitBE(current_chunk+0x1a,streamFile)) {
case 0x53445832: /* SDX2 */
coding_type = coding_SDX2;
interleave = 1;
break;
case 0x43424432: /* CBD2 */
coding_type = coding_CBD2;
interleave = 1;
break;
case 0x41445034: /* ADP4 */
coding_type = coding_DVI_IMA;
/* don't know how stereo DVI is laid out */
if (channel_count != 1) break;
break;
default:
/* we should probably support uncompressed here */
goto fail;
}
} else if (AIFF) {
switch (sample_size) {
case 8:
coding_type = coding_PCM8;
interleave = 1;
break;
case 16:
coding_type = coding_PCM16BE;
interleave = 2;
break;
/* 32 is a possibility, but we don't see it and I
* don't have a reader for it yet */
default:
goto fail;
}
}
/* we don't check the human-readable portion of AIFF-C*/
break;
case 0x53534E44: /* SSND */
/* at most one per file */
if (SoundDataChunkFound) goto fail;
SoundDataChunkFound = 1;
start_offset = current_chunk + 16 + read_32bitBE(current_chunk+8,streamFile);
break;
case 0x4D41524B: /* MARK */
if (MarkerChunkFound) goto fail;
MarkerChunkFound = 1;
MarkerChunkOffset = current_chunk;
break;
case 0x494E5354: /* INST */
if (InstrumentChunkFound) goto fail;
InstrumentChunkFound = 1;
InstrumentChunkOffset = current_chunk;
break;
default:
/* spec says we can skip unrecognized chunks */
break;
}
current_chunk += 8+chunk_size;
}
}
if (AIFC) {
if (!FormatVersionChunkFound || !CommonChunkFound || !SoundDataChunkFound)
goto fail;
} else if (AIFF) {
if (!CommonChunkFound || !SoundDataChunkFound)
goto fail;
}
/* read loop points */
if (InstrumentChunkFound && MarkerChunkFound) {
int start_marker;
int end_marker;
/* use the sustain loop */
/* if playMode=ForwardLooping */
if (read_16bitBE(InstrumentChunkOffset+16,streamFile) == 1) {
start_marker = read_16bitBE(InstrumentChunkOffset+18,streamFile);
end_marker = read_16bitBE(InstrumentChunkOffset+20,streamFile);
/* check for sustain markers != 0 (invalid marker no) */
if (start_marker && end_marker) {
/* find start marker */
loop_start = find_marker(streamFile,MarkerChunkOffset,start_marker);
loop_end = find_marker(streamFile,MarkerChunkOffset,end_marker);
/* find_marker is type uint32_t as the spec says that's the type
* of the position value, but it returns a -1 on error, and the
* loop_start and loop_end variables are int32_t, so the error
* will become apparent.
* We shouldn't have a loop point that overflows an int32_t
* anyway. */
loop_flag = 1;
if (loop_start==loop_end) loop_flag = 0;
}
}
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = sample_rate;
vgmstream->coding_type = coding_type;
if (channel_count > 1)
vgmstream->layout_type = layout_interleave;
else
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = interleave;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
if (AIFC)
vgmstream->meta_type = meta_AIFC;
else if (AIFF)
vgmstream->meta_type = meta_AIFF;
/* open the file, set up each channel */
{
int i;
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset =
start_offset+i*interleave;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,417 @@
#include "../vgmstream.h"
#include "meta.h"
#include "../util.h"
typedef struct _AIXSTREAMFILE
{
STREAMFILE sf;
STREAMFILE *real_file;
off_t start_physical_offset;
off_t current_physical_offset;
off_t current_logical_offset;
off_t current_block_size;
int stream_id;
} AIXSTREAMFILE;
static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id);
VGMSTREAM * init_vgmstream_aix(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileAIX = NULL;
STREAMFILE * streamFileADX = NULL;
char filename[PATH_LIMIT];
off_t *segment_offset = NULL;
int32_t *samples_in_segment = NULL;
int32_t sample_count;
int loop_flag = 0;
int32_t loop_start_sample=0;
int32_t loop_end_sample=0;
aix_codec_data *data = NULL;
off_t first_AIXP;
off_t stream_list_offset;
off_t stream_list_end;
const int segment_list_entry_size = 0x10;
const off_t segment_list_offset = 0x20;
int stream_count,channel_count,segment_count;
int sample_rate;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("aix",filename_extension(filename))) goto fail;
if (read_32bitBE(0x0,streamFile) != 0x41495846 || /* "AIXF" */
read_32bitBE(0x08,streamFile) != 0x01000014 ||
read_32bitBE(0x0c,streamFile) != 0x00000800)
goto fail;
first_AIXP = read_32bitBE(0x4,streamFile)+8;
segment_count = (uint16_t)read_16bitBE(0x18,streamFile);
stream_list_offset = segment_list_offset+segment_list_entry_size*segment_count+0x10;
if (stream_list_offset >= first_AIXP)
goto fail;
if (segment_count < 1)
goto fail;
sample_rate = read_32bitBE(stream_list_offset+8,streamFile);
if (!check_sample_rate(sample_rate))
goto fail;
samples_in_segment = calloc(segment_count,sizeof(int32_t));
if (!samples_in_segment)
goto fail;
segment_offset = calloc(segment_count,sizeof(off_t));
if (!segment_offset)
goto fail;
for (i = 0; i < segment_count; i++)
{
segment_offset[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0,streamFile);
samples_in_segment[i] = read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x08,streamFile);
/*printf("samples_in_segment[%d]=%d\n",i,samples_in_segment[i]);*/
/* all segments must have equal sample rate */
if (read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) != sample_rate)
{
/* segments > 0 can have 0 sample rate (Ryu ga gotoku: Kenzan! tenkei_sng1.aix),
seems to indicate same sample rate as first */
if (!(i > 0 && read_32bitBE(segment_list_offset+segment_list_entry_size*i+0x0c,streamFile) == 0))
goto fail;
}
}
if (segment_offset[0] != first_AIXP)
goto fail;
stream_count = (uint8_t)read_8bit(stream_list_offset,streamFile);
if (stream_count < 1)
goto fail;
stream_list_end = stream_list_offset + 0x8 + stream_count * 8;
if (stream_list_end >= first_AIXP)
goto fail;
channel_count = 0;
for (i = 0; i < stream_count; i++)
{
/* all streams must have same samplerate as segments */
if (read_32bitBE(stream_list_offset+8+i*8,streamFile)!=sample_rate)
goto fail;
channel_count += read_8bit(stream_list_offset+8+i*8+4,streamFile);
}
/* check for existence of segments */
for (i = 0; i < segment_count; i++)
{
int j;
off_t AIXP_offset = segment_offset[i];
for (j = 0; j < stream_count; j++)
{
if (read_32bitBE(AIXP_offset,streamFile)!=0x41495850) /* "AIXP" */
goto fail;
if (read_8bit(AIXP_offset+8,streamFile)!=j)
goto fail;
AIXP_offset += read_32bitBE(AIXP_offset+4,streamFile)+8;
}
}
/*streamFileAIX = streamFile->open(streamFile,filename,sample_rate*0.0375*2/32*18segment_count);*/
streamFileAIX = streamFile->open(streamFile,filename,sample_rate*0.1*segment_count);
if (!streamFileAIX) goto fail;
data = malloc(sizeof(aix_codec_data));
if (!data) goto fail;
data->segment_count = segment_count;
data->stream_count = stream_count;
data->adxs = malloc(sizeof(STREAMFILE *)*segment_count*stream_count);
if (!data->adxs) goto fail;
for (i=0;i<segment_count*stream_count;i++) {
data->adxs[i] = NULL;
}
data->sample_counts = calloc(segment_count,sizeof(int32_t));
if (!data->sample_counts) goto fail;
memcpy(data->sample_counts,samples_in_segment,segment_count*sizeof(int32_t));
/* for each segment */
for (i = 0; i < segment_count; i++)
{
int j;
/* for each stream */
for (j = 0; j < stream_count; j++)
{
VGMSTREAM *adx;
/*printf("try opening segment %d/%d stream %d/%d %x\n",i,segment_count,j,stream_count,segment_offset[i]);*/
streamFileADX = open_aix_with_STREAMFILE(streamFileAIX,segment_offset[i],j);
if (!streamFileADX) goto fail;
adx = data->adxs[i*stream_count+j] = init_vgmstream_adx(streamFileADX);
if (!adx)
goto fail;
close_streamfile(streamFileADX); streamFileADX = NULL;
if (adx->num_samples != data->sample_counts[i] ||
adx->loop_flag != 0)
goto fail;
/* save start things so we can restart for seeking/looping */
/* copy the channels */
memcpy(adx->start_ch,adx->ch,sizeof(VGMSTREAMCHANNEL)*adx->channels);
/* copy the whole VGMSTREAM */
memcpy(adx->start_vgmstream,adx,sizeof(VGMSTREAM));
}
}
if (segment_count > 1)
{
loop_flag = 1;
}
sample_count = 0;
for (i = 0; i < segment_count; i++)
{
sample_count += data->sample_counts[i];
if (i == 0)
loop_start_sample = sample_count;
if (i == 1)
loop_end_sample = sample_count;
}
vgmstream = allocate_vgmstream(channel_count,loop_flag);
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = sample_rate;
vgmstream->loop_start_sample = loop_start_sample;
vgmstream->loop_end_sample = loop_end_sample;
vgmstream->coding_type = data->adxs[0]->coding_type;
vgmstream->layout_type = layout_aix;
vgmstream->meta_type = meta_AIX;
vgmstream->ch[0].streamfile = streamFileAIX;
data->current_segment = 0;
vgmstream->codec_data = data;
free(segment_offset);
free(samples_in_segment);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (streamFileAIX) close_streamfile(streamFileAIX);
if (streamFileADX) close_streamfile(streamFileADX);
if (vgmstream) close_vgmstream(vgmstream);
if (samples_in_segment) free(samples_in_segment);
if (segment_offset) free(segment_offset);
if (data) {
if (data->adxs)
{
int i;
for (i=0;i<data->segment_count*data->stream_count;i++)
if (data->adxs)
close_vgmstream(data->adxs[i]);
free(data->adxs);
}
if (data->sample_counts)
{
free(data->sample_counts);
}
free(data);
}
return NULL;
}
static size_t read_aix(AIXSTREAMFILE *streamfile,uint8_t *dest,off_t offset,size_t length)
{
size_t sz = 0;
/*printf("trying to read %x bytes from %x (str%d)\n",length,offset,streamfile->stream_id);*/
while (length > 0)
{
int read_something = 0;
/* read the beginning of the requested block, if we can */
if (offset >= streamfile->current_logical_offset)
{
off_t to_read;
off_t length_available;
length_available =
(streamfile->current_logical_offset+
streamfile->current_block_size) -
offset;
if (length < length_available)
{
to_read = length;
}
else
{
to_read = length_available;
}
if (to_read > 0)
{
size_t bytes_read;
bytes_read = read_streamfile(dest,
streamfile->current_physical_offset+0x10+
(offset-streamfile->current_logical_offset),
to_read,streamfile->real_file);
sz += bytes_read;
if (bytes_read != to_read)
{
/* an error which we will not attempt to handle here */
return sz;
}
read_something = 1;
dest += bytes_read;
offset += bytes_read;
length -= bytes_read;
}
}
if (!read_something)
{
/* couldn't read anything, must seek */
int found_block = 0;
/* as we have no memory we must start seeking from the beginning */
if (offset < streamfile->current_logical_offset)
{
streamfile->current_logical_offset = 0;
streamfile->current_block_size = 0;
streamfile->current_physical_offset =
streamfile->start_physical_offset;
}
/* seek ye forwards */
while (!found_block) {
/*printf("seek looks at %x\n",streamfile->current_physical_offset);*/
switch (read_32bitBE(streamfile->current_physical_offset,
streamfile->real_file))
{
case 0x41495850: /* AIXP */
if (read_8bit(
streamfile->current_physical_offset+8,
streamfile->real_file) ==
streamfile->stream_id)
{
streamfile->current_block_size =
(uint16_t)read_16bitBE(
streamfile->current_physical_offset+0x0a,
streamfile->real_file);
if (offset >= streamfile->current_logical_offset+
streamfile->current_block_size)
{
streamfile->current_logical_offset +=
streamfile->current_block_size;
}
else
{
found_block = 1;
}
}
if (!found_block)
{
streamfile->current_physical_offset +=
read_32bitBE(
streamfile->current_physical_offset+0x04,
streamfile->real_file
) + 8;
}
break;
case 0x41495846: /* AIXF */
/* shouldn't ever see this */
case 0x41495845: /* AIXE */
/* shouldn't have reached the end o' the line... */
default:
return sz;
break;
} /* end block/chunk type select */
} /* end while !found_block */
} /* end if !read_something */
} /* end while length > 0 */
return sz;
}
static void close_aix(AIXSTREAMFILE *streamfile)
{
free(streamfile);
return;
}
static size_t get_size_aix(AIXSTREAMFILE *streamfile)
{
return 0;
}
static size_t get_offset_aix(AIXSTREAMFILE *streamfile)
{
return streamfile->current_logical_offset;
}
static void get_name_aix(AIXSTREAMFILE *streamfile,char *buffer,size_t length)
{
strncpy(buffer,"ARBITRARY.ADX",length);
buffer[length-1]='\0';
}
static STREAMFILE *open_aix_impl(AIXSTREAMFILE *streamfile,const char * const filename,size_t buffersize)
{
AIXSTREAMFILE *newfile;
if (strcmp(filename,"ARBITRARY.ADX"))
return NULL;
newfile = malloc(sizeof(AIXSTREAMFILE));
if (!newfile)
return NULL;
memcpy(newfile,streamfile,sizeof(AIXSTREAMFILE));
return &newfile->sf;
}
static STREAMFILE *open_aix_with_STREAMFILE(STREAMFILE *file,off_t start_offset,int stream_id)
{
AIXSTREAMFILE *streamfile = malloc(sizeof(AIXSTREAMFILE));
if (!streamfile)
return NULL;
/* success, set our pointers */
streamfile->sf.read = (void*)read_aix;
streamfile->sf.get_size = (void*)get_size_aix;
streamfile->sf.get_offset = (void*)get_offset_aix;
streamfile->sf.get_name = (void*)get_name_aix;
streamfile->sf.get_realname = (void*)get_name_aix;
streamfile->sf.open = (void*)open_aix_impl;
streamfile->sf.close = (void*)close_aix;
#ifdef PROFILE_STREAMFILE
streamfile->sf.get_bytes_read = NULL;
streamfile->sf.get_error_count = NULL;
#endif
streamfile->real_file = file;
streamfile->current_physical_offset =
streamfile->start_physical_offset = start_offset;
streamfile->current_logical_offset = 0;
streamfile->current_block_size = 0;
streamfile->stream_id = stream_id;
return &streamfile->sf;
}

View File

@ -0,0 +1,32 @@
#include "../vgmstream.h"
#include "meta.h"
#if defined(VGM_USE_MP4V2) && defined(VGM_USE_FDKAAC)
VGMSTREAM * init_vgmstream_akb(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
size_t filesize;
uint32_t loop_start, loop_end;
if ((uint32_t)read_32bitBE(0, streamFile) != 0x414b4220) goto fail;
loop_start = read_32bitLE(0x14, streamFile);
loop_end = read_32bitLE(0x18, streamFile);
filesize = get_streamfile_size( streamFile );
vgmstream = init_vgmstream_mp4_aac_offset( streamFile, 0x20, filesize - 0x20 );
if ( !vgmstream ) goto fail;
if ( loop_start || loop_end ) {
vgmstream->loop_flag = 1;
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
}
return vgmstream;
fail:
return NULL;
}
#endif

View File

@ -0,0 +1,170 @@
#include "meta.h"
#include "../util.h"
/* Apple Core Audio Format */
VGMSTREAM * init_vgmstream_apple_caff(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset = 0;
off_t data_size = 0;
off_t sample_count = 0;
off_t interleave = 0;
int sample_rate = -1, unused_frames = 0;
int channel_count = 0;
off_t file_length;
off_t chunk_offset = 8;
int found_desc = 0, found_pakt = 0, found_data = 0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("caf",filename_extension(filename))) goto fail;
/* check "caff" id */
if (read_32bitBE(0,streamFile)!=0x63616666) goto fail;
/* check version, flags */
if (read_32bitBE(4,streamFile)!=0x00010000) goto fail;
file_length = (off_t)get_streamfile_size(streamFile);
while (chunk_offset < file_length)
{
/* high half of size (expect 0s) */
if (read_32bitBE(chunk_offset+4,streamFile) != 0) goto fail;
/* handle chunk type */
switch (read_32bitBE(chunk_offset,streamFile))
{
case 0x64657363: /* desc */
found_desc = 1;
{
/* rather than put a convoluted conversion here for
portability, just look it up */
uint32_t sratefloat = read_32bitBE(chunk_offset+0x0c, streamFile);
if (read_32bitBE(chunk_offset+0x10, streamFile) != 0) goto fail;
switch (sratefloat)
{
case 0x40D19400:
sample_rate = 18000;
break;
case 0x40D58880:
sample_rate = 22050;
break;
case 0x40DF4000:
sample_rate = 32000;
break;
case 0x40E58880:
sample_rate = 44100;
break;
case 0x40E77000:
sample_rate = 48000;
break;
default:
goto fail;
}
}
{
uint32_t bytes_per_packet, frames_per_packet, channels_per_frame, bits_per_channel;
uint32_t codec_4cc = read_32bitBE(chunk_offset+0x14, streamFile);
/* only supporting ima4 for now */
if (codec_4cc != 0x696d6134) goto fail;
/* format flags */
if (read_32bitBE(chunk_offset+0x18, streamFile) != 0) goto fail;
bytes_per_packet = read_32bitBE(chunk_offset+0x1c, streamFile);
frames_per_packet = read_32bitBE(chunk_offset+0x20, streamFile);
channels_per_frame = read_32bitBE(chunk_offset+0x24, streamFile);
bits_per_channel = read_32bitBE(chunk_offset+0x28, streamFile);
interleave = bytes_per_packet / channels_per_frame;
channel_count = channels_per_frame;
if (channels_per_frame != 1 && channels_per_frame != 2)
goto fail;
/* ima4-specific */
if (frames_per_packet != 64) goto fail;
if ((frames_per_packet / 2 + 2) * channels_per_frame !=
bytes_per_packet) goto fail;
if (bits_per_channel != 0) goto fail;
}
break;
case 0x70616b74: /* pakt */
found_pakt = 1;
/* 64-bit packet table size, 0 for constant bitrate */
if (
read_32bitBE(chunk_offset+0x0c,streamFile) != 0 ||
read_32bitBE(chunk_offset+0x10,streamFile) != 0) goto fail;
/* high half of valid frames count */
if (read_32bitBE(chunk_offset+0x14,streamFile) != 0) goto fail;
/* frame count */
sample_count = read_32bitBE(chunk_offset+0x18,streamFile);
/* priming frames */
if (read_32bitBE(chunk_offset+0x1c,streamFile) != 0) goto fail;
/* remainder (unused) frames */
unused_frames = read_32bitBE(chunk_offset+0x20,streamFile);
break;
case 0x66726565: /* free */
/* padding, ignore */
break;
case 0x64617461: /* data */
if (read_32bitBE(chunk_offset+12,streamFile) != 1) goto fail;
found_data = 1;
start_offset = chunk_offset + 16;
data_size = read_32bitBE(chunk_offset+8,streamFile) - 4;
break;
default:
goto fail;
}
/* done with chunk */
chunk_offset += 12 + read_32bitBE(chunk_offset+8,streamFile);
}
if (!found_pakt || !found_desc || !found_data) goto fail;
if (start_offset == 0 || data_size == 0 || sample_count == 0 ||
sample_rate == -1 || channel_count == 0) goto fail;
/* ima4-specific */
/* check for full packets */
if (data_size % (interleave*channel_count) != 0) goto fail;
if ((sample_count+unused_frames)%((interleave-2)*2) != 0) goto fail;
/* check that all packets are accounted for */
if (data_size/interleave/channel_count !=
(sample_count+unused_frames)/((interleave-2)*2)) goto fail;
vgmstream = allocate_vgmstream(channel_count,0);
if (!vgmstream) goto fail;
vgmstream->channels = channel_count;
vgmstream->sample_rate = sample_rate;
vgmstream->num_samples = sample_count;
/* ima4-specific */
vgmstream->coding_type = coding_APPLE_IMA4;
if (channel_count == 2)
vgmstream->layout_type = layout_interleave;
else
vgmstream->layout_type = layout_none;
vgmstream->interleave_block_size = interleave;
vgmstream->meta_type = meta_CAFF;
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++)
{
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].offset =
vgmstream->ch[i].channel_start_offset =
start_offset + interleave * i;
}
}
return vgmstream;
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,91 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
VGMSTREAM * init_vgmstream_ast(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
coding_t coding_type;
int codec_number;
int channel_count;
int loop_flag;
size_t max_block;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("ast",filename_extension(filename))) goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x5354524D || /* "STRM" */
read_16bitBE(0xa,streamFile)!=0x10 ||
/* check that file = header (0x40) + data */
read_32bitBE(4,streamFile)+0x40!=get_streamfile_size(streamFile))
goto fail;
/* check for a first block */
if (read_32bitBE(0x40,streamFile)!=0x424C434B) /* "BLCK" */
goto fail;
/* check type details */
codec_number = read_16bitBE(8,streamFile);
loop_flag = read_16bitBE(0xe,streamFile);
channel_count = read_16bitBE(0xc,streamFile);
max_block = read_32bitBE(0x20,streamFile);
switch (codec_number) {
case 0:
coding_type = coding_NGC_AFC;
break;
case 1:
coding_type = coding_PCM16BE;
break;
default:
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(0x14,streamFile);
vgmstream->sample_rate = read_32bitBE(0x10,streamFile);
/* channels and loop flag are set by allocate_vgmstream */
vgmstream->loop_start_sample = read_32bitBE(0x18,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x1c,streamFile);
vgmstream->coding_type = coding_type;
vgmstream->layout_type = layout_ast_blocked;
vgmstream->meta_type = meta_AST;
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
(i==0?
max_block+0x20-4: /* first buffer a bit bigger to
read block header without
inefficiency */
max_block
)
);
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
/* start me up */
ast_block_update(0x40,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,72 @@
#include "meta.h"
#include "../util.h"
/* .BAF - Bizarre Creations (Blur, James Bond 007: Blood Stone, etc) */
VGMSTREAM * init_vgmstream_baf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t WAVE_size,DATA_size;
off_t start_offset;
long sample_count;
const int frame_size = 33;
const int frame_samples = 64;
int channels;
int loop_flag = 0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("baf",filename_extension(filename))) goto fail;
/* check WAVE */
if (read_32bitBE(0,streamFile) != 0x57415645) goto fail;
WAVE_size = read_32bitBE(4,streamFile);
if (WAVE_size != 0x4c) goto fail;
/* check for DATA after WAVE */
if (read_32bitBE(WAVE_size,streamFile) != 0x44415441) goto fail;
/* check that WAVE size is data size */
DATA_size = read_32bitBE(0x30,streamFile);
if (read_32bitBE(WAVE_size+4,streamFile)-8 != DATA_size) goto fail;
sample_count = read_32bitBE(0x44,streamFile);
/* unsure how to detect channel count, so use a hack */
channels = (long long)DATA_size / frame_size * frame_samples / sample_count;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channels,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = WAVE_size + 8;
vgmstream->sample_rate = read_32bitBE(0x40,streamFile);
vgmstream->num_samples = sample_count;
vgmstream->coding_type = coding_BAF_ADPCM;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = frame_size;
vgmstream->meta_type = meta_BAF;
/* open the file for reading by each channel */
{
int i;
STREAMFILE *file = streamFile->open(streamFile,filename,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!file) goto fail;
for (i=0;i<channels;i++) {
vgmstream->ch[i].streamfile = file;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,126 @@
#include "meta.h"
#include "../util.h"
VGMSTREAM * init_vgmstream_bcstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
coding_t coding_type;
off_t head_offset;
int codec_number;
int channel_count;
int loop_flag;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile, filename, sizeof(filename));
if (strcasecmp("bcstm", filename_extension(filename)))
goto fail;
/* check header */
if ((uint32_t)read_32bitBE(0, streamFile) != 0x4353544D) /* "CSTM" */
goto fail;
if ((uint32_t)read_32bitBE(4, streamFile) != 0xFFFE4000)
goto fail;
/* get head offset, check */
head_offset = read_32bitLE(0x18, streamFile);
if ((uint32_t)read_32bitBE(head_offset, streamFile) != 0x494E464F) /* "INFO" */
goto fail;
/* check type details */
codec_number = read_8bit(head_offset + 0x20, streamFile);
loop_flag = read_8bit(head_offset + 0x21, streamFile);
channel_count = read_8bit(head_offset + 0x22, streamFile);
switch (codec_number) {
case 0:
coding_type = coding_PCM8;
break;
case 1:
coding_type = coding_PCM16BE;
break;
case 2:
coding_type = coding_NGC_DSP;
break;
default:
goto fail;
}
if (channel_count < 1) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count, loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitLE(head_offset + 0x2c, streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitLE(head_offset + 0x24, streamFile);
/* channels and loop flag are set by allocate_vgmstream */
vgmstream->loop_start_sample = read_32bitLE(head_offset + 0x28, streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_type;
if (channel_count == 1)
vgmstream->layout_type = layout_none;
else
vgmstream->layout_type = layout_interleave_shortblock;
vgmstream->meta_type = meta_CSTM;
vgmstream->interleave_block_size = read_32bitLE(head_offset + 0x34, streamFile);
vgmstream->interleave_smallblock_size = read_32bitLE(head_offset + 0x44, streamFile);
if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_offset;
off_t coef_offset1;
off_t coef_offset2;
int i, j;
int coef_spacing = 0x2E;
coef_offset1 = read_32bitLE(head_offset + 0x1c, streamFile);
coef_offset = coef_offset1 + 0x40;
for (j = 0; j<vgmstream->channels; j++) {
for (i = 0; i<16; i++) {
vgmstream->ch[j].adpcm_coef[i] = read_16bitLE(head_offset + coef_offset + j*coef_spacing + i * 2, streamFile);
}
}
}
start_offset = read_32bitLE(0x30, streamFile) + 0x20;
/* open the file for reading by each channel */
{
int i;
for (i = 0; i<channel_count; i++) {
if (vgmstream->layout_type == layout_interleave_shortblock)
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
vgmstream->interleave_block_size);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile, filename,
0x1000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset =
vgmstream->ch[i].offset =
start_offset + i*vgmstream->interleave_block_size;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,140 @@
#include "meta.h"
#include "../util.h"
/* BGW (FF XI) */
VGMSTREAM * init_vgmstream_bgw(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int32_t loop_start;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("bgw",filename_extension(filename))) goto fail;
/* "BGMStream" */
if (read_32bitBE(0,streamFile) != 0x42474d53 ||
read_32bitBE(4,streamFile) != 0x74726561 ||
read_32bitBE(8,streamFile) != 0x6d000000 ||
read_32bitBE(12,streamFile) != 0) goto fail;
/* check file size with header value */
if (read_32bitLE(0x10,streamFile) != get_streamfile_size(streamFile))
goto fail;
channel_count = read_8bit(0x2e,streamFile);
loop_start = read_32bitLE(0x1c,streamFile);
loop_flag = (loop_start > 0);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitLE(0x28,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_FFXI;
vgmstream->num_samples = read_32bitLE(0x18,streamFile)*16;
if (loop_flag) {
vgmstream->loop_start_sample = (loop_start-1)*16;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 9;
vgmstream->meta_type = meta_FFXI_BGW;
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+i*9;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
/* .spw (SEWave, PlayOnline viewer for FFXI), very similar to bgw */
VGMSTREAM * init_vgmstream_spw(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int32_t loop_start;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("spw",filename_extension(filename))) goto fail;
/* "SeWave" */
if (read_32bitBE(0,streamFile) != 0x53655761 ||
read_32bitBE(4,streamFile) != 0x76650000) goto fail;
/* check file size with header value */
if (read_32bitLE(0x8,streamFile) != get_streamfile_size(streamFile))
goto fail;
channel_count = read_8bit(0x2a,streamFile);
loop_start = read_32bitLE(0x18,streamFile);
loop_flag = (loop_start > 0);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = read_32bitLE(0x24,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = 44100;
vgmstream->coding_type = coding_FFXI;
vgmstream->num_samples = read_32bitLE(0x14,streamFile)*16;
if (loop_flag) {
vgmstream->loop_start_sample = (loop_start-1)*16;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 9;
vgmstream->meta_type = meta_FFXI_SPW;
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+i*9;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,202 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
#include "../vgmstream.h"
/* Namco Bandai's Bandai Namco Sound Format/File (BNSF) */
/* similar to RIFX */
VGMSTREAM * init_vgmstream_bnsf(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t file_size = -1;
uint32_t riff_size;
uint32_t bnsf_form;
enum {
form_IS14 = UINT32_C(0x49533134), /* IS14 */
};
int channel_count = 0;
int sample_count = 0;
int sample_rate = 0;
int coding_type = -1;
off_t start_offset = -1;
int loop_flag = 0;
off_t loop_start = -1;
off_t loop_end = -1;
uint32_t data_size = 0;
uint32_t block_size = 0;
uint32_t block_samples = 0;
int FormatChunkFound = 0;
int DataChunkFound = 0;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("bnsf",filename_extension(filename)))
{
goto fail;
}
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x424E5346) /* BNSF */
goto fail;
/* check form */
bnsf_form = read_32bitBE(8,streamFile);
switch (bnsf_form)
{
#ifdef VGM_USE_G7221
case form_IS14:
break;
#endif
default:
goto fail;
}
riff_size = read_32bitBE(4,streamFile);
file_size = get_streamfile_size(streamFile);
/* check for tructated RIFF */
if (file_size < riff_size+8) goto fail;
/* read through chunks to verify format and find metadata */
{
off_t current_chunk = 0xc; /* start with first chunk */
while (current_chunk < file_size && current_chunk < riff_size+8) {
uint32_t chunk_type = read_32bitBE(current_chunk,streamFile);
off_t chunk_size = read_32bitBE(current_chunk+4,streamFile);
if (current_chunk+8+chunk_size > file_size) goto fail;
switch(chunk_type) {
case 0x73666d74: /* "sfmt" */
/* only one per file */
if (FormatChunkFound) goto fail;
FormatChunkFound = 1;
sample_rate = read_32bitBE(current_chunk+0x0c,streamFile);
channel_count = read_16bitBE(current_chunk+0x0a,streamFile);
// read_32bitBE(current_chunk+0x10,streamFile); // ?
// read_32bitBE(current_chunk+0x14,streamFile); // ?
block_size = read_16bitBE(current_chunk+0x18,streamFile);
block_samples = read_16bitBE(current_chunk+0x1a,streamFile);
/* I assume this is still the codec id, but as the codec is
specified by the BNSF "form" I've only seen this zero */
switch ((uint16_t)read_16bitBE(current_chunk+0x8,streamFile)) {
case 0:
break;
default:
goto fail;
}
break;
case 0x73646174: /* sdat */
/* at most one per file */
if (DataChunkFound) goto fail;
DataChunkFound = 1;
start_offset = current_chunk + 8;
data_size = chunk_size;
break;
case 0x6C6F6F70: /* loop */
loop_flag = 1;
loop_start =
read_32bitBE(current_chunk+8, streamFile);
loop_end =
read_32bitBE(current_chunk+0xc,streamFile);
break;
default:
/* ignorance is bliss */
break;
}
current_chunk += 8+chunk_size;
}
}
if (!FormatChunkFound || !DataChunkFound) goto fail;
switch (bnsf_form) {
#ifdef VGM_USE_G7221
case form_IS14:
coding_type = coding_G7221C;
sample_count = data_size/block_size*block_samples;
break;
#endif
default:
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = sample_rate;
vgmstream->coding_type = coding_type;
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = block_size/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = loop_start;
vgmstream->loop_end_sample = loop_end;
}
vgmstream->meta_type = meta_BNSF;
#ifdef VGM_USE_G7221
if (coding_G7221C == coding_type)
{
int i;
g7221_codec_data *data;
/* one data structure per channel */
data = malloc(sizeof(g7221_codec_data) * channel_count);
if (!data)
{
goto fail;
}
memset(data,0,sizeof(g7221_codec_data) * channel_count);
vgmstream->codec_data = data;
for (i = 0; i < channel_count; i++)
{
/* Siren 14 == 14khz bandwidth */
data[i].handle = g7221_init(vgmstream->interleave_block_size, 14000);
if (!data[i].handle)
{
goto fail; /* close_vgmstream is able to clean up */
}
}
}
#endif
/* open the file, set up each channel */
{
int i;
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
vgmstream->ch[i].offset = vgmstream->ch[i].channel_start_offset =
start_offset+i*vgmstream->interleave_block_size;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,163 @@
#include "meta.h"
#include "../util.h"
VGMSTREAM * init_vgmstream_brstm(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
coding_t coding_type;
off_t head_offset;
int codec_number;
int channel_count;
int loop_flag;
/* Certain Super Paper Mario tracks have a 44.1KHz sample rate in the
* header, but they should be played at 22.05KHz. We will make this
* correction if we see a file with a .brstmspm extension. */
int spm_flag = 0;
/* Trauma Center Second Opinion has an odd, semi-corrupt header */
int atlus_shrunken_head = 0;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("brstm",filename_extension(filename))) {
if (strcasecmp("brstmspm",filename_extension(filename))) goto fail;
else spm_flag = 1;
}
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x5253544D) /* "RSTM" */
goto fail;
if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0100)
{
if ((uint32_t)read_32bitBE(4,streamFile)!=0xFEFF0001)
goto fail;
else
atlus_shrunken_head = 1;
}
/* get head offset, check */
head_offset = read_32bitBE(0x10,streamFile);
if (atlus_shrunken_head)
{
/* the HEAD chunk is where we would expect to find the offset of that
* chunk... */
if ((uint32_t)head_offset!=0x48454144 || read_32bitBE(0x14,streamFile) != 8)
goto fail;
head_offset = -8; /* most of the normal Nintendo RSTM offsets work
with this assumption */
}
else
{
if ((uint32_t)read_32bitBE(head_offset,streamFile)!=0x48454144) /* "HEAD" */
goto fail;
}
/* check type details */
codec_number = read_8bit(head_offset+0x20,streamFile);
loop_flag = read_8bit(head_offset+0x21,streamFile);
channel_count = read_8bit(head_offset+0x22,streamFile);
switch (codec_number) {
case 0:
coding_type = coding_PCM8;
break;
case 1:
coding_type = coding_PCM16BE;
break;
case 2:
coding_type = coding_NGC_DSP;
break;
default:
goto fail;
}
if (channel_count < 1) goto fail;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = read_32bitBE(head_offset+0x2c,streamFile);
vgmstream->sample_rate = (uint16_t)read_16bitBE(head_offset+0x24,streamFile);
/* channels and loop flag are set by allocate_vgmstream */
vgmstream->loop_start_sample = read_32bitBE(head_offset+0x28,streamFile);
vgmstream->loop_end_sample = vgmstream->num_samples;
vgmstream->coding_type = coding_type;
if (channel_count==1)
vgmstream->layout_type = layout_none;
else
vgmstream->layout_type = layout_interleave_shortblock;
vgmstream->meta_type = meta_RSTM;
if (atlus_shrunken_head)
vgmstream->meta_type = meta_RSTM_shrunken;
if (spm_flag&& vgmstream->sample_rate == 44100) {
vgmstream->meta_type = meta_RSTM_SPM;
vgmstream->sample_rate = 22050;
}
vgmstream->interleave_block_size = read_32bitBE(head_offset+0x38,streamFile);
vgmstream->interleave_smallblock_size = read_32bitBE(head_offset+0x48,streamFile);
if (vgmstream->coding_type == coding_NGC_DSP) {
off_t coef_offset;
off_t coef_offset1;
off_t coef_offset2;
int i,j;
int coef_spacing = 0x38;
if (atlus_shrunken_head)
{
coef_offset = 0x50;
coef_spacing = 0x30;
}
else
{
coef_offset1=read_32bitBE(head_offset+0x1c,streamFile);
coef_offset2=read_32bitBE(head_offset+0x10+coef_offset1,streamFile);
coef_offset=coef_offset2+0x10;
}
for (j=0;j<vgmstream->channels;j++) {
for (i=0;i<16;i++) {
vgmstream->ch[j].adpcm_coef[i]=read_16bitBE(head_offset+coef_offset+j*coef_spacing+i*2,streamFile);
}
}
}
start_offset = read_32bitBE(head_offset+0x30,streamFile);
/* open the file for reading by each channel */
{
int i;
for (i=0;i<channel_count;i++) {
if (vgmstream->layout_type==layout_interleave_shortblock)
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
vgmstream->interleave_block_size);
else
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,
0x1000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=
start_offset + i*vgmstream->interleave_block_size;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,68 @@
#include "meta.h"
#include "../util.h"
/* CAPDSP (found in Capcom games) */
VGMSTREAM * init_vgmstream_capdsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("capdsp",filename_extension(filename))) goto fail;
loop_flag = (read_32bitBE(0x14,streamFile) !=2);
channel_count = read_32bitBE(0x10,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x80;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x0C,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
vgmstream->num_samples = read_32bitBE(0x04,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile)/8/channel_count*14;
vgmstream->loop_end_sample = read_32bitBE(0x18,streamFile)/8/channel_count*14;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x4000;
vgmstream->meta_type = meta_CAPDSP;
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<8;i++) {
vgmstream->ch[0].adpcm_coef[i*2]=read_16bitBE(0x20+i*2,streamFile);
vgmstream->ch[0].adpcm_coef[i*2+1]=read_16bitBE(0x30+i*2,streamFile);
vgmstream->ch[1].adpcm_coef[i*2]=read_16bitBE(0x40+i*2,streamFile);
vgmstream->ch[1].adpcm_coef[i*2+1]=read_16bitBE(0x50+i*2,streamFile);
}
}
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,75 @@
#include "meta.h"
#include "../util.h"
/* ASD - found in Miss Moonlight (DC) */
VGMSTREAM * init_vgmstream_dc_asd(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("asd",filename_extension(filename))) goto fail;
/* We have no "Magic" words in this header format, so we have to do some,
other checks, it seems the samplecount is stored twice in the header,
we'll compare it... */
if (read_32bitLE(0x0,streamFile) != read_32bitLE(0x4,streamFile))
goto fail;
/* compare the frequency with the bitrate, if it doesn't match we'll close
the vgmstream... */
if (read_32bitLE(0x10,streamFile)/read_32bitLE(0xC,streamFile) != (uint16_t)read_16bitLE(0xA,streamFile)*2)
goto fail;
loop_flag = 0;
channel_count = read_16bitLE(0x0A,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = get_streamfile_size(streamFile) - read_32bitLE(0x0,streamFile);
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x0C,streamFile);
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = read_32bitLE(0x0,streamFile)/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x0,streamFile)/2/channel_count;
}
vgmstream->meta_type = meta_DC_ASD;
if (vgmstream->channels == 1) {
vgmstream->layout_type = layout_none;
} else if (vgmstream->channels == 2) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2;
}
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,119 @@
#include "meta.h"
#include "../util.h"
/* WAV+DCS (DCSW+DCS)
2008-12-06 - manakoAT : Evil Twin - Cypriens Chronicles...
2008-12-07 - manakoAT : Added a function to read the Header file and for
retrieving the channels/frequency, Frequency starts
always at a "data" chunk - 0x0C bytes, Channels
always - 0x0E bytes...
2010-01-13 - manakoAT : Changed the 'Helper' extension from .wav to .dcws, to prevent conflicts */
VGMSTREAM * init_vgmstream_dc_dcsw_dcs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileDCSW = NULL;
char filename[PATH_LIMIT];
char filenameDCSW[260];
int i;
int channel_count;
int loop_flag;
int frequency;
int dataBuffer = 0;
int Founddata = 0;
size_t file_size;
off_t current_chunk;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("dcs",filename_extension(filename))) goto fail;
/* Getting the Header file name... */
strcpy(filenameDCSW,filename);
strcpy(filenameDCSW+strlen(filenameDCSW)-3,"dcsw");
/* Look if the Header file is present, else cancel vgmstream */
streamFileDCSW = streamFile->open(streamFile,filenameDCSW,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!streamFileDCSW) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFileDCSW) != 0x52494646 || /* "RIFF" */
read_32bitBE(0x08,streamFileDCSW) != 0x57415645 || /* "WAVE" */
read_32bitBE(0x0C,streamFileDCSW) != 0x34582E76 || /* 0x34582E76 */
read_32bitBE(0x3C,streamFileDCSW) != 0x406E616D) /* "@nam" */
goto fail;
/* scan file until we find a "data" string */
file_size = get_streamfile_size(streamFileDCSW);
{
current_chunk = 0;
/* Start at 0 and loop until we reached the
file size, or until we found a "data string */
while (!Founddata && current_chunk < file_size) {
dataBuffer = (read_32bitBE(current_chunk,streamFileDCSW));
if (dataBuffer == 0x64617461) { /* "data" */
/* if "data" string found, retrieve the needed infos */
Founddata = 1;
/* We will cancel the search here if we have a match */
break;
}
/* else we will increase the search offset by 1 */
current_chunk = current_chunk + 1;
}
}
if (Founddata == 0) {
goto fail;
} else if (Founddata == 1) {
channel_count = (uint16_t)read_16bitLE(current_chunk-0x0E,streamFileDCSW);
frequency = read_32bitLE(current_chunk-0x0C,streamFileDCSW);
}
loop_flag = 0;
/* Seems we're dealing with a vaild file+header,
now we can finally build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = frequency;
vgmstream->num_samples=(get_streamfile_size(streamFile))*2/channel_count;
if(loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile))*2/channel_count;
}
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
} else if (channel_count > 1) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x4000;
}
vgmstream->coding_type = coding_AICA;
vgmstream->meta_type = meta_DC_DCSW_DCS;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
vgmstream->ch[i].adpcm_step_index = 0x7f; /* AICA */
}
}
close_streamfile(streamFileDCSW); streamFileDCSW=NULL;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (streamFileDCSW) close_streamfile(streamFileDCSW);
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,71 @@
#include "meta.h"
#include "../util.h"
/* IDVI (Eldorado Gate Volume 1-7) */
VGMSTREAM * init_vgmstream_dc_idvi(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("idvi",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x49445649) /* "IDVI." */
goto fail;
loop_flag = read_32bitLE(0x0C,streamFile);
channel_count = read_32bitLE(0x04,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
start_offset = 0x800;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->coding_type = coding_INT_DVI_IMA;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitLE(0x0C,streamFile);
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset);
}
vgmstream->meta_type = meta_DC_IDVI;
/* Calculating the short block... */
if (channel_count > 1) {
vgmstream->interleave_block_size = 0x400;
vgmstream->interleave_smallblock_size = ((get_streamfile_size(streamFile)-start_offset)%(vgmstream->channels*vgmstream->interleave_block_size))/vgmstream->channels;
vgmstream->layout_type = layout_interleave_shortblock;
} else {
vgmstream->layout_type = layout_none;
}
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,66 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
VGMSTREAM * init_vgmstream_kcey(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("kcey",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x4B434559) /* "DVI." */
goto fail;
loop_flag = (read_32bitBE(0x14,streamFile)!=0xFFFFFFFF);
channel_count = read_32bitBE(0x08,streamFile);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
start_offset = read_32bitBE(0x10,streamFile);
vgmstream->sample_rate = 37800;
vgmstream->coding_type = coding_EACS_IMA;
vgmstream->num_samples = read_32bitBE(0x0C,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x14,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x0C,streamFile);
}
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_KCEY;
vgmstream->get_high_nibble=1;
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+(i*vgmstream->interleave_block_size);
vgmstream->ch[i].adpcm_history1_32=0;
vgmstream->ch[i].adpcm_step_index=0;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,165 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../util.h"
/* SEGA Stream Asset Builder...
this meta handles only V1 and V3... */
VGMSTREAM * init_vgmstream_dc_str(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int interleave;
int channel_count;
int samples;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0xD5,streamFile) != 0x53656761) /* "Sega" */
goto fail;
interleave = read_32bitLE(0xC,streamFile);
if ((get_streamfile_size(streamFile)-0x800) != (read_32bitLE(0x10,streamFile) *
((read_32bitLE(0x0,streamFile)*(read_32bitLE(0x18,streamFile))))*interleave))
goto fail;
loop_flag = 0; /* (read_32bitLE(0x00,streamFile)!=0x00000000); */
samples = read_32bitLE(0x08,streamFile);
channel_count = (read_32bitLE(0x0,streamFile))*(read_32bitLE(0x18,streamFile));
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
switch (samples) {
case 4:
vgmstream->coding_type = coding_AICA;
vgmstream->num_samples = read_32bitLE(0x14,streamFile);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile);
}
break;
case 16:
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = read_32bitLE(0x14,streamFile)/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = read_32bitLE(0x14,streamFile)/2/channel_count;
}
break;
default:
goto fail;
}
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x04,streamFile);
if (vgmstream->channels == 1) {
vgmstream->layout_type = layout_none;
} else if (vgmstream->channels > 1) {
vgmstream->interleave_block_size = interleave;
vgmstream->layout_type = layout_interleave;
}
vgmstream->meta_type = meta_DC_STR;
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
/* This handles V2, not sure if it is really V2, cause the header is always
the same, not like in V1 and V3, only found in "102 Dalmatians - Puppies to the Rescue"
until now... */
VGMSTREAM * init_vgmstream_dc_str_v2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t start_offset;
int loop_flag = 0;
int channel_count;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("str",filename_extension(filename))) goto fail;
/* check header */
if ((read_32bitLE(0x00,streamFile) != 0x2))
goto fail;
if ((read_32bitLE(0x10,streamFile) != 0x10000))
goto fail;
if ((read_32bitLE(0x1C,streamFile) != 0x1F))
goto fail;
channel_count = 2;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
start_offset = 0x800;
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitLE(0x4,streamFile);
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = (get_streamfile_size(streamFile)-start_offset)/2/channel_count;
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (get_streamfile_size(streamFile)-start_offset)/2/channel_count;
}
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = read_32bitLE(0xC,streamFile);
vgmstream->meta_type = meta_DC_STR_V2;
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,101 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
/* Gurumin .de2 */
/* A ways into the file we have a fake RIFF header wrapping MS ADPCM */
VGMSTREAM * init_vgmstream_de2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
off_t riff_off;
int channel_count;
int sample_count;
int sample_rate;
off_t start_offset;
int loop_flag = 0;
uint32_t data_size;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("de2",filename_extension(filename))) goto fail;
/* still not sure what this is for, but consistently 0xb */
if (read_32bitLE(0x04,streamFile)!=0xb) goto fail;
/* legitimate! really! */
riff_off = 0x10 +
(read_32bitLE(0x0c,streamFile) ^ read_32bitLE(0x04,streamFile));
/* check header */
if ((uint32_t)read_32bitBE(riff_off+0,streamFile)!=0x52494646) /* "RIFF" */
goto fail;
/* check for WAVE form */
if ((uint32_t)read_32bitBE(riff_off+8,streamFile)!=0x57415645) /* "WAVE" */
goto fail;
/* check for "fmt " */
if ((uint32_t)read_32bitBE(riff_off+12,streamFile)!=0x666d7420) /* "fmt " */
goto fail;
/* check for "data" */
if ((uint32_t)read_32bitBE(riff_off+0x24,streamFile)!=0x64617461) /* "data" */
goto fail;
/* check for bad fmt chunk size */
if (read_32bitLE(riff_off+0x10,streamFile)!=0x12) goto fail;
sample_rate = read_32bitLE(riff_off+0x18,streamFile);
channel_count = read_16bitLE(riff_off+0x16,streamFile);
if (channel_count != 2) goto fail;
/* PCM */
if (read_16bitLE(riff_off+0x14,streamFile) != 1) goto fail;
/* 16-bit */
if (read_16bitLE(riff_off+0x20,streamFile) != 4 ||
read_16bitLE(riff_off+0x22,streamFile) != 16) goto fail;
start_offset = riff_off + 0x2c;
data_size = read_32bitLE(riff_off+0x28,streamFile);
sample_count = data_size/2/channel_count;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->num_samples = sample_count;
vgmstream->sample_rate = sample_rate;
vgmstream->coding_type = coding_MSADPCM;
vgmstream->layout_type = layout_de2_blocked;
vgmstream->interleave_block_size = 0x800;
vgmstream->meta_type = meta_DE2;
/* open the file, set up each channel */
{
int i;
vgmstream->ch[0].streamfile = streamFile->open(streamFile,filename,
STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!vgmstream->ch[0].streamfile) goto fail;
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = vgmstream->ch[0].streamfile;
}
}
/* start me up */
de2_block_update(start_offset,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,110 @@
#include "meta.h"
#include "../util.h"
/* DMSG
found in: Nightcaster II - Equinox
2010-01-05 (manakoAT): Seems it's a corrupted "SGT" file, but I'm not sure...
*/
VGMSTREAM * init_vgmstream_dmsg(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int loop_flag = 0;
int frequency;
int channel_count;
int dataBuffer = 0;
int Founddata = 0;
size_t file_size;
off_t current_chunk;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("dmsg",filename_extension(filename))) goto fail;
/* check header */
if (read_32bitBE(0x00,streamFile) != 0x52494646) /* "RIFF" */
goto fail;
if (read_32bitBE(0x08,streamFile) != 0x444D5347) /* "DMSG" */
goto fail;
if (read_32bitBE(0x0C,streamFile) != 0x73656768) /* "segh" */
goto fail;
if (read_32bitBE(0x10,streamFile) != 0x38000000) /* "0x38" */
goto fail;
/* scan file until we find a "data" string */
file_size = get_streamfile_size(streamFile);
{
current_chunk = 0;
/* Start at 0 and loop until we reached the
file size, or until we found a "data string */
while (!Founddata && current_chunk < file_size) {
dataBuffer = (read_32bitBE(current_chunk,streamFile));
if (dataBuffer == 0x64617461) { /* "data" */
/* if "data" string found, retrieve the needed infos */
Founddata = 1;
/* We will cancel the search here if we have a match */
break;
}
/* else we will increase the search offset by 1 */
current_chunk = current_chunk + 1;
}
}
if (Founddata == 0) {
goto fail;
} else if (Founddata == 1) {
channel_count = (uint16_t)read_16bitLE(current_chunk-0x10,streamFile);
frequency = read_32bitLE(current_chunk-0xE,streamFile);
}
loop_flag = 1;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
if (Founddata == 0) {
goto fail;
} else if (Founddata == 1) {
start_offset = current_chunk+0x8;
vgmstream->channels = channel_count;
vgmstream->sample_rate = frequency;
vgmstream->coding_type = coding_PCM16LE;
vgmstream->num_samples = (read_32bitLE(current_chunk+0x4,streamFile)/2/channel_count);
if (loop_flag) {
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = (read_32bitLE(current_chunk+0x4,streamFile)/2/channel_count);
}
}
if (channel_count == 1) {
vgmstream->layout_type = layout_none;
} else if (channel_count > 1) {
vgmstream->layout_type = layout_interleave;
vgmstream->interleave_block_size = 0x2;
}
vgmstream->meta_type = meta_DMSG;
/* open the file for reading */
{
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;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=start_offset+
vgmstream->interleave_block_size*i;
}
}
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,87 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../util.h"
VGMSTREAM * init_vgmstream_dsp_bdsp(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int channel_count;
int loop_flag;
int i;
off_t start_offset;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("bdsp",filename_extension(filename))) goto fail;
channel_count = 2;
loop_flag = 0;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x8,streamFile);
vgmstream->coding_type = coding_NGC_DSP;
#if 0
if(loop_flag) {
vgmstream->loop_start_sample = read_32bitBE(0x64,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0x68,streamFile);
}
#endif
vgmstream->layout_type = layout_dsp_bdsp_blocked;
vgmstream->interleave_block_size = 0x8;
vgmstream->meta_type = meta_DSP_BDSP;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,vgmstream->interleave_block_size);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=
vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
}
}
if (vgmstream->coding_type == coding_NGC_DSP) {
int i;
for (i=0;i<16;i++) {
vgmstream->ch[0].adpcm_coef[i] = read_16bitBE(0x1C+i*2,streamFile);
}
if (vgmstream->channels == 2) {
for (i=0;i<16;i++) {
vgmstream->ch[1].adpcm_coef[i] = read_16bitBE(0x7C+i*2,streamFile);
}
}
}
/* Calc num_samples */
start_offset = 0x0;
dsp_bdsp_block_update(start_offset,vgmstream);
vgmstream->num_samples=0;
do
{
vgmstream->num_samples += vgmstream->current_block_size*14/8;
dsp_bdsp_block_update(vgmstream->next_block_offset,vgmstream);
}
while (vgmstream->next_block_offset<get_streamfile_size(streamFile));
dsp_bdsp_block_update(start_offset,vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,320 @@
#include "meta.h"
#include "../util.h"
/*
STH+STR
found in SpongebobSquarepants: Creature From The Krusty Krab (NGC)
*/
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str1(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileSTR = NULL;
char filename[PATH_LIMIT];
char filenameSTR[260];
int i, j;
int channel_count;
int loop_flag;
off_t coef_table[8] = {0x12C,0x18C,0x1EC,0x24C,0x2AC,0x30C,0x36C,0x3CC};
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("sth",filename_extension(filename))) goto fail;
strcpy(filenameSTR,filename);
strcpy(filenameSTR+strlen(filenameSTR)-3,"str");
streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!streamFileSTR) goto fail;
if (read_32bitBE(0x0,streamFile) != 0x0)
{
goto fail;
}
if (read_32bitBE(0x4,streamFile) != 0x800)
{
goto fail;
}
/* Not really channel_count, just 'included tracks * channels per track */
loop_flag = (read_32bitBE(0xD8,streamFile) != 0xFFFFFFFF);
channel_count = (read_32bitBE(0x70,streamFile)) * (read_32bitBE(0x88,streamFile));
if (channel_count > 8)
{
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x24,streamFile);
vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14;
vgmstream->coding_type = coding_NGC_DSP;
if(loop_flag)
{
vgmstream->loop_start_sample = read_32bitBE(0xD8,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0xDC,streamFile);
}
if (channel_count == 1)
{
vgmstream->layout_type = layout_none;
}
else
{
vgmstream->layout_type = layout_interleave;
if (channel_count == 2)
{
vgmstream->interleave_block_size=0x10000;
}
else
{
vgmstream->interleave_block_size=0x8000;
}
}
vgmstream->meta_type = meta_NGC_DSP_STH_STR;
/* open the file for reading */
for (i=0;i<channel_count;i++)
{
vgmstream->ch[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
}
// COEFFS
for (j=0;j<vgmstream->channels;j++)
{
for (i=0;i<16;i++)
{
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile);
}
}
close_streamfile(streamFileSTR); streamFileSTR=NULL;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (streamFileSTR) close_streamfile(streamFileSTR);
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
/*
STH+STR
found in Taz Wanted (NGC), Cubix Robots for Everyone: Showdown (NGC)
*/
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str2(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileSTR = NULL;
char filename[PATH_LIMIT];
char filenameSTR[260];
int i, j;
int channel_count;
int loop_flag;
off_t coef_table[8] = {0xDC,0x13C,0x19C,0x1FC,0x25C,0x2BC,0x31C,0x37C};
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("sth",filename_extension(filename))) goto fail;
strcpy(filenameSTR,filename);
strcpy(filenameSTR+strlen(filenameSTR)-3,"str");
streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!streamFileSTR) goto fail;
if (read_32bitBE(0x0,streamFile) != 0x0)
{
goto fail;
}
if (read_32bitBE(0x4,streamFile) != 0x900)
{
goto fail;
}
/* Not really channel_count, just 'included tracks * channels per track */
loop_flag = (read_32bitBE(0xB8,streamFile) != 0xFFFFFFFF);
channel_count = read_32bitBE(0x50,streamFile)*2;
if (channel_count > 8)
{
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x24,streamFile);
vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14;
vgmstream->coding_type = coding_NGC_DSP;
if(loop_flag)
{
vgmstream->loop_start_sample = read_32bitBE(0xB8,streamFile);
vgmstream->loop_end_sample = read_32bitBE(0xBC,streamFile);
}
if (channel_count == 1)
{
vgmstream->layout_type = layout_none;
}
else
{
vgmstream->layout_type = layout_interleave;
if (channel_count == 2)
{
vgmstream->interleave_block_size=0x10000;
}
else
{
vgmstream->interleave_block_size=0x8000;
}
}
vgmstream->meta_type = meta_NGC_DSP_STH_STR;
/* open the file for reading */
for (i=0;i<channel_count;i++)
{
vgmstream->ch[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
}
// COEFFS
for (j=0;j<vgmstream->channels;j++)
{
for (i=0;i<16;i++)
{
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile);
}
}
close_streamfile(streamFileSTR); streamFileSTR=NULL;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (streamFileSTR) close_streamfile(streamFileSTR);
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}
/*
STH+STR
found in Tak and the Guardians of Gross (WII)
*/
VGMSTREAM * init_vgmstream_ngc_dsp_sth_str3(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
STREAMFILE * streamFileSTR = NULL;
char filename[PATH_LIMIT];
char filenameSTR[260];
int i, j;
int channel_count;
int loop_flag;
off_t coef_table[8] = {read_32bitBE(0x7C,streamFile),read_32bitBE(0x80,streamFile),read_32bitBE(0x84,streamFile),read_32bitBE(0x88,streamFile),read_32bitBE(0x8C,streamFile),read_32bitBE(0x90,streamFile),read_32bitBE(0x94,streamFile),read_32bitBE(0x98,streamFile)};
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("sth",filename_extension(filename))) goto fail;
strcpy(filenameSTR,filename);
strcpy(filenameSTR+strlen(filenameSTR)-3,"str");
streamFileSTR = streamFile->open(streamFile,filenameSTR,STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!streamFileSTR) goto fail;
if (read_32bitBE(0x0,streamFile) != 0x0)
{
goto fail;
}
if ((read_32bitBE(0x4,streamFile) != 0x700) &&
(read_32bitBE(0x4,streamFile) != 0x800))
{
goto fail;
}
/* Not really channel_count, just 'included tracks * channels per track */
loop_flag = 0;
channel_count = read_32bitBE(0x70,streamFile);
if (channel_count > 8)
{
goto fail;
}
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->sample_rate = read_32bitBE(0x38,streamFile);
vgmstream->num_samples=get_streamfile_size(streamFileSTR)/8/channel_count*14;
vgmstream->coding_type = coding_NGC_DSP;
if(loop_flag)
{
vgmstream->loop_start_sample = 0;
vgmstream->loop_end_sample = 0;
}
if (channel_count == 1)
{
vgmstream->layout_type = layout_none;
}
else
{
vgmstream->layout_type = layout_interleave;
if (channel_count == 2 || channel_count == 4)
{
vgmstream->interleave_block_size=0x8000;
}
else
{
vgmstream->interleave_block_size=0x4000;
}
}
vgmstream->meta_type = meta_NGC_DSP_STH_STR;
/* open the file for reading */
for (i=0;i<channel_count;i++)
{
vgmstream->ch[i].streamfile = streamFileSTR->open(streamFileSTR,filenameSTR,0x8000);
if (!vgmstream->ch[i].streamfile) goto fail;
vgmstream->ch[i].channel_start_offset=vgmstream->ch[i].offset=i*vgmstream->interleave_block_size;
}
// COEFFS
for (j=0;j<vgmstream->channels;j++)
{
for (i=0;i<16;i++)
{
vgmstream->ch[j].adpcm_coef[i] = read_16bitBE(coef_table[j]+i*2,streamFile);
}
}
close_streamfile(streamFileSTR); streamFileSTR=NULL;
return vgmstream;
/* clean up anything we may have opened */
fail:
if (streamFileSTR) close_streamfile(streamFileSTR);
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,308 @@
#include "meta.h"
#include "../layout/layout.h"
#include "../coding/coding.h"
#include "../util.h"
// Platform constants
#define EA_PC 0x00
#define EA_PSX 0x01
#define EA_PS2 0x05
#define EA_GC 0x06
#define EA_XBOX 0x07
#define EA_X360 0x09
// Compression Version
#define EAXA_R1 0x01
#define EAXA_R2 0x02
#define EAXA_R3 0x03
// Compression Type
#define EA_VAG 0x01
#define EA_EAXA 0x0A
#define EA_ADPCM 0x30
#define EA_PCM_BE 0x07
#define EA_PCM_LE 0x08
#define EA_IMA 0x14
typedef struct {
int32_t num_samples;
int32_t sample_rate;
uint8_t channels;
uint8_t platform;
int32_t interleave;
uint8_t compression_type;
uint8_t compression_version;
} EA_STRUCT;
uint32_t readPatch(STREAMFILE* streamFile, off_t* offset) {
uint32_t result=0;
uint8_t byteCount;
byteCount = read_8bit(*offset,streamFile);
(*offset)++;
for(;byteCount>0;byteCount--) {
result <<=8;
result+=(uint8_t)read_8bit(*offset,streamFile);
(*offset)++;
}
return result;
}
void Parse_Header(STREAMFILE* streamFile,EA_STRUCT* ea, off_t offset, int length) {
uint8_t byteRead;
off_t begin_offset=offset;
// default value ...
ea->channels=1;
ea->compression_type=0;
ea->compression_version=0x01;
ea->platform=EA_GC;
if(read_32bitBE(offset, streamFile)==0x47535452) { // GSTR
ea->compression_version=0x03;
offset+=8;
ea->platform=6;
} else {
if(read_16bitBE(offset,streamFile)!=0x5054) // PT
offset+=4;
ea->platform=(uint8_t)read_16bitLE(offset+2,streamFile);
offset+=4;
}
do {
byteRead = read_8bit(offset++,streamFile);
switch(byteRead) {
case 0xFF:
case 0xFE:
case 0xFC:
case 0xFD:
break;
#if 0
// was added for My Sims Kingdom, apparently this is not the right
// way to do it (see NFS Most Wanted and Underground 2)
case 0x06: //
if (readPatch(streamFile, &offset) == 0x65)
ea->compression_type = EA_PCM_BE;
break;
#endif
case 0x80: // compression version
ea->compression_version = (uint8_t)readPatch(streamFile, &offset);
break;
case 0x82: // channels count
ea->channels = (uint8_t)readPatch(streamFile, &offset);
break;
case 0x83: // compression type
ea->compression_type = (uint8_t)readPatch(streamFile, &offset);
if(ea->compression_type==0x07) ea->compression_type=0x30;
break;
case 0x84: // sample frequency
ea->sample_rate = readPatch(streamFile,&offset);
break;
case 0x85: // samples count
ea->num_samples = readPatch(streamFile, &offset);
break;
case 0x8A:
offset+=4;
if(ea->compression_type==0) ea->compression_type=EA_PCM_LE;
break;
case 0x86:
case 0x87:
case 0x8C:
case 0x92:
case 0x9C:
case 0x9D: // unknown patch
readPatch(streamFile, &offset);
break;
case 0x88: // interleave
ea->interleave = readPatch(streamFile, &offset);
break;
case 0xA0: // compression type
ea->compression_type = (uint8_t)readPatch(streamFile, &offset);
break;
}
} while(offset-begin_offset<length);
if(ea->platform==EA_PSX)
ea->compression_type=EA_VAG;
if(ea->compression_type==0)
ea->compression_type=EA_EAXA;
}
VGMSTREAM * init_vgmstream_ea(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
EA_STRUCT ea;
char filename[PATH_LIMIT];
int loop_flag=0;
int channel_count;
int header_length;
off_t start_offset;
int i;
memset(&ea,0,sizeof(EA_STRUCT));
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("strm",filename_extension(filename)) &&
strcasecmp("xa",filename_extension(filename)) &&
strcasecmp("sng",filename_extension(filename)) &&
strcasecmp("asf",filename_extension(filename)) &&
strcasecmp("str",filename_extension(filename)) &&
strcasecmp("xsf",filename_extension(filename)) &&
strcasecmp("eam",filename_extension(filename))) goto fail;
/* check Header */
if (read_32bitBE(0x00,streamFile) != 0x5343486C) // SCHl
goto fail;
header_length = read_32bitLE(0x04,streamFile);
start_offset=8;
if(header_length>0x100) goto fail;
Parse_Header(streamFile,&ea,start_offset,header_length-8);
/* unknown loop value for the moment */
loop_flag = 0;
channel_count=ea.channels;
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,loop_flag);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
vgmstream->channels = channel_count;
vgmstream->ea_platform=ea.platform;
vgmstream->ea_compression_type=ea.compression_type;
vgmstream->ea_compression_version=ea.compression_version;
// Set defaut sample rate if not define in the header
if(ea.sample_rate!=0) {
vgmstream->sample_rate = ea.sample_rate;
} else {
if(read_32bitBE(0x08,streamFile)==0x47535452) { // GSTR
vgmstream->sample_rate=44100;
} else {
switch(vgmstream->ea_platform) {
case EA_XBOX:
vgmstream->sample_rate=24000;
break;
case EA_X360:
vgmstream->sample_rate=44100;
break;
default:
vgmstream->sample_rate=22050;
}
}
}
// Set default compression scheme if not define in the header
switch(vgmstream->ea_platform) {
case EA_X360:
vgmstream->ea_compression_version=0x03;
break;
}
vgmstream->num_samples=ea.num_samples;
switch(vgmstream->ea_compression_type) {
case EA_EAXA:
if(vgmstream->ea_compression_version==0x03)
vgmstream->meta_type=meta_EAXA_R3;
else {
// seems there's no EAXA R2 on PC
if(ea.platform==EA_PC) {
vgmstream->ea_compression_version=0x03;
vgmstream->meta_type=meta_EAXA_R3;
} else
vgmstream->meta_type=meta_EAXA_R2;
}
vgmstream->coding_type=coding_EAXA;
vgmstream->layout_type=layout_ea_blocked;
if((vgmstream->ea_platform==EA_GC) || (vgmstream->ea_platform==EA_X360))
vgmstream->ea_big_endian=1;
break;
case EA_VAG:
vgmstream->meta_type=meta_EAXA_PSX;
vgmstream->coding_type=coding_PSX;
vgmstream->layout_type=layout_ea_blocked;
break;
case EA_PCM_LE:
vgmstream->meta_type=meta_EA_PCM;
vgmstream->coding_type=coding_PCM16LE_int;
vgmstream->layout_type=layout_ea_blocked;
break;
case EA_PCM_BE:
vgmstream->meta_type=meta_EA_PCM;
vgmstream->coding_type=coding_PCM16BE;
vgmstream->layout_type=layout_ea_blocked;
break;
case EA_ADPCM:
vgmstream->meta_type=meta_EA_ADPCM;
vgmstream->coding_type=coding_EA_ADPCM;
vgmstream->layout_type=layout_ea_blocked;
break;
case EA_IMA:
vgmstream->meta_type=meta_EA_IMA;
vgmstream->coding_type=coding_XBOX;
vgmstream->layout_type=layout_ea_blocked;
break;
}
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
// Special function for .EAM files ...
if(!strcasecmp("eam",filename_extension(filename))) {
size_t file_length=get_streamfile_size(streamFile);
size_t block_length;
vgmstream->next_block_offset=start_offset+header_length;
vgmstream->num_samples=0;
// to initialize the block length
ea_block_update(start_offset+header_length,vgmstream);
block_length=vgmstream->next_block_offset-start_offset+header_length;
do {
ea_block_update(vgmstream->next_block_offset,vgmstream);
if(vgmstream->coding_type==coding_PSX)
vgmstream->num_samples+=(int32_t)vgmstream->current_block_size/16*28;
else if (vgmstream->coding_type==coding_EA_ADPCM)
vgmstream->num_samples+=(int32_t)vgmstream->current_block_size;
else if (vgmstream->coding_type==coding_PCM16LE_int)
vgmstream->num_samples+=(int32_t)vgmstream->current_block_size/vgmstream->channels;
else
vgmstream->num_samples+=(int32_t)vgmstream->current_block_size*28;
} while(vgmstream->next_block_offset<(off_t)(file_length-block_length));
}
ea_block_update(start_offset+header_length,vgmstream);
init_get_high_nibble(vgmstream);
return vgmstream;
/* clean up anything we may have opened */
fail:
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

View File

@ -0,0 +1,162 @@
#include "meta.h"
#include "../coding/coding.h"
#include "../layout/layout.h"
#include "../util.h"
typedef struct
{
char szID[4];
int dwSampleRate;
char bBits;
char bChannels;
char bCompression;
char bType;
int dwNumSamples;
int dwLoopStart;
int dwLoopLength;
int dwDataStart;
int dwUnknown;
} EACSHeader;
VGMSTREAM * init_vgmstream_eacs(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
char filename[PATH_LIMIT];
int channel_count;
int loop_flag=0;
char little_endian=0;
off_t start_offset;
EACSHeader *ea_header = NULL;
int32_t samples_count=0;
int i;
/* check extension, case insensitive */
streamFile->get_name(streamFile,filename,sizeof(filename));
if (strcasecmp("cnk",filename_extension(filename)) &&
strcasecmp("as4",filename_extension(filename)) &&
strcasecmp("asf",filename_extension(filename))) goto fail;
ea_header=(EACSHeader *)malloc(sizeof(EACSHeader));
/* check header */
if ((uint32_t)read_32bitBE(0,streamFile)!=0x31534E68) /* "1SNh" */
goto fail;
/* check if we are little or big endian */
if ((uint32_t)read_32bitBE(4,streamFile)<0x40)
little_endian=1;
/* check type details */
start_offset = read_32bitLE(0x04,streamFile);
if((uint32_t)read_32bitBE(0x08,streamFile)==0x45414353) { /* EACS */
read_streamfile((uint8_t*)ea_header,0x08,sizeof(EACSHeader),streamFile);
loop_flag = 0; //(ea_header->dwLoopStart!=0);
channel_count = (ea_header->bChannels);
/* build the VGMSTREAM */
vgmstream = allocate_vgmstream(channel_count,0);
if (!vgmstream) goto fail;
/* fill in the vital statistics */
init_get_high_nibble(vgmstream);
vgmstream->sample_rate = ea_header->dwSampleRate;
if(ea_header->bCompression==0) {
vgmstream->coding_type = coding_PCM16LE_int;
if(ea_header->bBits==1)
vgmstream->coding_type = coding_PCM8_int;
}
else
vgmstream->coding_type = coding_EACS_IMA;
vgmstream->layout_type = layout_eacs_blocked;
vgmstream->meta_type = meta_EACS_PC;
if(little_endian)
vgmstream->meta_type = meta_EACS_SAT;
} else {
channel_count=read_32bitLE(0x20,streamFile);
vgmstream = allocate_vgmstream(channel_count,0);
if (!vgmstream) goto fail;
vgmstream->sample_rate = read_32bitLE(0x08,streamFile);
vgmstream->coding_type = coding_PSX;
vgmstream->layout_type=layout_eacs_blocked;
vgmstream->meta_type=meta_EACS_PSX;
}
vgmstream->ea_platform=little_endian;
/* open the file for reading by each channel */
{
for (i=0;i<channel_count;i++) {
vgmstream->ch[i].streamfile = streamFile->open(streamFile,filename,0x8000);
if (!vgmstream->ch[i].streamfile) goto fail;
}
}
// calc the samples length ...
if(little_endian)
vgmstream->next_block_offset=read_32bitBE(0x04,streamFile);
else
vgmstream->next_block_offset=read_32bitLE(0x04,streamFile);
if(vgmstream->next_block_offset>0x30) {
vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader);
samples_count=(int32_t)vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream);
samples_count/=vgmstream->channels;
}
do {
if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E6C) {
ea_header->dwLoopStart=read_32bitLE(vgmstream->next_block_offset+0x08,vgmstream->ch[0].streamfile);
vgmstream->next_block_offset+=0x0C;
}
if(read_32bitBE(vgmstream->next_block_offset,vgmstream->ch[0].streamfile)==0x31534E65)
break;
eacs_block_update(vgmstream->next_block_offset,vgmstream);
samples_count+=vgmstream->current_block_size/get_vgmstream_frame_size(vgmstream)*get_vgmstream_samples_per_frame(vgmstream);
} while(vgmstream->next_block_offset<get_streamfile_size(streamFile)-8);
// Reset values ...
// setting up the first header by calling the eacs_block_update sub
if(little_endian)
vgmstream->next_block_offset=read_32bitBE(0x04,streamFile);
else
vgmstream->next_block_offset=read_32bitLE(0x04,streamFile);
vgmstream->current_block_size=vgmstream->next_block_offset-sizeof(EACSHeader);
if(vgmstream->coding_type!=coding_PSX)
vgmstream->current_block_size-=8;
if(vgmstream->coding_type==coding_PSX)
eacs_block_update(0x2C,vgmstream);
else
eacs_block_update(0x28,vgmstream);
// re-allocate the sample count
vgmstream->num_samples=samples_count;
if(loop_flag) {
vgmstream->loop_start_sample = ea_header->dwLoopStart;
vgmstream->loop_end_sample = vgmstream->num_samples;
}
if(ea_header)
free(ea_header);
return vgmstream;
/* clean up anything we may have opened */
fail:
if(ea_header)
free(ea_header);
if (vgmstream) close_vgmstream(vgmstream);
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More