SBC音频编解码算法(转载)

21 篇文章 0 订阅
4 篇文章 0 订阅

转自:https://blog.csdn.net/wzz4420381/article/details/48676921

原作者:wzz4420381

1. SBC算法简介

  • SBC是sub band code的缩写,也可称为子带编码
  • 在A2DP协议中,SBC算法是默认支持的
  • 蓝牙SBC算法是一种以中等比特率传递高质量音频数据的低计算复杂度的音频编码算法

1.1 算法基本框图

  • SBC系统使用一个余弦调制的滤波器组,用来解析和同步。滤波器组可设定成4或8个子带
  • 子带信号的量化采用比特分配器和自适应脉冲编码器组调制
  • 可用的比特位数和编码器的块数都是可配置的
  • 编码后的数据由比特流打包器打包,以有线或无线方式传输
  • 解码是编码的逆过程
    这里写图片描述

1.1 算法所用参数

  • sampling_frequency:采样频率。常用的是16KHz,32KHz,44.1KHz和48KHz
  • channel mode:通道模式。可以是单声道,双声道,立体声和联合立体声
  • block length:块长度。可以是4,8,12,16
  • subbands:子带数量。可以是4或8
  • allocation method:分配方式。可以是SNR或loudness
  • bitpool:比特池。范围是2-250。此值越大,编码产生的数据越长

2 SBC算法实现

2.1 SBC编码算法实现

这里写图片描述

  • PCM格式的左右声道进入多相解析器,输出尺度因子和子带采样数据
  • 每个尺度因子分别对应一个子带
  • 量化后的子带采样数据需要进行打包,打包方式可以是分段或不分段
    这里写图片描述
  • 多相解析器的代码实现较为复杂,流程图如下[具体请看参考文献2的Appendix B]:
    这里写图片描述

2.2 SBC解码算法实现

这里写图片描述

  • 解码过程是编码过程的逆
  • 多相综合器的代码实现较为复杂,流程图如下[具体请看参考文献2的Appendix B]:
    这里写图片描述

3 SBC解码算法在某蓝牙主设备上的应用

3.1 帧格式

这里写图片描述

3.2 参数选择

  • sampling frequency:16
  • channel mode:单声道
  • number of subbands:8
  • number of channels:1
  • number of blocks:15
  • allocation method:SNR
  • bitpool:26

