Просмотр исходного кода

Merge branch 'feature/btdm_msbc_codec' into 'master'

Wide Band Speech for HFP

See merge request idf/esp-idf!4854
Jiang Jiang Jian 6 лет назад
Родитель
Сommit
da13efc17a
24 измененных файлов с 1001 добавлено и 395 удалено
  1. 2 0
      components/bt/CMakeLists.txt
  2. 5 7
      components/bt/bluedroid/bta/hf_client/bta_hf_client_main.c
  3. 23 7
      components/bt/bluedroid/bta/hf_client/bta_hf_client_sco.c
  4. 7 0
      components/bt/bluedroid/bta/hf_client/include/bta_hf_client_int.h
  5. 2 2
      components/bt/bluedroid/bta/include/bta/bta_hf_client_co.h
  6. 1 1
      components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_sink.c
  7. 2 4
      components/bt/bluedroid/btc/profile/std/a2dp/btc_a2dp_source.c
  8. 375 8
      components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c
  9. 19 2
      components/bt/bluedroid/common/include/common/bt_target.h
  10. 7 1
      components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h
  11. 2 1
      components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc_private.h
  12. 35 5
      components/bt/bluedroid/external/sbc/decoder/srce/decoder-private.c
  13. 6 3
      components/bt/bluedroid/external/sbc/decoder/srce/decoder-sbc.c
  14. 7 0
      components/bt/bluedroid/external/sbc/encoder/include/sbc_encoder.h
  15. 94 164
      components/bt/bluedroid/external/sbc/encoder/srce/sbc_encoder.c
  16. 10 3
      components/bt/bluedroid/external/sbc/encoder/srce/sbc_packing.c
  17. 91 0
      components/bt/bluedroid/external/sbc/plc/include/sbc_plc.h
  18. 306 0
      components/bt/bluedroid/external/sbc/plc/sbc_plc.c
  19. 0 165
      components/bt/bluedroid/stack/a2dp/a2d_sbc.c
  20. 0 1
      components/bt/bluedroid/stack/a2dp/include/a2d_int.h
  21. 4 0
      components/bt/bluedroid/stack/btm/include/btm_int.h
  22. 0 20
      components/bt/bluedroid/stack/include/stack/a2d_sbc.h
  23. 1 1
      components/bt/bluedroid/stack/include/stack/btm_api.h
  24. 2 0
      components/bt/component.mk

+ 2 - 0
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"

+ 5 - 7
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;
 

+ 23 - 7
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.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.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) {
             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->out_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->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);
@@ -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.out_pkt_len, BTA_HF_CLIENT_CI_SCO_DATA_EVT);
 #endif
 
     if (bta_hf_client_cb.scb.negotiated_codec == BTM_SCO_CODEC_MSBC) {

+ 7 - 0
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              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;
+    UINT8               air_mode;
 } tBTA_HF_CLIENT_SCB;
 
 /* sco states */

