From f15323b453eb1d53921f58e0537c274b6ce1d969 Mon Sep 17 00:00:00 2001 From: baohongde Date: Mon, 25 Mar 2019 20:28:55 +0800 Subject: [PATCH 1/6] component/bt: remove SBC frame scramling --- .../btc/profile/std/a2dp/btc_a2dp_source.c | 3 +- .../external/sbc/encoder/srce/sbc_encoder.c | 97 ---------- components/bt/bluedroid/stack/a2dp/a2d_sbc.c | 165 ------------------ .../bt/bluedroid/stack/a2dp/include/a2d_int.h | 1 - .../bluedroid/stack/include/stack/a2d_sbc.h | 20 --- 5 files changed, 1 insertion(+), 285 deletions(-) diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c index a4697bc26..c67b9783c 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c @@ -1375,8 +1375,7 @@ static void btc_media_aa_prep_sbc_2_send(UINT8 nb_frame) if (btc_media_aa_read_feeding()) { /* SBC encode and descramble frame */ SBC_Encoder(&(btc_sbc_encoder)); - A2D_SbcChkFrInit(btc_sbc_encoder.pu8Packet); - A2D_SbcDescramble(btc_sbc_encoder.pu8Packet, btc_sbc_encoder.u16PacketLength); + /* Update SBC frame length */ p_buf->len += btc_sbc_encoder.u16PacketLength; nb_frame--; diff --git a/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c b/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c index c08d4a5cc..378111b00 100644 --- a/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c +++ b/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c @@ -31,84 +31,6 @@ SINT16 EncMaxShiftCounter; -/************************************************************************************************* - * SBC encoder scramble code - * Purpose: to tie the SBC code with BTE/mobile stack code, - * especially for the case when the SBC is ported into a third-party Multimedia chip - * - * Algorithm: - * init process: all counters reset to 0, - * calculate base_index: (6 + s16NumOfChannels*s16NumOfSubBands/2) - * scramble side: the init process happens every time SBC_Encoder_Init() is called. - * descramble side: it would be nice to know if he "init" process has happened. - * alter the SBC SYNC word 0x9C (1001 1100) to 0x8C (1000 1100). - * - * scramble process: - * The CRC byte: - * Every SBC frame has a frame header. - * The 1st byte is the sync word and the following 2 bytes are about the stream format. - * They are supposed to be "constant" within a "song" - * The 4th byte is the CRC byte. The CRC byte is bound to be random. - * Derive 2 items from the CRC byte; one is the "use" bit, the other is the "index". - * - * SBC keeps 2 sets of "use" & "index"; derived the current and the previous frame. - * - * The "use" bit is any bit in SBC_PRTC_USE_MASK is set. - * If set, SBC uses the "index" from the current frame. - * If not set, SBC uses the "index" from the previous frame or 0. - * - * index = (CRC & 0x3) + ((CRC & 0x30) >> 2) // 8 is the max index - * - * if(index > 0) - * { - * p = &u8frame[base_index]; - * if((index&1)&&(u16PacketLength > (base_index+index*2))) - * { - * // odd index: swap 2 bytes - * tmp = p[index]; - * p[index] = p[index*2]; - * p[index*2] = tmp; - * } - * else - * { - * // even index: shift by 3 - * tmp = (p[index] >> 5) + (p[index] << 3); - * p[index] = tmp; - * } - * } - * //else index is 0. The frame stays unaltered - * - */ - -#define SBC_PRTC_CRC_IDX 3 -#define SBC_PRTC_USE_MASK 0x64 -#define SBC_PRTC_SYNC_MASK 0x10 -#define SBC_PRTC_CIDX 0 -#define SBC_PRTC_LIDX 1 -typedef struct { - UINT8 use; - UINT8 idx; -} tSBC_FR_CB; - -typedef struct { - tSBC_FR_CB fr[2]; - UINT8 init; - UINT8 index; - UINT8 base; -} tSBC_PRTC_CB; -tSBC_PRTC_CB sbc_prtc_cb; - -#define SBC_PRTC_IDX(sc) (((sc) & 0x3) + (((sc) & 0x30) >> 2)) -#define SBC_PRTC_CHK_INIT(ar) {if(sbc_prtc_cb.init == 0){sbc_prtc_cb.init=1; ar[0] &= ~SBC_PRTC_SYNC_MASK;}} -#define SBC_PRTC_C2L() {p_last=&sbc_prtc_cb.fr[SBC_PRTC_LIDX]; p_cur=&sbc_prtc_cb.fr[SBC_PRTC_CIDX]; \ - p_last->idx = p_cur->idx; p_last->use = p_cur->use;} -#define SBC_PRTC_GETC(ar) {p_cur->use = ar[SBC_PRTC_CRC_IDX] & SBC_PRTC_USE_MASK; \ - p_cur->idx = SBC_PRTC_IDX(ar[SBC_PRTC_CRC_IDX]);} -#define SBC_PRTC_CHK_CRC(ar) {SBC_PRTC_C2L();SBC_PRTC_GETC(ar);sbc_prtc_cb.index = (p_cur->use)?SBC_PRTC_CIDX:SBC_PRTC_LIDX;} -#define SBC_PRTC_SCRMB(ar) {idx = sbc_prtc_cb.fr[sbc_prtc_cb.index].idx; \ - if(idx > 0){if((idx&1)&&(pstrEncParams->u16PacketLength > (sbc_prtc_cb.base+(idx<<1)))) {tmp2=idx<<1; tmp=ar[idx];ar[idx]=ar[tmp2];ar[tmp2]=tmp;} \ - else{tmp2=ar[idx]; tmp=(tmp2>>5)+(tmp2<<3);ar[idx]=(UINT8)tmp;}}} - #if (SBC_JOINT_STE_INCLUDED == TRUE) SINT32 s32LRDiff[SBC_MAX_NUM_OF_BLOCKS] = {0}; SINT32 s32LRSum[SBC_MAX_NUM_OF_BLOCKS] = {0}; @@ -130,9 +52,6 @@ void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) UINT32 u32CountSum, u32CountDiff; SINT32 *pSum, *pDiff; #endif - UINT8 *pu8; - tSBC_FR_CB *p_cur, *p_last; - UINT32 idx, tmp, tmp2; register SINT32 s32NumOfSubBands = pstrEncParams->s16NumOfSubBands; pstrEncParams->pu8NextPacket = pstrEncParams->pu8Packet; @@ -263,22 +182,9 @@ void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) sbc_enc_bit_alloc_mono(pstrEncParams); } - /* save the beginning of the frame. pu8NextPacket is modified in EncPacking() */ - pu8 = pstrEncParams->pu8NextPacket; /* Quantize the encoded audio */ EncPacking(pstrEncParams); - /* scramble the code */ - SBC_PRTC_CHK_INIT(pu8); - SBC_PRTC_CHK_CRC(pu8); -#if 0 - if (pstrEncParams->u16PacketLength > ((sbc_prtc_cb.fr[sbc_prtc_cb.index].idx * 2) + sbc_prtc_cb.base)) { - printf("len: %d, idx: %d\n", pstrEncParams->u16PacketLength, sbc_prtc_cb.fr[sbc_prtc_cb.index].idx); - } else { - printf("len: %d, idx: %d!!!!\n", pstrEncParams->u16PacketLength, sbc_prtc_cb.fr[sbc_prtc_cb.index].idx); - } -#endif - SBC_PRTC_SCRMB((&pu8[sbc_prtc_cb.base])); } while (--(pstrEncParams->u8NumPacketToEncode)); pstrEncParams->u8NumPacketToEncode = 1; /* default is one for retrocompatibility purpose */ @@ -395,9 +301,6 @@ void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams) pstrEncParams->u16BitRate, pstrEncParams->s16BitPool); SbcAnalysisInit(); - - memset(&sbc_prtc_cb, 0, sizeof(tSBC_PRTC_CB)); - sbc_prtc_cb.base = 6 + pstrEncParams->s16NumOfChannels * pstrEncParams->s16NumOfSubBands / 2; } #endif /* #if (defined(SBC_ENC_INCLUDED) && SBC_ENC_INCLUDED == TRUE) */ diff --git a/components/bt/bluedroid/stack/a2dp/a2d_sbc.c b/components/bt/bluedroid/stack/a2dp/a2d_sbc.c index 00977fc39..1319d11fa 100644 --- a/components/bt/bluedroid/stack/a2dp/a2d_sbc.c +++ b/components/bt/bluedroid/stack/a2dp/a2d_sbc.c @@ -33,171 +33,6 @@ #if (defined(A2D_INCLUDED) && A2D_INCLUDED == TRUE) -/************************************************************************************************* - * SBC descramble code - * Purpose: to tie the SBC code with BTE/mobile stack code, - * especially for the case when the SBC is ported into a third-party Multimedia chip - * - * Algorithm: - * init process: all counters reset to 0, - * calculate base_index: (6 + s16NumOfChannels*s16NumOfSubBands/2) - * scramble side: the init process happens every time SBC_Encoder_Init() is called. - * descramble side: it would be nice to know if he "init" process has happened. - * alter the SBC SYNC word 0x9C (1001 1100) to 0x8C (1000 1100). - * - * scramble process: - * The CRC byte: - * Every SBC frame has a frame header. - * The 1st byte is the sync word and the following 2 bytes are about the stream format. - * They are supposed to be "constant" within a "song" - * The 4th byte is the CRC byte. The CRC byte is bound to be random. - * Derive 2 items from the CRC byte; one is the "use" bit, the other is the "index". - * - * SBC keeps 2 sets of "use" & "index"; derived the current and the previous frame. - * - * The "use" bit is any bit in SBC_PRTC_USE_MASK is set. - * If set, SBC uses the "index" from the current frame. - * If not set, SBC uses the "index" from the previous frame or 0. - * - * index = (CRC & 0x3) + ((CRC & 0x30) >> 2) // 8 is the max index - * - * if(index > 0) - * { - * p = &u8frame[base_index]; - * if((index&1)&&(u16PacketLength > (base_index+index*2))) - * { - * // odd index: swap 2 bytes - * tmp = p[index]; - * p[index] = p[index*2]; - * p[index*2] = tmp; - * } - * else - * { - * // even index: shift by 3 - * tmp = (p[index] >> 3) + (p[index] << 5); - * p[index] = tmp; - * } - * } - * //else index is 0. The frame stays unaltered - * - */ -#define A2D_SBC_SYNC_WORD 0x9C -#define A2D_SBC_CRC_IDX 3 -#define A2D_SBC_USE_MASK 0x64 -#define A2D_SBC_SYNC_MASK 0x10 -#define A2D_SBC_CIDX 0 -#define A2D_SBC_LIDX 1 -#define A2D_SBC_CH_M_BITS 0xC /* channel mode bits: 0: mono; 1 ch */ -#define A2D_SBC_SUBBAND_BIT 0x1 /* num of subband bit: 0:4; 1: 8 */ - -#define A2D_SBC_GET_IDX(sc) (((sc) & 0x3) + (((sc) & 0x30) >> 2)) - -typedef struct { - UINT8 use; - UINT8 idx; -} tA2D_SBC_FR_CB; - -typedef struct { - tA2D_SBC_FR_CB fr[2]; - UINT8 index; - UINT8 base; -} tA2D_SBC_DS_CB; - -static tA2D_SBC_DS_CB a2d_sbc_ds_cb; -/*int a2d_count = 0;*/ -/****************************************************************************** -** -** Function A2D_SbcChkFrInit -** -** Description check if need to init the descramble control block. -** -** Returns nothing. -******************************************************************************/ -void A2D_SbcChkFrInit(UINT8 *p_pkt) -{ - UINT8 fmt; - UINT8 num_chnl = 1; - UINT8 num_subband = 4; - - if ((p_pkt[0] & A2D_SBC_SYNC_MASK) == 0) { - a2d_cb.use_desc = TRUE; - fmt = p_pkt[1]; - p_pkt[0] |= A2D_SBC_SYNC_MASK; - memset(&a2d_sbc_ds_cb, 0, sizeof(tA2D_SBC_DS_CB)); - if (fmt & A2D_SBC_CH_M_BITS) { - num_chnl = 2; - } - if (fmt & A2D_SBC_SUBBAND_BIT) { - num_subband = 8; - } - a2d_sbc_ds_cb.base = 6 + num_chnl * num_subband / 2; - /*printf("base: %d\n", a2d_sbc_ds_cb.base); - a2d_count = 0;*/ - } -} - -/****************************************************************************** -** -** Function A2D_SbcDescramble -** -** Description descramble the packet. -** -** Returns nothing. -******************************************************************************/ -void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len) -{ - tA2D_SBC_FR_CB *p_cur, *p_last; - UINT32 idx, tmp, tmp2; - - if (a2d_cb.use_desc) { - /* c2l */ - p_last = &a2d_sbc_ds_cb.fr[A2D_SBC_LIDX]; - p_cur = &a2d_sbc_ds_cb.fr[A2D_SBC_CIDX]; - p_last->idx = p_cur->idx; - p_last->use = p_cur->use; - /* getc */ - p_cur->use = p_pkt[A2D_SBC_CRC_IDX] & A2D_SBC_USE_MASK; - p_cur->idx = A2D_SBC_GET_IDX(p_pkt[A2D_SBC_CRC_IDX]); - a2d_sbc_ds_cb.index = (p_cur->use) ? A2D_SBC_CIDX : A2D_SBC_LIDX; - /* - printf("%05d: ar[%02d]: x%02x, msk: x%02x, use: %s, idx: %02d, ", - a2d_count++, - A2D_SBC_CRC_IDX, p_pkt[A2D_SBC_CRC_IDX], A2D_SBC_USE_MASK, - (p_cur->use)?"cur":"lst", p_cur->idx); - */ - /* descramble */ - idx = a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx; - if (idx > 0) { - p_pkt = &p_pkt[a2d_sbc_ds_cb.base]; - if ((idx & 1) && (len > (a2d_sbc_ds_cb.base + (idx << 1)))) { - tmp2 = (idx << 1); - tmp = p_pkt[idx]; - p_pkt[idx] = p_pkt[tmp2]; - p_pkt[tmp2] = tmp; - /* - printf("tmp2: %02d, len: %d, idx: %d\n", - tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx); - */ - } else { - tmp2 = p_pkt[idx]; - tmp = (tmp2 >> 3) + (tmp2 << 5); - p_pkt[idx] = (UINT8)tmp; - /* - printf("tmp: x%02x, len: %d, idx: %d(cmp:%d)\n", - (UINT8)tmp2, len, a2d_sbc_ds_cb.fr[a2d_sbc_ds_cb.index].idx, - (a2d_sbc_ds_cb.base+(idx<<1))); - */ - } - } - /* - else - { - printf("!!!!\n"); - } - */ - } -} - /****************************************************************************** ** ** Function A2D_BldSbcInfo diff --git a/components/bt/bluedroid/stack/a2dp/include/a2d_int.h b/components/bt/bluedroid/stack/a2dp/include/a2d_int.h index ddd3e9646..0791a975f 100644 --- a/components/bt/bluedroid/stack/a2dp/include/a2d_int.h +++ b/components/bt/bluedroid/stack/a2dp/include/a2d_int.h @@ -51,7 +51,6 @@ typedef struct { typedef struct { tA2D_FIND_CB find; /* find service control block */ UINT8 trace_level; - BOOLEAN use_desc; UINT16 avdt_sdp_ver; /* AVDTP version */ } tA2D_CB; diff --git a/components/bt/bluedroid/stack/include/stack/a2d_sbc.h b/components/bt/bluedroid/stack/include/stack/a2d_sbc.h index 98b63e46c..065f264f9 100644 --- a/components/bt/bluedroid/stack/include/stack/a2d_sbc.h +++ b/components/bt/bluedroid/stack/include/stack/a2d_sbc.h @@ -92,26 +92,6 @@ typedef struct { extern "C" { #endif -/****************************************************************************** -** -** Function A2D_SbcChkFrInit -** -** Description check if need to init the descramble control block. -** -** Returns nothing. -******************************************************************************/ -extern void A2D_SbcChkFrInit(UINT8 *p_pkt); - -/****************************************************************************** -** -** Function A2D_SbcDescramble -** -** Description descramble the packet. -** -** Returns nothing. -******************************************************************************/ -extern void A2D_SbcDescramble(UINT8 *p_pkt, UINT16 len); - /****************************************************************************** ** ** Function A2D_BldSbcInfo From 7c28611a3dbd650dda0635f4c01fcfaed49cd7ba Mon Sep 17 00:00:00 2001 From: wangmengyang Date: Fri, 25 May 2018 14:23:38 +0800 Subject: [PATCH 2/6] component/bt: modify the SBC encoder to support mSBC mode --- .../btc/profile/std/a2dp/btc_a2dp_source.c | 3 +- .../sbc/encoder/include/sbc_encoder.h | 7 + .../external/sbc/encoder/srce/sbc_encoder.c | 171 ++++++++++-------- .../external/sbc/encoder/srce/sbc_packing.c | 13 +- 4 files changed, 117 insertions(+), 77 deletions(-) diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c index c67b9783c..b734325e3 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c @@ -820,7 +820,7 @@ static void btc_a2dp_source_enc_init(BT_HDR *p_msg) btc_aa_src_cb.timestamp = 0; /* SBC encoder config (enforced even if not used) */ - + btc_sbc_encoder.sbc_mode = SBC_MODE_STD; btc_sbc_encoder.s16ChannelMode = pInitAudio->ChannelMode; btc_sbc_encoder.s16NumOfSubBands = pInitAudio->NumOfSubBands; btc_sbc_encoder.s16NumOfBlocks = pInitAudio->NumOfBlocks; @@ -879,7 +879,6 @@ static void btc_a2dp_source_enc_update(BT_HDR *p_msg) BTC_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR)) < pUpdateAudio->MinMtuSize) ? (BTC_MEDIA_AA_BUF_SIZE - BTC_MEDIA_AA_SBC_OFFSET - sizeof(BT_HDR)) : pUpdateAudio->MinMtuSize; - /* Set the initial target bit rate */ pstrEncParams->u16BitRate = btc_a2dp_source_get_sbc_rate(); diff --git a/components/bt/bluedroid/external/sbc/encoder/include/sbc_encoder.h b/components/bt/bluedroid/external/sbc/encoder/include/sbc_encoder.h index 8a507a7d3..b7b807f53 100644 --- a/components/bt/bluedroid/external/sbc/encoder/include/sbc_encoder.h +++ b/components/bt/bluedroid/external/sbc/encoder/include/sbc_encoder.h @@ -67,6 +67,12 @@ #define SBC_NULL 0 +#define SBC_MODE_STD 0 +#define SBC_MODE_MSBC 1 + +#define SBC_SYNC_WORD_STD (0x9C) +#define SBC_SYNC_WORD_MSBC (0xAD) + #ifndef SBC_MAX_NUM_FRAME #define SBC_MAX_NUM_FRAME 1 #endif @@ -161,6 +167,7 @@ typedef struct SBC_ENC_PARAMS_TAG { SINT16 s16BitPool; /* 16*numOfSb for mono & dual; 32*numOfSb for stereo & joint stereo */ UINT16 u16BitRate; + UINT8 sbc_mode; /* SBC_MODE_STD or SBC_MODE_MSBC */ UINT8 u8NumPacketToEncode; /* number of sbc frame to encode. Default is 1 */ #if (SBC_JOINT_STE_INCLUDED == TRUE) SINT16 as16Join[SBC_MAX_NUM_OF_SUBBANDS]; /*1 if JS, 0 otherwise*/ diff --git a/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c b/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c index 378111b00..c0ab99b83 100644 --- a/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c +++ b/components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c @@ -184,7 +184,6 @@ void SBC_Encoder(SBC_ENC_PARAMS *pstrEncParams) /* Quantize the encoded audio */ EncPacking(pstrEncParams); - } while (--(pstrEncParams->u8NumPacketToEncode)); pstrEncParams->u8NumPacketToEncode = 1; /* default is one for retrocompatibility purpose */ @@ -206,83 +205,111 @@ void SBC_Encoder_Init(SBC_ENC_PARAMS *pstrEncParams) pstrEncParams->u8NumPacketToEncode = 1; /* default is one for retrocompatibility purpose */ - /* Required number of channels */ - if (pstrEncParams->s16ChannelMode == SBC_MONO) { - pstrEncParams->s16NumOfChannels = 1; - } else { - pstrEncParams->s16NumOfChannels = 2; - } - - /* Bit pool calculation */ - if (pstrEncParams->s16SamplingFreq == SBC_sf16000) { - s16SamplingFreq = 16000; - } else if (pstrEncParams->s16SamplingFreq == SBC_sf32000) { - s16SamplingFreq = 32000; - } else if (pstrEncParams->s16SamplingFreq == SBC_sf44100) { - s16SamplingFreq = 44100; - } else { - s16SamplingFreq = 48000; - } - - if ( (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) - || (pstrEncParams->s16ChannelMode == SBC_STEREO) ) { - s16Bitpool = (SINT16)( (pstrEncParams->u16BitRate * - pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq) - - ( (32 + (4 * pstrEncParams->s16NumOfSubBands * - pstrEncParams->s16NumOfChannels) - + ( (pstrEncParams->s16ChannelMode - 2) * - pstrEncParams->s16NumOfSubBands ) ) - / pstrEncParams->s16NumOfBlocks) ); - - s16FrameLen = 4 + (4 * pstrEncParams->s16NumOfSubBands * - pstrEncParams->s16NumOfChannels) / 8 - + ( ((pstrEncParams->s16ChannelMode - 2) * - pstrEncParams->s16NumOfSubBands) - + (pstrEncParams->s16NumOfBlocks * s16Bitpool) ) / 8; - - s16BitRate = (8 * s16FrameLen * s16SamplingFreq) - / (pstrEncParams->s16NumOfSubBands * - pstrEncParams->s16NumOfBlocks * 1000); - - if (s16BitRate > pstrEncParams->u16BitRate) { - s16Bitpool--; - } - - if (pstrEncParams->s16NumOfSubBands == 8) { - pstrEncParams->s16BitPool = (s16Bitpool > 255) ? 255 : s16Bitpool; + if (pstrEncParams->sbc_mode != SBC_MODE_MSBC) { + /* Required number of channels */ + if (pstrEncParams->s16ChannelMode == SBC_MONO) { + pstrEncParams->s16NumOfChannels = 1; } else { - pstrEncParams->s16BitPool = (s16Bitpool > 128) ? 128 : s16Bitpool; + pstrEncParams->s16NumOfChannels = 2; } + + /* Bit pool calculation */ + if (pstrEncParams->s16SamplingFreq == SBC_sf16000) { + s16SamplingFreq = 16000; + } else if (pstrEncParams->s16SamplingFreq == SBC_sf32000) { + s16SamplingFreq = 32000; + } else if (pstrEncParams->s16SamplingFreq == SBC_sf44100) { + s16SamplingFreq = 44100; + } else { + s16SamplingFreq = 48000; + } + + if ( (pstrEncParams->s16ChannelMode == SBC_JOINT_STEREO) + || (pstrEncParams->s16ChannelMode == SBC_STEREO) ) { + s16Bitpool = (SINT16)( (pstrEncParams->u16BitRate * + pstrEncParams->s16NumOfSubBands * 1000 / s16SamplingFreq) + - ( (32 + (4 * pstrEncParams->s16NumOfSubBands * + pstrEncParams->s16NumOfChannels) + + ( (pstrEncParams->s16ChannelMode - 2) * + pstrEncParams->s16NumOfSubBands ) ) + / pstrEncParams->s16NumOfBlocks) ); + + s16FrameLen = 4 + (4 * pstrEncParams->s16NumOfSubBands * + pstrEncParams->s16NumOfChannels) / 8 + + ( ((pstrEncParams->s16ChannelMode - 2) * + pstrEncParams->s16NumOfSubBands) + + (pstrEncParams->s16NumOfBlocks * s16Bitpool) ) / 8; + + s16BitRate = (8 * s16FrameLen * s16SamplingFreq) + / (pstrEncParams->s16NumOfSubBands * + pstrEncParams->s16NumOfBlocks * 1000); + + if (s16BitRate > pstrEncParams->u16BitRate) { + s16Bitpool--; + } + + if (pstrEncParams->s16NumOfSubBands == 8) { + pstrEncParams->s16BitPool = (s16Bitpool > 255) ? 255 : s16Bitpool; + } else { + pstrEncParams->s16BitPool = (s16Bitpool > 128) ? 128 : s16Bitpool; + } + } else { + s16Bitpool = (SINT16)( ((pstrEncParams->s16NumOfSubBands * + pstrEncParams->u16BitRate * 1000) + / (s16SamplingFreq * pstrEncParams->s16NumOfChannels)) + - ( ( (32 / pstrEncParams->s16NumOfChannels) + + (4 * pstrEncParams->s16NumOfSubBands) ) + / pstrEncParams->s16NumOfBlocks ) ); + + pstrEncParams->s16BitPool = (s16Bitpool > + (16 * pstrEncParams->s16NumOfSubBands)) + ? (16 * pstrEncParams->s16NumOfSubBands) : s16Bitpool; + } + + if (pstrEncParams->s16BitPool < 0) { + pstrEncParams->s16BitPool = 0; + } + /* sampling freq */ + HeaderParams = ((pstrEncParams->s16SamplingFreq & 3) << 6); + + /* number of blocks*/ + HeaderParams |= (((pstrEncParams->s16NumOfBlocks - 4) & 12) << 2); + + /* channel mode: mono, dual...*/ + HeaderParams |= ((pstrEncParams->s16ChannelMode & 3) << 2); + + /* Loudness or SNR */ + HeaderParams |= ((pstrEncParams->s16AllocationMethod & 1) << 1); + HeaderParams |= ((pstrEncParams->s16NumOfSubBands >> 3) & 1); /*4 or 8*/ + + pstrEncParams->FrameHeader = HeaderParams; } else { - s16Bitpool = (SINT16)( ((pstrEncParams->s16NumOfSubBands * - pstrEncParams->u16BitRate * 1000) - / (s16SamplingFreq * pstrEncParams->s16NumOfChannels)) - - ( ( (32 / pstrEncParams->s16NumOfChannels) + - (4 * pstrEncParams->s16NumOfSubBands) ) - / pstrEncParams->s16NumOfBlocks ) ); + // mSBC - pstrEncParams->s16BitPool = (s16Bitpool > - (16 * pstrEncParams->s16NumOfSubBands)) - ? (16 * pstrEncParams->s16NumOfSubBands) : s16Bitpool; + // Use mSBC encoding parameters to reset the control field + /* Required number of channels: 1 */ + pstrEncParams->s16ChannelMode = SBC_MONO; + pstrEncParams->s16NumOfChannels = 1; + + /* Required Sampling frequency : 16KHz */ + pstrEncParams->s16SamplingFreq = SBC_sf16000; + + /* Bit pool value: 26 */ + pstrEncParams->s16BitPool = 26; + + /* number of subbands: 8 */ + pstrEncParams->s16NumOfSubBands = 8; + + /* number of blocks: 15 */ + pstrEncParams->s16NumOfBlocks = 15; + + /* allocation method: loudness */ + pstrEncParams->s16AllocationMethod = SBC_LOUDNESS; + + /* set the header paramers, unused for mSBC */ + pstrEncParams->FrameHeader = 0; } - if (pstrEncParams->s16BitPool < 0) { - pstrEncParams->s16BitPool = 0; - } - /* sampling freq */ - HeaderParams = ((pstrEncParams->s16SamplingFreq & 3) << 6); - - /* number of blocks*/ - HeaderParams |= (((pstrEncParams->s16NumOfBlocks - 4) & 12) << 2); - - /* channel mode: mono, dual...*/ - HeaderParams |= ((pstrEncParams->s16ChannelMode & 3) << 2); - - /* Loudness or SNR */ - HeaderParams |= ((pstrEncParams->s16AllocationMethod & 1) << 1); - HeaderParams |= ((pstrEncParams->s16NumOfSubBands >> 3) & 1); /*4 or 8*/ - pstrEncParams->FrameHeader = HeaderParams; - if (pstrEncParams->s16NumOfSubBands == 4) { if (pstrEncParams->s16NumOfChannels == 1) { EncMaxShiftCounter = ((ENC_VX_BUFFER_SIZE - 4 * 10) >> 2) << 2; diff --git a/components/bt/bluedroid/external/sbc/encoder/srce/sbc_packing.c b/components/bt/bluedroid/external/sbc/encoder/srce/sbc_packing.c index d2019baaf..4b1dc259d 100644 --- a/components/bt/bluedroid/external/sbc/encoder/srce/sbc_packing.c +++ b/components/bt/bluedroid/external/sbc/encoder/srce/sbc_packing.c @@ -84,10 +84,17 @@ void EncPacking(SBC_ENC_PARAMS *pstrEncParams) #endif pu8PacketPtr = pstrEncParams->pu8NextPacket; /*Initialize the ptr*/ - *pu8PacketPtr++ = (UINT8)0x9C; /*Sync word*/ - *pu8PacketPtr++ = (UINT8)(pstrEncParams->FrameHeader); + if (pstrEncParams->sbc_mode != SBC_MODE_MSBC) { + *pu8PacketPtr++ = (UINT8)SBC_SYNC_WORD_STD; /*Sync word*/ + *pu8PacketPtr++ = (UINT8)(pstrEncParams->FrameHeader); - *pu8PacketPtr = (UINT8)(pstrEncParams->s16BitPool & 0x00FF); + *pu8PacketPtr = (UINT8)(pstrEncParams->s16BitPool & 0x00FF); + } else { + *pu8PacketPtr++ = (UINT8)SBC_SYNC_WORD_MSBC; /*Sync word*/ + // two reserved bytes + *pu8PacketPtr++ = 0; + *pu8PacketPtr = 0; + } pu8PacketPtr += 2; /*skip for CRC*/ /*here it indicate if it is byte boundary or nibble boundary*/ From e10d5aaddc4f1f8bf2aafba2cae35d8233e960a6 Mon Sep 17 00:00:00 2001 From: baohongde Date: Mon, 15 Apr 2019 14:54:29 +0800 Subject: [PATCH 3/6] component/bt: modify the SBC decoder to support mSBC mode --- .../sbc/decoder/include/oi_codec_sbc.h | 1 + .../sbc/decoder/srce/decoder-private.c | 31 ++++++++++++++++--- .../external/sbc/decoder/srce/decoder-sbc.c | 4 ++- 3 files changed, 31 insertions(+), 5 deletions(-) diff --git a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h index a3f7d8751..6f3134895 100644 --- a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h +++ b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h @@ -76,6 +76,7 @@ Declarations of codec functions, data types, and macros. #define OI_SBC_SYNCWORD 0x9c #define OI_SBC_ENHANCED_SYNCWORD 0x9d +#define OI_mSBC_SYNCWORD 0xad /**@name Sampling frequencies */ /**@{*/ diff --git a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c index 86c4fdf59..1e4d73995 100644 --- a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c +++ b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c @@ -81,9 +81,6 @@ INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, return OI_OK; } - - - /** * Read the SBC header up to but not including the joint stereo mask. The syncword has already been * examined, and the enhanced mode flag set, by FindSyncword. @@ -94,7 +91,33 @@ INLINE void OI_SBC_ReadHeader(OI_CODEC_SBC_COMMON_CONTEXT *common, const OI_BYTE OI_UINT8 d1; - OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD); + OI_ASSERT(data[0] == OI_SBC_SYNCWORD || data[0] == OI_SBC_ENHANCED_SYNCWORD + || data[0] == OI_mSBC_SYNCWORD); + + /** + * For mSBC, just set those parameters + */ + if (data[0] == OI_mSBC_SYNCWORD){ + frame->freqIndex = 0; + frame->frequency = 16000; + + frame->blocks = 4; + frame->nrof_blocks = 15; + + frame->mode = 0; + frame->nrof_channels = 1; + + frame->alloc = SBC_LOUDNESS; + + frame->subbands = 1; + frame->nrof_subbands = 8; + + frame->cachedInfo = 0; + + frame->bitpool = 26; + frame->crc = data[3]; + return; + } /* Avoid filling out all these strucutures if we already remember the values * from last time. Just in case we get a stream corresponding to data[1] == diff --git a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c index 80a1f3354..b2cd75cec 100644 --- a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c +++ b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c @@ -79,7 +79,9 @@ PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context, return OI_CODEC_SBC_NO_SYNCWORD; } #else // SBC_ENHANCED - while (*frameBytes && (**frameData != OI_SBC_SYNCWORD)) { + + while (*frameBytes && (**frameData != OI_SBC_SYNCWORD) + && (**frameData != OI_mSBC_SYNCWORD)) { (*frameBytes)--; (*frameData)++; } From 20758443df1367164d51e0da750d777da9289868 Mon Sep 17 00:00:00 2001 From: baohongde Date: Mon, 15 Apr 2019 15:32:19 +0800 Subject: [PATCH 4/6] components/bt: Add packet loss concealment (PLC) for HFP --- components/bt/CMakeLists.txt | 2 + .../profile/std/hf_client/bta_hf_client_co.c | 48 +++ .../common/include/common/bt_target.h | 1 + .../external/sbc/plc/include/sbc_plc.h | 91 ++++++ .../bt/bluedroid/external/sbc/plc/sbc_plc.c | 302 ++++++++++++++++++ components/bt/component.mk | 2 + 6 files changed, 446 insertions(+) create mode 100644 components/bt/bluedroid/external/sbc/plc/include/sbc_plc.h create mode 100644 components/bt/bluedroid/external/sbc/plc/sbc_plc.c diff --git a/components/bt/CMakeLists.txt b/components/bt/CMakeLists.txt index 50ff9abf6..eb4aed797 100644 --- a/components/bt/CMakeLists.txt +++ b/components/bt/CMakeLists.txt @@ -21,6 +21,7 @@ if(CONFIG_BT_ENABLED) bluedroid/osi/include bluedroid/external/sbc/decoder/include bluedroid/external/sbc/encoder/include + bluedroid/external/sbc/plc/include bluedroid/btc/profile/esp/blufi/include bluedroid/btc/profile/esp/include bluedroid/btc/profile/std/a2dp/include @@ -156,6 +157,7 @@ if(CONFIG_BT_ENABLED) "bluedroid/external/sbc/encoder/srce/sbc_enc_coeffs.c" "bluedroid/external/sbc/encoder/srce/sbc_encoder.c" "bluedroid/external/sbc/encoder/srce/sbc_packing.c" + "bluedroid/external/sbc/plc/sbc_plc.c" "bluedroid/hci/hci_audio.c" "bluedroid/hci/hci_hal_h4.c" "bluedroid/hci/hci_layer.c" diff --git a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c index 27eda746d..a0e003872 100644 --- a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c +++ b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c @@ -15,9 +15,30 @@ #include "bta/bta_hf_client_co.h" #include "hci/hci_audio.h" #include "btc_hf_client.h" +#include "osi/allocator.h" +#include + #if (BTA_HF_INCLUDED == TRUE) #if (BTM_SCO_HCI_INCLUDED == TRUE) + +#if (PLC_INCLUDED == TRUE) +#include "sbc_plc.h" + +typedef struct { + sbc_plc_state_t plc_state; + int16_t sbc_plc_out[SBC_FS]; +} bta_hf_ct_plc_t; + +#if HFP_DYNAMIC_MEMORY == FALSE +static bta_hf_ct_plc_t bta_hf_ct_plc; +#else +static bta_hf_ct_plc_t *bta_hf_ct_plc_ptr; +#define bta_hf_ct_plc (*bta_hf_ct_plc_ptr) +#endif + +#endif ///(PLC_INCLUDED == TRUE) + /******************************************************************************* ** ** Function bta_hf_client_co_audio_state @@ -65,6 +86,7 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, { APPL_TRACE_EVENT("%s rx_bw %d, tx_bw %d, codec %d", __FUNCTION__, rx_bw, tx_bw, p_codec_info->codec_type); + return BTA_HFP_SCO_ROUTE_HCI; } @@ -82,6 +104,19 @@ void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event) { APPL_TRACE_EVENT("%s hdl %x, pkt_sz %u, event %u", __FUNCTION__, handle, pkt_size, event); + +#if (PLC_INCLUDED == TRUE) + +#if (HFP_DYNAMIC_MEMORY == TRUE) + if ((bta_hf_ct_plc_ptr = (bta_hf_ct_plc_t *)osi_malloc(sizeof(bta_hf_ct_plc_t))) == NULL) { + APPL_TRACE_ERROR("%s malloc fail.", __FUNCTION__); + return; + } + memset((void *)bta_hf_ct_plc_ptr, 0, sizeof(bta_hf_ct_plc_t)); +#endif /// (HFP_DYNAMIC_MEMORY == TRUE) + + sbc_plc_init(&(bta_hf_ct_plc.plc_state)); +#endif ///(PLC_INCLUDED == TRUE) } /******************************************************************************* @@ -97,6 +132,15 @@ void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event) void bta_hf_client_sco_co_close(void) { APPL_TRACE_EVENT("%s", __FUNCTION__); + +#if (PLC_INCLUDED == TRUE) + sbc_plc_deinit(&(bta_hf_ct_plc.plc_state)); + +#if (HFP_DYNAMIC_MEMORY == TRUE) + osi_free(bta_hf_ct_plc_ptr); +#endif /// (HFP_DYNAMIC_MEMORY == TRUE) + +#endif ///(PLC_INCLUDED == TRUE) } /******************************************************************************* @@ -129,6 +173,10 @@ void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) STREAM_SKIP_UINT16(p); STREAM_TO_UINT8 (pkt_size, p); + + if(status != BTM_SCO_DATA_CORRECT){ + APPL_TRACE_DEBUG("%s: not a correct frame(%d).", __func__, status); + } btc_hf_client_incoming_data_cb_to_app(p, pkt_size); } diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index 98dbe7a16..258c13d2d 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -77,6 +77,7 @@ #if CONFIG_BT_HFP_CLIENT_ENABLE #define BTC_HF_CLIENT_INCLUDED TRUE #define BTA_HF_INCLUDED TRUE +#define PLC_INCLUDED TRUE #ifndef RFCOMM_INCLUDED #define RFCOMM_INCLUDED TRUE #endif diff --git a/components/bt/bluedroid/external/sbc/plc/include/sbc_plc.h b/components/bt/bluedroid/external/sbc/plc/include/sbc_plc.h new file mode 100644 index 000000000..6d7f4d2ea --- /dev/null +++ b/components/bt/bluedroid/external/sbc/plc/include/sbc_plc.h @@ -0,0 +1,91 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#ifndef _SBC_PLC_H +#define _SBC_PLC_H + +#include + +#if defined __cplusplus +extern "C" { +#endif + +/* Paramter for PLC (16 kHZ)*/ +#define SBC_FS 120 /* SBC Frame Size */ +#define SBC_N 256 /* 16ms - Window Length for pattern matching */ +#define SBC_M 64 /* 4ms - Template for matching */ +#define SBC_LHIST (SBC_N + SBC_FS - 1) /* Length of history buffer required */ +#define SBC_RT 36 /* SBC Reconvergence Time (samples) */ +#define SBC_OLAL 16 /* OverLap-Add Length (samples) */ + +/* PLC State Information */ +typedef struct sbc_plc_state { + int16_t hist[SBC_LHIST + SBC_FS + SBC_RT + SBC_OLAL]; + int16_t bestlag; + int nbf; +} sbc_plc_state_t; + +/* Prototypes */ +/** + * Perform PLC initialization of memory vectors. + * + * @param plc_state pointer to PLC state memory + */ +void sbc_plc_init(sbc_plc_state_t *plc_state); + +/** + * Perform PLC deinitialization of memory vectors. + * + * @param plc_state pointer to PLC state memory + */ +void sbc_plc_deinit(sbc_plc_state_t *plc_state); + +/** + * Perform bad frame processing. + * + * @param plc_state pointer to PLC state memory + * @param ZIRbuf pointer to the ZIR response of the SBC decoder + * @param out pointer to the output samples + */ +void sbc_plc_bad_frame(sbc_plc_state_t *plc_state, int16_t *ZIRbuf, int16_t *out); + +/** + * Perform good frame processing. Most of the time, this function + * just updates history buffers and passes the input to the output, + * but in the first good frame after frame loss, it must conceal the + * received signal as it reconverges with the true output. + * + * @param plc_state pointer to PLC state memory + * @param in pointer to the input vector + * @param out pointer to the output samples + */ +void sbc_plc_good_frame(sbc_plc_state_t *plc_state, int16_t *in, int16_t *out); + +/** + * Get a zero signal eSCO frame + * @return pointer to data buffer + */ +uint8_t * sbc_plc_zero_signal_frame(void); + +/** + * Get a zero signal eSCO pcm frame + * @return pointer to data buffer + */ +int16_t * sbc_plc_zero_signal_frame_pcm(void); + +#if defined __cplusplus +} +#endif + +#endif /// _SBC_PLC_H diff --git a/components/bt/bluedroid/external/sbc/plc/sbc_plc.c b/components/bt/bluedroid/external/sbc/plc/sbc_plc.c new file mode 100644 index 000000000..b44593082 --- /dev/null +++ b/components/bt/bluedroid/external/sbc/plc/sbc_plc.c @@ -0,0 +1,302 @@ +// Copyright 2015-2016 Espressif Systems (Shanghai) PTE LTD +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at + +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include +#include +#include +#include +#include "common/bt_target.h" +#include "sbc_plc.h" + +#if (PLC_INCLUDED == TRUE) +/* msbc */ +static const uint8_t indices0[] = { 0xad, 0x00, 0x00, 0xc5, 0x00, 0x00, 0x00, 0x00, 0x77, 0x6d, +0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, +0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, +0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6d, 0xdd, 0xb6, 0xdb, 0x77, 0x6d, +0xb6, 0xdd, 0xdb, 0x6d, 0xb7, 0x76, 0xdb, 0x6c}; + + +/* 8 kHZ */ +static const int16_t indices0_pcm[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + +/* Raised COSine table for OLA */ +/* 16 kHZ */ +static float rcos[SBC_OLAL] = { + 0.99148655f,0.96623611f,0.92510857f,0.86950446f, + 0.80131732f,0.72286918f,0.63683150f,0.54613418f, + 0.45386582f,0.36316850f,0.27713082f,0.19868268f, + 0.13049554f,0.07489143f,0.03376389f,0.00851345f}; + +// /* 8 kHZ */ +// static float rcos[SBC_OLAL] = { +// 0.96984631f,0.88302222f, 0.75f,0.58682409f, +// 0.41317591f, 0.25f,0.11697778f,0.09015369f}; + +static float SqrtByCarmack(const float x){ + int i; + float x2, y; + const float threehalfs = 1.5f; + + x2 = x * 0.5f; + y = x; + i = *(int *)&y; + i = 0x5f375a86 - (i >> 1); + y = *(float *)&i; + y = y * (threehalfs - (x2 * y *y)); + // y = y * (threehalfs - (x2 * y *y)); + // y = y * (threehalfs - (x2 * y *y)); + + return (x * y); +} + +static float absolute(float x){ + if (x < 0) { + x = -x; + } + + return x; +} + +/** + * Compute the cross correlation according to Eq. (4) of Goodman + * paper, except that the true correlation is used. His formula + * seems to be incorrect. + * + * @param x pointer to x input vector + * @param y pointer to y input vector + * + * @return value containing the cross-correlation of x and y + */ +static float CrossCorrelation(int16_t *x, int16_t *y){ + int m; + float num = 0; + float den = 0; + float x2 = 0; + float y2 = 0; + + for (m = 0; m < SBC_M; m++) { + num += ((float)x[m]) * y[m]; + x2 += ((float)x[m]) * x[m]; + y2 += ((float)y[m]) * y[m]; + } + den = (float)SqrtByCarmack(x2 * y2); + return num / den; +} + +/** + * Perform pattern matching to find the match of template with the + * history buffer according to Section B of Goodman paper. + * + * @param y pointer to history buffer + * + * @return the lag corresponding to the best match. The lag is + * with respect to the beginning of the history buffer. + * + */ +static int PatternMatch(int16_t *y){ + int n; + float maxCn = -999999.0; // large negative number + float Cn; + int bestmatch = 0; + + for (n = 0; n < SBC_N; n++){ + Cn = CrossCorrelation(&y[SBC_LHIST-SBC_M], &y[n]); + if (Cn > maxCn){ + bestmatch = n; + maxCn = Cn; + } + } + return bestmatch; +} + +/** + * Perform amplitude matching using mean-absolute-value according + * to Goodman paper. + * + * @param y pointer to history buffer + * @param bestmatch value of the lag to the best match + * + * @return scale factor + */ +static float AmplitudeMatch(int16_t *y, int16_t bestmatch) { + int i; + float sumx = 0; + float sumy = 0.000001f; + float sf; + + for (i = 0; i < SBC_FS; i++){ + sumx += absolute(y[SBC_LHIST - SBC_FS + i]); + sumy += absolute(y[bestmatch + i]); + } + sf = sumx / sumy; + // This is not in the paper, but limit the scaling factor to something reasonable to avoid creating artifacts + if (sf < 0.75f) { + sf = 0.75f; + } + if (sf > 1.2f) { + sf = 1.2f; + } + return sf; +} + +static int16_t crop_sample(float val){ + float croped_val = val; + if (croped_val > 32767.0) croped_val= 32767.0; + if (croped_val < -32768.0) croped_val=-32768.0; + return (int16_t) croped_val; +} + +/** + * Get a zero signal eSCO frame + * @return pointer to data buffer + */ +uint8_t * sbc_plc_zero_signal_frame(void){ + return (uint8_t *)&indices0; +} + +/** + * Get a zero signal eSCO pcm frame + * @return pointer to data buffer + */ +int16_t * sbc_plc_zero_signal_frame_pcm(void){ + return (int16_t *)&indices0_pcm; +} + +/** + * Perform PLC initialization of memory vectors. + * + * @param plc_state pointer to PLC state memory + */ +void sbc_plc_init(sbc_plc_state_t *plc_state){ + plc_state->nbf=0; + plc_state->bestlag=0; + memset(plc_state->hist, 0, sizeof(plc_state->hist)); +} + +/** + * Perform PLC deinitialization of memory vectors. + * + * @param plc_state pointer to PLC state memory + */ +void sbc_plc_deinit(sbc_plc_state_t *plc_state){ + plc_state->nbf=0; + plc_state->bestlag=0; + memset(plc_state->hist, 0, sizeof(plc_state->hist)); +} + +/** + * Perform bad frame processing. + * + * @param plc_state pointer to PLC state memory + * @param ZIRbuf pointer to the ZIR response of the SBC decoder + * @param out pointer to the output samples + */ +void sbc_plc_bad_frame(sbc_plc_state_t *plc_state, int16_t *ZIRbuf, int16_t *out){ + int i = 0; + float val; + float sf = 1; + + plc_state->nbf++; + + if (plc_state->nbf == 1){ + // Perform pattern matching to find where to replicate + plc_state->bestlag = PatternMatch(plc_state->hist); + // the replication begins after the template match + plc_state->bestlag += SBC_M; + + // Compute Scale Factor to Match Amplitude of Substitution Packet to that of Preceding Packet + sf = AmplitudeMatch(plc_state->hist, plc_state->bestlag); + + for (i = 0; i < SBC_OLAL; i++){ + val = ZIRbuf[i] * rcos[i] + + sf * plc_state->hist[plc_state->bestlag + i] * rcos[SBC_OLAL - i - 1]; + plc_state->hist[SBC_LHIST + i] = crop_sample(val); + } + + for (; i < SBC_FS; i++){ + val = sf*plc_state->hist[plc_state->bestlag + i]; + plc_state->hist[SBC_LHIST + i] = crop_sample(val); + } + + for (; i < SBC_FS + SBC_OLAL; i++){ + val = sf * plc_state->hist[plc_state->bestlag + i] * rcos[i-SBC_FS] + + plc_state->hist[plc_state->bestlag + i] * rcos[SBC_OLAL - 1 - i + SBC_FS]; + plc_state->hist[SBC_LHIST + i] = crop_sample(val); + } + + for (; i < SBC_FS + SBC_RT + SBC_OLAL; i++){ + plc_state->hist[SBC_LHIST + i] = plc_state->hist[plc_state->bestlag + i]; + } + } else { + for ( ;i < SBC_FS + SBC_RT + SBC_OLAL; i++){ + plc_state->hist[SBC_LHIST + i] = plc_state->hist[plc_state->bestlag + i]; + } + } + + for (i = 0; i < SBC_FS; i++){ + out[i] = plc_state->hist[SBC_LHIST + i]; + } + + // shift the history buffer + for (i = 0; i < SBC_LHIST + SBC_RT + SBC_OLAL; i++){ + plc_state->hist[i] = plc_state->hist[i + SBC_FS]; + } +} + +/** + * Perform good frame processing. Most of the time, this function + * just updates history buffers and passes the input to the output, + * but in the first good frame after frame loss, it must conceal the + * received signal as it reconverges with the true output. + * + * @param plc_state pointer to PLC state memory + * @param in pointer to the input vector + * @param out pointer to the output samples + */ +void sbc_plc_good_frame(sbc_plc_state_t *plc_state, int16_t *in, int16_t *out){ + int i = 0; + + if (plc_state->nbf > 0){ + for (i = 0; i < SBC_RT; i++){ + out[i] = plc_state->hist[SBC_LHIST + i]; + } + + for (i = SBC_RT; i < SBC_RT + SBC_OLAL; i++){ + out[i] = (int16_t)(plc_state->hist[SBC_LHIST + i] * rcos[i - SBC_RT] + in[i] * rcos[SBC_OLAL - 1 - i + SBC_RT]); + } + } + + for (; i < SBC_FS; i++){ + out[i] = in[i]; + } + // Copy the output to the history buffer + for (i = 0; i < SBC_FS; i++){ + plc_state->hist[SBC_LHIST + i] = out[i]; + } + // shift the history buffer + for (i = 0; i < SBC_LHIST; i++){ + plc_state->hist[i] = plc_state->hist[i + SBC_FS]; + } + + plc_state->nbf = 0; +} + +#endif ///(PLC_INCLUDED == TRUE) \ No newline at end of file diff --git a/components/bt/component.mk b/components/bt/component.mk index d04846919..b77e8f664 100644 --- a/components/bt/component.mk +++ b/components/bt/component.mk @@ -45,6 +45,7 @@ COMPONENT_PRIV_INCLUDEDIRS += bluedroid/bta/include \ bluedroid/utils/include \ bluedroid/external/sbc/decoder/include \ bluedroid/external/sbc/encoder/include \ + bluedroid/external/sbc/plc/include \ bluedroid/btc/core/include \ bluedroid/btc/profile/esp/blufi/include \ bluedroid/btc/profile/esp/include \ @@ -92,6 +93,7 @@ COMPONENT_SRCDIRS += bluedroid/bta/dm \ bluedroid/osi \ bluedroid/external/sbc/decoder/srce \ bluedroid/external/sbc/encoder/srce \ + bluedroid/external/sbc/plc \ bluedroid/btc/core \ bluedroid/btc/profile/esp/blufi \ bluedroid/btc/profile/std/gap \ From dd906a91a5053514ab05c0f451a6f49f49e0fedf Mon Sep 17 00:00:00 2001 From: baohongde Date: Tue, 14 May 2019 15:19:07 +0800 Subject: [PATCH 5/6] components/bt: Enable mSBC and add decoder and encoder --- .../bta/hf_client/bta_hf_client_main.c | 12 +- .../bta/hf_client/bta_hf_client_sco.c | 30 +- .../bta/hf_client/include/bta_hf_client_int.h | 7 + .../bta/include/bta/bta_hf_client_co.h | 4 +- .../btc/profile/std/a2dp/btc_a2dp_sink.c | 2 +- .../profile/std/hf_client/bta_hf_client_co.c | 339 ++++++++++++++++-- .../common/include/common/bt_target.h | 20 +- .../sbc/decoder/include/oi_codec_sbc.h | 7 +- .../decoder/include/oi_codec_sbc_private.h | 3 +- .../sbc/decoder/srce/decoder-private.c | 9 +- .../external/sbc/decoder/srce/decoder-sbc.c | 11 +- .../bt/bluedroid/external/sbc/plc/sbc_plc.c | 24 +- .../bt/bluedroid/stack/btm/include/btm_int.h | 4 + .../bluedroid/stack/include/stack/btm_api.h | 2 +- 14 files changed, 416 insertions(+), 58 deletions(-) diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c index 16e67cf73..dcaf665db 100644 --- a/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c @@ -232,6 +232,8 @@ const tBTA_HF_CLIENT_ST_TBL bta_hf_client_st_tbl[] = { bta_hf_client_st_closing }; +const char *bta_hf_client_version = "1.6"; + /* HF Client control block */ #if BTA_DYNAMIC_MEMORY == FALSE tBTA_HF_CLIENT_CB bta_hf_client_cb; @@ -385,15 +387,11 @@ static void bta_hf_client_api_enable(tBTA_HF_CLIENT_DATA *p_data) bta_hf_client_cb.p_cback = p_data->api_enable.p_cback; /* check if mSBC support enabled */ -#if 0 // todo - char value[PROPERTY_VALUE_MAX]; - property_get("ro.bluetooth.hfp.ver", value, "0"); - if (strcmp(value, "1.6") == 0) { + if (strcmp(bta_hf_client_version, "1.6") == 0) { bta_hf_client_cb.msbc_enabled = TRUE; + } else{ + bta_hf_client_cb.msbc_enabled = FALSE; } -#else - bta_hf_client_cb.msbc_enabled = FALSE; -#endif bta_hf_client_cb.scb.negotiated_codec = BTM_SCO_CODEC_CVSD; diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c index 16efd6673..e9396f14a 100644 --- a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c @@ -268,13 +268,28 @@ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) { BT_HDR *p_buf; UINT8 *rem_bd; + tBTM_ESCO_DATA sco_data; APPL_TRACE_DEBUG("%s %d", __FUNCTION__, sco_idx); rem_bd = BTM_ReadScoBdAddr(sco_idx); + BTM_ReadEScoLinkParms (sco_idx, &sco_data); if (rem_bd && bdcmp(bta_hf_client_cb.scb.peer_addr, rem_bd) == 0 && bta_hf_client_cb.scb.svc_conn && bta_hf_client_cb.scb.sco_idx == sco_idx) { + + bta_hf_client_cb.scb.link_type = sco_data.link_type; + bta_hf_client_cb.scb.tx_interval = sco_data.tx_interval; + bta_hf_client_cb.scb.retrans_window = sco_data.retrans_window; + bta_hf_client_cb.scb.air_mode = sco_data.air_mode; + if (sco_data.air_mode == BTM_SCO_AIR_MODE_CVSD) { + bta_hf_client_cb.scb.tx_pkt_len = sco_data.tx_pkt_len * 2; + bta_hf_client_cb.scb.rx_pkt_len = sco_data.rx_pkt_len * 2; + } else { + bta_hf_client_cb.scb.tx_pkt_len = sco_data.tx_pkt_len; + bta_hf_client_cb.scb.rx_pkt_len = sco_data.rx_pkt_len; + } + if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { p_buf->event = BTA_HF_CLIENT_SCO_OPEN_EVT; p_buf->layer_specific = bta_hf_client_cb.scb.conn_handle; @@ -428,20 +443,20 @@ static void bta_hf_client_sco_event(UINT8 event) #if (BTM_SCO_HCI_INCLUDED == TRUE ) if (event == BTA_HF_CLIENT_SCO_CI_DATA_E) { - uint16_t pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE; - uint16_t len_to_send = 0; + UINT16 pkt_offset = 1 + HCI_SCO_PREAMBLE_SIZE; + UINT16 len_to_send = 0; while (true) { - p_buf = osi_malloc(sizeof(BT_HDR) + pkt_offset + BTM_SCO_DATA_SIZE_MAX); + p_buf = osi_calloc(sizeof(BT_HDR) + pkt_offset + p_scb->tx_pkt_len); if (!p_buf) { APPL_TRACE_WARNING("%s, no mem", __FUNCTION__); break; } p_buf->offset = pkt_offset; - p_buf->len = BTM_SCO_DATA_SIZE_MAX; - len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset, BTM_SCO_DATA_SIZE_MAX); - if (len_to_send == BTM_SCO_DATA_SIZE_MAX) { + len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset); + p_buf->len = len_to_send; + if (len_to_send == p_scb->tx_pkt_len) { // expect to get the exact size of data from upper layer if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) { tBTM_STATUS write_stat = BTM_WriteScoData(p_scb->sco_idx, p_buf); @@ -731,7 +746,8 @@ void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data) #if (BTM_SCO_HCI_INCLUDED == TRUE) bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_ON, 0); /* open SCO codec if SCO is routed through transport */ - bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, BTA_HFP_SCO_OUT_PKT_SIZE, BTA_HF_CLIENT_CI_SCO_DATA_EVT); + bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, bta_hf_client_cb.scb.air_mode, + bta_hf_client_cb.scb.tx_pkt_len, BTA_HF_CLIENT_CI_SCO_DATA_EVT); #endif if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) { diff --git a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h index 2e3fab9c1..b5b07b9c5 100644 --- a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h +++ b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h @@ -157,6 +157,13 @@ typedef struct { tBTM_SCO_CODEC_TYPE negotiated_codec; /* negotiated codec */ TIMER_LIST_ENT colli_timer; /* Collision timer */ BOOLEAN colli_tmr_on; /* TRUE if collision timer is active */ + + UINT16 rx_pkt_len; + UINT16 tx_pkt_len; + UINT8 link_type; /* BTM_LINK_TYPE_SCO or BTM_LINK_TYPE_ESCO */ + UINT8 tx_interval; + UINT8 retrans_window; + UINT8 air_mode; } tBTA_HF_CLIENT_SCB; /* sco states */ diff --git a/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h index af53e6e31..eef1c6668 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h +++ b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h @@ -73,7 +73,7 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, ** Returns void ** *******************************************************************************/ -void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event); +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 pkt_size, UINT16 event); /******************************************************************************* ** @@ -96,7 +96,7 @@ void bta_hf_client_sco_co_close(void); ** Returns number of bytes got from application ** *******************************************************************************/ -uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz); +uint32_t bta_hf_client_sco_co_out_data(UINT8 *p_buf); /******************************************************************************* ** diff --git a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c index 619e0143a..a5d09b2ca 100644 --- a/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c +++ b/components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c @@ -516,7 +516,7 @@ static void btc_a2dp_sink_handle_decoder_reset(tBTC_MEDIA_SINK_CFG_UPDATE *p_msg btc_aa_snk_cb.rx_flush = FALSE; APPL_TRACE_EVENT("Reset to sink role"); status = OI_CODEC_SBC_DecoderReset(&btc_sbc_decoder_context, btc_sbc_decoder_context_data, - BTC_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 2, 2, FALSE); + BTC_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 2, 2, FALSE, FALSE); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); } diff --git a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c index a0e003872..6b3830b5e 100644 --- a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c +++ b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c @@ -22,10 +22,17 @@ #if (BTM_SCO_HCI_INCLUDED == TRUE) +#include "btm_int.h" +#include "stack/btm_api.h" +#include "oi_codec_sbc.h" +#include "oi_status.h" +#include "sbc_encoder.h" + #if (PLC_INCLUDED == TRUE) #include "sbc_plc.h" typedef struct { + bool first_good_frame_found; sbc_plc_state_t plc_state; int16_t sbc_plc_out[SBC_FS]; } bta_hf_ct_plc_t; @@ -39,6 +46,31 @@ static bta_hf_ct_plc_t *bta_hf_ct_plc_ptr; #endif ///(PLC_INCLUDED == TRUE) + +#define HF_SBC_DEC_CONTEXT_DATA_LEN (CODEC_DATA_WORDS(1, SBC_CODEC_FAST_FILTER_BUFFERS)) +#define HF_SBC_DEC_PCM_DATA_LEN 240 +#define HF_SBC_ENC_PCM_DATA_LEN 240 + +#if HFP_DYNAMIC_MEMORY == FALSE +static OI_CODEC_SBC_DECODER_CONTEXT hf_sbc_decoder_context; +static OI_UINT32 hf_sbc_decoder_context_data[HF_SBC_DEC_CONTEXT_DATA_LEN]; +static OI_INT16 hf_sbc_decode_pcm_data[HF_SBC_DEC_PCM_DATA_LEN]; + +static SBC_ENC_PARAMS hf_sbc_encoder; +#else +static OI_CODEC_SBC_DECODER_CONTEXT *hf_sbc_decoder_context_ptr; +static OI_UINT32 *hf_sbc_decoder_context_data; +static OI_INT16 *hf_sbc_decode_pcm_data; +#define hf_sbc_decoder_context (*hf_sbc_decoder_context_ptr) + +static SBC_ENC_PARAMS *hf_sbc_encoder_ptr; +#define hf_sbc_encoder (*hf_sbc_encoder_ptr) +#endif /* HFP_DYNAMIC_MEMORY == FALSE */ + +static UINT8 hf_sequence_number = 0; +static UINT8 hf_air_mode; +static UINT8 hf_pkt_size; + /******************************************************************************* ** ** Function bta_hf_client_co_audio_state @@ -86,10 +118,56 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, { APPL_TRACE_EVENT("%s rx_bw %d, tx_bw %d, codec %d", __FUNCTION__, rx_bw, tx_bw, p_codec_info->codec_type); - return BTA_HFP_SCO_ROUTE_HCI; } +/******************************************************************************* + ** + ** Function bta_hf_dec_init + ** + ** Description Initialize decoding task + ** + ** Returns void + ** + *******************************************************************************/ +static void bta_hf_dec_init(void) { +#if (PLC_INCLUDED == TRUE) + sbc_plc_init(&(bta_hf_ct_plc.plc_state)); +#endif ///(PLC_INCLUDED == TRUE) + + OI_STATUS status; + + status = OI_CODEC_SBC_DecoderReset(&hf_sbc_decoder_context, hf_sbc_decoder_context_data, + HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 1, 1, FALSE, TRUE); + if (!OI_SUCCESS(status)) { + APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); + } +} + +/******************************************************************************* + ** + ** Function bta_hf_enc_init + ** + ** Description Initialize encoding task + ** + ** Returns void + ** + *******************************************************************************/ +static void bta_hf_enc_init(void) { + hf_sequence_number = 0; + + hf_sbc_encoder.sbc_mode = SBC_MODE_MSBC; + hf_sbc_encoder.s16NumOfBlocks = 15; + hf_sbc_encoder.s16NumOfSubBands = 8; + hf_sbc_encoder.s16AllocationMethod = SBC_LOUDNESS; + hf_sbc_encoder.s16BitPool = 26; + hf_sbc_encoder.s16ChannelMode = SBC_MONO; + hf_sbc_encoder.s16NumOfChannels = 1; + hf_sbc_encoder.s16SamplingFreq = SBC_sf16000; + + SBC_Encoder_Init(&(hf_sbc_encoder)); +} + /******************************************************************************* ** ** Function bta_hf_client_sco_co_open @@ -100,23 +178,78 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, ** Returns void ** *******************************************************************************/ -void bta_hf_client_sco_co_open(UINT16 handle, UINT8 pkt_size, UINT16 event) +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 pkt_size, UINT16 event) { APPL_TRACE_EVENT("%s hdl %x, pkt_sz %u, event %u", __FUNCTION__, handle, pkt_size, event); -#if (PLC_INCLUDED == TRUE) + hf_air_mode = air_mode; + hf_pkt_size = pkt_size; + if (air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { #if (HFP_DYNAMIC_MEMORY == TRUE) - if ((bta_hf_ct_plc_ptr = (bta_hf_ct_plc_t *)osi_malloc(sizeof(bta_hf_ct_plc_t))) == NULL) { - APPL_TRACE_ERROR("%s malloc fail.", __FUNCTION__); - return; - } - memset((void *)bta_hf_ct_plc_ptr, 0, sizeof(bta_hf_ct_plc_t)); + hf_sbc_decoder_context_ptr = osi_calloc(sizeof(OI_CODEC_SBC_DECODER_CONTEXT)); + hf_sbc_decoder_context_data = osi_calloc(HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32)); + hf_sbc_decode_pcm_data = osi_calloc(HF_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16)); + if (!hf_sbc_decoder_context_ptr || !hf_sbc_decoder_context_data || !hf_sbc_decode_pcm_data) { + APPL_TRACE_ERROR("%s failed to allocate SBC decoder", __FUNCTION__); + goto error_exit; + } + + hf_sbc_encoder_ptr = osi_calloc(sizeof(SBC_ENC_PARAMS)); + + if (!hf_sbc_encoder_ptr) { + APPL_TRACE_ERROR("%s failed to allocate SBC encoder", __FUNCTION__); + goto error_exit; + } + +#if (PLC_INCLUDED == TRUE) + bta_hf_ct_plc_ptr = (bta_hf_ct_plc_t *)osi_calloc(sizeof(bta_hf_ct_plc_t)); + if (!bta_hf_ct_plc_ptr) { + APPL_TRACE_ERROR("%s malloc fail.", __FUNCTION__); + goto error_exit; + } +#endif ///(PLC_INCLUDED == TRUE) + #endif /// (HFP_DYNAMIC_MEMORY == TRUE) - sbc_plc_init(&(bta_hf_ct_plc.plc_state)); + bta_hf_dec_init(); + bta_hf_enc_init(); + + return; + +error_exit:; +#if (HFP_DYNAMIC_MEMORY == TRUE) + if (hf_sbc_decoder_context_ptr) { + osi_free(hf_sbc_decoder_context_ptr); + hf_sbc_decoder_context_ptr = NULL; + } + if (hf_sbc_decoder_context_data) { + osi_free(hf_sbc_decoder_context_data); + hf_sbc_decoder_context_data = NULL; + } + if (hf_sbc_decode_pcm_data) { + osi_free(hf_sbc_decode_pcm_data); + hf_sbc_decode_pcm_data = NULL; + } + if (hf_sbc_encoder_ptr) { + osi_free(hf_sbc_encoder_ptr); + hf_sbc_encoder_ptr = NULL; + } + +#if (PLC_INCLUDED == TRUE) + if (bta_hf_ct_plc_ptr) { + osi_free(bta_hf_ct_plc_ptr); + bta_hf_ct_plc_ptr = NULL; + } #endif ///(PLC_INCLUDED == TRUE) + +#endif /// (HFP_DYNAMIC_MEMORY == TRUE) + } else { + // Nothing to do + } + + return; } /******************************************************************************* @@ -133,14 +266,66 @@ void bta_hf_client_sco_co_close(void) { APPL_TRACE_EVENT("%s", __FUNCTION__); + if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { #if (PLC_INCLUDED == TRUE) - sbc_plc_deinit(&(bta_hf_ct_plc.plc_state)); + sbc_plc_deinit(&(bta_hf_ct_plc.plc_state)); + bta_hf_ct_plc.first_good_frame_found = FALSE; #if (HFP_DYNAMIC_MEMORY == TRUE) - osi_free(bta_hf_ct_plc_ptr); + osi_free(bta_hf_ct_plc_ptr); #endif /// (HFP_DYNAMIC_MEMORY == TRUE) #endif ///(PLC_INCLUDED == TRUE) + +#if (HFP_DYNAMIC_MEMORY == TRUE) + osi_free(hf_sbc_decoder_context_ptr); + hf_sbc_decoder_context_ptr = NULL; + + osi_free(hf_sbc_decoder_context_data); + hf_sbc_decoder_context_data = NULL; + + osi_free(hf_sbc_decode_pcm_data); + hf_sbc_decode_pcm_data = NULL; + + osi_free(hf_sbc_encoder_ptr); + hf_sbc_encoder_ptr = NULL; +#endif /* HFP_DYNAMIC_MEMORY == TRUE */ + } else { + // Nothing to do + } +} + +/******************************************************************************* +** +** Function bta_hf_client_h2_header +** +** Description This function is called to fill in H2 header +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_h2_header(UINT16 *p_buf) +{ + // H2: Header with synchronization word and sequence number +#define BTA_HF_H2_HEADER 0x0801 +#define BTA_HF_H2_HEADER_BIT0_MASK (1 << 0) +#define BTA_HF_H2_HEADER_BIT1_MASK (1 << 1) +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 12 +#define BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 13 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 14 +#define BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 15 + + UINT16 h2_header = BTA_HF_H2_HEADER; + UINT8 h2_header_sn0 = hf_sequence_number & BTA_HF_H2_HEADER_BIT0_MASK; + UINT8 h2_header_sn1 = hf_sequence_number & BTA_HF_H2_HEADER_BIT1_MASK; + h2_header |= (h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 + | h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 + | h2_header_sn1 << (BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 - 1) + | h2_header_sn1 << (BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 - 1) + ); + + hf_sequence_number++; + *p_buf = h2_header; } /******************************************************************************* @@ -152,9 +337,101 @@ void bta_hf_client_sco_co_close(void) ** Returns number of bytes got from application ** *******************************************************************************/ -uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz) +uint32_t bta_hf_client_sco_co_out_data(UINT8 *p_buf) { - return btc_hf_client_outgoing_data_cb_to_app(p_buf, sz); + if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { + // CVSD + return btc_hf_client_outgoing_data_cb_to_app(p_buf, hf_pkt_size); + } else if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { + // mSBC + UINT32 size = btc_hf_client_outgoing_data_cb_to_app((UINT8 *)hf_sbc_encoder.as16PcmBuffer, HF_SBC_ENC_PCM_DATA_LEN); + if (size != HF_SBC_ENC_PCM_DATA_LEN){ + return 0; + } + + bta_hf_client_h2_header((UINT16 *)p_buf); + hf_sbc_encoder.pu8Packet = p_buf + 2; + + SBC_Encoder(&hf_sbc_encoder); + if (hf_sbc_encoder.u16PacketLength == BTM_ESCO_DATA_SIZE) { + return BTM_ESCO_DATA_SIZE_MAX; + } else { + return 0; + } + } else { + APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); + return 0; + } +} + +/******************************************************************************* +** +** Function bta_hf_client_decode_msbc_frame +** +** Description This function is called decode a mSBC frame +** +** Returns void +** +*******************************************************************************/ +static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN is_bad_frame){ + OI_STATUS status; + const OI_BYTE *zero_signal_frame_data; + UINT8 zero_signal_frame_len = BTM_ESCO_DATA_SIZE; + UINT32 sbc_frame_len = HF_SBC_DEC_PCM_DATA_LEN; + + if (is_bad_frame){ + status = OI_CODEC_SBC_CHECKSUM_MISMATCH; + } else { + status = OI_CODEC_SBC_DecodeFrame(&hf_sbc_decoder_context, (const OI_BYTE **)data, + (OI_UINT32 *)length, + (OI_INT16 *)hf_sbc_decode_pcm_data, + (OI_UINT32 *)&sbc_frame_len); + } + +// PLC_INCLUDED will be set to TRUE when enabling Wide Band Speech +#if (PLC_INCLUDED == TRUE) + switch(status){ + case OI_OK: + bta_hf_ct_plc.first_good_frame_found = TRUE; + sbc_plc_good_frame(&(bta_hf_ct_plc.plc_state), (int16_t *)hf_sbc_decode_pcm_data, bta_hf_ct_plc.sbc_plc_out); + case OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA: + case OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA: + case OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA: + break; + case OI_CODEC_SBC_NO_SYNCWORD: + case OI_CODEC_SBC_CHECKSUM_MISMATCH: + if (!bta_hf_ct_plc.first_good_frame_found) { + break; + } + zero_signal_frame_data = sbc_plc_zero_signal_frame(); + sbc_frame_len = HF_SBC_DEC_PCM_DATA_LEN; + status = OI_CODEC_SBC_DecodeFrame(&hf_sbc_decoder_context, &zero_signal_frame_data, + (OI_UINT32 *)&zero_signal_frame_len, + (OI_INT16 *)hf_sbc_decode_pcm_data, + (OI_UINT32 *)&sbc_frame_len); + + sbc_plc_bad_frame(&(bta_hf_ct_plc.plc_state), hf_sbc_decode_pcm_data, bta_hf_ct_plc.sbc_plc_out); + break; + case OI_STATUS_INVALID_PARAMETERS: + // This caused by corrupt frames. + // The codec apparently does not recover from this. + // Re-initialize the codec. + APPL_TRACE_ERROR("Frame decode error: OI_STATUS_INVALID_PARAMETERS"); + + if (!OI_SUCCESS(OI_CODEC_SBC_DecoderReset(&hf_sbc_decoder_context, hf_sbc_decoder_context_data, + HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 1, 1, FALSE, TRUE))) { + APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); + } + break; + default: + APPL_TRACE_ERROR("Frame decode error: %d", status); + break; + } +#endif ///(PLC_INCLUDED == TRUE) + + if (OI_SUCCESS(status)){ + btc_hf_client_incoming_data_cb_to_app((const uint8_t *)(bta_hf_ct_plc.sbc_plc_out), sbc_frame_len); + } } /******************************************************************************* @@ -168,18 +445,40 @@ uint32_t bta_hf_client_sco_co_out_data(uint8_t *p_buf, uint32_t sz) *******************************************************************************/ void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) { - UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; - UINT8 pkt_size = 0; + UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; + UINT8 pkt_size = 0; + UINT16 handle, sco_index; - STREAM_SKIP_UINT16(p); + STREAM_TO_UINT16 (handle, p); STREAM_TO_UINT8 (pkt_size, p); - if(status != BTM_SCO_DATA_CORRECT){ - APPL_TRACE_DEBUG("%s: not a correct frame(%d).", __func__, status); + handle = BTMD_GET_HANDLE (handle); + sco_index = btm_find_scb_by_handle(handle); + tSCO_CONN *sco_p = &btm_cb.sco_cb.sco_db[sco_index]; + + if (sco_p->esco.data.air_mode == BTM_SCO_AIR_MODE_CVSD) { + // CVSD + if(status != BTM_SCO_DATA_CORRECT){ + APPL_TRACE_DEBUG("%s: not a correct frame(%d).", __func__, status); + } + btc_hf_client_incoming_data_cb_to_app(p, pkt_size); + } else if (sco_p->esco.data.air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { + // mSBC + BOOLEAN is_bad_frame = false; + UINT8 msbc_frame_size = BTM_ESCO_DATA_SIZE; + if (pkt_size < msbc_frame_size) { + is_bad_frame = true; + } + if (status != BTM_SCO_DATA_CORRECT) { + is_bad_frame = true; + } + UINT8 *data = p; + bta_hf_client_decode_msbc_frame(&data, &pkt_size, is_bad_frame); + } else { + APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, sco_p->esco.data.air_mode); } - btc_hf_client_incoming_data_cb_to_app(p, pkt_size); } #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */ -#endif /* #if (BTA_HF_INCLUDED == TRUE) */ +#endif /* #if (BTA_HF_INCLUDED == TRUE) */ \ No newline at end of file diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index 258c13d2d..0c57d0e16 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -87,6 +87,12 @@ #ifndef BTM_MAX_SCO_LINKS #define BTM_MAX_SCO_LINKS (1) #endif +#ifndef SBC_DEC_INCLUDED +#define SBC_DEC_INCLUDED TRUE +#endif +#ifndef SBC_ENC_INCLUDED +#define SBC_ENC_INCLUDED TRUE +#endif #endif /* CONFIG_HFP_HF_ENABLE */ #if CONFIG_BT_SSP_ENABLED @@ -152,13 +158,13 @@ #ifndef CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM #define BLE_ADV_REPORT_FLOW_CONTROL_NUM 100 -#else +#else #define BLE_ADV_REPORT_FLOW_CONTROL_NUM CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM #endif /* CONFIG_BTDM_BLE_ADV_REPORT_FLOW_CTRL_NUM */ #ifndef CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD #define BLE_ADV_REPORT_DISCARD_THRSHOLD 20 -#else +#else #define BLE_ADV_REPORT_DISCARD_THRSHOLD CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD #endif /* CONFIG_BTDM_BLE_ADV_REPORT_DISCARD_THRSHOLD */ @@ -610,6 +616,16 @@ #define BTM_SCO_DATA_SIZE_MAX 120 //240 #endif +/* max TX eSCO data packet size */ +#ifndef BTM_ESCO_DATA_SIZE_MAX +#define BTM_ESCO_DATA_SIZE_MAX 60 +#endif + +/* TX eSCO data packet size */ +#ifndef BTM_ESCO_DATA_SIZE +#define BTM_ESCO_DATA_SIZE 57 +#endif + /* The size in bytes of the BTM inquiry database. 5 As Default */ #ifndef BTM_INQ_DB_SIZE #define BTM_INQ_DB_SIZE 5 diff --git a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h index 6f3134895..643bd82cc 100644 --- a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h +++ b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h @@ -78,6 +78,9 @@ Declarations of codec functions, data types, and macros. #define OI_SBC_ENHANCED_SYNCWORD 0x9d #define OI_mSBC_SYNCWORD 0xad +#define OI_SBC_MODE_STD 0 +#define OI_SBC_MODE_MSBC 1 + /**@name Sampling frequencies */ /**@{*/ #define SBC_FREQ_16000 0 /**< The sampling frequency is 16 kHz. One possible value for the @a frequency parameter of OI_CODEC_SBC_EncoderConfigure() */ @@ -200,6 +203,7 @@ typedef struct { OI_UINT8 restrictSubbands; OI_UINT8 enhancedEnabled; OI_UINT8 bufferedBlocks; + OI_UINT8 sbc_mode; /* OI_SBC_MODE_STD or OI_SBC_MODE_MSBC */ } OI_CODEC_SBC_DECODER_CONTEXT; typedef struct { @@ -236,7 +240,8 @@ OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_UINT8 maxChannels, OI_UINT8 pcmStride, - OI_BOOL enhanced); + OI_BOOL enhanced, + OI_BOOL msbc_enable); /** * This function restricts the kind of SBC frames that the Decoder will diff --git a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h index 4e3897614..092d26f9a 100644 --- a/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h +++ b/components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h @@ -170,7 +170,8 @@ INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_BYTE maxChannels, OI_BYTE pcmStride, - OI_BOOL enhanced); + OI_BOOL enhanced, + OI_BOOL msbc_enable); INLINE OI_UINT16 OI_SBC_CalculateFrameAndHeaderlen(OI_CODEC_SBC_FRAME_INFO *frame, OI_UINT *headerLen_); diff --git a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c index 1e4d73995..f198f5793 100644 --- a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c +++ b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c @@ -47,7 +47,8 @@ INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_BYTE maxChannels, OI_BYTE pcmStride, - OI_BOOL enhanced) + OI_BOOL enhanced, + OI_BOOL msbc_enable) { OI_UINT i; OI_STATUS status; @@ -65,6 +66,12 @@ INLINE OI_STATUS internal_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, } #endif + if (msbc_enable) { + context->sbc_mode = OI_SBC_MODE_MSBC; + } else { + context->sbc_mode = OI_SBC_MODE_STD; + } + status = OI_CODEC_SBC_Alloc(&context->common, decoderData, decoderDataBytes, maxChannels, pcmStride); if (!OI_SUCCESS(status)) { diff --git a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c index b2cd75cec..553b4eddd 100644 --- a/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c +++ b/components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c @@ -79,9 +79,9 @@ PRIVATE OI_STATUS FindSyncword(OI_CODEC_SBC_DECODER_CONTEXT *context, return OI_CODEC_SBC_NO_SYNCWORD; } #else // SBC_ENHANCED - - while (*frameBytes && (**frameData != OI_SBC_SYNCWORD) - && (**frameData != OI_mSBC_SYNCWORD)) { + while (*frameBytes + && (!(context->sbc_mode == OI_SBC_MODE_STD && **frameData == OI_SBC_SYNCWORD)) + && (!(context->sbc_mode == OI_SBC_MODE_MSBC && **frameData == OI_mSBC_SYNCWORD))) { (*frameBytes)--; (*frameData)++; } @@ -230,9 +230,10 @@ OI_STATUS OI_CODEC_SBC_DecoderReset(OI_CODEC_SBC_DECODER_CONTEXT *context, OI_UINT32 decoderDataBytes, OI_UINT8 maxChannels, OI_UINT8 pcmStride, - OI_BOOL enhanced) + OI_BOOL enhanced, + OI_BOOL msbc_enable) { - return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced); + return internal_DecoderReset(context, decoderData, decoderDataBytes, maxChannels, pcmStride, enhanced, msbc_enable); } OI_STATUS OI_CODEC_SBC_DecodeFrame(OI_CODEC_SBC_DECODER_CONTEXT *context, diff --git a/components/bt/bluedroid/external/sbc/plc/sbc_plc.c b/components/bt/bluedroid/external/sbc/plc/sbc_plc.c index b44593082..dceae9a84 100644 --- a/components/bt/bluedroid/external/sbc/plc/sbc_plc.c +++ b/components/bt/bluedroid/external/sbc/plc/sbc_plc.c @@ -50,21 +50,25 @@ static float rcos[SBC_OLAL] = { // 0.96984631f,0.88302222f, 0.75f,0.58682409f, // 0.41317591f, 0.25f,0.11697778f,0.09015369f}; + static float SqrtByCarmack(const float x){ - int i; - float x2, y; + union { + int i; + float y; + } float_int; + + float x2; const float threehalfs = 1.5f; x2 = x * 0.5f; - y = x; - i = *(int *)&y; - i = 0x5f375a86 - (i >> 1); - y = *(float *)&i; - y = y * (threehalfs - (x2 * y *y)); - // y = y * (threehalfs - (x2 * y *y)); - // y = y * (threehalfs - (x2 * y *y)); + float_int.y = x; - return (x * y); + float_int.i = 0x5f375a86 - (float_int.i >> 1); + float_int.y = float_int.y * (threehalfs - (x2 * float_int.y * float_int.y)); + // float_int.y = float_int.y * (threehalfs - (x2 * float_int.y * float_int.y)); + // float_int.y = float_int.y * (threehalfs - (x2 * float_int.y * float_int.y)); + + return (x * float_int.y); } static float absolute(float x){ diff --git a/components/bt/bluedroid/stack/btm/include/btm_int.h b/components/bt/bluedroid/stack/btm/include/btm_int.h index 79c3eff72..455ce7ca3 100644 --- a/components/bt/bluedroid/stack/btm/include/btm_int.h +++ b/components/bt/bluedroid/stack/btm/include/btm_int.h @@ -320,6 +320,10 @@ typedef UINT8 *BTM_BD_NAME_PTR; /* Pointer to Device name */ typedef tBTM_SEC_CBACK tBTM_SEC_CALLBACK; +#define BTM_DATA_HANDLE_MASK 0x0FFF + +#define BTMD_GET_HANDLE(u16) (UINT16)((u16) & BTM_DATA_HANDLE_MASK) + typedef void (tBTM_SCO_IND_CBACK) (UINT16 sco_inx) ; /* MACROs to convert from SCO packet types mask to ESCO and back */ diff --git a/components/bt/bluedroid/stack/include/stack/btm_api.h b/components/bt/bluedroid/stack/include/stack/btm_api.h index 6aa833c03..03a0e79d4 100644 --- a/components/bt/bluedroid/stack/include/stack/btm_api.h +++ b/components/bt/bluedroid/stack/include/stack/btm_api.h @@ -992,7 +992,7 @@ typedef UINT8 tBTM_SCO_AIR_MODE_TYPE; #define BTM_VOICE_SETTING_TRANS ((UINT16) (HCI_INP_CODING_LINEAR | \ HCI_INP_DATA_FMT_2S_COMPLEMENT | \ - HCI_INP_SAMPLE_SIZE_16BIT | \ + HCI_INP_SAMPLE_SIZE_8BIT | \ HCI_AIR_CODING_FORMAT_TRANSPNT)) /******************* From fcf4886172fe811395ba4bb83433bdeb1dad381d Mon Sep 17 00:00:00 2001 From: baohongde Date: Wed, 15 May 2019 21:35:31 +0800 Subject: [PATCH 6/6] components/bt: Support EV3 packet type --- .../bta/hf_client/bta_hf_client_sco.c | 14 +- .../bta/hf_client/include/bta_hf_client_int.h | 4 +- .../bta/include/bta/bta_hf_client_co.h | 2 +- .../profile/std/hf_client/bta_hf_client_co.c | 250 ++++++++++-------- .../common/include/common/bt_target.h | 8 +- 5 files changed, 149 insertions(+), 129 deletions(-) diff --git a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c index e9396f14a..a519eeebe 100644 --- a/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c +++ b/components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c @@ -283,11 +283,11 @@ static void bta_hf_client_sco_conn_cback(UINT16 sco_idx) bta_hf_client_cb.scb.retrans_window = sco_data.retrans_window; bta_hf_client_cb.scb.air_mode = sco_data.air_mode; if (sco_data.air_mode == BTM_SCO_AIR_MODE_CVSD) { - bta_hf_client_cb.scb.tx_pkt_len = sco_data.tx_pkt_len * 2; - bta_hf_client_cb.scb.rx_pkt_len = sco_data.rx_pkt_len * 2; + bta_hf_client_cb.scb.out_pkt_len = sco_data.tx_pkt_len * 2; + bta_hf_client_cb.scb.in_pkt_len = sco_data.rx_pkt_len * 2; } else { - bta_hf_client_cb.scb.tx_pkt_len = sco_data.tx_pkt_len; - bta_hf_client_cb.scb.rx_pkt_len = sco_data.rx_pkt_len; + bta_hf_client_cb.scb.out_pkt_len = sco_data.tx_pkt_len; + bta_hf_client_cb.scb.in_pkt_len = sco_data.rx_pkt_len; } if ((p_buf = (BT_HDR *) osi_malloc(sizeof(BT_HDR))) != NULL) { @@ -447,7 +447,7 @@ static void bta_hf_client_sco_event(UINT8 event) UINT16 len_to_send = 0; while (true) { - p_buf = osi_calloc(sizeof(BT_HDR) + pkt_offset + p_scb->tx_pkt_len); + p_buf = osi_calloc(sizeof(BT_HDR) + pkt_offset + p_scb->out_pkt_len); if (!p_buf) { APPL_TRACE_WARNING("%s, no mem", __FUNCTION__); break; @@ -456,7 +456,7 @@ static void bta_hf_client_sco_event(UINT8 event) p_buf->offset = pkt_offset; len_to_send = bta_hf_client_sco_co_out_data(p_buf->data + pkt_offset); p_buf->len = len_to_send; - if (len_to_send == p_scb->tx_pkt_len) { + if (len_to_send == p_scb->out_pkt_len) { // expect to get the exact size of data from upper layer if (bta_hf_client_cb.scb.sco_state == BTA_HF_CLIENT_SCO_OPEN_ST) { tBTM_STATUS write_stat = BTM_WriteScoData(p_scb->sco_idx, p_buf); @@ -747,7 +747,7 @@ void bta_hf_client_sco_conn_open(tBTA_HF_CLIENT_DATA *p_data) bta_hf_client_co_audio_state(bta_hf_client_cb.scb.sco_idx, SCO_STATE_ON, 0); /* open SCO codec if SCO is routed through transport */ bta_hf_client_sco_co_open(bta_hf_client_cb.scb.sco_idx, bta_hf_client_cb.scb.air_mode, - bta_hf_client_cb.scb.tx_pkt_len, BTA_HF_CLIENT_CI_SCO_DATA_EVT); + bta_hf_client_cb.scb.out_pkt_len, BTA_HF_CLIENT_CI_SCO_DATA_EVT); #endif if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) { diff --git a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h index b5b07b9c5..60dfc759c 100644 --- a/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h +++ b/components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h @@ -158,8 +158,8 @@ typedef struct { TIMER_LIST_ENT colli_timer; /* Collision timer */ BOOLEAN colli_tmr_on; /* TRUE if collision timer is active */ - UINT16 rx_pkt_len; - UINT16 tx_pkt_len; + UINT16 in_pkt_len; + UINT16 out_pkt_len; UINT8 link_type; /* BTM_LINK_TYPE_SCO or BTM_LINK_TYPE_ESCO */ UINT8 tx_interval; UINT8 retrans_window; diff --git a/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h index eef1c6668..ec1e35ce8 100644 --- a/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h +++ b/components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h @@ -73,7 +73,7 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw, ** Returns void ** *******************************************************************************/ -void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 pkt_size, UINT16 event); +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 inout_pkt_size, UINT16 event); /******************************************************************************* ** diff --git a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c index 6b3830b5e..6e756fc6c 100644 --- a/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c +++ b/components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c @@ -22,8 +22,6 @@ #if (BTM_SCO_HCI_INCLUDED == TRUE) -#include "btm_int.h" -#include "stack/btm_api.h" #include "oi_codec_sbc.h" #include "oi_status.h" #include "sbc_encoder.h" @@ -48,28 +46,35 @@ static bta_hf_ct_plc_t *bta_hf_ct_plc_ptr; #define HF_SBC_DEC_CONTEXT_DATA_LEN (CODEC_DATA_WORDS(1, SBC_CODEC_FAST_FILTER_BUFFERS)) -#define HF_SBC_DEC_PCM_DATA_LEN 240 -#define HF_SBC_ENC_PCM_DATA_LEN 240 +#define HF_SBC_DEC_RAW_DATA_SIZE 240 +#define HF_SBC_ENC_RAW_DATA_SIZE 240 + +/* BTA-HF-CO control block to map bdaddr to BTA handle */ +typedef struct +{ + OI_CODEC_SBC_DECODER_CONTEXT decoder_context; + OI_UINT32 decoder_context_data[HF_SBC_DEC_CONTEXT_DATA_LEN]; + OI_INT16 decode_raw_data[HF_SBC_DEC_RAW_DATA_SIZE]; + + SBC_ENC_PARAMS encoder; + + UINT8 sequence_number; + bool is_bad_frame; + bool decode_first_pkt; + OI_BYTE decode_msbc_data[BTM_MSBC_FRAME_SIZE]; + bool encode_first_pkt; + OI_BYTE encode_msbc_data[BTM_MSBC_FRAME_SIZE]; +} bta_hf_client_co_cb_t; #if HFP_DYNAMIC_MEMORY == FALSE -static OI_CODEC_SBC_DECODER_CONTEXT hf_sbc_decoder_context; -static OI_UINT32 hf_sbc_decoder_context_data[HF_SBC_DEC_CONTEXT_DATA_LEN]; -static OI_INT16 hf_sbc_decode_pcm_data[HF_SBC_DEC_PCM_DATA_LEN]; - -static SBC_ENC_PARAMS hf_sbc_encoder; +static bta_hf_client_co_cb_t bta_hf_client_co_cb; #else -static OI_CODEC_SBC_DECODER_CONTEXT *hf_sbc_decoder_context_ptr; -static OI_UINT32 *hf_sbc_decoder_context_data; -static OI_INT16 *hf_sbc_decode_pcm_data; -#define hf_sbc_decoder_context (*hf_sbc_decoder_context_ptr) - -static SBC_ENC_PARAMS *hf_sbc_encoder_ptr; -#define hf_sbc_encoder (*hf_sbc_encoder_ptr) +static bta_hf_client_co_cb_t *bta_hf_client_co_cb_ptr; +#define bta_hf_client_co_cb (*bta_hf_client_co_cb_ptr) #endif /* HFP_DYNAMIC_MEMORY == FALSE */ -static UINT8 hf_sequence_number = 0; static UINT8 hf_air_mode; -static UINT8 hf_pkt_size; +static UINT8 hf_inout_pkt_size; /******************************************************************************* ** @@ -137,7 +142,7 @@ static void bta_hf_dec_init(void) { OI_STATUS status; - status = OI_CODEC_SBC_DecoderReset(&hf_sbc_decoder_context, hf_sbc_decoder_context_data, + status = OI_CODEC_SBC_DecoderReset(&bta_hf_client_co_cb.decoder_context, bta_hf_client_co_cb.decoder_context_data, HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 1, 1, FALSE, TRUE); if (!OI_SUCCESS(status)) { APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); @@ -154,18 +159,21 @@ static void bta_hf_dec_init(void) { ** *******************************************************************************/ static void bta_hf_enc_init(void) { - hf_sequence_number = 0; + bta_hf_client_co_cb.sequence_number = 0; + bta_hf_client_co_cb.decode_first_pkt = true; + bta_hf_client_co_cb.encode_first_pkt = true; + bta_hf_client_co_cb.is_bad_frame = false; - hf_sbc_encoder.sbc_mode = SBC_MODE_MSBC; - hf_sbc_encoder.s16NumOfBlocks = 15; - hf_sbc_encoder.s16NumOfSubBands = 8; - hf_sbc_encoder.s16AllocationMethod = SBC_LOUDNESS; - hf_sbc_encoder.s16BitPool = 26; - hf_sbc_encoder.s16ChannelMode = SBC_MONO; - hf_sbc_encoder.s16NumOfChannels = 1; - hf_sbc_encoder.s16SamplingFreq = SBC_sf16000; + bta_hf_client_co_cb.encoder.sbc_mode = SBC_MODE_MSBC; + bta_hf_client_co_cb.encoder.s16NumOfBlocks = 15; + bta_hf_client_co_cb.encoder.s16NumOfSubBands = 8; + bta_hf_client_co_cb.encoder.s16AllocationMethod = SBC_LOUDNESS; + bta_hf_client_co_cb.encoder.s16BitPool = 26; + bta_hf_client_co_cb.encoder.s16ChannelMode = SBC_MONO; + bta_hf_client_co_cb.encoder.s16NumOfChannels = 1; + bta_hf_client_co_cb.encoder.s16SamplingFreq = SBC_sf16000; - SBC_Encoder_Init(&(hf_sbc_encoder)); + SBC_Encoder_Init(&(bta_hf_client_co_cb.encoder)); } /******************************************************************************* @@ -178,28 +186,19 @@ static void bta_hf_enc_init(void) { ** Returns void ** *******************************************************************************/ -void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 pkt_size, UINT16 event) +void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 inout_pkt_size, UINT16 event) { APPL_TRACE_EVENT("%s hdl %x, pkt_sz %u, event %u", __FUNCTION__, handle, - pkt_size, event); + inout_pkt_size, event); hf_air_mode = air_mode; - hf_pkt_size = pkt_size; + hf_inout_pkt_size = inout_pkt_size; if (air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { #if (HFP_DYNAMIC_MEMORY == TRUE) - hf_sbc_decoder_context_ptr = osi_calloc(sizeof(OI_CODEC_SBC_DECODER_CONTEXT)); - hf_sbc_decoder_context_data = osi_calloc(HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32)); - hf_sbc_decode_pcm_data = osi_calloc(HF_SBC_DEC_PCM_DATA_LEN * sizeof(OI_INT16)); - if (!hf_sbc_decoder_context_ptr || !hf_sbc_decoder_context_data || !hf_sbc_decode_pcm_data) { - APPL_TRACE_ERROR("%s failed to allocate SBC decoder", __FUNCTION__); - goto error_exit; - } - - hf_sbc_encoder_ptr = osi_calloc(sizeof(SBC_ENC_PARAMS)); - - if (!hf_sbc_encoder_ptr) { - APPL_TRACE_ERROR("%s failed to allocate SBC encoder", __FUNCTION__); + bta_hf_client_co_cb_ptr = osi_calloc(sizeof(bta_hf_client_co_cb_t)); + if (!bta_hf_client_co_cb_ptr) { + APPL_TRACE_ERROR("%s allocate failed", __FUNCTION__); goto error_exit; } @@ -220,21 +219,9 @@ void bta_hf_client_sco_co_open(UINT16 handle, UINT8 air_mode, UINT8 pkt_size, UI error_exit:; #if (HFP_DYNAMIC_MEMORY == TRUE) - if (hf_sbc_decoder_context_ptr) { - osi_free(hf_sbc_decoder_context_ptr); - hf_sbc_decoder_context_ptr = NULL; - } - if (hf_sbc_decoder_context_data) { - osi_free(hf_sbc_decoder_context_data); - hf_sbc_decoder_context_data = NULL; - } - if (hf_sbc_decode_pcm_data) { - osi_free(hf_sbc_decode_pcm_data); - hf_sbc_decode_pcm_data = NULL; - } - if (hf_sbc_encoder_ptr) { - osi_free(hf_sbc_encoder_ptr); - hf_sbc_encoder_ptr = NULL; + if (bta_hf_client_co_cb_ptr) { + osi_free(bta_hf_client_co_cb_ptr); + bta_hf_client_co_cb_ptr = NULL; } #if (PLC_INCLUDED == TRUE) @@ -273,22 +260,14 @@ void bta_hf_client_sco_co_close(void) #if (HFP_DYNAMIC_MEMORY == TRUE) osi_free(bta_hf_ct_plc_ptr); + bta_hf_ct_plc_ptr = NULL; #endif /// (HFP_DYNAMIC_MEMORY == TRUE) #endif ///(PLC_INCLUDED == TRUE) #if (HFP_DYNAMIC_MEMORY == TRUE) - osi_free(hf_sbc_decoder_context_ptr); - hf_sbc_decoder_context_ptr = NULL; - - osi_free(hf_sbc_decoder_context_data); - hf_sbc_decoder_context_data = NULL; - - osi_free(hf_sbc_decode_pcm_data); - hf_sbc_decode_pcm_data = NULL; - - osi_free(hf_sbc_encoder_ptr); - hf_sbc_encoder_ptr = NULL; + osi_free(bta_hf_client_co_cb_ptr); + bta_hf_client_co_cb_ptr = NULL; #endif /* HFP_DYNAMIC_MEMORY == TRUE */ } else { // Nothing to do @@ -316,15 +295,15 @@ static void bta_hf_client_h2_header(UINT16 *p_buf) #define BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 15 UINT16 h2_header = BTA_HF_H2_HEADER; - UINT8 h2_header_sn0 = hf_sequence_number & BTA_HF_H2_HEADER_BIT0_MASK; - UINT8 h2_header_sn1 = hf_sequence_number & BTA_HF_H2_HEADER_BIT1_MASK; + UINT8 h2_header_sn0 = bta_hf_client_co_cb.sequence_number & BTA_HF_H2_HEADER_BIT0_MASK; + UINT8 h2_header_sn1 = bta_hf_client_co_cb.sequence_number & BTA_HF_H2_HEADER_BIT1_MASK; h2_header |= (h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET1 | h2_header_sn0 << BTA_HF_H2_HEADER_SN0_BIT_OFFSET2 | h2_header_sn1 << (BTA_HF_H2_HEADER_SN1_BIT_OFFSET1 - 1) | h2_header_sn1 << (BTA_HF_H2_HEADER_SN1_BIT_OFFSET2 - 1) ); - hf_sequence_number++; + bta_hf_client_co_cb.sequence_number++; *p_buf = h2_header; } @@ -341,27 +320,52 @@ uint32_t bta_hf_client_sco_co_out_data(UINT8 *p_buf) { if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { // CVSD - return btc_hf_client_outgoing_data_cb_to_app(p_buf, hf_pkt_size); + uint32_t hf_raw_pkt_size = hf_inout_pkt_size; + return btc_hf_client_outgoing_data_cb_to_app(p_buf, hf_raw_pkt_size); } else if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { // mSBC - UINT32 size = btc_hf_client_outgoing_data_cb_to_app((UINT8 *)hf_sbc_encoder.as16PcmBuffer, HF_SBC_ENC_PCM_DATA_LEN); - if (size != HF_SBC_ENC_PCM_DATA_LEN){ - return 0; - } - bta_hf_client_h2_header((UINT16 *)p_buf); - hf_sbc_encoder.pu8Packet = p_buf + 2; + if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE / 2) { + if (bta_hf_client_co_cb.encode_first_pkt){ + UINT32 size = btc_hf_client_outgoing_data_cb_to_app((UINT8 *)bta_hf_client_co_cb.encoder.as16PcmBuffer, HF_SBC_ENC_RAW_DATA_SIZE); + if (size != HF_SBC_ENC_RAW_DATA_SIZE){ + return 0; + } - SBC_Encoder(&hf_sbc_encoder); - if (hf_sbc_encoder.u16PacketLength == BTM_ESCO_DATA_SIZE) { - return BTM_ESCO_DATA_SIZE_MAX; + bta_hf_client_h2_header((UINT16 *)bta_hf_client_co_cb.encode_msbc_data); + bta_hf_client_co_cb.encoder.pu8Packet = bta_hf_client_co_cb.encode_msbc_data + 2; + + SBC_Encoder(&bta_hf_client_co_cb.encoder); + memcpy(p_buf, bta_hf_client_co_cb.encode_msbc_data, hf_inout_pkt_size); + bta_hf_client_co_cb.encode_first_pkt = !bta_hf_client_co_cb.encode_first_pkt; + return hf_inout_pkt_size; + } else { + memcpy(p_buf, bta_hf_client_co_cb.encode_msbc_data + hf_inout_pkt_size, hf_inout_pkt_size); + bta_hf_client_co_cb.encode_first_pkt = !bta_hf_client_co_cb.encode_first_pkt; + return hf_inout_pkt_size; + } + + } else if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE) { + UINT32 size = btc_hf_client_outgoing_data_cb_to_app((UINT8 *)bta_hf_client_co_cb.encoder.as16PcmBuffer, HF_SBC_ENC_RAW_DATA_SIZE); + if (size != HF_SBC_ENC_RAW_DATA_SIZE){ + return 0; + } + + bta_hf_client_h2_header((UINT16 *)p_buf); + bta_hf_client_co_cb.encoder.pu8Packet = p_buf + 2; + + SBC_Encoder(&bta_hf_client_co_cb.encoder); + return hf_inout_pkt_size; } else { - return 0; + //Never run to here. } + + + } else { APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); - return 0; } + return 0; } /******************************************************************************* @@ -376,16 +380,16 @@ uint32_t bta_hf_client_sco_co_out_data(UINT8 *p_buf) static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN is_bad_frame){ OI_STATUS status; const OI_BYTE *zero_signal_frame_data; - UINT8 zero_signal_frame_len = BTM_ESCO_DATA_SIZE; - UINT32 sbc_frame_len = HF_SBC_DEC_PCM_DATA_LEN; + UINT8 zero_signal_frame_len = BTM_MSBC_FRAME_DATA_SIZE; + UINT32 sbc_raw_data_size = HF_SBC_DEC_RAW_DATA_SIZE; if (is_bad_frame){ status = OI_CODEC_SBC_CHECKSUM_MISMATCH; } else { - status = OI_CODEC_SBC_DecodeFrame(&hf_sbc_decoder_context, (const OI_BYTE **)data, + status = OI_CODEC_SBC_DecodeFrame(&bta_hf_client_co_cb.decoder_context, (const OI_BYTE **)data, (OI_UINT32 *)length, - (OI_INT16 *)hf_sbc_decode_pcm_data, - (OI_UINT32 *)&sbc_frame_len); + (OI_INT16 *)bta_hf_client_co_cb.decode_raw_data, + (OI_UINT32 *)&sbc_raw_data_size); } // PLC_INCLUDED will be set to TRUE when enabling Wide Band Speech @@ -393,7 +397,7 @@ static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN switch(status){ case OI_OK: bta_hf_ct_plc.first_good_frame_found = TRUE; - sbc_plc_good_frame(&(bta_hf_ct_plc.plc_state), (int16_t *)hf_sbc_decode_pcm_data, bta_hf_ct_plc.sbc_plc_out); + sbc_plc_good_frame(&(bta_hf_ct_plc.plc_state), (int16_t *)bta_hf_client_co_cb.decode_raw_data, bta_hf_ct_plc.sbc_plc_out); case OI_CODEC_SBC_NOT_ENOUGH_HEADER_DATA: case OI_CODEC_SBC_NOT_ENOUGH_BODY_DATA: case OI_CODEC_SBC_NOT_ENOUGH_AUDIO_DATA: @@ -404,13 +408,13 @@ static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN break; } zero_signal_frame_data = sbc_plc_zero_signal_frame(); - sbc_frame_len = HF_SBC_DEC_PCM_DATA_LEN; - status = OI_CODEC_SBC_DecodeFrame(&hf_sbc_decoder_context, &zero_signal_frame_data, + sbc_raw_data_size = HF_SBC_DEC_RAW_DATA_SIZE; + status = OI_CODEC_SBC_DecodeFrame(&bta_hf_client_co_cb.decoder_context, &zero_signal_frame_data, (OI_UINT32 *)&zero_signal_frame_len, - (OI_INT16 *)hf_sbc_decode_pcm_data, - (OI_UINT32 *)&sbc_frame_len); - - sbc_plc_bad_frame(&(bta_hf_ct_plc.plc_state), hf_sbc_decode_pcm_data, bta_hf_ct_plc.sbc_plc_out); + (OI_INT16 *)bta_hf_client_co_cb.decode_raw_data, + (OI_UINT32 *)&sbc_raw_data_size); + sbc_plc_bad_frame(&(bta_hf_ct_plc.plc_state), bta_hf_client_co_cb.decode_raw_data, bta_hf_ct_plc.sbc_plc_out); + APPL_TRACE_DEBUG("bad frame, using PLC to fix it."); break; case OI_STATUS_INVALID_PARAMETERS: // This caused by corrupt frames. @@ -418,7 +422,7 @@ static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN // Re-initialize the codec. APPL_TRACE_ERROR("Frame decode error: OI_STATUS_INVALID_PARAMETERS"); - if (!OI_SUCCESS(OI_CODEC_SBC_DecoderReset(&hf_sbc_decoder_context, hf_sbc_decoder_context_data, + if (!OI_SUCCESS(OI_CODEC_SBC_DecoderReset(&bta_hf_client_co_cb.decoder_context, bta_hf_client_co_cb.decoder_context_data, HF_SBC_DEC_CONTEXT_DATA_LEN * sizeof(OI_UINT32), 1, 1, FALSE, TRUE))) { APPL_TRACE_ERROR("OI_CODEC_SBC_DecoderReset failed with error code %d\n", status); } @@ -430,7 +434,7 @@ static void bta_hf_client_decode_msbc_frame(UINT8 **data, UINT8 *length, BOOLEAN #endif ///(PLC_INCLUDED == TRUE) if (OI_SUCCESS(status)){ - btc_hf_client_incoming_data_cb_to_app((const uint8_t *)(bta_hf_ct_plc.sbc_plc_out), sbc_frame_len); + btc_hf_client_incoming_data_cb_to_app((const uint8_t *)(bta_hf_ct_plc.sbc_plc_out), sbc_raw_data_size); } } @@ -447,35 +451,51 @@ void bta_hf_client_sco_co_in_data(BT_HDR *p_buf, tBTM_SCO_DATA_FLAG status) { UINT8 *p = (UINT8 *)(p_buf + 1) + p_buf->offset; UINT8 pkt_size = 0; - UINT16 handle, sco_index; - STREAM_TO_UINT16 (handle, p); + STREAM_SKIP_UINT16(p); STREAM_TO_UINT8 (pkt_size, p); - handle = BTMD_GET_HANDLE (handle); - sco_index = btm_find_scb_by_handle(handle); - tSCO_CONN *sco_p = &btm_cb.sco_cb.sco_db[sco_index]; - - if (sco_p->esco.data.air_mode == BTM_SCO_AIR_MODE_CVSD) { + if (hf_air_mode == BTM_SCO_AIR_MODE_CVSD) { // CVSD if(status != BTM_SCO_DATA_CORRECT){ APPL_TRACE_DEBUG("%s: not a correct frame(%d).", __func__, status); } btc_hf_client_incoming_data_cb_to_app(p, pkt_size); - } else if (sco_p->esco.data.air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { + } else if (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) { // mSBC - BOOLEAN is_bad_frame = false; - UINT8 msbc_frame_size = BTM_ESCO_DATA_SIZE; - if (pkt_size < msbc_frame_size) { - is_bad_frame = true; + UINT8 *data = NULL; + + if (pkt_size != hf_inout_pkt_size) { + bta_hf_client_co_cb.is_bad_frame = true; } if (status != BTM_SCO_DATA_CORRECT) { - is_bad_frame = true; + bta_hf_client_co_cb.is_bad_frame = true; + } + if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE / 2) { + if (bta_hf_client_co_cb.decode_first_pkt){ + if (!bta_hf_client_co_cb.is_bad_frame){ + memcpy(bta_hf_client_co_cb.decode_msbc_data, p, pkt_size); + } + } else { + if (!bta_hf_client_co_cb.is_bad_frame){ + memcpy(bta_hf_client_co_cb.decode_msbc_data + BTM_MSBC_FRAME_SIZE / 2, p, pkt_size); + } + + data = bta_hf_client_co_cb.decode_msbc_data; + bta_hf_client_decode_msbc_frame(&data, &pkt_size, bta_hf_client_co_cb.is_bad_frame); + bta_hf_client_co_cb.is_bad_frame = false; + } + bta_hf_client_co_cb.decode_first_pkt = !bta_hf_client_co_cb.decode_first_pkt; + + } else if (hf_inout_pkt_size == BTM_MSBC_FRAME_SIZE) { + data = p; + bta_hf_client_decode_msbc_frame(&data, &pkt_size, bta_hf_client_co_cb.is_bad_frame); + bta_hf_client_co_cb.is_bad_frame = false; + } else { + //Never run to here. } - UINT8 *data = p; - bta_hf_client_decode_msbc_frame(&data, &pkt_size, is_bad_frame); } else { - APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, sco_p->esco.data.air_mode); + APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode); } } diff --git a/components/bt/bluedroid/common/include/common/bt_target.h b/components/bt/bluedroid/common/include/common/bt_target.h index 0c57d0e16..0ea6939f8 100644 --- a/components/bt/bluedroid/common/include/common/bt_target.h +++ b/components/bt/bluedroid/common/include/common/bt_target.h @@ -617,13 +617,13 @@ #endif /* max TX eSCO data packet size */ -#ifndef BTM_ESCO_DATA_SIZE_MAX -#define BTM_ESCO_DATA_SIZE_MAX 60 +#ifndef BTM_MSBC_FRAME_SIZE +#define BTM_MSBC_FRAME_SIZE 60 #endif /* TX eSCO data packet size */ -#ifndef BTM_ESCO_DATA_SIZE -#define BTM_ESCO_DATA_SIZE 57 +#ifndef BTM_MSBC_FRAME_DATA_SIZE +#define BTM_MSBC_FRAME_DATA_SIZE 57 #endif /* The size in bytes of the BTM inquiry database. 5 As Default */