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 /** 39a602f23dSMatthias Ringwald * @title HFP Audio Encoder 40a602f23dSMatthias Ringwald * @brief Create SCO packet with H2 Synchronization Header and encoded audio samples 41a602f23dSMatthias Ringwald */ 42a602f23dSMatthias Ringwald 43a602f23dSMatthias Ringwald #ifndef HFP_CODEC_H 44a602f23dSMatthias Ringwald #define HFP_CODEC_H 45a602f23dSMatthias Ringwald 46a602f23dSMatthias Ringwald #include "btstack_config.h" 47a602f23dSMatthias Ringwald 48*cf8294b2SMatthias Ringwald #include "classic/hfp.h" // HFP_CODEC_xxx 49a602f23dSMatthias Ringwald 50a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 51*cf8294b2SMatthias Ringwald #include "classic/btstack_sbc.h" 52*cf8294b2SMatthias Ringwald #include "classic/btstack_sbc_bluedroid.h" 53a602f23dSMatthias Ringwald #endif 54a602f23dSMatthias Ringwald 5516527ed5SMatthias Ringwald #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH 5616527ed5SMatthias Ringwald #include "btstack_lc3_google.h" 5716527ed5SMatthias Ringwald #endif 5816527ed5SMatthias Ringwald 59bcdbf704SMatthias Ringwald #include <stdint.h> 60bcdbf704SMatthias Ringwald 61a602f23dSMatthias Ringwald #if defined __cplusplus 62a602f23dSMatthias Ringwald extern "C" { 63a602f23dSMatthias Ringwald #endif 64a602f23dSMatthias Ringwald 65f789a318SMatthias Ringwald #define SCO_FRAME_SIZE 60 66f789a318SMatthias Ringwald 67bcdbf704SMatthias Ringwald // HFP H2 68bcdbf704SMatthias Ringwald 69bcdbf704SMatthias Ringwald #define HFP_H2_SYNC_FRAME_SIZE 60 70bcdbf704SMatthias Ringwald 71bcdbf704SMatthias Ringwald // HFP H2 Framing 72bcdbf704SMatthias Ringwald typedef struct { 73bcdbf704SMatthias Ringwald uint8_t sequence_number; 74bcdbf704SMatthias Ringwald } hfp_h2_framing_t; 75bcdbf704SMatthias Ringwald 76bcdbf704SMatthias Ringwald /** 77bcdbf704SMatthias Ringwald * @brief Init HFP H2 Framing state 78bcdbf704SMatthias Ringwald * @param hfp_h2_framing 79bcdbf704SMatthias Ringwald */ 80bcdbf704SMatthias Ringwald void hfp_h2_framing_init(hfp_h2_framing_t * hfp_h2_framing); 81bcdbf704SMatthias Ringwald 82bcdbf704SMatthias Ringwald /** 83bcdbf704SMatthias Ringwald * @brief Add next H2 Header 84bcdbf704SMatthias Ringwald * @param hfp_h2_framing 85bcdbf704SMatthias Ringwald * @param buffer [2] 86bcdbf704SMatthias Ringwald */ 87bcdbf704SMatthias Ringwald void hfp_h2_framing_add_header(hfp_h2_framing_t * hfp_h2_framing, uint8_t * buffer); 88bcdbf704SMatthias Ringwald 89bcdbf704SMatthias Ringwald 90a602f23dSMatthias Ringwald struct hfp_codec { 91f789a318SMatthias Ringwald // to allow for 24 byte USB payloads, we encode up to two SCO packets 92f789a318SMatthias Ringwald uint8_t sco_packet[2*SCO_FRAME_SIZE]; 93a602f23dSMatthias Ringwald uint16_t read_pos; 94a602f23dSMatthias Ringwald uint16_t write_pos; 95a602f23dSMatthias Ringwald uint16_t samples_per_frame; 96a602f23dSMatthias Ringwald hfp_h2_framing_t h2_framing; 97a602f23dSMatthias Ringwald void (*encode)(struct hfp_codec * hfp_codec, int16_t * pcm_samples); 98a602f23dSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 99*cf8294b2SMatthias Ringwald // @deprecated interface 1000a4f399aSMatthias Ringwald btstack_sbc_encoder_state_t * msbc_encoder_context; 101*cf8294b2SMatthias Ringwald // codec instance based interface 102*cf8294b2SMatthias Ringwald const btstack_sbc_encoder_t * sbc_encoder_instance; 103*cf8294b2SMatthias Ringwald void * sbc_encoder_context; 104a602f23dSMatthias Ringwald #endif 10516527ed5SMatthias Ringwald #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH 10616527ed5SMatthias Ringwald const btstack_lc3_encoder_t * lc3_encoder; 107aeb2ea11SMatthias Ringwald void * lc3_encoder_context; 10816527ed5SMatthias Ringwald #endif 109a602f23dSMatthias Ringwald }; 110a602f23dSMatthias Ringwald 111a602f23dSMatthias Ringwald /* API_START */ 112a602f23dSMatthias Ringwald 113a602f23dSMatthias Ringwald typedef struct hfp_codec hfp_codec_t; 114a602f23dSMatthias Ringwald 1157555fa8bSMatthias Ringwald #ifdef ENABLE_HFP_WIDE_BAND_SPEECH 116a602f23dSMatthias Ringwald /** 117aeb2ea11SMatthias Ringwald * @brief Initialize HFP Audio Codec for mSBC 118a602f23dSMatthias Ringwald * @param hfp_codec 1190a4f399aSMatthias Ringwald * @param msbc_encoder_context for msbc encoder 120a602f23dSMatthias Ringwald * @return status 121a602f23dSMatthias Ringwald */ 122*cf8294b2SMatthias Ringwald void hfp_codec_init_msbc_with_codec(hfp_codec_t * hfp_codec, const btstack_sbc_encoder_t * sbc_encoder, void * sbc_encoder_context); 123*cf8294b2SMatthias Ringwald 124*cf8294b2SMatthias Ringwald /** 125*cf8294b2SMatthias Ringwald * @brief Initialize HFP Audio Codec for mSBC 126*cf8294b2SMatthias Ringwald * @deprecated Please use hfp_codec_init_msbc_with_codec 127*cf8294b2SMatthias Ringwald * @param hfp_codec 128*cf8294b2SMatthias Ringwald * @param msbc_encoder_context for msbc encoder 129*cf8294b2SMatthias Ringwald * @return status 130*cf8294b2SMatthias Ringwald */ 1310a4f399aSMatthias Ringwald void hfp_codec_init_msbc(hfp_codec_t * hfp_codec, btstack_sbc_encoder_state_t * msbc_encoder_context); 1327555fa8bSMatthias Ringwald #endif 133aeb2ea11SMatthias Ringwald 134712c022aSMatthias Ringwald #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH 135aeb2ea11SMatthias Ringwald /** 136aeb2ea11SMatthias Ringwald * @brief Initialize HFP Audio Codec for LC3-SWB 137aeb2ea11SMatthias Ringwald * @param hfp_codec 138aeb2ea11SMatthias Ringwald * @param lc3_encoder 139aeb2ea11SMatthias Ringwald * @param lc3_encoder_context for lc3_encoder 140aeb2ea11SMatthias Ringwald * @return status 141aeb2ea11SMatthias Ringwald */ 142aeb2ea11SMatthias Ringwald void hfp_codec_init_lc3_swb(hfp_codec_t * hfp_codec, const btstack_lc3_encoder_t * lc3_encoder, void * lc3_encoder_context); 143712c022aSMatthias Ringwald #endif 144a602f23dSMatthias Ringwald 145a602f23dSMatthias Ringwald /** 146a602f23dSMatthias Ringwald * @brief Get number of audio samples per HFP SCO frame 147a602f23dSMatthias Ringwald * @param hfp_codec 148a602f23dSMatthias Ringwald * @return num audio samples per 7.5ms SCO packet 149a602f23dSMatthias Ringwald */ 150a602f23dSMatthias Ringwald uint16_t hfp_codec_num_audio_samples_per_frame(const hfp_codec_t * hfp_codec); 151a602f23dSMatthias Ringwald 152a602f23dSMatthias Ringwald /** 153a602f23dSMatthias Ringwald * @brief Checks if next frame can be encoded 154a602f23dSMatthias Ringwald * @param hfp_codec 155a602f23dSMatthias Ringwald */ 156a602f23dSMatthias Ringwald bool hfp_codec_can_encode_audio_frame_now(const hfp_codec_t * hfp_codec); 157a602f23dSMatthias Ringwald 158a602f23dSMatthias Ringwald /** 159a602f23dSMatthias Ringwald * Get number of bytes ready for sending 160a602f23dSMatthias Ringwald * @param hfp_codec 161a602f23dSMatthias Ringwald * @return num bytes ready for current packet 162a602f23dSMatthias Ringwald */ 163a602f23dSMatthias Ringwald uint16_t hfp_codec_num_bytes_available(const hfp_codec_t * hfp_codec); 164a602f23dSMatthias Ringwald 165a602f23dSMatthias Ringwald /** 166a602f23dSMatthias Ringwald * Encode audio samples for HFP SCO packet 167a602f23dSMatthias Ringwald * @param hfp_codec 168a602f23dSMatthias Ringwald * @param pcm_samples - complete audio frame of hfp_msbc_num_audio_samples_per_frame int16 samples 169a602f23dSMatthias Ringwald */ 170a602f23dSMatthias Ringwald void hfp_codec_encode_audio_frame(hfp_codec_t * hfp_codec, int16_t * pcm_samples); 171a602f23dSMatthias Ringwald 172a602f23dSMatthias Ringwald /** 173a602f23dSMatthias Ringwald * Read from stream into SCO packet buffer 174a602f23dSMatthias Ringwald * @param hfp_codec 175a602f23dSMatthias Ringwald * @param buffer to store stream 176a602f23dSMatthias Ringwald * @param size num bytes to read from stream 177a602f23dSMatthias Ringwald */ 178a602f23dSMatthias Ringwald void hfp_codec_read_from_stream(hfp_codec_t * hfp_codec, uint8_t * buffer, uint16_t size); 179a602f23dSMatthias Ringwald 180a602f23dSMatthias Ringwald /** 181a602f23dSMatthias Ringwald * @param hfp_codec 182a602f23dSMatthias Ringwald */ 183a602f23dSMatthias Ringwald void hfp_codec_deinit(hfp_codec_t * hfp_codec); 184a602f23dSMatthias Ringwald 185a602f23dSMatthias Ringwald /* API_END */ 186a602f23dSMatthias Ringwald 187a602f23dSMatthias Ringwald #if defined __cplusplus 188a602f23dSMatthias Ringwald } 189a602f23dSMatthias Ringwald #endif 190a602f23dSMatthias Ringwald 191a602f23dSMatthias Ringwald #endif 192