xref: /btstack/src/classic/btstack_sbc_bluedroid.c (revision 113ff2bc0af39c4454c5c239318755ec65070fce)
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