3.3 代码示例

 
  1. void SBC_Decode(uint8_t * DataIn, FILE * fOutput)

  2. {

  3. #define SBC_SAMPLING_FREQ 16

  4. #define SBC_CHANNEL_MODE 0

  5. #define SBC_NUM_OF_SUBBANDS 8

  6. #define SBC_NUM_OF_CHANNELS 1

  7. #define SBC_NUM_OF_BLOCKS 15

  8. #define SBC_ALLOC_METHOD 0

  9. #define SBC_BITPOOL 26

  10. #define SBC_DECODED_BUFFER_SIZE (16*8)

  11. uint8_t blocks_per_packet = SBC_NUM_OF_BLOCKS;

  12. uint8_t num_bits = SBC_BITPOOL;

  13. const uint8_t * buf = (DataIn+1);//ignore CRC byte

  14. uint16_t len = SBC_GROUP_SIZE;

  15. uint16_t usDecodedBuffer[SBC_DECODED_BUFFER_SIZE];

  16. /* convenience */

  17. const uint8_t * end = buf + len;

  18. #define left (end - buf)

  19. uint16_t * outBufPtr = usDecodedBuffer;

  20. /* workspace */

  21. static INSAMPLE samples[16][8]; /* We blow the stack if this is not static. */

  22. ITER i, j, k;

  23. uint32_t scaleFactors[8]; //= {0x0f, 0x0c, 0x0b, 0x0b, 0x0a, 0x0a, 0x09, 0x09};

  24. int32_t bitneed[8];

  25. uint32_t bits[8];

  26. int32_t bitcount, slicecount, bitslice;

  27. uint8_t samplingRate, blocks, snr, numSubbands, bitpoolSz, bitpos = 0x80;

  28. int8_t max_bitneed = 0;

  29. #ifndef SPEED_OVER_ACCURACY

  30. int32_t levels[8];

  31. #endif

  32. #if (DEBUG_DECODING == 1)

  33. const uint8_t *start_buf = buf;

  34. pr_info("%s: blocks_per_packet = %d, num_bits = %d, buf = %p, len = %d\n",

  35. __func__, blocks_per_packet, num_bits, buf, len);

  36. for (i = 0; i < len; i++) {

  37. pr_info("buf[%d] = 0x%02x\n", i, buf[i]);

  38. }

  39. #endif

  40. /* look into the frame header */

  41. if (left < SBC_GROUP_SIZE) goto out;/* too short a frame header */

  42. /* use Bemote specific constants */

  43. samplingRate = 0; /* always 16000 Hz */

  44. blocks = blocks_per_packet;

  45. snr = 0;

  46. numSubbands = SBC_NUM_OF_SUBBANDS;

  47. bitpoolSz = num_bits;

  48. /* read scale factors */

  49. /* pr_info("sbc_decode: read scale factors, numSubbands = %d\n", numSubbands); */

  50. /**/

  51. for(i = 0; i < numSubbands; i++){

  52. if(bitpos == 0x80){

  53. scaleFactors[i] = (*buf) >> 4;

  54. bitpos = 0x08;

  55. }

  56. else{

  57. scaleFactors[i] = (*buf++) & 0x0F;

  58. bitpos = 0x80;

  59. }

  60. }

  61. /* calculate bitneed table and max_bitneed value (A2DP 12.6.3.1) */

  62. if(snr){

  63. for(i = 0; i < numSubbands; i++){

  64. bitneed[i] = scaleFactors[i];

  65. if(bitneed[i] > max_bitneed) max_bitneed = bitneed[i];

  66. }

  67. }

  68. else{

  69. const signed char* tbl;

  70. if(numSubbands == 4) tbl = (const signed char*)loudness_4[samplingRate];

  71. else tbl = (const signed char*)loudness_8[samplingRate];

  72. for(i = 0; i < numSubbands; i++){

  73. if(scaleFactors[i]){

  74. int loudness = scaleFactors[i] - tbl[i];

  75. if(loudness > 0) loudness /= 2;

  76. bitneed[i] = loudness;

  77. }

  78. else bitneed[i] = -5;

  79. if(bitneed[i] > max_bitneed) max_bitneed = bitneed[i];

  80. }

  81. }

  82. /* fit bitslices into the bitpool */

  83. bitcount = 0;

  84. slicecount = 0;

  85. bitslice = max_bitneed + 1;

  86. /* pr_info("sbc_decode: fit bitslices into the bitpool, bitslice = %d\n", bitslice ); */

  87. do{

  88. bitslice--;

  89. bitcount += slicecount;

  90. slicecount = 0;

  91. for(i = 0; i < numSubbands; i++){

  92. if(bitneed[i] > bitslice + 1 && bitneed[i] < bitslice + 16) slicecount++;

  93. else if(bitneed[i] == bitslice + 1) slicecount += 2;

  94. }

  95. }while(bitcount + slicecount < bitpoolSz);

  96. /* distribute bits */

  97. for(i = 0; i < numSubbands; i++){

  98. if(bitneed[i] < bitslice + 2) bits[i] = 0;

  99. else{

  100. int8_t v = bitneed[i] - bitslice;

  101. if(v > 16) v = 16;

  102. bits[i] = v;

  103. }

  104. }

  105. /* allocate remaining bits */

  106. for(i = 0; i < numSubbands && bitcount < bitpoolSz; i++){

  107. if(bits[i] >= 2 && bits[i] < 16){

  108. bits[i]++;

  109. bitcount++;

  110. }

  111. else if(bitneed[i] == bitslice + 1 && bitpoolSz > bitcount + 1){

  112. bits[i] = 2;

  113. bitcount += 2;

  114. }

  115. }

  116. for(i = 0; i < numSubbands && bitcount < bitpoolSz; i++){

  117. if(bits[i] < 16){

  118. bits[i]++;

  119. bitcount++;

  120. }

  121. }

  122. /* reconstruct subband samples (A2DP 12.6.4) */

  123. #ifndef SPEED_OVER_ACCURACY

  124. for(i = 0; i < numSubbands; i++) levels[i] = (1 << bits[i]) - 1;

  125. #endif

  126. /* pr_info("sbc_decode: reconstruct subband samples, blocks = %d\n", blocks ); */

  127. for(j = 0; j < blocks; j++){

  128. for(i = 0; i < numSubbands; i++){

  129. if(bits[i]){

  130. uint32_t val = 0;

  131. k = bits[i];

  132. do{

  133. val <<= 1;

  134. #if (DEBUG_DECODING == 1)

  135. pr_info("%s: buf = %p, offset %d\n",

  136. __func__, buf, buf-start_buf);

  137. #endif

  138. if(*buf & bitpos) val++;

  139. if(!(bitpos >>= 1)){

  140. bitpos = 0x80;

  141. buf++;

  142. }

  143. }while(--k);

  144. val = (val << 1) | 1;

  145. val <<= scaleFactors[i];

  146. #ifdef SPEED_OVER_ACCURACY

  147. val = mulshift(val, bits[i]);

  148. #else

  149. val /= levels[i];

  150. #endif

  151. val -= (1 << scaleFactors[i]);

  152. samples[j][i] = SAMPLE_CVT(val);

  153. }

  154. else samples[j][i] = SAMPLE_CVT(0);

  155. }

  156. }

  157. //sbc_decoder_reset();

  158. for(j = 0; j < blocks; j++){

  159. synth(outBufPtr, samples[j], numSubbands, gV);

  160. outBufPtr += numSubbands;

  161. }

  162. /* if we used a byte partially, skip the rest of it, it is "padding" */

  163. if(bitpos != 0x80) buf++;

  164. out:

  165. #if (DEBUG_DECODING == 1)

  166. if(left < 0)

  167. pr_err("SBC: buffer over-read by %d bytes.\n", -left);

  168. if(left > 0)

  169. pr_err("SBC: buffer under-read by %d bytes.\n", left);

  170. #endif

  171. fwrite(usDecodedBuffer, sizeof(uint16_t), 120, fOutput);

  172. fflush(fOutput);

  173. memset(usDecodedBuffer, 0, sizeof(usDecodedBuffer));

  174. }

