VGMStream: Updated libvgmstream code base
Some checks failed
Check if Cog buildable / Build Universal Cog.app (push) Has been cancelled

Updated VGMStream to r2023-27-g7b0c835c

Signed-off-by: Christopher Snowhill <kode54@gmail.com>
This commit is contained in:
Christopher Snowhill 2025-06-14 23:14:53 -07:00
parent 6e28ac6825
commit d74af63da0
9 changed files with 102 additions and 105 deletions

View file

@ -106,4 +106,5 @@ void vgmstream_apply_config(VGMSTREAM* vgmstream, vgmstream_cfg_t* vcfg) {
vgmstream->config_enabled = def->config_set; vgmstream->config_enabled = def->config_set;
setup_vgmstream_play_state(vgmstream); setup_vgmstream_play_state(vgmstream);
setup_vgmstream(vgmstream);
} }

View file

@ -166,10 +166,6 @@ static void setup_state_processing(VGMSTREAM* vgmstream) {
ps->fade_start = ps->pad_begin_duration + ps->body_duration; ps->fade_start = ps->pad_begin_duration + ps->body_duration;
//ps->pad_end_left = ps->pad_end_duration; //ps->pad_end_left = ps->pad_end_duration;
ps->pad_end_start = ps->fade_start + ps->fade_duration; ps->pad_end_start = ps->fade_start + ps->fade_duration;
/* other info (updated once mixing is enabled) */
ps->input_channels = vgmstream->channels;
ps->output_channels = vgmstream->channels;
} }
/* apply play config to internal state */ /* apply play config to internal state */
@ -179,7 +175,4 @@ void setup_vgmstream_play_state(VGMSTREAM* vgmstream) {
setup_state_modifiers(vgmstream); setup_state_modifiers(vgmstream);
setup_state_processing(vgmstream); setup_state_processing(vgmstream);
/* save new config for resets */
setup_vgmstream(vgmstream);
} }

View file

@ -159,8 +159,6 @@ void vgmstream_mixing_enable(VGMSTREAM* vgmstream, int32_t max_sample_count, int
mixing_setup(vgmstream, max_sample_count); mixing_setup(vgmstream, max_sample_count);
mixing_info(vgmstream, input_channels, output_channels); mixing_info(vgmstream, input_channels, output_channels);
/* update internals */
mixing_info(vgmstream, &vgmstream->pstate.input_channels, &vgmstream->pstate.output_channels);
setup_vgmstream(vgmstream); setup_vgmstream(vgmstream);
} }

View file

@ -1552,6 +1552,9 @@ static const hcakey_info hcakey_list[] = {
// Suikoden I & II HD Remaster (PC) // Suikoden I & II HD Remaster (PC)
{14510296783270449627u}, // C95EEE0BA85411DB {14510296783270449627u}, // C95EEE0BA85411DB
// CHUNITHM Chinese Version (AC)
{30194896045700459}, // 006B461914D5756B
}; };
#endif #endif

View file

