Handle loop points in seconds and cleanup

This commit is contained in:
bnnm 2019-03-03 20:03:26 +01:00
parent 19c10e014c
commit 563c59664d

View File

@ -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");