cleanup: layouts

This commit is contained in:
bnnm 2024-08-18 01:14:32 +02:00
parent b5dffc9556
commit d253f90d25
6 changed files with 217 additions and 177 deletions

View File

@ -828,10 +828,10 @@ bool decode_uses_internal_offset_updates(VGMSTREAM* vgmstream) {
* buffer already, and we have samples_to_do consecutive samples ahead of us (won't call * buffer already, and we have samples_to_do consecutive samples ahead of us (won't call
* more than one frame if configured above to do so). * more than one frame if configured above to do so).
* Called by layouts since they handle samples written/to_do */ * Called by layouts since they handle samples written/to_do */
void decode_vgmstream(VGMSTREAM* vgmstream, int samples_written, int samples_to_do, sample_t* buffer) { void decode_vgmstream(VGMSTREAM* vgmstream, int samples_filled, int samples_to_do, sample_t* buffer) {
int ch; int ch;
buffer += samples_written * vgmstream->channels; /* passed externally to simplify I guess */ buffer += samples_filled * vgmstream->channels; /* passed externally to simplify I guess */
switch (vgmstream->coding_type) { switch (vgmstream->coding_type) {
case coding_SILENCE: case coding_SILENCE:

View File

@ -1,38 +1,36 @@
#include "layout.h" #include "layout.h"
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../base/decode.h" #include "../base/decode.h"
#include "../base/sbuf.h"
#include "../coding/coding.h" #include "../coding/coding.h"
/* Decodes samples for blocked streams. /* Decodes samples for blocked streams.
* Data is divided into headered blocks with a bunch of data. The layout calls external helper functions * Data is divided into headered blocks with a bunch of data. The layout calls external helper functions
* when a block is decoded, and those must parse the new block and move offsets accordingly. */ * when a block is decoded, and those must parse the new block and move offsets accordingly. */
void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM* vgmstream) { void render_vgmstream_blocked(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vgmstream) {
int samples_written = 0;
int frame_size, samples_per_frame, samples_this_block;
frame_size = decode_get_frame_size(vgmstream); int frame_size = decode_get_frame_size(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream); int samples_per_frame = decode_get_samples_per_frame(vgmstream);
samples_this_block = 0; int samples_this_block = 0;
if (vgmstream->current_block_samples) { if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples; samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */ } else if (frame_size == 0) { /* assume 4 bit */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else { } else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
} }
int samples_filled = 0;
while (samples_written < sample_count) { while (samples_filled < sample_count) {
int samples_to_do; int samples_to_do;
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping, readjust back to loop start values */ /* handle looping, readjust back to loop start values */
if (vgmstream->current_block_samples) { if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples; samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */ } else if (frame_size == 0) { /* assume 4 bit */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else { } else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
@ -42,28 +40,26 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
if (samples_this_block < 0) { if (samples_this_block < 0) {
/* probably block bug or EOF, next calcs would give wrong values/segfaults/infinite loop */ /* probably block bug or EOF, next calcs would give wrong values/segfaults/infinite loop */
VGM_LOG("layout_blocked: wrong block samples at 0x%x\n", (uint32_t)vgmstream->current_block_offset); VGM_LOG("BLOCKED: wrong block samples\n");
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t)); goto decode_fail;
break;
} }
if (vgmstream->current_block_offset < 0 || vgmstream->current_block_offset == 0xFFFFFFFF) { if (vgmstream->current_block_offset < 0 || vgmstream->current_block_offset == 0xFFFFFFFF) {
/* probably block bug or EOF, block functions won't be able to read anything useful/infinite loop */ /* probably block bug or EOF, block functions won't be able to read anything useful/infinite loop */
VGM_LOG("layout_blocked: wrong block offset found\n"); VGM_LOG("BLOCKED: wrong block offset found\n");
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t)); goto decode_fail;
break;
} }
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written) if (samples_to_do > sample_count - samples_filled)
samples_to_do = sample_count - samples_written; samples_to_do = sample_count - samples_filled;
if (samples_to_do > 0) { if (samples_to_do > 0) {
/* samples_this_block = 0 is allowed (empty block, do nothing then move to next block) */ /* samples_this_block = 0 is allowed (empty block, do nothing then move to next block) */
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer); decode_vgmstream(vgmstream, samples_filled, samples_to_do, outbuf);
} }
samples_written += samples_to_do; samples_filled += samples_to_do;
vgmstream->current_sample += samples_to_do; vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block += samples_to_do; vgmstream->samples_into_block += samples_to_do;
@ -71,14 +67,14 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
/* move to next block when all samples are consumed */ /* move to next block when all samples are consumed */
if (vgmstream->samples_into_block == samples_this_block if (vgmstream->samples_into_block == samples_this_block
/*&& vgmstream->current_sample < vgmstream->num_samples*/) { /* don't go past last block */ //todo /*&& vgmstream->current_sample < vgmstream->num_samples*/) { /* don't go past last block */ //todo
block_update(vgmstream->next_block_offset,vgmstream); block_update(vgmstream->next_block_offset, vgmstream);
/* update since these may change each block */ /* update since these may change each block */
frame_size = decode_get_frame_size(vgmstream); frame_size = decode_get_frame_size(vgmstream);
samples_per_frame = decode_get_samples_per_frame(vgmstream); samples_per_frame = decode_get_samples_per_frame(vgmstream);
if (vgmstream->current_block_samples) { if (vgmstream->current_block_samples) {
samples_this_block = vgmstream->current_block_samples; samples_this_block = vgmstream->current_block_samples;
} else if (frame_size == 0) { /* assume 4 bit */ //TODO: decode_get_frame_size() really should return bits... */ } else if (frame_size == 0) { /* assume 4 bit */
samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame; samples_this_block = vgmstream->current_block_size * 2 * samples_per_frame;
} else { } else {
samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame; samples_this_block = vgmstream->current_block_size / frame_size * samples_per_frame;
@ -86,8 +82,11 @@ void render_vgmstream_blocked(sample_t* buffer, int32_t sample_count, VGMSTREAM*
vgmstream->samples_into_block = 0; vgmstream->samples_into_block = 0;
} }
} }
return;
decode_fail:
sbuf_silence(outbuf, sample_count, vgmstream->channels, samples_filled);
} }
/* helper functions to parse new block */ /* helper functions to parse new block */

