19a19cd78SMatthias Ringwald /* 29a19cd78SMatthias Ringwald * Copyright (C) 2022 BlueKitchen GmbH 39a19cd78SMatthias Ringwald * 49a19cd78SMatthias Ringwald * Redistribution and use in source and binary forms, with or without 59a19cd78SMatthias Ringwald * modification, are permitted provided that the following conditions 69a19cd78SMatthias Ringwald * are met: 79a19cd78SMatthias Ringwald * 89a19cd78SMatthias Ringwald * 1. Redistributions of source code must retain the above copyright 99a19cd78SMatthias Ringwald * notice, this list of conditions and the following disclaimer. 109a19cd78SMatthias Ringwald * 2. Redistributions in binary form must reproduce the above copyright 119a19cd78SMatthias Ringwald * notice, this list of conditions and the following disclaimer in the 129a19cd78SMatthias Ringwald * documentation and/or other materials provided with the distribution. 139a19cd78SMatthias Ringwald * 3. Neither the name of the copyright holders nor the names of 149a19cd78SMatthias Ringwald * contributors may be used to endorse or promote products derived 159a19cd78SMatthias Ringwald * from this software without specific prior written permission. 169a19cd78SMatthias Ringwald * 179a19cd78SMatthias Ringwald * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 189a19cd78SMatthias Ringwald * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 199a19cd78SMatthias Ringwald * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 209a19cd78SMatthias Ringwald * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 219a19cd78SMatthias Ringwald * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 229a19cd78SMatthias Ringwald * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 239a19cd78SMatthias Ringwald * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 249a19cd78SMatthias Ringwald * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 259a19cd78SMatthias Ringwald * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 269a19cd78SMatthias Ringwald * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 279a19cd78SMatthias Ringwald * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 289a19cd78SMatthias Ringwald * SUCH DAMAGE. 299a19cd78SMatthias Ringwald * 309a19cd78SMatthias Ringwald */ 319a19cd78SMatthias Ringwald 329a19cd78SMatthias Ringwald #define BTSTACK_FILE__ "btstack_lc3_google.c" 339a19cd78SMatthias Ringwald 349a19cd78SMatthias Ringwald /** 359a19cd78SMatthias Ringwald * @title LC3 Google Adapter 369a19cd78SMatthias Ringwald */ 379a19cd78SMatthias Ringwald 389a19cd78SMatthias Ringwald #include "btstack_config.h" 399a19cd78SMatthias Ringwald #include "bluetooth.h" 409a19cd78SMatthias Ringwald 419a19cd78SMatthias Ringwald #include "btstack_lc3_google.h" 429a19cd78SMatthias Ringwald #include "btstack_debug.h" 439a19cd78SMatthias Ringwald #include <string.h> 449a19cd78SMatthias Ringwald 459a19cd78SMatthias Ringwald static uint16_t lc3_frame_duration_in_us(btstack_lc3_frame_duration_t frame_duration){ 469a19cd78SMatthias Ringwald switch (frame_duration) { 479a19cd78SMatthias Ringwald case BTSTACK_LC3_FRAME_DURATION_7500US: 489a19cd78SMatthias Ringwald return 7500; 499a19cd78SMatthias Ringwald case BTSTACK_LC3_FRAME_DURATION_10000US: 509a19cd78SMatthias Ringwald return 10000; 519a19cd78SMatthias Ringwald default: 529a19cd78SMatthias Ringwald return 0; 539a19cd78SMatthias Ringwald } 549a19cd78SMatthias Ringwald } 559a19cd78SMatthias Ringwald 569a19cd78SMatthias Ringwald /* Decoder implementation */ 579a19cd78SMatthias Ringwald 58*da364eecSMatthias Ringwald 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){ 599a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 609a19cd78SMatthias Ringwald 619a19cd78SMatthias Ringwald // map frame duration 629a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 639a19cd78SMatthias Ringwald if (duration_us == 0){ 649a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 659a19cd78SMatthias Ringwald } 669a19cd78SMatthias Ringwald 679a19cd78SMatthias Ringwald // store config 689a19cd78SMatthias Ringwald instance->sample_rate = sample_rate; 699a19cd78SMatthias Ringwald instance->frame_duration = frame_duration; 70*da364eecSMatthias Ringwald instance->octets_per_frame = octets_per_frame; 719a19cd78SMatthias Ringwald 729a19cd78SMatthias Ringwald // config decoder 739a19cd78SMatthias Ringwald instance->decoder = lc3_setup_decoder(duration_us, sample_rate, 0, &instance->decoder_mem); 749a19cd78SMatthias Ringwald 759a19cd78SMatthias Ringwald if (instance->decoder == NULL) { 769a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 779a19cd78SMatthias Ringwald } 789a19cd78SMatthias Ringwald 799a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 809a19cd78SMatthias Ringwald } 819a19cd78SMatthias Ringwald 829a19cd78SMatthias Ringwald static uint16_t lc3_decoder_google_get_number_octets_for_bitrate(void * context, uint32_t bitrate){ 839a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 849a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 859a19cd78SMatthias Ringwald if (duration_us == 0){ 869a19cd78SMatthias Ringwald return 0; 879a19cd78SMatthias Ringwald } 889a19cd78SMatthias Ringwald return lc3_frame_bytes(duration_us, bitrate); 899a19cd78SMatthias Ringwald } 909a19cd78SMatthias Ringwald 919a19cd78SMatthias Ringwald static uint16_t lc3_decoder_google_get_number_samples_per_frame(void * context){ 929a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 939a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 949a19cd78SMatthias Ringwald if (duration_us == 0){ 959a19cd78SMatthias Ringwald return 0; 969a19cd78SMatthias Ringwald } 979a19cd78SMatthias Ringwald return lc3_frame_samples(duration_us, instance->sample_rate); 989a19cd78SMatthias Ringwald } 999a19cd78SMatthias Ringwald 100*da364eecSMatthias Ringwald static uint8_t 101*da364eecSMatthias Ringwald lc3_decoder_google_decode(void *context, const uint8_t *bytes, uint8_t BFI, enum lc3_pcm_format fmt, void *pcm_out, 102*da364eecSMatthias Ringwald uint16_t stride, uint8_t *BEC_detect) { 1039a19cd78SMatthias Ringwald btstack_lc3_decoder_google_t * instance = (btstack_lc3_decoder_google_t *) context; 1049a19cd78SMatthias Ringwald 1059a19cd78SMatthias Ringwald if (BFI){ 1069a19cd78SMatthias Ringwald // bit errors, trigger PLC by passing NULL as buffer 1079a19cd78SMatthias Ringwald *BEC_detect = 1; 1089a19cd78SMatthias Ringwald bytes = NULL; 1099a19cd78SMatthias Ringwald } else { 1109a19cd78SMatthias Ringwald // no bit errors, regular processing 1119a19cd78SMatthias Ringwald *BEC_detect = 0; 1129a19cd78SMatthias Ringwald } 1139a19cd78SMatthias Ringwald 114*da364eecSMatthias Ringwald int result = lc3_decode(instance->decoder, (const void *) bytes, instance->octets_per_frame, fmt, pcm_out, stride); 1159a19cd78SMatthias Ringwald switch (result){ 1169a19cd78SMatthias Ringwald case 0: // success 1179a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 1189a19cd78SMatthias Ringwald case -1: // PLC engaged 1199a19cd78SMatthias Ringwald *BEC_detect = 1; 1209a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 1219a19cd78SMatthias Ringwald default: 1229a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 1239a19cd78SMatthias Ringwald } 1249a19cd78SMatthias Ringwald } 1259a19cd78SMatthias Ringwald 126*da364eecSMatthias Ringwald 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){ 127*da364eecSMatthias Ringwald return lc3_decoder_google_decode(context, bytes, BFI, LC3_PCM_FORMAT_S16, (void *) pcm_out, stride, BEC_detect); 1289a19cd78SMatthias Ringwald } 1299a19cd78SMatthias Ringwald 130*da364eecSMatthias Ringwald 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) { 131*da364eecSMatthias Ringwald return lc3_decoder_google_decode(context, bytes, BFI, LC3_PCM_FORMAT_S24, (void *) pcm_out, stride, BEC_detect); 1329a19cd78SMatthias Ringwald } 1339a19cd78SMatthias Ringwald 1349a19cd78SMatthias Ringwald static const btstack_lc3_decoder_t btstack_l3c_decoder_google_instance = { 1359a19cd78SMatthias Ringwald lc3_decoder_google_configure, 1369a19cd78SMatthias Ringwald lc3_decoder_google_get_number_octets_for_bitrate, 1379a19cd78SMatthias Ringwald lc3_decoder_google_get_number_samples_per_frame, 1389a19cd78SMatthias Ringwald lc3_decoder_google_decode_signed_16, 1399a19cd78SMatthias Ringwald lc3_decoder_google_decode_signed_24 1409a19cd78SMatthias Ringwald }; 1419a19cd78SMatthias Ringwald 1429a19cd78SMatthias Ringwald const btstack_lc3_decoder_t * btstack_lc3_decoder_google_init_instance(btstack_lc3_decoder_google_t * context){ 1439a19cd78SMatthias Ringwald memset(context, 0, sizeof(btstack_lc3_decoder_google_t)); 1449a19cd78SMatthias Ringwald return &btstack_l3c_decoder_google_instance; 1459a19cd78SMatthias Ringwald } 1469a19cd78SMatthias Ringwald 1479a19cd78SMatthias Ringwald /* Encoder implementation */ 1489a19cd78SMatthias Ringwald 149*da364eecSMatthias Ringwald 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){ 1509a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 1519a19cd78SMatthias Ringwald 1529a19cd78SMatthias Ringwald // map frame duration 1539a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(frame_duration); 1549a19cd78SMatthias Ringwald if (duration_us == 0){ 1559a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 1569a19cd78SMatthias Ringwald } 1579a19cd78SMatthias Ringwald 1589a19cd78SMatthias Ringwald // store config 1599a19cd78SMatthias Ringwald instance->sample_rate = sample_rate; 1609a19cd78SMatthias Ringwald instance->frame_duration = frame_duration; 161*da364eecSMatthias Ringwald instance->octets_per_frame = octets_per_frame; 1629a19cd78SMatthias Ringwald 1639a19cd78SMatthias Ringwald // config encoder 1649a19cd78SMatthias Ringwald instance->encoder = lc3_setup_encoder(duration_us, sample_rate, 0, &instance->encoder_mem); 1659a19cd78SMatthias Ringwald 1669a19cd78SMatthias Ringwald if (instance->encoder == NULL) { 1679a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 1689a19cd78SMatthias Ringwald } 1699a19cd78SMatthias Ringwald 1709a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 1719a19cd78SMatthias Ringwald } 1729a19cd78SMatthias Ringwald 1739a19cd78SMatthias Ringwald static uint32_t lc3_encoder_google_get_bitrate_for_number_of_octets(void * context, uint16_t number_of_octets){ 1749a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 1759a19cd78SMatthias Ringwald // map frame duration 1769a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 1779a19cd78SMatthias Ringwald if (duration_us == 0){ 1789a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 1799a19cd78SMatthias Ringwald } 1809a19cd78SMatthias Ringwald return lc3_resolve_bitrate(duration_us, number_of_octets); 1819a19cd78SMatthias Ringwald } 1829a19cd78SMatthias Ringwald 1839a19cd78SMatthias Ringwald static uint16_t lc3_encoder_google_get_number_samples_per_frame(void * context){ 1849a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 1859a19cd78SMatthias Ringwald // map frame duration 1869a19cd78SMatthias Ringwald uint16_t duration_us = lc3_frame_duration_in_us(instance->frame_duration); 1879a19cd78SMatthias Ringwald if (duration_us == 0){ 1889a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 1899a19cd78SMatthias Ringwald } 1909a19cd78SMatthias Ringwald return lc3_frame_samples(duration_us, instance->sample_rate); 1919a19cd78SMatthias Ringwald } 192*da364eecSMatthias Ringwald static uint8_t 193*da364eecSMatthias Ringwald lc3_encoder_google_encode_signed(void *context, enum lc3_pcm_format fmt, const void *pcm_in, uint16_t stride, uint8_t *bytes) { 1949a19cd78SMatthias Ringwald btstack_lc3_encoder_google_t * instance = (btstack_lc3_encoder_google_t *) context; 195*da364eecSMatthias Ringwald int result = lc3_encode(instance->encoder, fmt, pcm_in, stride, instance->octets_per_frame, (void*) bytes); 1969a19cd78SMatthias Ringwald switch (result){ 1979a19cd78SMatthias Ringwald case 0: 1989a19cd78SMatthias Ringwald return ERROR_CODE_SUCCESS; 1999a19cd78SMatthias Ringwald default: 2009a19cd78SMatthias Ringwald return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 2019a19cd78SMatthias Ringwald } 2029a19cd78SMatthias Ringwald } 2039a19cd78SMatthias Ringwald 204*da364eecSMatthias Ringwald static uint8_t lc3_encoder_google_encode_signed_16(void * context, const int16_t* pcm_in, uint16_t stride, uint8_t *bytes){ 205*da364eecSMatthias Ringwald return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S16, (const void *) pcm_in, stride, bytes); 2069a19cd78SMatthias Ringwald } 2079a19cd78SMatthias Ringwald 208*da364eecSMatthias Ringwald static uint8_t lc3_encoder_google_encode_signed_24(void * context, const int32_t* pcm_in, uint16_t stride, uint8_t *bytes){ 209*da364eecSMatthias Ringwald return lc3_encoder_google_encode_signed(context, LC3_PCM_FORMAT_S24, (const void *) pcm_in, stride, bytes); 2109a19cd78SMatthias Ringwald } 2119a19cd78SMatthias Ringwald 2129a19cd78SMatthias Ringwald static const btstack_lc3_encoder_t btstack_l3c_encoder_google_instance = { 2139a19cd78SMatthias Ringwald lc3_encoder_google_configure, 2149a19cd78SMatthias Ringwald lc3_encoder_google_get_bitrate_for_number_of_octets, 2159a19cd78SMatthias Ringwald lc3_encoder_google_get_number_samples_per_frame, 2169a19cd78SMatthias Ringwald lc3_encoder_google_encode_signed_16, 2179a19cd78SMatthias Ringwald lc3_encoder_google_encode_signed_24 2189a19cd78SMatthias Ringwald }; 2199a19cd78SMatthias Ringwald 2209a19cd78SMatthias Ringwald const btstack_lc3_encoder_t * btstack_lc3_encoder_google_init_instance(btstack_lc3_encoder_google_t * context){ 2219a19cd78SMatthias Ringwald memset(context, 0, sizeof(btstack_lc3_encoder_google_t)); 2229a19cd78SMatthias Ringwald return &btstack_l3c_encoder_google_instance; 2239a19cd78SMatthias Ringwald } 2249a19cd78SMatthias Ringwald 225