cleanup: move code

This commit is contained in:
bnnm 2024-08-12 01:11:52 +02:00
parent 06db5fca76
commit 1169b68b99
10 changed files with 280 additions and 254 deletions

View File

@ -1601,10 +1601,10 @@ int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMS
return samples_to_do; return samples_to_do;
} }
/* Detect loop start and save values, or detect loop end and restore (loop back).
* Returns 1 if loop was done. */ /* Detect loop start and save values, or detect loop end and restore (loop back). Returns true if loop was done. */
int decode_do_loop(VGMSTREAM* vgmstream) { bool decode_do_loop(VGMSTREAM* vgmstream) {
/*if (!vgmstream->loop_flag) return 0;*/ //if (!vgmstream->loop_flag) return false;
/* is this the loop end? = new loop, continue from loop_start_sample */ /* is this the loop end? = new loop, continue from loop_start_sample */
if (vgmstream->current_sample == vgmstream->loop_end_sample) { if (vgmstream->current_sample == vgmstream->loop_end_sample) {
@ -1613,8 +1613,8 @@ int decode_do_loop(VGMSTREAM* vgmstream) {
* (only needed with the "play stream end after looping N times" option enabled) */ * (only needed with the "play stream end after looping N times" option enabled) */
vgmstream->loop_count++; vgmstream->loop_count++;
if (vgmstream->loop_target && vgmstream->loop_target == vgmstream->loop_count) { if (vgmstream->loop_target && vgmstream->loop_target == vgmstream->loop_count) {
vgmstream->loop_flag = 0; /* could be improved but works ok, will be restored on resets */ vgmstream->loop_flag = false; /* could be improved but works ok, will be restored on resets */
return 0; return false;
} }
/* against everything I hold sacred, preserve adpcm history before looping for certain types */ /* against everything I hold sacred, preserve adpcm history before looping for certain types */
@ -1623,8 +1623,7 @@ int decode_do_loop(VGMSTREAM* vgmstream) {
vgmstream->meta_type == meta_DSP_CSTR || vgmstream->meta_type == meta_DSP_CSTR ||
vgmstream->coding_type == coding_PSX || vgmstream->coding_type == coding_PSX ||
vgmstream->coding_type == coding_PSX_badflags) { vgmstream->coding_type == coding_PSX_badflags) {
int ch; for (int ch = 0; ch < vgmstream->channels; ch++) {
for (ch = 0; ch < vgmstream->channels; ch++) {
vgmstream->loop_ch[ch].adpcm_history1_16 = vgmstream->ch[ch].adpcm_history1_16; vgmstream->loop_ch[ch].adpcm_history1_16 = vgmstream->ch[ch].adpcm_history1_16;
vgmstream->loop_ch[ch].adpcm_history2_16 = vgmstream->ch[ch].adpcm_history2_16; vgmstream->loop_ch[ch].adpcm_history2_16 = vgmstream->ch[ch].adpcm_history2_16;
vgmstream->loop_ch[ch].adpcm_history1_32 = vgmstream->ch[ch].adpcm_history1_32; vgmstream->loop_ch[ch].adpcm_history1_32 = vgmstream->ch[ch].adpcm_history1_32;
@ -1633,12 +1632,13 @@ int decode_do_loop(VGMSTREAM* vgmstream) {
} }
//TODO: improve //TODO: improve
/* loop codecs that need special handling, usually: /* codecs with codec_data that decode_seek need special handling, usually:
* - on hit_loop, current offset is copied to loop_ch[].offset * - during decode, codec uses vgmstream->ch[].offset to handle current offset
* - some codecs will overwrite loop_ch[].offset with a custom value * - on hit_loop, current offset is auto-copied to vgmstream->loop_ch[].offset
* - loop_ch[] is copied to ch[] (with custom value) * - decode_seek codecs may overwrite vgmstream->loop_ch[].offset with a custom value (such as start_offset)
* - then codec will use ch[]'s offset * - vgmstream->loop_ch[] is copied below to vgmstream->ch[] (with the newly assigned custom value)
* regular codecs may use copied loop_ch[] offset without issue */ * - then codec will use vgmstream->ch[].offset during decode
* regular codecs will use copied vgmstream->loop_ch[].offset without issue */
decode_seek(vgmstream); decode_seek(vgmstream);
/* restore! */ /* restore! */
@ -1649,7 +1649,7 @@ int decode_do_loop(VGMSTREAM* vgmstream) {
vgmstream->current_block_samples = vgmstream->loop_block_samples; vgmstream->current_block_samples = vgmstream->loop_block_samples;
vgmstream->current_block_offset = vgmstream->loop_block_offset; vgmstream->current_block_offset = vgmstream->loop_block_offset;
vgmstream->next_block_offset = vgmstream->loop_next_block_offset; vgmstream->next_block_offset = vgmstream->loop_next_block_offset;
//vgmstream->pstate = vgmstream->lstate; /* play state is applied over loops */ vgmstream->full_block_size = vgmstream->loop_full_block_size;
/* loop layouts (after restore, in case layout needs state manipulations) */ /* loop layouts (after restore, in case layout needs state manipulations) */
switch(vgmstream->layout_type) { switch(vgmstream->layout_type) {
@ -1663,24 +1663,30 @@ int decode_do_loop(VGMSTREAM* vgmstream) {
break; break;
} }
return 1; /* looped */ /* play state is applied over loops and stream decoding, so it's not restored on loops */
//vgmstream->pstate = vgmstream->lstate;
return true; /* has looped */
} }
/* is this the loop start? save if we haven't saved yet (right when first loop starts) */ /* is this the loop start? save if we haven't saved yet (right when first loop starts) */
if (!vgmstream->hit_loop && vgmstream->current_sample == vgmstream->loop_start_sample) { if (!vgmstream->hit_loop && vgmstream->current_sample == vgmstream->loop_start_sample) {
/* save! */ /* save! */
memcpy(vgmstream->loop_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL)*vgmstream->channels); memcpy(vgmstream->loop_ch, vgmstream->ch, sizeof(VGMSTREAMCHANNEL) * vgmstream->channels);
vgmstream->loop_current_sample = vgmstream->current_sample; vgmstream->loop_current_sample = vgmstream->current_sample;
vgmstream->loop_samples_into_block = vgmstream->samples_into_block; vgmstream->loop_samples_into_block = vgmstream->samples_into_block;
vgmstream->loop_block_size = vgmstream->current_block_size; vgmstream->loop_block_size = vgmstream->current_block_size;
vgmstream->loop_block_samples = vgmstream->current_block_samples; vgmstream->loop_block_samples = vgmstream->current_block_samples;
vgmstream->loop_block_offset = vgmstream->current_block_offset; vgmstream->loop_block_offset = vgmstream->current_block_offset;
vgmstream->loop_next_block_offset = vgmstream->next_block_offset; vgmstream->loop_next_block_offset = vgmstream->next_block_offset;
//vgmstream->lstate = vgmstream->pstate; /* play state is applied over loops */ vgmstream->loop_full_block_size = vgmstream->full_block_size;
/* play state is applied over loops and stream decoding, so it's not saved on loops */
//vgmstream->lstate = vgmstream->pstate;
vgmstream->hit_loop = true; /* info that loop is now ready to use */ vgmstream->hit_loop = true; /* info that loop is now ready to use */
} }
return 0; /* not looped */ return false; /* has not looped */
} }

View File

@ -11,8 +11,8 @@ void decode_reset(VGMSTREAM* vgmstream);
* buffer already, and we have samples_to_do consecutive samples ahead of us. */ * buffer already, and we have samples_to_do consecutive samples ahead of us. */
void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_do, sample_t* buffer); void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_do, sample_t* buffer);
/* Detect loop start and save values, or detect loop end and restore (loop back). Returns 1 if loop was done. */ /* Detect loop start and save values, or detect loop end and restore (loop back). Returns true if loop was done. */
int decode_do_loop(VGMSTREAM* vgmstream); bool decode_do_loop(VGMSTREAM* vgmstream);
/* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */ /* Calculate number of consecutive samples to do (taking into account stopping for loop start and end) */
int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream); int decode_get_samples_to_do(int samples_this_block, int samples_per_frame, VGMSTREAM* vgmstream);

View File

@ -6,6 +6,8 @@
#include "../util/channel_mappings.h" #include "../util/channel_mappings.h"
#include "../util/sf_utils.h" #include "../util/sf_utils.h"
#define TEMPSIZE (256+32)
/*******************************************************************************/ /*******************************************************************************/
/* TEXT */ /* TEXT */
/*******************************************************************************/ /*******************************************************************************/
@ -21,7 +23,6 @@ static void describe_get_time(int32_t samples, int sample_rate, double* p_time_m
/* Write a description of the stream into array pointed by desc, which must be length bytes long. /* Write a description of the stream into array pointed by desc, which must be length bytes long.
* Will always be null-terminated if length > 0 */ * Will always be null-terminated if length > 0 */
void describe_vgmstream(VGMSTREAM* vgmstream, char* desc, int length) { void describe_vgmstream(VGMSTREAM* vgmstream, char* desc, int length) {
#define TEMPSIZE (256+32)
char temp[TEMPSIZE]; char temp[TEMPSIZE];
double time_mm, time_ss; double time_mm, time_ss;

View File

@ -13,50 +13,50 @@ static void copy_time(bool* dst_flag, int32_t* dst_time, double* dst_time_s, boo
*dst_time_s = *src_time_s; *dst_time_s = *src_time_s;
} }
//todo reuse in txtp? // config that has been set internally via TXTP
static void load_default_config(play_config_t* def, play_config_t* tcfg) { static void load_default_config(play_config_t* def, play_config_t* tcfg) {
/* loop limit: txtp #L > txtp #l > player #L > player #l */ /* loop limit: txtp #L > txtp #l > player #L > player #l */
if (tcfg->play_forever) { if (tcfg->play_forever) {
def->play_forever = 1; def->play_forever = true;
def->ignore_loop = 0; def->ignore_loop = false;
} }
if (tcfg->loop_count_set) { if (tcfg->loop_count_set) {
def->loop_count = tcfg->loop_count; def->loop_count = tcfg->loop_count;
def->loop_count_set = 1; def->loop_count_set = true;
def->ignore_loop = 0; def->ignore_loop = false;
if (!tcfg->play_forever) if (!tcfg->play_forever)
def->play_forever = 0; def->play_forever = false;
} }
/* fade priority: #F > #f, #d */ /* fade priority: #F > #f, #d */
if (tcfg->ignore_fade) { if (tcfg->ignore_fade) {
def->ignore_fade = 1; def->ignore_fade = true;
} }
if (tcfg->fade_delay_set) { if (tcfg->fade_delay_set) {
def->fade_delay = tcfg->fade_delay; def->fade_delay = tcfg->fade_delay;
def->fade_delay_set = 1; def->fade_delay_set = true;
} }
if (tcfg->fade_time_set) { if (tcfg->fade_time_set) {
def->fade_time = tcfg->fade_time; def->fade_time = tcfg->fade_time;
def->fade_time_set = 1; def->fade_time_set = true;
} }
/* loop priority: #i > #e > #E (respect player's ignore too) */ /* loop priority: #i > #e > #E (respect player's ignore too) */
if (tcfg->really_force_loop) { if (tcfg->really_force_loop) {
//def->ignore_loop = 0; //def->ignore_loop = false;
def->force_loop = 0; def->force_loop = false;
def->really_force_loop = 1; def->really_force_loop = true;
} }
if (tcfg->force_loop) { if (tcfg->force_loop) {
//def->ignore_loop = 0; //def->ignore_loop = false;
def->force_loop = 1; def->force_loop = true;
def->really_force_loop = 0; def->really_force_loop = false;
} }
if (tcfg->ignore_loop) { if (tcfg->ignore_loop) {
def->ignore_loop = 1; def->ignore_loop = true;
def->force_loop = 0; def->force_loop = false;
def->really_force_loop = 0; def->really_force_loop = false;
} }
copy_time(&def->pad_begin_set, &def->pad_begin, &def->pad_begin_s, &tcfg->pad_begin_set, &tcfg->pad_begin, &tcfg->pad_begin_s); copy_time(&def->pad_begin_set, &def->pad_begin, &def->pad_begin_s, &tcfg->pad_begin_set, &tcfg->pad_begin, &tcfg->pad_begin_s);
@ -69,7 +69,8 @@ static void load_default_config(play_config_t* def, play_config_t* tcfg) {
def->is_txtp = tcfg->is_txtp; def->is_txtp = tcfg->is_txtp;
} }
static void load_player_config(play_config_t* def, vgmstream_cfg_t* vcfg) { /* config that has been set externally by plugins */
static void load_external_config(play_config_t* def, vgmstream_cfg_t* vcfg) {
def->play_forever = vcfg->play_forever; def->play_forever = vcfg->play_forever;
def->ignore_loop = vcfg->ignore_loop; def->ignore_loop = vcfg->ignore_loop;
def->force_loop = vcfg->force_loop; def->force_loop = vcfg->force_loop;
@ -77,31 +78,32 @@ static void load_player_config(play_config_t* def, vgmstream_cfg_t* vcfg) {
def->ignore_fade = vcfg->ignore_fade; def->ignore_fade = vcfg->ignore_fade;
def->loop_count = vcfg->loop_count; def->loop_count = vcfg->loop_count;
def->loop_count_set = 1; def->loop_count_set = true;
def->fade_delay = vcfg->fade_delay; def->fade_delay = vcfg->fade_delay;
def->fade_delay_set = 1; def->fade_delay_set = true;
def->fade_time = vcfg->fade_time; def->fade_time = vcfg->fade_time;
def->fade_time_set = 1; def->fade_time_set = true;
} }
/* apply play config to vgmstream */
void vgmstream_apply_config(VGMSTREAM* vgmstream, vgmstream_cfg_t* vcfg) { void vgmstream_apply_config(VGMSTREAM* vgmstream, vgmstream_cfg_t* vcfg) {
play_config_t defs = {0}; play_config_t defs = {0};
play_config_t* def = &defs; /* for convenience... */ play_config_t* def = &defs; /* for convenience... */
play_config_t* tcfg = &vgmstream->config; play_config_t* tcfg = &vgmstream->config;
load_player_config(def, vcfg); load_external_config(def, vcfg);
def->config_set = 1; def->config_set = true;
if (!vcfg->disable_config_override) if (!vcfg->disable_config_override)
load_default_config(def, tcfg); load_default_config(def, tcfg);
if (!vcfg->allow_play_forever) if (!vcfg->allow_play_forever)
def->play_forever = 0; def->play_forever = false;
/* copy final config back */ /* copy final config back */
*tcfg = *def; *tcfg = *def;
vgmstream->config_enabled = def->config_set; vgmstream->config_enabled = def->config_set;
setup_state_vgmstream(vgmstream); setup_vgmstream_play_state(vgmstream);
} }

185
src/base/play_state.c Normal file
View File

@ -0,0 +1,185 @@
#include "../vgmstream.h"
//#include "../layout/layout.h"
//#include "render.h"
//#include "decode.h"
//#include "mixing.h"
//#include "plugins.h"
int vgmstream_get_play_forever(VGMSTREAM* vgmstream) {
return vgmstream->config.play_forever;
}
void vgmstream_set_play_forever(VGMSTREAM* vgmstream, int enabled) {
/* sometimes we need to enable/disable right before playback
* (play config is left untouched, should mix ok as this flag is only used during
* render, while config is always prepared as if play forever wasn't enabled) */
vgmstream->config.play_forever = enabled;
setup_vgmstream(vgmstream); /* update config */
}
int32_t vgmstream_get_samples(VGMSTREAM* vgmstream) {
if (!vgmstream->config_enabled || !vgmstream->config.config_set)
return vgmstream->num_samples;
return vgmstream->pstate.play_duration;
}
/* calculate samples based on player's config */
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM* vgmstream) {
if (vgmstream->loop_flag) {
if (vgmstream->loop_target == (int)looptimes) { /* set externally, as this function is info-only */
/* Continue playing the file normally after looping, instead of fading.
* Most files cut abruply after the loop, but some do have proper endings.
* With looptimes = 1 this option should give the same output vs loop disabled */
int loop_count = (int)looptimes; /* no half loops allowed */
return vgmstream->loop_start_sample
+ (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * loop_count
+ (vgmstream->num_samples - vgmstream->loop_end_sample);
}
else {
return vgmstream->loop_start_sample
+ (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * looptimes
+ (fadedelayseconds + fadeseconds) * vgmstream->sample_rate;
}
}
else {
return vgmstream->num_samples;
}
}
/*****************************************************************************/
/* apply config like forced loops */
static void setup_state_modifiers(VGMSTREAM* vgmstream) {
play_config_t* pc = &vgmstream->config;
/* apply final config */
if (pc->really_force_loop) {
vgmstream_force_loop(vgmstream, true, 0, vgmstream->num_samples);
}
if (pc->force_loop && !vgmstream->loop_flag) {
vgmstream_force_loop(vgmstream, true, 0, vgmstream->num_samples);
}
if (pc->ignore_loop) {
vgmstream_force_loop(vgmstream, false, 0, 0);
}
if (!vgmstream->loop_flag) {
pc->play_forever = false;
}
if (pc->play_forever) {
pc->ignore_fade = false;
}
/* loop N times, but also play stream end instead of fading out */
if (pc->ignore_fade) {
vgmstream_set_loop_target(vgmstream, (int)pc->loop_count);
pc->fade_time = 0;
pc->fade_delay = 0;
}
}
/* apply config like trims */
static void setup_state_processing(VGMSTREAM* vgmstream) {
play_state_t* ps = &vgmstream->pstate;
play_config_t* pc = &vgmstream->config;
double sample_rate = vgmstream->sample_rate;
/* time to samples */
if (pc->pad_begin_s)
pc->pad_begin = pc->pad_begin_s * sample_rate;
if (pc->pad_end_s)
pc->pad_end = pc->pad_end_s * sample_rate;
if (pc->trim_begin_s)
pc->trim_begin = pc->trim_begin_s * sample_rate;
if (pc->trim_end_s)
pc->trim_end = pc->trim_end_s * sample_rate;
if (pc->body_time_s)
pc->body_time = pc->body_time_s * sample_rate;
//todo fade time also set to samples
/* samples before all decode */
ps->pad_begin_duration = pc->pad_begin;
/* removed samples from first decode */
ps->trim_begin_duration = pc->trim_begin;
/* main samples part */
ps->body_duration = 0;
if (pc->body_time) {
ps->body_duration += pc->body_time; /* whether it loops or not */
}
else if (vgmstream->loop_flag) {
double loop_count = 1.0;
if (pc->loop_count_set) /* may set 0.0 on purpose I guess */
loop_count = pc->loop_count;
ps->body_duration += vgmstream->loop_start_sample;
if (pc->ignore_fade) {
ps->body_duration += (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * (int)loop_count;
ps->body_duration += (vgmstream->num_samples - vgmstream->loop_end_sample);
}
else {
ps->body_duration += (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * loop_count;
}
}
else {
ps->body_duration += vgmstream->num_samples;
}
/* samples from some modify body */
if (pc->trim_begin)
ps->body_duration -= pc->trim_begin;
if (pc->trim_end)
ps->body_duration -= pc->trim_end;
if (pc->fade_delay && vgmstream->loop_flag)
ps->body_duration += pc->fade_delay * vgmstream->sample_rate;
/* samples from fade part */
if (pc->fade_time && vgmstream->loop_flag)
ps->fade_duration = pc->fade_time * vgmstream->sample_rate;
/* samples from last part (anything beyond this is empty, unless play forever is set) */
ps->pad_end_duration = pc->pad_end;
/* final count */
ps->play_duration = ps->pad_begin_duration + ps->body_duration + ps->fade_duration + ps->pad_end_duration;
ps->play_position = 0;
/* values too big can overflow, just ignore */
if (ps->pad_begin_duration < 0)
ps->pad_begin_duration = 0;
if (ps->body_duration < 0)
ps->body_duration = 0;
if (ps->fade_duration < 0)
ps->fade_duration = 0;
if (ps->pad_end_duration < 0)
ps->pad_end_duration = 0;
if (ps->play_duration < 0)
ps->play_duration = 0;
ps->pad_begin_left = ps->pad_begin_duration;
ps->trim_begin_left = ps->trim_begin_duration;
ps->fade_left = ps->fade_duration;
ps->fade_start = ps->pad_begin_duration + ps->body_duration;
//ps->pad_end_left = ps->pad_end_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 */
void setup_vgmstream_play_state(VGMSTREAM* vgmstream) {
if (!vgmstream->config.config_set)
return;
setup_state_modifiers(vgmstream);
setup_state_processing(vgmstream);
/* save new config for resets */
setup_vgmstream(vgmstream);
}

View File

@ -47,179 +47,6 @@
* This mainly applies to TXTP, segments/layers in metas usually don't need to trigger config mode. * This mainly applies to TXTP, segments/layers in metas usually don't need to trigger config mode.
*/ */
int vgmstream_get_play_forever(VGMSTREAM* vgmstream) {
return vgmstream->config.play_forever;
}
void vgmstream_set_play_forever(VGMSTREAM* vgmstream, int enabled) {
/* sometimes we need to enable/disable right before playback
* (play config is left untouched, should mix ok as this flag is only used during
* render, while config is always prepared as if play forever wasn't enabled) */
vgmstream->config.play_forever = enabled;
setup_vgmstream(vgmstream); /* update config */
}
int32_t vgmstream_get_samples(VGMSTREAM* vgmstream) {
if (!vgmstream->config_enabled || !vgmstream->config.config_set)
return vgmstream->num_samples;
return vgmstream->pstate.play_duration;
}
/* calculate samples based on player's config */
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM* vgmstream) {
if (vgmstream->loop_flag) {
if (vgmstream->loop_target == (int)looptimes) { /* set externally, as this function is info-only */
/* Continue playing the file normally after looping, instead of fading.
* Most files cut abruply after the loop, but some do have proper endings.
* With looptimes = 1 this option should give the same output vs loop disabled */
int loop_count = (int)looptimes; /* no half loops allowed */
return vgmstream->loop_start_sample
+ (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * loop_count
+ (vgmstream->num_samples - vgmstream->loop_end_sample);
}
else {
return vgmstream->loop_start_sample
+ (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * looptimes
+ (fadedelayseconds + fadeseconds) * vgmstream->sample_rate;
}
}
else {
return vgmstream->num_samples;
}
}
/*****************************************************************************/
static void setup_state_modifiers(VGMSTREAM* vgmstream) {
play_config_t* pc = &vgmstream->config;
/* apply final config */
if (pc->really_force_loop) {
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
}
if (pc->force_loop && !vgmstream->loop_flag) {
vgmstream_force_loop(vgmstream, 1, 0,vgmstream->num_samples);
}
if (pc->ignore_loop) {
vgmstream_force_loop(vgmstream, 0, 0,0);
}
if (!vgmstream->loop_flag) {
pc->play_forever = 0;
}
if (pc->play_forever) {
pc->ignore_fade = 0;
}
/* loop N times, but also play stream end instead of fading out */
if (pc->ignore_fade) {
vgmstream_set_loop_target(vgmstream, (int)pc->loop_count);
pc->fade_time = 0;
pc->fade_delay = 0;
}
}
static void setup_state_processing(VGMSTREAM* vgmstream) {
play_state_t* ps = &vgmstream->pstate;
play_config_t* pc = &vgmstream->config;
double sample_rate = vgmstream->sample_rate;
/* time to samples */
if (pc->pad_begin_s)
pc->pad_begin = pc->pad_begin_s * sample_rate;
if (pc->pad_end_s)
pc->pad_end = pc->pad_end_s * sample_rate;
if (pc->trim_begin_s)
pc->trim_begin = pc->trim_begin_s * sample_rate;
if (pc->trim_end_s)
pc->trim_end = pc->trim_end_s * sample_rate;
if (pc->body_time_s)
pc->body_time = pc->body_time_s * sample_rate;
//todo fade time also set to samples
/* samples before all decode */
ps->pad_begin_duration = pc->pad_begin;
/* removed samples from first decode */
ps->trim_begin_duration = pc->trim_begin;
/* main samples part */
ps->body_duration = 0;
if (pc->body_time) {
ps->body_duration += pc->body_time; /* whether it loops or not */
}
else if (vgmstream->loop_flag) {
double loop_count = 1.0;
if (pc->loop_count_set) /* may set 0.0 on purpose I guess */
loop_count = pc->loop_count;
ps->body_duration += vgmstream->loop_start_sample;
if (pc->ignore_fade) {
ps->body_duration += (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * (int)loop_count;
ps->body_duration += (vgmstream->num_samples - vgmstream->loop_end_sample);
}
else {
ps->body_duration += (vgmstream->loop_end_sample - vgmstream->loop_start_sample) * loop_count;
}
}
else {
ps->body_duration += vgmstream->num_samples;
}
/* samples from some modify body */
if (pc->trim_begin)
ps->body_duration -= pc->trim_begin;
if (pc->trim_end)
ps->body_duration -= pc->trim_end;
if (pc->fade_delay && vgmstream->loop_flag)
ps->body_duration += pc->fade_delay * vgmstream->sample_rate;
/* samples from fade part */
if (pc->fade_time && vgmstream->loop_flag)
ps->fade_duration = pc->fade_time * vgmstream->sample_rate;
/* samples from last part (anything beyond this is empty, unless play forever is set) */
ps->pad_end_duration = pc->pad_end;
/* final count */
ps->play_duration = ps->pad_begin_duration + ps->body_duration + ps->fade_duration + ps->pad_end_duration;
ps->play_position = 0;
/* values too big can overflow, just ignore */
if (ps->pad_begin_duration < 0)
ps->pad_begin_duration = 0;
if (ps->body_duration < 0)
ps->body_duration = 0;
if (ps->fade_duration < 0)
ps->fade_duration = 0;
if (ps->pad_end_duration < 0)
ps->pad_end_duration = 0;
if (ps->play_duration < 0)
ps->play_duration = 0;
ps->pad_begin_left = ps->pad_begin_duration;
ps->trim_begin_left = ps->trim_begin_duration;
ps->fade_left = ps->fade_duration;
ps->fade_start = ps->pad_begin_duration + ps->body_duration;
//ps->pad_end_left = ps->pad_end_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;
}
void setup_state_vgmstream(VGMSTREAM* vgmstream) {
if (!vgmstream->config.config_set)
return;
setup_state_modifiers(vgmstream);
setup_state_processing(vgmstream);
setup_vgmstream(vgmstream); /* save current config for reset */
}
/*****************************************************************************/ /*****************************************************************************/
void render_free(VGMSTREAM* vgmstream) { void render_free(VGMSTREAM* vgmstream) {
@ -333,8 +160,9 @@ int render_layout(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream) {
return sample_count; return sample_count;
} }
/*****************************************************************************/
static void render_trim(VGMSTREAM* vgmstream) { static void render_op_trim(VGMSTREAM* vgmstream) {
sample_t* tmpbuf = vgmstream->tmpbuf; sample_t* tmpbuf = vgmstream->tmpbuf;
size_t tmpbuf_size = vgmstream->tmpbuf_size; size_t tmpbuf_size = vgmstream->tmpbuf_size;
int32_t buf_samples = tmpbuf_size / vgmstream->channels; /* base channels, no need to apply mixing */ int32_t buf_samples = tmpbuf_size / vgmstream->channels; /* base channels, no need to apply mixing */
@ -350,7 +178,7 @@ static void render_trim(VGMSTREAM* vgmstream) {
} }
} }
static int render_pad_begin(VGMSTREAM* vgmstream, sample_t* buf, int samples_to_do) { static int render_op_pad_begin(VGMSTREAM* vgmstream, sample_t* buf, int samples_to_do) {
int channels = vgmstream->pstate.output_channels; int channels = vgmstream->pstate.output_channels;
int to_do = vgmstream->pstate.pad_begin_left; int to_do = vgmstream->pstate.pad_begin_left;
if (to_do > samples_to_do) if (to_do > samples_to_do)
@ -362,7 +190,7 @@ static int render_pad_begin(VGMSTREAM* vgmstream, sample_t* buf, int samples_to_
return to_do; return to_do;
} }
static int render_fade(VGMSTREAM* vgmstream, sample_t* buf, int samples_left) { static int render_op_fade(VGMSTREAM* vgmstream, sample_t* buf, int samples_left) {
play_state_t* ps = &vgmstream->pstate; play_state_t* ps = &vgmstream->pstate;
//play_config_t* pc = &vgmstream->config; //play_config_t* pc = &vgmstream->config;
@ -404,7 +232,7 @@ static int render_fade(VGMSTREAM* vgmstream, sample_t* buf, int samples_left) {
} }
} }
static int render_pad_end(VGMSTREAM* vgmstream, sample_t* buf, int samples_left) { static int render_op_pad_end(VGMSTREAM* vgmstream, sample_t* buf, int samples_left) {
play_state_t* ps = &vgmstream->pstate; play_state_t* ps = &vgmstream->pstate;
int channels = vgmstream->pstate.output_channels; int channels = vgmstream->pstate.output_channels;
int skip = 0; int skip = 0;
@ -428,6 +256,7 @@ static int render_pad_end(VGMSTREAM* vgmstream, sample_t* buf, int samples_left)
return skip + to_do; return skip + to_do;
} }
/*****************************************************************************/
/* Decode data into sample buffer. Controls the "external" part of the decoding, /* Decode data into sample buffer. Controls the "external" part of the decoding,
* while layout/decode control the "internal" part. */ * while layout/decode control the "internal" part. */
@ -449,12 +278,12 @@ int render_vgmstream(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream)
/* trim may go first since it doesn't need output nor changes totals */ /* trim may go first since it doesn't need output nor changes totals */
if (ps->trim_begin_left) { if (ps->trim_begin_left) {
render_trim(vgmstream); render_op_trim(vgmstream);
} }
/* adds empty samples to buf */ /* adds empty samples to buf */
if (ps->pad_begin_left) { if (ps->pad_begin_left) {
done = render_pad_begin(vgmstream, tmpbuf, samples_to_do); done = render_op_pad_begin(vgmstream, tmpbuf, samples_to_do);
samples_done += done; samples_done += done;
samples_to_do -= done; samples_to_do -= done;
tmpbuf += done * vgmstream->pstate.output_channels; /* as if mixed */ tmpbuf += done * vgmstream->pstate.output_channels; /* as if mixed */
@ -464,7 +293,7 @@ int render_vgmstream(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream)
if (!vgmstream->config.play_forever if (!vgmstream->config.play_forever
&& ps->play_position /*+ samples_to_do*/ >= ps->pad_end_start && ps->play_position /*+ samples_to_do*/ >= ps->pad_end_start
&& samples_to_do) { && samples_to_do) {
done = render_pad_end(vgmstream, tmpbuf, samples_to_do); done = render_op_pad_end(vgmstream, tmpbuf, samples_to_do);
samples_done += done; samples_done += done;
samples_to_do -= done; samples_to_do -= done;
tmpbuf += done * vgmstream->pstate.output_channels; /* as if mixed */ tmpbuf += done * vgmstream->pstate.output_channels; /* as if mixed */
@ -481,12 +310,12 @@ int render_vgmstream(sample_t* buf, int32_t sample_count, VGMSTREAM* vgmstream)
if (!vgmstream->config.play_forever) { if (!vgmstream->config.play_forever) {
/* simple fadeout */ /* simple fadeout */
if (ps->fade_left && ps->play_position + done >= ps->fade_start) { if (ps->fade_left && ps->play_position + done >= ps->fade_start) {
render_fade(vgmstream, tmpbuf, done); render_op_fade(vgmstream, tmpbuf, done);
} }
/* silence leftover buf samples (rarely used when no fade is set) */ /* silence leftover buf samples (rarely used when no fade is set) */
if (ps->play_position + done >= ps->pad_end_start) { if (ps->play_position + done >= ps->pad_end_start) {
render_pad_end(vgmstream, tmpbuf, done); render_op_pad_end(vgmstream, tmpbuf, done);
} }
} }

View File

@ -219,7 +219,6 @@
<ClCompile Include="base\api_helpers.c" /> <ClCompile Include="base\api_helpers.c" />
<ClCompile Include="base\api_libsf.c" /> <ClCompile Include="base\api_libsf.c" />
<ClCompile Include="base\api_tags.c" /> <ClCompile Include="base\api_tags.c" />
<ClCompile Include="base\config.c" />
<ClCompile Include="base\decode.c" /> <ClCompile Include="base\decode.c" />
<ClCompile Include="base\info.c" /> <ClCompile Include="base\info.c" />
<ClCompile Include="base\mixer.c" /> <ClCompile Include="base\mixer.c" />
@ -228,6 +227,8 @@
<ClCompile Include="base\mixing.c" /> <ClCompile Include="base\mixing.c" />
<ClCompile Include="base\mixing_commands.c" /> <ClCompile Include="base\mixing_commands.c" />
<ClCompile Include="base\mixing_macros.c" /> <ClCompile Include="base\mixing_macros.c" />
<ClCompile Include="base\play_config.c" />
<ClCompile Include="base\play_state.c" />
<ClCompile Include="base\plugins.c" /> <ClCompile Include="base\plugins.c" />
<ClCompile Include="base\render.c" /> <ClCompile Include="base\render.c" />
<ClCompile Include="base\seek.c" /> <ClCompile Include="base\seek.c" />
@ -630,7 +631,6 @@
<ClCompile Include="meta\ps2_vgv.c" /> <ClCompile Include="meta\ps2_vgv.c" />
<ClCompile Include="meta\ps2_vms.c" /> <ClCompile Include="meta\ps2_vms.c" />
<ClCompile Include="meta\ps2_wmus.c" /> <ClCompile Include="meta\ps2_wmus.c" />
<ClCompile Include="meta\ps2_xa30.c" />
<ClCompile Include="meta\psb.c" /> <ClCompile Include="meta\psb.c" />
<ClCompile Include="meta\psf.c" /> <ClCompile Include="meta\psf.c" />
<ClCompile Include="meta\psnd.c" /> <ClCompile Include="meta\psnd.c" />

View File

@ -487,9 +487,6 @@
<ClCompile Include="base\api_tags.c"> <ClCompile Include="base\api_tags.c">
<Filter>base\Source Files</Filter> <Filter>base\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="base\config.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\decode.c"> <ClCompile Include="base\decode.c">
<Filter>base\Source Files</Filter> <Filter>base\Source Files</Filter>
</ClCompile> </ClCompile>
@ -514,6 +511,12 @@
<ClCompile Include="base\mixing_macros.c"> <ClCompile Include="base\mixing_macros.c">
<Filter>base\Source Files</Filter> <Filter>base\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="base\play_config.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\play_state.c">
<Filter>base\Source Files</Filter>
</ClCompile>
<ClCompile Include="base\plugins.c"> <ClCompile Include="base\plugins.c">
<Filter>base\Source Files</Filter> <Filter>base\Source Files</Filter>
</ClCompile> </ClCompile>
@ -1720,9 +1723,6 @@
<ClCompile Include="meta\ps2_wmus.c"> <ClCompile Include="meta\ps2_wmus.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>
<ClCompile Include="meta\ps2_xa30.c">
<Filter>meta\Source Files</Filter>
</ClCompile>
<ClCompile Include="meta\psb.c"> <ClCompile Include="meta\psb.c">
<Filter>meta\Source Files</Filter> <Filter>meta\Source Files</Filter>
</ClCompile> </ClCompile>

View File

@ -131,7 +131,7 @@ static void apply_settings(VGMSTREAM* vgmstream, txtp_entry_t* current) {
/* default play config (last after sample rate mods/mixing/etc) */ /* default play config (last after sample rate mods/mixing/etc) */
txtp_copy_config(&vgmstream->config, &current->config); txtp_copy_config(&vgmstream->config, &current->config);
setup_state_vgmstream(vgmstream); setup_vgmstream_play_state(vgmstream);
/* config is enabled in layouts or externally (for compatibility, since we don't know yet if this /* 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) */ * VGMSTREAM will part of a layout, or is enabled externally to not mess up plugins's calcs) */
} }

View File

@ -186,8 +186,15 @@ typedef struct {
bool allow_dual_stereo; /* search for dual stereo (file_L.ext + file_R.ext = single stereo file) */ bool allow_dual_stereo; /* search for dual stereo (file_L.ext + file_R.ext = single stereo file) */
int format_id; /* internal format ID */ int format_id; /* internal format ID */
/* decoder config/state */
int codec_endian; /* little/big endian marker; name is left vague but usually means big endian */
int codec_config; /* flags for codecs or layouts with minor variations; meaning is up to them (may change during decode) */
bool codec_internal_updates; /* temp(?) kludge (see vgmstream_open_stream/decode) */
int32_t ws_output_size; /* WS ADPCM: output bytes for this block */
/* layout/block state */ /* layout/block state */
int32_t current_sample; /* sample point within the file (for loop detection) */ int32_t current_sample; /* sample point within the stream (for loop detection) */
int32_t samples_into_block; /* number of samples into the current block/interleave/segment/etc */ int32_t samples_into_block; /* number of samples into the current block/interleave/segment/etc */
off_t current_block_offset; /* start of this block (offset of block header) */ off_t current_block_offset; /* start of this block (offset of block header) */
size_t current_block_size; /* size in usable bytes of the block we're in now (used to calculate num_samples per block) */ size_t current_block_size; /* size in usable bytes of the block we're in now (used to calculate num_samples per block) */
@ -195,28 +202,24 @@ typedef struct {
off_t next_block_offset; /* offset of header of the next block */ off_t next_block_offset; /* offset of header of the next block */
size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */ size_t full_block_size; /* actual data size of an entire block (ie. may be fixed, include padding/headers, etc) */
/* loop state (saved when loop is hit to restore later) */ /* layout/block state copy for loops (saved on loop_start and restored later on loop_end) */
int32_t loop_current_sample; /* saved from current_sample (same as loop_start_sample, but more state-like) */ int32_t loop_current_sample; /* saved from current_sample (same as loop_start_sample, but more state-like) */
int32_t loop_samples_into_block;/* saved from samples_into_block */ int32_t loop_samples_into_block;/* saved from samples_into_block */
off_t loop_block_offset; /* saved from current_block_offset */ off_t loop_block_offset; /* saved from current_block_offset */
size_t loop_block_size; /* saved from current_block_size */ size_t loop_block_size; /* saved from current_block_size */
int32_t loop_block_samples; /* saved from current_block_samples */ int32_t loop_block_samples; /* saved from current_block_samples */
off_t loop_next_block_offset; /* saved from next_block_offset */ off_t loop_next_block_offset; /* saved from next_block_offset */
size_t loop_full_block_size; /* saved from full_block_size (probably unnecessary) */
bool hit_loop; /* save config when loop is hit, but first time only */ bool hit_loop; /* save config when loop is hit, but first time only */
/* decoder config/state */
int codec_endian; /* little/big endian marker; name is left vague but usually means big endian */
int codec_config; /* flags for codecs or layouts with minor variations; meaning is up to them */
bool codec_internal_updates; /* temp(?) kludge (see vgmstream_open_stream/decode) */
int32_t ws_output_size; /* WS ADPCM: output bytes for this block */
/* main state */ /* main state */
VGMSTREAMCHANNEL* ch; /* array of channels */ VGMSTREAMCHANNEL* ch; /* array of channels with current offset + per-channel codec config */
VGMSTREAMCHANNEL* start_ch; /* shallow copy of channels as they were at the beginning of the stream (for resets) */
VGMSTREAMCHANNEL* loop_ch; /* shallow copy of channels as they were at the loop point (for loops) */ VGMSTREAMCHANNEL* loop_ch; /* shallow copy of channels as they were at the loop point (for loops) */
void* start_vgmstream; /* shallow copy of the VGMSTREAM as it was at the beginning of the stream (for resets) */ void* start_vgmstream; /* shallow copy of the VGMSTREAM as it was at the beginning of the stream (for resets) */
VGMSTREAMCHANNEL* start_ch; /* shallow copy of channels as they were at the beginning of the stream (for resets) */
void* mixer; /* state for mixing effects */ void* mixer; /* state for mixing effects */
@ -242,7 +245,6 @@ typedef struct {
} VGMSTREAM; } VGMSTREAM;
// VGMStream description in structure format
typedef struct { typedef struct {
int sample_rate; int sample_rate;
int channels; int channels;
@ -326,11 +328,10 @@ void get_vgmstream_coding_description(VGMSTREAM* vgmstream, char* out, size_t ou
void get_vgmstream_layout_description(VGMSTREAM* vgmstream, char* out, size_t out_size); void get_vgmstream_layout_description(VGMSTREAM* vgmstream, char* out, size_t out_size);
void get_vgmstream_meta_description(VGMSTREAM* vgmstream, char* out, size_t out_size); void get_vgmstream_meta_description(VGMSTREAM* vgmstream, char* out, size_t out_size);
//TODO: remove, unused internally
/* calculate the number of samples to be played based on looping parameters */ /* calculate the number of samples to be played based on looping parameters */
int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM* vgmstream); int32_t get_vgmstream_play_samples(double looptimes, double fadeseconds, double fadedelayseconds, VGMSTREAM* vgmstream);
void setup_state_vgmstream(VGMSTREAM* vgmstream);
/* Force enable/disable internal looping. Should be done before playing anything (or after reset), /* Force enable/disable internal looping. Should be done before playing anything (or after reset),
* and not all codecs support arbitrary loop values ATM. */ * and not all codecs support arbitrary loop values ATM. */
void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample); void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sample, int loop_end_sample);
@ -338,4 +339,6 @@ void vgmstream_force_loop(VGMSTREAM* vgmstream, int loop_flag, int loop_start_sa
/* Set number of max loops to do, then play up to stream end (for songs with proper endings) */ /* Set number of max loops to do, then play up to stream end (for songs with proper endings) */
void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target); void vgmstream_set_loop_target(VGMSTREAM* vgmstream, int loop_target);
void setup_vgmstream_play_state(VGMSTREAM* vgmstream);
#endif #endif