Add TXTP "loop_mode=keep" for intro+main songs that also loop normally

This commit is contained in:
bnnm 2019-02-15 18:36:12 +01:00
parent a49d9851a1
commit 9e9495168c
2 changed files with 51 additions and 17 deletions

View File

@ -6,7 +6,7 @@
* Chains together sequential vgmstreams, for data divided into separate sections or files
* (like one part for intro and other for loop segments, which may even use different codecs). */
void render_vgmstream_segmented(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
int samples_written = 0;
int samples_written = 0, loop_samples_skip = 0;
segmented_layout_data *data = vgmstream->layout_data;
@ -16,28 +16,34 @@ void render_vgmstream_segmented(sample * buffer, int32_t sample_count, VGMSTREAM
if (vgmstream->loop_flag && vgmstream_do_loop(vgmstream)) {
/* handle looping, finding loop segment */
int loop_segment = 0, samples = 0, loop_samples_skip = 0;
while (samples < vgmstream->num_samples) {
int segment, loop_segment, total_samples;
/* handle looping by finding loop segment and loop_start inside that segment */
loop_segment = 0;
total_samples = 0;
while (total_samples < vgmstream->num_samples) {
int32_t segment_samples = data->segments[loop_segment]->num_samples;
if (vgmstream->loop_start_sample >= samples && vgmstream->loop_start_sample < samples + segment_samples) {
loop_samples_skip = vgmstream->loop_start_sample - samples;
if (vgmstream->loop_start_sample >= total_samples && vgmstream->loop_start_sample < total_samples + segment_samples) {
loop_samples_skip = vgmstream->loop_start_sample - total_samples;
break; /* loop_start falls within loop_segment's samples */
}
samples += segment_samples;
total_samples += segment_samples;
loop_segment++;
}
if (loop_segment == data->segment_count) {
VGM_LOG("segmented_layout: can't find loop segment\n");
loop_segment = 0;
}
if (loop_samples_skip > 0) {
VGM_LOG("segmented_layout: loop starts after %i samples\n", loop_samples_skip);
//todo skip/fix, but probably won't happen
}
data->current_segment = loop_segment;
reset_vgmstream(data->segments[data->current_segment]);
/* loops can span multiple segments */
for (segment = loop_segment; segment < data->segment_count; segment++) {
reset_vgmstream(data->segments[segment]);
}
vgmstream->samples_into_block = 0;
continue;
}
@ -46,6 +52,12 @@ void render_vgmstream_segmented(sample * buffer, int32_t sample_count, VGMSTREAM
if (samples_to_do > sample_count - samples_written)
samples_to_do = sample_count - samples_written;
/* segment looping: discard until actual start */
if (loop_samples_skip > 0) {
if (samples_to_do > loop_samples_skip)
samples_to_do = loop_samples_skip;
}
/* detect segment change and restart */
if (samples_to_do == 0) {
data->current_segment++;
@ -57,11 +69,17 @@ void render_vgmstream_segmented(sample * buffer, int32_t sample_count, VGMSTREAM
render_vgmstream(&buffer[samples_written*data->segments[data->current_segment]->channels],
samples_to_do,data->segments[data->current_segment]);
if (loop_samples_skip > 0) {
loop_samples_skip -= samples_to_do;
vgmstream->samples_into_block += samples_to_do;
}
else {
samples_written += samples_to_do;
vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block += samples_to_do;
}
}
}
segmented_layout_data* init_layout_segmented(int segment_count) {

View File

@ -32,6 +32,7 @@ typedef struct {
int default_entry_set;
size_t is_layered;
int is_loop_keep;
} txtp_header;
static txtp_header* parse_txtp(STREAMFILE* streamFile);
@ -148,16 +149,23 @@ VGMSTREAM * init_vgmstream_txtp(STREAMFILE *streamFile) {
if (txtp->loop_start_segment && !txtp->loop_end_segment)
txtp->loop_end_segment = txtp->entry_count;
loop_flag = (txtp->loop_start_segment > 0 && txtp->loop_start_segment <= txtp->entry_count);
num_samples = 0;
for (i = 0; i < data_s->segment_count; i++) {
if (loop_flag && txtp->loop_start_segment == i+1) {
if (txtp->is_loop_keep /*&& data_s->segments[i]->loop_start_sample*/)
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;
}
}
@ -475,6 +483,14 @@ static int parse_keyval(txtp_header * txtp, const char * key, const char * val)
goto fail;
}
}
else if (0==strcmp(key,"loop_mode")) {
if (0==strcmp(val,"keep")) {
txtp->is_loop_keep = 1;
}
else {
goto fail;
}
}
else if (0==strcmp(key,"commands")) {
char val2[TXT_LINE_MAX];
strcpy(val2, val); /* copy since val is modified here but probably not important */