View File

@ -1,43 +1,42 @@
#include "layout.h" #include "layout.h"
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../base/decode.h" #include "../base/decode.h"
#include "../base/sbuf.h"
/* Decodes samples for flat streams. /* Decodes samples for flat streams.
* Data forms a single stream, and the decoder may internally skip chunks and move offsets as needed. */ * Data forms a single stream, and the decoder may internally skip chunks and move offsets as needed. */
void render_vgmstream_flat(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vgmstream) { void render_vgmstream_flat(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vgmstream) {
int samples_written = 0;
int samples_per_frame, samples_this_block;
samples_per_frame = decode_get_samples_per_frame(vgmstream); int samples_per_frame = decode_get_samples_per_frame(vgmstream);
samples_this_block = vgmstream->num_samples; /* do all samples if possible */ int samples_this_block = vgmstream->num_samples; /* do all samples if possible */
/* write samples */
while (samples_written < sample_count) { int samples_filled = 0;
int samples_to_do; while (samples_filled < sample_count) {
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping */ /* handle looping */
continue; continue;
} }
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); int samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written) if (samples_to_do > sample_count - samples_filled)
samples_to_do = sample_count - samples_written; samples_to_do = sample_count - samples_filled;
if (samples_to_do == 0) { /* when decoding more than num_samples */ if (samples_to_do <= 0) { /* when decoding more than num_samples */
VGM_LOG_ONCE("FLAT: samples_to_do 0\n"); VGM_LOG_ONCE("FLAT: wrong samples_to_do\n");
goto decode_fail; goto decode_fail;
} }
decode_vgmstream(vgmstream, samples_written, samples_to_do, outbuf); decode_vgmstream(vgmstream, samples_filled, samples_to_do, outbuf);
samples_written += samples_to_do; samples_filled += samples_to_do;
vgmstream->current_sample += samples_to_do; vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block += samples_to_do; vgmstream->samples_into_block += samples_to_do;
} }
return; return;
decode_fail: decode_fail:
memset(outbuf + samples_written * vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t)); sbuf_silence(outbuf, sample_count, vgmstream->channels, samples_filled);
} }

