mirror of
https://github.com/vgmstream/vgmstream.git
synced 2024-11-24 06:50:20 +01:00
Move bitstream reader to coding_utils
This commit is contained in:
parent
ecf01351cb
commit
765af1994a
@ -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*/
|
||||||
|
@ -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);
|
||||||
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user