Move bitstream reader to coding_utils

This commit is contained in:
bnnm 2017-12-09 17:06:21 +01:00
parent ecf01351cb
commit 765af1994a
7 changed files with 200 additions and 221 deletions

View File

@ -276,4 +276,19 @@ void xma2_parse_xma2_chunk(STREAMFILE *streamFile, off_t chunk_offset, int * cha
size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align); size_t atrac3_bytes_to_samples(size_t bytes, int full_block_align);
size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align); size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align);
/* An internal struct to pass around and simulate a bitstream. */
typedef enum { BITSTREAM_MSF, BITSTREAM_VORBIS } vgm_bitstream_t;
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
off_t info_offset; /* for logging */
vgm_bitstream_t mode; /* read/write modes */
} vgm_bitstream;
int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value);
int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value);
#endif /*_CODING_H*/ #endif /*_CODING_H*/

View File

@ -835,3 +835,149 @@ size_t atrac3plus_bytes_to_samples(size_t bytes, int full_block_align) {
* so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */ * so (full_block_align / channels) DOESN'T give the size of a single channel (common in ATRAC3plus) */
return (bytes / full_block_align) * 2048; return (bytes / full_block_align) * 2048;
} }
/* ******************************************** */
/* BITSTREAM */
/* ******************************************** */
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
static int r_bits_vorbis(vgm_bitstream * ib, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = ib->b_off / 8; /* byte offset */
pos = ib->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
bit_val = (1U << i); /* bit to set in value */
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ib->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/
static int w_bits_vorbis(vgm_bitstream * ob, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail;
off = ob->b_off / 8; /* byte offset */
pos = ob->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << i); /* bit check for value */
bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
ob->buf[off] |= bit_buf; /* set bit */
else
ob->buf[off] &= ~bit_buf; /* unset bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ob->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */
static int r_bits_msf(vgm_bitstream * ib, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = ib->b_off / 8; /* byte offset */
pos = ib->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */
bit_val = (1U << (num_bits-1-i)); /* bit to set in value */
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
ib->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */
static int w_bits_msf(vgm_bitstream * ob, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ob->b_off + num_bits > ob->bufsize*8) goto fail;
off = ob->b_off / 8; /* byte offset */
pos = ob->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << (num_bits-1-i)); /* bit check for value */
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
ob->buf[off] |= bit_buf; /* set bit */
else
ob->buf[off] &= ~bit_buf; /* unset bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
ob->b_off += num_bits;
return 1;
fail:
return 0;
}
int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value) {
if (ib->mode == BITSTREAM_VORBIS)
return r_bits_vorbis(ib,num_bits,value);
else
return r_bits_msf(ib,num_bits,value);
}
int w_bits(vgm_bitstream * ob, int num_bits, uint32_t value) {
if (ob->mode == BITSTREAM_VORBIS)
return w_bits_vorbis(ob,num_bits,value);
else
return w_bits_msf(ob,num_bits,value);
}

View File

@ -25,14 +25,6 @@
#define EALAYER3_MAX_GRANULES 2 #define EALAYER3_MAX_GRANULES 2
#define EALAYER3_MAX_CHANNELS 2 #define EALAYER3_MAX_CHANNELS 2
/* helper to simulate a bitstream */
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
off_t info_offset; /* for logs */
} ealayer3_bitstream;
/* parsed info from a single EALayer3 frame */ /* parsed info from a single EALayer3 frame */
typedef struct { typedef struct {
/* EALayer3 v1 header */ /* EALayer3 v1 header */
@ -81,18 +73,14 @@ typedef struct {
} ealayer3_frame_info; } ealayer3_frame_info;
static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf); static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b); static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b);
static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf); static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf); static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf);
static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os); static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os);
static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf); static int ealayer3_write_pcm_block(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, ealayer3_frame_info * eaf);
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start); static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start);
static int r_bits(ealayer3_bitstream * iw, int num_bits, uint32_t * value);
static int w_bits(ealayer3_bitstream * ow, int num_bits, uint32_t value);
/* **************************************************************************** */ /* **************************************************************************** */
/* EXTERNAL API */ /* EXTERNAL API */
/* **************************************************************************** */ /* **************************************************************************** */
@ -101,7 +89,7 @@ static int w_bits(ealayer3_bitstream * ow, int num_bits, uint32_t value);
int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type) { int mpeg_custom_setup_init_ealayer3(STREAMFILE *streamFile, off_t start_offset, mpeg_codec_data *data, coding_t *coding_type) {
int ok; int ok;
ealayer3_frame_info eaf; ealayer3_frame_info eaf;
ealayer3_bitstream is = {0}; vgm_bitstream is = {0};
uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE]; uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE];
//;VGM_LOG("init at %lx\n", start_offset); //;VGM_LOG("init at %lx\n", start_offset);
@ -135,7 +123,7 @@ int mpeg_custom_parse_frame_ealayer3(VGMSTREAMCHANNEL *stream, mpeg_codec_data *
off_t info_offset = stream->offset; off_t info_offset = stream->offset;
ealayer3_frame_info eaf_0, eaf_1; ealayer3_frame_info eaf_0, eaf_1;
ealayer3_bitstream is_0 = {0}, is_1 = {0}, os = {0}; vgm_bitstream is_0 = {0}, is_1 = {0}, os = {0};
uint8_t ibuf_0[EALAYER3_EA_FRAME_BUFFER_SIZE], ibuf_1[EALAYER3_EA_FRAME_BUFFER_SIZE]; uint8_t ibuf_0[EALAYER3_EA_FRAME_BUFFER_SIZE], ibuf_1[EALAYER3_EA_FRAME_BUFFER_SIZE];
/* read first frame/granule, or PCM-only frame (found alone at the end of SCHl streams) */ /* read first frame/granule, or PCM-only frame (found alone at the end of SCHl streams) */
@ -213,7 +201,7 @@ fail:
/* INTERNAL HELPERS */ /* INTERNAL HELPERS */
/* **************************************************************************** */ /* **************************************************************************** */
static int ealayer3_parse_frame(mpeg_codec_data *data, ealayer3_bitstream *is, ealayer3_frame_info * eaf) { static int ealayer3_parse_frame(mpeg_codec_data *data, vgm_bitstream *is, ealayer3_frame_info * eaf) {
int ok; int ok;
/* make sure as there is re-parsing in loops */ /* make sure as there is re-parsing in loops */
@ -235,7 +223,7 @@ fail:
/* read V1"a" (in SCHl) and V1"b" (in SNS) EALayer3 frame */ /* read V1"a" (in SCHl) and V1"b" (in SNS) EALayer3 frame */
static int ealayer3_parse_frame_v1(ealayer3_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b) { static int ealayer3_parse_frame_v1(vgm_bitstream *is, ealayer3_frame_info * eaf, int channels_per_frame, int is_v1b) {
int ok; int ok;
/* read EA-frame V1 header */ /* read EA-frame V1 header */
@ -282,7 +270,7 @@ fail:
/* read V2"PCM" and V2"Spike" EALayer3 frame (exactly the same but V2P seems to have bigger /* read V2"PCM" and V2"Spike" EALayer3 frame (exactly the same but V2P seems to have bigger
* PCM blocks and maybe smaller frames) */ * PCM blocks and maybe smaller frames) */
static int ealayer3_parse_frame_v2(ealayer3_bitstream *is, ealayer3_frame_info * eaf) { static int ealayer3_parse_frame_v2(vgm_bitstream *is, ealayer3_frame_info * eaf) {
int ok; int ok;
/* read EA-frame V2 header */ /* read EA-frame V2 header */
@ -328,7 +316,7 @@ fail:
/* parses an EALayer3 frame (common part) */ /* parses an EALayer3 frame (common part) */
static int ealayer3_parse_frame_common(ealayer3_bitstream *is, ealayer3_frame_info * eaf) { static int ealayer3_parse_frame_common(vgm_bitstream *is, ealayer3_frame_info * eaf) {
/* index tables */ /* index tables */
static const int versions[4] = { /* MPEG 2.5 */ 3, /* reserved */ -1, /* MPEG 2 */ 2, /* MPEG 1 */ 1 }; static const int versions[4] = { /* MPEG 2.5 */ 3, /* reserved */ -1, /* MPEG 2 */ 2, /* MPEG 1 */ 1 };
static const int sample_rates[4][4] = { /* [version_index][sample rate index] */ static const int sample_rates[4][4] = { /* [version_index][sample rate index] */
@ -412,7 +400,7 @@ fail:
/* converts an EALAYER3 frame to a standard MPEG frame from pre-parsed info */ /* converts an EALAYER3 frame to a standard MPEG frame from pre-parsed info */
static int ealayer3_rebuild_mpeg_frame(ealayer3_bitstream* is_0, ealayer3_frame_info* eaf_0, ealayer3_bitstream* is_1, ealayer3_frame_info* eaf_1, ealayer3_bitstream* os) { static int ealayer3_rebuild_mpeg_frame(vgm_bitstream* is_0, ealayer3_frame_info* eaf_0, vgm_bitstream* is_1, ealayer3_frame_info* eaf_1, vgm_bitstream* os) {
uint32_t c = 0; uint32_t c = 0;
int i,j; int i,j;
int expected_bitrate_index, expected_frame_size; int expected_bitrate_index, expected_frame_size;
@ -663,7 +651,7 @@ fail:
static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start) { static int ealayer3_skip_data(VGMSTREAMCHANNEL *stream, mpeg_codec_data *data, int num_stream, int at_start) {
int ok, i; int ok, i;
ealayer3_frame_info eaf; ealayer3_frame_info eaf;
ealayer3_bitstream is = {0}; vgm_bitstream is = {0};
uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE]; uint8_t ibuf[EALAYER3_EA_FRAME_BUFFER_SIZE];
int skips = at_start ? num_stream : data->streams_size - 1 - num_stream; int skips = at_start ? num_stream : data->streams_size - 1 - num_stream;
@ -685,68 +673,4 @@ fail:
return 0; return 0;
} }
/* ********************************************* */
/* Read bits (max 32) from buf and update the bit offset. Order is BE (MSF). */
static int r_bits(ealayer3_bitstream * is, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || is->b_off + num_bits > is->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = is->b_off / 8; /* byte offset */
pos = is->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit check for buf */
bit_val = (1U << (num_bits-1-i)); /* bit to set in value */
if (is->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
is->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Order is BE (MSF). */
static int w_bits(ealayer3_bitstream * os, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || os->b_off + num_bits > os->bufsize*8) goto fail;
off = os->b_off / 8; /* byte offset */
pos = os->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << (num_bits-1-i)); /* bit check for value */
bit_buf = (1U << (8-1-pos)) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
os->buf[off] |= bit_buf; /* set bit */
else
os->buf[off] &= ~bit_buf; /* unset bit */
pos++;
if (pos%8 == 0) { /* new byte starts */
pos = 0;
off++;
}
}
os->b_off += num_bits;
return 1;
fail:
return 0;
}
#endif #endif

View File

@ -2,6 +2,7 @@
#define _MPEG_DECODER_H_ #define _MPEG_DECODER_H_
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../coding/coding.h"
/* used by mpeg_decoder.c, but scattered in other .c files */ /* used by mpeg_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_MPEG #ifdef VGM_USE_MPEG

View File

@ -2,6 +2,7 @@
#define _VORBIS_CUSTOM_DECODER_H_ #define _VORBIS_CUSTOM_DECODER_H_
#include "../vgmstream.h" #include "../vgmstream.h"
#include "../coding/coding.h"
/* used by vorbis_custom_decoder.c, but scattered in other .c files */ /* used by vorbis_custom_decoder.c, but scattered in other .c files */
#ifdef VGM_USE_VORBIS #ifdef VGM_USE_VORBIS

View File

@ -8,15 +8,6 @@
/* DEFS */ /* DEFS */
/* **************************************************************************** */ /* **************************************************************************** */
/* An internal struct to pass around and simulate a bitstream. */
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
} vgm_bitstream;
static int r_bits(vgm_bitstream * iw, int num_bits, uint32_t * value);
static int get_packet_header(STREAMFILE *streamFile, off_t *offset, size_t *size); static int get_packet_header(STREAMFILE *streamFile, off_t *offset, size_t *size);
static int build_header_comment(uint8_t * buf, size_t bufsize); static int build_header_comment(uint8_t * buf, size_t bufsize);
@ -137,6 +128,7 @@ static int get_packet_header(STREAMFILE *streamFile, off_t *offset, size_t *size
ib.buf = ibuf; ib.buf = ibuf;
ib.bufsize = ibufsize; ib.bufsize = ibufsize;
ib.b_off = 0; ib.b_off = 0;
ib.mode = BITSTREAM_VORBIS;
/* read using Vorbis weird LSF */ /* read using Vorbis weird LSF */
r_bits(&ib, 4,&size_bits); r_bits(&ib, 4,&size_bits);
@ -157,35 +149,4 @@ fail:
return 0; return 0;
} }
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
static int r_bits(vgm_bitstream * ib, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ib->b_off + num_bits > ib->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = ib->b_off / 8; /* byte offset */
pos = ib->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
bit_val = (1U << i); /* bit to set in value */
if (ib->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ib->b_off += num_bits;
return 1;
fail:
return 0;
}
#endif #endif

View File

@ -13,25 +13,17 @@
/* DEFS */ /* DEFS */
/* **************************************************************************** */ /* **************************************************************************** */
/* An internal struct to pass around and simulate a bitstream.
* Mainly to keep code cleaner and somewhat closer to ww2ogg */
typedef struct {
uint8_t * buf; /* buffer to read/write*/
size_t bufsize; /* max size of the buffer */
off_t b_off; /* current offset in bits inside the buffer */
} ww_bitstream;
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_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_comment(uint8_t * buf, size_t bufsize);
static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_t header_type, int * granulepos, size_t * packet_size, int big_endian); static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_t header_type, int * granulepos, size_t * packet_size, int big_endian);
static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian); static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels); static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels);
static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian); static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian);
static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile); static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile);
static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw); static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw);
static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile); static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile);
static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile); static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile);
static int ww2ogg_tremor_ilog(unsigned int v); static int ww2ogg_tremor_ilog(unsigned int v);
static unsigned int ww2ogg_tremor_book_maptype1_quantvals(unsigned int entries, unsigned int dimensions); static unsigned int ww2ogg_tremor_book_maptype1_quantvals(unsigned int entries, unsigned int dimensions);
@ -39,9 +31,6 @@ static int load_wvc(uint8_t * ibuf, size_t ibufsize, uint32_t codebook_id, wwise
static int load_wvc_file(uint8_t * buf, size_t bufsize, uint32_t codebook_id, STREAMFILE *streamFile); static int load_wvc_file(uint8_t * buf, size_t bufsize, uint32_t codebook_id, STREAMFILE *streamFile);
static int load_wvc_array(uint8_t * buf, size_t bufsize, uint32_t codebook_id, wwise_setup_t setup_type); static int load_wvc_array(uint8_t * buf, size_t bufsize, uint32_t codebook_id, wwise_setup_t setup_type);
static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value);
static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value);
/* **************************************************************************** */ /* **************************************************************************** */
/* EXTERNAL API */ /* EXTERNAL API */
@ -165,7 +154,7 @@ static int get_packet_header(STREAMFILE *streamFile, off_t offset, wwise_header_
/* Transforms a Wwise data packet into a real Vorbis one (depending on config) */ /* Transforms a Wwise data packet into a real Vorbis one (depending on config) */
static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) { static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
ww_bitstream ow, iw; vgm_bitstream ow, iw;
int rc, granulepos; int rc, granulepos;
size_t header_size, packet_size; size_t header_size, packet_size;
@ -183,11 +172,13 @@ static int rebuild_packet(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFil
/* prepare helper structs */ /* prepare helper structs */
ow.buf = obuf; ow.buf = obuf;
ow.bufsize = obufsize; ow.bufsize = obufsize;
ow.b_off = 0 ; ow.b_off = 0;
ow.mode = BITSTREAM_VORBIS;
iw.buf = ibuf; iw.buf = ibuf;
iw.bufsize = ibufsize; iw.bufsize = ibufsize;
iw.b_off = 0; iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
rc = ww2ogg_generate_vorbis_packet(&ow,&iw, streamFile,offset, data, big_endian); rc = ww2ogg_generate_vorbis_packet(&ow,&iw, streamFile,offset, data, big_endian);
if (!rc) goto fail; if (!rc) goto fail;
@ -206,7 +197,7 @@ fail:
/* Transforms a Wwise setup packet into a real Vorbis one (depending on config). */ /* Transforms a Wwise setup packet into a real Vorbis one (depending on config). */
static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels) { static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian, int channels) {
ww_bitstream ow, iw; vgm_bitstream ow, iw;
int rc, granulepos; int rc, granulepos;
size_t header_size, packet_size; size_t header_size, packet_size;
@ -226,10 +217,12 @@ static int rebuild_setup(uint8_t * obuf, size_t obufsize, STREAMFILE *streamFile
ow.buf = obuf; ow.buf = obuf;
ow.bufsize = obufsize; ow.bufsize = obufsize;
ow.b_off = 0; ow.b_off = 0;
ow.mode = BITSTREAM_VORBIS;
iw.buf = ibuf; iw.buf = ibuf;
iw.bufsize = ibufsize; iw.bufsize = ibufsize;
iw.b_off = 0; iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
rc = ww2ogg_generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile); rc = ww2ogg_generate_vorbis_setup(&ow,&iw, data, channels, packet_size, streamFile);
if (!rc) goto fail; if (!rc) goto fail;
@ -295,7 +288,7 @@ static int build_header_comment(uint8_t * buf, size_t bufsize) {
/* Copy packet as-is or rebuild first byte if mod_packets is used. /* Copy packet as-is or rebuild first byte if mod_packets is used.
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-720004.3) */ * (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-720004.3) */
static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) { static int ww2ogg_generate_vorbis_packet(vgm_bitstream * ow, vgm_bitstream * iw, STREAMFILE *streamFile, off_t offset, vorbis_custom_codec_data * data, int big_endian) {
int i,granule; int i,granule;
size_t header_size, packet_size, data_size; size_t header_size, packet_size, data_size;
@ -350,10 +343,13 @@ static int ww2ogg_generate_vorbis_packet(ww_bitstream * ow, ww_bitstream * iw, S
/* get next first byte to read next_mode_number */ /* get next first byte to read next_mode_number */
uint32_t next_mode_number; uint32_t next_mode_number;
uint8_t nbuf[1]; uint8_t nbuf[1];
ww_bitstream nw; vgm_bitstream nw;
nw.buf = nbuf; nw.buf = nbuf;
nw.bufsize = 1; nw.bufsize = 1;
nw.b_off = 0; nw.b_off = 0;
nw.mode = BITSTREAM_VORBIS;
if (read_streamfile(nw.buf, next_offset + next_header_size, nw.bufsize, streamFile) != nw.bufsize) if (read_streamfile(nw.buf, next_offset + next_header_size, nw.bufsize, streamFile) != nw.bufsize)
goto fail; goto fail;
@ -409,7 +405,7 @@ fail:
/* Rebuild a Wwise setup (simplified with removed stuff), recreating all six setup parts. /* Rebuild a Wwise setup (simplified with removed stuff), recreating all six setup parts.
* (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4) */ * (ref: https://www.xiph.org/vorbis/doc/Vorbis_I_spec.html#x1-650004.2.4) */
static int ww2ogg_generate_vorbis_setup(ww_bitstream * ow, ww_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) { static int ww2ogg_generate_vorbis_setup(vgm_bitstream * ow, vgm_bitstream * iw, vorbis_custom_codec_data * data, int channels, size_t packet_size, STREAMFILE *streamFile) {
int i,j,k; int i,j,k;
uint32_t codebook_count = 0, floor_count = 0, residue_count = 0; uint32_t codebook_count = 0, floor_count = 0, residue_count = 0;
uint32_t codebook_count_less1 = 0; uint32_t codebook_count_less1 = 0;
@ -798,7 +794,7 @@ fail:
/* copies Vorbis codebooks (untouched, but size uncertain) */ /* copies Vorbis codebooks (untouched, but size uncertain) */
static int ww2ogg_codebook_library_copy(ww_bitstream * ow, ww_bitstream * iw) { static int ww2ogg_codebook_library_copy(vgm_bitstream * ow, vgm_bitstream * iw) {
int i; int i;
uint32_t id = 0, dimensions = 0, entries = 0; uint32_t id = 0, dimensions = 0, entries = 0;
uint32_t ordered = 0, lookup_type = 0; uint32_t ordered = 0, lookup_type = 0;
@ -914,7 +910,7 @@ fail:
/* rebuilds a Wwise codebook into a Vorbis codebook */ /* rebuilds a Wwise codebook into a Vorbis codebook */
static int ww2ogg_codebook_library_rebuild(ww_bitstream * ow, ww_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) { static int ww2ogg_codebook_library_rebuild(vgm_bitstream * ow, vgm_bitstream * iw, size_t cb_size, STREAMFILE *streamFile) {
int i; int i;
uint32_t id = 0, dimensions = 0, entries = 0; uint32_t id = 0, dimensions = 0, entries = 0;
uint32_t ordered = 0, lookup_type = 0; uint32_t ordered = 0, lookup_type = 0;
@ -1038,11 +1034,11 @@ fail:
} }
/* rebuilds an external Wwise codebook referenced by id to a Vorbis codebook */ /* rebuilds an external Wwise codebook referenced by id to a Vorbis codebook */
static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) { static int ww2ogg_codebook_library_rebuild_by_id(vgm_bitstream * ow, uint32_t codebook_id, wwise_setup_t setup_type, STREAMFILE *streamFile) {
size_t ibufsize = 0x8000; /* arbitrary max size of a codebook */ size_t ibufsize = 0x8000; /* arbitrary max size of a codebook */
uint8_t ibuf[0x8000]; /* Wwise codebook buffer */ uint8_t ibuf[0x8000]; /* Wwise codebook buffer */
size_t cb_size; size_t cb_size;
ww_bitstream iw; vgm_bitstream iw;
cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, streamFile); cb_size = load_wvc(ibuf,ibufsize, codebook_id, setup_type, streamFile);
if (cb_size == 0) goto fail; if (cb_size == 0) goto fail;
@ -1050,6 +1046,7 @@ static int ww2ogg_codebook_library_rebuild_by_id(ww_bitstream * ow, uint32_t cod
iw.buf = ibuf; iw.buf = ibuf;
iw.bufsize = ibufsize; iw.bufsize = ibufsize;
iw.b_off = 0; iw.b_off = 0;
iw.mode = BITSTREAM_VORBIS;
return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, streamFile); return ww2ogg_codebook_library_rebuild(ow, &iw, cb_size, streamFile);
fail: fail:
@ -1228,70 +1225,4 @@ fail:
return 0; return 0;
} }
/* ********************************************* */
/* Read bits (max 32) from buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. from 2 bytes 00100111 00000001 we can could read 4b=0111 and 6b=010010, 6b=remainder (second value is split into the 2nd byte) */
static int r_bits(ww_bitstream * iw, int num_bits, uint32_t * value) {
off_t off, pos;
int i, bit_buf, bit_val;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || iw->b_off + num_bits > iw->bufsize*8) goto fail;
*value = 0; /* set all bits to 0 */
off = iw->b_off / 8; /* byte offset */
pos = iw->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_buf = (1U << pos) & 0xFF; /* bit check for buf */
bit_val = (1U << i); /* bit to set in value */
if (iw->buf[off] & bit_buf) /* is bit in buf set? */
*value |= bit_val; /* set bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
iw->b_off += num_bits;
return 1;
fail:
return 0;
}
/* Write bits (max 32) to buf and update the bit offset. Vorbis packs values in LSB order and byte by byte.
* (ex. writing 1101011010 from b_off 2 we get 01101011 00001101 (value split, and 11 in the first byte skipped)*/
static int w_bits(ww_bitstream * ow, int num_bits, uint32_t value) {
off_t off, pos;
int i, bit_val, bit_buf;
if (num_bits == 0) return 1;
if (num_bits > 32 || num_bits < 0 || ow->b_off + num_bits > ow->bufsize*8) goto fail;
off = ow->b_off / 8; /* byte offset */
pos = ow->b_off % 8; /* bit sub-offset */
for (i = 0; i < num_bits; i++) {
bit_val = (1U << i); /* bit check for value */
bit_buf = (1U << pos) & 0xFF; /* bit to set in buf */
if (value & bit_val) /* is bit in val set? */
ow->buf[off] |= bit_buf; /* set bit */
else
ow->buf[off] &= ~bit_buf; /* unset bit */
pos++; /* new byte starts */
if (pos%8 == 0) {
pos = 0;
off++;
}
}
ow->b_off += num_bits;
return 1;
fail:
return 0;
}
#endif #endif