View File

@ -1,157 +1,197 @@
#include "layout.h" #include "layout.h"
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../base/decode.h" #include "../base/decode.h"
#include "../base/sbuf.h"
typedef struct {
/* default */
int samples_per_frame_d;
int samples_this_block_d;
/* first */
int samples_per_frame_f;
int samples_this_block_f;
/* last */
int samples_per_frame_l;
int samples_this_block_l;
bool has_interleave_first;
bool has_interleave_last;
bool has_interleave_internal_updates;
} layout_config_t;
static bool setup_helper(layout_config_t* layout, VGMSTREAM* vgmstream) {
//TO-DO: this could be pre-calc'd after main init
layout->has_interleave_first = vgmstream->interleave_first_block_size && vgmstream->channels > 1;
layout->has_interleave_last = vgmstream->interleave_last_block_size && vgmstream->channels > 1;
layout->has_interleave_internal_updates = vgmstream->codec_internal_updates;
{
int frame_size_d = decode_get_frame_size(vgmstream);
layout->samples_per_frame_d = decode_get_samples_per_frame(vgmstream);
if (frame_size_d == 0 || layout->samples_per_frame_d == 0)
goto fail;
layout->samples_this_block_d = vgmstream->interleave_block_size / frame_size_d * layout->samples_per_frame_d;
}
if (layout->has_interleave_first) {
int frame_size_f = decode_get_frame_size(vgmstream);
layout->samples_per_frame_f = decode_get_samples_per_frame(vgmstream); //todo samples per shortframe
if (frame_size_f == 0 || layout->samples_per_frame_f == 0)
goto fail;
layout->samples_this_block_f = vgmstream->interleave_first_block_size / frame_size_f * layout->samples_per_frame_f;
}
if (layout->has_interleave_last) {
int frame_size_l = decode_get_shortframe_size(vgmstream);
layout->samples_per_frame_l = decode_get_samples_per_shortframe(vgmstream);
if (frame_size_l == 0 || layout->samples_per_frame_l == 0) goto fail;
layout->samples_this_block_l = vgmstream->interleave_last_block_size / frame_size_l * layout->samples_per_frame_l;
}
return true;
fail:
return false;
}
static void update_default_values(layout_config_t* layout, VGMSTREAM* vgmstream, int* p_samples_per_frame, int* p_samples_this_block) {
if (layout->has_interleave_first &&
vgmstream->current_sample < layout->samples_this_block_f) {
*p_samples_per_frame = layout->samples_per_frame_f;
*p_samples_this_block = layout->samples_this_block_f;
}
else if (layout->has_interleave_last &&
vgmstream->current_sample - vgmstream->samples_into_block + layout->samples_this_block_d > vgmstream->num_samples) {
*p_samples_per_frame = layout->samples_per_frame_l;
*p_samples_this_block = layout->samples_this_block_l;
}
else {
*p_samples_per_frame = layout->samples_per_frame_d;
*p_samples_this_block = layout->samples_this_block_d;
}
}
static void update_loop_values(layout_config_t* layout, VGMSTREAM* vgmstream, int* p_samples_per_frame, int* p_samples_this_block) {
if (layout->has_interleave_first &&
vgmstream->current_sample < layout->samples_this_block_f) {
/* use first interleave*/
*p_samples_per_frame = layout->samples_per_frame_f;
*p_samples_this_block = layout->samples_this_block_f;
if (*p_samples_this_block == 0 && vgmstream->channels == 1)
*p_samples_this_block = vgmstream->num_samples;
}
else if (layout->has_interleave_last) { /* assumes that won't loop back into a interleave_last */
*p_samples_per_frame = layout->samples_per_frame_d;
*p_samples_this_block = layout->samples_this_block_d;
if (*p_samples_this_block == 0 && vgmstream->channels == 1)
*p_samples_this_block = vgmstream->num_samples;
}
}
static void update_offsets(layout_config_t* layout, VGMSTREAM* vgmstream, int* p_samples_per_frame, int* p_samples_this_block) {
int channels = vgmstream->channels;
if (layout->has_interleave_first &&
vgmstream->current_sample == layout->samples_this_block_f) {
/* interleave during first interleave: restore standard frame size after going past first interleave */
*p_samples_per_frame = layout->samples_per_frame_d;
*p_samples_this_block = layout->samples_this_block_d;
if (*p_samples_this_block == 0 && channels == 1)
*p_samples_this_block = vgmstream->num_samples;
for (int ch = 0; ch < channels; ch++) {
off_t skip = vgmstream->interleave_first_skip * (channels - 1 - ch) +
vgmstream->interleave_first_block_size * (channels - ch) +
vgmstream->interleave_block_size * ch;
vgmstream->ch[ch].offset += skip;
}
}
else if (layout->has_interleave_last &&
vgmstream->current_sample + *p_samples_this_block > vgmstream->num_samples) {
/* interleave during last interleave: adjust values again if inside last interleave */
*p_samples_per_frame = layout->samples_per_frame_l;
*p_samples_this_block = layout->samples_this_block_l;
if (*p_samples_this_block == 0 && channels == 1)
*p_samples_this_block = vgmstream->num_samples;
for (int ch = 0; ch < channels; ch++) {
off_t skip = vgmstream->interleave_block_size * (channels - ch) +
vgmstream->interleave_last_block_size * ch;
vgmstream->ch[ch].offset += skip;
}
}
else if (layout->has_interleave_internal_updates) {
/* interleave for some decoders that have already moved offsets over their data, so skip other channels's data */
for (int ch = 0; ch < channels; ch++) {
off_t skip = vgmstream->interleave_block_size * (channels - 1);
vgmstream->ch[ch].offset += skip;
}
}
else {
/* regular interleave */
for (int ch = 0; ch < channels; ch++) {
off_t skip = vgmstream->interleave_block_size * channels;
vgmstream->ch[ch].offset += skip;
}
}
vgmstream->samples_into_block = 0;
}
/* Decodes samples for interleaved streams. /* Decodes samples for interleaved streams.
* Data has interleaved chunks per channel, and once one is decoded the layout moves offsets, * Data has interleaved chunks per channel, and once one is decoded the layout moves offsets,
* skipping other chunks (essentially a simplified variety of blocked layout). * skipping other chunks (essentially a simplified variety of blocked layout).
* Incompatible with decoders that move offsets. */ * Incompatible with decoders that move offsets. */
void render_vgmstream_interleave(sample_t * buffer, int32_t sample_count, VGMSTREAM * vgmstream) { void render_vgmstream_interleave(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vgmstream) {
int samples_written = 0; layout_config_t layout = {0};
int samples_per_frame, samples_this_block; /* used */ if (!setup_helper(&layout, vgmstream)) {
int samples_per_frame_d = 0, samples_this_block_d = 0; /* default */ VGM_LOG_ONCE("INTERLEAVE: wrong config found\n");
int samples_per_frame_f = 0, samples_this_block_f = 0; /* first */ sbuf_silence(outbuf, sample_count, vgmstream->channels, 0);
int samples_per_frame_l = 0, samples_this_block_l = 0; /* last */ return;
int has_interleave_first = vgmstream->interleave_first_block_size && vgmstream->channels > 1; }
int has_interleave_last = vgmstream->interleave_last_block_size && vgmstream->channels > 1;
int has_interleave_internal_updates = vgmstream->codec_internal_updates;
/* setup */
{
int frame_size_d = decode_get_frame_size(vgmstream);
samples_per_frame_d = decode_get_samples_per_frame(vgmstream);
if (frame_size_d == 0 || samples_per_frame_d == 0) goto fail;
samples_this_block_d = vgmstream->interleave_block_size / frame_size_d * samples_per_frame_d;
}
if (has_interleave_first) {
int frame_size_f = decode_get_frame_size(vgmstream);
samples_per_frame_f = decode_get_samples_per_frame(vgmstream); //todo samples per shortframe
if (frame_size_f == 0 || samples_per_frame_f == 0) goto fail;
samples_this_block_f = vgmstream->interleave_first_block_size / frame_size_f * samples_per_frame_f;
}
if (has_interleave_last) {
int frame_size_l = decode_get_shortframe_size(vgmstream);
samples_per_frame_l = decode_get_samples_per_shortframe(vgmstream);
if (frame_size_l == 0 || samples_per_frame_l == 0) goto fail;
samples_this_block_l = vgmstream->interleave_last_block_size / frame_size_l * samples_per_frame_l;
}
/* set current values */ /* set current values */
if (has_interleave_first && int samples_per_frame, samples_this_block;
vgmstream->current_sample < samples_this_block_f) { update_default_values(&layout, vgmstream, &samples_per_frame, &samples_this_block);
samples_per_frame = samples_per_frame_f;
samples_this_block = samples_this_block_f;
}
else if (has_interleave_last &&
vgmstream->current_sample - vgmstream->samples_into_block + samples_this_block_d > vgmstream->num_samples) {
samples_per_frame = samples_per_frame_l;
samples_this_block = samples_this_block_l;
}
else {
samples_per_frame = samples_per_frame_d;
samples_this_block = samples_this_block_d;
}
/* mono interleaved stream with no layout set, just behave like flat layout */ /* mono interleaved stream with no layout set, just behave like flat layout */
if (samples_this_block == 0 && vgmstream->channels == 1) if (samples_this_block == 0 && vgmstream->channels == 1)
samples_this_block = vgmstream->num_samples; samples_this_block = vgmstream->num_samples;
int samples_filled = 0;
/* write samples */ while (samples_filled < sample_count) {
while (samples_written < sample_count) {
int samples_to_do;
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping, restore standard interleave sizes */ /* handle looping, restore standard interleave sizes */
update_loop_values(&layout, vgmstream, &samples_per_frame, &samples_this_block);
if (has_interleave_first &&
vgmstream->current_sample < samples_this_block_f) {
/* use first interleave*/
samples_per_frame = samples_per_frame_f;
samples_this_block = samples_this_block_f;
if (samples_this_block == 0 && vgmstream->channels == 1)
samples_this_block = vgmstream->num_samples;
}
else if (has_interleave_last) { /* assumes that won't loop back into a interleave_last */
samples_per_frame = samples_per_frame_d;
samples_this_block = samples_this_block_d;
if (samples_this_block == 0 && vgmstream->channels == 1)
samples_this_block = vgmstream->num_samples;
}
continue; continue;
} }
samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); int samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_count - samples_written) if (samples_to_do > sample_count - samples_filled)
samples_to_do = sample_count - samples_written; samples_to_do = sample_count - samples_filled;
if (samples_to_do == 0) { /* happens when interleave is not set */ if (samples_to_do <= 0) { /* happens when interleave is not set */
goto fail; VGM_LOG_ONCE("INTERLEAVE: wrong samples_to_do\n");
goto decode_fail;
} }
decode_vgmstream(vgmstream, samples_written, samples_to_do, buffer); decode_vgmstream(vgmstream, samples_filled, samples_to_do, outbuf);
samples_written += samples_to_do; samples_filled += samples_to_do;
vgmstream->current_sample += samples_to_do; vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block += samples_to_do; vgmstream->samples_into_block += samples_to_do;
/* move to next interleaved block when all samples are consumed */ /* move to next interleaved block when all samples are consumed */
if (vgmstream->samples_into_block == samples_this_block) { if (vgmstream->samples_into_block == samples_this_block) {
int ch; update_offsets(&layout, vgmstream, &samples_per_frame, &samples_this_block);
if (has_interleave_first &&
vgmstream->current_sample == samples_this_block_f) {
/* restore standard frame size after going past first interleave */
samples_per_frame = samples_per_frame_d;
samples_this_block = samples_this_block_d;
if (samples_this_block == 0 && vgmstream->channels == 1)
samples_this_block = vgmstream->num_samples;
for (ch = 0; ch < vgmstream->channels; ch++) {
off_t skip =
vgmstream->interleave_first_skip*(vgmstream->channels-1-ch) +
vgmstream->interleave_first_block_size*(vgmstream->channels-ch) +
vgmstream->interleave_block_size*ch;
vgmstream->ch[ch].offset += skip;
}
}
else if (has_interleave_last &&
vgmstream->current_sample + samples_this_block > vgmstream->num_samples) {
/* adjust values again if inside last interleave */
samples_per_frame = samples_per_frame_l;
samples_this_block = samples_this_block_l;
if (samples_this_block == 0 && vgmstream->channels == 1)
samples_this_block = vgmstream->num_samples;
for (ch = 0; ch < vgmstream->channels; ch++) {
off_t skip =
vgmstream->interleave_block_size*(vgmstream->channels-ch) +
vgmstream->interleave_last_block_size*ch;
vgmstream->ch[ch].offset += skip;
}
}
else if (has_interleave_internal_updates) {
for (ch = 0; ch < vgmstream->channels; ch++) {
off_t skip = vgmstream->interleave_block_size * (vgmstream->channels - 1);
vgmstream->ch[ch].offset += skip;
}
}
else {
for (ch = 0; ch < vgmstream->channels; ch++) {
off_t skip = vgmstream->interleave_block_size * vgmstream->channels;
vgmstream->ch[ch].offset += skip;
}
}
vgmstream->samples_into_block = 0;
} }
} }
return; return;
fail: decode_fail:
VGM_LOG_ONCE("layout_interleave: wrong values found\n"); sbuf_silence(outbuf, sample_count, vgmstream->channels, samples_filled);
memset(buffer + samples_written*vgmstream->channels, 0, (sample_count - samples_written) * vgmstream->channels * sizeof(sample_t));
} }

