mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Handle loop points in seconds and cleanup
This commit is contained in:
parent
19c10e014c
commit
563c59664d
171
src/meta/txtp.c
171
src/meta/txtp.c
@ -28,7 +28,10 @@ typedef struct {
|
|||||||
|
|
||||||
int sample_rate;
|
int sample_rate;
|
||||||
int loop_install;
|
int loop_install;
|
||||||
|
int loop_end_max;
|
||||||
|
double loop_start_second;
|
||||||
int32_t loop_start_sample;
|
int32_t loop_start_sample;
|
||||||
|
double loop_end_second;
|
||||||
int32_t loop_end_sample;
|
int32_t loop_end_sample;
|
||||||
|
|
||||||
} txtp_entry;
|
} txtp_entry;
|
||||||
@ -91,14 +94,13 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
|
|||||||
}
|
}
|
||||||
else if (txtp->is_layered) {
|
else if (txtp->is_layered) {
|
||||||
/* layered multi file */
|
/* layered multi file */
|
||||||
int channel_count = 0, loop_flag;
|
|
||||||
|
|
||||||
/* init layout */
|
/* init layout */
|
||||||
data_l = init_layout_layered(txtp->entry_count);
|
data_l = init_layout_layered(txtp->entry_count);
|
||||||
if (!data_l) goto fail;
|
if (!data_l) goto fail;
|
||||||
|
|
||||||
/* open each segment subfile */
|
/* open each segment subfile */
|
||||||
for (i = 0; i < txtp->entry_count; i++) {
|
for (i = 0; i < data_l->layer_count; i++) {
|
||||||
STREAMFILE* temp_streamFile = open_streamfile_by_filename(streamFile, txtp->entry[i].filename);
|
STREAMFILE* temp_streamFile = open_streamfile_by_filename(streamFile, txtp->entry[i].filename);
|
||||||
if (!temp_streamFile) goto fail;
|
if (!temp_streamFile) goto fail;
|
||||||
temp_streamFile->stream_index = txtp->entry[i].subsong;
|
temp_streamFile->stream_index = txtp->entry[i].subsong;
|
||||||
@ -108,43 +110,34 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
|
|||||||
if (!data_l->layers[i]) goto fail;
|
if (!data_l->layers[i]) goto fail;
|
||||||
|
|
||||||
apply_config(data_l->layers[i], &txtp->entry[i]);
|
apply_config(data_l->layers[i], &txtp->entry[i]);
|
||||||
|
|
||||||
/* get actual channel count after config */
|
|
||||||
channel_count += data_l->layers[i]->channels;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* setup layered VGMSTREAMs */
|
/* setup layered VGMSTREAMs */
|
||||||
if (!setup_layout_layered(data_l))
|
if (!setup_layout_layered(data_l))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
loop_flag = data_l->layers[0]->loop_flag;
|
/* build the layered VGMSTREAM */
|
||||||
|
vgmstream = allocate_layered_vgmstream(data_l);
|
||||||
/* build the VGMSTREAM */
|
|
||||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
|
||||||
if (!vgmstream) goto fail;
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
vgmstream->sample_rate = data_l->layers[0]->sample_rate;
|
/* custom meta name if all parts don't match */
|
||||||
vgmstream->num_samples = data_l->layers[0]->num_samples;
|
for (i = 0; i < data_l->layer_count; i++) {
|
||||||
vgmstream->loop_start_sample = data_l->layers[0]->loop_start_sample;
|
if (vgmstream->meta_type != data_l->layers[i]->meta_type) {
|
||||||
vgmstream->loop_end_sample = data_l->layers[0]->loop_end_sample;
|
vgmstream->meta_type = meta_TXTP;
|
||||||
|
break;
|
||||||
vgmstream->meta_type = meta_TXTP;
|
}
|
||||||
vgmstream->coding_type = data_l->layers[0]->coding_type;
|
}
|
||||||
vgmstream->layout_type = layout_layered;
|
|
||||||
|
|
||||||
vgmstream->layout_data = data_l;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
/* segmented multi file */
|
/* segmented multi file */
|
||||||
int num_samples, loop_start_sample = 0, loop_end_sample = 0;
|
int loop_flag;
|
||||||
int loop_flag, channel_count;
|
|
||||||
|
|
||||||
/* init layout */
|
/* init layout */
|
||||||
data_s = init_layout_segmented(txtp->entry_count);
|
data_s = init_layout_segmented(txtp->entry_count);
|
||||||
if (!data_s) goto fail;
|
if (!data_s) goto fail;
|
||||||
|
|
||||||
/* open each segment subfile */
|
/* open each segment subfile */
|
||||||
for (i = 0; i < txtp->entry_count; i++) {
|
for (i = 0; i < data_s->segment_count; i++) {
|
||||||
STREAMFILE* temp_streamFile = open_streamfile_by_filename(streamFile, txtp->entry[i].filename);
|
STREAMFILE* temp_streamFile = open_streamfile_by_filename(streamFile, txtp->entry[i].filename);
|
||||||
if (!temp_streamFile) goto fail;
|
if (!temp_streamFile) goto fail;
|
||||||
temp_streamFile->stream_index = txtp->entry[i].subsong;
|
temp_streamFile->stream_index = txtp->entry[i].subsong;
|
||||||
@ -165,41 +158,34 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
|
|||||||
txtp->loop_end_segment = txtp->entry_count;
|
txtp->loop_end_segment = txtp->entry_count;
|
||||||
loop_flag = (txtp->loop_start_segment > 0 && txtp->loop_start_segment <= txtp->entry_count);
|
loop_flag = (txtp->loop_start_segment > 0 && txtp->loop_start_segment <= txtp->entry_count);
|
||||||
|
|
||||||
num_samples = 0;
|
|
||||||
|
/* build the VGMSTREAM */
|
||||||
|
vgmstream = allocate_segmented_vgmstream(data_s,loop_flag, txtp->loop_start_segment - 1, txtp->loop_end_segment - 1);
|
||||||
|
if (!vgmstream) goto fail;
|
||||||
|
|
||||||
|
/* custom meta name if all parts don't match */
|
||||||
for (i = 0; i < data_s->segment_count; i++) {
|
for (i = 0; i < data_s->segment_count; i++) {
|
||||||
|
if (vgmstream->meta_type != data_s->segments[i]->meta_type) {
|
||||||
if (loop_flag && txtp->loop_start_segment == i+1) {
|
vgmstream->meta_type = meta_TXTP;
|
||||||
if (txtp->is_loop_keep /*&& data_s->segments[i]->loop_start_sample*/)
|
break;
|
||||||
loop_start_sample = num_samples + data_s->segments[i]->loop_start_sample;
|
|
||||||
else
|
|
||||||
loop_start_sample = num_samples;
|
|
||||||
}
|
|
||||||
|
|
||||||
num_samples += data_s->segments[i]->num_samples;
|
|
||||||
|
|
||||||
if (loop_flag && txtp->loop_end_segment == i+1) {
|
|
||||||
if (txtp->is_loop_keep && data_s->segments[i]->loop_end_sample)
|
|
||||||
loop_end_sample = num_samples - data_s->segments[i]->num_samples + data_s->segments[i]->loop_end_sample;
|
|
||||||
else
|
|
||||||
loop_end_sample = num_samples;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
channel_count = data_s->segments[0]->channels;
|
/* fix loop keep */
|
||||||
|
if (loop_flag && txtp->is_loop_keep) {
|
||||||
|
int32_t current_samples = 0;
|
||||||
|
for (i = 0; i < data_s->segment_count; i++) {
|
||||||
|
if (txtp->loop_start_segment == i+1 /*&& data_s->segments[i]->loop_start_sample*/) {
|
||||||
|
vgmstream->loop_start_sample = current_samples + data_s->segments[i]->loop_start_sample;
|
||||||
|
}
|
||||||
|
|
||||||
/* build the VGMSTREAM */
|
current_samples += data_s->segments[i]->num_samples;
|
||||||
vgmstream = allocate_vgmstream(channel_count,loop_flag);
|
|
||||||
if (!vgmstream) goto fail;
|
|
||||||
|
|
||||||
vgmstream->sample_rate = data_s->segments[0]->sample_rate;
|
if (txtp->loop_end_segment == i+1 && data_s->segments[i]->loop_end_sample) {
|
||||||
vgmstream->num_samples = num_samples;
|
vgmstream->loop_end_sample = current_samples - data_s->segments[i]->num_samples + data_s->segments[i]->loop_end_sample;
|
||||||
vgmstream->loop_start_sample = loop_start_sample;
|
}
|
||||||
vgmstream->loop_end_sample = loop_end_sample;
|
}
|
||||||
|
}
|
||||||
vgmstream->meta_type = meta_TXTP;
|
|
||||||
vgmstream->coding_type = data_s->segments[0]->coding_type;
|
|
||||||
vgmstream->layout_type = layout_segmented;
|
|
||||||
vgmstream->layout_data = data_s;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -240,12 +226,23 @@ static void apply_config(VGMSTREAM *vgmstream, txtp_entry *current) {
|
|||||||
vgmstream->config_force_loop = current->config_force_loop;
|
vgmstream->config_force_loop = current->config_force_loop;
|
||||||
vgmstream->config_ignore_fade = current->config_ignore_fade;
|
vgmstream->config_ignore_fade = current->config_ignore_fade;
|
||||||
|
|
||||||
if (current->sample_rate > 0)
|
if (current->sample_rate > 0) {
|
||||||
vgmstream->sample_rate = current->sample_rate;
|
vgmstream->sample_rate = current->sample_rate;
|
||||||
|
}
|
||||||
|
|
||||||
if (current->loop_install) {
|
if (current->loop_install) {
|
||||||
if (current->loop_end_sample < 0)
|
if (current->loop_start_second > 0 || current->loop_end_second > 0) {
|
||||||
|
current->loop_start_sample = current->loop_start_second * (double)vgmstream->sample_rate;
|
||||||
|
current->loop_end_sample = current->loop_end_second * (double)vgmstream->sample_rate;
|
||||||
|
if (current->loop_end_sample > vgmstream->num_samples &&
|
||||||
|
current->loop_end_sample - vgmstream->num_samples <= 1000)
|
||||||
|
current->loop_end_sample = vgmstream->num_samples; /* allow some rounding leeway */
|
||||||
|
}
|
||||||
|
|
||||||
|
if (current->loop_end_max) {
|
||||||
current->loop_end_sample = vgmstream->num_samples;
|
current->loop_end_sample = vgmstream->num_samples;
|
||||||
|
}
|
||||||
|
|
||||||
vgmstream_force_loop(vgmstream, current->loop_install, current->loop_start_sample, current->loop_end_sample);
|
vgmstream_force_loop(vgmstream, current->loop_install, current->loop_start_sample, current->loop_end_sample);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,6 +330,47 @@ static int get_int(const char * config, int *value) {
|
|||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int get_time(const char * config, double *value_f, int32_t *value_i) {
|
||||||
|
int n,m;
|
||||||
|
int temp_i1, temp_i2;
|
||||||
|
double temp_f1, temp_f2;
|
||||||
|
char temp_c;
|
||||||
|
|
||||||
|
/* test if format is hour: N:N(.n) or N_N(.n) */
|
||||||
|
m = sscanf(config, " %i%c%i%n", &temp_i1,&temp_c,&temp_i2,&n);
|
||||||
|
if (m == 3 && (temp_c == ':' || temp_c == '_')) {
|
||||||
|
m = sscanf(config, " %lf%c%lf%n", &temp_f1,&temp_c,&temp_f2,&n);
|
||||||
|
if (m != 3 || temp_f1 < 0.0 || temp_f1 >= 60.0 || temp_f2 < 0.0 || temp_f2 >= 60.0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
*value_f = temp_f1 * 60.0 + temp_f2;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* test if format is seconds: N.n */
|
||||||
|
m = sscanf(config, " %i.%i%n", &temp_i1,&temp_i2,&n);
|
||||||
|
if (m == 2) {
|
||||||
|
m = sscanf(config, " %lf%n", &temp_f1,&n);
|
||||||
|
if (m != 1 || temp_f1 < 0.0)
|
||||||
|
return 0;
|
||||||
|
*value_f = temp_f1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* assume format is samples: N */
|
||||||
|
m = sscanf(config, " %i%n", &temp_i1,&n);
|
||||||
|
if (m == 1) {
|
||||||
|
if (temp_i1 < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
//*is_time_i = 1;
|
||||||
|
*value_i = temp_i1;
|
||||||
|
return n;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int get_bool(const char * config, int *value) {
|
static int get_bool(const char * config, int *value) {
|
||||||
int n,m;
|
int n,m;
|
||||||
char temp;
|
char temp;
|
||||||
@ -450,7 +488,7 @@ static void add_config(txtp_entry* current, txtp_entry* cfg, const char* filenam
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
#ifdef VGMSTREAM_MIXING
|
#ifdef VGMSTREAM_MIXING
|
||||||
//*current = *cfg; /* don't memcopy to allow list additions */
|
//*current = *cfg; /* don't memcopy to allow list additions */ //todo save list first then memcpy
|
||||||
|
|
||||||
if (cfg->mixing_count > 0) {
|
if (cfg->mixing_count > 0) {
|
||||||
int i;
|
int i;
|
||||||
@ -470,13 +508,15 @@ static void add_config(txtp_entry* current, txtp_entry* cfg, const char* filenam
|
|||||||
|
|
||||||
current->sample_rate = cfg->sample_rate;
|
current->sample_rate = cfg->sample_rate;
|
||||||
current->loop_install = cfg->loop_install;
|
current->loop_install = cfg->loop_install;
|
||||||
|
current->loop_end_max = cfg->loop_end_max;
|
||||||
current->loop_start_sample = cfg->loop_start_sample;
|
current->loop_start_sample = cfg->loop_start_sample;
|
||||||
|
current->loop_start_second = cfg->loop_start_second;
|
||||||
current->loop_end_sample = cfg->loop_end_sample;
|
current->loop_end_sample = cfg->loop_end_sample;
|
||||||
|
current->loop_end_second = cfg->loop_end_second;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int add_filename(txtp_header * txtp, char *filename, int is_default) {
|
static int add_filename(txtp_header * txtp, char *filename, int is_default) {
|
||||||
int i, n, m, nc, mc;
|
int i, n, nc, mc;
|
||||||
txtp_entry cfg = {0};
|
txtp_entry cfg = {0};
|
||||||
size_t range_start, range_end;
|
size_t range_start, range_end;
|
||||||
char command[TXTP_LINE_MAX] = {0};
|
char command[TXTP_LINE_MAX] = {0};
|
||||||
@ -688,16 +728,21 @@ static int add_filename(txtp_header * txtp, char *filename, int is_default) {
|
|||||||
//;VGM_LOG("TXTP: sample_rate %i\n", cfg.sample_rate);
|
//;VGM_LOG("TXTP: sample_rate %i\n", cfg.sample_rate);
|
||||||
}
|
}
|
||||||
else if (strcmp(command,"I") == 0) {
|
else if (strcmp(command,"I") == 0) {
|
||||||
m = sscanf(config, " %d %d%n", &cfg.loop_start_sample, &cfg.loop_end_sample, &n);
|
n = get_time(config, &cfg.loop_start_second, &cfg.loop_start_sample);
|
||||||
if (m == 2) {
|
if (n > 0) { /* first value must exist */
|
||||||
|
config += n;
|
||||||
|
|
||||||
|
n = get_time(config, &cfg.loop_end_second, &cfg.loop_end_sample);
|
||||||
|
if (n == 0) { /* second value is optional */
|
||||||
|
cfg.loop_end_max = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
config += n;
|
||||||
cfg.loop_install = 1;
|
cfg.loop_install = 1;
|
||||||
} else if (m == 1) {
|
|
||||||
cfg.loop_install = 1;
|
|
||||||
cfg.loop_end_sample = -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
config += n;
|
//;VGM_LOG("TXTP: loop_install %i (max=%i): %i %i / %f %f\n", cfg.loop_install, cfg.loop_end_max,
|
||||||
//;VGM_LOG("TXTP: loop_install %i = %i %i\n", cfg.loop_install, cfg.loop_start_sample, cfg.loop_end_sample);
|
// cfg.loop_start_sample, cfg.loop_end_sample, cfg.loop_start_second, cfg.loop_end_second);
|
||||||
}
|
}
|
||||||
else if (config[nc] == ' ') {
|
else if (config[nc] == ' ') {
|
||||||
//;VGM_LOG("TXTP: comment\n");
|
//;VGM_LOG("TXTP: comment\n");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user