1*a602f23dSMatthias Ringwald /* 2*a602f23dSMatthias Ringwald * Copyright (C) 2023 BlueKitchen GmbH 3*a602f23dSMatthias Ringwald * 4*a602f23dSMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*a602f23dSMatthias Ringwald * modification, are permitted provided that the following conditions 6*a602f23dSMatthias Ringwald * are met: 7*a602f23dSMatthias Ringwald * 8*a602f23dSMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*a602f23dSMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*a602f23dSMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*a602f23dSMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*a602f23dSMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*a602f23dSMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*a602f23dSMatthias Ringwald * contributors may be used to endorse or promote products derived 15*a602f23dSMatthias Ringwald * from this software without specific prior written permission. 16*a602f23dSMatthias Ringwald * 4. Any redistribution, use, or modification is done solely for 17*a602f23dSMatthias Ringwald * personal benefit and not for any commercial purpose or for 18*a602f23dSMatthias Ringwald * monetary gain. 19*a602f23dSMatthias Ringwald * 20*a602f23dSMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21*a602f23dSMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22*a602f23dSMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23*a602f23dSMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24*a602f23dSMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25*a602f23dSMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26*a602f23dSMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27*a602f23dSMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28*a602f23dSMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29*a602f23dSMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30*a602f23dSMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31*a602f23dSMatthias Ringwald * SUCH DAMAGE. 32*a602f23dSMatthias Ringwald * 33*a602f23dSMatthias Ringwald * Please inquire about commercial licensing options at 34*a602f23dSMatthias Ringwald * [email protected] 35*a602f23dSMatthias Ringwald * 36*a602f23dSMatthias Ringwald */ 37*a602f23dSMatthias Ringwald 38*a602f23dSMatthias Ringwald #define BTSTACK_FILE__ "hfp_codec.c" 39*a602f23dSMatthias Ringwald 40*a602f23dSMatthias Ringwald // ***************************************************************************** 41*a602f23dSMatthias Ringwald // 42*a602f23dSMatthias Ringwald // HFP Codec 43*a602f23dSMatthias Ringwald // 44*a602f23dSMatthias Ringwald // ***************************************************************************** 45*a602f23dSMatthias Ringwald 46*a602f23dSMatthias Ringwald #include "btstack_config.h" 47*a602f23dSMatthias Ringwald 48*a602f23dSMatthias Ringwald #include <string.h> 49*a602f23dSMatthias Ringwald 50*a602f23dSMatthias Ringwald #include "hfp_codec.h" 51*a602f23dSMatthias Ringwald #include "btstack_debug.h" 52*a602f23dSMatthias Ringwald 53*a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 54*a602f23dSMatthias Ringwald #include "btstack_sbc.h" 55*a602f23dSMatthias Ringwald #define FRAME_SIZE_MSBC 57 56*a602f23dSMatthias Ringwald static void hfp_codec_encode_msbc(hfp_codec_t * hfp_codec, int16_t * pcm_samples); 57*a602f23dSMatthias Ringwald #endif 58*a602f23dSMatthias Ringwald 59*a602f23dSMatthias Ringwald #include "hfp_codec.h" 60*a602f23dSMatthias Ringwald 61*a602f23dSMatthias Ringwald void hfp_codec_init(hfp_codec_t * hfp_codec, uint8_t codec_id){ 62*a602f23dSMatthias Ringwald memset(hfp_codec, 0, sizeof(hfp_codec_t)); 63*a602f23dSMatthias Ringwald hfp_h2_framing_init(&hfp_codec->h2_framing); 64*a602f23dSMatthias Ringwald switch (codec_id){ 65*a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 66*a602f23dSMatthias Ringwald case HFP_CODEC_MSBC: 67*a602f23dSMatthias Ringwald hfp_codec->samples_per_frame = 120; 68*a602f23dSMatthias Ringwald hfp_codec->encode = &hfp_codec_encode_msbc; 69*a602f23dSMatthias Ringwald btstack_sbc_encoder_init(&hfp_codec->msbc_state, SBC_MODE_mSBC, 16, 8, SBC_ALLOCATION_METHOD_LOUDNESS, 16000, 26, SBC_CHANNEL_MODE_MONO); 70*a602f23dSMatthias Ringwald break; 71*a602f23dSMatthias Ringwald #endif 72*a602f23dSMatthias Ringwald default: 73*a602f23dSMatthias Ringwald btstack_assert(false); 74*a602f23dSMatthias Ringwald break; 75*a602f23dSMatthias Ringwald } 76*a602f23dSMatthias Ringwald } 77*a602f23dSMatthias Ringwald 78*a602f23dSMatthias Ringwald bool hfp_codec_can_encode_audio_frame_now(const hfp_codec_t * hfp_codec){ 79*a602f23dSMatthias Ringwald return hfp_codec->read_pos == hfp_codec->write_pos; 80*a602f23dSMatthias Ringwald } 81*a602f23dSMatthias Ringwald 82*a602f23dSMatthias Ringwald uint16_t hfp_codec_num_audio_samples_per_frame(const hfp_codec_t * hfp_codec){ 83*a602f23dSMatthias Ringwald return hfp_codec->samples_per_frame; 84*a602f23dSMatthias Ringwald } 85*a602f23dSMatthias Ringwald 86*a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 87*a602f23dSMatthias Ringwald static void hfp_codec_encode_msbc(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 88*a602f23dSMatthias Ringwald // Synchronization Header H2 89*a602f23dSMatthias Ringwald hfp_h2_framing_add_header(&hfp_codec->h2_framing, hfp_codec->sco_packet); 90*a602f23dSMatthias Ringwald hfp_codec->write_pos += 2; 91*a602f23dSMatthias Ringwald 92*a602f23dSMatthias Ringwald // Encode SBC Frame 93*a602f23dSMatthias Ringwald btstack_sbc_encoder_process_data(pcm_samples); 94*a602f23dSMatthias Ringwald (void)memcpy(&hfp_codec->sco_packet[hfp_codec->write_pos], 95*a602f23dSMatthias Ringwald btstack_sbc_encoder_sbc_buffer(), FRAME_SIZE_MSBC); 96*a602f23dSMatthias Ringwald hfp_codec->write_pos += FRAME_SIZE_MSBC; 97*a602f23dSMatthias Ringwald 98*a602f23dSMatthias Ringwald // Final padding to use 60 bytes 99*a602f23dSMatthias Ringwald hfp_codec->sco_packet[hfp_codec->write_pos++] = 0; 100*a602f23dSMatthias Ringwald } 101*a602f23dSMatthias Ringwald #endif 102*a602f23dSMatthias Ringwald 103*a602f23dSMatthias Ringwald void hfp_codec_encode_audio_frame(hfp_codec_t * hfp_codec, int16_t * pcm_samples){ 104*a602f23dSMatthias Ringwald btstack_assert(hfp_codec_can_encode_audio_frame_now(hfp_codec)); 105*a602f23dSMatthias Ringwald 106*a602f23dSMatthias Ringwald // reset packet buffer 107*a602f23dSMatthias Ringwald hfp_codec->read_pos = 0; 108*a602f23dSMatthias Ringwald hfp_codec->write_pos = 0; 109*a602f23dSMatthias Ringwald 110*a602f23dSMatthias Ringwald // encode 111*a602f23dSMatthias Ringwald hfp_codec->encode(hfp_codec, pcm_samples); 112*a602f23dSMatthias Ringwald } 113*a602f23dSMatthias Ringwald 114*a602f23dSMatthias Ringwald uint16_t hfp_codec_num_bytes_available(const hfp_codec_t * hfp_codec){ 115*a602f23dSMatthias Ringwald return hfp_codec->write_pos - hfp_codec->read_pos; 116*a602f23dSMatthias Ringwald } 117*a602f23dSMatthias Ringwald 118*a602f23dSMatthias Ringwald void hfp_msbc_read_from_stream(hfp_codec_t * hfp_codec, uint8_t * buf, int size){ 119*a602f23dSMatthias Ringwald uint16_t num_bytes_available = hfp_codec_num_bytes_available(hfp_codec); 120*a602f23dSMatthias Ringwald btstack_assert(num_bytes_available >= size); 121*a602f23dSMatthias Ringwald 122*a602f23dSMatthias Ringwald uint16_t num_bytes_to_copy = btstack_min(num_bytes_available, size); 123*a602f23dSMatthias Ringwald 124*a602f23dSMatthias Ringwald memcpy(buf, &hfp_codec->sco_packet[hfp_codec->read_pos], num_bytes_to_copy); 125*a602f23dSMatthias Ringwald hfp_codec->read_pos += num_bytes_to_copy; 126*a602f23dSMatthias Ringwald } 127*a602f23dSMatthias Ringwald 128*a602f23dSMatthias Ringwald void hfp_codec_deinit(hfp_codec_t * hfp_codec){ 129*a602f23dSMatthias Ringwald UNUSED(hfp_codec); 130*a602f23dSMatthias Ringwald } 131