+ 2 - 2
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 inout_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);
 
 /*******************************************************************************
 **

+ 1 - 1
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);
     }

+ 2 - 4
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();
 
@@ -1375,8 +1374,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--;

+ 375 - 8
components/bt/bluedroid/btc/profile/std/hf_client/bta_hf_client_co.c

@@ -15,9 +15,67 @@
 #include "bta/bta_hf_client_co.h"
 #include "hci/hci_audio.h"
 #include "btc_hf_client.h"
+#include "osi/allocator.h"
+#include <string.h>
+
 #if (BTA_HF_INCLUDED == TRUE)
 
 #if (BTM_SCO_HCI_INCLUDED == TRUE)
+
+#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;
+
+#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)
+
+
+#define HF_SBC_DEC_CONTEXT_DATA_LEN     (CODEC_DATA_WORDS(1, SBC_CODEC_FAST_FILTER_BUFFERS))
+#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 bta_hf_client_co_cb_t bta_hf_client_co_cb;
+#else
+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_air_mode;
+static UINT8 hf_inout_pkt_size;
+
 /*******************************************************************************
 **
 ** Function         bta_hf_client_co_audio_state
@@ -68,6 +126,56 @@ tBTA_HFP_SCO_ROUTE_TYPE bta_hf_client_sco_co_init(UINT32 rx_bw, UINT32 tx_bw,
     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(&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);
+    }
+}
+
+/*******************************************************************************
+ **
+ ** Function       bta_hf_enc_init
+ **
+ ** Description    Initialize encoding task
+ **
+ ** Returns        void
+ **
+ *******************************************************************************/
+static void bta_hf_enc_init(void) {
+    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;
+
+    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(&(bta_hf_client_co_cb.encoder));
+}
+
 /*******************************************************************************
 **
 ** Function         bta_hf_client_sco_co_open
@@ -78,10 +186,57 @@ 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 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_inout_pkt_size = inout_pkt_size;
+
+    if (air_mode == BTM_SCO_AIR_MODE_TRANSPNT) {
+#if (HFP_DYNAMIC_MEMORY == TRUE)
+        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;
+        }
+
+#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)
+
+    bta_hf_dec_init();
+    bta_hf_enc_init();
+
+    return;
+
+error_exit:;
+#if (HFP_DYNAMIC_MEMORY == TRUE)
+        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)
+        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;
 }
 
 /*******************************************************************************
@@ -97,6 +252,59 @@ 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 (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) {
+#if (PLC_INCLUDED == TRUE)
+        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);
+        bta_hf_ct_plc_ptr = NULL;
+#endif  /// (HFP_DYNAMIC_MEMORY == TRUE)
+
+#endif  ///(PLC_INCLUDED == TRUE)
+
+#if (HFP_DYNAMIC_MEMORY == TRUE)
+        osi_free(bta_hf_client_co_cb_ptr);
+        bta_hf_client_co_cb_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 = 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)
+                );
+
+    bta_hf_client_co_cb.sequence_number++;
+    *p_buf = h2_header;
 }
 
 /*******************************************************************************
@@ -108,9 +316,126 @@ 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
+        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
+
+        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;
+                }
+
+                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 {
+            //Never run to here.
+        }
+
+
+
+    } 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_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(&bta_hf_client_co_cb.decoder_context, (const OI_BYTE **)data,
+                                          (OI_UINT32 *)length,
+                                          (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
+#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 *)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:
+            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_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 *)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.
+            // 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(&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);
+            }
+            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_raw_data_size);
+    }
 }
 
 /*******************************************************************************
@@ -124,14 +449,56 @@ 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;
 
     STREAM_SKIP_UINT16(p);
     STREAM_TO_UINT8 (pkt_size, p);
-    btc_hf_client_incoming_data_cb_to_app(p, pkt_size);
+
+    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 (hf_air_mode == BTM_SCO_AIR_MODE_TRANSPNT) {
+        // mSBC
+        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) {
+            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.
+        }
+    } else {
+        APPL_TRACE_ERROR("%s invaild air mode: %d", __FUNCTION__, hf_air_mode);
+    }
 }
 
 #endif /* #if (BTM_SCO_HCI_INCLUDED == TRUE) */
 
-#endif /* #if (BTA_HF_INCLUDED == TRUE) */
+#endif /* #if (BTA_HF_INCLUDED == TRUE) */

+ 19 - 2
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
@@ -86,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
@@ -151,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 */
 
@@ -609,6 +616,16 @@
 #define BTM_SCO_DATA_SIZE_MAX       120 //240
 #endif
 
+/* max TX eSCO data packet size */
+#ifndef BTM_MSBC_FRAME_SIZE
+#define BTM_MSBC_FRAME_SIZE      60
+#endif
+
+/* TX eSCO data packet size */
+#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 */
 #ifndef BTM_INQ_DB_SIZE
 #define BTM_INQ_DB_SIZE             5

