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 // config decoder 73 instance->decoder = lc3_setup_decoder(duration_us, sample_rate, 0, &instance->decoder_mem); 74 75 if (instance->decoder == NULL) { 76 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 77 } 78 79 return ERROR_CODE_SUCCESS; 80 } 81 82 static uint8_t 83 lc3_decoder_google_decode(void *context, const uint8_t *bytes, uint8_t BFI, enum lc3_pcm_format fmt, void *pcm_out, 84 uint16_t stride, uint8_t *BEC_detect) { 85 btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 86 87 if (BFI){ 88 // bit errors, trigger PLC by passing NULL as buffer 89 *BEC_detect = 1; 90 bytes = NULL; 91 } else { 92 // no bit errors, regular processing 93 *BEC_detect = 0; 94 } 95 96 int result = lc3_decode(instance->decoder, (const void *) bytes, instance->octets_per_frame, fmt, pcm_out, stride); 97 switch (result){ 98 case 0: // success 99 return ERROR_CODE_SUCCESS; 100 case -1: // PLC engaged 101 *BEC_detect = 1; 102 return ERROR_CODE_SUCCESS; 103 default: 104 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 105 } 106 } 107 108 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){ 109 return lc3_decoder_google_decode(context, bytes, BFI, LC3_PCM_FORMAT_S16, (void *) pcm_out, stride, BEC_detect); 110 } 111 112 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) { 113 return lc3_decoder_google_decode(context, bytes, BFI, LC3_PCM_FORMAT_S24, (void *) pcm_out, stride, BEC_detect); 114 } 115 116 static const btstack_lc3_decoder_t btstack_l3c_decoder_google_instance = { 117 lc3_decoder_google_configure, 118 lc3_decoder_google_decode_signed_16, 119 lc3_decoder_google_decode_signed_24 120 }; 121 122 const btstack_lc3_decoder_t * btstack_lc3_decoder_google_init_instance(btstack_lc3_decoder_google_t * context){ 123 memset(context, 0, sizeof(btstack_lc3_decoder_google_t)); 124 return &btstack_l3c_decoder_google_instance; 125 } 126 127 /* Encoder implementation */ 128 129 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){ 130 btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 131 132 // map frame duration 133 uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 134 if (duration_us == 0){ 135 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 136 } 137 138 // store config 139 instance->sample_rate = sample_rate; 140 instance->frame_duration = frame_duration; 141 instance->octets_per_frame = octets_per_frame; 142 143 // config encoder 144 instance->encoder = lc3_setup_encoder(duration_us, sample_rate, 0, &instance->encoder_mem); 145 146 if (instance->encoder == NULL) { 147 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 148 } 149 150 return ERROR_CODE_SUCCESS; 151 } 152 153 static uint8_t 154 lc3_encoder_google_encode_signed(void *context, enum lc3_pcm_format fmt, const void *pcm_in, uint16_t stride, uint8_t *bytes) { 155 btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 156 int result = lc3_encode(instance->encoder, fmt, pcm_in, stride, instance->octets_per_frame, (void*) bytes); 157 switch (result){ 158 case 0: 159 return ERROR_CODE_SUCCESS; 160 default: 161 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 162 } 163 } 164 165 static uint8_t lc3_encoder_google_encode_signed_16(void * context, const int16_t* pcm_in, uint16_t stride, uint8_t *bytes){ 166 return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S16, (const void *) pcm_in, stride, bytes); 167 } 168 169 static uint8_t lc3_encoder_google_encode_signed_24(void * context, const int32_t* pcm_in, uint16_t stride, uint8_t *bytes){ 170 return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S24, (const void *) pcm_in, stride, bytes); 171 } 172 173 static const btstack_lc3_encoder_t btstack_l3c_encoder_google_instance = { 174 lc3_encoder_google_configure, 175 lc3_encoder_google_encode_signed_16, 176 lc3_encoder_google_encode_signed_24 177 }; 178 179 const btstack_lc3_encoder_t * btstack_lc3_encoder_google_init_instance(btstack_lc3_encoder_google_t * context){ 180 memset(context, 0, sizeof(btstack_lc3_encoder_google_t)); 181 return &btstack_l3c_encoder_google_instance; 182 } 183 184