/* * Copyright (C) 2023 BlueKitchen GmbH * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * 4. Any redistribution, use, or modification is done solely for * personal benefit and not for any commercial purpose or for * monetary gain. * * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * Please inquire about commercial licensing options at * contact@bluekitchen-gmbh.com * */ /** * @title HFP Audio Encoder * @brief Create SCO packet with H2 Synchronization Header and encoded audio samples */ #ifndef HFP_CODEC_H #define HFP_CODEC_H #include "btstack_config.h" #include "classic/hfp.h" // HFP_CODEC_xxx #ifdef ENABLE_HFP_WIDE_BAND_SPEECH #include "classic/btstack_sbc.h" #include "classic/btstack_sbc_bluedroid.h" #endif #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH #include "btstack_lc3_google.h" #endif #include #if defined __cplusplus extern "C" { #endif #define SCO_FRAME_SIZE 60 // HFP H2 #define HFP_H2_SYNC_FRAME_SIZE 60 // HFP H2 Framing typedef struct { uint8_t sequence_number; } hfp_h2_framing_t; /** * @brief Init HFP H2 Framing state * @param hfp_h2_framing */ void hfp_h2_framing_init(hfp_h2_framing_t * hfp_h2_framing); /** * @brief Add next H2 Header * @param hfp_h2_framing * @param buffer [2] */ void hfp_h2_framing_add_header(hfp_h2_framing_t * hfp_h2_framing, uint8_t * buffer); struct hfp_codec { // to allow for 24 byte USB payloads, we encode up to two SCO packets uint8_t sco_packet[2*SCO_FRAME_SIZE]; uint16_t read_pos; uint16_t write_pos; uint16_t samples_per_frame; hfp_h2_framing_t h2_framing; void (*encode)(struct hfp_codec * hfp_codec, int16_t * pcm_samples); #ifdef ENABLE_HFP_WIDE_BAND_SPEECH // @deprecated interface btstack_sbc_encoder_state_t * msbc_encoder_context; // codec instance based interface const btstack_sbc_encoder_t * sbc_encoder_instance; void * sbc_encoder_context; #endif #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH const btstack_lc3_encoder_t * lc3_encoder; void * lc3_encoder_context; #endif }; /* API_START */ typedef struct hfp_codec hfp_codec_t; #ifdef ENABLE_HFP_WIDE_BAND_SPEECH /** * @brief Initialize HFP Audio Codec for mSBC * @param hfp_codec * @param msbc_encoder_context for msbc encoder * @return status */ void hfp_codec_init_msbc_with_codec(hfp_codec_t * hfp_codec, const btstack_sbc_encoder_t * sbc_encoder, void * sbc_encoder_context); /** * @brief Initialize HFP Audio Codec for mSBC * @deprecated Please use hfp_codec_init_msbc_with_codec * @param hfp_codec * @param msbc_encoder_context for msbc encoder * @return status */ void hfp_codec_init_msbc(hfp_codec_t * hfp_codec, btstack_sbc_encoder_state_t * msbc_encoder_context); #endif #ifdef ENABLE_HFP_SUPER_WIDE_BAND_SPEECH /** * @brief Initialize HFP Audio Codec for LC3-SWB * @param hfp_codec * @param lc3_encoder * @param lc3_encoder_context for lc3_encoder * @return status */ void hfp_codec_init_lc3_swb(hfp_codec_t * hfp_codec, const btstack_lc3_encoder_t * lc3_encoder, void * lc3_encoder_context); #endif /** * @brief Get number of audio samples per HFP SCO frame * @param hfp_codec * @return num audio samples per 7.5ms SCO packet */ uint16_t hfp_codec_num_audio_samples_per_frame(const hfp_codec_t * hfp_codec); /** * @brief Checks if next frame can be encoded * @param hfp_codec */ bool hfp_codec_can_encode_audio_frame_now(const hfp_codec_t * hfp_codec); /** * Get number of bytes ready for sending * @param hfp_codec * @return num bytes ready for current packet */ uint16_t hfp_codec_num_bytes_available(const hfp_codec_t * hfp_codec); /** * Encode audio samples for HFP SCO packet * @param hfp_codec * @param pcm_samples - complete audio frame of hfp_msbc_num_audio_samples_per_frame int16 samples */ void hfp_codec_encode_audio_frame(hfp_codec_t * hfp_codec, int16_t * pcm_samples); /** * Read from stream into SCO packet buffer * @param hfp_codec * @param buffer to store stream * @param size num bytes to read from stream */ void hfp_codec_read_from_stream(hfp_codec_t * hfp_codec, uint8_t * buffer, uint16_t size); /** * @param hfp_codec */ void hfp_codec_deinit(hfp_codec_t * hfp_codec); /* API_END */ #if defined __cplusplus } #endif #endif