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_google.c" 33 34 /** 35 * @title LC3 Google Adapter 36 */ 37 38 #include "btstack_config.h" 39 #include "bluetooth.h" 40 41 #include "btstack_lc3_google.h" 42 #include "btstack_debug.h" 43 #include <string.h> 44 45 static uint16_t lc3_frame_duration_in_us(btstack_lc3_frame_duration_t frame_duration){ 46 switch (frame_duration) { 47 case BTSTACK_LC3_FRAME_DURATION_7500US: 48 return 7500; 49 case BTSTACK_LC3_FRAME_DURATION_10000US: 50 return 10000; 51 default: 52 return 0; 53 } 54 } 55 56 /* Decoder implementation */ 57 58 static uint8_t lc3_decoder_google_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame){ 59 btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 60 61 // map frame duration 62 uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 63 if (duration_us == 0){ 64 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 65 } 66 67 // store config 68 instance->sample_rate = sample_rate; 69 instance->frame_duration = frame_duration; 70 instance->octets_per_frame = octets_per_frame; 71 72 // map 44.1 to 48 73 if (sample_rate == 44100){ 74 sample_rate = 48000; 75 } 76 77 // config decoder 78 instance->decoder = lc3_setup_decoder(duration_us, sample_rate, 0, &instance->decoder_mem); 79 80 if (instance->decoder == NULL) { 81 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 82 } 83 84 return ERROR_CODE_SUCCESS; 85 } 86 87 static uint8_t 88 lc3_decoder_google_decode(void *context, const uint8_t *bytes, uint8_t BFI, enum lc3_pcm_format fmt, void *pcm_out, 89 uint16_t stride, uint8_t *BEC_detect) { 90 btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 91 92 if (BFI){ 93 // bit errors, trigger PLC by passing NULL as buffer 94 *BEC_detect = 1; 95 bytes = NULL; 96 } else { 97 // no bit errors, regular processing 98 *BEC_detect = 0; 99 } 100 101 int result = lc3_decode(instance->decoder, (const void *) bytes, instance->octets_per_frame, fmt, pcm_out, stride); 102 switch (result){ 103 case 0: // success 104 return ERROR_CODE_SUCCESS; 105 case -1: // PLC engaged 106 *BEC_detect = 1; 107 return ERROR_CODE_SUCCESS; 108 default: 109 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 110 } 111 } 112 113 static uint8_t lc3_decoder_google_decode_signed_16(void * context, const uint8_t *bytes, uint8_t BFI, int16_t* pcm_out, uint16_t stride, uint8_t * BEC_detect){ 114 return lc3_decoder_google_decode(context, bytes, BFI, LC3_PCM_FORMAT_S16, (void *) pcm_out, stride, BEC_detect); 115 } 116 117 static uint8_t lc3_decoder_google_decode_signed_24(void * context, const uint8_t *bytes, uint8_t BFI, int32_t* pcm_out, uint16_t stride, uint8_t * BEC_detect) { 118 return lc3_decoder_google_decode(context, bytes, BFI, LC3_PCM_FORMAT_S24, (void *) pcm_out, stride, BEC_detect); 119 } 120 121 static const btstack_lc3_decoder_t btstack_l3c_decoder_google_instance = { 122 lc3_decoder_google_configure, 123 lc3_decoder_google_decode_signed_16, 124 lc3_decoder_google_decode_signed_24 125 }; 126 127 const btstack_lc3_decoder_t * btstack_lc3_decoder_google_init_instance(btstack_lc3_decoder_google_t * context){ 128 memset(context, 0, sizeof(btstack_lc3_decoder_google_t)); 129 return &btstack_l3c_decoder_google_instance; 130 } 131 132 /* Encoder implementation */ 133 134 static uint8_t lc3_encoder_google_configure(void * context, uint32_t sample_rate, btstack_lc3_frame_duration_t frame_duration, uint16_t octets_per_frame){ 135 btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 136 137 // map frame duration 138 uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 139 if (duration_us == 0){ 140 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 141 } 142 143 // store config 144 instance->sample_rate = sample_rate; 145 instance->frame_duration = frame_duration; 146 instance->octets_per_frame = octets_per_frame; 147 148 // map 44.1 to 48 149 if (sample_rate == 44100){ 150 sample_rate = 48000; 151 } 152 153 // config encoder 154 instance->encoder = lc3_setup_encoder(duration_us, sample_rate, 0, &instance->encoder_mem); 155 156 if (instance->encoder == NULL) { 157 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 158 } 159 160 return ERROR_CODE_SUCCESS; 161 } 162 163 static uint8_t 164 lc3_encoder_google_encode_signed(void *context, enum lc3_pcm_format fmt, const void *pcm_in, uint16_t stride, uint8_t *bytes) { 165 btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 166 int result = lc3_encode(instance->encoder, fmt, pcm_in, stride, instance->octets_per_frame, (void*) bytes); 167 switch (result){ 168 case 0: 169 return ERROR_CODE_SUCCESS; 170 default: 171 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 172 } 173 } 174 175 static uint8_t lc3_encoder_google_encode_signed_16(void * context, const int16_t* pcm_in, uint16_t stride, uint8_t *bytes){ 176 return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S16, (const void *) pcm_in, stride, bytes); 177 } 178 179 static uint8_t lc3_encoder_google_encode_signed_24(void * context, const int32_t* pcm_in, uint16_t stride, uint8_t *bytes){ 180 return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S24, (const void *) pcm_in, stride, bytes); 181 } 182 183 static const btstack_lc3_encoder_t btstack_l3c_encoder_google_instance = { 184 lc3_encoder_google_configure, 185 lc3_encoder_google_encode_signed_16, 186 lc3_encoder_google_encode_signed_24 187 }; 188 189 const btstack_lc3_encoder_t * btstack_lc3_encoder_google_init_instance(btstack_lc3_encoder_google_t * context){ 190 memset(context, 0, sizeof(btstack_lc3_encoder_google_t)); 191 return &btstack_l3c_encoder_google_instance; 192 } 193 194