4 总结

  • 在章节3中给出的例子中,压缩前的数据有120*2=240Byte,压缩后的数据有54Byte,压缩比接近4.4:1,压缩比是可调的,其与编码参数有关
  • 压缩后的帧数据长度可以由编码参数计算出来。此例中,
    帧长度=4+(4 * 子带数量 * 通道数量)/8+(块数量 * 通道数量 * bitpool)/8
    =4+(4*8*1)/8+(15*1*26)/8=8+48.75=57(加上CRC正好58字节)
  • 如果在传输过程中丢失了个别帧,解压后回放时会出现一小段音频的整体丢失,对整体的解压没有影响

参考文献

1. LOW-POWER IMPLEMENTATION OF THE BLUETOOTH SUBBAND AUDIO CODEC.pdf
2. A2DP_SPEC_V12.pdf
3. 音频数据SBC算法编码方法及蓝牙立体声子系统.pdf

  • 2
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,以下是一个简单的用C语言实现的sbc转pcm算法: ```c #include <stdint.h> #include <stdbool.h> #define SBC_FRAME_SIZE 64 void sbc_to_pcm(uint8_t *sbc_data, uint32_t sbc_len, int16_t *pcm_data, uint32_t *pcm_len) { static const int16_t sbc_scale_factor[16] = { 0x0008, 0x000a, 0x000c, 0x000e, 0x0010, 0x0014, 0x0018, 0x001c, 0x0020, 0x0028, 0x0030, 0x0038, 0x0040, 0x0050, 0x0060, 0x0070 }; static const uint8_t sbc_bitpool_limits[2][16] = { { 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224 }, { 16, 20, 24, 28, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176 } }; uint8_t *sbc_ptr = sbc_data; uint8_t sbc_header; uint8_t sbc_bitpool; uint8_t sbc_channels; uint8_t sbc_blocks; uint8_t sbc_subbands; uint8_t sbc_bit_allocation[SBC_FRAME_SIZE]; int16_t pcm_samples[SBC_FRAME_SIZE * 2]; uint32_t sbc_data_len = sbc_len; uint32_t pcm_data_len = 0; uint32_t frame_size; while (sbc_data_len > 0) { /* 解析SBC帧头 */ sbc_header = *sbc_ptr++; sbc_bitpool = *sbc_ptr++; sbc_channels = (sbc_header >> 4) & 0x03; sbc_blocks = (sbc_header >> 2) & 0x03; sbc_subbands = (sbc_header >> 1) & 0x01; frame_size = sbc_header & 0x01 ? 53 : 64; /* 计算每个采样点的比特数 */ uint8_t bit_alloc_size = (frame_size * sbc_channels * sbc_subbands + 7) / 8; memcpy(sbc_bit_allocation, sbc_ptr, bit_alloc_size); sbc_ptr += bit_alloc_size; /* 解压缩采样点 */ for (uint32_t i = 0; i < frame_size; i++) { for (uint32_t ch = 0; ch < sbc_channels; ch++) { int16_t pcm_sample = 0; uint8_t bits = sbc_bit_allocation[i * sbc_channels + ch]; if (bits == 0) { pcm_samples[i * sbc_channels + ch] = 0; continue; } for (uint32_t sb = 0; sb < sbc_subbands; sb++) { uint8_t code = *sbc_ptr++; int16_t sb_sample = (int16

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值