mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 06:50:20 +01:00
vorbis: cleanup
This commit is contained in:
parent
bb185027ed
commit
1ed15ed25a
@ -54,4 +54,11 @@ int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL* stream, vorbis_custom_code
|
||||
int vorbis_custom_parse_packet_awc(VGMSTREAMCHANNEL* stream, vorbis_custom_codec_data* data);
|
||||
#endif/* VGM_USE_VORBIS */
|
||||
|
||||
/* other utils to make/parse vorbis stuff */
|
||||
int build_header_comment(uint8_t* buf, int bufsize);
|
||||
int build_header_identification(uint8_t* buf, int bufsize, vorbis_custom_config* cfg);
|
||||
void load_blocksizes(vorbis_custom_config* cfg, int blocksize_short, int blocksize_long);
|
||||
bool load_header_packet(STREAMFILE* sf, vorbis_custom_codec_data* data, uint32_t packet_size, int packet_skip, uint32_t* p_offset);
|
||||
|
||||
|
||||
#endif/*_VORBIS_CUSTOM_DECODER_H_ */
|
||||
|
93
src/coding/vorbis_custom_utils.c
Normal file
93
src/coding/vorbis_custom_utils.c
Normal file
@ -0,0 +1,93 @@
|
||||
#include "vorbis_custom_decoder.h"
|
||||
|
||||
#ifdef VGM_USE_VORBIS
|
||||
int build_header_comment(uint8_t* buf, int bufsize) {
|
||||
int bytes = 0x19;
|
||||
|
||||
if (bytes > bufsize) return 0;
|
||||
|
||||
put_u8 (buf+0x00, 0x03); /* packet_type (comments) */
|
||||
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||
put_u32le(buf+0x07, 0x09); /* vendor_length */
|
||||
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
|
||||
put_u32le(buf+0x14, 0x00); /* user_comment_list_length */
|
||||
put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
int build_header_identification(uint8_t* buf, int bufsize, vorbis_custom_config* cfg) {
|
||||
int bytes = 0x1e;
|
||||
|
||||
if (bytes > bufsize)
|
||||
return 0;
|
||||
|
||||
uint8_t blocksizes = (cfg->blocksize_0_exp << 4) | (cfg->blocksize_1_exp);
|
||||
|
||||
put_u8 (buf+0x00, 0x01); /* packet_type (id) */
|
||||
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||
put_u32le(buf+0x07, 0x00); /* vorbis_version (fixed) */
|
||||
put_u8 (buf+0x0b, cfg->channels); /* audio_channels */
|
||||
put_u32le(buf+0x0c, cfg->sample_rate); /* audio_sample_rate */
|
||||
put_u32le(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */
|
||||
put_u32le(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */
|
||||
put_u32le(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */
|
||||
put_u8 (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */
|
||||
put_u8 (buf+0x1d, 0x01); /* framing_flag (fixed) */
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
bool make_header_identification(vorbis_custom_codec_data* data, vorbis_custom_config* cfg) {
|
||||
|
||||
data->op.bytes = build_header_comment(data->buffer, data->buffer_size);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
void load_blocksizes(vorbis_custom_config* cfg, int blocksize_short, int blocksize_long) {
|
||||
uint8_t exp_blocksize_0, exp_blocksize_1;
|
||||
|
||||
/* guetto log2 for allowed blocksizes (2-exp), could be improved */
|
||||
switch(blocksize_long) {
|
||||
case 64: exp_blocksize_0 = 6; break;
|
||||
case 128: exp_blocksize_0 = 7; break;
|
||||
case 256: exp_blocksize_0 = 8; break;
|
||||
case 512: exp_blocksize_0 = 9; break;
|
||||
case 1024: exp_blocksize_0 = 10; break;
|
||||
case 2048: exp_blocksize_0 = 11; break;
|
||||
case 4096: exp_blocksize_0 = 12; break;
|
||||
case 8192: exp_blocksize_0 = 13; break;
|
||||
default: exp_blocksize_0 = 0;
|
||||
}
|
||||
switch(blocksize_short) {
|
||||
case 64: exp_blocksize_1 = 6; break;
|
||||
case 128: exp_blocksize_1 = 7; break;
|
||||
case 256: exp_blocksize_1 = 8; break;
|
||||
case 512: exp_blocksize_1 = 9; break;
|
||||
case 1024: exp_blocksize_1 = 10; break;
|
||||
case 2048: exp_blocksize_1 = 11; break;
|
||||
case 4096: exp_blocksize_1 = 12; break;
|
||||
case 8192: exp_blocksize_1 = 13; break;
|
||||
default: exp_blocksize_1 = 0;
|
||||
}
|
||||
|
||||
cfg->blocksize_0_exp = exp_blocksize_0;
|
||||
cfg->blocksize_1_exp = exp_blocksize_1;
|
||||
}
|
||||
|
||||
bool load_header_packet(STREAMFILE* sf, vorbis_custom_codec_data* data, uint32_t packet_size, int packet_skip, uint32_t* p_offset) {
|
||||
if (packet_size > data->buffer_size)
|
||||
goto fail;
|
||||
|
||||
data->op.bytes = read_streamfile(data->buffer, *p_offset + packet_skip, packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)
|
||||
goto fail;
|
||||
*p_offset += packet_skip + packet_size;
|
||||
|
||||
return true;
|
||||
fail:
|
||||
return false;
|
||||
}
|
||||
#endif/* VGM_USE_VORBIS */
|
@ -9,49 +9,35 @@
|
||||
/* **************************************************************************** */
|
||||
|
||||
/**
|
||||
* AWC removes the Ogg layer and uses 32b frame sizes for headers and 16b frame sizes for data
|
||||
* AWC uses 32b frame sizes for headers and 16b frame sizes for data,
|
||||
* with standard header packet triad.
|
||||
*/
|
||||
int vorbis_custom_setup_init_awc(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data) {
|
||||
off_t offset = data->config.header_offset;
|
||||
size_t packet_size;
|
||||
uint32_t offset = data->config.header_offset;
|
||||
uint32_t packet_size;
|
||||
|
||||
/* read 3 packets with triad (id/comment/setup), each with an AWC header */
|
||||
|
||||
/* normal identificacion packet */
|
||||
packet_size = read_u32le(offset, sf);
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer, offset + 0x04, packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)
|
||||
if (!load_header_packet(sf, data, packet_size, 0x04, &offset)) /* identificacion packet */
|
||||
goto fail;
|
||||
offset += 0x04 + packet_size;
|
||||
|
||||
/* normal comment packet */
|
||||
packet_size = read_u32le(offset, sf);
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer, offset + 0x04, packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0)
|
||||
if (!load_header_packet(sf, data, packet_size, 0x04, &offset)) /* comment packet */
|
||||
goto fail;
|
||||
offset += 0x04 + packet_size;
|
||||
|
||||
/* normal setup packet */
|
||||
packet_size = read_u32le(offset, sf);
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer, offset + 0x04, packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)
|
||||
if (!load_header_packet(sf, data, packet_size, 0x04, &offset)) /* setup packet */
|
||||
goto fail;
|
||||
offset += 0x04 + packet_size;
|
||||
|
||||
/* data starts separate */
|
||||
/* data starts separate from headers */
|
||||
data->config.data_start_offset = start_offset;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* as AWC was coded by wackos, frames are forced to fit 0x800 chunks and rest is padded, in both sfx and music/blocked modes
|
||||
* (ex. read frame until 0x7A0 + next frame is size 0x140 > pads 0x60 and last goes to next chunk) */
|
||||
* (ex. read frame until 0x7A0 + next frame is size 0x140 > pads 0x60 and last goes to next chunk) */
|
||||
static inline off_t find_padding_awc(off_t offset, vorbis_custom_codec_data* data) {
|
||||
offset = offset - data->config.data_start_offset;
|
||||
|
||||
@ -61,7 +47,7 @@ static inline off_t find_padding_awc(off_t offset, vorbis_custom_codec_data* dat
|
||||
int vorbis_custom_parse_packet_awc(VGMSTREAMCHANNEL* stream, vorbis_custom_codec_data* data) {
|
||||
size_t bytes;
|
||||
|
||||
/* get next packet size from the AWC 16b header, except between chunks */
|
||||
/* get next packet size, except between chunks */
|
||||
data->op.bytes = read_u16le(stream->offset, stream->streamfile);
|
||||
if (data->op.bytes == 0) { // || (stream->offset - start & 0x800) < 0x01 //todo could pad near block end?
|
||||
stream->offset += find_padding_awc(stream->offset, data);
|
||||
@ -78,7 +64,6 @@ int vorbis_custom_parse_packet_awc(VGMSTREAMCHANNEL* stream, vorbis_custom_codec
|
||||
if (bytes != data->op.bytes) goto fail; /* wrong packet? */
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
@ -13,8 +13,6 @@
|
||||
/* DEFS */
|
||||
/* **************************************************************************** */
|
||||
|
||||
static int build_header_identification(uint8_t* buf, size_t bufsize, int channels, int sample_rate, int blocksize_short, int blocksize_long);
|
||||
static int build_header_comment(uint8_t* buf, size_t bufsize);
|
||||
static int build_header_setup(uint8_t* buf, size_t bufsize, uint32_t setup_id, STREAMFILE* sf);
|
||||
|
||||
#if !(FSB_VORBIS_USE_PRECOMPILED_FVS)
|
||||
@ -36,20 +34,21 @@ static int load_fvs_array(uint8_t* buf, size_t bufsize, uint32_t setup_id, STREA
|
||||
int vorbis_custom_setup_init_fsb(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data) {
|
||||
vorbis_custom_config cfg = data->config;
|
||||
|
||||
data->op.bytes = build_header_identification(data->buffer, data->buffer_size, cfg.channels, cfg.sample_rate, 256, 2048); /* FSB default block sizes */
|
||||
if (!data->op.bytes) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||
load_blocksizes(&cfg, 256, 2048); /* FSB default */
|
||||
|
||||
data->op.bytes = build_header_identification(data->buffer, data->buffer_size, &cfg);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) /* identification packet */
|
||||
goto fail;
|
||||
|
||||
data->op.bytes = build_header_comment(data->buffer, data->buffer_size);
|
||||
if (!data->op.bytes) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) /* comment packet */
|
||||
goto fail;
|
||||
|
||||
data->op.bytes = build_header_setup(data->buffer, data->buffer_size, cfg.setup_id, sf);
|
||||
if (!data->op.bytes) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) /* setup packet */
|
||||
goto fail;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
@ -78,66 +77,6 @@ fail:
|
||||
/* INTERNAL HELPERS */
|
||||
/* **************************************************************************** */
|
||||
|
||||
static int build_header_identification(uint8_t* buf, size_t bufsize, int channels, int sample_rate, int blocksize_short, int blocksize_long) {
|
||||
int bytes = 0x1e;
|
||||
uint8_t blocksizes, exp_blocksize_0, exp_blocksize_1;
|
||||
|
||||
if (bytes > bufsize) return 0;
|
||||
|
||||
/* guetto log2 for allowed blocksizes (2-exp), could be improved */
|
||||
switch(blocksize_long) {
|
||||
case 64: exp_blocksize_0 = 6; break;
|
||||
case 128: exp_blocksize_0 = 7; break;
|
||||
case 256: exp_blocksize_0 = 8; break;
|
||||
case 512: exp_blocksize_0 = 9; break;
|
||||
case 1024: exp_blocksize_0 = 10; break;
|
||||
case 2048: exp_blocksize_0 = 11; break;
|
||||
case 4096: exp_blocksize_0 = 12; break;
|
||||
case 8192: exp_blocksize_0 = 13; break;
|
||||
default: return 0;
|
||||
}
|
||||
switch(blocksize_short) {
|
||||
case 64: exp_blocksize_1 = 6; break;
|
||||
case 128: exp_blocksize_1 = 7; break;
|
||||
case 256: exp_blocksize_1 = 8; break;
|
||||
case 512: exp_blocksize_1 = 9; break;
|
||||
case 1024: exp_blocksize_1 = 10; break;
|
||||
case 2048: exp_blocksize_1 = 11; break;
|
||||
case 4096: exp_blocksize_1 = 12; break;
|
||||
case 8192: exp_blocksize_1 = 13; break;
|
||||
default: return 0;
|
||||
}
|
||||
blocksizes = (exp_blocksize_0 << 4) | (exp_blocksize_1);
|
||||
|
||||
put_u8 (buf+0x00, 0x01); /* packet_type (id) */
|
||||
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||
put_u32le(buf+0x07, 0x00); /* vorbis_version (fixed) */
|
||||
put_u8 (buf+0x0b, channels); /* audio_channels */
|
||||
put_s32le(buf+0x0c, sample_rate); /* audio_sample_rate */
|
||||
put_u32le(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */
|
||||
put_u32le(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */
|
||||
put_u32le(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */
|
||||
put_u8 (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */
|
||||
put_u8 (buf+0x1d, 0x01); /* framing_flag (fixed) */
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int build_header_comment(uint8_t* buf, size_t bufsize) {
|
||||
int bytes = 0x19;
|
||||
|
||||
if (bytes > bufsize) return 0;
|
||||
|
||||
put_u8 (buf+0x00, 0x03); /* packet_type (comments) */
|
||||
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||
put_u32le(buf+0x07, 0x09); /* vendor_length */
|
||||
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
|
||||
put_u32le(buf+0x14, 0x00); /* user_comment_list_length */
|
||||
put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static int build_header_setup(uint8_t* buf, size_t bufsize, uint32_t setup_id, STREAMFILE* sf) {
|
||||
int bytes;
|
||||
|
||||
|
@ -9,41 +9,29 @@
|
||||
/* **************************************************************************** */
|
||||
|
||||
/**
|
||||
* OGL removes the Ogg layer and uses 16b packet headers, that have the size of the next packet, but
|
||||
* the lower 2b need to be removed (usually 00 but 01 for the id packet, not sure about the meaning).
|
||||
* OGL uses 16b packet headers (14b size + 2b flags, usually 00 but 01 for the id packet),
|
||||
* with standard header packet triad.
|
||||
*/
|
||||
int vorbis_custom_setup_init_ogl(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data) {
|
||||
off_t offset = start_offset;
|
||||
size_t packet_size;
|
||||
uint32_t offset = start_offset;
|
||||
uint32_t packet_size;
|
||||
|
||||
/* read 3 packets with triad (id/comment/setup), each with an OGL header */
|
||||
packet_size = read_u16le(offset, sf) >> 2;
|
||||
if (!load_header_packet(sf, data, packet_size, 0x02, &offset)) /* identificacion packet */
|
||||
goto fail;
|
||||
|
||||
/* normal identificacion packet */
|
||||
packet_size = (uint16_t)read_16bitLE(offset, sf) >> 2;
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset+2,packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||
offset += 2+packet_size;
|
||||
packet_size = read_u16le(offset, sf) >> 2;
|
||||
if (!load_header_packet(sf, data, packet_size, 0x02, &offset)) /* comment packet */
|
||||
goto fail;
|
||||
|
||||
/* normal comment packet */
|
||||
packet_size = (uint16_t)read_16bitLE(offset, sf) >> 2;
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset+2,packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||
offset += 2+packet_size;
|
||||
|
||||
/* normal setup packet */
|
||||
packet_size = (uint16_t)read_16bitLE(offset, sf) >> 2;
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset+2,packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||
offset += 2+packet_size;
|
||||
packet_size = read_u16le(offset, sf) >> 2;
|
||||
if (!load_header_packet(sf, data, packet_size, 0x02, &offset)) /* setup packet */
|
||||
goto fail;
|
||||
|
||||
/* data starts after triad */
|
||||
data->config.data_start_offset = offset;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
@ -52,18 +40,17 @@ fail:
|
||||
int vorbis_custom_parse_packet_ogl(VGMSTREAMCHANNEL* stream, vorbis_custom_codec_data* data) {
|
||||
size_t bytes;
|
||||
|
||||
/* get next packet size from the OGL 16b header (upper 14b) */
|
||||
data->op.bytes = (uint16_t)read_16bitLE(stream->offset, stream->streamfile) >> 2;
|
||||
/* get next packet size */
|
||||
data->op.bytes = read_u16le(stream->offset, stream->streamfile) >> 2;
|
||||
stream->offset += 2;
|
||||
if (data->op.bytes == 0 || data->op.bytes == 0xFFFF || data->op.bytes > data->buffer_size) goto fail; /* EOF or end padding */
|
||||
|
||||
/* read raw block */
|
||||
bytes = read_streamfile(data->buffer,stream->offset, data->op.bytes,stream->streamfile);
|
||||
bytes = read_streamfile(data->buffer, stream->offset, data->op.bytes, stream->streamfile);
|
||||
stream->offset += data->op.bytes;
|
||||
if (bytes != data->op.bytes) goto fail; /* wrong packet? */
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
/* DEFS */
|
||||
/* **************************************************************************** */
|
||||
|
||||
static int get_page_info(STREAMFILE* sf, off_t page_offset, off_t* p_packet_offset, size_t* p_packet_size, int* p_page_packets, int target_packet);
|
||||
static bool get_page_info(STREAMFILE* sf, off_t page_offset, off_t* p_packet_offset, size_t* p_packet_size, int* p_page_packets, int target_packet);
|
||||
static int build_header(uint8_t* buf, size_t bufsize, STREAMFILE* sf, off_t packet_offset, size_t packet_size);
|
||||
|
||||
|
||||
@ -19,7 +19,7 @@ static int build_header(uint8_t* buf, size_t bufsize, STREAMFILE* sf, off_t pack
|
||||
* SK just replaces the id 0x4F676753 ("OggS") by 0x11534B10 (\11"SK"\10), and the word "vorbis" by "SK"
|
||||
* in init packets (for obfuscation, surely). So essentially we are parsing regular Ogg here.
|
||||
*
|
||||
* A simpler way to implement this would be in ogg_vorbis_file with read callbacks (pretend this is proof of concept).
|
||||
* A simpler way to implement this may be using ogg_vorbis_file with read callbacks (pretend this is proof of concept).
|
||||
*/
|
||||
int vorbis_custom_setup_init_sk(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data) {
|
||||
off_t offset = start_offset;
|
||||
@ -27,7 +27,7 @@ int vorbis_custom_setup_init_sk(STREAMFILE* sf, off_t start_offset, vorbis_custo
|
||||
size_t id_size = 0, comment_size = 0, setup_size = 0;
|
||||
int page_packets;
|
||||
|
||||
/* rebuild header packets, they are standard except the "vorbis" keyword is replaced by "SK" */
|
||||
/* standard header packets except the "vorbis" keyword is replaced by "SK" */
|
||||
|
||||
/* first page has the id packet */
|
||||
if (!get_page_info(sf, offset, &id_offset, &id_size, &page_packets, 0)) goto fail;
|
||||
@ -69,12 +69,12 @@ int vorbis_custom_parse_packet_sk(VGMSTREAMCHANNEL* stream, vorbis_custom_codec_
|
||||
off_t packet_offset = 0;
|
||||
size_t packet_size = 0;
|
||||
int page_packets;
|
||||
int res;
|
||||
bool ok;
|
||||
|
||||
/* read OggS/SK page and get current packet */
|
||||
res = get_page_info(stream->streamfile, stream->offset, &packet_offset, &packet_size, &page_packets, data->current_packet);
|
||||
ok = get_page_info(stream->streamfile, stream->offset, &packet_offset, &packet_size, &page_packets, data->current_packet);
|
||||
data->current_packet++;
|
||||
if (!res || packet_size > data->buffer_size) goto fail;
|
||||
if (!ok || packet_size > data->buffer_size) goto fail;
|
||||
|
||||
/* read raw block */
|
||||
data->op.bytes = read_streamfile(data->buffer, packet_offset, packet_size, stream->streamfile);
|
||||
@ -113,7 +113,7 @@ fail:
|
||||
* 0x--(n): data
|
||||
* Reference: https://xiph.org/ogg/doc/framing.html
|
||||
*/
|
||||
static int get_page_info(STREAMFILE* sf, off_t page_offset, off_t* p_packet_offset, size_t* p_packet_size, int* p_page_packets, int target_packet) {
|
||||
static bool get_page_info(STREAMFILE* sf, off_t page_offset, off_t* p_packet_offset, size_t* p_packet_size, int* p_page_packets, int target_packet) {
|
||||
off_t table_offset, current_packet_offset, target_packet_offset = 0;
|
||||
size_t total_packets_size = 0, current_packet_size = 0, target_packet_size = 0;
|
||||
int page_packets = 0;
|
||||
@ -121,18 +121,18 @@ static int get_page_info(STREAMFILE* sf, off_t page_offset, off_t* p_packet_offs
|
||||
int i;
|
||||
|
||||
|
||||
if (read_32bitBE(page_offset+0x00, sf) != 0x11534B10) /* \11"SK"\10 */
|
||||
if (read_u32be(page_offset+0x00, sf) != 0x11534B10) /* \11"SK"\10 */
|
||||
goto fail; /* not a valid page */
|
||||
/* No point on validating other stuff, but they look legal enough (CRC too it seems) */
|
||||
|
||||
segments = (uint8_t)read_8bit(page_offset+0x1a, sf);
|
||||
segments = read_u8(page_offset+0x1a, sf);
|
||||
|
||||
table_offset = page_offset + 0x1b;
|
||||
current_packet_offset = page_offset + 0x1b + segments; /* first packet starts after segments */
|
||||
|
||||
/* process segments */
|
||||
for (i = 0; i < segments; i++) {
|
||||
uint8_t segment_size = (uint8_t)read_8bit(table_offset, sf);
|
||||
uint8_t segment_size = read_u8(table_offset, sf);
|
||||
total_packets_size += segment_size;
|
||||
current_packet_size += segment_size;
|
||||
table_offset += 0x01;
|
||||
@ -169,19 +169,21 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* rebuild a "SK" header packet to a "vorbis" one */
|
||||
/* rebuild a custom header packet into a "vorbis" one */
|
||||
static int build_header(uint8_t* buf, size_t bufsize, STREAMFILE* sf, off_t packet_offset, size_t packet_size) {
|
||||
int bytes;
|
||||
int vorbis_word_size = 0x02; /* "SK" */
|
||||
|
||||
if (0x07+packet_size-0x03 > bufsize) return 0;
|
||||
|
||||
put_u8(buf+0x00, read_8bit(packet_offset,sf)); /* packet_type */
|
||||
memcpy(buf+0x01, "vorbis", 6); /* id */
|
||||
bytes = read_streamfile(buf+0x07,packet_offset+0x03, packet_size-0x03,sf); /* copy rest (all except id+"SK") */
|
||||
if (packet_size-0x03 != bytes)
|
||||
if (0x07 + packet_size - 0x01 - vorbis_word_size > bufsize)
|
||||
return 0;
|
||||
|
||||
return 0x07+packet_size-0x03;
|
||||
put_u8(buf+0x00, read_u8(packet_offset,sf)); /* packet_type */
|
||||
memcpy(buf+0x01, "vorbis", 6); /* id */
|
||||
bytes = read_streamfile(buf+0x07, packet_offset + 0x01 + vorbis_word_size, packet_size - 0x01 - vorbis_word_size, sf); /* copy rest (all except id+"(vorbis word)") */
|
||||
if (packet_size - 0x03 != bytes)
|
||||
return 0;
|
||||
|
||||
return 0x07 + packet_size - 0x03;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -10,8 +10,7 @@
|
||||
/* DEFS */
|
||||
/* **************************************************************************** */
|
||||
|
||||
static int get_packet_header(STREAMFILE* sf, off_t* offset, size_t* size);
|
||||
static int build_header_comment(uint8_t* buf, size_t bufsize);
|
||||
static int get_packet_header(STREAMFILE* sf, uint32_t* offset, uint32_t* size);
|
||||
|
||||
|
||||
/* **************************************************************************** */
|
||||
@ -20,36 +19,27 @@ static int build_header_comment(uint8_t* buf, size_t bufsize);
|
||||
|
||||
/**
|
||||
* VID1 removes the Ogg layer and uses a block layout with custom packet headers.
|
||||
* Has standard id/setup packets but removes comment packet.
|
||||
*
|
||||
* Info from hcs's vid1_2ogg: https://github.com/hcs64/vgm_ripping/tree/master/demux/vid1_2ogg
|
||||
*/
|
||||
int vorbis_custom_setup_init_vid1(STREAMFILE* sf, off_t start_offset, vorbis_custom_codec_data* data) {
|
||||
off_t offset = start_offset;
|
||||
size_t packet_size = 0;
|
||||
uint32_t offset = start_offset;
|
||||
uint32_t packet_size = 0;
|
||||
|
||||
/* read header packets (id/setup), each with an VID1 header */
|
||||
|
||||
/* normal identificacion packet */
|
||||
get_packet_header(sf, &offset, &packet_size);
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset,packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||
offset += packet_size;
|
||||
if (!load_header_packet(sf, data, packet_size, 0x00, &offset)) /* identificacion packet */
|
||||
goto fail;
|
||||
|
||||
/* generate comment packet */
|
||||
data->op.bytes = build_header_comment(data->buffer, data->buffer_size);
|
||||
if (!data->op.bytes) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)/* comment packet */
|
||||
goto fail;
|
||||
|
||||
/* normal setup packet */
|
||||
get_packet_header(sf, &offset, &packet_size);
|
||||
if (packet_size > data->buffer_size) goto fail;
|
||||
data->op.bytes = read_streamfile(data->buffer,offset,packet_size, sf);
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||
offset += packet_size;
|
||||
if (!load_header_packet(sf, data, packet_size, 0x00, &offset)) /* setup packet */
|
||||
goto fail;
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
@ -60,23 +50,23 @@ int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL* stream, vorbis_custom_code
|
||||
|
||||
|
||||
/* test block start */
|
||||
if (read_32bitBE(stream->offset + 0x00,stream->streamfile) == 0x4652414D) { /* "FRAM" */
|
||||
if (is_id32be(stream->offset + 0x00,stream->streamfile, "FRAM")) {
|
||||
stream->offset += 0x20;
|
||||
|
||||
if (read_32bitBE(stream->offset + 0x00,stream->streamfile) == 0x56494444) { /* "VIDD"*/
|
||||
stream->offset += read_32bitBE(stream->offset + 0x04, stream->streamfile);
|
||||
if (is_id32be(stream->offset + 0x00,stream->streamfile, "VIDD")) {
|
||||
stream->offset += read_u32be(stream->offset + 0x04, stream->streamfile);
|
||||
}
|
||||
|
||||
if (read_32bitBE(stream->offset + 0x00,stream->streamfile) == 0x41554444) { /* "AUDD" */
|
||||
if (is_id32be(stream->offset + 0x00,stream->streamfile, "AUDD")) {
|
||||
data->block_offset = stream->offset;
|
||||
data->block_size = read_32bitBE(stream->offset + 0x0c,stream->streamfile);
|
||||
data->block_size = read_u32be(stream->offset + 0x0c,stream->streamfile);
|
||||
stream->offset += 0x14; /* actual start, rest is chunk sizes and maybe granule info */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* get packet info the VID1 header */
|
||||
get_packet_header(stream->streamfile, &stream->offset, (size_t*)&data->op.bytes);
|
||||
get_packet_header(stream->streamfile, (uint32_t*)&stream->offset, (uint32_t*)&data->op.bytes);
|
||||
if (data->op.bytes == 0 || data->op.bytes > data->buffer_size) goto fail; /* EOF or end padding */
|
||||
|
||||
/* read raw block */
|
||||
@ -88,7 +78,7 @@ int vorbis_custom_parse_packet_vid1(VGMSTREAMCHANNEL* stream, vorbis_custom_code
|
||||
|
||||
/* test block end (weird size calc but seems ok) */
|
||||
if ((stream->offset - (data->block_offset + 0x14)) >= (data->block_size - 0x06)) {
|
||||
stream->offset = data->block_offset + read_32bitBE(data->block_offset + 0x04,stream->streamfile);
|
||||
stream->offset = data->block_offset + read_u32be(data->block_offset + 0x04,stream->streamfile);
|
||||
}
|
||||
|
||||
return 1;
|
||||
@ -102,23 +92,8 @@ fail:
|
||||
/* INTERNAL HELPERS */
|
||||
/* **************************************************************************** */
|
||||
|
||||
static int build_header_comment(uint8_t* buf, size_t bufsize) {
|
||||
int bytes = 0x19;
|
||||
|
||||
if (bytes > bufsize) return 0;
|
||||
|
||||
put_u8 (buf+0x00, 0x03); /* packet_type (comments) */
|
||||
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||
put_u32le(buf+0x07, 0x09); /* vendor_length */
|
||||
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
|
||||
put_u32le(buf+0x14, 0x00); /* user_comment_list_length */
|
||||
put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
/* read header in Vorbis bitpacking format */
|
||||
static int get_packet_header(STREAMFILE* sf, off_t* offset, size_t* size) {
|
||||
static int get_packet_header(STREAMFILE* sf, uint32_t* offset, uint32_t* size) {
|
||||
uint8_t ibuf[0x04]; /* header buffer */
|
||||
size_t ibufsize = 0x04; /* header ~max */
|
||||
bitstream_t ib = {0};
|
||||
|
@ -23,9 +23,6 @@ typedef struct {
|
||||
uint8_t inxt[0x01];
|
||||
} wpacket_t;
|
||||
|
||||
static size_t build_header_identification(uint8_t* buf, size_t bufsize, vorbis_custom_config* cfg);
|
||||
static size_t build_header_comment(uint8_t* buf, size_t bufsize);
|
||||
|
||||
static int read_packet(wpacket_t* wp, uint8_t* ibuf, size_t ibufsize, STREAMFILE* sf, off_t offset, vorbis_custom_codec_data* data, int is_setup);
|
||||
static size_t rebuild_packet(uint8_t* obuf, size_t obufsize, wpacket_t* wp, STREAMFILE* sf, off_t offset, vorbis_custom_codec_data* data);
|
||||
static size_t rebuild_setup(uint8_t* obuf, size_t obufsize, wpacket_t* wp, STREAMFILE* sf, off_t offset, vorbis_custom_codec_data* data);
|
||||
@ -64,44 +61,43 @@ int vorbis_custom_setup_init_wwise(STREAMFILE* sf, off_t start_offset, vorbis_cu
|
||||
ok = read_packet(&wp, data->buffer, data->buffer_size, sf, offset, data, 1);
|
||||
if (!ok) goto fail;
|
||||
data->op.bytes = wp.packet_size;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)
|
||||
goto fail;
|
||||
offset += wp.header_size + wp.packet_size;
|
||||
|
||||
/* normal comment packet */
|
||||
ok = read_packet(&wp, data->buffer, data->buffer_size, sf, offset, data, 1);
|
||||
if (!ok) goto fail;
|
||||
data->op.bytes = wp.packet_size;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)
|
||||
goto fail;
|
||||
offset += wp.header_size + wp.packet_size;
|
||||
|
||||
/* normal setup packet */
|
||||
ok = read_packet(&wp, data->buffer, data->buffer_size, sf, offset, data, 1);
|
||||
if (!ok) goto fail;
|
||||
data->op.bytes = wp.packet_size;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0)
|
||||
goto fail;
|
||||
offset += wp.header_size + wp.packet_size;
|
||||
}
|
||||
else {
|
||||
/* rebuild headers */
|
||||
|
||||
/* new identificacion packet */
|
||||
data->op.bytes = build_header_identification(data->buffer, data->buffer_size, &data->config);
|
||||
if (!data->op.bytes) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse identification header */
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) /* identification packet */
|
||||
goto fail;
|
||||
|
||||
/* new comment packet */
|
||||
data->op.bytes = build_header_comment(data->buffer, data->buffer_size);
|
||||
if (!data->op.bytes) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) goto fail; /* parse comment header */
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) !=0 ) /* comment packet */
|
||||
goto fail;
|
||||
|
||||
/* rebuild setup packet */
|
||||
data->op.bytes = rebuild_setup(data->buffer, data->buffer_size, &wp, sf, start_offset, data);
|
||||
if (!data->op.bytes) goto fail;
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) goto fail; /* parse setup header */
|
||||
if (vorbis_synthesis_headerin(&data->vi, &data->vc, &data->op) != 0) /* setup packet */
|
||||
goto fail;
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
fail:
|
||||
return 0;
|
||||
}
|
||||
@ -259,44 +255,6 @@ fail:
|
||||
return 0;
|
||||
}
|
||||
|
||||
static size_t build_header_identification(uint8_t* buf, size_t bufsize, vorbis_custom_config* cfg) {
|
||||
size_t bytes = 0x1e;
|
||||
uint8_t blocksizes;
|
||||
|
||||
if (bytes > bufsize) return 0;
|
||||
|
||||
blocksizes = (cfg->blocksize_0_exp << 4) | (cfg->blocksize_1_exp);
|
||||
|
||||
put_u8 (buf+0x00, 0x01); /* packet_type (id) */
|
||||
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||
put_u32le(buf+0x07, 0x00); /* vorbis_version (fixed) */
|
||||
put_u8 (buf+0x0b, cfg->channels); /* audio_channels */
|
||||
put_u32le(buf+0x0c, cfg->sample_rate);/* audio_sample_rate */
|
||||
put_u32le(buf+0x10, 0x00); /* bitrate_maximum (optional hint) */
|
||||
put_u32le(buf+0x14, 0x00); /* bitrate_nominal (optional hint) */
|
||||
put_u32le(buf+0x18, 0x00); /* bitrate_minimum (optional hint) */
|
||||
put_u8 (buf+0x1c, blocksizes); /* blocksize_0 + blocksize_1 nibbles */
|
||||
put_u8 (buf+0x1d, 0x01); /* framing_flag (fixed) */
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
static size_t build_header_comment(uint8_t* buf, size_t bufsize) {
|
||||
size_t bytes = 0x19;
|
||||
|
||||
if (bytes > bufsize) return 0;
|
||||
|
||||
put_u8 (buf+0x00, 0x03); /* packet_type (comments) */
|
||||
memcpy (buf+0x01, "vorbis", 6); /* id */
|
||||
put_u32le(buf+0x07, 0x09); /* vendor_length */
|
||||
memcpy (buf+0x0b, "vgmstream", 9); /* vendor_string */
|
||||
put_u32le(buf+0x14, 0x00); /* user_comment_list_length */
|
||||
put_u8 (buf+0x18, 0x01); /* framing_flag (fixed) */
|
||||
|
||||
return bytes;
|
||||
}
|
||||
|
||||
|
||||
/* copy packet bytes, where input/output bufs may not be byte-aligned (so no memcpy) */
|
||||
static int copy_bytes(bitstream_t* ob, bitstream_t* ib, uint32_t bytes) {
|
||||
int i;
|
||||
|
@ -279,6 +279,7 @@
|
||||
<ClCompile Include="coding\ubi_adpcm_decoder.c" />
|
||||
<ClCompile Include="coding\vadpcm_decoder.c" />
|
||||
<ClCompile Include="coding\vorbis_custom_decoder.c" />
|
||||
<ClCompile Include="coding\vorbis_custom_utils.c" />
|
||||
<ClCompile Include="coding\vorbis_custom_utils_awc.c" />
|
||||
<ClCompile Include="coding\vorbis_custom_utils_fsb.c" />
|
||||
<ClCompile Include="coding\vorbis_custom_utils_ogl.c" />
|
||||
|
@ -658,6 +658,9 @@
|
||||
<ClCompile Include="coding\vorbis_custom_decoder.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\vorbis_custom_utils.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="coding\vorbis_custom_utils_awc.c">
|
||||
<Filter>coding\Source Files</Filter>
|
||||
</ClCompile>
|
||||
|
Loading…
Reference in New Issue
Block a user