📄 sbc.c
字号:
/* * * Bluetooth low-complexity, subband codec (SBC) library * * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> * Copyright (C) 2004-2005 Henryk Ploetz <henryk@ploetzli.ch> * * * This library 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. * * This library 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 this library; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * */#ifdef HAVE_CONFIG_H#include <config.h>#endif#include <errno.h>#include <malloc.h>#include <string.h>#include <sys/types.h>#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 }};/* A2DP specification: Appendix B, page 70 */static const float sbc_proto_4_40[40] = { 0.00000000E+00, 5.36548976E-04, 1.49188357E-03, 2.73370904E-03, 3.83720193E-03, 3.89205149E-03, 1.86581691E-03, -3.06012286E-03, 1.09137620E-02, 2.04385087E-02, 2.88757392E-02, 3.21939290E-02, 2.58767811E-02, 6.13245186E-03, -2.88217274E-02, -7.76463494E-02, 1.35593274E-01, 1.94987841E-01, 2.46636662E-01, 2.81828203E-01, 2.94315332E-01, 2.81828203E-01, 2.46636662E-01, 1.94987841E-01, -1.35593274E-01, -7.76463494E-02, -2.88217274E-02, 6.13245186E-03, 2.58767811E-02, 3.21939290E-02, 2.88757392E-02, 2.04385087E-02, -1.09137620E-02, -3.06012286E-03, 1.86581691E-03, 3.89205149E-03, 3.83720193E-03, 2.73370904E-03, 1.49188357E-03, 5.36548976E-04};/* A2DP specification: Appendix B, page 70 */static const float sbc_proto_8_80[80] = { 0.00000000E+00, 1.56575398E-04, 3.43256425E-04, 5.54620202E-04, 8.23919506E-04, 1.13992507E-03, 1.47640169E-03, 1.78371725E-03, 2.01182542E-03, 2.10371989E-03, 1.99454554E-03, 1.61656283E-03, 9.02154502E-04, -1.78805361E-04, -1.64973098E-03, -3.49717454E-03, 5.65949473E-03, 8.02941163E-03, 1.04584443E-02, 1.27472335E-02, 1.46525263E-02, 1.59045603E-02, 1.62208471E-02, 1.53184106E-02, 1.29371806E-02, 8.85757540E-03, 2.92408442E-03, -4.91578024E-03, -1.46404076E-02, -2.61098752E-02, -3.90751381E-02, -5.31873032E-02, 6.79989431E-02, 8.29847578E-02, 9.75753918E-02, 1.11196689E-01, 1.23264548E-01, 1.33264415E-01, 1.40753505E-01, 1.45389847E-01, 1.46955068E-01, 1.45389847E-01, 1.40753505E-01, 1.33264415E-01, 1.23264548E-01, 1.11196689E-01, 9.75753918E-02, 8.29847578E-02, -6.79989431E-02, -5.31873032E-02, -3.90751381E-02, -2.61098752E-02, -1.46404076E-02, -4.91578024E-03, 2.92408442E-03, 8.85757540E-03, 1.29371806E-02, 1.53184106E-02, 1.62208471E-02, 1.59045603E-02, 1.46525263E-02, 1.27472335E-02, 1.04584443E-02, 8.02941163E-03, -5.65949473E-03, -3.49717454E-03, -1.64973098E-03, -1.78805361E-04, 9.02154502E-04, 1.61656283E-03, 1.99454554E-03, 2.10371989E-03, 2.01182542E-03, 1.78371725E-03, 1.47640169E-03, 1.13992507E-03, 8.23919506E-04, 5.54620202E-04, 3.43256425E-04, 1.56575398E-04};/* Precomputed: synmatrix4[k][i] = cos( (i+0.5) * (k+2.0) * pi/4.0 ) */static const float synmatrix4[8][4] = { { 0.707106781186548, -0.707106781186547, -0.707106781186548, 0.707106781186547 }, { 0.38268343236509, -0.923879532511287, 0.923879532511287, -0.38268343236509 }, { 0, 0, 0, 0 }, { -0.38268343236509, 0.923879532511287, -0.923879532511287, 0.382683432365091 }, { -0.707106781186547, 0.707106781186548, 0.707106781186547, -0.707106781186547 }, { -0.923879532511287, -0.38268343236509, 0.382683432365091, 0.923879532511288 }, { -1, -1, -1, -1 }, { -0.923879532511287, -0.382683432365091, 0.38268343236509, 0.923879532511287 }};/* Precomputed: synmatrix8[k][i] = cos( (i+0.5) * (k+4.0) * pi/8.0 ) */static const float synmatrix8[16][8] = { { 0.707106781186548, -0.707106781186547, -0.707106781186548, 0.707106781186547, 0.707106781186548, -0.707106781186547, -0.707106781186547, 0.707106781186547 }, { 0.555570233019602, -0.98078528040323, 0.195090322016128, 0.831469612302545, -0.831469612302545, -0.195090322016128, 0.980785280403231, -0.555570233019602 }, { 0.38268343236509, -0.923879532511287, 0.923879532511287, -0.38268343236509, -0.382683432365091, 0.923879532511287, -0.923879532511286, 0.38268343236509 }, { 0.195090322016128, -0.555570233019602, 0.831469612302545, -0.980785280403231, 0.98078528040323, -0.831469612302545, 0.555570233019602, -0.195090322016129 }, { 0, 0, 0, 0, 0, 0, 0, 0 }, { -0.195090322016128, 0.555570233019602, -0.831469612302545, 0.98078528040323, -0.980785280403231, 0.831469612302545, -0.555570233019603, 0.19509032201613 }, { -0.38268343236509, 0.923879532511287, -0.923879532511287, 0.382683432365091, 0.38268343236509, -0.923879532511287, 0.923879532511288, -0.382683432365091 }, { -0.555570233019602, 0.98078528040323, -0.195090322016128, -0.831469612302545, 0.831469612302545, 0.195090322016128, -0.98078528040323, 0.555570233019606 }, { -0.707106781186547, 0.707106781186548, 0.707106781186547, -0.707106781186547, -0.707106781186546, 0.707106781186548, 0.707106781186546, -0.707106781186548 }, { -0.831469612302545, 0.195090322016129, 0.980785280403231, 0.555570233019602, -0.555570233019603, -0.98078528040323, -0.195090322016128, 0.831469612302547 }, { -0.923879532511287, -0.38268343236509, 0.382683432365091, 0.923879532511288, 0.923879532511287, 0.382683432365089, -0.382683432365091, -0.923879532511287 }, { -0.98078528040323, -0.831469612302545, -0.555570233019602, -0.195090322016129, 0.19509032201613, 0.555570233019606, 0.831469612302547, 0.980785280403231 }, { -1, -1, -1, -1, -1, -1, -1, -1 }, { -0.98078528040323, -0.831469612302546, -0.555570233019603, -0.19509032201613, 0.195090322016128, 0.555570233019604, 0.831469612302545, 0.98078528040323 }, { -0.923879532511287, -0.382683432365091, 0.38268343236509, 0.923879532511287, 0.923879532511288, 0.382683432365088, -0.382683432365089, -0.923879532511285 }, { -0.831469612302545, 0.195090322016127, 0.98078528040323, 0.555570233019603, -0.555570233019601, -0.98078528040323, -0.195090322016131, 0.831469612302545 }};/* Precomputed: anamatrix4[i][k] = cos( (i+0.5) * (k-2) * pi/4 ) */static const float anamatrix4[4][8] = { { 0.707106781186548, 0.923879532511287, 1, 0.923879532511287, 0.707106781186548, 0.38268343236509, 0, -0.38268343236509 }, { -0.707106781186547, 0.38268343236509, 1, 0.38268343236509, -0.707106781186547, -0.923879532511287, 0, 0.923879532511287 }, { -0.707106781186548, -0.38268343236509, 1, -0.38268343236509, -0.707106781186548, 0.923879532511287, 0, -0.923879532511287 }, { 0.707106781186547, -0.923879532511287, 1, -0.923879532511287, 0.707106781186547, -0.38268343236509, 0, 0.382683432365091 }};/* Precomputed: anamatrix8[i][k] = cos( (i+0.5) * (k-4) * pi/8) */static const float anamatrix8[8][16] = { { 0.923879532511287, 0.98078528040323, 1, 0.98078528040323, 0.923879532511287, 0.831469612302545, 0.707106781186548, 0.555570233019602, 0.38268343236509, 0.195090322016128, 0, -0.195090322016128, -0.38268343236509, -0.555570233019602, -0.707106781186547, -0.831469612302545 }, { 0.38268343236509, 0.831469612302545, 1, 0.831469612302545, 0.38268343236509, -0.195090322016128, -0.707106781186547, -0.98078528040323, -0.923879532511287, -0.555570233019602, 0, 0.555570233019602, 0.923879532511287, 0.98078528040323, 0.707106781186548, 0.195090322016129 }, { -0.38268343236509, 0.555570233019602, 1, 0.555570233019602, -0.38268343236509, -0.98078528040323, -0.707106781186548, 0.195090322016128, 0.923879532511287, 0.831469612302545, 0, -0.831469612302545, -0.923879532511287, -0.195090322016128, 0.707106781186547, 0.980785280403231 }, { -0.923879532511287, 0.195090322016128, 1, 0.195090322016128, -0.923879532511287, -0.555570233019602, 0.707106781186547, 0.831469612302545, -0.38268343236509, -0.980785280403231, 0, 0.98078528040323, 0.382683432365091, -0.831469612302545, -0.707106781186547, 0.555570233019602 }, { -0.923879532511287, -0.195090322016128, 1, -0.195090322016128, -0.923879532511287, 0.555570233019602, 0.707106781186548, -0.831469612302545, -0.382683432365091, 0.98078528040323, 0, -0.980785280403231, 0.38268343236509, 0.831469612302545, -0.707106781186546, -0.555570233019603 }, { -0.38268343236509, -0.555570233019602, 1, -0.555570233019602, -0.38268343236509, 0.98078528040323, -0.707106781186547, -0.195090322016128, 0.923879532511287, -0.831469612302545, 0, 0.831469612302545, -0.923879532511287, 0.195090322016128, 0.707106781186548, -0.98078528040323 }, { 0.38268343236509, -0.831469612302545, 1, -0.831469612302545, 0.38268343236509, 0.195090322016129, -0.707106781186547, 0.980785280403231, -0.923879532511286, 0.555570233019602, 0, -0.555570233019603, 0.923879532511288, -0.98078528040323, 0.707106781186546, -0.195090322016128 }, { 0.923879532511287, -0.98078528040323, 1, -0.98078528040323, 0.923879532511287, -0.831469612302545, 0.707106781186547, -0.555570233019602, 0.38268343236509, -0.195090322016129, 0, 0.19509032201613, -0.382683432365091, 0.555570233019606, -0.707106781186548, 0.831469612302547 }};#define fabs(x) ((x) < 0 ? (-x) : (x))#define SBC_SYNCWORD 0x9C/* sampling frequency */#define SBC_FS_16 0x00#define SBC_FS_32 0x01#define SBC_FS_44 0x02#define SBC_FS_48 0x03/* nrof_blocks */#define SBC_NB_4 0x00#define SBC_NB_8 0x01#define SBC_NB_12 0x02#define SBC_NB_16 0x03/* channel mode */#define SBC_CM_MONO 0x00#define SBC_CM_DUAL_CHANNEL 0x01#define SBC_CM_STEREO 0x02#define SBC_CM_JOINT_STEREO 0x03/* allocation mode */#define SBC_AM_LOUDNESS 0x00#define SBC_AM_SNR 0x01/* subbands */#define SBC_SB_4 0x00#define SBC_SB_8 0x01/* This structure contains an unpacked SBC frame. Yes, there is probably quite some unused space herein */struct sbc_frame { double sampling_frequency; /* in kHz */ u_int8_t blocks; enum { MONO = SBC_CM_MONO, DUAL_CHANNEL = SBC_CM_DUAL_CHANNEL, STEREO = SBC_CM_STEREO, JOINT_STEREO = SBC_CM_JOINT_STEREO } channel_mode; u_int8_t channels; enum { LOUDNESS = SBC_AM_LOUDNESS, SNR = SBC_AM_SNR } allocation_method; u_int8_t subbands; u_int8_t bitpool; u_int8_t join; /* bit number x set means joint stereo has been used in subband x */ u_int8_t scale_factor[2][8]; /* only the lower 4 bits of every element are to be used */ u_int16_t audio_sample[16][2][8]; /* raw integer subband samples in the frame */ double sb_sample[16][2][8]; /* modified subband samples */ double pcm_sample[2][16*8]; /* original pcm audio samples */};struct sbc_decoder_state { int subbands; float S[2][8]; /* Subband samples */ float X[2][8]; /* Audio samples */ float V[2][160], U[2][80], W[2][80]; /* Vectors */};struct sbc_encoder_state { int subbands; float S[2][8]; /* Subband samples */ float X[2][80], Y[2][16], Z[2][80]; /* Vectors */};/* * Calculates the CRC-8 of the first len bits in data */static const u_int8_t crc_table[256] = { 0x00, 0x1D, 0x3A, 0x27, 0x74, 0x69, 0x4E, 0x53, 0xE8, 0xF5, 0xD2, 0xCF, 0x9C, 0x81, 0xA6, 0xBB, 0xCD, 0xD0, 0xF7, 0xEA, 0xB9, 0xA4, 0x83, 0x9E, 0x25, 0x38, 0x1F, 0x02, 0x51, 0x4C, 0x6B, 0x76, 0x87, 0x9A, 0xBD, 0xA0, 0xF3, 0xEE, 0xC9, 0xD4, 0x6F, 0x72, 0x55, 0x48, 0x1B, 0x06, 0x21, 0x3C, 0x4A, 0x57, 0x70, 0x6D, 0x3E, 0x23, 0x04, 0x19, 0xA2, 0xBF, 0x98, 0x85, 0xD6, 0xCB, 0xEC, 0xF1, 0x13, 0x0E, 0x29, 0x34, 0x67, 0x7A, 0x5D, 0x40, 0xFB, 0xE6, 0xC1, 0xDC, 0x8F, 0x92, 0xB5, 0xA8, 0xDE, 0xC3, 0xE4, 0xF9, 0xAA, 0xB7, 0x90, 0x8D, 0x36, 0x2B, 0x0C, 0x11, 0x42, 0x5F, 0x78, 0x65, 0x94, 0x89, 0xAE, 0xB3, 0xE0, 0xFD, 0xDA, 0xC7, 0x7C, 0x61, 0x46, 0x5B, 0x08, 0x15, 0x32, 0x2F, 0x59, 0x44, 0x63, 0x7E, 0x2D, 0x30, 0x17, 0x0A, 0xB1, 0xAC, 0x8B, 0x96, 0xC5, 0xD8, 0xFF, 0xE2, 0x26, 0x3B, 0x1C, 0x01, 0x52, 0x4F, 0x68, 0x75, 0xCE, 0xD3, 0xF4, 0xE9, 0xBA, 0xA7, 0x80, 0x9D, 0xEB, 0xF6, 0xD1, 0xCC, 0x9F, 0x82, 0xA5, 0xB8, 0x03, 0x1E, 0x39, 0x24, 0x77, 0x6A, 0x4D, 0x50, 0xA1, 0xBC, 0x9B, 0x86, 0xD5, 0xC8, 0xEF, 0xF2, 0x49, 0x54, 0x73, 0x6E, 0x3D, 0x20, 0x07, 0x1A, 0x6C, 0x71, 0x56, 0x4B, 0x18, 0x05, 0x22, 0x3F, 0x84, 0x99, 0xBE, 0xA3, 0xF0, 0xED, 0xCA, 0xD7, 0x35, 0x28, 0x0F, 0x12, 0x41, 0x5C, 0x7B, 0x66, 0xDD, 0xC0, 0xE7, 0xFA, 0xA9, 0xB4, 0x93, 0x8E, 0xF8, 0xE5, 0xC2, 0xDF, 0x8C, 0x91, 0xB6, 0xAB, 0x10, 0x0D, 0x2A, 0x37, 0x64, 0x79, 0x5E, 0x43, 0xB2, 0xAF, 0x88, 0x95, 0xC6, 0xDB, 0xFC, 0xE1, 0x5A, 0x47, 0x60, 0x7D, 0x2E, 0x33, 0x14, 0x09, 0x7F, 0x62, 0x45, 0x58, 0x0B, 0x16, 0x31, 0x2C, 0x97, 0x8A, 0xAD, 0xB0, 0xE3, 0xFE, 0xD9, 0xC4};static u_int8_t sbc_crc8(const u_int8_t * data, size_t len){ u_int8_t crc = 0x0f; size_t i; u_int8_t octet; for (i = 0; i < len / 8; i++) crc = crc_table[crc ^ data[i]]; octet = data[i]; for (i = 0; i < len % 8; i++) { char bit = ((octet ^ crc) & 0x80) >> 7; crc = ((crc & 0x7f) << 1) ^ (bit ? 0x1d : 0); octet = octet << 1; } return crc;}/* * Code straight from the spec to calculate the bits array * Takes a pointer to the frame in question, a pointer to the bits array and the sampling frequency (as 2 bit integer) */static void sbc_calculate_bits(const struct sbc_frame *frame, int (*bits)[8], u_int8_t sf){ if (frame->channel_mode == MONO || frame->channel_mode == DUAL_CHANNEL) { int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; int ch, sb; for (ch = 0; ch < frame->channels; ch++) { if (frame->allocation_method == SNR) { for (sb = 0; sb < frame->subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; } } else { for (sb = 0; sb < frame->subbands; sb++) { if (frame->scale_factor[ch][sb] == 0) { bitneed[ch][sb] = -5; } else { if (frame->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; } } } } max_bitneed = 0; for (sb = 0; sb < frame->subbands; sb++) { 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 < frame->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 < frame->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; } } sb = 0; while (bitcount < frame->bitpool && sb < frame->subbands) { 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; } sb++; } sb = 0; while (bitcount < frame->bitpool && sb < frame->subbands) { if (bits[ch][sb] < 16) { bits[ch][sb]++; bitcount++; } sb++; } } } else if (frame->channel_mode == STEREO || frame->channel_mode == JOINT_STEREO) { int bitneed[2][8], loudness, max_bitneed, bitcount, slicecount, bitslice; int ch, sb; if (frame->allocation_method == SNR) { for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < frame->subbands; sb++) { bitneed[ch][sb] = frame->scale_factor[ch][sb]; } } } else { for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < frame->subbands; sb++) { if (frame->scale_factor[ch][sb] == 0) { bitneed[ch][sb] = -5; } else { if (frame->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; } } } } } max_bitneed = 0; for (ch = 0; ch < 2; ch++) { for (sb = 0; sb < frame->subbands; sb++) { 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 < frame->subbands; sb++) { if ((bitneed[ch][sb] > bitslice + 1) && (bitneed[ch][sb] < bitslice + 16)) { slicecount++; } else if (bitneed[ch][sb] == bitslice + 1) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -