1a602f23dSMatthias Ringwald /* 2a602f23dSMatthias Ringwald * Copyright (C) 2023 BlueKitchen GmbH 3a602f23dSMatthias Ringwald * 4a602f23dSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5a602f23dSMatthias Ringwald * modification, are permitted provided that the following conditions 6a602f23dSMatthias Ringwald * are met: 7a602f23dSMatthias Ringwald * 8a602f23dSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9a602f23dSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10a602f23dSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11a602f23dSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12a602f23dSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13a602f23dSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14a602f23dSMatthias Ringwald * contributors may be used to endorse or promote products derived 15a602f23dSMatthias Ringwald * from this software without specific prior written permission. 16a602f23dSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17a602f23dSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18a602f23dSMatthias Ringwald * monetary gain. 19a602f23dSMatthias Ringwald * 20a602f23dSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21a602f23dSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22a602f23dSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23a602f23dSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24a602f23dSMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25a602f23dSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26a602f23dSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27a602f23dSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28a602f23dSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29a602f23dSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30a602f23dSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31a602f23dSMatthias Ringwald * SUCH DAMAGE. 32a602f23dSMatthias Ringwald * 33a602f23dSMatthias Ringwald * Please inquire about commercial licensing options at 34a602f23dSMatthias Ringwald * [email protected] 35a602f23dSMatthias Ringwald * 36a602f23dSMatthias Ringwald */ 37a602f23dSMatthias Ringwald 38a602f23dSMatthias Ringwald #define BTSTACK_FILE__ "hfp_codec.c" 39a602f23dSMatthias Ringwald 40a602f23dSMatthias Ringwald // ***************************************************************************** 41a602f23dSMatthias Ringwald // 42a602f23dSMatthias Ringwald // HFP Codec 43a602f23dSMatthias Ringwald // 44a602f23dSMatthias Ringwald // ***************************************************************************** 45a602f23dSMatthias Ringwald 46a602f23dSMatthias Ringwald #include "btstack_config.h" 47a602f23dSMatthias Ringwald 48a602f23dSMatthias Ringwald #include <string.h> 49a602f23dSMatthias Ringwald 50a602f23dSMatthias Ringwald #include "hfp_codec.h" 51a602f23dSMatthias Ringwald #include "btstack_debug.h" 52a602f23dSMatthias Ringwald 53eaf8fe31SMatthias Ringwald // enable to send test data 54eaf8fe31SMatthias Ringwald // #define HFP_CODEC_TEST 55eaf8fe31SMatthias Ringwald 56a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 57a602f23dSMatthias Ringwald #include "btstack_sbc.h" 58a602f23dSMatthias Ringwald #define FRAME_SIZE_MSBC 57 59a602f23dSMatthias Ringwald static void hfp_codec_encode_msbc(hfp_codec_t * hfp_codec, int16_t * pcm_samples); 60a602f23dSMatthias Ringwald #endif 61a602f23dSMatthias Ringwald 6216527ed5SMatthias Ringwald #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH 6316527ed5SMatthias Ringwald #define LC3_SWB_OCTETS_PER_FRAME 58 6416527ed5SMatthias Ringwald static void hfp_codec_encode_lc3swb(hfp_codec_t * hfp_codec, int16_t * pcm_samples); 6516527ed5SMatthias Ringwald #endif 6616527ed5SMatthias Ringwald 67bcdbf704SMatthias Ringwald // HFP H2 Framing - might get moved into a hfp_h2.c 68bcdbf704SMatthias Ringwald 69bcdbf704SMatthias Ringwald // const 70bcdbf704SMatthias Ringwald static const uint8_t hfp_h2_header_h2_byte_0 = 1; 71bcdbf704SMatthias Ringwald static const uint8_t hfp_h2_header_h2_byte_1_table[] = {0x08, 0x38, 0xc8, 0xf8 }; 72bcdbf704SMatthias Ringwald 73bcdbf704SMatthias Ringwald void hfp_h2_framing_init(hfp_h2_framing_t * hfp_h2_framing){ 74bcdbf704SMatthias Ringwald hfp_h2_framing->sequence_number = 0; 75bcdbf704SMatthias Ringwald } 76bcdbf704SMatthias Ringwald 77bcdbf704SMatthias Ringwald /** 78bcdbf704SMatthias Ringwald * @brief Add next H2 Header 79bcdbf704SMatthias Ringwald * @param hfp_h2_framing 80bcdbf704SMatthias Ringwald * @param buffer [2] 81bcdbf704SMatthias Ringwald */ 82bcdbf704SMatthias Ringwald void hfp_h2_framing_add_header(hfp_h2_framing_t * hfp_h2_framing, uint8_t * buffer){ 83bcdbf704SMatthias Ringwald // Synchronization Header H2 84bcdbf704SMatthias Ringwald buffer[0] = hfp_h2_header_h2_byte_0; 85bcdbf704SMatthias Ringwald buffer[1] = hfp_h2_header_h2_byte_1_table[hfp_h2_framing->sequence_number]; 86bcdbf704SMatthias Ringwald hfp_h2_framing->sequence_number = (hfp_h2_framing->sequence_number + 1) & 3; 87bcdbf704SMatthias Ringwald } 88bcdbf704SMatthias Ringwald 89*aeb2ea11SMatthias Ringwald void hfp_codec_init_msbc(hfp_codec_t * hfp_codec){ 90a602f23dSMatthias Ringwald memset(hfp_codec, 0, sizeof(hfp_codec_t)); 91a602f23dSMatthias Ringwald hfp_h2_framing_init(&hfp_codec->h2_framing); 92a602f23dSMatthias Ringwald hfp_codec->samples_per_frame = 120; 93a602f23dSMatthias Ringwald hfp_codec->encode = &hfp_codec_encode_msbc; 94a602f23dSMatthias Ringwald btstack_sbc_encoder_init(&hfp_codec->msbc_state, SBC_MODE_mSBC, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 16000, 26, SBC_CHANNEL_MODE_MONO); 95*aeb2ea11SMatthias Ringwald } 96*aeb2ea11SMatthias Ringwald 97*aeb2ea11SMatthias Ringwald void hfp_codec_init_lc3_swb(hfp_codec_t * hfp_codec, const btstack_lc3_encoder_t * lc3_encoder, void * lc3_encoder_context){ 98*aeb2ea11SMatthias Ringwald memset(hfp_codec, 0, sizeof(hfp_codec_t)); 99*aeb2ea11SMatthias Ringwald hfp_h2_framing_init(&hfp_codec->h2_framing); 10016527ed5SMatthias Ringwald hfp_codec->samples_per_frame = 240; 10116527ed5SMatthias Ringwald hfp_codec->encode = &hfp_codec_encode_lc3swb; 10216527ed5SMatthias Ringwald // init lc3 encoder 103*aeb2ea11SMatthias Ringwald hfp_codec->lc3_encoder = lc3_encoder; 104*aeb2ea11SMatthias Ringwald hfp_codec->lc3_encoder_context = lc3_encoder_context; 10516527ed5SMatthias Ringwald hfp_codec->lc3_encoder->configure(&hfp_codec->lc3_encoder_context, 32000, BTSTACK_LC3_FRAME_DURATION_7500US, LC3_SWB_OCTETS_PER_FRAME); 106a602f23dSMatthias Ringwald } 107a602f23dSMatthias Ringwald 108a602f23dSMatthias Ringwald bool hfp_codec_can_encode_audio_frame_now(const hfp_codec_t * hfp_codec){ 109f789a318SMatthias Ringwald return hfp_codec->write_pos <= SCO_FRAME_SIZE; 110a602f23dSMatthias Ringwald } 111a602f23dSMatthias Ringwald 112a602f23dSMatthias Ringwald uint16_t hfp_codec_num_audio_samples_per_frame(const hfp_codec_t * hfp_codec){ 113a602f23dSMatthias Ringwald return hfp_codec->samples_per_frame; 114a602f23dSMatthias Ringwald } 115a602f23dSMatthias Ringwald 116a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 117a602f23dSMatthias Ringwald static void hfp_codec_encode_msbc(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 118a602f23dSMatthias Ringwald // Encode SBC Frame 119a602f23dSMatthias Ringwald btstack_sbc_encoder_process_data(pcm_samples); 120f789a318SMatthias Ringwald (void)memcpy(&hfp_codec->sco_packet[hfp_codec->write_pos], btstack_sbc_encoder_sbc_buffer(), FRAME_SIZE_MSBC); 121a602f23dSMatthias Ringwald hfp_codec->write_pos += FRAME_SIZE_MSBC; 122f789a318SMatthias Ringwald // Final padding to use SCO_FRAME_SIZE bytes 123a602f23dSMatthias Ringwald hfp_codec->sco_packet[hfp_codec->write_pos++] = 0; 124a602f23dSMatthias Ringwald } 125a602f23dSMatthias Ringwald #endif 126a602f23dSMatthias Ringwald 12716527ed5SMatthias Ringwald #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH 12816527ed5SMatthias Ringwald static void hfp_codec_encode_lc3swb(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 12916527ed5SMatthias Ringwald // Encode LC3 Frame 13016527ed5SMatthias Ringwald hfp_codec->lc3_encoder->encode_signed_16(&hfp_codec->lc3_encoder_context, pcm_samples, 1, &hfp_codec->sco_packet[hfp_codec->write_pos]); 13116527ed5SMatthias Ringwald hfp_codec->write_pos += LC3_SWB_OCTETS_PER_FRAME; 13216527ed5SMatthias Ringwald } 13316527ed5SMatthias Ringwald #endif 13416527ed5SMatthias Ringwald 135a602f23dSMatthias Ringwald void hfp_codec_encode_audio_frame(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 136a602f23dSMatthias Ringwald btstack_assert(hfp_codec_can_encode_audio_frame_now(hfp_codec)); 137f789a318SMatthias Ringwald // Synchronization Header H2 138f789a318SMatthias Ringwald hfp_h2_framing_add_header(&hfp_codec->h2_framing, &hfp_codec->sco_packet[hfp_codec->write_pos]); 139f789a318SMatthias Ringwald hfp_codec->write_pos += 2; 140a602f23dSMatthias Ringwald // encode 141eaf8fe31SMatthias Ringwald #ifdef HFP_CODEC_TEST 142eaf8fe31SMatthias Ringwald // packet counter 143eaf8fe31SMatthias Ringwald static uint8_t counter = 0; 144eaf8fe31SMatthias Ringwald hfp_codec->sco_packet[hfp_codec->write_pos++] = counter++; 145eaf8fe31SMatthias Ringwald // test data 146eaf8fe31SMatthias Ringwald uint8_t i; 147eaf8fe31SMatthias Ringwald for (i=3;i<SCO_FRAME_SIZE;i++){ 148eaf8fe31SMatthias Ringwald hfp_codec->sco_packet[hfp_codec->write_pos++] = i; 149eaf8fe31SMatthias Ringwald } 150eaf8fe31SMatthias Ringwald #else 151a602f23dSMatthias Ringwald hfp_codec->encode(hfp_codec, pcm_samples); 152eaf8fe31SMatthias Ringwald #endif 153f789a318SMatthias Ringwald log_info("Encode frame, read %u, write %u", hfp_codec->read_pos, hfp_codec->write_pos); 154a602f23dSMatthias Ringwald } 155a602f23dSMatthias Ringwald 156a602f23dSMatthias Ringwald uint16_t hfp_codec_num_bytes_available(const hfp_codec_t * hfp_codec){ 157a602f23dSMatthias Ringwald return hfp_codec->write_pos - hfp_codec->read_pos; 158a602f23dSMatthias Ringwald } 159f789a318SMatthias Ringwald 160ffdcc4c7SMatthias Ringwald void hfp_codec_read_from_stream(hfp_codec_t * hfp_codec, uint8_t * buf, uint16_t size){ 161a602f23dSMatthias Ringwald uint16_t num_bytes_available = hfp_codec_num_bytes_available(hfp_codec); 162a602f23dSMatthias Ringwald btstack_assert(num_bytes_available >= size); 163a602f23dSMatthias Ringwald 164a602f23dSMatthias Ringwald uint16_t num_bytes_to_copy = btstack_min(num_bytes_available, size); 165a602f23dSMatthias Ringwald 166a602f23dSMatthias Ringwald memcpy(buf, &hfp_codec->sco_packet[hfp_codec->read_pos], num_bytes_to_copy); 167a602f23dSMatthias Ringwald hfp_codec->read_pos += num_bytes_to_copy; 168f789a318SMatthias Ringwald 169f789a318SMatthias Ringwald // reset buffer 170f789a318SMatthias Ringwald if (hfp_codec->read_pos == hfp_codec->write_pos){ 171f789a318SMatthias Ringwald hfp_codec->read_pos = 0; 172f789a318SMatthias Ringwald hfp_codec->write_pos = 0; 173f789a318SMatthias Ringwald } 174f789a318SMatthias Ringwald 175f789a318SMatthias Ringwald log_info("Read %u from stream, read %u, write %u", size, hfp_codec->read_pos, hfp_codec->write_pos); 176a602f23dSMatthias Ringwald } 177a602f23dSMatthias Ringwald 178a602f23dSMatthias Ringwald void hfp_codec_deinit(hfp_codec_t * hfp_codec){ 179a602f23dSMatthias Ringwald UNUSED(hfp_codec); 180a602f23dSMatthias Ringwald } 181