View File

@ -12,26 +12,27 @@
/* Decodes samples for layered streams. /* Decodes samples for layered streams.
* Each decoded vgmstream 'layer' (which may have different codecs and number of channels) * Each decoded vgmstream 'layer' (which may have different codecs and number of channels)
* is mixed into a final buffer, creating a single super-vgmstream. */ * is mixed into a final buffer, creating a single super-vgmstream. */
void render_vgmstream_layered(sample_t* outbuf, int32_t sample_len, VGMSTREAM* vgmstream) { void render_vgmstream_layered(sample_t* outbuf, int32_t sample_count, VGMSTREAM* vgmstream) {
layered_layout_data* data = vgmstream->layout_data; layered_layout_data* data = vgmstream->layout_data;
int samples_per_frame = VGMSTREAM_LAYER_SAMPLE_BUFFER; int samples_per_frame = VGMSTREAM_LAYER_SAMPLE_BUFFER;
int samples_this_block = vgmstream->num_samples; /* do all samples if possible */ int samples_this_block = vgmstream->num_samples; /* do all samples if possible */
int samples_filled = 0; int samples_filled = 0;
while (samples_filled < sample_len) { while (samples_filled < sample_count) {
int ch;
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping (loop_layout has been called below) */ /* handle looping (loop_layout has been called inside) */
continue; continue;
} }
int ch;
int samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream); int samples_to_do = decode_get_samples_to_do(samples_this_block, samples_per_frame, vgmstream);
if (samples_to_do > sample_len - samples_filled) if (samples_to_do > sample_count - samples_filled)
samples_to_do = sample_len - samples_filled; samples_to_do = sample_count - samples_filled;
if (samples_to_do <= 0) { /* when decoding more than num_samples */ if (samples_to_do <= 0) { /* when decoding more than num_samples */
VGM_LOG_ONCE("LAYERED: samples_to_do 0\n"); VGM_LOG_ONCE("LAYERED: wrong samples_to_do\n");
goto decode_fail; goto decode_fail;
} }
@ -57,7 +58,7 @@ void render_vgmstream_layered(sample_t* outbuf, int32_t sample_len, VGMSTREAM* v
return; return;
decode_fail: decode_fail:
sbuf_silence(outbuf, sample_len, data->output_channels, samples_filled); sbuf_silence(outbuf, sample_count, data->output_channels, samples_filled);
} }

