1*9a19cd78SMatthias Ringwald /* 2*9a19cd78SMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH 3*9a19cd78SMatthias Ringwald * 4*9a19cd78SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*9a19cd78SMatthias Ringwald * modification, are permitted provided that the following conditions 6*9a19cd78SMatthias Ringwald * are met: 7*9a19cd78SMatthias Ringwald * 8*9a19cd78SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*9a19cd78SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*9a19cd78SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*9a19cd78SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*9a19cd78SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*9a19cd78SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*9a19cd78SMatthias Ringwald * contributors may be used to endorse or promote products derived 15*9a19cd78SMatthias Ringwald * from this software without specific prior written permission. 16*9a19cd78SMatthias Ringwald * 17*9a19cd78SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 18*9a19cd78SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*9a19cd78SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20*9a19cd78SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 21*9a19cd78SMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22*9a19cd78SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23*9a19cd78SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 24*9a19cd78SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25*9a19cd78SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26*9a19cd78SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 27*9a19cd78SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*9a19cd78SMatthias Ringwald * SUCH DAMAGE. 29*9a19cd78SMatthias Ringwald * 30*9a19cd78SMatthias Ringwald */ 31*9a19cd78SMatthias Ringwald 32*9a19cd78SMatthias Ringwald #define BTSTACK_FILE__ "btstack_lc3_google.c" 33*9a19cd78SMatthias Ringwald 34*9a19cd78SMatthias Ringwald /** 35*9a19cd78SMatthias Ringwald * @title LC3 Google Adapter 36*9a19cd78SMatthias Ringwald */ 37*9a19cd78SMatthias Ringwald 38*9a19cd78SMatthias Ringwald #include "btstack_config.h" 39*9a19cd78SMatthias Ringwald #include "bluetooth.h" 40*9a19cd78SMatthias Ringwald 41*9a19cd78SMatthias Ringwald #include "btstack_lc3_google.h" 42*9a19cd78SMatthias Ringwald #include "btstack_debug.h" 43*9a19cd78SMatthias Ringwald #include <string.h> 44*9a19cd78SMatthias Ringwald 45*9a19cd78SMatthias Ringwald static uint16_t lc3_frame_duration_in_us(btstack_lc3_frame_duration_t frame_duration){ 46*9a19cd78SMatthias Ringwald switch (frame_duration) { 47*9a19cd78SMatthias Ringwald case BTSTACK_LC3_FRAME_DURATION_7500US: 48*9a19cd78SMatthias Ringwald return 7500; 49*9a19cd78SMatthias Ringwald case BTSTACK_LC3_FRAME_DURATION_10000US: 50*9a19cd78SMatthias Ringwald return 10000; 51*9a19cd78SMatthias Ringwald default: 52*9a19cd78SMatthias Ringwald return 0; 53*9a19cd78SMatthias Ringwald } 54*9a19cd78SMatthias Ringwald } 55*9a19cd78SMatthias Ringwald 56*9a19cd78SMatthias Ringwald /* Decoder implementation */ 57*9a19cd78SMatthias Ringwald 58*9a19cd78SMatthias Ringwald static uint8_t lc3_decoder_google_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration){ 59*9a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 60*9a19cd78SMatthias Ringwald 61*9a19cd78SMatthias Ringwald // map frame duration 62*9a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 63*9a19cd78SMatthias Ringwald if (duration_us == 0){ 64*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 65*9a19cd78SMatthias Ringwald } 66*9a19cd78SMatthias Ringwald 67*9a19cd78SMatthias Ringwald // store config 68*9a19cd78SMatthias Ringwald instance->sample_rate = sample_rate; 69*9a19cd78SMatthias Ringwald instance->frame_duration = frame_duration; 70*9a19cd78SMatthias Ringwald 71*9a19cd78SMatthias Ringwald // config decoder 72*9a19cd78SMatthias Ringwald instance->decoder = lc3_setup_decoder(duration_us, sample_rate, 0, &instance->decoder_mem); 73*9a19cd78SMatthias Ringwald 74*9a19cd78SMatthias Ringwald if (instance->decoder == NULL) { 75*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 76*9a19cd78SMatthias Ringwald } 77*9a19cd78SMatthias Ringwald 78*9a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 79*9a19cd78SMatthias Ringwald } 80*9a19cd78SMatthias Ringwald 81*9a19cd78SMatthias Ringwald static uint16_t lc3_decoder_google_get_number_octets_for_bitrate(void * context, uint32_t bitrate){ 82*9a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 83*9a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 84*9a19cd78SMatthias Ringwald if (duration_us == 0){ 85*9a19cd78SMatthias Ringwald return 0; 86*9a19cd78SMatthias Ringwald } 87*9a19cd78SMatthias Ringwald return lc3_frame_bytes(duration_us, bitrate); 88*9a19cd78SMatthias Ringwald } 89*9a19cd78SMatthias Ringwald 90*9a19cd78SMatthias Ringwald static uint16_t lc3_decoder_google_get_number_samples_per_frame(void * context){ 91*9a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 92*9a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 93*9a19cd78SMatthias Ringwald if (duration_us == 0){ 94*9a19cd78SMatthias Ringwald return 0; 95*9a19cd78SMatthias Ringwald } 96*9a19cd78SMatthias Ringwald return lc3_frame_samples(duration_us, instance->sample_rate); 97*9a19cd78SMatthias Ringwald } 98*9a19cd78SMatthias Ringwald 99*9a19cd78SMatthias Ringwald static uint8_t lc3_decoder_google_decode(void * context, const uint8_t *bytes, uint16_t byte_count, uint8_t BFI, enum lc3_pcm_format fmt, void * pcm_out, uint16_t stride, uint8_t * BEC_detect){ 100*9a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 101*9a19cd78SMatthias Ringwald 102*9a19cd78SMatthias Ringwald if (BFI){ 103*9a19cd78SMatthias Ringwald // bit errors, trigger PLC by passing NULL as buffer 104*9a19cd78SMatthias Ringwald *BEC_detect = 1; 105*9a19cd78SMatthias Ringwald bytes = NULL; 106*9a19cd78SMatthias Ringwald } else { 107*9a19cd78SMatthias Ringwald // no bit errors, regular processing 108*9a19cd78SMatthias Ringwald *BEC_detect = 0; 109*9a19cd78SMatthias Ringwald } 110*9a19cd78SMatthias Ringwald 111*9a19cd78SMatthias Ringwald int result = lc3_decode(instance->decoder, (const void *) bytes, byte_count, fmt, pcm_out, stride); 112*9a19cd78SMatthias Ringwald switch (result){ 113*9a19cd78SMatthias Ringwald case 0: // success 114*9a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 115*9a19cd78SMatthias Ringwald case -1: // PLC engaged 116*9a19cd78SMatthias Ringwald *BEC_detect = 1; 117*9a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 118*9a19cd78SMatthias Ringwald default: 119*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 120*9a19cd78SMatthias Ringwald } 121*9a19cd78SMatthias Ringwald } 122*9a19cd78SMatthias Ringwald 123*9a19cd78SMatthias Ringwald static uint8_t lc3_decoder_google_decode_signed_16(void * context, const uint8_t *bytes, uint16_t byte_count, uint8_t BFI, int16_t* pcm_out, uint16_t stride, uint8_t * BEC_detect){ 124*9a19cd78SMatthias Ringwald return lc3_decoder_google_decode(context, bytes, byte_count, BFI, LC3_PCM_FORMAT_S16, (void *) pcm_out, stride, BEC_detect); 125*9a19cd78SMatthias Ringwald } 126*9a19cd78SMatthias Ringwald 127*9a19cd78SMatthias Ringwald static uint8_t lc3_decoder_google_decode_signed_24(void * context, const uint8_t *bytes, uint16_t byte_count, uint8_t BFI, int32_t* pcm_out, uint16_t stride, uint8_t * BEC_detect) { 128*9a19cd78SMatthias Ringwald return lc3_decoder_google_decode(context, bytes, byte_count, BFI, LC3_PCM_FORMAT_S24, (void *) pcm_out, stride, BEC_detect); 129*9a19cd78SMatthias Ringwald } 130*9a19cd78SMatthias Ringwald 131*9a19cd78SMatthias Ringwald static const btstack_lc3_decoder_t btstack_l3c_decoder_google_instance = { 132*9a19cd78SMatthias Ringwald lc3_decoder_google_configure, 133*9a19cd78SMatthias Ringwald lc3_decoder_google_get_number_octets_for_bitrate, 134*9a19cd78SMatthias Ringwald lc3_decoder_google_get_number_samples_per_frame, 135*9a19cd78SMatthias Ringwald lc3_decoder_google_decode_signed_16, 136*9a19cd78SMatthias Ringwald lc3_decoder_google_decode_signed_24 137*9a19cd78SMatthias Ringwald }; 138*9a19cd78SMatthias Ringwald 139*9a19cd78SMatthias Ringwald const btstack_lc3_decoder_t * btstack_lc3_decoder_google_init_instance(btstack_lc3_decoder_google_t * context){ 140*9a19cd78SMatthias Ringwald memset(context, 0, sizeof(btstack_lc3_decoder_google_t)); 141*9a19cd78SMatthias Ringwald return &btstack_l3c_decoder_google_instance; 142*9a19cd78SMatthias Ringwald } 143*9a19cd78SMatthias Ringwald 144*9a19cd78SMatthias Ringwald /* Encoder implementation */ 145*9a19cd78SMatthias Ringwald 146*9a19cd78SMatthias Ringwald static uint8_t lc3_encoder_google_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration){ 147*9a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 148*9a19cd78SMatthias Ringwald 149*9a19cd78SMatthias Ringwald // map frame duration 150*9a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 151*9a19cd78SMatthias Ringwald if (duration_us == 0){ 152*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 153*9a19cd78SMatthias Ringwald } 154*9a19cd78SMatthias Ringwald 155*9a19cd78SMatthias Ringwald // store config 156*9a19cd78SMatthias Ringwald instance->sample_rate = sample_rate; 157*9a19cd78SMatthias Ringwald instance->frame_duration = frame_duration; 158*9a19cd78SMatthias Ringwald 159*9a19cd78SMatthias Ringwald // config encoder 160*9a19cd78SMatthias Ringwald instance->encoder = lc3_setup_encoder(duration_us, sample_rate, 0, &instance->encoder_mem); 161*9a19cd78SMatthias Ringwald 162*9a19cd78SMatthias Ringwald if (instance->encoder == NULL) { 163*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 164*9a19cd78SMatthias Ringwald } 165*9a19cd78SMatthias Ringwald 166*9a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 167*9a19cd78SMatthias Ringwald } 168*9a19cd78SMatthias Ringwald 169*9a19cd78SMatthias Ringwald static uint32_t lc3_encoder_google_get_bitrate_for_number_of_octets(void * context, uint16_t number_of_octets){ 170*9a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 171*9a19cd78SMatthias Ringwald // map frame duration 172*9a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 173*9a19cd78SMatthias Ringwald if (duration_us == 0){ 174*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 175*9a19cd78SMatthias Ringwald } 176*9a19cd78SMatthias Ringwald return lc3_resolve_bitrate(duration_us, number_of_octets); 177*9a19cd78SMatthias Ringwald } 178*9a19cd78SMatthias Ringwald 179*9a19cd78SMatthias Ringwald static uint16_t lc3_encoder_google_get_number_samples_per_frame(void * context){ 180*9a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 181*9a19cd78SMatthias Ringwald // map frame duration 182*9a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 183*9a19cd78SMatthias Ringwald if (duration_us == 0){ 184*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 185*9a19cd78SMatthias Ringwald } 186*9a19cd78SMatthias Ringwald return lc3_frame_samples(duration_us, instance->sample_rate); 187*9a19cd78SMatthias Ringwald } 188*9a19cd78SMatthias Ringwald static uint8_t lc3_encoder_google_encode_signed(void * context, enum lc3_pcm_format fmt, const void *pcm_in, uint16_t stride, uint8_t *bytes, uint16_t byte_count) { 189*9a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 190*9a19cd78SMatthias Ringwald int result = lc3_encode(instance->encoder, fmt, pcm_in, stride, byte_count, (void*) bytes); 191*9a19cd78SMatthias Ringwald switch (result){ 192*9a19cd78SMatthias Ringwald case 0: 193*9a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 194*9a19cd78SMatthias Ringwald default: 195*9a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 196*9a19cd78SMatthias Ringwald } 197*9a19cd78SMatthias Ringwald } 198*9a19cd78SMatthias Ringwald 199*9a19cd78SMatthias Ringwald static uint8_t lc3_encoder_google_encode_signed_16(void * context, const int16_t* pcm_in, uint16_t stride, uint8_t *bytes, uint16_t byte_count){ 200*9a19cd78SMatthias Ringwald return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S16, (const void *) pcm_in, stride, bytes, byte_count); 201*9a19cd78SMatthias Ringwald } 202*9a19cd78SMatthias Ringwald 203*9a19cd78SMatthias Ringwald static uint8_t lc3_encoder_google_encode_signed_24(void * context, const int32_t* pcm_in, uint16_t stride, uint8_t *bytes, uint16_t byte_count){ 204*9a19cd78SMatthias Ringwald return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S24, (const void *) pcm_in, stride, bytes, byte_count); 205*9a19cd78SMatthias Ringwald } 206*9a19cd78SMatthias Ringwald 207*9a19cd78SMatthias Ringwald static const btstack_lc3_encoder_t btstack_l3c_encoder_google_instance = { 208*9a19cd78SMatthias Ringwald lc3_encoder_google_configure, 209*9a19cd78SMatthias Ringwald lc3_encoder_google_get_bitrate_for_number_of_octets, 210*9a19cd78SMatthias Ringwald lc3_encoder_google_get_number_samples_per_frame, 211*9a19cd78SMatthias Ringwald lc3_encoder_google_encode_signed_16, 212*9a19cd78SMatthias Ringwald lc3_encoder_google_encode_signed_24 213*9a19cd78SMatthias Ringwald }; 214*9a19cd78SMatthias Ringwald 215*9a19cd78SMatthias Ringwald const btstack_lc3_encoder_t * btstack_lc3_encoder_google_init_instance(btstack_lc3_encoder_google_t * context){ 216*9a19cd78SMatthias Ringwald memset(context, 0, sizeof(btstack_lc3_encoder_google_t)); 217*9a19cd78SMatthias Ringwald return &btstack_l3c_encoder_google_instance; 218*9a19cd78SMatthias Ringwald } 219*9a19cd78SMatthias Ringwald 220