cog/Frameworks/vgmstream/vgmstream/src/meta/mul_streamfile.h

83 lines
2.7 KiB
C

#ifndef _MUL_STREAMFILE_H_
#define _MUL_STREAMFILE_H_
#include "deblock_streamfile.h"
static void block_callback(STREAMFILE* sf, deblock_io_data* data) {
uint32_t (*read_u32)(off_t,STREAMFILE*) = data->cfg.big_endian ? read_u32be : read_u32le;
/* Blocks have base header + sub-blocks with track sub-header.
* Some blocks don't contain all channels (instead they begin next block). */
if (data->chunk_size && data->chunk_size < 0x10) {
/* padding after all sub-blocks */
data->block_size = data->chunk_size;
data->data_size = 0;
data->skip_size = 0;
data->chunk_size = 0;
}
else if (data->chunk_size) {
/* audio block sub-headers, ignore data for other tracks */
uint32_t track_size = read_u32(data->physical_offset + 0x00, sf);
uint32_t track_number = read_u32(data->physical_offset + 0x04, sf);
/* 0x08: dummy (may contain un-init'd data) */
/* 0x0c: dummy (may contain un-init'd data) */
data->block_size = 0x10 + track_size;
data->data_size = 0;
data->skip_size = 0;
if (track_number == data->cfg.track_number) {
data->data_size = track_size;
data->skip_size = 0x10;
}
data->chunk_size -= data->block_size;
}
else {
/* base block header */
uint32_t block_type = read_u32(data->physical_offset + 0x00, sf);
uint32_t block_size = read_u32(data->physical_offset + 0x04, sf);
/* 0x08: dummy */
/* 0x0c: dummy */
/* blocks are padded after all sub-blocks */
if (block_size % 0x10) {
block_size = block_size + 0x10 - (block_size % 0x10);
}
data->data_size = 0;
data->skip_size = 0;
if (block_type == 0x00 && block_size != 0) {
/* audio block */
data->block_size = 0x10;
data->chunk_size = block_size;
}
else {
/* non-audio block (or empty audio block) */
data->block_size = block_size + 0x10;
}
}
}
/* Deinterleaves MUL streams */
static STREAMFILE* setup_mul_streamfile(STREAMFILE* sf, off_t offset, int big_endian, int track_number, int track_count, const char* extension) {
STREAMFILE *new_sf = NULL;
deblock_config_t cfg = {0};
cfg.stream_start = offset;
cfg.big_endian = big_endian;
cfg.track_number = track_number;
cfg.track_count = track_count;
cfg.block_callback = block_callback;
new_sf = open_wrap_streamfile(sf);
new_sf = open_io_deblock_streamfile_f(new_sf, &cfg);
if (extension)
new_sf = open_fakename_streamfile_f(new_sf, NULL, extension);
return new_sf;
}
#endif /* _MUL_STREAMFILE_H_ */