mirror of
https://github.com/vgmstream/vgmstream.git
synced 2025-01-17 23:36:41 +01:00
Clean scd_int layout and rename to layered layout for later reuse
This commit is contained in:
parent
642c833fcd
commit
c843c350d1
@ -559,8 +559,8 @@ static const layout_info layout_info_list[] = {
|
||||
{layout_interleave, "interleave"},
|
||||
|
||||
{layout_segmented, "segmented"},
|
||||
{layout_aix, "AIX interleave, internally 18-byte interleaved"},
|
||||
{layout_scd_int, "SCD multistream interleave"},
|
||||
{layout_layered, "layered"},
|
||||
{layout_aix, "AIX"},
|
||||
|
||||
{layout_blocked_mxch, "blocked (MxCh)"},
|
||||
{layout_blocked_ast, "blocked (AST)"},
|
||||
|
@ -57,6 +57,10 @@ int setup_layout_segmented(segmented_layout_data* data);
|
||||
void free_layout_segmented(segmented_layout_data *data);
|
||||
void reset_layout_segmented(segmented_layout_data *data);
|
||||
|
||||
void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
void render_vgmstream_layered(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream);
|
||||
layered_layout_data* init_layout_layered(int layer_count);
|
||||
int setup_layout_layered(layered_layout_data* data);
|
||||
void free_layout_layered(layered_layout_data *data);
|
||||
void reset_layout_layered(layered_layout_data *data);
|
||||
|
||||
#endif
|
||||
|
@ -2,37 +2,121 @@
|
||||
#include "../vgmstream.h"
|
||||
|
||||
/* TODO: currently only properly handles mono substreams */
|
||||
/* TODO: there must be a reasonable way to respect the loop settings, as is
|
||||
the substreams are in their own little world */
|
||||
/* 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. */
|
||||
|
||||
#define INTERLEAVE_BUF_SIZE 512
|
||||
void render_vgmstream_scd_int(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
|
||||
|
||||
|
||||
void render_vgmstream_layered(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstream) {
|
||||
sample interleave_buf[INTERLEAVE_BUF_SIZE];
|
||||
int32_t samples_done = 0;
|
||||
scd_int_codec_data *data = vgmstream->codec_data;
|
||||
layered_layout_data *data = vgmstream->layout_data;
|
||||
|
||||
while (samples_done < sample_count)
|
||||
{
|
||||
while (samples_done < sample_count) {
|
||||
int32_t samples_to_do = INTERLEAVE_BUF_SIZE;
|
||||
int c;
|
||||
if (samples_to_do > sample_count - samples_done)
|
||||
samples_to_do = sample_count - samples_done;
|
||||
|
||||
for (c=0; c < data->substream_count; c++)
|
||||
{
|
||||
for (c=0; c < data->layer_count; c++) {
|
||||
int32_t i;
|
||||
|
||||
render_vgmstream(interleave_buf,
|
||||
samples_to_do, data->substreams[c]);
|
||||
render_vgmstream(interleave_buf, samples_to_do, data->layers[c]);
|
||||
|
||||
for (i=0; i < samples_to_do; i++)
|
||||
{
|
||||
buffer[(samples_done+i)*data->substream_count + c] = interleave_buf[i];
|
||||
for (i=0; i < samples_to_do; i++) {
|
||||
buffer[(samples_done+i)*data->layer_count + c] = interleave_buf[i];
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
//todo only mono at the moment
|
||||
if (data->layers[i]->channels != 1)
|
||||
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]);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,6 @@
|
||||
#include "meta.h"
|
||||
#include "../coding/coding.h"
|
||||
#include "../layout/layout.h"
|
||||
#include "sqex_scd_streamfile.h"
|
||||
|
||||
|
||||
@ -279,53 +280,54 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
|
||||
|
||||
case 0x0A: /* DSP ADPCM [Dragon Quest X (Wii)] */
|
||||
case 0x15: { /* DSP ADPCM [Dragon Quest X (Wii U)] (no apparent differences except higher sample rate) */
|
||||
int i;
|
||||
const off_t interleave_size = 0x800;
|
||||
const off_t stride_size = interleave_size * channel_count;
|
||||
int i;
|
||||
size_t total_size;
|
||||
scd_int_codec_data * data = NULL;
|
||||
|
||||
layered_layout_data * data = NULL;
|
||||
|
||||
/* interleaved DSPs including the header (so the first 0x800 is 0x60 header + 0x740 data)
|
||||
* so interleave layout can't used; we'll setup de-interleaving streamfiles as layers/channels instead */
|
||||
//todo this could be simplified using a block layout or adding interleave_first_block
|
||||
vgmstream->coding_type = coding_NGC_DSP;
|
||||
vgmstream->layout_type = layout_scd_int;
|
||||
vgmstream->layout_type = layout_layered;
|
||||
|
||||
/* a normal DSP header... */
|
||||
total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2;
|
||||
vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end+1;
|
||||
}
|
||||
/* read from the first DSP header and verify other channel headers */
|
||||
{
|
||||
total_size = (read_32bitBE(start_offset+0x04,streamFile)+1)/2; /* rounded nibbles / 2 */
|
||||
vgmstream->num_samples = read_32bitBE(start_offset+0x00,streamFile);
|
||||
if (loop_flag) {
|
||||
vgmstream->loop_start_sample = loop_start;
|
||||
vgmstream->loop_end_sample = loop_end+1;
|
||||
}
|
||||
|
||||
/* verify other channel headers */
|
||||
for (i = 1; i < channel_count; i++) {
|
||||
if (read_32bitBE(start_offset+interleave_size*i+0,streamFile) != vgmstream->num_samples ||
|
||||
(read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size) {
|
||||
goto fail;
|
||||
for (i = 1; i < channel_count; i++) {
|
||||
if ((read_32bitBE(start_offset+4,streamFile)+1)/2 != total_size ||
|
||||
read_32bitBE(start_offset+interleave_size*i+0x00,streamFile) != vgmstream->num_samples) {
|
||||
goto fail;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data = malloc(sizeof(scd_int_codec_data));
|
||||
data->substream_count = channel_count;
|
||||
data->substreams = calloc(channel_count, sizeof(VGMSTREAM *));
|
||||
/* init layout */
|
||||
data = init_layout_layered(channel_count);
|
||||
if (!data) goto fail;
|
||||
vgmstream->layout_data = data;
|
||||
|
||||
vgmstream->codec_data = data;
|
||||
|
||||
for (i=0;i<channel_count;i++) {
|
||||
/* open each layer subfile */
|
||||
for (i = 0; i < channel_count; i++) {
|
||||
STREAMFILE* temp_streamFile = setup_scd_dsp_streamfile(streamFile, start_offset+interleave_size*i, interleave_size, stride_size, total_size);
|
||||
if (!temp_streamFile) goto fail;
|
||||
|
||||
data->substreams[i] = init_vgmstream_ngc_dsp_std(temp_streamFile);
|
||||
data->layers[i] = init_vgmstream_ngc_dsp_std(temp_streamFile);
|
||||
close_streamfile(temp_streamFile);
|
||||
if (!data->substreams[i]) goto fail;
|
||||
|
||||
/* TODO: only handles mono substreams, though that's all we have with DSP */
|
||||
|
||||
/* save start things so we can restart for seeking/looping */
|
||||
memcpy(data->substreams[i]->start_ch,data->substreams[i]->ch,sizeof(VGMSTREAMCHANNEL)*1);
|
||||
memcpy(data->substreams[i]->start_vgmstream,data->substreams[i],sizeof(VGMSTREAM));
|
||||
if (!data->layers[i]) goto fail;
|
||||
}
|
||||
|
||||
/* setup layered VGMSTREAMs */
|
||||
if (!setup_layout_layered(data))
|
||||
goto fail;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -603,13 +603,8 @@ void reset_vgmstream(VGMSTREAM * vgmstream) {
|
||||
reset_layout_segmented(vgmstream->layout_data);
|
||||
}
|
||||
|
||||
if (vgmstream->layout_type==layout_scd_int) {
|
||||
scd_int_codec_data *data = vgmstream->codec_data;
|
||||
int i;
|
||||
|
||||
for (i=0;i<data->substream_count;i++) {
|
||||
reset_vgmstream(data->substreams[i]);
|
||||
}
|
||||
if (vgmstream->layout_type==layout_layered) {
|
||||
reset_layout_layered(vgmstream->layout_data);
|
||||
}
|
||||
}
|
||||
|
||||
@ -794,24 +789,12 @@ void close_vgmstream(VGMSTREAM * vgmstream) {
|
||||
|
||||
if (vgmstream->layout_type==layout_segmented) {
|
||||
free_layout_segmented(vgmstream->layout_data);
|
||||
vgmstream->codec_data = NULL;
|
||||
vgmstream->layout_data = NULL;
|
||||
}
|
||||
|
||||
if (vgmstream->layout_type==layout_scd_int) {
|
||||
scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data;
|
||||
|
||||
if (data) {
|
||||
if (data->substreams) {
|
||||
int i;
|
||||
for (i=0;i<data->substream_count;i++) {
|
||||
close_vgmstream(data->substreams[i]);
|
||||
}
|
||||
free(data->substreams);
|
||||
}
|
||||
|
||||
free(data);
|
||||
}
|
||||
vgmstream->codec_data = NULL;
|
||||
if (vgmstream->layout_type==layout_layered) {
|
||||
free_layout_layered(vgmstream->layout_data);
|
||||
vgmstream->layout_data = NULL;
|
||||
}
|
||||
|
||||
|
||||
@ -937,8 +920,8 @@ void render_vgmstream(sample * buffer, int32_t sample_count, VGMSTREAM * vgmstre
|
||||
case layout_segmented:
|
||||
render_vgmstream_segmented(buffer,sample_count,vgmstream);
|
||||
break;
|
||||
case layout_scd_int:
|
||||
render_vgmstream_scd_int(buffer,sample_count,vgmstream);
|
||||
case layout_layered:
|
||||
render_vgmstream_layered(buffer,sample_count,vgmstream);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -2366,9 +2349,9 @@ static int get_vgmstream_average_bitrate_channel_count(VGMSTREAM * vgmstream)
|
||||
{
|
||||
//AAX, AIX, ACM?
|
||||
|
||||
if (vgmstream->layout_type==layout_scd_int) {
|
||||
scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data;
|
||||
return (data) ? data->substream_count : 0;
|
||||
if (vgmstream->layout_type==layout_layered) {
|
||||
layered_layout_data *data = (layered_layout_data *) vgmstream->layout_data;
|
||||
return (data) ? data->layer_count : 0;
|
||||
}
|
||||
#ifdef VGM_USE_VORBIS
|
||||
if (vgmstream->coding_type==coding_OGG_VORBIS) {
|
||||
@ -2400,9 +2383,9 @@ static STREAMFILE * get_vgmstream_average_bitrate_channel_streamfile(VGMSTREAM *
|
||||
{
|
||||
//AAX, AIX?
|
||||
|
||||
if (vgmstream->layout_type==layout_scd_int) {
|
||||
scd_int_codec_data *data = (scd_int_codec_data *) vgmstream->codec_data;
|
||||
return data->substreams[channel]->ch[0].streamfile;
|
||||
if (vgmstream->layout_type==layout_layered) {
|
||||
layered_layout_data *data = (layered_layout_data *) vgmstream->layout_data;
|
||||
return data->layers[channel]->ch[0].streamfile;
|
||||
}
|
||||
|
||||
if (vgmstream->coding_type==coding_NWA) {
|
||||
@ -2525,7 +2508,7 @@ int vgmstream_open_stream(VGMSTREAM * vgmstream, STREAMFILE *streamFile, off_t s
|
||||
/* stream/offsets not needed, manage themselves */
|
||||
if (vgmstream->layout_type == layout_aix ||
|
||||
vgmstream->layout_type == layout_segmented ||
|
||||
vgmstream->layout_type == layout_scd_int)
|
||||
vgmstream->layout_type == layout_layered)
|
||||
return 1;
|
||||
|
||||
#ifdef VGM_USE_FFMPEG
|
||||
|
@ -255,8 +255,8 @@ typedef enum {
|
||||
|
||||
/* otherwise odd */
|
||||
layout_aix, /* CRI AIX's wheels within wheels */
|
||||
layout_segmented, /* song divided in segments, each a complete VGMSTREAM */
|
||||
layout_scd_int, /* deinterleave done by the SCDINTSTREAMFILE */
|
||||
layout_segmented, /* song divided in segments (song sections) */
|
||||
layout_layered, /* song divided in layers (song channels) */
|
||||
|
||||
} layout_t;
|
||||
|
||||
@ -1056,24 +1056,25 @@ typedef struct {
|
||||
VGMSTREAM **adxs;
|
||||
} aix_codec_data;
|
||||
|
||||
/* for files made of segments, each a full subfile (VGMSTREAM) */
|
||||
/* for files made of "vertical" segments, one per section of a song (using a complete sub-VGMSTREAM) */
|
||||
typedef struct {
|
||||
int segment_count;
|
||||
VGMSTREAM **segments;
|
||||
int current_segment;
|
||||
int loop_segment;
|
||||
VGMSTREAM **segments;
|
||||
} segmented_layout_data;
|
||||
|
||||
/* for files made of "horizontal" layers, one per group of channels (using a complete sub-VGMSTREAM) */
|
||||
typedef struct {
|
||||
int layer_count;
|
||||
VGMSTREAM **layers;
|
||||
} layered_layout_data;
|
||||
|
||||
/* for compressed NWA */
|
||||
typedef struct {
|
||||
NWAData *nwa;
|
||||
} nwa_codec_data;
|
||||
|
||||
/* SQEX SCD interleaved */
|
||||
typedef struct {
|
||||
int substream_count;
|
||||
VGMSTREAM **substreams;
|
||||
} scd_int_codec_data;
|
||||
|
||||
typedef struct {
|
||||
STREAMFILE *streamfile;
|
||||
|
Loading…
x
Reference in New Issue
Block a user