@ -30,8 +30,10 @@ VGMSTREAM* init_vgmstream_nub(STREAMFILE* sf) {
goto fail; goto fail;
/* .nub: standard /* .nub: standard
* .nub2: rare [iDOLM@STER: Gravure For You (PS3), Noby Noby Boy (iOS)] */ * .nub2: rare [iDOLM@STER: Gravure For You (PS3), Noby Noby Boy (iOS)]
if (!check_extensions(sf, "nub,nub2")) * .nps: Ace Combat Joint Assault (PSP) BGM only
*/
if (!check_extensions(sf, "nub,nub2,nps"))
goto fail; goto fail;
/* sometimes LE [Soul Calibur: Broken Destiny (PSP), Tales of Vesperia (PS4) */ /* sometimes LE [Soul Calibur: Broken Destiny (PSP), Tales of Vesperia (PS4) */

View file

@ -2,6 +2,7 @@
#include "../coding/coding.h" #include "../coding/coding.h"
#include "../util/chunks.h" #include "../util/chunks.h"
static uint32_t get_name_offset(STREAMFILE* sf_sxd1, uint32_t first_offset, int target_subsong);
/* SXDF/SXDS - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */ /* SXDF/SXDS - Sony/SCE's SNDX lib format (cousin of SGXD) [Gravity Rush, Freedom Wars, Soul Sacrifice PSV] */
VGMSTREAM* init_vgmstream_sndx(STREAMFILE* sf) { VGMSTREAM* init_vgmstream_sndx(STREAMFILE* sf) {
@ -147,19 +148,7 @@ VGMSTREAM* init_vgmstream_sndx(STREAMFILE* sf) {
} }
} }
/* get stream name (NAME is tied to REQD/cues, and SFX cues repeat WAVEs, but should work ok for streams) */ name_offset = get_name_offset(sf_sxd1, first_offset, target_subsong);
if (is_dual && find_chunk_le(sf_sxd1, get_id32be("NAME"),first_offset,0, &chunk_offset,NULL)) {
/* table: relative offset (32b) + hash? (32b) + cue index (32b) */
int i;
int num_entries = read_s16le(chunk_offset + 0x04, sf_sxd1); /* can be bigger than streams */
for (i = 0; i < num_entries; i++) {
uint32_t index = read_u32le(chunk_offset + 0x08 + 0x08 + i * 0x0c,sf_sxd1);
if (index+1 == target_subsong) {
name_offset = chunk_offset + 0x08 + 0x00 + i*0x0c + read_u32le(chunk_offset + 0x08 + 0x00 + i * 0x0c, sf_sxd1);
break;
}
}
}
if (is_external && !is_dual) { if (is_external && !is_dual) {
VGM_LOG("SXD: found single sxd with external data\n"); VGM_LOG("SXD: found single sxd with external data\n");
@ -228,14 +217,6 @@ VGMSTREAM* init_vgmstream_sndx(STREAMFILE* sf) {
goto fail; goto fail;
} }
/* .sxd have names but they are a bit complex:
* - WAVE chunk has N subsongs
* - NAME chunk may define M names but usually doesn't match with subsongs (may be less or more)
* - LVRN may define some state and LVAR its possible values (battle_state=bgm_battle_start/win/intro)
* - TRNS also has names based on possible transition
* - final WAVE seem to depend on NAME (event?) + state=value, similar to Wwise
* - presumably TONE/REQD/SEQD chunks have WAVE<>event matching info since they seem to always appear
*/
/* open the file for reading */ /* open the file for reading */
if (!vgmstream_open_stream(vgmstream, sf_data, start_offset)) if (!vgmstream_open_stream(vgmstream, sf_data, start_offset))
@ -251,3 +232,32 @@ fail:
close_vgmstream(vgmstream); close_vgmstream(vgmstream);
return NULL; return NULL;
} }
/* .sxd have names but they are a bit complex:
* - WAVE chunk has N subsongs
* - NAME chunk may define M names but may not match with subsongs (less or more, ex. randoms)
* - LVRN may define some state and LVAR its possible values (battle_state=bgm_battle_start/win/intro)
* - TRNS also has names based on possible transition
* - final WAVE seem to depend on NAME (event?) + state=value, similar to Wwise
* - presumably TONE/REQD/SEQD chunks have WAVE<>event matching info since they seem to always appear
* For now do simple matching.
*/
static uint32_t get_name_offset(STREAMFILE* sf_sxd1, uint32_t first_offset, int target_subsong) {
off_t chunk_offset = 0;
if (!find_chunk_le(sf_sxd1, get_id32be("NAME"),first_offset,0, &chunk_offset,NULL))
return 0;
// table: relative offset (32b) + hash? (32b) + cue index (32b)
int num_entries = read_s16le(chunk_offset + 0x04, sf_sxd1);
// TODO: index N to subsong N works ok for streams but not always for SFX
for (int i = 0; i < num_entries; i++) {
uint32_t index = read_u32le(chunk_offset + 0x08 + 0x08 + i * 0x0c,sf_sxd1);
if (index+1 != target_subsong)
continue;
return chunk_offset + 0x08 + 0x00 + i*0x0c + read_u32le(chunk_offset + 0x08 + 0x00 + i * 0x0c, sf_sxd1);
}
return 0;
}

View file

