/* * Bluetooth low-complexity, subband codec (SBC) * * Copyright (C) 2017 Aurelien Jacobs <aurel@gnuage.org> * Copyright (C) 2012-2013 Intel Corporation * Copyright (C) 2008-2010 Nokia Corporation * Copyright (C) 2004-2010 Marcel Holtmann <marcel@holtmann.org> * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch> * Copyright (C) 2005-2008 Brad Midgley <bmidgley@xmission.com> * * This file is part of FFmpeg. * * FFmpeg is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * FFmpeg is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with FFmpeg; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA */ /** * @file * SBC common functions for the encoder and decoder */ #include "sbc.h" /* A2DP specification: Appendix B, page 69 */ static const int sbc_offset4[4][4] = { { -1, 0, 0, 0 }, { -2, 0, 0, 1 }, { -2, 0, 0, 1 }, { -2, 0, 0, 1 } }; /* A2DP specification: Appendix B, page 69 */ static const int sbc_offset8[4][8] = { { -2, 0, 0, 0, 0, 0, 0, 1 }, { -3, 0, 0, 0, 0, 0, 1, 2 }, { -4, 0, 0, 0, 0, 0, 1, 2 }, { -4, 0, 0, 0, 0, 0, 1, 2 } }; /* * Calculates the CRC-8 of the first len bits in data */ uint8_t ff_sbc_crc8(const AVCRC *ctx, const uint8_t *data, size_t len) { size_t byte_length = len >> 3; int bit_length = len & 7; uint8_t crc; crc = av_crc(ctx, 0x0F, data, byte_length); if (bit_length) { uint8_t bits = data[byte_length]; while (bit_length--) { int8_t mask = bits ^ crc; crc = (crc << 1) ^ ((mask >> 7) & 0x1D); bits <<= 1; } } return crc; } /* * Code straight from the spec to calculate the bits array * Takes a pointer to the frame in question and a pointer to the bits array */ void ff_sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8]) { int subbands = frame->subbands; uint8_t sf = frame->frequency; if (frame->mode == MONO || frame->mode == DUAL_CHANNEL) { int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; int ch, sb; for (ch = 0; ch < frame->channels; ch++) { max_bitneed = 0; if (frame->allocation == SNR) { for (sb = 0; sb < subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; if (bitneed[ch][sb] > max_bitneed) max_bitneed = bitneed[ch][sb]; } } else { for (sb = 0; sb < subbands; sb++) { if (frame->scale_factor[ch][sb] == 0) bitneed[ch][sb] = -5; else { if (subbands == 4) loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; else loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; if (loudness > 0) bitneed[ch][sb] = loudness / 2; else bitneed[ch][sb] = loudness; } if (bitneed[ch][sb] > max_bitneed) max_bitneed = bitneed[ch][sb]; } } bitcount = 0; slicecount = 0; bitslice = max_bitneed + 1; do { bitslice--; bitcount += slicecount; slicecount = 0; for (sb = 0; sb < subbands; sb++) { if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) slicecount++; else if (bitneed[ch][sb] == bitslice + 1) slicecount += 2; } } while (bitcount + slicecount < frame->bitpool); if (bitcount + slicecount == frame->bitpool) { bitcount += slicecount; bitslice--; } for (sb = 0; sb < subbands; sb++) { if (bitneed[ch][sb] < bitslice + 2) bits[ch][sb] = 0; else { bits[ch][sb] = bitneed[ch][sb] - bitslice; if (bits[ch][sb] > 16) bits[ch][sb] = 16; } } for (sb = 0; bitcount < frame->bitpool && sb < subbands; sb++) { if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { bits[ch][sb]++; bitcount++; } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { bits[ch][sb] = 2; bitcount += 2; } } for (sb = 0; bitcount < frame->bitpool && sb < subbands; sb++) { if (bits[ch][sb] < 16) { bits[ch][sb]++; bitcount++; } } } } else if (frame->mode == STEREO || frame->mode == JOINT_STEREO) { int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; int ch, sb; max_bitneed = 0; if (frame->allocation == SNR) { for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; if (bitneed[ch][sb] > max_bitneed) max_bitneed = bitneed[ch][sb]; } } } else { for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < subbands; sb++) { if (frame->scale_factor[ch][sb] == 0) bitneed[ch][sb] = -5; else { if (subbands == 4) loudness = frame->scale_factor[ch][sb] - sbc_offset4[sf][sb]; else loudness = frame->scale_factor[ch][sb] - sbc_offset8[sf][sb]; if (loudness > 0) bitneed[ch][sb] = loudness / 2; else bitneed[ch][sb] = loudness; } if (bitneed[ch][sb] > max_bitneed) max_bitneed = bitneed[ch][sb]; } } } bitcount = 0; slicecount = 0; bitslice = max_bitneed + 1; do { bitslice--; bitcount += slicecount; slicecount = 0; for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < subbands; sb++) { if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) slicecount++; else if (bitneed[ch][sb] == bitslice + 1) slicecount += 2; } } } while (bitcount + slicecount < frame->bitpool); if (bitcount + slicecount == frame->bitpool) { bitcount += slicecount; bitslice--; } for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < subbands; sb++) { if (bitneed[ch][sb] < bitslice + 2) { bits[ch][sb] = 0; } else { bits[ch][sb] = bitneed[ch][sb] - bitslice; if (bits[ch][sb] > 16) bits[ch][sb] = 16; } } } ch = 0; sb = 0; while (bitcount < frame->bitpool) { if ((bits[ch][sb] >= 2) && (bits[ch][sb] < 16)) { bits[ch][sb]++; bitcount++; } else if ((bitneed[ch][sb] == bitslice + 1) && (frame->bitpool > bitcount + 1)) { bits[ch][sb] = 2; bitcount += 2; } if (ch == 1) { ch = 0; sb++; if (sb >= subbands) break; } else ch = 1; } ch = 0; sb = 0; while (bitcount < frame->bitpool) { if (bits[ch][sb] < 16) { bits[ch][sb]++; bitcount++; } if (ch == 1) { ch = 0; sb++; if (sb >= subbands) break; } else ch = 1; } } }