summaryrefslogtreecommitdiffstats
path: root/sbc/sbc.c
diff options
context:
space:
mode:
Diffstat (limited to 'sbc/sbc.c')
-rw-r--r--sbc/sbc.c65
1 files changed, 37 insertions, 28 deletions
diff --git a/sbc/sbc.c b/sbc/sbc.c
index 7072673e..c495a75c 100644
--- a/sbc/sbc.c
+++ b/sbc/sbc.c
@@ -909,6 +909,29 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
}
}
+/* Supplementary bitstream writing macros for 'sbc_pack_frame' */
+
+#define PUT_BITS(v, n)\
+ {\
+ bits_cache = (v) | (bits_cache << (n));\
+ bits_count += (n);\
+ if (bits_count >= 16) {\
+ bits_count -= 8;\
+ *data_ptr++ = (uint8_t)(bits_cache >> bits_count);\
+ bits_count -= 8;\
+ *data_ptr++ = (uint8_t)(bits_cache >> bits_count);\
+ }\
+ } while (0);\
+
+#define FLUSH_BITS()\
+ while (bits_count >= 8) {\
+ bits_count -= 8;\
+ *data_ptr++ = (uint8_t)(bits_cache >> bits_count);\
+ }\
+ if (bits_count > 0) {\
+ *data_ptr++ = (uint8_t)(bits_cache << (8 - bits_count));\
+ }\
+
/*
* Packs the SBC frame from frame into the memory at data. At most len
* bytes will be used, should more memory be needed an appropriate
@@ -926,14 +949,18 @@ static int sbc_analyze_audio(struct sbc_encoder_state *state,
static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
{
- int produced;
+ /* Bitstream writer starts from the fourth byte */
+ uint8_t *data_ptr = data + 4;
+ uint32_t bits_cache = 0;
+ uint32_t bits_count = 0;
+
/* Will copy the header parts for CRC-8 calculation here */
uint8_t crc_header[11] = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int crc_pos = 0;
uint16_t audio_sample;
- int ch, sb, blk, bit; /* channel, subband, block and bit counters */
+ int ch, sb, blk; /* channel, subband, block and bit counters */
int bits[2][8]; /* bits distribution */
int levels[2][8]; /* levels are derived from that */
@@ -973,8 +1000,6 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
/* Can't fill in crc yet */
- produced = 32;
-
crc_header[0] = data[1];
crc_header[1] = data[2];
crc_pos = 16;
@@ -999,6 +1024,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
u_int32_t scalefactor_j[2];
uint8_t scale_factor_j[2];
+ uint8_t joint = 0;
frame->joint = 0;
for (sb = 0; sb < frame->subbands - 1; sb++) {
@@ -1031,6 +1057,7 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
if ((scalefactor[0][sb] + scalefactor[1][sb]) >
(scalefactor_j[0] + scalefactor_j[1]) ) {
/* use joint stereo for this subband */
+ joint |= 1 << (frame->subbands - 1 - sb);
frame->joint |= 1 << sb;
frame->scale_factor[0][sb] = scale_factor_j[0];
frame->scale_factor[1][sb] = scale_factor_j[1];
@@ -1045,24 +1072,16 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
}
}
- data[4] = 0;
- for (sb = 0; sb < frame->subbands - 1; sb++)
- data[4] |= ((frame->joint >> sb) & 0x01) << (frame->subbands - 1 - sb);
-
- crc_header[crc_pos >> 3] = data[4];
-
- produced += frame->subbands;
+ PUT_BITS(joint, frame->subbands);
+ crc_header[crc_pos >> 3] = joint;
crc_pos += frame->subbands;
}
for (ch = 0; ch < frame->channels; ch++) {
for (sb = 0; sb < frame->subbands; sb++) {
- data[produced >> 3] <<= 4;
+ PUT_BITS(frame->scale_factor[ch][sb] & 0x0F, 4);
crc_header[crc_pos >> 3] <<= 4;
- data[produced >> 3] |= frame->scale_factor[ch][sb] & 0x0F;
crc_header[crc_pos >> 3] |= frame->scale_factor[ch][sb] & 0x0F;
-
- produced += 4;
crc_pos += 4;
}
}
@@ -1088,25 +1107,15 @@ static int sbc_pack_frame(uint8_t *data, struct sbc_frame *frame, size_t len)
(uint16_t) ((((frame->sb_sample_f[blk][ch][sb]*levels[ch][sb]) >>
(frame->scale_factor[ch][sb] + 1)) +
levels[ch][sb]) >> 1);
- audio_sample <<= 16 - bits[ch][sb];
- for (bit = 0; bit < bits[ch][sb]; bit++) {
- data[produced >> 3] <<= 1;
- if (audio_sample & 0x8000)
- data[produced >> 3] |= 0x1;
- audio_sample <<= 1;
- produced++;
- }
+ PUT_BITS(audio_sample & levels[ch][sb], bits[ch][sb]);
}
}
}
}
- /* align the last byte */
- if (produced % 8) {
- data[produced >> 3] <<= 8 - (produced % 8);
- }
+ FLUSH_BITS();
- return (produced + 7) >> 3;
+ return data_ptr - data;
}
struct sbc_priv {