Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Update vgmstream to r1896 #390

Open
wants to merge 3 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
52 changes: 36 additions & 16 deletions Frameworks/vgmstream/libvgmstream.xcodeproj/project.pbxproj

Large diffs are not rendered by default.

11 changes: 10 additions & 1 deletion Frameworks/vgmstream/vgmstream/src/base/decode.c
Original file line number Diff line number Diff line change
Expand Up @@ -418,7 +418,8 @@ int decode_get_samples_per_frame(VGMSTREAM* vgmstream) {
case coding_XBOX_IMA_int:
case coding_FSB_IMA:
case coding_WWISE_IMA:
case coding_CD_IMA:
case coding_CD_IMA: /* (0x24 - 0x04) * 2 */
case coding_CRANKCASE_IMA: /* (0x23 - 0x3) * 2 */
return 64;
case coding_APPLE_IMA4:
return 64;
Expand Down Expand Up @@ -654,6 +655,8 @@ int decode_get_frame_size(VGMSTREAM* vgmstream) {
case coding_WWISE_IMA:
case coding_CD_IMA:
return 0x24;
case coding_CRANKCASE_IMA:
return 0x23;
case coding_XBOX_IMA_mch:
case coding_FSB_IMA:
return 0x24 * vgmstream->channels;
Expand Down Expand Up @@ -1264,6 +1267,12 @@ void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
}
break;
case coding_CRANKCASE_IMA:
for (ch = 0; ch < vgmstream->channels; ch++) {
decode_crankcase_ima(&vgmstream->ch[ch], buffer+ch,
vgmstream->channels, vgmstream->samples_into_block, samples_to_do);
}
break;

case coding_WS:
for (ch = 0; ch < vgmstream->channels; ch++) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -330,7 +330,7 @@ circus_handle_t* circus_init(off_t start, uint8_t codec, uint8_t flags) {
handle->flags = flags; //(config >> 8) & 0xFF;

scale_index = (handle->flags & 0xF);
if (scale_index > 5) goto fail;
if (scale_index >= 5) goto fail;
handle->scales = scale_table[scale_index];

if (handle->codec == XPCM_CODEC_VQ_DEFLATE) {
Expand Down
1 change: 1 addition & 0 deletions Frameworks/vgmstream/vgmstream/src/coding/coding.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ void decode_ubi_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspaci
void decode_ubi_sce_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel);
void decode_h4m_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do, int channel, uint16_t frame_format);
void decode_cd_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
void decode_crankcase_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do);
size_t ima_bytes_to_samples(size_t bytes, int channels);
size_t ms_ima_bytes_to_samples(size_t bytes, int block_align, int channels);
size_t xbox_ima_bytes_to_samples(size_t bytes, int channels);
Expand Down
70 changes: 56 additions & 14 deletions Frameworks/vgmstream/vgmstream/src/coding/ima_decoder.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,30 +35,35 @@ static const int IMA_IndexTable[16] = {


/* Original IMA expansion, using shift+ADDs to avoid MULs (slow back then) */
static void std_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
int sample_nibble, sample_decoded, step, delta;
static void std_ima_expand_nibble_data(uint8_t byte, int shift, int32_t* hist1, int32_t* index) {
int code, sample, step, delta;

/* simplified through math from:
* - diff = (code + 1/2) * (step / 4)
* > diff = ((step * nibble) + (step / 2)) / 4
* > diff = (step * nibble / 4) + (step / 8)
* final diff = [signed] (step / 8) + (step / 4) + (step / 2) + (step) [when code = 4+2+1] */

sample_nibble = (read_8bit(byte_offset,stream->streamfile) >> nibble_shift)&0xf; /* ADPCM code */
sample_decoded = *hist1; /* predictor value */
step = ADPCMTable[*step_index]; /* current step */
code = (byte >> shift) & 0xf;
sample = *hist1; /* predictor value */
step = ADPCMTable[*index]; /* current step */

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) delta = -delta;
sample_decoded += delta;
if (code & 1) delta += step >> 2;
if (code & 2) delta += step >> 1;
if (code & 4) delta += step;
if (code & 8) delta = -delta;
sample += 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;
*hist1 = clamp16(sample);
*index += IMA_IndexTable[code];
if (*index < 0) *index = 0;
if (*index > 88) *index = 88;
}

