vgmstream/src/layout/layered.c

130 lines
3.7 KiB
C
Raw Normal View History

#include "layout.h"
#include "../vgmstream.h"
/* TODO: there must be a reasonable way to respect the loop settings, as
the substreams are in their own little world.
Currently the VGMSTREAMs layers loop internally and the external/base VGMSTREAM
doesn't actually loop, and would ignore any altered values/loop_flag. */
2018-04-22 02:19:37 +02:00
#define LAYER_BUF_SIZE 512
#define LAYER_MAX_CHANNELS 6 /* at least 2, but let's be generous */
void render_vgmstream_layered(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
2018-04-22 02:19:37 +02:00
sample interleave_buf[LAYER_BUF_SIZE*LAYER_MAX_CHANNELS];
int32_t samples_done = 0;
layered_layout_data *data = vgmstream->layout_data;
while (samples_done < sample_count) {
2018-04-22 02:19:37 +02:00
int32_t samples_to_do = LAYER_BUF_SIZE;
int layer;
if (samples_to_do > sample_count - samples_done)
samples_to_do = sample_count - samples_done;
2018-04-22 02:19:37 +02:00
for (layer = 0; layer < data->layer_count; layer++) {
int s,l_ch;
int layer_channels = data->layers[layer]->channels;
render_vgmstream(interleave_buf, samples_to_do, data->layers[layer]);
2018-04-22 02:19:37 +02:00
for (l_ch = 0; l_ch < layer_channels; l_ch++) {
for (s = 0; s < samples_to_do; s++) {
size_t layer_sample = s*layer_channels + l_ch;
size_t buffer_sample = (samples_done+s)*vgmstream->channels + (layer*layer_channels+l_ch);
2018-04-22 02:19:37 +02:00
buffer[buffer_sample] = interleave_buf[layer_sample];
}
}
2018-04-22 02:19:37 +02:00
}
samples_done += samples_to_do;
}
}
layered_layout_data* init_layout_layered(int layer_count) {
layered_layout_data *data = NULL;
if (layer_count <= 0 || layer_count > 255)
goto fail;
data = calloc(1, sizeof(layered_layout_data));
if (!data) goto fail;
data->layer_count = layer_count;
data->layers = calloc(layer_count, sizeof(VGMSTREAM*));
if (!data->layers) goto fail;
return data;
fail:
free_layout_layered(data);
return NULL;
}
int setup_layout_layered(layered_layout_data* data) {
int i;
/* setup each VGMSTREAM (roughly equivalent to vgmstream.c's init_vgmstream_internal stuff) */
for (i = 0; i < data->layer_count; i++) {
if (!data->layers[i])
goto fail;
if (data->layers[i]->num_samples <= 0)
goto fail;
2018-04-22 02:19:37 +02:00
if (data->layers[i]->channels > LAYER_MAX_CHANNELS)
goto fail;
if (i > 0) {
/* a bit weird, but no matter */
if (data->layers[i]->sample_rate != data->layers[i-1]->sample_rate) {
VGM_LOG("layered layout: layer %i has different sample rate\n", i);
}
/* also weird */
if (data->layers[i]->coding_type != data->layers[i-1]->coding_type) {
VGM_LOG("layered layout: layer %i has different coding type\n", i);
}
}
//todo could check if layers'd loop match vs main, etc
/* save start things so we can restart for seeking/looping */
memcpy(data->layers[i]->start_ch,data->layers[i]->ch,sizeof(VGMSTREAMCHANNEL)*data->layers[i]->channels);
memcpy(data->layers[i]->start_vgmstream,data->layers[i],sizeof(VGMSTREAM));
}
return 1;
fail:
return 0; /* caller is expected to free */
}
void free_layout_layered(layered_layout_data *data) {
int i;
if (!data)
return;
if (data->layers) {
for (i = 0; i < data->layer_count; i++) {
close_vgmstream(data->layers[i]);
}
free(data->layers);
}
free(data);
}
void reset_layout_layered(layered_layout_data *data) {
int i;
if (!data)
return;
for (i = 0; i < data->layer_count; i++) {
reset_vgmstream(data->layers[i]);
}
}