diff options
author | Siarhei Siamashka <siarhei.siamashka@nokia.com> | 2008-12-11 21:21:28 +0200 |
---|---|---|
committer | Marcel Holtmann <marcel@holtmann.org> | 2008-12-18 23:45:36 +0100 |
commit | 037a47214cf85251ea61c611b1aaf1d73b772ce3 (patch) | |
tree | 3d06a920f264d01497ad8e344bdd12ee39025894 /sbc/sbc.c | |
parent | 8e1872f93d867af16bccd8839752a05422bdbc25 (diff) |
Bitstream writing optimization for SBC encoder
SBC encoder performance improvement up to 1.5x for ARM11
and almost twice faster for Intel Core2 in some cases.
Diffstat (limited to 'sbc/sbc.c')
-rw-r--r-- | sbc/sbc.c | 65 |
1 files changed, 37 insertions, 28 deletions
@@ -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 { |