mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-12 01:30:49 +01:00
cleanup: layouts
This commit is contained in:
parent
b5dffc9556
commit
d253f90d25
@ -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:
|
||||||
|
@ -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 */
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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));
|
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -31,9 +31,10 @@ void render_vgmstream_segmented(sample_t* outbuf, int32_t sample_count, VGMSTREA
|
|||||||
mixing_info(data->segments[data->current_segment], NULL, ¤t_channels);
|
mixing_info(data->segments[data->current_segment], NULL, ¤t_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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user