1 /* 2 * Copyright (C) 2023 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 * 4. Any redistribution, use, or modification is done solely for 17 * personal benefit and not for any commercial purpose or for 18 * monetary gain. 19 * 20 * THIS SOFTWARE IS PROVIDED BY BLUEKITCHEN GMBH AND CONTRIBUTORS 21 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL BLUEKITCHEN 24 * GMBH OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 25 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, 26 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS 27 * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 28 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF 30 * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31 * SUCH DAMAGE. 32 * 33 * Please inquire about commercial licensing options at 34 * [email protected] 35 * 36 */ 37 38 #define BTSTACK_FILE__ "btstack_sbc_bluedroid.c" 39 40 #include "btstack_sbc_bluedroid.h" 41 42 #include "btstack_bool.h" 43 #include "btstack_config.h" 44 #include "btstack_debug.h" 45 46 #include <stdint.h> 47 #include "bluetooth.h" 48 49 static uint8_t btstack_sbc_encoder_bluedroid_configure(void * context, btstack_sbc_mode_t mode, 50 uint8_t blocks, uint8_t subbands, btstack_sbc_allocation_method_t allocation_method, 51 uint16_t sample_rate, uint8_t bitpool, btstack_sbc_channel_mode_t channel_mode){ 52 53 btstack_sbc_encoder_bluedroid_t * instance = (btstack_sbc_encoder_bluedroid_t *) context; 54 55 instance->mode = mode; 56 57 switch (instance->mode){ 58 case SBC_MODE_STANDARD: 59 instance->params.s16NumOfBlocks = blocks; 60 instance->params.s16NumOfSubBands = subbands; 61 instance->params.s16AllocationMethod = (uint8_t)allocation_method; 62 instance->params.s16BitPool = bitpool; 63 instance->params.mSBCEnabled = 0; 64 instance->params.s16ChannelMode = (uint8_t)channel_mode; 65 instance->params.s16NumOfChannels = 2; 66 if (instance->params.s16ChannelMode == SBC_MONO){ 67 instance->params.s16NumOfChannels = 1; 68 } 69 switch(sample_rate){ 70 case 16000: instance->params.s16SamplingFreq = SBC_sf16000; break; 71 case 32000: instance->params.s16SamplingFreq = SBC_sf32000; break; 72 case 44100: instance->params.s16SamplingFreq = SBC_sf44100; break; 73 case 48000: instance->params.s16SamplingFreq = SBC_sf48000; break; 74 default: instance->params.s16SamplingFreq = 0; break; 75 } 76 break; 77 case SBC_MODE_mSBC: 78 instance->params.s16NumOfBlocks = 15; 79 instance->params.s16NumOfSubBands = 8; 80 instance->params.s16AllocationMethod = SBC_LOUDNESS; 81 instance->params.s16BitPool = 26; 82 instance->params.s16ChannelMode = SBC_MONO; 83 instance->params.s16NumOfChannels = 1; 84 instance->params.mSBCEnabled = 1; 85 instance->params.s16SamplingFreq = SBC_sf16000; 86 break; 87 default: 88 return ERROR_CODE_INVALID_HCI_COMMAND_PARAMETERS; 89 } 90 91 SBC_Encoder_Init(&instance->params); 92 93 return ERROR_CODE_SUCCESS; 94 } 95 96 /** 97 * @brief Return number of audio frames required for one SBC packet 98 * @param context 99 * @note each audio frame contains 2 sample values in stereo modes 100 */ 101 static uint16_t btstack_sbc_encoder_bluedroid_num_audio_frames(void * context){ 102 btstack_sbc_encoder_bluedroid_t * instance = (btstack_sbc_encoder_bluedroid_t *) context; 103 return instance->params.s16NumOfSubBands * instance->params.s16NumOfBlocks; 104 } 105 106 static uint16_t btstack_sbc_encoder_bluedroid_sbc_buffer_length(void * context){ 107 btstack_sbc_encoder_bluedroid_t * instance = (btstack_sbc_encoder_bluedroid_t *) context; 108 return instance->params.u16PacketLength; 109 } 110 111 /** 112 * @brief Encode PCM data 113 * @param context 114 * @param pcm_in with samples in host endianess 115 * @param sbc_out 116 * @return status 117 */ 118 static uint8_t btstack_sbc_encoder_bluedroid_encode_signed_16(void * context, const int16_t* pcm_in, uint8_t * sbc_out){ 119 btstack_sbc_encoder_bluedroid_t * instance = (btstack_sbc_encoder_bluedroid_t *) context; 120 121 instance->params.ps16PcmBuffer = (int16_t *) pcm_in; 122 instance->params.pu8Packet = sbc_out; 123 if (instance->params.mSBCEnabled){ 124 instance->params.pu8Packet[0] = 0xad; 125 } 126 SBC_Encoder(&instance->params); 127 return ERROR_CODE_SUCCESS; 128 } 129 130 static const btstack_sbc_encoder_t btstack_sbc_encoder_bluedroid = { 131 .configure = btstack_sbc_encoder_bluedroid_configure, 132 .sbc_buffer_length = btstack_sbc_encoder_bluedroid_sbc_buffer_length, 133 .num_audio_frames = btstack_sbc_encoder_bluedroid_num_audio_frames, 134 .encode_signed_16 = btstack_sbc_encoder_bluedroid_encode_signed_16 135 }; 136 137 const btstack_sbc_encoder_t * btstack_sbc_encoder_bluedroid_init_instance(btstack_sbc_encoder_bluedroid_t * context){ 138 return &btstack_sbc_encoder_bluedroid; 139 } 140