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 897555fa8bSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 900a4f399aSMatthias Ringwald void hfp_codec_init_msbc(hfp_codec_t * hfp_codec, btstack_sbc_encoder_state_t * msbc_encoder_context){ 91a602f23dSMatthias Ringwald memset(hfp_codec, 0, sizeof(hfp_codec_t)); 92a602f23dSMatthias Ringwald hfp_h2_framing_init(&hfp_codec->h2_framing); 93a602f23dSMatthias Ringwald hfp_codec->samples_per_frame = 120; 94a602f23dSMatthias Ringwald hfp_codec->encode = &hfp_codec_encode_msbc; 950a4f399aSMatthias Ringwald hfp_codec->msbc_encoder_context = msbc_encoder_context; 960a4f399aSMatthias Ringwald btstack_sbc_encoder_init(hfp_codec->msbc_encoder_context, SBC_MODE_mSBC, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 16000, 26, SBC_CHANNEL_MODE_MONO); 97aeb2ea11SMatthias Ringwald } 987555fa8bSMatthias Ringwald #endif 99aeb2ea11SMatthias Ringwald 100712c022aSMatthias Ringwald #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH 101aeb2ea11SMatthias Ringwald void hfp_codec_init_lc3_swb(hfp_codec_t * hfp_codec, const btstack_lc3_encoder_t * lc3_encoder, void * lc3_encoder_context){ 102aeb2ea11SMatthias Ringwald memset(hfp_codec, 0, sizeof(hfp_codec_t)); 103aeb2ea11SMatthias Ringwald hfp_h2_framing_init(&hfp_codec->h2_framing); 10416527ed5SMatthias Ringwald hfp_codec->samples_per_frame = 240; 10516527ed5SMatthias Ringwald hfp_codec->encode = &hfp_codec_encode_lc3swb; 10616527ed5SMatthias Ringwald // init lc3 encoder 107aeb2ea11SMatthias Ringwald hfp_codec->lc3_encoder = lc3_encoder; 108aeb2ea11SMatthias Ringwald hfp_codec->lc3_encoder_context = lc3_encoder_context; 10916527ed5SMatthias Ringwald hfp_codec->lc3_encoder->configure(&hfp_codec->lc3_encoder_context, 32000, BTSTACK_LC3_FRAME_DURATION_7500US, LC3_SWB_OCTETS_PER_FRAME); 110a602f23dSMatthias Ringwald } 111712c022aSMatthias Ringwald #endif 112a602f23dSMatthias Ringwald 113a602f23dSMatthias Ringwald bool hfp_codec_can_encode_audio_frame_now(const hfp_codec_t * hfp_codec){ 114f789a318SMatthias Ringwald return hfp_codec->write_pos <= SCO_FRAME_SIZE; 115a602f23dSMatthias Ringwald } 116a602f23dSMatthias Ringwald 117a602f23dSMatthias Ringwald uint16_t hfp_codec_num_audio_samples_per_frame(const hfp_codec_t * hfp_codec){ 118a602f23dSMatthias Ringwald return hfp_codec->samples_per_frame; 119a602f23dSMatthias Ringwald } 120a602f23dSMatthias Ringwald 121a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 122a602f23dSMatthias Ringwald static void hfp_codec_encode_msbc(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 123a602f23dSMatthias Ringwald // Encode SBC Frame 124a602f23dSMatthias Ringwald btstack_sbc_encoder_process_data(pcm_samples); 125f789a318SMatthias Ringwald (void)memcpy(&hfp_codec->sco_packet[hfp_codec->write_pos], btstack_sbc_encoder_sbc_buffer(), FRAME_SIZE_MSBC); 126a602f23dSMatthias Ringwald hfp_codec->write_pos += FRAME_SIZE_MSBC; 127f789a318SMatthias Ringwald // Final padding to use SCO_FRAME_SIZE bytes 128a602f23dSMatthias Ringwald hfp_codec->sco_packet[hfp_codec->write_pos++] = 0; 129a602f23dSMatthias Ringwald } 130a602f23dSMatthias Ringwald #endif 131a602f23dSMatthias Ringwald 13216527ed5SMatthias Ringwald #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH 13316527ed5SMatthias Ringwald static void hfp_codec_encode_lc3swb(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 13416527ed5SMatthias Ringwald // Encode LC3 Frame 13516527ed5SMatthias Ringwald hfp_codec->lc3_encoder->encode_signed_16(&hfp_codec->lc3_encoder_context, pcm_samples, 1, &hfp_codec->sco_packet[hfp_codec->write_pos]); 13616527ed5SMatthias Ringwald hfp_codec->write_pos += LC3_SWB_OCTETS_PER_FRAME; 13716527ed5SMatthias Ringwald } 13816527ed5SMatthias Ringwald #endif 13916527ed5SMatthias Ringwald 140a602f23dSMatthias Ringwald void hfp_codec_encode_audio_frame(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 141a602f23dSMatthias Ringwald btstack_assert(hfp_codec_can_encode_audio_frame_now(hfp_codec)); 142f789a318SMatthias Ringwald // Synchronization Header H2 143f789a318SMatthias Ringwald hfp_h2_framing_add_header(&hfp_codec->h2_framing, &hfp_codec->sco_packet[hfp_codec->write_pos]); 144f789a318SMatthias Ringwald hfp_codec->write_pos += 2; 145a602f23dSMatthias Ringwald // encode 146eaf8fe31SMatthias Ringwald #ifdef HFP_CODEC_TEST 147eaf8fe31SMatthias Ringwald // packet counter 148eaf8fe31SMatthias Ringwald static uint8_t counter = 0; 149eaf8fe31SMatthias Ringwald hfp_codec->sco_packet[hfp_codec->write_pos++] = counter++; 150eaf8fe31SMatthias Ringwald // test data 151eaf8fe31SMatthias Ringwald uint8_t i; 152eaf8fe31SMatthias Ringwald for (i=3;i<SCO_FRAME_SIZE;i++){ 153eaf8fe31SMatthias Ringwald hfp_codec->sco_packet[hfp_codec->write_pos++] = i; 154eaf8fe31SMatthias Ringwald } 155eaf8fe31SMatthias Ringwald #else 156a602f23dSMatthias Ringwald hfp_codec->encode(hfp_codec, pcm_samples); 157eaf8fe31SMatthias Ringwald #endif 158*7879c4f7SMatthias Ringwald log_debug("Encode frame, read %u, write %u", hfp_codec->read_pos, hfp_codec->write_pos); 159a602f23dSMatthias Ringwald } 160a602f23dSMatthias Ringwald 161a602f23dSMatthias Ringwald uint16_t hfp_codec_num_bytes_available(const hfp_codec_t * hfp_codec){ 162a602f23dSMatthias Ringwald return hfp_codec->write_pos - hfp_codec->read_pos; 163a602f23dSMatthias Ringwald } 164f789a318SMatthias Ringwald 165ffdcc4c7SMatthias Ringwald void hfp_codec_read_from_stream(hfp_codec_t * hfp_codec, uint8_t * buf, uint16_t size){ 166a602f23dSMatthias Ringwald uint16_t num_bytes_available = hfp_codec_num_bytes_available(hfp_codec); 167a602f23dSMatthias Ringwald btstack_assert(num_bytes_available >= size); 168a602f23dSMatthias Ringwald 169a602f23dSMatthias Ringwald uint16_t num_bytes_to_copy = btstack_min(num_bytes_available, size); 170a602f23dSMatthias Ringwald 171a602f23dSMatthias Ringwald memcpy(buf, &hfp_codec->sco_packet[hfp_codec->read_pos], num_bytes_to_copy); 172a602f23dSMatthias Ringwald hfp_codec->read_pos += num_bytes_to_copy; 173f789a318SMatthias Ringwald 174f789a318SMatthias Ringwald // reset buffer 175f789a318SMatthias Ringwald if (hfp_codec->read_pos == hfp_codec->write_pos){ 176f789a318SMatthias Ringwald hfp_codec->read_pos = 0; 177f789a318SMatthias Ringwald hfp_codec->write_pos = 0; 178f789a318SMatthias Ringwald } 179f789a318SMatthias Ringwald 180*7879c4f7SMatthias Ringwald log_debug("Read %u from stream, read %u, write %u", size, hfp_codec->read_pos, hfp_codec->write_pos); 181a602f23dSMatthias Ringwald } 182a602f23dSMatthias Ringwald 183a602f23dSMatthias Ringwald void hfp_codec_deinit(hfp_codec_t * hfp_codec){ 184a602f23dSMatthias Ringwald UNUSED(hfp_codec); 185a602f23dSMatthias Ringwald } 186