1*d60a1028SMatthias Ringwald /* 2*d60a1028SMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH 3*d60a1028SMatthias Ringwald * 4*d60a1028SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 5*d60a1028SMatthias Ringwald * modification, are permitted provided that the following conditions 6*d60a1028SMatthias Ringwald * are met: 7*d60a1028SMatthias Ringwald * 8*d60a1028SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 9*d60a1028SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 10*d60a1028SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 11*d60a1028SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 12*d60a1028SMatthias Ringwald * documentation and/or other materials provided with the distribution. 13*d60a1028SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 14*d60a1028SMatthias Ringwald * contributors may be used to endorse or promote products derived 15*d60a1028SMatthias Ringwald * from this software without specific prior written permission. 16*d60a1028SMatthias Ringwald * 17*d60a1028SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 18*d60a1028SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 19*d60a1028SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 20*d60a1028SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 21*d60a1028SMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 22*d60a1028SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 23*d60a1028SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 24*d60a1028SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 25*d60a1028SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 26*d60a1028SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 27*d60a1028SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28*d60a1028SMatthias Ringwald * SUCH DAMAGE. 29*d60a1028SMatthias Ringwald * 30*d60a1028SMatthias Ringwald */ 31*d60a1028SMatthias Ringwald 32*d60a1028SMatthias Ringwald #define BTSTACK_FILE__ "btstack_lc3_plus_fraunhofer.c" 33*d60a1028SMatthias Ringwald 34*d60a1028SMatthias Ringwald /** 35*d60a1028SMatthias Ringwald * @title LC3 Plus Fraunhofer Adapter 36*d60a1028SMatthias Ringwald */ 37*d60a1028SMatthias Ringwald 38*d60a1028SMatthias Ringwald #include "btstack_config.h" 39*d60a1028SMatthias Ringwald #include "bluetooth.h" 40*d60a1028SMatthias Ringwald 41*d60a1028SMatthias Ringwald #include "btstack_lc3plus_fraunhofer.h" 42*d60a1028SMatthias Ringwald #include "btstack_debug.h" 43*d60a1028SMatthias Ringwald #include <string.h> 44*d60a1028SMatthias Ringwald 45*d60a1028SMatthias Ringwald #ifdef HAVE_LC3PLUS 46*d60a1028SMatthias Ringwald 47*d60a1028SMatthias Ringwald #define MAX_SAMPLES_PER_FRAME 480 48*d60a1028SMatthias Ringwald 49*d60a1028SMatthias Ringwald static uint8_t lc3plus_farunhofer_scratch[LC3PLUS_DEC_MAX_SCRATCH_SIZE]; 50*d60a1028SMatthias Ringwald 51*d60a1028SMatthias Ringwald static uint16_t lc3_frame_duration_in_us(btstack_lc3_frame_duration_t frame_duration){ 52*d60a1028SMatthias Ringwald switch (frame_duration) { 53*d60a1028SMatthias Ringwald case BTSTACK_LC3_FRAME_DURATION_7500US: 54*d60a1028SMatthias Ringwald return 7500; 55*d60a1028SMatthias Ringwald case BTSTACK_LC3_FRAME_DURATION_10000US: 56*d60a1028SMatthias Ringwald return 10000; 57*d60a1028SMatthias Ringwald default: 58*d60a1028SMatthias Ringwald return 0; 59*d60a1028SMatthias Ringwald } 60*d60a1028SMatthias Ringwald } 61*d60a1028SMatthias Ringwald 62*d60a1028SMatthias Ringwald /* Decoder implementation */ 63*d60a1028SMatthias Ringwald 64*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_decoder_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame){ 65*d60a1028SMatthias Ringwald btstack_lc3plus_fraunhofer_decoder_t * instance = (btstack_lc3plus_fraunhofer_decoder_t *) context; 66*d60a1028SMatthias Ringwald LC3PLUS_Dec * decoder = (LC3PLUS_Dec*) instance->decoder; 67*d60a1028SMatthias Ringwald 68*d60a1028SMatthias Ringwald // map frame duration 69*d60a1028SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 70*d60a1028SMatthias Ringwald if (duration_us == 0){ 71*d60a1028SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 72*d60a1028SMatthias Ringwald } 73*d60a1028SMatthias Ringwald 74*d60a1028SMatthias Ringwald // store config 75*d60a1028SMatthias Ringwald instance->sample_rate = sample_rate; 76*d60a1028SMatthias Ringwald instance->frame_duration = frame_duration; 77*d60a1028SMatthias Ringwald instance->octets_per_frame = octets_per_frame; 78*d60a1028SMatthias Ringwald instance->samples_per_frame = btstack_lc3_samples_per_frame(sample_rate, frame_duration); 79*d60a1028SMatthias Ringwald 80*d60a1028SMatthias Ringwald LC3PLUS_Error error; 81*d60a1028SMatthias Ringwald error = lc3plus_dec_init(decoder, sample_rate, 1, LC3PLUS_PLC_ADVANCED, 0); 82*d60a1028SMatthias Ringwald btstack_assert(error == LC3PLUS_OK); 83*d60a1028SMatthias Ringwald 84*d60a1028SMatthias Ringwald error = lc3plus_dec_set_frame_dms(decoder, duration_us / 100); 85*d60a1028SMatthias Ringwald btstack_assert(error == LC3PLUS_OK); 86*d60a1028SMatthias Ringwald 87*d60a1028SMatthias Ringwald return ERROR_CODE_SUCCESS; 88*d60a1028SMatthias Ringwald } 89*d60a1028SMatthias Ringwald 90*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_decoder_decode_signed_16(void * context, const uint8_t *bytes, uint8_t BFI, int16_t* pcm_out, uint16_t stride, uint8_t * BEC_detect) { 91*d60a1028SMatthias Ringwald btstack_lc3plus_fraunhofer_decoder_t *instance = (btstack_lc3plus_fraunhofer_decoder_t *) context; 92*d60a1028SMatthias Ringwald LC3PLUS_Dec *decoder = (LC3PLUS_Dec *) instance->decoder; 93*d60a1028SMatthias Ringwald 94*d60a1028SMatthias Ringwald // temporary output buffer to interleave samples for caller 95*d60a1028SMatthias Ringwald int16_t temp_out[MAX_SAMPLES_PER_FRAME]; 96*d60a1028SMatthias Ringwald 97*d60a1028SMatthias Ringwald // output_samples: array of channel buffers. use temp_out if stride is used 98*d60a1028SMatthias Ringwald int16_t *output_samples[1]; 99*d60a1028SMatthias Ringwald if (stride > 1) { 100*d60a1028SMatthias Ringwald output_samples[0] = temp_out; 101*d60a1028SMatthias Ringwald } else { 102*d60a1028SMatthias Ringwald output_samples[0] = pcm_out; 103*d60a1028SMatthias Ringwald } 104*d60a1028SMatthias Ringwald 105*d60a1028SMatthias Ringwald // trigger plc if BFI by passing 0 valid input bytes 106*d60a1028SMatthias Ringwald uint16_t byte_count = instance->octets_per_frame; 107*d60a1028SMatthias Ringwald if (BFI != 0){ 108*d60a1028SMatthias Ringwald byte_count = 0; 109*d60a1028SMatthias Ringwald } 110*d60a1028SMatthias Ringwald 111*d60a1028SMatthias Ringwald LC3PLUS_Error error = lc3plus_dec16(decoder, (void*) bytes, byte_count, output_samples, lc3plus_farunhofer_scratch, BFI); 112*d60a1028SMatthias Ringwald 113*d60a1028SMatthias Ringwald // store samples 114*d60a1028SMatthias Ringwald if (stride > 1){ 115*d60a1028SMatthias Ringwald uint16_t i; 116*d60a1028SMatthias Ringwald for (i = 0; i < instance->samples_per_frame; i++){ 117*d60a1028SMatthias Ringwald pcm_out [i * stride] = temp_out[i]; 118*d60a1028SMatthias Ringwald } 119*d60a1028SMatthias Ringwald } 120*d60a1028SMatthias Ringwald 121*d60a1028SMatthias Ringwald // map error 122*d60a1028SMatthias Ringwald switch (error){ 123*d60a1028SMatthias Ringwald case LC3PLUS_OK: 124*d60a1028SMatthias Ringwald // success 125*d60a1028SMatthias Ringwald return ERROR_CODE_SUCCESS; 126*d60a1028SMatthias Ringwald case LC3PLUS_DECODE_ERROR: 127*d60a1028SMatthias Ringwald // PLC enagaged 128*d60a1028SMatthias Ringwald *BEC_detect = 1; 129*d60a1028SMatthias Ringwald return ERROR_CODE_SUCCESS; 130*d60a1028SMatthias Ringwald default: 131*d60a1028SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 132*d60a1028SMatthias Ringwald } 133*d60a1028SMatthias Ringwald } 134*d60a1028SMatthias Ringwald 135*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_decoder_decode_signed_24(void * context, const uint8_t *bytes, uint8_t BFI, int32_t* pcm_out, uint16_t stride, uint8_t * BEC_detect) { 136*d60a1028SMatthias Ringwald btstack_lc3plus_fraunhofer_decoder_t * instance = (btstack_lc3plus_fraunhofer_decoder_t *) context; 137*d60a1028SMatthias Ringwald LC3PLUS_Dec * decoder = (LC3PLUS_Dec*) instance->decoder; 138*d60a1028SMatthias Ringwald 139*d60a1028SMatthias Ringwald // output_samples: array of channel buffers. 140*d60a1028SMatthias Ringwald int32_t * output_samples[1]; 141*d60a1028SMatthias Ringwald output_samples[0] = pcm_out; 142*d60a1028SMatthias Ringwald 143*d60a1028SMatthias Ringwald // trigger plc if BFI by passing 0 valid input bytes 144*d60a1028SMatthias Ringwald uint16_t byte_count = instance->octets_per_frame; 145*d60a1028SMatthias Ringwald if (BFI != 0){ 146*d60a1028SMatthias Ringwald byte_count = 0; 147*d60a1028SMatthias Ringwald } 148*d60a1028SMatthias Ringwald 149*d60a1028SMatthias Ringwald LC3PLUS_Error error = lc3plus_dec24(decoder, (void *) bytes, byte_count, output_samples, lc3plus_farunhofer_scratch, BFI); 150*d60a1028SMatthias Ringwald 151*d60a1028SMatthias Ringwald // map error 152*d60a1028SMatthias Ringwald switch (error){ 153*d60a1028SMatthias Ringwald case LC3PLUS_OK: 154*d60a1028SMatthias Ringwald // success 155*d60a1028SMatthias Ringwald return ERROR_CODE_SUCCESS; 156*d60a1028SMatthias Ringwald case LC3PLUS_DECODE_ERROR: 157*d60a1028SMatthias Ringwald // PLC enagaged 158*d60a1028SMatthias Ringwald *BEC_detect = 1; 159*d60a1028SMatthias Ringwald return ERROR_CODE_SUCCESS; 160*d60a1028SMatthias Ringwald default: 161*d60a1028SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 162*d60a1028SMatthias Ringwald } 163*d60a1028SMatthias Ringwald } 164*d60a1028SMatthias Ringwald 165*d60a1028SMatthias Ringwald static const btstack_lc3_decoder_t btstack_l3cplus_fraunhofer_decoder_instance = { 166*d60a1028SMatthias Ringwald lc3plus_fraunhofer_decoder_configure, 167*d60a1028SMatthias Ringwald lc3plus_fraunhofer_decoder_decode_signed_16, 168*d60a1028SMatthias Ringwald lc3plus_fraunhofer_decoder_decode_signed_24 169*d60a1028SMatthias Ringwald }; 170*d60a1028SMatthias Ringwald 171*d60a1028SMatthias Ringwald const btstack_lc3_decoder_t * btstack_lc3plus_fraunhofer_decoder_init_instance(btstack_lc3plus_fraunhofer_decoder_t * context){ 172*d60a1028SMatthias Ringwald memset(context, 0, sizeof(btstack_lc3plus_fraunhofer_decoder_t)); 173*d60a1028SMatthias Ringwald return &btstack_l3cplus_fraunhofer_decoder_instance; 174*d60a1028SMatthias Ringwald } 175*d60a1028SMatthias Ringwald 176*d60a1028SMatthias Ringwald /* Encoder implementation */ 177*d60a1028SMatthias Ringwald 178*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_encoder_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame){ 179*d60a1028SMatthias Ringwald btstack_lc3plus_fraunhofer_encoder_t * instance = (btstack_lc3plus_fraunhofer_encoder_t *) context; 180*d60a1028SMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 181*d60a1028SMatthias Ringwald } 182*d60a1028SMatthias Ringwald 183*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_encoder_encode_signed_16(void * context, const int16_t* pcm_in, uint16_t stride, uint8_t *bytes){ 184*d60a1028SMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 185*d60a1028SMatthias Ringwald } 186*d60a1028SMatthias Ringwald 187*d60a1028SMatthias Ringwald static uint8_t lc3plus_fraunhofer_encoder_encode_signed_24(void * context, const int32_t* pcm_in, uint16_t stride, uint8_t *bytes) { 188*d60a1028SMatthias Ringwald return ERROR_CODE_COMMAND_DISALLOWED; 189*d60a1028SMatthias Ringwald } 190*d60a1028SMatthias Ringwald 191*d60a1028SMatthias Ringwald static const btstack_lc3_encoder_t btstack_l3cplus_fraunhofer_encoder_instance = { 192*d60a1028SMatthias Ringwald lc3plus_fraunhofer_encoder_configure, 193*d60a1028SMatthias Ringwald lc3plus_fraunhofer_encoder_encode_signed_16, 194*d60a1028SMatthias Ringwald lc3plus_fraunhofer_encoder_encode_signed_24 195*d60a1028SMatthias Ringwald }; 196*d60a1028SMatthias Ringwald 197*d60a1028SMatthias Ringwald const btstack_lc3_encoder_t * btstack_lc3plus_fraunhofer_encoder_init_instance(btstack_lc3plus_fraunhofer_encoder_t * context){ 198*d60a1028SMatthias Ringwald memset(context, 0, sizeof(btstack_lc3plus_fraunhofer_encoder_t)); 199*d60a1028SMatthias Ringwald return &btstack_l3cplus_fraunhofer_encoder_instance; 200*d60a1028SMatthias Ringwald } 201*d60a1028SMatthias Ringwald 202*d60a1028SMatthias Ringwald #endif /* HAVE_LC3PLUS */ 203