static void std_ima_expand_nibble(VGMSTREAMCHANNEL * stream, off_t byte_offset, int nibble_shift, int32_t * hist1, int32_t * step_index) {
uint8_t byte = read_u8(byte_offset,stream->streamfile);
std_ima_expand_nibble_data(byte, nibble_shift, hist1, step_index);
}

/* Apple's IMA variation. Exactly the same except it uses 16b history (probably more sensitive to overflow/sign extend?) */
Expand Down Expand Up @@ -1287,6 +1292,43 @@ void decode_cd_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacin
stream->adpcm_step_index = step_index;
}

/* Crankcase Audio IMA, from libs (internally CrankcaseAudio::ADPCM and revadpcm) */
void decode_crankcase_ima(VGMSTREAMCHANNEL* stream, sample_t* outbuf, int channelspacing, int32_t first_sample, int32_t samples_to_do) {
uint8_t frame[0x23] = {0};
int i, frames_in, sample_pos = 0, block_samples, frame_size;
int32_t hist1 = stream->adpcm_history1_32;
int step_index = stream->adpcm_step_index;
uint32_t frame_offset;

/* external interleave (fixed size), mono */
frame_size = 0x23;
block_samples = (frame_size - 0x3) * 2;
frames_in = first_sample / block_samples;
first_sample = first_sample % block_samples;

frame_offset = stream->offset + frame_size * frames_in;
read_streamfile(frame, frame_offset, frame_size, stream->streamfile); /* ignore EOF errors */

/* normal header (hist+step), mono */
if (first_sample == 0) {
hist1 = get_s16be(frame + 0x00);
step_index = get_u8(frame + 0x02); /* no reserved value at 0x03 unlike other IMAs (misaligned reads?) */
step_index = _clamp_s32(step_index, 0, 88);
}

/* decode nibbles (layout: straight in mono) */
for (i = first_sample; i < first_sample + samples_to_do; i++) {
int pos = 0x03 + (i/2);
int shift = (i & 1 ? 4:0); /* low first */

std_ima_expand_nibble_data(frame[pos], shift, &hist1, &step_index);
outbuf[sample_pos] = (short)(hist1); /* internally output to float using "sample / 32767.0" */
sample_pos += channelspacing;
}

stream->adpcm_history1_32 = hist1;
stream->adpcm_step_index = step_index;
}

/* ************************************************************* */

Expand Down
25 changes: 15 additions & 10 deletions Frameworks/vgmstream/vgmstream/src/coding/mpeg_custom_utils_ahx.c
Original file line number Diff line number Diff line change
Expand Up @@ -188,28 +188,33 @@ int mpeg_custom_parse_frame_ahx(VGMSTREAMCHANNEL* stream, mpeg_codec_data* data,
}


#define AHX_KEY_BUFFER 0x2000
#define AHX_KEY_TEST_FRAMES 20 /* wrong keys may work ok in some frames */
#define AHX_KEY_BUFFER 0x1000 /* not too big since it's read per new key */
#define AHX_KEY_TEST_FRAMES 25 /* wrong keys may work ok in some frames (specially blank) */

