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