+ 7 - 1
components/bt/bluedroid/external/sbc/decoder/include/oi_codec_sbc.h

@@ -76,6 +76,10 @@ Declarations of codec functions, data types, and macros.
 
 #define OI_SBC_SYNCWORD 0x9c
 #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 */
 /**@{*/
@@ -199,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 {
@@ -235,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

+ 2 - 1
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_);
 

+ 35 - 5
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)) {
@@ -81,9 +88,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 +98,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] ==

+ 6 - 3
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
+        && (!(context->sbc_mode == OI_SBC_MODE_STD && **frameData == OI_SBC_SYNCWORD))
+        && (!(context->sbc_mode == OI_SBC_MODE_MSBC && **frameData == OI_mSBC_SYNCWORD))) {
         (*frameBytes)--;
         (*frameData)++;
     }
@@ -228,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,

+ 7 - 0
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*/

+ 94 - 164
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,8 @@ 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 */
@@ -300,82 +205,110 @@ 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->sbc_mode != SBC_MODE_MSBC) {
+        /* Required number of channels */
+        if (pstrEncParams->s16ChannelMode == SBC_MONO) {
+            pstrEncParams->s16NumOfChannels = 1;
+        } else {
+            pstrEncParams->s16NumOfChannels = 2;
+        }
 
-    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--;
+        /* 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->s16NumOfSubBands == 8) {
-            pstrEncParams->s16BitPool = (s16Bitpool > 255) ? 255 : s16Bitpool;
+        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 {
-            pstrEncParams->s16BitPool = (s16Bitpool > 128) ? 128 : s16Bitpool;
+            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 ) );
-
-        pstrEncParams->s16BitPool = (s16Bitpool >
-                                     (16 * pstrEncParams->s16NumOfSubBands))
-                                    ? (16 * pstrEncParams->s16NumOfSubBands) : s16Bitpool;
-    }
+        // mSBC
 
-    if (pstrEncParams->s16BitPool < 0) {
-        pstrEncParams->s16BitPool = 0;
-    }
-    /* sampling freq */
-    HeaderParams = ((pstrEncParams->s16SamplingFreq & 3) << 6);
+        // 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;
 
-    /* number of blocks*/
-    HeaderParams |= (((pstrEncParams->s16NumOfBlocks - 4) & 12) << 2);
+        /* Bit pool value: 26 */
+        pstrEncParams->s16BitPool = 26;
 
-    /* channel mode: mono, dual...*/
-    HeaderParams |= ((pstrEncParams->s16ChannelMode & 3) << 2);
+        /* number of subbands: 8 */
+        pstrEncParams->s16NumOfSubBands = 8;
 
-    /* Loudness or SNR */
-    HeaderParams |= ((pstrEncParams->s16AllocationMethod & 1) << 1);
-    HeaderParams |= ((pstrEncParams->s16NumOfSubBands >> 3) & 1);  /*4 or 8*/
-    pstrEncParams->FrameHeader = HeaderParams;
+        /* 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->s16NumOfSubBands == 4) {
         if (pstrEncParams->s16NumOfChannels == 1) {
@@ -395,9 +328,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) */

+ 10 - 3
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*/

+ 91 - 0
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 <stdint.h>
+
+#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

+ 306 - 0
components/bt/bluedroid/external/sbc/plc/sbc_plc.c

@@ -0,0 +1,306 @@
+// 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 <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#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){
+    union {
+        int i;
+        float y;
+    } float_int;
+
+    float x2;
+    const float threehalfs = 1.5f;
+
+    x2 = x * 0.5f;
+    float_int.y = x;
+
+    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){
+    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)

+ 0 - 165
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

+ 0 - 1
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;
 

+ 4 - 0
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 */

+ 0 - 20
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

+ 1 - 1
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))
 
 /*******************

+ 2 - 0
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         \