@ -102,8 +102,7 @@ static void apply_settings(VGMSTREAM* vgmstream, txtp_entry_t* current) {
/* add macro to mixing list */ /* add macro to mixing list */
if (current->channel_mask) { if (current->channel_mask) {
int ch; for (int ch = 0; ch < vgmstream->channels; ch++) {
for (ch = 0; ch < vgmstream->channels; ch++) {
if (!((current->channel_mask >> ch) & 1)) { if (!((current->channel_mask >> ch) & 1)) {
txtp_mix_data_t mix = {0}; txtp_mix_data_t mix = {0};
mix.ch_dst = ch + 1; mix.ch_dst = ch + 1;
@ -113,15 +112,18 @@ static void apply_settings(VGMSTREAM* vgmstream, txtp_entry_t* current) {
} }
} }
/* copy mixing list (should be done last as some mixes depend on config) */ /* apply play config (after sample rate/etc mods) */
if (current->mixing_count > 0) { txtp_copy_config(&vgmstream->config, &current->config);
int m, position_samples; setup_vgmstream_play_state(vgmstream);
// config is enabled in layouts or externally (for compatibility, since we don't know yet if this
// VGMSTREAM will part of a layout, or is enabled externally to not mess up plugins's calcs)
for (m = 0; m < current->mixing_count; m++) { /* apply mixing (last as some mixes depend on config like loops/etc, shouldn't matter much) */
txtp_mix_data_t *mix = &current->mixing[m]; for (int m = 0; m < current->mixing_count; m++) {
txtp_mix_data_t* mix = &current->mixing[m];
switch(mix->command) { switch(mix->command) {
/* base mixes */ // base mixes
case MIX_SWAP: mixing_push_swap(vgmstream, mix->ch_dst, mix->ch_src); break; case MIX_SWAP: mixing_push_swap(vgmstream, mix->ch_dst, mix->ch_src); break;
case MIX_ADD: mixing_push_add(vgmstream, mix->ch_dst, mix->ch_src, 1.0); break; case MIX_ADD: mixing_push_add(vgmstream, mix->ch_dst, mix->ch_src, 1.0); break;
case MIX_ADD_VOLUME: mixing_push_add(vgmstream, mix->ch_dst, mix->ch_src, mix->vol); break; case MIX_ADD_VOLUME: mixing_push_add(vgmstream, mix->ch_dst, mix->ch_src, mix->vol); break;
@ -131,14 +133,14 @@ static void apply_settings(VGMSTREAM* vgmstream, txtp_entry_t* current) {
case MIX_DOWNMIX: mixing_push_downmix(vgmstream, mix->ch_dst); break; case MIX_DOWNMIX: mixing_push_downmix(vgmstream, mix->ch_dst); break;
case MIX_KILLMIX: mixing_push_killmix(vgmstream, mix->ch_dst); break; case MIX_KILLMIX: mixing_push_killmix(vgmstream, mix->ch_dst); break;
case MIX_FADE: case MIX_FADE:
/* Convert from time to samples now that sample rate is final. // Convert from time to samples now that sample rate is final.
* Samples and time values may be mixed though, so it's done for every // Samples and time values may be mixed though, so it's done for every
* value (if one is 0 the other will be too, though) */ // value (if one is 0 the other will be too, though)
if (mix->time_pre > 0.0) mix->sample_pre = mix->time_pre * vgmstream->sample_rate; if (mix->time_pre > 0.0) mix->sample_pre = mix->time_pre * vgmstream->sample_rate;
if (mix->time_start > 0.0) mix->sample_start = mix->time_start * vgmstream->sample_rate; if (mix->time_start > 0.0) mix->sample_start = mix->time_start * vgmstream->sample_rate;
if (mix->time_end > 0.0) mix->sample_end = mix->time_end * vgmstream->sample_rate; if (mix->time_end > 0.0) mix->sample_end = mix->time_end * vgmstream->sample_rate;
if (mix->time_post > 0.0) mix->sample_post = mix->time_post * vgmstream->sample_rate; if (mix->time_post > 0.0) mix->sample_post = mix->time_post * vgmstream->sample_rate;
/* convert special meaning too */ // convert special meaning too
if (mix->time_pre < 0.0) mix->sample_pre = -1; if (mix->time_pre < 0.0) mix->sample_pre = -1;
if (mix->time_post < 0.0) mix->sample_post = -1; if (mix->time_post < 0.0) mix->sample_post = -1;
@ -146,7 +148,7 @@ static void apply_settings(VGMSTREAM* vgmstream, txtp_entry_t* current) {
int loop_pre = vgmstream->loop_start_sample; int loop_pre = vgmstream->loop_start_sample;
int loop_samples = (vgmstream->loop_end_sample - vgmstream->loop_start_sample); int loop_samples = (vgmstream->loop_end_sample - vgmstream->loop_start_sample);
position_samples = loop_pre + loop_samples * mix->position; int position_samples = loop_pre + loop_samples * mix->position;
if (mix->sample_pre >= 0) mix->sample_pre += position_samples; if (mix->sample_pre >= 0) mix->sample_pre += position_samples;
mix->sample_start += position_samples; mix->sample_start += position_samples;
@ -154,12 +156,12 @@ static void apply_settings(VGMSTREAM* vgmstream, txtp_entry_t* current) {
if (mix->sample_post >= 0) mix->sample_post += position_samples; if (mix->sample_post >= 0) mix->sample_post += position_samples;
} }
mixing_push_fade(vgmstream,
mixing_push_fade(vgmstream, mix->ch_dst, mix->vol_start, mix->vol_end, mix->shape, mix->ch_dst, mix->vol_start, mix->vol_end, mix->shape,
mix->sample_pre, mix->sample_start, mix->sample_end, mix->sample_post); mix->sample_pre, mix->sample_start, mix->sample_end, mix->sample_post);
break; break;
/* macro mixes */ // macro mixes
case MACRO_VOLUME: mixing_macro_volume(vgmstream, mix->vol, mix->mask); break; case MACRO_VOLUME: mixing_macro_volume(vgmstream, mix->vol, mix->mask); break;
case MACRO_TRACK: mixing_macro_track(vgmstream, mix->mask); break; case MACRO_TRACK: mixing_macro_track(vgmstream, mix->mask); break;
case MACRO_LAYER: mixing_macro_layer(vgmstream, mix->max, mix->mask, mix->mode); break; case MACRO_LAYER: mixing_macro_layer(vgmstream, mix->max, mix->mask, mix->mode); break;
@ -171,14 +173,9 @@ static void apply_settings(VGMSTREAM* vgmstream, txtp_entry_t* current) {
break; break;
} }
} }
}
/* save final config */
/* default play config (last after sample rate mods/mixing/etc) */ setup_vgmstream(vgmstream);
txtp_copy_config(&vgmstream->config, &current->config);
setup_vgmstream_play_state(vgmstream);
/* config is enabled in layouts or externally (for compatibility, since we don't know yet if this
* VGMSTREAM will part of a layout, or is enabled externally to not mess up plugins's calcs) */
} }

View file

@ -711,14 +711,14 @@ static int parse_xsb_cues(xsb_header *xsb, STREAMFILE *sf) {
* - https://github.com/MonoGame/MonoGame/blob/master/MonoGame.Framework/Audio/Xact/ * - https://github.com/MonoGame/MonoGame/blob/master/MonoGame.Framework/Audio/Xact/
* - https://github.com/espes/MacTerrariaWrapper/tree/master/xactxtract * - https://github.com/espes/MacTerrariaWrapper/tree/master/xactxtract
*/ */
static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) { static bool parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) {
/* check header */ /* check header */
if ((read_u32be(0x00,sf) != 0x5344424B) && /* "SDBK" (LE) */ if (!is_id32be(0x00,sf, "SDBK") && // LE
(read_u32be(0x00,sf) != 0x4B424453)) /* "KBDS" (BE) */ !is_id32be(0x00,sf, "KBDS")) // BE
goto fail; return false;
xsb->big_endian = (read_u32be(0x00,sf) == 0x4B424453); /* "KBDS" */ xsb->big_endian = (is_id32be(0x00,sf, "KBDS"));
read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le; read_s32_t read_s32 = xsb->big_endian ? read_s32be : read_s32le;
read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le; read_s16_t read_s16 = xsb->big_endian ? read_s16be : read_s16le;
@ -843,20 +843,18 @@ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) {
if (xsb->version > XSB_XACT1_2_MAX && xsb->cue_names_size <= 0) { if (xsb->version > XSB_XACT1_2_MAX && xsb->cue_names_size <= 0) {
VGM_LOG("XSB: no names found\n"); VGM_LOG("XSB: no names found\n");
return 1; return true;
} }
/* find target wavebank */ /* find target wavebank */
if (xsb->wavebanks_count) { if (xsb->wavebanks_count) {
char xsb_wavebank_name[64+1]; char xsb_wavebank_name[64+1];
int i;
off_t offset;
xsb->selected_wavebank = -1; xsb->selected_wavebank = -1;
offset = xsb->wavebanks_offset; off_t offset = xsb->wavebanks_offset;
for (i = 0; i < xsb->wavebanks_count; i++) { for (int i = 0; i < xsb->wavebanks_count; i++) {
read_string(xsb_wavebank_name,xsb->wavebanks_name_size, offset, sf); read_string(xsb_wavebank_name,xsb->wavebanks_name_size, offset, sf);
//;VGM_LOG("XSB wavebanks: bank %i\n", i); //, wavebank_name //;VGM_LOG("XSB wavebanks: bank %i\n", i); //, wavebank_name
if (strcasecmp(xsb_wavebank_name, xwb_wavebank_name)==0) { if (strcasecmp(xsb_wavebank_name, xwb_wavebank_name)==0) {
@ -883,9 +881,7 @@ static int parse_xsb(xsb_header *xsb, STREAMFILE *sf, char *xwb_wavebank_name) {
parse_xsb_cues(xsb, sf); parse_xsb_cues(xsb, sf);
} }
return 1; return true;
fail:
return 0;
} }
static STREAMFILE * open_xsb_filename_pair(STREAMFILE *streamXwb) { static STREAMFILE * open_xsb_filename_pair(STREAMFILE *streamXwb) {

View file

@ -81,9 +81,6 @@ typedef struct {
typedef struct { typedef struct {
int input_channels;
int output_channels;
int32_t pad_begin_duration; int32_t pad_begin_duration;
int32_t pad_begin_left; int32_t pad_begin_left;
int32_t trim_begin_duration; int32_t trim_begin_duration;