/* check if current key ends properly in frame syncs */
int test_ahx_key(STREAMFILE* sf, off_t offset, crikey_t* crikey) {
int bytes;
int bytes = 0;
uint8_t buf[AHX_KEY_BUFFER];
const int buf_size = sizeof(buf);
int pos = 0;
uint32_t base_sync, curr_sync;

bytes = read_streamfile(buf, offset, buf_size, sf);
//if (bytes != buf_size) goto fail; /* possible in small AHX */

base_sync = get_u32be(buf + 0x00);
for (int i = 0; i < AHX_KEY_TEST_FRAMES; i++) {
if (bytes < MPEG_AHX_EXPECTED_FRAME_SIZE) {
offset += pos;
pos = 0;
bytes = read_streamfile(buf, offset, buf_size, sf);
//if (bytes != buf_size) goto fail; /* possible in small AHX */
base_sync = get_u32be(buf + 0x00);
}

int size = ahx_decrypt(buf + pos, bytes, crikey);
if (size <= 0 || size >= bytes - 0x04) goto fail;
int frame_size = ahx_decrypt(buf + pos, bytes, crikey);
if (frame_size <= 0 || frame_size >= bytes - 0x04)
goto fail;

bytes -= size;
pos += size;
bytes -= frame_size;
pos += frame_size;

curr_sync = get_u32be(buf + pos);
if (curr_sync == 0x00800100) /* EOF tag */
Expand Down
9 changes: 8 additions & 1 deletion Frameworks/vgmstream/vgmstream/src/formats.c
Original file line number Diff line number Diff line change
Expand Up @@ -392,6 +392,7 @@ static const char* extension_list[] = {
"nwa",
"nwav",
"nxa",
"nxopus",

//"ogg", //common
"ogg_",
Expand Down Expand Up @@ -474,6 +475,7 @@ static const char* extension_list[] = {
"sbr",
"sbv",
"sig",
"slb", //txth/reserved [Vingt-et-un Systems PS2 games (Last Escort, etc]
"sm0",
"sm1",
"sm2",
Expand Down Expand Up @@ -522,6 +524,7 @@ static const char* extension_list[] = {
"sps",
"spsd",
"spw",
"srsa",
"ss2",
"ssd", //txth/reserved [Zack & Wiki (Wii)]
"ssm",
Expand All @@ -535,6 +538,7 @@ static const char* extension_list[] = {
"stream",
"strm",
"sts",
"stv", //txth/reserved [Socio Art Logic PS2 games (Zero no Tsukaima games, Cambrian QTS, Shirogane no Soleil, etc)]
"sts_cp3",
"stx",
"svag",
Expand Down Expand Up @@ -628,6 +632,7 @@ static const char* extension_list[] = {
"wd",
"wem",
"wii",
"wiive", //txth/semi [Rubik World (Wii)]
"wic", //txth/reserved [Road Rash (SAT)-videos]
"wip", //txth/reserved [Colin McRae DiRT (PC)]
"wlv", //txth/reserved [ToeJam & Earl III: Mission to Earth (DC)]
Expand Down Expand Up @@ -831,6 +836,7 @@ static const coding_info coding_info_list[] = {
{coding_UBI_SCE_IMA, "Ubisoft 4-bit SCE IMA ADPCM"},
{coding_H4M_IMA, "Hudson HVQM4 4-bit IMA ADPCM"},
{coding_CD_IMA, "Crystal Dynamics 4-bit IMA ADPCM"},
{coding_CRANKCASE_IMA, "CrankcaseAudio REV 4-bit IMA ADPCM"},

{coding_MSADPCM, "Microsoft 4-bit ADPCM"},
{coding_MSADPCM_int, "Microsoft 4-bit ADPCM (mono/interleave)"},
Expand Down Expand Up @@ -1325,7 +1331,7 @@ static const meta_info meta_info_list[] = {
{meta_XAU_KONAMI, "Konami XAU header"},
{meta_DERF, "Xilam DERF header"},
{meta_UTK, "Maxis UTK header"},
{meta_NXA, "Entergram NXA header"},
{meta_NXA1, "Entergram NXA1 header"},
{meta_ADPCM_CAPCOM, "Capcom .ADPCM header"},
{meta_UE4OPUS, "Epic Games UE4OPUS header"},
{meta_XWMA, "Microsoft XWMA RIFF header"},
Expand Down Expand Up @@ -1415,6 +1421,7 @@ static const meta_info meta_info_list[] = {
{meta_SQUEAKSTREAM, "Torus SqueakStream header"},
{meta_SQUEAKSAMPLE, "Torus SqueakSample header"},
{meta_SNDS, "Sony SNDS header"},
{meta_NXOF, "Nihon Falcom FDK Opus Header"},
};

void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t out_size) {
Expand Down
52 changes: 33 additions & 19 deletions Frameworks/vgmstream/vgmstream/src/layout/blocked_awc.c
Original file line number Diff line number Diff line change
Expand Up @@ -11,38 +11,52 @@ static size_t get_block_header_size(STREAMFILE* sf, off_t offset, size_t channel
void block_update_awc(off_t block_offset, VGMSTREAM * vgmstream) {
STREAMFILE* sf = vgmstream->ch[0].streamfile;
int32_t (*read_32bit)(off_t,STREAMFILE*) = vgmstream->codec_endian ? read_32bitBE : read_32bitLE;
size_t header_size, entries, block_size, block_samples;
size_t channel_header_size;
size_t header_size, entries, block_size, block_samples, frame_size;
size_t channel_header_size;
int i;

/* assumed only AWC_IMA enters here, MPEG/XMA2 need special parsing as blocked layout is too limited */
entries = read_32bit(block_offset + 0x04, sf); /* se first channel, assume all are the same */
//block_samples = entries * (0x800-4)*2; //todo use
/* assumes only AWC_IMA/DSP enters here, MPEG/XMA2 need special parsing as blocked layout is too limited.
* Block header (see awc.c for a complete description):
* - per channel: header table (size 0x18 or 0x10)
* - per channel: seek table (32b * entries = global samples per frame in each block) (not in DSP/Vorbis)
* - per channel: extra table (DSP only)
* - padding (not in ATRAC9/DSP)
*/

entries = read_32bit(block_offset + 0x04, sf); /* se first channel, assume all are the same (not true in MPEG/XMA) */
block_samples = read_32bit(block_offset + 0x0c, sf);
block_size = vgmstream->full_block_size;

vgmstream->current_block_offset = block_offset;
vgmstream->next_block_offset = block_offset + block_size;
vgmstream->current_block_samples = block_samples;

/* starts with a header block */
/* for each channel
* 0x00: start entry within channel (ie. entries * ch) but may be off by +1/+2
* 0x04: entries
* 0x08: samples to discard in the beginning of this block (MPEG only?)
* 0x0c: samples in channel (for MPEG/XMA2 can vary between channels)
* (next fields don't exist in later versions for IMA)
* 0x10: (MPEG only, empty otherwise) close to number of frames but varies a bit?
* 0x14: (MPEG only, empty otherwise) channel usable data size (not counting padding)
* for each channel
* 32b * entries = global samples per frame in each block (for MPEG probably per full frame)
*/
switch(vgmstream->coding_type) {
case coding_NGC_DSP:
channel_header_size = 0x10;
frame_size = 0x08;

/* coefs on every block but it's always the same */
dsp_read_coefs_le(vgmstream, sf, block_offset + channel_header_size * vgmstream->channels + 0x10 + 0x1c + 0x00, 0x10 + 0x60);
dsp_read_hist_le (vgmstream, sf, block_offset + channel_header_size * vgmstream->channels + 0x10 + 0x1c + 0x20, 0x10 + 0x60);

header_size = 0;
header_size += channel_header_size * vgmstream->channels; /* header table */
/* no seek table */
header_size += 0x70 * vgmstream->channels; /* extra table */
/* no padding */

break;

default:
channel_header_size = get_channel_header_size(sf, block_offset, vgmstream->codec_endian);
header_size = get_block_header_size(sf, block_offset, channel_header_size, vgmstream->channels, vgmstream->codec_endian);
frame_size = 0x800;
break;
}

for (i = 0; i < vgmstream->channels; i++) {
vgmstream->ch[i].offset = block_offset + header_size + 0x800*entries*i;
VGM_ASSERT(entries != read_32bit(block_offset + channel_header_size*i + 0x04, sf), "AWC: variable number of entries found at %lx\n", block_offset);
vgmstream->ch[i].offset = block_offset + header_size + frame_size * entries * i;
}

}
Expand Down
Loading
Loading