View File

@ -31,9 +31,10 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
mixing_info(data->segments[data->current_segment], NULL, &current_channels); mixing_info(data->segments[data->current_segment], NULL, &current_channels);
int samples_this_block = vgmstream_get_samples(data->segments[data->current_segment]); int samples_this_block = vgmstream_get_samples(data->segments[data->current_segment]);
int samples_written = 0; int samples_filled = 0;
while (samples_written < sample_count) { while (samples_filled < sample_count) {
int samples_to_do; int samples_to_do;
sample_t* buf;
if (vgmstream->loop_flag && decode_do_loop(vgmstream)) { if (vgmstream->loop_flag && decode_do_loop(vgmstream)) {
/* handle looping (loop_layout has been called below, changes segments/state) */ /* handle looping (loop_layout has been called below, changes segments/state) */
@ -62,8 +63,8 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
samples_to_do = decode_get_samples_to_do(samples_this_block, sample_count, vgmstream); samples_to_do = decode_get_samples_to_do(samples_this_block, sample_count, vgmstream);
if (samples_to_do > sample_count - samples_written) if (samples_to_do > sample_count - samples_filled)
samples_to_do = sample_count - samples_written; samples_to_do = sample_count - samples_filled;
if (samples_to_do > VGMSTREAM_SEGMENT_SAMPLE_BUFFER /*&& use_internal_buffer*/) /* always for fade/etc mixes */ if (samples_to_do > VGMSTREAM_SEGMENT_SAMPLE_BUFFER /*&& use_internal_buffer*/) /* always for fade/etc mixes */
samples_to_do = VGMSTREAM_SEGMENT_SAMPLE_BUFFER; samples_to_do = VGMSTREAM_SEGMENT_SAMPLE_BUFFER;
@ -72,21 +73,21 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
goto decode_fail; goto decode_fail;
} }
sample_t* buf = use_internal_buffer ? data->buffer : &outbuf[samples_written * data->output_channels]; buf = use_internal_buffer ? data->buffer : &outbuf[samples_filled * data->output_channels];
render_vgmstream(buf, samples_to_do, data->segments[data->current_segment]); render_vgmstream(buf, samples_to_do, data->segments[data->current_segment]);
if (use_internal_buffer) { if (use_internal_buffer) {
sbuf_copy_samples(outbuf, data->output_channels, data->buffer, current_channels, samples_to_do, samples_written); sbuf_copy_samples(outbuf, data->output_channels, data->buffer, current_channels, samples_to_do, samples_filled);
} }
samples_written += samples_to_do; samples_filled += samples_to_do;
vgmstream->current_sample += samples_to_do; vgmstream->current_sample += samples_to_do;
vgmstream->samples_into_block += samples_to_do; vgmstream->samples_into_block += samples_to_do;
} }
return; return;
decode_fail: decode_fail:
sbuf_silence(outbuf, sample_count, data->output_channels, samples_written); sbuf_silence(outbuf, sample_count, data->output_channels, samples_filled);
} }